resolve: skip IP_UNICAST_IF for local sockets
SO_BINDTODEVICE was used during connect() to fix an issue where IP_UNICAST_IF was improperly ignored for route lookups made by connect in linux. This has since been resolved upstream [1][2], but as a result we must apply the local socket excpetion to IP_UNICAST_IF as well. The SO_BINDTODEVICE is no longer necessary, but left in place for 5.x kernels. [1] https://lore.kernel.org/all/20220829111554.GA1771@debian/ [2] https://lore.kernel.org/all/20221208145437.GA75680@debian/
This commit is contained in:
committed by
Lennart Poettering
parent
38ff8b07e3
commit
51d056858e
@@ -424,7 +424,15 @@ static int dns_scope_socket(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ifindex != 0) {
|
||||
bool addr_is_nonlocal = s->link &&
|
||||
!manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
|
||||
in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0;
|
||||
|
||||
if (addr_is_nonlocal && ifindex != 0) {
|
||||
/* As a special exception we don't use UNICAST_IF if we notice that the specified IP address
|
||||
* is on the local host. Otherwise, destination addresses on the local host result in
|
||||
* EHOSTUNREACH, since Linux won't send the packets out of the specified interface, but
|
||||
* delivers them directly to the local socket. */
|
||||
r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -463,19 +471,13 @@ static int dns_scope_socket(
|
||||
else {
|
||||
bool bound = false;
|
||||
|
||||
/* Let's temporarily bind the socket to the specified ifindex. The kernel currently takes
|
||||
* only the SO_BINDTODEVICE/SO_BINDTOINDEX ifindex into account when making routing decisions
|
||||
/* Let's temporarily bind the socket to the specified ifindex. Older kernels only take
|
||||
* the SO_BINDTODEVICE/SO_BINDTOINDEX ifindex into account when making routing decisions
|
||||
* in connect() — and not IP_UNICAST_IF. We don't really want any of the other semantics of
|
||||
* SO_BINDTODEVICE/SO_BINDTOINDEX, hence we immediately unbind the socket after the fact
|
||||
* again.
|
||||
*
|
||||
* As a special exception we don't do this if we notice that the specified IP address is on
|
||||
* the local host. SO_BINDTODEVICE in combination with destination addresses on the local
|
||||
* host result in EHOSTUNREACH, since Linux won't send the packets out of the specified
|
||||
* interface, but delivers them directly to the local socket. */
|
||||
if (s->link &&
|
||||
!manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
|
||||
in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0) {
|
||||
*/
|
||||
if (addr_is_nonlocal) {
|
||||
r = socket_bind_to_ifindex(fd, ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Reference in New Issue
Block a user