1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/icmpv6.h>
23 #include "alloc-util.h"
24 #include "conf-parser.h"
25 #include "in-addr-util.h"
26 #include "netlink-util.h"
27 #include "networkd-manager.h"
28 #include "networkd-route.h"
29 #include "parse-util.h"
31 #include "string-util.h"
32 #include "sysctl-util.h"
35 #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
37 static unsigned routes_max(void) {
38 static thread_local
unsigned cached
= 0;
40 _cleanup_free_
char *s4
= NULL
, *s6
= NULL
;
41 unsigned val4
= ROUTES_DEFAULT_MAX_PER_FAMILY
, val6
= ROUTES_DEFAULT_MAX_PER_FAMILY
;
46 if (sysctl_read("net/ipv4/route/max_size", &s4
) >= 0) {
48 if (safe_atou(s4
, &val4
) >= 0 &&
50 /* This is the default "no limit" value in the kernel */
51 val4
= ROUTES_DEFAULT_MAX_PER_FAMILY
;
54 if (sysctl_read("net/ipv6/route/max_size", &s6
) >= 0) {
56 (void) safe_atou(s6
, &val6
);
59 cached
= MAX(ROUTES_DEFAULT_MAX_PER_FAMILY
, val4
) +
60 MAX(ROUTES_DEFAULT_MAX_PER_FAMILY
, val6
);
64 int route_new(Route
**ret
) {
65 _cleanup_route_free_ Route
*route
= NULL
;
67 route
= new0(Route
, 1);
71 route
->family
= AF_UNSPEC
;
72 route
->scope
= RT_SCOPE_UNIVERSE
;
73 route
->protocol
= RTPROT_UNSPEC
;
74 route
->type
= RTN_UNICAST
;
75 route
->table
= RT_TABLE_MAIN
;
76 route
->lifetime
= USEC_INFINITY
;
79 *ret
= TAKE_PTR(route
);
84 int route_new_static(Network
*network
, const char *filename
, unsigned section_line
, Route
**ret
) {
85 _cleanup_network_config_section_free_ NetworkConfigSection
*n
= NULL
;
86 _cleanup_route_free_ Route
*route
= NULL
;
91 assert(!!filename
== (section_line
> 0));
94 r
= network_config_section_new(filename
, section_line
, &n
);
98 route
= hashmap_get(network
->routes_by_section
, n
);
100 *ret
= TAKE_PTR(route
);
106 if (network
->n_static_routes
>= routes_max())
109 r
= route_new(&route
);
113 route
->protocol
= RTPROT_STATIC
;
116 route
->section
= TAKE_PTR(n
);
118 r
= hashmap_put(network
->routes_by_section
, route
->section
, route
);
123 route
->network
= network
;
124 LIST_PREPEND(routes
, network
->static_routes
, route
);
125 network
->n_static_routes
++;
127 *ret
= TAKE_PTR(route
);
132 void route_free(Route
*route
) {
136 if (route
->network
) {
137 LIST_REMOVE(routes
, route
->network
->static_routes
, route
);
139 assert(route
->network
->n_static_routes
> 0);
140 route
->network
->n_static_routes
--;
143 hashmap_remove(route
->network
->routes_by_section
, route
->section
);
146 network_config_section_free(route
->section
);
149 set_remove(route
->link
->routes
, route
);
150 set_remove(route
->link
->routes_foreign
, route
);
153 sd_event_source_unref(route
->expire
);
158 static void route_hash_func(const void *b
, struct siphash
*state
) {
159 const Route
*route
= b
;
163 siphash24_compress(&route
->family
, sizeof(route
->family
), state
);
165 switch (route
->family
) {
168 /* Equality of routes are given by the 4-touple
169 (dst_prefix,dst_prefixlen,tos,priority,table) */
170 siphash24_compress(&route
->dst
, FAMILY_ADDRESS_SIZE(route
->family
), state
);
171 siphash24_compress(&route
->dst_prefixlen
, sizeof(route
->dst_prefixlen
), state
);
172 siphash24_compress(&route
->tos
, sizeof(route
->tos
), state
);
173 siphash24_compress(&route
->priority
, sizeof(route
->priority
), state
);
174 siphash24_compress(&route
->table
, sizeof(route
->table
), state
);
178 /* treat any other address family as AF_UNSPEC */
183 static int route_compare_func(const void *_a
, const void *_b
) {
184 const Route
*a
= _a
, *b
= _b
;
186 if (a
->family
< b
->family
)
188 if (a
->family
> b
->family
)
194 if (a
->dst_prefixlen
< b
->dst_prefixlen
)
196 if (a
->dst_prefixlen
> b
->dst_prefixlen
)
204 if (a
->priority
< b
->priority
)
206 if (a
->priority
> b
->priority
)
209 if (a
->table
< b
->table
)
211 if (a
->table
> b
->table
)
214 return memcmp(&a
->dst
, &b
->dst
, FAMILY_ADDRESS_SIZE(a
->family
));
216 /* treat any other address family as AF_UNSPEC */
221 static const struct hash_ops route_hash_ops
= {
222 .hash
= route_hash_func
,
223 .compare
= route_compare_func
226 int route_get(Link
*link
,
228 const union in_addr_union
*dst
,
229 unsigned char dst_prefixlen
,
235 Route route
, *existing
;
243 .dst_prefixlen
= dst_prefixlen
,
245 .priority
= priority
,
249 existing
= set_get(link
->routes
, &route
);
256 existing
= set_get(link
->routes_foreign
, &route
);
266 static int route_add_internal(
270 const union in_addr_union
*dst
,
271 unsigned char dst_prefixlen
,
277 _cleanup_route_free_ Route
*route
= NULL
;
284 r
= route_new(&route
);
288 route
->family
= family
;
290 route
->dst_prefixlen
= dst_prefixlen
;
292 route
->priority
= priority
;
293 route
->table
= table
;
295 r
= set_ensure_allocated(routes
, &route_hash_ops
);
299 r
= set_put(*routes
, route
);
313 int route_add_foreign(
316 const union in_addr_union
*dst
,
317 unsigned char dst_prefixlen
,
323 return route_add_internal(link
, &link
->routes_foreign
, family
, dst
, dst_prefixlen
, tos
, priority
, table
, ret
);
329 const union in_addr_union
*dst
,
330 unsigned char dst_prefixlen
,
339 r
= route_get(link
, family
, dst
, dst_prefixlen
, tos
, priority
, table
, &route
);
341 /* Route does not exist, create a new one */
342 r
= route_add_internal(link
, &link
->routes
, family
, dst
, dst_prefixlen
, tos
, priority
, table
, &route
);
346 /* Take over a foreign route */
347 r
= set_ensure_allocated(&link
->routes
, &route_hash_ops
);
351 r
= set_put(link
->routes
, route
);
355 set_remove(link
->routes_foreign
, route
);
357 /* Route exists, do nothing */
368 void route_update(Route
*route
,
369 const union in_addr_union
*src
,
370 unsigned char src_prefixlen
,
371 const union in_addr_union
*gw
,
372 const union in_addr_union
*prefsrc
,
374 unsigned char protocol
,
375 unsigned char type
) {
383 route
->src_prefixlen
= src_prefixlen
;
385 route
->prefsrc
= *prefsrc
;
386 route
->scope
= scope
;
387 route
->protocol
= protocol
;
391 int route_remove(Route
*route
, Link
*link
,
392 sd_netlink_message_handler_t callback
) {
393 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
397 assert(link
->manager
);
398 assert(link
->manager
->rtnl
);
399 assert(link
->ifindex
> 0);
400 assert(IN_SET(route
->family
, AF_INET
, AF_INET6
));
402 r
= sd_rtnl_message_new_route(link
->manager
->rtnl
, &req
,
403 RTM_DELROUTE
, route
->family
,
406 return log_error_errno(r
, "Could not create RTM_DELROUTE message: %m");
408 if (!in_addr_is_null(route
->family
, &route
->gw
)) {
409 if (route
->family
== AF_INET
)
410 r
= sd_netlink_message_append_in_addr(req
, RTA_GATEWAY
, &route
->gw
.in
);
411 else if (route
->family
== AF_INET6
)
412 r
= sd_netlink_message_append_in6_addr(req
, RTA_GATEWAY
, &route
->gw
.in6
);
414 return log_error_errno(r
, "Could not append RTA_GATEWAY attribute: %m");
417 if (route
->dst_prefixlen
) {
418 if (route
->family
== AF_INET
)
419 r
= sd_netlink_message_append_in_addr(req
, RTA_DST
, &route
->dst
.in
);
420 else if (route
->family
== AF_INET6
)
421 r
= sd_netlink_message_append_in6_addr(req
, RTA_DST
, &route
->dst
.in6
);
423 return log_error_errno(r
, "Could not append RTA_DST attribute: %m");
425 r
= sd_rtnl_message_route_set_dst_prefixlen(req
, route
->dst_prefixlen
);
427 return log_error_errno(r
, "Could not set destination prefix length: %m");
430 if (route
->src_prefixlen
) {
431 if (route
->family
== AF_INET
)
432 r
= sd_netlink_message_append_in_addr(req
, RTA_SRC
, &route
->src
.in
);
433 else if (route
->family
== AF_INET6
)
434 r
= sd_netlink_message_append_in6_addr(req
, RTA_SRC
, &route
->src
.in6
);
436 return log_error_errno(r
, "Could not append RTA_SRC attribute: %m");
438 r
= sd_rtnl_message_route_set_src_prefixlen(req
, route
->src_prefixlen
);
440 return log_error_errno(r
, "Could not set source prefix length: %m");
443 if (!in_addr_is_null(route
->family
, &route
->prefsrc
)) {
444 if (route
->family
== AF_INET
)
445 r
= sd_netlink_message_append_in_addr(req
, RTA_PREFSRC
, &route
->prefsrc
.in
);
446 else if (route
->family
== AF_INET6
)
447 r
= sd_netlink_message_append_in6_addr(req
, RTA_PREFSRC
, &route
->prefsrc
.in6
);
449 return log_error_errno(r
, "Could not append RTA_PREFSRC attribute: %m");
452 r
= sd_rtnl_message_route_set_scope(req
, route
->scope
);
454 return log_error_errno(r
, "Could not set scope: %m");
456 r
= sd_netlink_message_append_u32(req
, RTA_PRIORITY
, route
->priority
);
458 return log_error_errno(r
, "Could not append RTA_PRIORITY attribute: %m");
460 if (!IN_SET(route
->type
, RTN_UNREACHABLE
, RTN_PROHIBIT
, RTN_BLACKHOLE
)) {
461 r
= sd_netlink_message_append_u32(req
, RTA_OIF
, link
->ifindex
);
463 return log_error_errno(r
, "Could not append RTA_OIF attribute: %m");
466 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
468 return log_error_errno(r
, "Could not send rtnetlink message: %m");
475 static int route_expire_callback(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
476 Link
*link
= userdata
;
482 assert(link
->ifname
);
484 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
487 r
= sd_netlink_message_get_errno(m
);
488 if (r
< 0 && r
!= -EEXIST
)
489 log_link_warning_errno(link
, r
, "could not remove route: %m");
494 int route_expire_handler(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
495 Route
*route
= userdata
;
500 r
= route_remove(route
, route
->link
, route_expire_callback
);
502 log_warning_errno(r
, "Could not remove route: %m");
512 sd_netlink_message_handler_t callback
) {
514 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
515 _cleanup_(sd_event_source_unrefp
) sd_event_source
*expire
= NULL
;
520 assert(link
->manager
);
521 assert(link
->manager
->rtnl
);
522 assert(link
->ifindex
> 0);
523 assert(IN_SET(route
->family
, AF_INET
, AF_INET6
));
525 if (route_get(link
, route
->family
, &route
->dst
, route
->dst_prefixlen
, route
->tos
, route
->priority
, route
->table
, NULL
) <= 0 &&
526 set_size(link
->routes
) >= routes_max())
529 r
= sd_rtnl_message_new_route(link
->manager
->rtnl
, &req
,
530 RTM_NEWROUTE
, route
->family
,
533 return log_error_errno(r
, "Could not create RTM_NEWROUTE message: %m");
535 if (!in_addr_is_null(route
->family
, &route
->gw
)) {
536 if (route
->family
== AF_INET
)
537 r
= sd_netlink_message_append_in_addr(req
, RTA_GATEWAY
, &route
->gw
.in
);
538 else if (route
->family
== AF_INET6
)
539 r
= sd_netlink_message_append_in6_addr(req
, RTA_GATEWAY
, &route
->gw
.in6
);
541 return log_error_errno(r
, "Could not append RTA_GATEWAY attribute: %m");
543 r
= sd_rtnl_message_route_set_family(req
, route
->family
);
545 return log_error_errno(r
, "Could not set route family: %m");
548 if (route
->dst_prefixlen
) {
549 if (route
->family
== AF_INET
)
550 r
= sd_netlink_message_append_in_addr(req
, RTA_DST
, &route
->dst
.in
);
551 else if (route
->family
== AF_INET6
)
552 r
= sd_netlink_message_append_in6_addr(req
, RTA_DST
, &route
->dst
.in6
);
554 return log_error_errno(r
, "Could not append RTA_DST attribute: %m");
556 r
= sd_rtnl_message_route_set_dst_prefixlen(req
, route
->dst_prefixlen
);
558 return log_error_errno(r
, "Could not set destination prefix length: %m");
561 if (route
->src_prefixlen
) {
562 if (route
->family
== AF_INET
)
563 r
= sd_netlink_message_append_in_addr(req
, RTA_SRC
, &route
->src
.in
);
564 else if (route
->family
== AF_INET6
)
565 r
= sd_netlink_message_append_in6_addr(req
, RTA_SRC
, &route
->src
.in6
);
567 return log_error_errno(r
, "Could not append RTA_SRC attribute: %m");
569 r
= sd_rtnl_message_route_set_src_prefixlen(req
, route
->src_prefixlen
);
571 return log_error_errno(r
, "Could not set source prefix length: %m");
574 if (!in_addr_is_null(route
->family
, &route
->prefsrc
)) {
575 if (route
->family
== AF_INET
)
576 r
= sd_netlink_message_append_in_addr(req
, RTA_PREFSRC
, &route
->prefsrc
.in
);
577 else if (route
->family
== AF_INET6
)
578 r
= sd_netlink_message_append_in6_addr(req
, RTA_PREFSRC
, &route
->prefsrc
.in6
);
580 return log_error_errno(r
, "Could not append RTA_PREFSRC attribute: %m");
583 r
= sd_rtnl_message_route_set_scope(req
, route
->scope
);
585 return log_error_errno(r
, "Could not set scope: %m");
587 r
= sd_rtnl_message_route_set_flags(req
, route
->flags
);
589 return log_error_errno(r
, "Could not set flags: %m");
591 if (route
->table
!= RT_TABLE_MAIN
) {
592 if (route
->table
< 256) {
593 r
= sd_rtnl_message_route_set_table(req
, route
->table
);
595 return log_error_errno(r
, "Could not set route table: %m");
597 r
= sd_rtnl_message_route_set_table(req
, RT_TABLE_UNSPEC
);
599 return log_error_errno(r
, "Could not set route table: %m");
601 /* Table attribute to allow more than 256. */
602 r
= sd_netlink_message_append_data(req
, RTA_TABLE
, &route
->table
, sizeof(route
->table
));
604 return log_error_errno(r
, "Could not append RTA_TABLE attribute: %m");
608 r
= sd_netlink_message_append_u32(req
, RTA_PRIORITY
, route
->priority
);
610 return log_error_errno(r
, "Could not append RTA_PRIORITY attribute: %m");
612 r
= sd_netlink_message_append_u8(req
, RTA_PREF
, route
->pref
);
614 return log_error_errno(r
, "Could not append RTA_PREF attribute: %m");
616 if (route
->lifetime
!= USEC_INFINITY
&& kernel_route_expiration_supported()) {
617 r
= sd_netlink_message_append_u32(req
, RTA_EXPIRES
,
618 DIV_ROUND_UP(usec_sub_unsigned(route
->lifetime
, now(clock_boottime_or_monotonic())), USEC_PER_SEC
));
620 return log_error_errno(r
, "Could not append RTA_EXPIRES attribute: %m");
623 r
= sd_rtnl_message_route_set_type(req
, route
->type
);
625 return log_error_errno(r
, "Could not set route type: %m");
627 if (!IN_SET(route
->type
, RTN_UNREACHABLE
, RTN_PROHIBIT
, RTN_BLACKHOLE
)) {
628 r
= sd_netlink_message_append_u32(req
, RTA_OIF
, link
->ifindex
);
630 return log_error_errno(r
, "Could not append RTA_OIF attribute: %m");
633 r
= sd_netlink_message_open_container(req
, RTA_METRICS
);
635 return log_error_errno(r
, "Could not append RTA_METRICS attribute: %m");
637 if (route
->mtu
> 0) {
638 r
= sd_netlink_message_append_u32(req
, RTAX_MTU
, route
->mtu
);
640 return log_error_errno(r
, "Could not append RTAX_MTU attribute: %m");
643 if (route
->initcwnd
> 0) {
644 r
= sd_netlink_message_append_u32(req
, RTAX_INITCWND
, route
->initcwnd
);
646 return log_error_errno(r
, "Could not append RTAX_INITCWND attribute: %m");
649 if (route
->initrwnd
> 0) {
650 r
= sd_netlink_message_append_u32(req
, RTAX_INITRWND
, route
->initrwnd
);
652 return log_error_errno(r
, "Could not append RTAX_INITRWND attribute: %m");
655 if (route
->quickack
!= -1) {
656 r
= sd_netlink_message_append_u32(req
, RTAX_QUICKACK
, route
->quickack
);
658 return log_error_errno(r
, "Could not append RTAX_QUICKACK attribute: %m");
661 r
= sd_netlink_message_close_container(req
);
663 return log_error_errno(r
, "Could not append RTA_METRICS attribute: %m");
665 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
667 return log_error_errno(r
, "Could not send rtnetlink message: %m");
671 lifetime
= route
->lifetime
;
673 r
= route_add(link
, route
->family
, &route
->dst
, route
->dst_prefixlen
, route
->tos
, route
->priority
, route
->table
, &route
);
675 return log_error_errno(r
, "Could not add route: %m");
677 /* TODO: drop expiration handling once it can be pushed into the kernel */
678 route
->lifetime
= lifetime
;
680 if (route
->lifetime
!= USEC_INFINITY
&& !kernel_route_expiration_supported()) {
681 r
= sd_event_add_time(link
->manager
->event
, &expire
, clock_boottime_or_monotonic(),
682 route
->lifetime
, 0, route_expire_handler
, route
);
684 return log_error_errno(r
, "Could not arm expiration timer: %m");
687 sd_event_source_unref(route
->expire
);
688 route
->expire
= TAKE_PTR(expire
);
693 int config_parse_gateway(const char *unit
,
694 const char *filename
,
697 unsigned section_line
,
704 Network
*network
= userdata
;
705 _cleanup_route_free_ Route
*n
= NULL
;
706 union in_addr_union buffer
;
715 if (streq(section
, "Network")) {
716 /* we are not in an Route section, so treat
717 * this as the special '0' section */
718 r
= route_new_static(network
, NULL
, 0, &n
);
720 r
= route_new_static(network
, filename
, section_line
, &n
);
725 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
727 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Route is invalid, ignoring assignment: %s", rvalue
);
738 int config_parse_preferred_src(const char *unit
,
739 const char *filename
,
742 unsigned section_line
,
749 Network
*network
= userdata
;
750 _cleanup_route_free_ Route
*n
= NULL
;
751 union in_addr_union buffer
;
760 r
= route_new_static(network
, filename
, section_line
, &n
);
764 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
766 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
767 "Preferred source is invalid, ignoring assignment: %s", rvalue
);
778 int config_parse_destination(const char *unit
,
779 const char *filename
,
782 unsigned section_line
,
789 Network
*network
= userdata
;
790 _cleanup_route_free_ Route
*n
= NULL
;
791 union in_addr_union buffer
;
792 unsigned char prefixlen
;
801 r
= route_new_static(network
, filename
, section_line
, &n
);
805 r
= in_addr_prefix_from_string(rvalue
, AF_INET
, &buffer
, &prefixlen
);
807 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &buffer
, &prefixlen
);
809 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
810 "Route %s= prefix is invalid, ignoring assignment: %s",
815 n
->family
= AF_INET6
;
819 if (streq(lvalue
, "Destination")) {
821 n
->dst_prefixlen
= prefixlen
;
822 } else if (streq(lvalue
, "Source")) {
824 n
->src_prefixlen
= prefixlen
;
826 assert_not_reached(lvalue
);
833 int config_parse_route_priority(const char *unit
,
834 const char *filename
,
837 unsigned section_line
,
843 Network
*network
= userdata
;
844 _cleanup_route_free_ Route
*n
= NULL
;
854 r
= route_new_static(network
, filename
, section_line
, &n
);
858 r
= safe_atou32(rvalue
, &k
);
860 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
861 "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue
);
871 int config_parse_route_scope(const char *unit
,
872 const char *filename
,
875 unsigned section_line
,
881 Network
*network
= userdata
;
882 _cleanup_route_free_ Route
*n
= NULL
;
891 r
= route_new_static(network
, filename
, section_line
, &n
);
895 if (streq(rvalue
, "host"))
896 n
->scope
= RT_SCOPE_HOST
;
897 else if (streq(rvalue
, "link"))
898 n
->scope
= RT_SCOPE_LINK
;
899 else if (streq(rvalue
, "global"))
900 n
->scope
= RT_SCOPE_UNIVERSE
;
902 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Unknown route scope: %s", rvalue
);
911 int config_parse_route_table(const char *unit
,
912 const char *filename
,
915 unsigned section_line
,
921 _cleanup_route_free_ Route
*n
= NULL
;
922 Network
*network
= userdata
;
932 r
= route_new_static(network
, filename
, section_line
, &n
);
936 r
= safe_atou32(rvalue
, &k
);
938 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
939 "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue
);
950 int config_parse_gateway_onlink(const char *unit
,
951 const char *filename
,
954 unsigned section_line
,
960 Network
*network
= userdata
;
961 _cleanup_route_free_ Route
*n
= NULL
;
970 r
= route_new_static(network
, filename
, section_line
, &n
);
974 r
= parse_boolean(rvalue
);
976 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
977 "Could not parse gateway onlink \"%s\", ignoring assignment: %m", rvalue
);
981 SET_FLAG(n
->flags
, RTNH_F_ONLINK
, r
);
987 int config_parse_ipv6_route_preference(const char *unit
,
988 const char *filename
,
991 unsigned section_line
,
997 Network
*network
= userdata
;
998 _cleanup_route_free_ Route
*n
= NULL
;
1001 r
= route_new_static(network
, filename
, section_line
, &n
);
1005 if (streq(rvalue
, "low"))
1006 n
->pref
= ICMPV6_ROUTER_PREF_LOW
;
1007 else if (streq(rvalue
, "medium"))
1008 n
->pref
= ICMPV6_ROUTER_PREF_MEDIUM
;
1009 else if (streq(rvalue
, "high"))
1010 n
->pref
= ICMPV6_ROUTER_PREF_HIGH
;
1012 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Unknown route preference: %s", rvalue
);
1021 int config_parse_route_protocol(const char *unit
,
1022 const char *filename
,
1024 const char *section
,
1025 unsigned section_line
,
1031 Network
*network
= userdata
;
1032 _cleanup_route_free_ Route
*n
= NULL
;
1035 r
= route_new_static(network
, filename
, section_line
, &n
);
1039 if (streq(rvalue
, "kernel"))
1040 n
->protocol
= RTPROT_KERNEL
;
1041 else if (streq(rvalue
, "boot"))
1042 n
->protocol
= RTPROT_BOOT
;
1043 else if (streq(rvalue
, "static"))
1044 n
->protocol
= RTPROT_STATIC
;
1046 r
= safe_atou8(rvalue
, &n
->protocol
);
1048 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue
);
1058 int config_parse_route_type(const char *unit
,
1059 const char *filename
,
1061 const char *section
,
1062 unsigned section_line
,
1068 Network
*network
= userdata
;
1069 _cleanup_route_free_ Route
*n
= NULL
;
1072 r
= route_new_static(network
, filename
, section_line
, &n
);
1076 if (streq(rvalue
, "unicast"))
1077 n
->type
= RTN_UNICAST
;
1078 else if (streq(rvalue
, "blackhole"))
1079 n
->type
= RTN_BLACKHOLE
;
1080 else if (streq(rvalue
, "unreachable"))
1081 n
->type
= RTN_UNREACHABLE
;
1082 else if (streq(rvalue
, "prohibit"))
1083 n
->type
= RTN_PROHIBIT
;
1085 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Could not parse route type \"%s\", ignoring assignment: %m", rvalue
);
1094 int config_parse_tcp_window(const char *unit
,
1095 const char *filename
,
1097 const char *section
,
1098 unsigned section_line
,
1104 _cleanup_route_free_ Route
*n
= NULL
;
1105 Network
*network
= userdata
;
1115 r
= route_new_static(network
, filename
, section_line
, &n
);
1119 r
= parse_size(rvalue
, 1024, &k
);
1120 if (r
< 0 || k
> UINT32_MAX
) {
1121 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1122 "Could not parse TCP %s \"%s\" bytes, ignoring assignment: %m", rvalue
, lvalue
);
1126 if (streq(lvalue
, "InitialCongestionWindow"))
1128 else if (streq(lvalue
, "InitialAdvertisedReceiveWindow"))
1131 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse TCP %s: %s", lvalue
, rvalue
);
1140 int config_parse_quickack(const char *unit
,
1141 const char *filename
,
1143 const char *section
,
1144 unsigned section_line
,
1150 _cleanup_route_free_ Route
*n
= NULL
;
1151 Network
*network
= userdata
;
1160 r
= route_new_static(network
, filename
, section_line
, &n
);
1164 k
= parse_boolean(rvalue
);
1166 log_syntax(unit
, LOG_ERR
, filename
, line
, k
, "Failed to parse TCP quickack, ignoring: %s", rvalue
);