1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <net/if_arp.h>
5 #include "sd-netlink.h"
7 #include "alloc-util.h"
9 #include "local-addresses.h"
11 #include "netlink-util.h"
12 #include "sort-util.h"
14 static int address_compare(const struct local_address
*a
, const struct local_address
*b
) {
17 /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */
19 if (a
->family
== AF_INET
&& b
->family
== AF_INET6
)
21 if (a
->family
== AF_INET6
&& b
->family
== AF_INET
)
24 r
= CMP(a
->scope
, b
->scope
);
28 r
= CMP(a
->metric
, b
->metric
);
32 r
= CMP(a
->ifindex
, b
->ifindex
);
36 return memcmp(&a
->address
, &b
->address
, FAMILY_ADDRESS_SIZE(a
->family
));
39 static void suppress_duplicates(struct local_address
*list
, size_t *n_list
) {
40 size_t old_size
, new_size
;
42 /* Removes duplicate entries, assumes the list of addresses is already sorted. Updates in-place. */
44 if (*n_list
< 2) /* list with less than two entries can't have duplicates */
50 for (size_t i
= 1; i
< old_size
; i
++) {
52 if (address_compare(list
+ i
, list
+ new_size
- 1) == 0)
55 list
[new_size
++] = list
[i
];
65 struct local_address
**ret
) {
67 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
68 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
69 _cleanup_free_
struct local_address
*list
= NULL
;
71 sd_netlink_message
*m
;
75 rtnl
= sd_netlink_ref(context
);
77 r
= sd_netlink_open(&rtnl
);
82 r
= sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, ifindex
, af
);
86 r
= sd_netlink_message_request_dump(req
, true);
90 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
94 for (m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
95 struct local_address
*a
;
100 r
= sd_netlink_message_get_errno(m
);
104 r
= sd_netlink_message_get_type(m
, &type
);
107 if (type
!= RTM_NEWADDR
)
110 r
= sd_rtnl_message_addr_get_ifindex(m
, &ifi
);
113 if (ifindex
> 0 && ifi
!= ifindex
)
116 r
= sd_rtnl_message_addr_get_family(m
, &family
);
119 if (af
!= AF_UNSPEC
&& af
!= family
)
122 r
= sd_rtnl_message_addr_get_flags(m
, &flags
);
125 if (flags
& IFA_F_DEPRECATED
)
128 if (!GREEDY_REALLOC0(list
, n_list
+1))
133 r
= sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
137 if (ifindex
== 0 && IN_SET(a
->scope
, RT_SCOPE_HOST
, RT_SCOPE_NOWHERE
))
143 r
= sd_netlink_message_read_in_addr(m
, IFA_LOCAL
, &a
->address
.in
);
145 r
= sd_netlink_message_read_in_addr(m
, IFA_ADDRESS
, &a
->address
.in
);
152 r
= sd_netlink_message_read_in6_addr(m
, IFA_LOCAL
, &a
->address
.in6
);
154 r
= sd_netlink_message_read_in6_addr(m
, IFA_ADDRESS
, &a
->address
.in6
);
171 typesafe_qsort(list
, n_list
, address_compare
);
172 suppress_duplicates(list
, &n_list
);
173 *ret
= TAKE_PTR(list
);
179 static int add_local_gateway(
180 struct local_address
**list
,
185 const RouteVia
*via
) {
191 if (af
!= AF_UNSPEC
&& af
!= via
->family
)
194 if (!GREEDY_REALLOC(*list
, *n_list
+ 1))
197 (*list
)[(*n_list
)++] = (struct local_address
) {
200 .family
= via
->family
,
201 .address
= via
->address
,
211 struct local_address
**ret
) {
213 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
214 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
215 _cleanup_free_
struct local_address
*list
= NULL
;
220 rtnl
= sd_netlink_ref(context
);
222 r
= sd_netlink_open(&rtnl
);
227 r
= sd_rtnl_message_new_route(rtnl
, &req
, RTM_GETROUTE
, af
, RTPROT_UNSPEC
);
231 r
= sd_rtnl_message_route_set_type(req
, RTN_UNICAST
);
235 r
= sd_rtnl_message_route_set_table(req
, RT_TABLE_MAIN
);
239 r
= sd_netlink_message_request_dump(req
, true);
243 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
247 for (sd_netlink_message
*m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
248 _cleanup_ordered_set_free_free_ OrderedSet
*multipath_routes
= NULL
;
249 _cleanup_free_
void *rta_multipath
= NULL
;
250 union in_addr_union gateway
;
252 unsigned char dst_len
, src_len
, table
;
253 uint32_t ifi
= 0, metric
= 0;
258 r
= sd_netlink_message_get_errno(m
);
262 r
= sd_netlink_message_get_type(m
, &type
);
265 if (type
!= RTM_NEWROUTE
)
268 /* We only care for default routes */
269 r
= sd_rtnl_message_route_get_dst_prefixlen(m
, &dst_len
);
275 r
= sd_rtnl_message_route_get_src_prefixlen(m
, &src_len
);
281 r
= sd_rtnl_message_route_get_table(m
, &table
);
284 if (table
!= RT_TABLE_MAIN
)
287 r
= sd_netlink_message_read_u32(m
, RTA_PRIORITY
, &metric
);
288 if (r
< 0 && r
!= -ENODATA
)
291 r
= sd_rtnl_message_route_get_family(m
, &family
);
294 if (!IN_SET(family
, AF_INET
, AF_INET6
))
297 r
= sd_netlink_message_read_u32(m
, RTA_OIF
, &ifi
);
298 if (r
< 0 && r
!= -ENODATA
)
303 if (ifindex
> 0 && (int) ifi
!= ifindex
)
306 r
= netlink_message_read_in_addr_union(m
, RTA_GATEWAY
, family
, &gateway
);
307 if (r
< 0 && r
!= -ENODATA
)
311 via
.address
= gateway
;
312 r
= add_local_gateway(&list
, &n_list
, af
, ifi
, metric
, &via
);
319 if (family
!= AF_INET
)
322 r
= sd_netlink_message_read(m
, RTA_VIA
, sizeof(via
), &via
);
323 if (r
< 0 && r
!= -ENODATA
)
326 r
= add_local_gateway(&list
, &n_list
, af
, ifi
, metric
, &via
);
334 r
= sd_netlink_message_read_data(m
, RTA_MULTIPATH
, &rta_len
, &rta_multipath
);
335 if (r
< 0 && r
!= -ENODATA
)
340 r
= rtattr_read_nexthop(rta_multipath
, rta_len
, family
, &multipath_routes
);
344 ORDERED_SET_FOREACH(mr
, multipath_routes
) {
345 if (ifindex
> 0 && mr
->ifindex
!= ifindex
)
348 r
= add_local_gateway(&list
, &n_list
, af
, ifi
, metric
, &mr
->gateway
);
356 typesafe_qsort(list
, n_list
, address_compare
);
357 suppress_duplicates(list
, &n_list
);
358 *ret
= TAKE_PTR(list
);
368 struct local_address
**ret
) {
370 _cleanup_free_
struct local_address
*list
= NULL
, *gateways
= NULL
;
374 /* Determines our default outbound addresses, i.e. the "primary" local addresses we use to talk to IP
375 * addresses behind the default routes. This is still an address of the local host (i.e. this doesn't
376 * resolve NAT or so), but it's the set of addresses the local IP stack most likely uses to talk to
379 * This works by connect()ing a SOCK_DGRAM socket to the local gateways, and then reading the IP
380 * address off the socket that was chosen for the routing decision. */
382 n_gateways
= local_gateways(context
, ifindex
, af
, &gateways
);
385 if (n_gateways
== 0) {
386 /* No gateways? Then we have no outbound addresses either. */
393 for (int i
= 0; i
< n_gateways
; i
++) {
394 _cleanup_close_
int fd
= -1;
395 union sockaddr_union sa
;
398 fd
= socket(gateways
[i
].family
, SOCK_DGRAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
402 switch (gateways
[i
].family
) {
405 sa
.in
= (struct sockaddr_in
) {
406 .sin_family
= AF_INET
,
407 .sin_addr
= gateways
[i
].address
.in
,
408 .sin_port
= htobe16(53), /* doesn't really matter which port we pick —
409 * we just care about the routing decision */
415 sa
.in6
= (struct sockaddr_in6
) {
416 .sin6_family
= AF_INET6
,
417 .sin6_addr
= gateways
[i
].address
.in6
,
418 .sin6_port
= htobe16(53),
419 .sin6_scope_id
= gateways
[i
].ifindex
,
425 assert_not_reached();
428 /* So ideally we'd just use IP_UNICAST_IF here to pass the ifindex info to the kernel before
429 * connect()ing, sot that it influences the routing decision. However, on current kernels
430 * IP_UNICAST_IF doesn't actually influence the routing decision for UDP — which I think
431 * should probably just be considered a bug. Once that bug is fixed this is the best API to
432 * use, since it is the most lightweight. */
433 r
= socket_set_unicast_if(fd
, gateways
[i
].family
, gateways
[i
].ifindex
);
435 log_debug_errno(r
, "Failed to set unicast interface index %i, ignoring: %m", gateways
[i
].ifindex
);
437 /* We'll also use SO_BINDTOINDEX. This requires CAP_NET_RAW on old kernels, hence there's a
438 * good chance this fails. Since 5.7 this restriction was dropped and the first
439 * SO_BINDTOINDEX on a socket may be done without privileges. This one has the benefit of
440 * really influencing the routing decision, i.e. this one definitely works for us — as long
441 * as we have the privileges for it. */
442 r
= socket_bind_to_ifindex(fd
, gateways
[i
].ifindex
);
444 log_debug_errno(r
, "Failed to bind socket to interface %i, ignoring: %m", gateways
[i
].ifindex
);
446 /* Let's now connect() to the UDP socket, forcing the kernel to make a routing decision and
447 * auto-bind the socket. We ignore failures on this, since that failure might happen for a
448 * multitude of reasons (policy/firewall issues, who knows?) and some of them might be
449 * *after* the routing decision and the auto-binding already took place. If so we can still
450 * make use of the binding and return it. Hence, let's not unnecessarily fail early here: we
451 * can still easily detect if the auto-binding worked or not, by comparing the bound IP
452 * address with zero — which we do below. */
453 if (connect(fd
, &sa
.sa
, SOCKADDR_LEN(sa
)) < 0)
454 log_debug_errno(errno
, "Failed to connect SOCK_DGRAM socket to gateway, ignoring: %m");
456 /* Let's now read the socket address of the socket. A routing decision should have been
457 * made. Let's verify that and use the data. */
458 salen
= SOCKADDR_LEN(sa
);
459 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
461 assert(sa
.sa
.sa_family
== gateways
[i
].family
);
462 assert(salen
== SOCKADDR_LEN(sa
));
464 switch (gateways
[i
].family
) {
467 if (in4_addr_is_null(&sa
.in
.sin_addr
)) /* Auto-binding didn't work. :-( */
470 if (!GREEDY_REALLOC(list
, n_list
+1))
473 list
[n_list
++] = (struct local_address
) {
474 .family
= gateways
[i
].family
,
475 .ifindex
= gateways
[i
].ifindex
,
476 .address
.in
= sa
.in
.sin_addr
,
482 if (in6_addr_is_null(&sa
.in6
.sin6_addr
))
485 if (!GREEDY_REALLOC(list
, n_list
+1))
488 list
[n_list
++] = (struct local_address
) {
489 .family
= gateways
[i
].family
,
490 .ifindex
= gateways
[i
].ifindex
,
491 .address
.in6
= sa
.in6
.sin6_addr
,
496 assert_not_reached();
501 typesafe_qsort(list
, n_list
, address_compare
);
502 suppress_duplicates(list
, &n_list
);
503 *ret
= TAKE_PTR(list
);