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
->priority
, b
->priority
);
32 r
= CMP(a
->weight
, b
->weight
);
36 r
= CMP(a
->ifindex
, b
->ifindex
);
40 return memcmp(&a
->address
, &b
->address
, FAMILY_ADDRESS_SIZE(a
->family
));
43 bool has_local_address(const struct local_address
*addresses
, size_t n_addresses
, const struct local_address
*needle
) {
44 assert(addresses
|| n_addresses
== 0);
47 for (size_t i
= 0; i
< n_addresses
; i
++)
48 if (address_compare(addresses
+ i
, needle
) == 0)
54 static void suppress_duplicates(struct local_address
*list
, size_t *n_list
) {
55 size_t old_size
, new_size
;
57 /* Removes duplicate entries, assumes the list of addresses is already sorted. Updates in-place. */
59 if (*n_list
< 2) /* list with less than two entries can't have duplicates */
65 for (size_t i
= 1; i
< old_size
; i
++) {
67 if (address_compare(list
+ i
, list
+ new_size
- 1) == 0)
70 list
[new_size
++] = list
[i
];
76 static int add_local_address_full(
77 struct local_address
**list
,
84 const union in_addr_union
*address
) {
89 assert(IN_SET(family
, AF_INET
, AF_INET6
));
92 if (!GREEDY_REALLOC(*list
, *n_list
+ 1))
95 (*list
)[(*n_list
)++] = (struct local_address
) {
107 static int add_local_address(
108 struct local_address
**list
,
113 const union in_addr_union
*address
) {
115 return add_local_address_full(list
, n_list
, ifindex
, scope
, 0, 0, family
, address
);
122 struct local_address
**ret
) {
124 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
125 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
126 _cleanup_free_
struct local_address
*list
= NULL
;
131 rtnl
= sd_netlink_ref(context
);
133 r
= sd_netlink_open(&rtnl
);
138 r
= sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, ifindex
, af
);
142 r
= sd_netlink_message_set_request_dump(req
, true);
146 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
150 for (sd_netlink_message
*m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
151 union in_addr_union a
;
152 unsigned char flags
, scope
;
156 r
= sd_netlink_message_get_errno(m
);
160 r
= sd_netlink_message_get_type(m
, &type
);
163 if (type
!= RTM_NEWADDR
)
166 r
= sd_rtnl_message_addr_get_ifindex(m
, &ifi
);
169 if (ifindex
> 0 && ifi
!= ifindex
)
172 r
= sd_rtnl_message_addr_get_family(m
, &family
);
175 if (!IN_SET(family
, AF_INET
, AF_INET6
))
177 if (af
!= AF_UNSPEC
&& af
!= family
)
180 r
= sd_rtnl_message_addr_get_flags(m
, &flags
);
183 if ((flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
)) != 0)
186 r
= sd_rtnl_message_addr_get_scope(m
, &scope
);
190 if (ifindex
== 0 && IN_SET(scope
, RT_SCOPE_HOST
, RT_SCOPE_NOWHERE
))
196 r
= sd_netlink_message_read_in_addr(m
, IFA_LOCAL
, &a
.in
);
198 r
= sd_netlink_message_read_in_addr(m
, IFA_ADDRESS
, &a
.in
);
205 r
= sd_netlink_message_read_in6_addr(m
, IFA_LOCAL
, &a
.in6
);
207 r
= sd_netlink_message_read_in6_addr(m
, IFA_ADDRESS
, &a
.in6
);
214 assert_not_reached();
217 r
= add_local_address(&list
, &n_list
, ifi
, scope
, family
, &a
);
222 typesafe_qsort(list
, n_list
, address_compare
);
223 suppress_duplicates(list
, &n_list
);
226 *ret
= TAKE_PTR(list
);
231 static int add_local_gateway(
232 struct local_address
**list
,
238 const union in_addr_union
*address
) {
240 return add_local_address_full(list
, n_list
, ifindex
, 0, priority
, weight
, family
, address
);
243 static int parse_nexthop_one(
244 struct local_address
**list
,
249 const struct rtnexthop
*rtnh
) {
256 size_t len
= rtnh
->rtnh_len
- sizeof(struct rtnexthop
);
257 for (struct rtattr
*attr
= RTNH_DATA(rtnh
); RTA_OK(attr
, len
); attr
= RTA_NEXT(attr
, len
))
259 switch (attr
->rta_type
) {
266 if (attr
->rta_len
!= RTA_LENGTH(FAMILY_ADDRESS_SIZE(family
)))
269 union in_addr_union a
;
270 memcpy(&a
, RTA_DATA(attr
), FAMILY_ADDRESS_SIZE(family
));
271 r
= add_local_gateway(list
, n_list
, rtnh
->rtnh_ifindex
, priority
, rtnh
->rtnh_hops
, family
, &a
);
286 if (family
!= AF_INET
)
287 return -EBADMSG
; /* RTA_VIA is only supported for IPv4 routes. */
289 if (attr
->rta_len
!= RTA_LENGTH(sizeof(RouteVia
)))
292 RouteVia
*via
= RTA_DATA(attr
);
293 if (via
->family
!= AF_INET6
)
294 return -EBADMSG
; /* gateway address should be always IPv6. */
296 r
= add_local_gateway(list
, n_list
, rtnh
->rtnh_ifindex
, priority
, rtnh
->rtnh_hops
, via
->family
,
297 &(union in_addr_union
) { .in6
= via
->address
.in6
});
307 static int parse_nexthops(
308 struct local_address
**list
,
314 const struct rtnexthop
*rtnh
,
321 assert(IN_SET(family
, AF_INET
, AF_INET6
));
322 assert(rtnh
|| size
== 0);
324 if (size
< sizeof(struct rtnexthop
))
327 for (; size
>= sizeof(struct rtnexthop
); ) {
328 if (NLMSG_ALIGN(rtnh
->rtnh_len
) > size
)
331 if (rtnh
->rtnh_len
< sizeof(struct rtnexthop
))
334 if (ifindex
> 0 && rtnh
->rtnh_ifindex
!= ifindex
)
337 r
= parse_nexthop_one(list
, n_list
, allow_via
, family
, priority
, rtnh
);
342 size
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
343 rtnh
= RTNH_NEXT(rtnh
);
353 struct local_address
**ret
) {
355 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
356 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
357 _cleanup_free_
struct local_address
*list
= NULL
;
361 /* The RTA_VIA attribute is used only for IPv4 routes with an IPv6 gateway. If IPv4 gateways are
362 * requested (af == AF_INET), then we do not return IPv6 gateway addresses. Similarly, if IPv6
363 * gateways are requested (af == AF_INET6), then we do not return gateway addresses for IPv4 routes.
364 * So, the RTA_VIA attribute is only parsed when af == AF_UNSPEC. */
365 bool allow_via
= af
== AF_UNSPEC
;
368 rtnl
= sd_netlink_ref(context
);
370 r
= sd_netlink_open(&rtnl
);
375 r
= sd_rtnl_message_new_route(rtnl
, &req
, RTM_GETROUTE
, af
, RTPROT_UNSPEC
);
379 r
= sd_rtnl_message_route_set_type(req
, RTN_UNICAST
);
383 r
= sd_rtnl_message_route_set_table(req
, RT_TABLE_MAIN
);
387 r
= sd_netlink_message_set_request_dump(req
, true);
391 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
395 for (sd_netlink_message
*m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
397 unsigned char dst_len
, src_len
, table
;
398 uint32_t ifi
= 0, priority
= 0;
401 r
= sd_netlink_message_get_errno(m
);
405 r
= sd_netlink_message_get_type(m
, &type
);
408 if (type
!= RTM_NEWROUTE
)
411 /* We only care for default routes */
412 r
= sd_rtnl_message_route_get_dst_prefixlen(m
, &dst_len
);
418 r
= sd_rtnl_message_route_get_src_prefixlen(m
, &src_len
);
424 r
= sd_rtnl_message_route_get_table(m
, &table
);
427 if (table
!= RT_TABLE_MAIN
)
430 r
= sd_netlink_message_read_u32(m
, RTA_PRIORITY
, &priority
);
431 if (r
< 0 && r
!= -ENODATA
)
434 r
= sd_rtnl_message_route_get_family(m
, &family
);
437 if (!IN_SET(family
, AF_INET
, AF_INET6
))
439 if (af
!= AF_UNSPEC
&& af
!= family
)
442 r
= sd_netlink_message_read_u32(m
, RTA_OIF
, &ifi
);
443 if (r
< 0 && r
!= -ENODATA
)
448 if (ifindex
> 0 && (int) ifi
!= ifindex
)
451 union in_addr_union gateway
;
452 r
= netlink_message_read_in_addr_union(m
, RTA_GATEWAY
, family
, &gateway
);
453 if (r
< 0 && r
!= -ENODATA
)
456 r
= add_local_gateway(&list
, &n_list
, ifi
, priority
, 0, family
, &gateway
);
466 if (family
!= AF_INET
)
470 r
= sd_netlink_message_read(m
, RTA_VIA
, sizeof(via
), &via
);
471 if (r
< 0 && r
!= -ENODATA
)
474 if (via
.family
!= AF_INET6
)
477 r
= add_local_gateway(&list
, &n_list
, ifi
, priority
, 0, via
.family
,
478 &(union in_addr_union
) { .in6
= via
.address
.in6
});
483 /* If the route has RTA_OIF, it does not have RTA_MULTIPATH. */
488 _cleanup_free_
void *rta_multipath
= NULL
;
489 r
= sd_netlink_message_read_data(m
, RTA_MULTIPATH
, &rta_len
, &rta_multipath
);
490 if (r
< 0 && r
!= -ENODATA
)
493 r
= parse_nexthops(&list
, &n_list
, ifindex
, allow_via
, family
, priority
, rta_multipath
, rta_len
);
499 typesafe_qsort(list
, n_list
, address_compare
);
500 suppress_duplicates(list
, &n_list
);
503 *ret
= TAKE_PTR(list
);
508 static int add_local_outbound(
509 struct local_address
**list
,
513 const union in_addr_union
*address
) {
515 return add_local_address_full(list
, n_list
, ifindex
, 0, 0, 0, family
, address
);
522 struct local_address
**ret
) {
524 _cleanup_free_
struct local_address
*list
= NULL
, *gateways
= NULL
;
528 /* Determines our default outbound addresses, i.e. the "primary" local addresses we use to talk to IP
529 * addresses behind the default routes. This is still an address of the local host (i.e. this doesn't
530 * resolve NAT or so), but it's the set of addresses the local IP stack most likely uses to talk to
533 * This works by connect()ing a SOCK_DGRAM socket to the local gateways, and then reading the IP
534 * address off the socket that was chosen for the routing decision. */
536 n_gateways
= local_gateways(context
, ifindex
, af
, &gateways
);
539 if (n_gateways
== 0) {
540 /* No gateways? Then we have no outbound addresses either. */
547 for (int i
= 0; i
< n_gateways
; i
++) {
548 _cleanup_close_
int fd
= -EBADF
;
549 union sockaddr_union sa
;
552 fd
= socket(gateways
[i
].family
, SOCK_DGRAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
556 switch (gateways
[i
].family
) {
559 sa
.in
= (struct sockaddr_in
) {
560 .sin_family
= AF_INET
,
561 .sin_addr
= gateways
[i
].address
.in
,
562 .sin_port
= htobe16(53), /* doesn't really matter which port we pick —
563 * we just care about the routing decision */
569 sa
.in6
= (struct sockaddr_in6
) {
570 .sin6_family
= AF_INET6
,
571 .sin6_addr
= gateways
[i
].address
.in6
,
572 .sin6_port
= htobe16(53),
573 .sin6_scope_id
= gateways
[i
].ifindex
,
579 assert_not_reached();
582 /* So ideally we'd just use IP_UNICAST_IF here to pass the ifindex info to the kernel before
583 * connect()ing, sot that it influences the routing decision. However, on current kernels
584 * IP_UNICAST_IF doesn't actually influence the routing decision for UDP — which I think
585 * should probably just be considered a bug. Once that bug is fixed this is the best API to
586 * use, since it is the most lightweight. */
587 r
= socket_set_unicast_if(fd
, gateways
[i
].family
, gateways
[i
].ifindex
);
589 log_debug_errno(r
, "Failed to set unicast interface index %i, ignoring: %m", gateways
[i
].ifindex
);
591 /* We'll also use SO_BINDTOINDEX. This requires CAP_NET_RAW on old kernels, hence there's a
592 * good chance this fails. Since 5.7 this restriction was dropped and the first
593 * SO_BINDTOINDEX on a socket may be done without privileges. This one has the benefit of
594 * really influencing the routing decision, i.e. this one definitely works for us — as long
595 * as we have the privileges for it. */
596 r
= socket_bind_to_ifindex(fd
, gateways
[i
].ifindex
);
598 log_debug_errno(r
, "Failed to bind socket to interface %i, ignoring: %m", gateways
[i
].ifindex
);
600 /* Let's now connect() to the UDP socket, forcing the kernel to make a routing decision and
601 * auto-bind the socket. We ignore failures on this, since that failure might happen for a
602 * multitude of reasons (policy/firewall issues, who knows?) and some of them might be
603 * *after* the routing decision and the auto-binding already took place. If so we can still
604 * make use of the binding and return it. Hence, let's not unnecessarily fail early here: we
605 * can still easily detect if the auto-binding worked or not, by comparing the bound IP
606 * address with zero — which we do below. */
607 if (connect(fd
, &sa
.sa
, SOCKADDR_LEN(sa
)) < 0)
608 log_debug_errno(errno
, "Failed to connect SOCK_DGRAM socket to gateway, ignoring: %m");
610 /* Let's now read the socket address of the socket. A routing decision should have been
611 * made. Let's verify that and use the data. */
612 salen
= SOCKADDR_LEN(sa
);
613 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
615 assert(sa
.sa
.sa_family
== gateways
[i
].family
);
616 assert(salen
== SOCKADDR_LEN(sa
));
618 switch (gateways
[i
].family
) {
621 if (in4_addr_is_null(&sa
.in
.sin_addr
)) /* Auto-binding didn't work. :-( */
624 r
= add_local_outbound(&list
, &n_list
, gateways
[i
].ifindex
, gateways
[i
].family
,
625 &(union in_addr_union
) { .in
= sa
.in
.sin_addr
});
631 if (in6_addr_is_null(&sa
.in6
.sin6_addr
))
634 r
= add_local_outbound(&list
, &n_list
, gateways
[i
].ifindex
, gateways
[i
].family
,
635 &(union in_addr_union
) { .in6
= sa
.in6
.sin6_addr
});
641 assert_not_reached();
645 typesafe_qsort(list
, n_list
, address_compare
);
646 suppress_duplicates(list
, &n_list
);
649 *ret
= TAKE_PTR(list
);