]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/local-addresses.c
build(deps): bump pkg/debian from `f550017` to `50b20e2`
[thirdparty/systemd.git] / src / shared / local-addresses.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <net/if_arp.h>
4
5 #include "sd-netlink.h"
6
7 #include "alloc-util.h"
8 #include "fd-util.h"
9 #include "local-addresses.h"
10 #include "macro.h"
11 #include "netlink-util.h"
12 #include "sort-util.h"
13
14 static int address_compare(const struct local_address *a, const struct local_address *b) {
15 int r;
16
17 /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */
18
19 if (a->family == AF_INET && b->family == AF_INET6)
20 return -1;
21 if (a->family == AF_INET6 && b->family == AF_INET)
22 return 1;
23
24 r = CMP(a->scope, b->scope);
25 if (r != 0)
26 return r;
27
28 r = CMP(a->priority, b->priority);
29 if (r != 0)
30 return r;
31
32 r = CMP(a->weight, b->weight);
33 if (r != 0)
34 return r;
35
36 r = CMP(a->ifindex, b->ifindex);
37 if (r != 0)
38 return r;
39
40 return memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family));
41 }
42
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);
45 assert(needle);
46
47 for (size_t i = 0; i < n_addresses; i++)
48 if (address_compare(addresses + i, needle) == 0)
49 return true;
50
51 return false;
52 }
53
54 static void suppress_duplicates(struct local_address *list, size_t *n_list) {
55 size_t old_size, new_size;
56
57 /* Removes duplicate entries, assumes the list of addresses is already sorted. Updates in-place. */
58
59 if (*n_list < 2) /* list with less than two entries can't have duplicates */
60 return;
61
62 old_size = *n_list;
63 new_size = 1;
64
65 for (size_t i = 1; i < old_size; i++) {
66
67 if (address_compare(list + i, list + new_size - 1) == 0)
68 continue;
69
70 list[new_size++] = list[i];
71 }
72
73 *n_list = new_size;
74 }
75
76 static int add_local_address_full(
77 struct local_address **list,
78 size_t *n_list,
79 int ifindex,
80 unsigned char scope,
81 uint32_t priority,
82 uint32_t weight,
83 int family,
84 const union in_addr_union *address) {
85
86 assert(list);
87 assert(n_list);
88 assert(ifindex > 0);
89 assert(IN_SET(family, AF_INET, AF_INET6));
90 assert(address);
91
92 if (!GREEDY_REALLOC(*list, *n_list + 1))
93 return -ENOMEM;
94
95 (*list)[(*n_list)++] = (struct local_address) {
96 .ifindex = ifindex,
97 .scope = scope,
98 .priority = priority,
99 .weight = weight,
100 .family = family,
101 .address = *address,
102 };
103
104 return 1;
105 }
106
107 static int add_local_address(
108 struct local_address **list,
109 size_t *n_list,
110 int ifindex,
111 unsigned char scope,
112 int family,
113 const union in_addr_union *address) {
114
115 return add_local_address_full(list, n_list, ifindex, scope, 0, 0, family, address);
116 }
117
118 int local_addresses(
119 sd_netlink *context,
120 int ifindex,
121 int af,
122 struct local_address **ret) {
123
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;
127 size_t n_list = 0;
128 int r;
129
130 if (context)
131 rtnl = sd_netlink_ref(context);
132 else {
133 r = sd_netlink_open(&rtnl);
134 if (r < 0)
135 return r;
136 }
137
138 r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, ifindex, af);
139 if (r < 0)
140 return r;
141
142 r = sd_netlink_message_set_request_dump(req, true);
143 if (r < 0)
144 return r;
145
146 r = sd_netlink_call(rtnl, req, 0, &reply);
147 if (r < 0)
148 return r;
149
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;
153 uint16_t type;
154 int ifi, family;
155
156 r = sd_netlink_message_get_errno(m);
157 if (r < 0)
158 return r;
159
160 r = sd_netlink_message_get_type(m, &type);
161 if (r < 0)
162 return r;
163 if (type != RTM_NEWADDR)
164 continue;
165
166 r = sd_rtnl_message_addr_get_ifindex(m, &ifi);
167 if (r < 0)
168 return r;
169 if (ifindex > 0 && ifi != ifindex)
170 continue;
171
172 r = sd_rtnl_message_addr_get_family(m, &family);
173 if (r < 0)
174 return r;
175 if (!IN_SET(family, AF_INET, AF_INET6))
176 continue;
177 if (af != AF_UNSPEC && af != family)
178 continue;
179
180 r = sd_rtnl_message_addr_get_flags(m, &flags);
181 if (r < 0)
182 return r;
183 if ((flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE)) != 0)
184 continue;
185
186 r = sd_rtnl_message_addr_get_scope(m, &scope);
187 if (r < 0)
188 return r;
189
190 if (ifindex == 0 && IN_SET(scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
191 continue;
192
193 switch (family) {
194
195 case AF_INET:
196 r = sd_netlink_message_read_in_addr(m, IFA_LOCAL, &a.in);
197 if (r < 0) {
198 r = sd_netlink_message_read_in_addr(m, IFA_ADDRESS, &a.in);
199 if (r < 0)
200 continue;
201 }
202 break;
203
204 case AF_INET6:
205 r = sd_netlink_message_read_in6_addr(m, IFA_LOCAL, &a.in6);
206 if (r < 0) {
207 r = sd_netlink_message_read_in6_addr(m, IFA_ADDRESS, &a.in6);
208 if (r < 0)
209 continue;
210 }
211 break;
212
213 default:
214 assert_not_reached();
215 }
216
217 r = add_local_address(&list, &n_list, ifi, scope, family, &a);
218 if (r < 0)
219 return r;
220 };
221
222 typesafe_qsort(list, n_list, address_compare);
223 suppress_duplicates(list, &n_list);
224
225 if (ret)
226 *ret = TAKE_PTR(list);
227
228 return (int) n_list;
229 }
230
231 static int add_local_gateway(
232 struct local_address **list,
233 size_t *n_list,
234 int ifindex,
235 uint32_t priority,
236 uint32_t weight,
237 int family,
238 const union in_addr_union *address) {
239
240 return add_local_address_full(list, n_list, ifindex, 0, priority, weight, family, address);
241 }
242
243 static int parse_nexthop_one(
244 struct local_address **list,
245 size_t *n_list,
246 bool allow_via,
247 int family,
248 uint32_t priority,
249 const struct rtnexthop *rtnh) {
250
251 bool has_gw = false;
252 int r;
253
254 assert(rtnh);
255
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))
258
259 switch (attr->rta_type) {
260 case RTA_GATEWAY:
261 if (has_gw)
262 return -EBADMSG;
263
264 has_gw = true;
265
266 if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(family)))
267 return -EBADMSG;
268
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);
272 if (r < 0)
273 return r;
274
275 break;
276
277 case RTA_VIA:
278 if (has_gw)
279 return -EBADMSG;
280
281 has_gw = true;
282
283 if (!allow_via)
284 continue;
285
286 if (family != AF_INET)
287 return -EBADMSG; /* RTA_VIA is only supported for IPv4 routes. */
288
289 if (attr->rta_len != RTA_LENGTH(sizeof(RouteVia)))
290 return -EBADMSG;
291
292 RouteVia *via = RTA_DATA(attr);
293 if (via->family != AF_INET6)
294 return -EBADMSG; /* gateway address should be always IPv6. */
295
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 });
298 if (r < 0)
299 return r;
300
301 break;
302 }
303
304 return 0;
305 }
306
307 static int parse_nexthops(
308 struct local_address **list,
309 size_t *n_list,
310 int ifindex,
311 bool allow_via,
312 int family,
313 uint32_t priority,
314 const struct rtnexthop *rtnh,
315 size_t size) {
316
317 int r;
318
319 assert(list);
320 assert(n_list);
321 assert(IN_SET(family, AF_INET, AF_INET6));
322 assert(rtnh || size == 0);
323
324 if (size < sizeof(struct rtnexthop))
325 return -EBADMSG;
326
327 for (; size >= sizeof(struct rtnexthop); ) {
328 if (NLMSG_ALIGN(rtnh->rtnh_len) > size)
329 return -EBADMSG;
330
331 if (rtnh->rtnh_len < sizeof(struct rtnexthop))
332 return -EBADMSG;
333
334 if (ifindex > 0 && rtnh->rtnh_ifindex != ifindex)
335 goto next_nexthop;
336
337 r = parse_nexthop_one(list, n_list, allow_via, family, priority, rtnh);
338 if (r < 0)
339 return r;
340
341 next_nexthop:
342 size -= NLMSG_ALIGN(rtnh->rtnh_len);
343 rtnh = RTNH_NEXT(rtnh);
344 }
345
346 return 0;
347 }
348
349 int local_gateways(
350 sd_netlink *context,
351 int ifindex,
352 int af,
353 struct local_address **ret) {
354
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;
358 size_t n_list = 0;
359 int r;
360
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;
366
367 if (context)
368 rtnl = sd_netlink_ref(context);
369 else {
370 r = sd_netlink_open(&rtnl);
371 if (r < 0)
372 return r;
373 }
374
375 r = sd_rtnl_message_new_route(rtnl, &req, RTM_GETROUTE, af, RTPROT_UNSPEC);
376 if (r < 0)
377 return r;
378
379 r = sd_rtnl_message_route_set_type(req, RTN_UNICAST);
380 if (r < 0)
381 return r;
382
383 r = sd_rtnl_message_route_set_table(req, RT_TABLE_MAIN);
384 if (r < 0)
385 return r;
386
387 r = sd_netlink_message_set_request_dump(req, true);
388 if (r < 0)
389 return r;
390
391 r = sd_netlink_call(rtnl, req, 0, &reply);
392 if (r < 0)
393 return r;
394
395 for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
396 uint16_t type;
397 unsigned char dst_len, src_len, table;
398 uint32_t ifi = 0, priority = 0;
399 int family;
400
401 r = sd_netlink_message_get_errno(m);
402 if (r < 0)
403 return r;
404
405 r = sd_netlink_message_get_type(m, &type);
406 if (r < 0)
407 return r;
408 if (type != RTM_NEWROUTE)
409 continue;
410
411 /* We only care for default routes */
412 r = sd_rtnl_message_route_get_dst_prefixlen(m, &dst_len);
413 if (r < 0)
414 return r;
415 if (dst_len != 0)
416 continue;
417
418 r = sd_rtnl_message_route_get_src_prefixlen(m, &src_len);
419 if (r < 0)
420 return r;
421 if (src_len != 0)
422 continue;
423
424 r = sd_rtnl_message_route_get_table(m, &table);
425 if (r < 0)
426 return r;
427 if (table != RT_TABLE_MAIN)
428 continue;
429
430 r = sd_netlink_message_read_u32(m, RTA_PRIORITY, &priority);
431 if (r < 0 && r != -ENODATA)
432 return r;
433
434 r = sd_rtnl_message_route_get_family(m, &family);
435 if (r < 0)
436 return r;
437 if (!IN_SET(family, AF_INET, AF_INET6))
438 continue;
439 if (af != AF_UNSPEC && af != family)
440 continue;
441
442 r = sd_netlink_message_read_u32(m, RTA_OIF, &ifi);
443 if (r < 0 && r != -ENODATA)
444 return r;
445 if (r >= 0) {
446 if (ifi <= 0)
447 return -EINVAL;
448 if (ifindex > 0 && (int) ifi != ifindex)
449 continue;
450
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)
454 return r;
455 if (r >= 0) {
456 r = add_local_gateway(&list, &n_list, ifi, priority, 0, family, &gateway);
457 if (r < 0)
458 return r;
459
460 continue;
461 }
462
463 if (!allow_via)
464 continue;
465
466 if (family != AF_INET)
467 continue;
468
469 RouteVia via;
470 r = sd_netlink_message_read(m, RTA_VIA, sizeof(via), &via);
471 if (r < 0 && r != -ENODATA)
472 return r;
473 if (r >= 0) {
474 if (via.family != AF_INET6)
475 return -EBADMSG;
476
477 r = add_local_gateway(&list, &n_list, ifi, priority, 0, via.family,
478 &(union in_addr_union) { .in6 = via.address.in6 });
479 if (r < 0)
480 return r;
481 }
482
483 /* If the route has RTA_OIF, it does not have RTA_MULTIPATH. */
484 continue;
485 }
486
487 size_t rta_len;
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)
491 return r;
492 if (r >= 0) {
493 r = parse_nexthops(&list, &n_list, ifindex, allow_via, family, priority, rta_multipath, rta_len);
494 if (r < 0)
495 return r;
496 }
497 }
498
499 typesafe_qsort(list, n_list, address_compare);
500 suppress_duplicates(list, &n_list);
501
502 if (ret)
503 *ret = TAKE_PTR(list);
504
505 return (int) n_list;
506 }
507
508 static int add_local_outbound(
509 struct local_address **list,
510 size_t *n_list,
511 int ifindex,
512 int family,
513 const union in_addr_union *address) {
514
515 return add_local_address_full(list, n_list, ifindex, 0, 0, 0, family, address);
516 }
517
518 int local_outbounds(
519 sd_netlink *context,
520 int ifindex,
521 int af,
522 struct local_address **ret) {
523
524 _cleanup_free_ struct local_address *list = NULL, *gateways = NULL;
525 size_t n_list = 0;
526 int r, n_gateways;
527
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
531 * other hosts.
532 *
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. */
535
536 n_gateways = local_gateways(context, ifindex, af, &gateways);
537 if (n_gateways < 0)
538 return n_gateways;
539 if (n_gateways == 0) {
540 /* No gateways? Then we have no outbound addresses either. */
541 if (ret)
542 *ret = NULL;
543
544 return 0;
545 }
546
547 for (int i = 0; i < n_gateways; i++) {
548 _cleanup_close_ int fd = -EBADF;
549 union sockaddr_union sa;
550 socklen_t salen;
551
552 fd = socket(gateways[i].family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
553 if (fd < 0)
554 return -errno;
555
556 switch (gateways[i].family) {
557
558 case AF_INET:
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 */
564 };
565
566 break;
567
568 case AF_INET6:
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,
574 };
575
576 break;
577
578 default:
579 assert_not_reached();
580 }
581
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);
588 if (r < 0)
589 log_debug_errno(r, "Failed to set unicast interface index %i, ignoring: %m", gateways[i].ifindex);
590
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);
597 if (r < 0)
598 log_debug_errno(r, "Failed to bind socket to interface %i, ignoring: %m", gateways[i].ifindex);
599
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");
609
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)
614 return -errno;
615 assert(sa.sa.sa_family == gateways[i].family);
616 assert(salen == SOCKADDR_LEN(sa));
617
618 switch (gateways[i].family) {
619
620 case AF_INET:
621 if (in4_addr_is_null(&sa.in.sin_addr)) /* Auto-binding didn't work. :-( */
622 continue;
623
624 r = add_local_outbound(&list, &n_list, gateways[i].ifindex, gateways[i].family,
625 &(union in_addr_union) { .in = sa.in.sin_addr });
626 if (r < 0)
627 return r;
628 break;
629
630 case AF_INET6:
631 if (in6_addr_is_null(&sa.in6.sin6_addr))
632 continue;
633
634 r = add_local_outbound(&list, &n_list, gateways[i].ifindex, gateways[i].family,
635 &(union in_addr_union) { .in6 = sa.in6.sin6_addr });
636 if (r < 0)
637 return r;
638 break;
639
640 default:
641 assert_not_reached();
642 }
643 }
644
645 typesafe_qsort(list, n_list, address_compare);
646 suppress_duplicates(list, &n_list);
647
648 if (ret)
649 *ret = TAKE_PTR(list);
650
651 return (int) n_list;
652 }