]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-route.c
network: add support to RoutingPolicyRule lookup table name
[thirdparty/systemd.git] / src / network / networkd-route.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <linux/icmpv6.h>
4 #include <linux/ipv6_route.h>
5
6 #include "alloc-util.h"
7 #include "netlink-util.h"
8 #include "networkd-ipv4ll.h"
9 #include "networkd-manager.h"
10 #include "networkd-network.h"
11 #include "networkd-nexthop.h"
12 #include "networkd-route.h"
13 #include "networkd-routing-policy-rule.h"
14 #include "parse-util.h"
15 #include "socket-netlink.h"
16 #include "string-table.h"
17 #include "string-util.h"
18 #include "strv.h"
19 #include "strxcpyx.h"
20 #include "sysctl-util.h"
21 #include "vrf.h"
22
23 #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
24
25 static uint32_t link_get_vrf_table(const Link *link) {
26 return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN;
27 }
28
29 uint32_t link_get_dhcp_route_table(const Link *link) {
30 /* When the interface is part of an VRF use the VRFs routing table, unless
31 * another table is explicitly specified. */
32 if (link->network->dhcp_route_table_set)
33 return link->network->dhcp_route_table;
34 return link_get_vrf_table(link);
35 }
36
37 uint32_t link_get_ipv6_accept_ra_route_table(const Link *link) {
38 if (link->network->ipv6_accept_ra_route_table_set)
39 return link->network->ipv6_accept_ra_route_table;
40 return link_get_vrf_table(link);
41 }
42
43 static const char * const route_type_table[__RTN_MAX] = {
44 [RTN_UNICAST] = "unicast",
45 [RTN_LOCAL] = "local",
46 [RTN_BROADCAST] = "broadcast",
47 [RTN_ANYCAST] = "anycast",
48 [RTN_MULTICAST] = "multicast",
49 [RTN_BLACKHOLE] = "blackhole",
50 [RTN_UNREACHABLE] = "unreachable",
51 [RTN_PROHIBIT] = "prohibit",
52 [RTN_THROW] = "throw",
53 [RTN_NAT] = "nat",
54 [RTN_XRESOLVE] = "xresolve",
55 };
56
57 assert_cc(__RTN_MAX <= UCHAR_MAX);
58 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_type, int);
59
60 static const char * const route_scope_table[] = {
61 [RT_SCOPE_UNIVERSE] = "global",
62 [RT_SCOPE_SITE] = "site",
63 [RT_SCOPE_LINK] = "link",
64 [RT_SCOPE_HOST] = "host",
65 [RT_SCOPE_NOWHERE] = "nowhere",
66 };
67
68 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int);
69
70 #define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1)
71 static const char *format_route_scope(int scope, char *buf, size_t size) {
72 const char *s;
73 char *p = buf;
74
75 s = route_scope_to_string(scope);
76 if (s)
77 strpcpy(&p, size, s);
78 else
79 strpcpyf(&p, size, "%d", scope);
80
81 return buf;
82 }
83
84 static const char * const route_table_table[] = {
85 [RT_TABLE_DEFAULT] = "default",
86 [RT_TABLE_MAIN] = "main",
87 [RT_TABLE_LOCAL] = "local",
88 };
89
90 DEFINE_STRING_TABLE_LOOKUP(route_table, int);
91
92 #define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1)
93 static const char *format_route_table(int table, char *buf, size_t size) {
94 const char *s;
95 char *p = buf;
96
97 s = route_table_to_string(table);
98 if (s)
99 strpcpy(&p, size, s);
100 else
101 strpcpyf(&p, size, "%d", table);
102
103 return buf;
104 }
105
106 static const char * const route_protocol_table[] = {
107 [RTPROT_KERNEL] = "kernel",
108 [RTPROT_BOOT] = "boot",
109 [RTPROT_STATIC] = "static",
110 };
111
112 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int);
113
114 static const char * const route_protocol_full_table[] = {
115 [RTPROT_REDIRECT] = "redirect",
116 [RTPROT_KERNEL] = "kernel",
117 [RTPROT_BOOT] = "boot",
118 [RTPROT_STATIC] = "static",
119 [RTPROT_GATED] = "gated",
120 [RTPROT_RA] = "ra",
121 [RTPROT_MRT] = "mrt",
122 [RTPROT_ZEBRA] = "zebra",
123 [RTPROT_BIRD] = "bird",
124 [RTPROT_DNROUTED] = "dnrouted",
125 [RTPROT_XORP] = "xorp",
126 [RTPROT_NTK] = "ntk",
127 [RTPROT_DHCP] = "dhcp",
128 [RTPROT_MROUTED] = "mrouted",
129 [RTPROT_BABEL] = "babel",
130 [RTPROT_BGP] = "bgp",
131 [RTPROT_ISIS] = "isis",
132 [RTPROT_OSPF] = "ospf",
133 [RTPROT_RIP] = "rip",
134 [RTPROT_EIGRP] = "eigrp",
135 };
136
137 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full, int);
138
139 #define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1)
140 static const char *format_route_protocol(int protocol, char *buf, size_t size) {
141 const char *s;
142 char *p = buf;
143
144 s = route_protocol_full_to_string(protocol);
145 if (s)
146 strpcpy(&p, size, s);
147 else
148 strpcpyf(&p, size, "%d", protocol);
149
150 return buf;
151 }
152
153 static unsigned routes_max(void) {
154 static thread_local unsigned cached = 0;
155 _cleanup_free_ char *s4 = NULL, *s6 = NULL;
156 unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY;
157
158 if (cached > 0)
159 return cached;
160
161 if (sysctl_read_ip_property(AF_INET, NULL, "route/max_size", &s4) >= 0)
162 if (safe_atou(s4, &val4) >= 0 && val4 == 2147483647U)
163 /* This is the default "no limit" value in the kernel */
164 val4 = ROUTES_DEFAULT_MAX_PER_FAMILY;
165
166 if (sysctl_read_ip_property(AF_INET6, NULL, "route/max_size", &s6) >= 0)
167 (void) safe_atou(s6, &val6);
168
169 cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) +
170 MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6);
171 return cached;
172 }
173
174 int route_new(Route **ret) {
175 _cleanup_(route_freep) Route *route = NULL;
176
177 route = new(Route, 1);
178 if (!route)
179 return -ENOMEM;
180
181 *route = (Route) {
182 .family = AF_UNSPEC,
183 .scope = RT_SCOPE_UNIVERSE,
184 .protocol = RTPROT_UNSPEC,
185 .type = RTN_UNICAST,
186 .table = RT_TABLE_MAIN,
187 .lifetime = USEC_INFINITY,
188 .quickack = -1,
189 .fast_open_no_cookie = -1,
190 .gateway_onlink = -1,
191 .ttl_propagate = -1,
192 };
193
194 *ret = TAKE_PTR(route);
195
196 return 0;
197 }
198
199 static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
200 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
201 _cleanup_(route_freep) Route *route = NULL;
202 int r;
203
204 assert(network);
205 assert(ret);
206 assert(filename);
207 assert(section_line > 0);
208
209 r = network_config_section_new(filename, section_line, &n);
210 if (r < 0)
211 return r;
212
213 route = hashmap_get(network->routes_by_section, n);
214 if (route) {
215 *ret = TAKE_PTR(route);
216 return 0;
217 }
218
219 if (hashmap_size(network->routes_by_section) >= routes_max())
220 return -E2BIG;
221
222 r = route_new(&route);
223 if (r < 0)
224 return r;
225
226 route->protocol = RTPROT_STATIC;
227 route->network = network;
228 route->section = TAKE_PTR(n);
229
230 r = hashmap_ensure_put(&network->routes_by_section, &network_config_hash_ops, route->section, route);
231 if (r < 0)
232 return r;
233
234 *ret = TAKE_PTR(route);
235 return 0;
236 }
237
238 Route *route_free(Route *route) {
239 if (!route)
240 return NULL;
241
242 if (route->network) {
243 assert(route->section);
244 hashmap_remove(route->network->routes_by_section, route->section);
245 }
246
247 network_config_section_free(route->section);
248
249 if (route->link) {
250 NDiscRoute *n;
251
252 set_remove(route->link->routes, route);
253 set_remove(route->link->routes_foreign, route);
254 set_remove(route->link->dhcp_routes, route);
255 set_remove(route->link->dhcp_routes_old, route);
256 set_remove(route->link->dhcp6_routes, route);
257 set_remove(route->link->dhcp6_routes_old, route);
258 set_remove(route->link->dhcp6_pd_routes, route);
259 set_remove(route->link->dhcp6_pd_routes_old, route);
260 SET_FOREACH(n, route->link->ndisc_routes)
261 if (n->route == route)
262 free(set_remove(route->link->ndisc_routes, n));
263 }
264
265 if (route->manager) {
266 set_remove(route->manager->routes, route);
267 set_remove(route->manager->routes_foreign, route);
268 }
269
270 ordered_set_free_free(route->multipath_routes);
271
272 sd_event_source_unref(route->expire);
273
274 return mfree(route);
275 }
276
277 void route_hash_func(const Route *route, struct siphash *state) {
278 assert(route);
279
280 siphash24_compress(&route->family, sizeof(route->family), state);
281
282 switch (route->family) {
283 case AF_INET:
284 case AF_INET6:
285 siphash24_compress(&route->dst_prefixlen, sizeof(route->dst_prefixlen), state);
286 siphash24_compress(&route->dst, FAMILY_ADDRESS_SIZE(route->family), state);
287
288 siphash24_compress(&route->src_prefixlen, sizeof(route->src_prefixlen), state);
289 siphash24_compress(&route->src, FAMILY_ADDRESS_SIZE(route->family), state);
290
291 siphash24_compress(&route->gw_family, sizeof(route->gw_family), state);
292 if (IN_SET(route->gw_family, AF_INET, AF_INET6)) {
293 siphash24_compress(&route->gw, FAMILY_ADDRESS_SIZE(route->gw_family), state);
294 siphash24_compress(&route->gw_weight, sizeof(route->gw_weight), state);
295 }
296
297 siphash24_compress(&route->prefsrc, FAMILY_ADDRESS_SIZE(route->family), state);
298
299 siphash24_compress(&route->tos, sizeof(route->tos), state);
300 siphash24_compress(&route->priority, sizeof(route->priority), state);
301 siphash24_compress(&route->table, sizeof(route->table), state);
302 siphash24_compress(&route->protocol, sizeof(route->protocol), state);
303 siphash24_compress(&route->scope, sizeof(route->scope), state);
304 siphash24_compress(&route->type, sizeof(route->type), state);
305
306 siphash24_compress(&route->initcwnd, sizeof(route->initcwnd), state);
307 siphash24_compress(&route->initrwnd, sizeof(route->initrwnd), state);
308
309 siphash24_compress(&route->advmss, sizeof(route->advmss), state);
310
311 break;
312 default:
313 /* treat any other address family as AF_UNSPEC */
314 break;
315 }
316 }
317
318 int route_compare_func(const Route *a, const Route *b) {
319 int r;
320
321 r = CMP(a->family, b->family);
322 if (r != 0)
323 return r;
324
325 switch (a->family) {
326 case AF_INET:
327 case AF_INET6:
328 r = CMP(a->dst_prefixlen, b->dst_prefixlen);
329 if (r != 0)
330 return r;
331
332 r = memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family));
333 if (r != 0)
334 return r;
335
336 r = CMP(a->src_prefixlen, b->src_prefixlen);
337 if (r != 0)
338 return r;
339
340 r = memcmp(&a->src, &b->src, FAMILY_ADDRESS_SIZE(a->family));
341 if (r != 0)
342 return r;
343
344 r = CMP(a->gw_family, b->gw_family);
345 if (r != 0)
346 return r;
347
348 if (IN_SET(a->gw_family, AF_INET, AF_INET6)) {
349 r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
350 if (r != 0)
351 return r;
352
353 r = CMP(a->gw_weight, b->gw_weight);
354 if (r != 0)
355 return r;
356 }
357
358 r = memcmp(&a->prefsrc, &b->prefsrc, FAMILY_ADDRESS_SIZE(a->family));
359 if (r != 0)
360 return r;
361
362 r = CMP(a->tos, b->tos);
363 if (r != 0)
364 return r;
365
366 r = CMP(a->priority, b->priority);
367 if (r != 0)
368 return r;
369
370 r = CMP(a->table, b->table);
371 if (r != 0)
372 return r;
373
374 r = CMP(a->protocol, b->protocol);
375 if (r != 0)
376 return r;
377
378 r = CMP(a->scope, b->scope);
379 if (r != 0)
380 return r;
381
382 r = CMP(a->type, b->type);
383 if (r != 0)
384 return r;
385
386 r = CMP(a->initcwnd, b->initcwnd);
387 if (r != 0)
388 return r;
389
390 r = CMP(a->initrwnd, b->initrwnd);
391 if (r != 0)
392 return r;
393
394 r = CMP(a->advmss, b->advmss);
395 if (r != 0)
396 return r;
397
398 return 0;
399 default:
400 /* treat any other address family as AF_UNSPEC */
401 return 0;
402 }
403 }
404
405 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
406 route_hash_ops,
407 Route,
408 route_hash_func,
409 route_compare_func,
410 route_free);
411
412 static bool route_equal(const Route *r1, const Route *r2) {
413 if (r1 == r2)
414 return true;
415
416 if (!r1 || !r2)
417 return false;
418
419 return route_compare_func(r1, r2) == 0;
420 }
421
422 static int route_get(const Manager *manager, const Link *link, const Route *in, Route **ret) {
423 Route *existing;
424
425 assert(manager || link);
426 assert(in);
427
428 if (link) {
429 existing = set_get(link->routes, in);
430 if (existing) {
431 if (ret)
432 *ret = existing;
433 return 1;
434 }
435
436 existing = set_get(link->routes_foreign, in);
437 if (existing) {
438 if (ret)
439 *ret = existing;
440 return 0;
441 }
442 } else {
443 existing = set_get(manager->routes, in);
444 if (existing) {
445 if (ret)
446 *ret = existing;
447 return 1;
448 }
449
450 existing = set_get(manager->routes_foreign, in);
451 if (existing) {
452 if (ret)
453 *ret = existing;
454 return 0;
455 }
456 }
457
458 return -ENOENT;
459 }
460
461 static void route_copy(Route *dest, const Route *src, const MultipathRoute *m) {
462 assert(dest);
463 assert(src);
464
465 dest->family = src->family;
466 dest->src = src->src;
467 dest->src_prefixlen = src->src_prefixlen;
468 dest->dst = src->dst;
469 dest->dst_prefixlen = src->dst_prefixlen;
470 dest->prefsrc = src->prefsrc;
471 dest->scope = src->scope;
472 dest->protocol = src->protocol;
473 dest->type = src->type;
474 dest->tos = src->tos;
475 dest->priority = src->priority;
476 dest->table = src->table;
477 dest->initcwnd = src->initcwnd;
478 dest->initrwnd = src->initrwnd;
479 dest->lifetime = src->lifetime;
480 dest->advmss= src->advmss;
481
482 if (m) {
483 dest->gw_family = m->gateway.family;
484 dest->gw = m->gateway.address;
485 dest->gw_weight = m->weight;
486 } else {
487 dest->gw_family = src->gw_family;
488 dest->gw = src->gw;
489 dest->gw_weight = src->gw_weight;
490 }
491 }
492
493 static int route_add_internal(Manager *manager, Link *link, Set **routes, const Route *in, Route **ret) {
494 _cleanup_(route_freep) Route *route = NULL;
495 int r;
496
497 assert(manager || link);
498 assert(routes);
499 assert(in);
500
501 r = route_new(&route);
502 if (r < 0)
503 return r;
504
505 route_copy(route, in, NULL);
506
507 r = set_ensure_put(routes, &route_hash_ops, route);
508 if (r < 0)
509 return r;
510 if (r == 0)
511 return -EEXIST;
512
513 route->link = link;
514 route->manager = manager;
515
516 if (ret)
517 *ret = route;
518
519 route = NULL;
520
521 return 0;
522 }
523
524 static int route_add_foreign(Manager *manager, Link *link, const Route *in, Route **ret) {
525 assert(manager || link);
526 return route_add_internal(manager, link, link ? &link->routes_foreign : &manager->routes_foreign, in, ret);
527 }
528
529 static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) {
530 _cleanup_(route_freep) Route *tmp = NULL;
531 Route *route;
532 int r;
533
534 assert(manager || link);
535 assert(in);
536
537 if (m) {
538 assert(link && (m->ifindex == 0 || m->ifindex == link->ifindex));
539
540 r = route_new(&tmp);
541 if (r < 0)
542 return r;
543
544 route_copy(tmp, in, m);
545 in = tmp;
546 }
547
548 r = route_get(manager, link, in, &route);
549 if (r == -ENOENT) {
550 /* Route does not exist, create a new one */
551 r = route_add_internal(manager, link, link ? &link->routes : &manager->routes, in, &route);
552 if (r < 0)
553 return r;
554 } else if (r == 0) {
555 /* Take over a foreign route */
556 if (link) {
557 r = set_ensure_put(&link->routes, &route_hash_ops, route);
558 if (r < 0)
559 return r;
560
561 set_remove(link->routes_foreign, route);
562 } else {
563 r = set_ensure_put(&manager->routes, &route_hash_ops, route);
564 if (r < 0)
565 return r;
566
567 set_remove(manager->routes_foreign, route);
568 }
569 } else if (r == 1) {
570 /* Route exists, do nothing */
571 ;
572 } else
573 return r;
574
575 if (ret)
576 *ret = route;
577
578 return 0;
579 }
580
581 static bool route_type_is_reject(const Route *route) {
582 assert(route);
583
584 return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW);
585 }
586
587 static void log_route_debug(const Route *route, const char *str, const Link *link) {
588 assert(route);
589 assert(str);
590
591 /* link may be NULL. */
592
593 if (DEBUG_LOGGING) {
594 _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
595 char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
596
597 if (!in_addr_is_null(route->family, &route->dst)) {
598 (void) in_addr_to_string(route->family, &route->dst, &dst);
599 (void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen);
600 }
601 if (!in_addr_is_null(route->family, &route->src))
602 (void) in_addr_to_string(route->family, &route->src, &src);
603 if (!in_addr_is_null(route->gw_family, &route->gw))
604 (void) in_addr_to_string(route->gw_family, &route->gw, &gw);
605 if (!in_addr_is_null(route->family, &route->prefsrc))
606 (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
607
608 log_link_debug(link,
609 "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
610 str, strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
611 format_route_scope(route->scope, scope, sizeof(scope)),
612 format_route_table(route->table, table, sizeof(table)),
613 format_route_protocol(route->protocol, protocol, sizeof(protocol)),
614 strna(route_type_to_string(route->type)));
615 }
616 }
617
618 static int route_set_netlink_message(const Route *route, sd_netlink_message *req, Link *link) {
619 unsigned flags;
620 int r;
621
622 assert(route);
623 assert(req);
624
625 /* link may be NULL */
626
627 if (in_addr_is_null(route->gw_family, &route->gw) == 0) {
628 if (route->gw_family == route->family) {
629 r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
630 if (r < 0)
631 return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
632 } else {
633 RouteVia rtvia = {
634 .family = route->gw_family,
635 .address = route->gw,
636 };
637
638 r = sd_netlink_message_append_data(req, RTA_VIA, &rtvia, sizeof(rtvia));
639 if (r < 0)
640 return log_link_error_errno(link, r, "Could not append RTA_VIA attribute: %m");
641 }
642 }
643
644 if (route->dst_prefixlen > 0) {
645 r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
646 if (r < 0)
647 return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
648
649 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
650 if (r < 0)
651 return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
652 }
653
654 if (route->src_prefixlen > 0) {
655 r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
656 if (r < 0)
657 return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
658
659 r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
660 if (r < 0)
661 return log_link_error_errno(link, r, "Could not set source prefix length: %m");
662 }
663
664 if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
665 r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
666 if (r < 0)
667 return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
668 }
669
670 r = sd_rtnl_message_route_set_scope(req, route->scope);
671 if (r < 0)
672 return log_link_error_errno(link, r, "Could not set scope: %m");
673
674 flags = route->flags;
675 if (route->gateway_onlink >= 0)
676 SET_FLAG(flags, RTNH_F_ONLINK, route->gateway_onlink);
677
678 r = sd_rtnl_message_route_set_flags(req, flags);
679 if (r < 0)
680 return log_link_error_errno(link, r, "Could not set flags: %m");
681
682 if (route->table != RT_TABLE_MAIN) {
683 if (route->table < 256) {
684 r = sd_rtnl_message_route_set_table(req, route->table);
685 if (r < 0)
686 return log_link_error_errno(link, r, "Could not set route table: %m");
687 } else {
688 r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
689 if (r < 0)
690 return log_link_error_errno(link, r, "Could not set route table: %m");
691
692 /* Table attribute to allow more than 256. */
693 r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table));
694 if (r < 0)
695 return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m");
696 }
697 }
698
699 r = sd_rtnl_message_route_set_type(req, route->type);
700 if (r < 0)
701 return log_link_error_errno(link, r, "Could not set route type: %m");
702
703 if (!route_type_is_reject(route)) {
704 assert(link); /* Those routes must be attached to a specific link */
705
706 r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
707 if (r < 0)
708 return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
709 }
710
711 r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
712 if (r < 0)
713 return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
714
715 r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
716 if (r < 0)
717 return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
718
719 return 0;
720 }
721
722 static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
723 int r;
724
725 assert(m);
726
727 /* Note that link may be NULL. */
728 if (link && IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
729 return 1;
730
731 r = sd_netlink_message_get_errno(m);
732 if (r < 0 && r != -ESRCH)
733 log_link_message_warning_errno(link, m, r, "Could not drop route, ignoring");
734
735 return 1;
736 }
737
738 int route_remove(
739 const Route *route,
740 Manager *manager,
741 Link *link,
742 link_netlink_message_handler_t callback) {
743
744 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
745 int r;
746
747 assert(link || manager);
748 assert(IN_SET(route->family, AF_INET, AF_INET6));
749
750 if (!manager)
751 manager = link->manager;
752 /* link may be NULL! */
753
754 log_route_debug(route, "Removing", link);
755
756 r = sd_rtnl_message_new_route(manager->rtnl, &req,
757 RTM_DELROUTE, route->family,
758 route->protocol);
759 if (r < 0)
760 return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
761
762 r = route_set_netlink_message(route, req, link);
763 if (r < 0)
764 return r;
765
766 r = netlink_call_async(manager->rtnl, NULL, req,
767 callback ?: route_remove_handler,
768 link_netlink_destroy_callback, link);
769 if (r < 0)
770 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
771
772 link_ref(link); /* link may be NULL, link_ref() is OK with that */
773
774 return 0;
775 }
776
777 static bool link_has_route(const Link *link, const Route *route) {
778 Route *net_route;
779
780 assert(link);
781 assert(route);
782
783 if (!link->network)
784 return false;
785
786 HASHMAP_FOREACH(net_route, link->network->routes_by_section)
787 if (route_equal(net_route, route))
788 return true;
789
790 return false;
791 }
792
793 static bool links_have_route(const Manager *manager, const Route *route, const Link *except) {
794 Link *link;
795
796 assert(manager);
797
798 HASHMAP_FOREACH(link, manager->links) {
799 if (link == except)
800 continue;
801
802 if (link_has_route(link, route))
803 return true;
804 }
805
806 return false;
807 }
808
809 static int manager_drop_routes_internal(Manager *manager, bool foreign, const Link *except) {
810 Route *route;
811 int k, r = 0;
812 Set *routes;
813
814 assert(manager);
815
816 routes = foreign ? manager->routes_foreign : manager->routes;
817 SET_FOREACH(route, routes) {
818 /* Do not touch routes managed by the kernel */
819 if (route->protocol == RTPROT_KERNEL)
820 continue;
821
822 /* The route will be configured later, or already configured by a link */
823 if (links_have_route(manager, route, except))
824 continue;
825
826 /* The existing links do not have the route. Let's drop this now. It may by
827 * re-configured later. */
828 k = route_remove(route, manager, NULL, NULL);
829 if (k < 0 && r >= 0)
830 r = k;
831 }
832
833 return r;
834 }
835
836 static int manager_drop_foreign_routes(Manager *manager) {
837 return manager_drop_routes_internal(manager, true, NULL);
838 }
839
840 static int manager_drop_routes(Manager *manager, const Link *except) {
841 return manager_drop_routes_internal(manager, false, except);
842 }
843
844 int link_drop_foreign_routes(Link *link) {
845 Route *route;
846 int k, r = 0;
847
848 assert(link);
849 assert(link->manager);
850
851 SET_FOREACH(route, link->routes_foreign) {
852 /* do not touch routes managed by the kernel */
853 if (route->protocol == RTPROT_KERNEL)
854 continue;
855
856 /* do not touch multicast route added by kernel */
857 /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that.
858 * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */
859 if (route->protocol == RTPROT_BOOT &&
860 route->family == AF_INET6 &&
861 route->dst_prefixlen == 8 &&
862 in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} }))
863 continue;
864
865 if (route->protocol == RTPROT_STATIC && link->network &&
866 FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC))
867 continue;
868
869 if (route->protocol == RTPROT_DHCP && link->network &&
870 FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
871 continue;
872
873 if (link_has_route(link, route))
874 k = route_add(NULL, link, route, NULL, NULL);
875 else
876 k = route_remove(route, NULL, link, NULL);
877 if (k < 0 && r >= 0)
878 r = k;
879 }
880
881 k = manager_drop_foreign_routes(link->manager);
882 if (k < 0 && r >= 0)
883 r = k;
884
885 return r;
886 }
887
888 int link_drop_routes(Link *link) {
889 Route *route;
890 int k, r = 0;
891
892 assert(link);
893
894 SET_FOREACH(route, link->routes) {
895 /* do not touch routes managed by the kernel */
896 if (route->protocol == RTPROT_KERNEL)
897 continue;
898
899 k = route_remove(route, NULL, link, NULL);
900 if (k < 0 && r >= 0)
901 r = k;
902 }
903
904 k = manager_drop_routes(link->manager, link);
905 if (k < 0 && r >= 0)
906 r = k;
907
908 return r;
909 }
910
911 static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
912 Route *route = userdata;
913 int r;
914
915 assert(route);
916
917 r = route_remove(route, route->manager, route->link, NULL);
918 if (r < 0) {
919 log_link_warning_errno(route->link, r, "Could not remove route: %m");
920 route_free(route);
921 }
922
923 return 1;
924 }
925
926 static int route_add_and_setup_timer(Link *link, const Route *route, const MultipathRoute *m, Route **ret) {
927 _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
928 Route *nr;
929 int r;
930
931 assert(link);
932 assert(route);
933
934 if (route_type_is_reject(route))
935 r = route_add(link->manager, NULL, route, NULL, &nr);
936 else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex)
937 r = route_add(NULL, link, route, m, &nr);
938 else {
939 Link *link_gw;
940
941 r = link_get(link->manager, m->ifindex, &link_gw);
942 if (r < 0)
943 return log_link_error_errno(link, r, "Failed to get link with ifindex %d: %m", m->ifindex);
944
945 r = route_add(NULL, link_gw, route, m, &nr);
946 }
947 if (r < 0)
948 return log_link_error_errno(link, r, "Could not add route: %m");
949
950 /* TODO: drop expiration handling once it can be pushed into the kernel */
951 if (nr->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
952 r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
953 nr->lifetime, 0, route_expire_handler, nr);
954 if (r < 0)
955 return log_link_error_errno(link, r, "Could not arm expiration timer: %m");
956 }
957
958 sd_event_source_unref(nr->expire);
959 nr->expire = TAKE_PTR(expire);
960
961 if (ret)
962 *ret = nr;
963
964 return 0;
965 }
966
967 static int append_nexthop_one(const Route *route, const MultipathRoute *m, struct rtattr **rta, size_t offset) {
968 struct rtnexthop *rtnh;
969 struct rtattr *new_rta;
970 int r;
971
972 assert(route);
973 assert(m);
974 assert(rta);
975 assert(*rta);
976
977 new_rta = realloc(*rta, RTA_ALIGN((*rta)->rta_len) + RTA_SPACE(sizeof(struct rtnexthop)));
978 if (!new_rta)
979 return -ENOMEM;
980 *rta = new_rta;
981
982 rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset);
983 *rtnh = (struct rtnexthop) {
984 .rtnh_len = sizeof(*rtnh),
985 .rtnh_ifindex = m->ifindex,
986 .rtnh_hops = m->weight > 0 ? m->weight - 1 : 0,
987 };
988
989 (*rta)->rta_len += sizeof(struct rtnexthop);
990
991 if (route->family == m->gateway.family) {
992 r = rtattr_append_attribute(rta, RTA_GATEWAY, &m->gateway.address, FAMILY_ADDRESS_SIZE(m->gateway.family));
993 if (r < 0)
994 goto clear;
995 rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset);
996 rtnh->rtnh_len += RTA_SPACE(FAMILY_ADDRESS_SIZE(m->gateway.family));
997 } else {
998 r = rtattr_append_attribute(rta, RTA_VIA, &m->gateway, FAMILY_ADDRESS_SIZE(m->gateway.family) + sizeof(m->gateway.family));
999 if (r < 0)
1000 goto clear;
1001 rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset);
1002 rtnh->rtnh_len += RTA_SPACE(FAMILY_ADDRESS_SIZE(m->gateway.family) + sizeof(m->gateway.family));
1003 }
1004
1005 return 0;
1006
1007 clear:
1008 (*rta)->rta_len -= sizeof(struct rtnexthop);
1009 return r;
1010 }
1011
1012 static int append_nexthops(const Route *route, sd_netlink_message *req) {
1013 _cleanup_free_ struct rtattr *rta = NULL;
1014 struct rtnexthop *rtnh;
1015 MultipathRoute *m;
1016 size_t offset;
1017 int r;
1018
1019 if (ordered_set_isempty(route->multipath_routes))
1020 return 0;
1021
1022 rta = new(struct rtattr, 1);
1023 if (!rta)
1024 return -ENOMEM;
1025
1026 *rta = (struct rtattr) {
1027 .rta_type = RTA_MULTIPATH,
1028 .rta_len = RTA_LENGTH(0),
1029 };
1030 offset = (uint8_t *) RTA_DATA(rta) - (uint8_t *) rta;
1031
1032 ORDERED_SET_FOREACH(m, route->multipath_routes) {
1033 r = append_nexthop_one(route, m, &rta, offset);
1034 if (r < 0)
1035 return r;
1036
1037 rtnh = (struct rtnexthop *)((uint8_t *) rta + offset);
1038 offset = (uint8_t *) RTNH_NEXT(rtnh) - (uint8_t *) rta;
1039 }
1040
1041 r = sd_netlink_message_append_data(req, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta));
1042 if (r < 0)
1043 return r;
1044
1045 return 0;
1046 }
1047
1048 int route_configure(
1049 const Route *route,
1050 Link *link,
1051 link_netlink_message_handler_t callback,
1052 Route **ret) {
1053
1054 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1055 int r;
1056
1057 assert(link);
1058 assert(link->manager);
1059 assert(link->manager->rtnl);
1060 assert(link->ifindex > 0);
1061 assert(IN_SET(route->family, AF_INET, AF_INET6));
1062 assert(callback);
1063
1064 if (route_get(link->manager, link, route, NULL) <= 0 &&
1065 set_size(link->routes) >= routes_max())
1066 return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
1067 "Too many routes are configured, refusing: %m");
1068
1069 log_route_debug(route, "Configuring", link);
1070
1071 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
1072 RTM_NEWROUTE, route->family,
1073 route->protocol);
1074 if (r < 0)
1075 return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
1076
1077 r = route_set_netlink_message(route, req, link);
1078 if (r < 0)
1079 return r;
1080
1081 if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
1082 r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
1083 DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
1084 if (r < 0)
1085 return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
1086 }
1087
1088 if (route->ttl_propagate >= 0) {
1089 r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate);
1090 if (r < 0)
1091 return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m");
1092 }
1093
1094 r = sd_netlink_message_open_container(req, RTA_METRICS);
1095 if (r < 0)
1096 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
1097
1098 if (route->mtu > 0) {
1099 r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu);
1100 if (r < 0)
1101 return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m");
1102 }
1103
1104 if (route->initcwnd > 0) {
1105 r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd);
1106 if (r < 0)
1107 return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m");
1108 }
1109
1110 if (route->initrwnd > 0) {
1111 r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd);
1112 if (r < 0)
1113 return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
1114 }
1115
1116 if (route->quickack >= 0) {
1117 r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
1118 if (r < 0)
1119 return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
1120 }
1121
1122 if (route->fast_open_no_cookie >= 0) {
1123 r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie);
1124 if (r < 0)
1125 return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m");
1126 }
1127
1128 if (route->advmss > 0) {
1129 r = sd_netlink_message_append_u32(req, RTAX_ADVMSS, route->advmss);
1130 if (r < 0)
1131 return log_link_error_errno(link, r, "Could not append RTAX_ADVMSS attribute: %m");
1132 }
1133
1134 r = sd_netlink_message_close_container(req);
1135 if (r < 0)
1136 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
1137
1138 r = append_nexthops(route, req);
1139 if (r < 0)
1140 return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
1141
1142 if (ordered_set_isempty(route->multipath_routes)) {
1143 Route *nr;
1144
1145 r = route_add_and_setup_timer(link, route, NULL, &nr);
1146 if (r < 0)
1147 return r;
1148
1149 if (ret)
1150 *ret = nr;
1151 } else {
1152 MultipathRoute *m;
1153
1154 assert(!ret);
1155
1156 ORDERED_SET_FOREACH(m, route->multipath_routes) {
1157 r = route_add_and_setup_timer(link, route, m, NULL);
1158 if (r < 0)
1159 return r;
1160 }
1161 }
1162
1163 r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
1164 link_netlink_destroy_callback, link);
1165 if (r < 0)
1166 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
1167
1168 link_ref(link);
1169
1170 return 0;
1171 }
1172
1173 static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
1174 int r;
1175
1176 assert(link);
1177 assert(link->route_messages > 0);
1178
1179 link->route_messages--;
1180
1181 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1182 return 1;
1183
1184 r = sd_netlink_message_get_errno(m);
1185 if (r < 0 && r != -EEXIST) {
1186 log_link_message_warning_errno(link, m, r, "Could not set route");
1187 link_enter_failed(link);
1188 return 1;
1189 }
1190
1191 if (link->route_messages == 0) {
1192 log_link_debug(link, "Routes set");
1193 link->static_routes_configured = true;
1194 link_set_nexthop(link);
1195 }
1196
1197 return 1;
1198 }
1199
1200 int link_set_routes(Link *link) {
1201 enum {
1202 PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
1203 PHASE_GATEWAY, /* Second phase: Routes with a gateway */
1204 _PHASE_MAX
1205 } phase;
1206 Route *rt;
1207 int r;
1208
1209 assert(link);
1210 assert(link->network);
1211 assert(link->state != _LINK_STATE_INVALID);
1212
1213 link->static_routes_configured = false;
1214
1215 if (!link->addresses_ready)
1216 return 0;
1217
1218 if (!link_has_carrier(link) && !link->network->configure_without_carrier)
1219 /* During configuring addresses, the link lost its carrier. As networkd is dropping
1220 * the addresses now, let's not configure the routes either. */
1221 return 0;
1222
1223 if (link->route_messages != 0) {
1224 log_link_debug(link, "Static routes are configuring.");
1225 return 0;
1226 }
1227
1228 r = link_set_routing_policy_rules(link);
1229 if (r < 0)
1230 return r;
1231
1232 /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
1233 for (phase = 0; phase < _PHASE_MAX; phase++)
1234 HASHMAP_FOREACH(rt, link->network->routes_by_section) {
1235 if (rt->gateway_from_dhcp_or_ra)
1236 continue;
1237
1238 if ((in_addr_is_null(rt->gw_family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
1239 continue;
1240
1241 r = route_configure(rt, link, route_handler, NULL);
1242 if (r < 0)
1243 return log_link_warning_errno(link, r, "Could not set routes: %m");
1244
1245 link->route_messages++;
1246 }
1247
1248 if (link->route_messages == 0) {
1249 link->static_routes_configured = true;
1250 link_set_nexthop(link);
1251 } else {
1252 log_link_debug(link, "Setting routes");
1253 link_set_state(link, LINK_STATE_CONFIGURING);
1254 }
1255
1256 return 0;
1257 }
1258
1259 static int process_route_one(Manager *manager, Link *link, uint16_t type, const Route *tmp, const MultipathRoute *m) {
1260 _cleanup_(route_freep) Route *nr = NULL;
1261 Route *route = NULL;
1262 int r;
1263
1264 assert(manager);
1265 assert(tmp);
1266 assert(IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE));
1267
1268 if (m) {
1269 if (link)
1270 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EINVAL),
1271 "rtnl: received route contains both RTA_OIF and RTA_MULTIPATH, ignoring.");
1272
1273 if (m->ifindex <= 0)
1274 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
1275 "rtnl: received multipath route with invalid ifindex, ignoring.");
1276
1277 r = link_get(manager, m->ifindex, &link);
1278 if (r < 0) {
1279 log_warning_errno(r, "rtnl: received multipath route for link (%d) we do not know, ignoring: %m", m->ifindex);
1280 return 0;
1281 }
1282
1283 r = route_new(&nr);
1284 if (r < 0)
1285 return log_oom();
1286
1287 route_copy(nr, tmp, m);
1288
1289 tmp = nr;
1290 }
1291
1292 (void) route_get(manager, link, tmp, &route);
1293
1294 switch (type) {
1295 case RTM_NEWROUTE:
1296 if (!route) {
1297 if (!manager->manage_foreign_routes)
1298 log_route_debug(tmp, "Ignoring received foreign", link);
1299 else {
1300 /* A route appeared that we did not request */
1301 log_route_debug(tmp, "Remembering foreign", link);
1302 r = route_add_foreign(manager, link, tmp, NULL);
1303 if (r < 0) {
1304 log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
1305 return 0;
1306 }
1307 }
1308 } else
1309 log_route_debug(tmp, "Received remembered", link);
1310
1311 break;
1312
1313 case RTM_DELROUTE:
1314 log_route_debug(tmp,
1315 route ? "Forgetting" :
1316 manager->manage_foreign_routes ? "Kernel removed unknown" : "Ignoring received foreign", link);
1317 route_free(route);
1318 break;
1319
1320 default:
1321 assert_not_reached("Received route message with invalid RTNL message type");
1322 }
1323
1324 return 1;
1325 }
1326
1327 int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
1328 _cleanup_ordered_set_free_free_ OrderedSet *multipath_routes = NULL;
1329 _cleanup_(route_freep) Route *tmp = NULL;
1330 _cleanup_free_ void *rta_multipath = NULL;
1331 Link *link = NULL;
1332 uint32_t ifindex;
1333 uint16_t type;
1334 unsigned char table;
1335 size_t rta_len;
1336 int r;
1337
1338 assert(rtnl);
1339 assert(message);
1340 assert(m);
1341
1342 if (sd_netlink_message_is_error(message)) {
1343 r = sd_netlink_message_get_errno(message);
1344 if (r < 0)
1345 log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring");
1346
1347 return 0;
1348 }
1349
1350 r = sd_netlink_message_get_type(message, &type);
1351 if (r < 0) {
1352 log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
1353 return 0;
1354 } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) {
1355 log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type);
1356 return 0;
1357 }
1358
1359 r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex);
1360 if (r < 0 && r != -ENODATA) {
1361 log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m");
1362 return 0;
1363 } else if (r >= 0) {
1364 if (ifindex <= 0) {
1365 log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex);
1366 return 0;
1367 }
1368
1369 r = link_get(m, ifindex, &link);
1370 if (r < 0 || !link) {
1371 /* when enumerating we might be out of sync, but we will
1372 * get the route again, so just ignore it */
1373 if (!m->enumerating)
1374 log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex);
1375 return 0;
1376 }
1377 }
1378
1379 r = route_new(&tmp);
1380 if (r < 0)
1381 return log_oom();
1382
1383 r = sd_rtnl_message_route_get_family(message, &tmp->family);
1384 if (r < 0) {
1385 log_link_warning(link, "rtnl: received route message without family, ignoring");
1386 return 0;
1387 } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
1388 log_link_debug(link, "rtnl: received route message with invalid family '%i', ignoring", tmp->family);
1389 return 0;
1390 }
1391
1392 r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol);
1393 if (r < 0) {
1394 log_warning_errno(r, "rtnl: received route message without route protocol: %m");
1395 return 0;
1396 }
1397
1398 r = netlink_message_read_in_addr_union(message, RTA_DST, tmp->family, &tmp->dst);
1399 if (r < 0 && r != -ENODATA) {
1400 log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
1401 return 0;
1402 }
1403
1404 r = netlink_message_read_in_addr_union(message, RTA_GATEWAY, tmp->family, &tmp->gw);
1405 if (r < 0 && r != -ENODATA) {
1406 log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
1407 return 0;
1408 } else if (r >= 0)
1409 tmp->gw_family = tmp->family;
1410 else if (tmp->family == AF_INET) {
1411 RouteVia via;
1412
1413 r = sd_netlink_message_read(message, RTA_VIA, sizeof(via), &via);
1414 if (r < 0 && r != -ENODATA) {
1415 log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
1416 return 0;
1417 } else if (r >= 0) {
1418 tmp->gw_family = via.family;
1419 tmp->gw = via.address;
1420 }
1421 }
1422
1423 r = netlink_message_read_in_addr_union(message, RTA_SRC, tmp->family, &tmp->src);
1424 if (r < 0 && r != -ENODATA) {
1425 log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
1426 return 0;
1427 }
1428
1429 r = netlink_message_read_in_addr_union(message, RTA_PREFSRC, tmp->family, &tmp->prefsrc);
1430 if (r < 0 && r != -ENODATA) {
1431 log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
1432 return 0;
1433 }
1434
1435 r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen);
1436 if (r < 0) {
1437 log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
1438 return 0;
1439 }
1440
1441 r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen);
1442 if (r < 0) {
1443 log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
1444 return 0;
1445 }
1446
1447 r = sd_rtnl_message_route_get_scope(message, &tmp->scope);
1448 if (r < 0) {
1449 log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m");
1450 return 0;
1451 }
1452
1453 r = sd_rtnl_message_route_get_tos(message, &tmp->tos);
1454 if (r < 0) {
1455 log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m");
1456 return 0;
1457 }
1458
1459 r = sd_rtnl_message_route_get_type(message, &tmp->type);
1460 if (r < 0) {
1461 log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m");
1462 return 0;
1463 }
1464
1465 r = sd_rtnl_message_route_get_table(message, &table);
1466 if (r < 0) {
1467 log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m");
1468 return 0;
1469 }
1470 tmp->table = table;
1471
1472 r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority);
1473 if (r < 0 && r != -ENODATA) {
1474 log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m");
1475 return 0;
1476 }
1477
1478 r = sd_netlink_message_enter_container(message, RTA_METRICS);
1479 if (r < 0 && r != -ENODATA) {
1480 log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m");
1481 return 0;
1482 }
1483 if (r >= 0) {
1484 r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd);
1485 if (r < 0 && r != -ENODATA) {
1486 log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m");
1487 return 0;
1488 }
1489
1490 r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd);
1491 if (r < 0 && r != -ENODATA) {
1492 log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m");
1493 return 0;
1494 }
1495
1496 r = sd_netlink_message_read_u32(message, RTAX_ADVMSS, &tmp->advmss);
1497 if (r < 0 && r != -ENODATA) {
1498 log_link_warning_errno(link, r, "rtnl: received route message with invalid advmss, ignoring: %m");
1499 return 0;
1500 }
1501
1502 r = sd_netlink_message_exit_container(message);
1503 if (r < 0) {
1504 log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m");
1505 return 0;
1506 }
1507 }
1508
1509 r = sd_netlink_message_read_data(message, RTA_MULTIPATH, &rta_len, &rta_multipath);
1510 if (r < 0 && r != -ENODATA) {
1511 log_link_warning_errno(link, r, "rtnl: failed to read RTA_MULTIPATH attribute, ignoring: %m");
1512 return 0;
1513 } else if (r >= 0) {
1514 r = rtattr_read_nexthop(rta_multipath, rta_len, tmp->family, &multipath_routes);
1515 if (r < 0) {
1516 log_link_warning_errno(link, r, "rtnl: failed to parse RTA_MULTIPATH attribute, ignoring: %m");
1517 return 0;
1518 }
1519 }
1520
1521 /* IPv6 routes with reject type are always assigned to the loopback interface. See kernel's
1522 * fib6_nh_init() in net/ipv6/route.c. However, we'd like to manage them by Manager. Hence, set
1523 * link to NULL here. */
1524 if (route_type_is_reject(tmp))
1525 link = NULL;
1526
1527 if (ordered_set_isempty(multipath_routes))
1528 (void) process_route_one(m, link, type, tmp, NULL);
1529 else {
1530 MultipathRoute *mr;
1531
1532 ORDERED_SET_FOREACH(mr, multipath_routes) {
1533 r = process_route_one(m, link, type, tmp, mr);
1534 if (r < 0)
1535 break;
1536 }
1537 }
1538
1539 return 1;
1540 }
1541
1542 int network_add_ipv4ll_route(Network *network) {
1543 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1544 unsigned section_line;
1545 int r;
1546
1547 assert(network);
1548
1549 if (!network->ipv4ll_route)
1550 return 0;
1551
1552 section_line = hashmap_find_free_section_line(network->routes_by_section);
1553
1554 /* IPv4LLRoute= is in [Network] section. */
1555 r = route_new_static(network, network->filename, section_line, &n);
1556 if (r < 0)
1557 return r;
1558
1559 r = in_addr_from_string(AF_INET, "169.254.0.0", &n->dst);
1560 if (r < 0)
1561 return r;
1562
1563 n->family = AF_INET;
1564 n->dst_prefixlen = 16;
1565 n->scope = RT_SCOPE_LINK;
1566 n->scope_set = true;
1567 n->table_set = true;
1568 n->priority = IPV4LL_ROUTE_METRIC;
1569 n->protocol = RTPROT_STATIC;
1570
1571 TAKE_PTR(n);
1572 return 0;
1573 }
1574
1575 int network_add_default_route_on_device(Network *network) {
1576 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1577 unsigned section_line;
1578 int r;
1579
1580 assert(network);
1581
1582 if (!network->default_route_on_device)
1583 return 0;
1584
1585 section_line = hashmap_find_free_section_line(network->routes_by_section);
1586
1587 /* DefaultRouteOnDevice= is in [Network] section. */
1588 r = route_new_static(network, network->filename, section_line, &n);
1589 if (r < 0)
1590 return r;
1591
1592 n->family = AF_INET;
1593 n->scope = RT_SCOPE_LINK;
1594 n->scope_set = true;
1595 n->protocol = RTPROT_STATIC;
1596
1597 TAKE_PTR(n);
1598 return 0;
1599 }
1600
1601 int config_parse_gateway(
1602 const char *unit,
1603 const char *filename,
1604 unsigned line,
1605 const char *section,
1606 unsigned section_line,
1607 const char *lvalue,
1608 int ltype,
1609 const char *rvalue,
1610 void *data,
1611 void *userdata) {
1612
1613 Network *network = userdata;
1614 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1615 int r;
1616
1617 assert(filename);
1618 assert(section);
1619 assert(lvalue);
1620 assert(rvalue);
1621 assert(data);
1622
1623 if (streq(section, "Network")) {
1624 /* we are not in an Route section, so use line number instead */
1625 r = route_new_static(network, filename, line, &n);
1626 if (r == -ENOMEM)
1627 return log_oom();
1628 if (r < 0) {
1629 log_syntax(unit, LOG_WARNING, filename, line, r,
1630 "Failed to allocate route, ignoring assignment: %m");
1631 return 0;
1632 }
1633 } else {
1634 r = route_new_static(network, filename, section_line, &n);
1635 if (r == -ENOMEM)
1636 return log_oom();
1637 if (r < 0) {
1638 log_syntax(unit, LOG_WARNING, filename, line, r,
1639 "Failed to allocate route, ignoring assignment: %m");
1640 return 0;
1641 }
1642
1643 if (isempty(rvalue)) {
1644 n->gateway_from_dhcp_or_ra = false;
1645 n->gw_family = AF_UNSPEC;
1646 n->gw = IN_ADDR_NULL;
1647 TAKE_PTR(n);
1648 return 0;
1649 }
1650
1651 if (streq(rvalue, "_dhcp")) {
1652 n->gateway_from_dhcp_or_ra = true;
1653 TAKE_PTR(n);
1654 return 0;
1655 }
1656
1657 if (streq(rvalue, "_dhcp4")) {
1658 n->gw_family = AF_INET;
1659 n->gateway_from_dhcp_or_ra = true;
1660 TAKE_PTR(n);
1661 return 0;
1662 }
1663
1664 if (streq(rvalue, "_ipv6ra")) {
1665 n->gw_family = AF_INET6;
1666 n->gateway_from_dhcp_or_ra = true;
1667 TAKE_PTR(n);
1668 return 0;
1669 }
1670 }
1671
1672 r = in_addr_from_string_auto(rvalue, &n->gw_family, &n->gw);
1673 if (r < 0) {
1674 log_syntax(unit, LOG_WARNING, filename, line, r,
1675 "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
1676 return 0;
1677 }
1678
1679 n->gateway_from_dhcp_or_ra = false;
1680 TAKE_PTR(n);
1681 return 0;
1682 }
1683
1684 int config_parse_preferred_src(
1685 const char *unit,
1686 const char *filename,
1687 unsigned line,
1688 const char *section,
1689 unsigned section_line,
1690 const char *lvalue,
1691 int ltype,
1692 const char *rvalue,
1693 void *data,
1694 void *userdata) {
1695
1696 Network *network = userdata;
1697 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1698 int r;
1699
1700 assert(filename);
1701 assert(section);
1702 assert(lvalue);
1703 assert(rvalue);
1704 assert(data);
1705
1706 r = route_new_static(network, filename, section_line, &n);
1707 if (r == -ENOMEM)
1708 return log_oom();
1709 if (r < 0) {
1710 log_syntax(unit, LOG_WARNING, filename, line, r,
1711 "Failed to allocate route, ignoring assignment: %m");
1712 return 0;
1713 }
1714
1715 if (n->family == AF_UNSPEC)
1716 r = in_addr_from_string_auto(rvalue, &n->family, &n->prefsrc);
1717 else
1718 r = in_addr_from_string(n->family, rvalue, &n->prefsrc);
1719 if (r < 0) {
1720 log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
1721 "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
1722 return 0;
1723 }
1724
1725 TAKE_PTR(n);
1726 return 0;
1727 }
1728
1729 int config_parse_destination(
1730 const char *unit,
1731 const char *filename,
1732 unsigned line,
1733 const char *section,
1734 unsigned section_line,
1735 const char *lvalue,
1736 int ltype,
1737 const char *rvalue,
1738 void *data,
1739 void *userdata) {
1740
1741 Network *network = userdata;
1742 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1743 union in_addr_union *buffer;
1744 unsigned char *prefixlen;
1745 int r;
1746
1747 assert(filename);
1748 assert(section);
1749 assert(lvalue);
1750 assert(rvalue);
1751 assert(data);
1752
1753 r = route_new_static(network, filename, section_line, &n);
1754 if (r == -ENOMEM)
1755 return log_oom();
1756 if (r < 0) {
1757 log_syntax(unit, LOG_WARNING, filename, line, r,
1758 "Failed to allocate route, ignoring assignment: %m");
1759 return 0;
1760 }
1761
1762 if (streq(lvalue, "Destination")) {
1763 buffer = &n->dst;
1764 prefixlen = &n->dst_prefixlen;
1765 } else if (streq(lvalue, "Source")) {
1766 buffer = &n->src;
1767 prefixlen = &n->src_prefixlen;
1768 } else
1769 assert_not_reached(lvalue);
1770
1771 if (n->family == AF_UNSPEC)
1772 r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen);
1773 else
1774 r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen);
1775 if (r < 0) {
1776 log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
1777 "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
1778 return 0;
1779 }
1780
1781 TAKE_PTR(n);
1782 return 0;
1783 }
1784
1785 int config_parse_route_priority(
1786 const char *unit,
1787 const char *filename,
1788 unsigned line,
1789 const char *section,
1790 unsigned section_line,
1791 const char *lvalue,
1792 int ltype,
1793 const char *rvalue,
1794 void *data,
1795 void *userdata) {
1796
1797 Network *network = userdata;
1798 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1799 int r;
1800
1801 assert(filename);
1802 assert(section);
1803 assert(lvalue);
1804 assert(rvalue);
1805 assert(data);
1806
1807 r = route_new_static(network, filename, section_line, &n);
1808 if (r == -ENOMEM)
1809 return log_oom();
1810 if (r < 0) {
1811 log_syntax(unit, LOG_WARNING, filename, line, r,
1812 "Failed to allocate route, ignoring assignment: %m");
1813 return 0;
1814 }
1815
1816 r = safe_atou32(rvalue, &n->priority);
1817 if (r < 0) {
1818 log_syntax(unit, LOG_WARNING, filename, line, r,
1819 "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
1820 return 0;
1821 }
1822
1823 n->priority_set = true;
1824 TAKE_PTR(n);
1825 return 0;
1826 }
1827
1828 int config_parse_route_scope(
1829 const char *unit,
1830 const char *filename,
1831 unsigned line,
1832 const char *section,
1833 unsigned section_line,
1834 const char *lvalue,
1835 int ltype,
1836 const char *rvalue,
1837 void *data,
1838 void *userdata) {
1839
1840 Network *network = userdata;
1841 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1842 int r;
1843
1844 assert(filename);
1845 assert(section);
1846 assert(lvalue);
1847 assert(rvalue);
1848 assert(data);
1849
1850 r = route_new_static(network, filename, section_line, &n);
1851 if (r == -ENOMEM)
1852 return log_oom();
1853 if (r < 0) {
1854 log_syntax(unit, LOG_WARNING, filename, line, r,
1855 "Failed to allocate route, ignoring assignment: %m");
1856 return 0;
1857 }
1858
1859 r = route_scope_from_string(rvalue);
1860 if (r < 0) {
1861 log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route scope: %s", rvalue);
1862 return 0;
1863 }
1864
1865 n->scope = r;
1866 n->scope_set = true;
1867 TAKE_PTR(n);
1868 return 0;
1869 }
1870
1871 int route_table_from_string_full(Manager *m, const char *s, uint32_t *ret) {
1872 int r;
1873
1874 assert(s);
1875 assert(m);
1876 assert(ret);
1877
1878 r = route_table_from_string(s);
1879 if (r >= 0) {
1880 *ret = (uint32_t) r;
1881 return 0;
1882 }
1883
1884 uint32_t t = PTR_TO_UINT32(hashmap_get(m->route_tables, s));
1885 if (t != 0) {
1886 *ret = t;
1887 return 0;
1888 }
1889
1890 return safe_atou32(s, ret);
1891 }
1892
1893 int config_parse_route_table(
1894 const char *unit,
1895 const char *filename,
1896 unsigned line,
1897 const char *section,
1898 unsigned section_line,
1899 const char *lvalue,
1900 int ltype,
1901 const char *rvalue,
1902 void *data,
1903 void *userdata) {
1904
1905 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1906 Network *network = userdata;
1907 int r;
1908
1909 assert(filename);
1910 assert(section);
1911 assert(lvalue);
1912 assert(rvalue);
1913 assert(data);
1914
1915 r = route_new_static(network, filename, section_line, &n);
1916 if (r == -ENOMEM)
1917 return log_oom();
1918 if (r < 0) {
1919 log_syntax(unit, LOG_WARNING, filename, line, r,
1920 "Failed to allocate route, ignoring assignment: %m");
1921 return 0;
1922 }
1923
1924 r = route_table_from_string_full(network->manager, rvalue, &n->table);
1925 if (r < 0) {
1926 log_syntax(unit, LOG_WARNING, filename, line, r,
1927 "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
1928 return 0;
1929 }
1930
1931 n->table_set = true;
1932 TAKE_PTR(n);
1933 return 0;
1934 }
1935
1936 int config_parse_route_boolean(
1937 const char *unit,
1938 const char *filename,
1939 unsigned line,
1940 const char *section,
1941 unsigned section_line,
1942 const char *lvalue,
1943 int ltype,
1944 const char *rvalue,
1945 void *data,
1946 void *userdata) {
1947
1948 Network *network = userdata;
1949 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
1950 int r;
1951
1952 assert(filename);
1953 assert(section);
1954 assert(lvalue);
1955 assert(rvalue);
1956 assert(data);
1957
1958 r = route_new_static(network, filename, section_line, &n);
1959 if (r == -ENOMEM)
1960 return log_oom();
1961 if (r < 0) {
1962 log_syntax(unit, LOG_WARNING, filename, line, r,
1963 "Failed to allocate route, ignoring assignment: %m");
1964 return 0;
1965 }
1966
1967 r = parse_boolean(rvalue);
1968 if (r < 0) {
1969 log_syntax(unit, LOG_WARNING, filename, line, r,
1970 "Could not parse %s=\"%s\", ignoring assignment: %m", lvalue, rvalue);
1971 return 0;
1972 }
1973
1974 if (STR_IN_SET(lvalue, "GatewayOnLink", "GatewayOnlink"))
1975 n->gateway_onlink = r;
1976 else if (streq(lvalue, "QuickAck"))
1977 n->quickack = r;
1978 else if (streq(lvalue, "FastOpenNoCookie"))
1979 n->fast_open_no_cookie = r;
1980 else if (streq(lvalue, "TTLPropagate"))
1981 n->ttl_propagate = r;
1982 else
1983 assert_not_reached("Invalid lvalue");
1984
1985 TAKE_PTR(n);
1986 return 0;
1987 }
1988
1989 int config_parse_ipv6_route_preference(
1990 const char *unit,
1991 const char *filename,
1992 unsigned line,
1993 const char *section,
1994 unsigned section_line,
1995 const char *lvalue,
1996 int ltype,
1997 const char *rvalue,
1998 void *data,
1999 void *userdata) {
2000
2001 Network *network = userdata;
2002 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2003 int r;
2004
2005 r = route_new_static(network, filename, section_line, &n);
2006 if (r == -ENOMEM)
2007 return log_oom();
2008 if (r < 0) {
2009 log_syntax(unit, LOG_WARNING, filename, line, r,
2010 "Failed to allocate route, ignoring assignment: %m");
2011 return 0;
2012 }
2013
2014 if (streq(rvalue, "low"))
2015 n->pref = ICMPV6_ROUTER_PREF_LOW;
2016 else if (streq(rvalue, "medium"))
2017 n->pref = ICMPV6_ROUTER_PREF_MEDIUM;
2018 else if (streq(rvalue, "high"))
2019 n->pref = ICMPV6_ROUTER_PREF_HIGH;
2020 else {
2021 log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route preference: %s", rvalue);
2022 return 0;
2023 }
2024
2025 n->pref_set = true;
2026 TAKE_PTR(n);
2027 return 0;
2028 }
2029
2030 int config_parse_route_protocol(
2031 const char *unit,
2032 const char *filename,
2033 unsigned line,
2034 const char *section,
2035 unsigned section_line,
2036 const char *lvalue,
2037 int ltype,
2038 const char *rvalue,
2039 void *data,
2040 void *userdata) {
2041
2042 Network *network = userdata;
2043 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2044 int r;
2045
2046 r = route_new_static(network, filename, section_line, &n);
2047 if (r == -ENOMEM)
2048 return log_oom();
2049 if (r < 0) {
2050 log_syntax(unit, LOG_WARNING, filename, line, r,
2051 "Failed to allocate route, ignoring assignment: %m");
2052 return 0;
2053 }
2054
2055 r = route_protocol_from_string(rvalue);
2056 if (r >= 0)
2057 n->protocol = r;
2058 else {
2059 r = safe_atou8(rvalue , &n->protocol);
2060 if (r < 0) {
2061 log_syntax(unit, LOG_WARNING, filename, line, r,
2062 "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue);
2063 return 0;
2064 }
2065 }
2066
2067 TAKE_PTR(n);
2068 return 0;
2069 }
2070
2071 int config_parse_route_type(
2072 const char *unit,
2073 const char *filename,
2074 unsigned line,
2075 const char *section,
2076 unsigned section_line,
2077 const char *lvalue,
2078 int ltype,
2079 const char *rvalue,
2080 void *data,
2081 void *userdata) {
2082
2083 Network *network = userdata;
2084 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2085 int t, r;
2086
2087 r = route_new_static(network, filename, section_line, &n);
2088 if (r == -ENOMEM)
2089 return log_oom();
2090 if (r < 0) {
2091 log_syntax(unit, LOG_WARNING, filename, line, r,
2092 "Failed to allocate route, ignoring assignment: %m");
2093 return 0;
2094 }
2095
2096 t = route_type_from_string(rvalue);
2097 if (t < 0) {
2098 log_syntax(unit, LOG_WARNING, filename, line, 0,
2099 "Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
2100 return 0;
2101 }
2102
2103 n->type = (unsigned char) t;
2104
2105 TAKE_PTR(n);
2106 return 0;
2107 }
2108
2109 int config_parse_tcp_advmss(
2110 const char *unit,
2111 const char *filename,
2112 unsigned line,
2113 const char *section,
2114 unsigned section_line,
2115 const char *lvalue,
2116 int ltype,
2117 const char *rvalue,
2118 void *data,
2119 void *userdata) {
2120
2121 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2122 Network *network = userdata;
2123 uint64_t u;
2124 int r;
2125
2126 assert(filename);
2127 assert(section);
2128 assert(lvalue);
2129 assert(rvalue);
2130 assert(data);
2131
2132 r = route_new_static(network, filename, section_line, &n);
2133 if (r == -ENOMEM)
2134 return log_oom();
2135 if (r < 0) {
2136 log_syntax(unit, LOG_WARNING, filename, line, r,
2137 "Failed to allocate route, ignoring assignment: %m");
2138 return 0;
2139 }
2140
2141 if (isempty(rvalue)) {
2142 n->advmss = 0;
2143 TAKE_PTR(n);
2144 return 0;
2145 }
2146
2147 r = parse_size(rvalue, 1024, &u);
2148 if (r < 0) {
2149 log_syntax(unit, LOG_WARNING, filename, line, r,
2150 "Could not parse TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue);
2151 return 0;
2152 }
2153
2154 if (u == 0 || u > UINT32_MAX) {
2155 log_syntax(unit, LOG_WARNING, filename, line, 0,
2156 "Invalid TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue);
2157 return 0;
2158 }
2159
2160 n->advmss = u;
2161
2162 TAKE_PTR(n);
2163 return 0;
2164 }
2165
2166 int config_parse_tcp_window(
2167 const char *unit,
2168 const char *filename,
2169 unsigned line,
2170 const char *section,
2171 unsigned section_line,
2172 const char *lvalue,
2173 int ltype,
2174 const char *rvalue,
2175 void *data,
2176 void *userdata) {
2177
2178 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2179 Network *network = userdata;
2180 uint32_t k;
2181 int r;
2182
2183 assert(filename);
2184 assert(section);
2185 assert(lvalue);
2186 assert(rvalue);
2187 assert(data);
2188
2189 r = route_new_static(network, filename, section_line, &n);
2190 if (r == -ENOMEM)
2191 return log_oom();
2192 if (r < 0) {
2193 log_syntax(unit, LOG_WARNING, filename, line, r,
2194 "Failed to allocate route, ignoring assignment: %m");
2195 return 0;
2196 }
2197
2198 r = safe_atou32(rvalue, &k);
2199 if (r < 0) {
2200 log_syntax(unit, LOG_WARNING, filename, line, r,
2201 "Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
2202 return 0;
2203 }
2204 if (k >= 1024) {
2205 log_syntax(unit, LOG_WARNING, filename, line, 0,
2206 "Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue);
2207 return 0;
2208 }
2209 if (k == 0) {
2210 log_syntax(unit, LOG_WARNING, filename, line, 0,
2211 "Invalid TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
2212 return 0;
2213 }
2214
2215 if (streq(lvalue, "InitialCongestionWindow"))
2216 n->initcwnd = k;
2217 else if (streq(lvalue, "InitialAdvertisedReceiveWindow"))
2218 n->initrwnd = k;
2219 else
2220 assert_not_reached("Invalid TCP window type.");
2221
2222 TAKE_PTR(n);
2223 return 0;
2224 }
2225
2226 int config_parse_route_mtu(
2227 const char *unit,
2228 const char *filename,
2229 unsigned line,
2230 const char *section,
2231 unsigned section_line,
2232 const char *lvalue,
2233 int ltype,
2234 const char *rvalue,
2235 void *data,
2236 void *userdata) {
2237
2238 Network *network = userdata;
2239 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2240 int r;
2241
2242 assert(filename);
2243 assert(section);
2244 assert(lvalue);
2245 assert(rvalue);
2246 assert(data);
2247
2248 r = route_new_static(network, filename, section_line, &n);
2249 if (r == -ENOMEM)
2250 return log_oom();
2251 if (r < 0) {
2252 log_syntax(unit, LOG_WARNING, filename, line, r,
2253 "Failed to allocate route, ignoring assignment: %m");
2254 return 0;
2255 }
2256
2257 r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->mtu, userdata);
2258 if (r < 0)
2259 return r;
2260
2261 TAKE_PTR(n);
2262 return 0;
2263 }
2264
2265 int config_parse_multipath_route(
2266 const char *unit,
2267 const char *filename,
2268 unsigned line,
2269 const char *section,
2270 unsigned section_line,
2271 const char *lvalue,
2272 int ltype,
2273 const char *rvalue,
2274 void *data,
2275 void *userdata) {
2276
2277 _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
2278 _cleanup_free_ char *word = NULL, *buf = NULL;
2279 _cleanup_free_ MultipathRoute *m = NULL;
2280 Network *network = userdata;
2281 const char *p, *ip, *dev;
2282 union in_addr_union a;
2283 int family, r;
2284
2285 assert(filename);
2286 assert(section);
2287 assert(lvalue);
2288 assert(rvalue);
2289 assert(data);
2290
2291 r = route_new_static(network, filename, section_line, &n);
2292 if (r == -ENOMEM)
2293 return log_oom();
2294 if (r < 0) {
2295 log_syntax(unit, LOG_WARNING, filename, line, r,
2296 "Failed to allocate route, ignoring assignment: %m");
2297 return 0;
2298 }
2299
2300 if (isempty(rvalue)) {
2301 n->multipath_routes = ordered_set_free_free(n->multipath_routes);
2302 return 0;
2303 }
2304
2305 m = new0(MultipathRoute, 1);
2306 if (!m)
2307 return log_oom();
2308
2309 p = rvalue;
2310 r = extract_first_word(&p, &word, NULL, 0);
2311 if (r == -ENOMEM)
2312 return log_oom();
2313 if (r <= 0) {
2314 log_syntax(unit, LOG_WARNING, filename, line, r,
2315 "Invalid multipath route option, ignoring assignment: %s", rvalue);
2316 return 0;
2317 }
2318
2319 dev = strchr(word, '@');
2320 if (dev) {
2321 buf = strndup(word, dev - word);
2322 if (!buf)
2323 return log_oom();
2324 ip = buf;
2325 dev++;
2326 } else
2327 ip = word;
2328
2329 r = in_addr_from_string_auto(ip, &family, &a);
2330 if (r < 0) {
2331 log_syntax(unit, LOG_WARNING, filename, line, r,
2332 "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
2333 return 0;
2334 }
2335 m->gateway.address = a;
2336 m->gateway.family = family;
2337
2338 if (dev) {
2339 r = resolve_interface(NULL, dev);
2340 if (r < 0) {
2341 log_syntax(unit, LOG_WARNING, filename, line, r,
2342 "Invalid interface name or index, ignoring assignment: %s", dev);
2343 return 0;
2344 }
2345 m->ifindex = r;
2346 }
2347
2348 if (!isempty(p)) {
2349 r = safe_atou32(p, &m->weight);
2350 if (r < 0) {
2351 log_syntax(unit, LOG_WARNING, filename, line, r,
2352 "Invalid multipath route weight, ignoring assignment: %s", p);
2353 return 0;
2354 }
2355 if (m->weight == 0 || m->weight > 256) {
2356 log_syntax(unit, LOG_WARNING, filename, line, 0,
2357 "Invalid multipath route weight, ignoring assignment: %s", p);
2358 return 0;
2359 }
2360 }
2361
2362 r = ordered_set_ensure_put(&n->multipath_routes, NULL, m);
2363 if (r == -ENOMEM)
2364 return log_oom();
2365 if (r < 0) {
2366 log_syntax(unit, LOG_WARNING, filename, line, r,
2367 "Failed to store multipath route, ignoring assignment: %m");
2368 return 0;
2369 }
2370
2371 TAKE_PTR(m);
2372 TAKE_PTR(n);
2373 return 0;
2374 }
2375
2376 int config_parse_route_table_names(
2377 const char *unit,
2378 const char *filename,
2379 unsigned line,
2380 const char *section,
2381 unsigned section_line,
2382 const char *lvalue,
2383 int ltype,
2384 const char *rvalue,
2385 void *data,
2386 void *userdata) {
2387
2388 _cleanup_free_ char *name = NULL;
2389 Hashmap **s = data;
2390 uint32_t table;
2391 const char *p;
2392 int r;
2393
2394 assert(filename);
2395 assert(lvalue);
2396 assert(rvalue);
2397 assert(data);
2398
2399 if (isempty(rvalue)) {
2400 *s = hashmap_free_free_key(*s);
2401 return 0;
2402 }
2403
2404 p = rvalue;
2405 r = extract_first_word(&p, &name, ":", 0);
2406 if (r == -ENOMEM)
2407 return log_oom();
2408 if (r <= 0 || isempty(p)) {
2409 log_syntax(unit, LOG_WARNING, filename, line, r,
2410 "Invalid RouteTable=, ignoring assignment: %s", rvalue);
2411 return 0;
2412 }
2413
2414 if (STR_IN_SET(name, "default", "main","local")) {
2415 log_syntax(unit, LOG_WARNING, filename, line, r,
2416 "Route table name %s already preconfigured. Ignoring assignment: %s", name, rvalue);
2417 return 0;
2418 }
2419
2420 r = safe_atou32(p, &table);
2421 if (r < 0) {
2422 log_syntax(unit, LOG_WARNING, filename, line, r,
2423 "Failed to parse RouteTable=, ignoring assignment: %s", p);
2424 return 0;
2425 }
2426
2427 if (table == 0) {
2428 log_syntax(unit, LOG_WARNING, filename, line, 0,
2429 "Invalid RouteTable=, ignoring assignment: %s", p);
2430 return 0;
2431 }
2432
2433 r = hashmap_ensure_put(s, &string_hash_ops, name, UINT32_TO_PTR(table));
2434 if (r == -ENOMEM)
2435 return log_oom();
2436 if (r == -EEXIST) {
2437 log_syntax(unit, LOG_WARNING, filename, line, r,
2438 "Specified RouteTable= name and value pair conflicts with others, ignoring assignment: %s", rvalue);
2439 return 0;
2440 }
2441 if (r > 0)
2442 TAKE_PTR(name);
2443
2444 return 0;
2445 }
2446
2447 static int route_section_verify(Route *route, Network *network) {
2448 if (section_is_invalid(route->section))
2449 return -EINVAL;
2450
2451 if (route->gateway_from_dhcp_or_ra) {
2452 if (route->gw_family == AF_UNSPEC) {
2453 /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
2454 switch (route->family) {
2455 case AF_UNSPEC:
2456 log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
2457 "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
2458 route->section->filename, route->section->line);
2459 route->family = AF_INET;
2460 break;
2461 case AF_INET:
2462 case AF_INET6:
2463 log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
2464 "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
2465 route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
2466 break;
2467 default:
2468 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
2469 "%s: Invalid route family. Ignoring [Route] section from line %u.",
2470 route->section->filename, route->section->line);
2471 }
2472 route->gw_family = route->family;
2473 }
2474
2475 if (route->gw_family == AF_INET && !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4))
2476 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
2477 "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
2478 "Ignoring [Route] section from line %u.",
2479 route->section->filename, route->section->line);
2480
2481 if (route->gw_family == AF_INET6 && !network->ipv6_accept_ra)
2482 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
2483 "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
2484 "Ignoring [Route] section from line %u.",
2485 route->section->filename, route->section->line);
2486 }
2487
2488 /* When only Gateway= is specified, assume the route family based on the Gateway address. */
2489 if (route->family == AF_UNSPEC)
2490 route->family = route->gw_family;
2491
2492 if (route->family == AF_UNSPEC) {
2493 assert(route->section);
2494
2495 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
2496 "%s: Route section without Gateway=, Destination=, Source=, "
2497 "or PreferredSource= field configured. "
2498 "Ignoring [Route] section from line %u.",
2499 route->section->filename, route->section->line);
2500 }
2501
2502 if (route->family == AF_INET6 && route->gw_family == AF_INET)
2503 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
2504 "%s: IPv4 gateway is configured for IPv6 route. "
2505 "Ignoring [Route] section from line %u.",
2506 route->section->filename, route->section->line);
2507
2508 if (!route->table_set && network->vrf) {
2509 route->table = VRF(network->vrf)->table;
2510 route->table_set = true;
2511 }
2512
2513 if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT))
2514 route->table = RT_TABLE_LOCAL;
2515
2516 if (!route->scope_set && route->family != AF_INET6) {
2517 if (IN_SET(route->type, RTN_LOCAL, RTN_NAT))
2518 route->scope = RT_SCOPE_HOST;
2519 else if (IN_SET(route->type, RTN_BROADCAST, RTN_ANYCAST, RTN_MULTICAST))
2520 route->scope = RT_SCOPE_LINK;
2521 }
2522
2523 if (route->scope != RT_SCOPE_UNIVERSE && route->family == AF_INET6) {
2524 log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route->section->filename);
2525 route->scope = RT_SCOPE_UNIVERSE;
2526 }
2527
2528 if (route->family == AF_INET6 && route->priority == 0)
2529 route->priority = IP6_RT_PRIO_USER;
2530
2531 if (ordered_hashmap_isempty(network->addresses_by_section) &&
2532 in_addr_is_null(route->gw_family, &route->gw) == 0 &&
2533 route->gateway_onlink < 0) {
2534 log_warning("%s: Gateway= without static address configured. "
2535 "Enabling GatewayOnLink= option.",
2536 network->filename);
2537 route->gateway_onlink = true;
2538 }
2539
2540 return 0;
2541 }
2542
2543 void network_drop_invalid_routes(Network *network) {
2544 Route *route;
2545
2546 assert(network);
2547
2548 HASHMAP_FOREACH(route, network->routes_by_section)
2549 if (route_section_verify(route, network) < 0)
2550 route_free(route);
2551 }