2 This file is part of systemd.
4 Copyright 2013 Tom Gundersen <teg@jklm.no>
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
23 #include "conf-parser.h"
24 #include "firewall-util.h"
25 #include "netlink-util.h"
26 #include "networkd-address.h"
27 #include "networkd-manager.h"
28 #include "parse-util.h"
30 #include "socket-util.h"
31 #include "string-util.h"
35 #define ADDRESSES_PER_LINK_MAX 2048U
36 #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
38 int address_new(Address
**ret
) {
39 _cleanup_address_free_ Address
*address
= NULL
;
41 address
= new0(Address
, 1);
45 address
->family
= AF_UNSPEC
;
46 address
->scope
= RT_SCOPE_UNIVERSE
;
47 address
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
48 address
->cinfo
.ifa_valid
= CACHE_INFO_INFINITY_LIFE_TIME
;
56 int address_new_static(Network
*network
, const char *filename
, unsigned section_line
, Address
**ret
) {
57 _cleanup_network_config_section_free_ NetworkConfigSection
*n
= NULL
;
58 _cleanup_address_free_ Address
*address
= NULL
;
63 assert(!!filename
== (section_line
> 0));
66 r
= network_config_section_new(filename
, section_line
, &n
);
70 address
= hashmap_get(network
->addresses_by_section
, n
);
79 if (network
->n_static_addresses
>= STATIC_ADDRESSES_PER_NETWORK_MAX
)
82 r
= address_new(&address
);
90 r
= hashmap_put(network
->addresses_by_section
, address
->section
, address
);
95 address
->network
= network
;
96 LIST_APPEND(addresses
, network
->static_addresses
, address
);
97 network
->n_static_addresses
++;
105 void address_free(Address
*address
) {
109 if (address
->network
) {
110 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
111 assert(address
->network
->n_static_addresses
> 0);
112 address
->network
->n_static_addresses
--;
114 if (address
->section
) {
115 hashmap_remove(address
->network
->addresses_by_section
, address
->section
);
116 network_config_section_free(address
->section
);
121 set_remove(address
->link
->addresses
, address
);
122 set_remove(address
->link
->addresses_foreign
, address
);
124 if (in_addr_equal(AF_INET6
, &address
->in_addr
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
))
125 memzero(&address
->link
->ipv6ll_address
, sizeof(struct in6_addr
));
131 static void address_hash_func(const void *b
, struct siphash
*state
) {
132 const Address
*a
= b
;
136 siphash24_compress(&a
->family
, sizeof(a
->family
), state
);
140 siphash24_compress(&a
->prefixlen
, sizeof(a
->prefixlen
), state
);
143 if (a
->prefixlen
!= 0) {
146 if (a
->in_addr_peer
.in
.s_addr
!= 0)
147 prefix
= be32toh(a
->in_addr_peer
.in
.s_addr
) >> (32 - a
->prefixlen
);
149 prefix
= be32toh(a
->in_addr
.in
.s_addr
) >> (32 - a
->prefixlen
);
151 siphash24_compress(&prefix
, sizeof(prefix
), state
);
157 siphash24_compress(&a
->in_addr
, FAMILY_ADDRESS_SIZE(a
->family
), state
);
161 /* treat any other address family as AF_UNSPEC */
166 static int address_compare_func(const void *c1
, const void *c2
) {
167 const Address
*a1
= c1
, *a2
= c2
;
169 if (a1
->family
< a2
->family
)
171 if (a1
->family
> a2
->family
)
174 switch (a1
->family
) {
175 /* use the same notion of equality as the kernel does */
177 if (a1
->prefixlen
< a2
->prefixlen
)
179 if (a1
->prefixlen
> a2
->prefixlen
)
182 /* compare the peer prefixes */
183 if (a1
->prefixlen
!= 0) {
184 /* make sure we don't try to shift by 32.
185 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
188 if (a1
->in_addr_peer
.in
.s_addr
!= 0)
189 b1
= be32toh(a1
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
191 b1
= be32toh(a1
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
193 if (a2
->in_addr_peer
.in
.s_addr
!= 0)
194 b2
= be32toh(a2
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
196 b2
= be32toh(a2
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
206 return memcmp(&a1
->in_addr
, &a2
->in_addr
, FAMILY_ADDRESS_SIZE(a1
->family
));
208 /* treat any other address family as AF_UNSPEC */
213 static const struct hash_ops address_hash_ops
= {
214 .hash
= address_hash_func
,
215 .compare
= address_compare_func
218 bool address_equal(Address
*a1
, Address
*a2
) {
225 return address_compare_func(a1
, a2
) == 0;
228 static int address_establish(Address
*address
, Link
*link
) {
235 masq
= link
->network
&&
236 link
->network
->ip_masquerade
&&
237 address
->family
== AF_INET
&&
238 address
->scope
< RT_SCOPE_LINK
;
240 /* Add firewall entry if this is requested */
241 if (address
->ip_masquerade_done
!= masq
) {
242 union in_addr_union masked
= address
->in_addr
;
243 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
245 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
247 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
249 address
->ip_masquerade_done
= masq
;
255 static int address_add_internal(Link
*link
, Set
**addresses
,
257 const union in_addr_union
*in_addr
,
258 unsigned char prefixlen
,
260 _cleanup_address_free_ Address
*address
= NULL
;
267 r
= address_new(&address
);
271 address
->family
= family
;
272 address
->in_addr
= *in_addr
;
273 address
->prefixlen
= prefixlen
;
274 /* Consider address tentative until we get the real flags from the kernel */
275 address
->flags
= IFA_F_TENTATIVE
;
277 r
= set_ensure_allocated(addresses
, &address_hash_ops
);
281 r
= set_put(*addresses
, address
);
285 address
->link
= link
;
295 int address_add_foreign(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
296 return address_add_internal(link
, &link
->addresses_foreign
, family
, in_addr
, prefixlen
, ret
);
299 int address_add(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
303 r
= address_get(link
, family
, in_addr
, prefixlen
, &address
);
305 /* Address does not exist, create a new one */
306 r
= address_add_internal(link
, &link
->addresses
, family
, in_addr
, prefixlen
, &address
);
310 /* Take over a foreign address */
311 r
= set_ensure_allocated(&link
->addresses
, &address_hash_ops
);
315 r
= set_put(link
->addresses
, address
);
319 set_remove(link
->addresses_foreign
, address
);
321 /* Already exists, do nothing */
332 static int address_release(Address
*address
) {
336 assert(address
->link
);
338 /* Remove masquerading firewall entry if it was added */
339 if (address
->ip_masquerade_done
) {
340 union in_addr_union masked
= address
->in_addr
;
341 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
343 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
345 log_link_warning_errno(address
->link
, r
, "Failed to disable IP masquerading: %m");
347 address
->ip_masquerade_done
= false;
357 const struct ifa_cacheinfo
*cinfo
) {
364 assert_return(address
->link
, 1);
366 if (IN_SET(address
->link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
369 ready
= address_is_ready(address
);
371 address
->flags
= flags
;
372 address
->scope
= scope
;
373 address
->cinfo
= *cinfo
;
375 link_update_operstate(address
->link
);
377 if (!ready
&& address_is_ready(address
)) {
378 link_check_ready(address
->link
);
380 if (address
->family
== AF_INET6
&&
381 in_addr_is_link_local(AF_INET6
, &address
->in_addr
) > 0 &&
382 in_addr_is_null(AF_INET6
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
) > 0) {
384 r
= link_ipv6ll_gained(address
->link
, &address
->in_addr
.in6
);
393 int address_drop(Address
*address
) {
399 ready
= address_is_ready(address
);
400 link
= address
->link
;
402 address_release(address
);
403 address_free(address
);
405 link_update_operstate(link
);
408 link_check_ready(link
);
413 int address_get(Link
*link
,
415 const union in_addr_union
*in_addr
,
416 unsigned char prefixlen
,
419 Address address
, *existing
;
424 address
= (Address
) {
427 .prefixlen
= prefixlen
,
430 existing
= set_get(link
->addresses
, &address
);
437 existing
= set_get(link
->addresses_foreign
, &address
);
450 sd_netlink_message_handler_t callback
) {
452 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
456 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
458 assert(link
->ifindex
> 0);
459 assert(link
->manager
);
460 assert(link
->manager
->rtnl
);
462 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
463 link
->ifindex
, address
->family
);
465 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
467 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
469 return log_error_errno(r
, "Could not set prefixlen: %m");
471 if (address
->family
== AF_INET
)
472 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
473 else if (address
->family
== AF_INET6
)
474 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
476 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
478 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
480 return log_error_errno(r
, "Could not send rtnetlink message: %m");
487 static int address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
488 union in_addr_union in_addr
= {};
489 struct in_addr broadcast
= {};
490 _cleanup_address_free_ Address
*na
= NULL
;
497 /* Something useful was configured? just use it */
498 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
501 /* The address is configured to be 0.0.0.0 or [::] by the user?
502 * Then let's acquire something more useful from the pool. */
503 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
505 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
507 log_link_error(link
, "Couldn't find free address for interface, all taken.");
511 if (original
->family
== AF_INET
) {
512 /* Pick first address in range for ourselves ... */
513 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
515 /* .. and use last as broadcast address */
516 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
517 } else if (original
->family
== AF_INET6
)
518 in_addr
.in6
.s6_addr
[15] |= 1;
520 r
= address_new(&na
);
524 na
->family
= original
->family
;
525 na
->prefixlen
= original
->prefixlen
;
526 na
->scope
= original
->scope
;
527 na
->cinfo
= original
->cinfo
;
529 if (original
->label
) {
530 na
->label
= strdup(original
->label
);
535 na
->broadcast
= broadcast
;
536 na
->in_addr
= in_addr
;
538 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
546 int address_configure(
549 sd_netlink_message_handler_t callback
,
552 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
556 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
558 assert(link
->ifindex
> 0);
559 assert(link
->manager
);
560 assert(link
->manager
->rtnl
);
562 /* If this is a new address, then refuse adding more than the limit */
563 if (address_get(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
) <= 0 &&
564 set_size(link
->addresses
) >= ADDRESSES_PER_LINK_MAX
)
567 r
= address_acquire(link
, address
, &address
);
572 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
573 link
->ifindex
, address
->family
);
575 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
576 link
->ifindex
, address
->family
);
578 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
580 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
582 return log_error_errno(r
, "Could not set prefixlen: %m");
584 address
->flags
|= IFA_F_PERMANENT
;
586 if (address
->home_address
)
587 address
->flags
|= IFA_F_HOMEADDRESS
;
589 if (address
->duplicate_address_detection
)
590 address
->flags
|= IFA_F_NODAD
;
592 if (address
->manage_temporary_address
)
593 address
->flags
|= IFA_F_MANAGETEMPADDR
;
595 if (address
->prefix_route
)
596 address
->flags
|= IFA_F_NOPREFIXROUTE
;
598 if (address
->autojoin
)
599 address
->flags
|= IFA_F_MCAUTOJOIN
;
601 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
603 return log_error_errno(r
, "Could not set flags: %m");
605 if (address
->flags
& ~0xff) {
606 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
608 return log_error_errno(r
, "Could not set extended flags: %m");
611 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
613 return log_error_errno(r
, "Could not set scope: %m");
615 if (address
->family
== AF_INET
)
616 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
617 else if (address
->family
== AF_INET6
)
618 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
620 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
622 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
623 if (address
->family
== AF_INET
)
624 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
625 else if (address
->family
== AF_INET6
)
626 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
628 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
630 if (address
->family
== AF_INET
) {
631 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
633 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
637 if (address
->label
) {
638 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
640 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
643 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
646 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
648 r
= address_establish(address
, link
);
652 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
654 address_release(address
);
655 return log_error_errno(r
, "Could not send rtnetlink message: %m");
660 r
= address_add(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
);
662 address_release(address
);
663 return log_error_errno(r
, "Could not add address: %m");
669 int config_parse_broadcast(
671 const char *filename
,
674 unsigned section_line
,
681 Network
*network
= userdata
;
682 _cleanup_address_free_ Address
*n
= NULL
;
691 r
= address_new_static(network
, filename
, section_line
, &n
);
695 if (n
->family
== AF_INET6
) {
696 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
700 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
702 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Broadcast is invalid, ignoring assignment: %s", rvalue
);
712 int config_parse_address(const char *unit
,
713 const char *filename
,
716 unsigned section_line
,
723 Network
*network
= userdata
;
724 _cleanup_address_free_ Address
*n
= NULL
;
725 const char *address
, *e
;
726 union in_addr_union buffer
;
735 if (streq(section
, "Network")) {
736 /* we are not in an Address section, so treat
737 * this as the special '0' section */
738 r
= address_new_static(network
, NULL
, 0, &n
);
740 r
= address_new_static(network
, filename
, section_line
, &n
);
745 /* Address=address/prefixlen */
748 e
= strchr(rvalue
, '/');
752 r
= safe_atou(e
+ 1, &i
);
754 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
758 n
->prefixlen
= (unsigned char) i
;
760 address
= strndupa(rvalue
, e
- rvalue
);
764 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
766 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address is invalid, ignoring assignment: %s", address
);
770 if (!e
&& f
== AF_INET
) {
771 r
= in4_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
773 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address
);
778 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
779 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Address is incompatible, ignoring assignment: %s", address
);
785 if (streq(lvalue
, "Address"))
788 n
->in_addr_peer
= buffer
;
790 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
791 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
798 int config_parse_label(
800 const char *filename
,
803 unsigned section_line
,
810 _cleanup_address_free_ Address
*n
= NULL
;
811 Network
*network
= userdata
;
820 r
= address_new_static(network
, filename
, section_line
, &n
);
824 if (!address_label_valid(rvalue
)) {
825 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface label is too long or invalid, ignoring assignment: %s", rvalue
);
829 r
= free_and_strdup(&n
->label
, rvalue
);
838 int config_parse_lifetime(const char *unit
,
839 const char *filename
,
842 unsigned section_line
,
848 Network
*network
= userdata
;
849 _cleanup_address_free_ Address
*n
= NULL
;
859 r
= address_new_static(network
, filename
, section_line
, &n
);
863 if (STR_IN_SET(rvalue
, "forever", "infinity")) {
864 n
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
870 r
= safe_atou(rvalue
, &k
);
872 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse PreferredLifetime, ignoring: %s", rvalue
);
877 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid PreferredLifetime value, ignoring: %d", k
);
879 n
->cinfo
.ifa_prefered
= k
;
886 int config_parse_address_flags(const char *unit
,
887 const char *filename
,
890 unsigned section_line
,
896 Network
*network
= userdata
;
897 _cleanup_address_free_ Address
*n
= NULL
;
906 r
= address_new_static(network
, filename
, section_line
, &n
);
910 r
= parse_boolean(rvalue
);
912 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address flag, ignoring: %s", rvalue
);
916 if (streq(lvalue
, "HomeAddress"))
918 else if (streq(lvalue
, "DuplicateAddressDetection"))
919 n
->duplicate_address_detection
= r
;
920 else if (streq(lvalue
, "ManageTemporaryAddress"))
921 n
->manage_temporary_address
= r
;
922 else if (streq(lvalue
, "PrefixRoute"))
924 else if (streq(lvalue
, "AutoJoin"))
930 int config_parse_address_scope(const char *unit
,
931 const char *filename
,
934 unsigned section_line
,
940 Network
*network
= userdata
;
941 _cleanup_address_free_ Address
*n
= NULL
;
950 r
= address_new_static(network
, filename
, section_line
, &n
);
954 if (streq(rvalue
, "host"))
955 n
->scope
= RT_SCOPE_HOST
;
956 else if (streq(rvalue
, "link"))
957 n
->scope
= RT_SCOPE_LINK
;
958 else if (streq(rvalue
, "global"))
959 n
->scope
= RT_SCOPE_UNIVERSE
;
961 r
= safe_atou8(rvalue
, &n
->scope
);
963 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue
);
973 bool address_is_ready(const Address
*a
) {
976 return !(a
->flags
& (IFA_F_TENTATIVE
| IFA_F_DEPRECATED
));
979 int config_parse_router_preference(const char *unit
,
980 const char *filename
,
983 unsigned section_line
,
989 Network
*network
= userdata
;
997 if (streq(rvalue
, "high"))
998 network
->router_preference
= SD_NDISC_PREFERENCE_HIGH
;
999 else if (STR_IN_SET(rvalue
, "medium", "normal", "default"))
1000 network
->router_preference
= SD_NDISC_PREFERENCE_MEDIUM
;
1001 else if (streq(rvalue
, "low"))
1002 network
->router_preference
= SD_NDISC_PREFERENCE_LOW
;
1004 log_syntax(unit
, LOG_ERR
, filename
, line
, -EINVAL
, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue
);
1009 void prefix_free(Prefix
*prefix
) {
1013 if (prefix
->network
) {
1014 LIST_REMOVE(prefixes
, prefix
->network
->static_prefixes
, prefix
);
1015 assert(prefix
->network
->n_static_prefixes
> 0);
1016 prefix
->network
->n_static_prefixes
--;
1018 if (prefix
->section
)
1019 hashmap_remove(prefix
->network
->prefixes_by_section
,
1023 prefix
->radv_prefix
= sd_radv_prefix_unref(prefix
->radv_prefix
);
1028 int prefix_new(Prefix
**ret
) {
1029 Prefix
*prefix
= NULL
;
1031 prefix
= new0(Prefix
, 1);
1035 if (sd_radv_prefix_new(&prefix
->radv_prefix
) < 0)
1044 int prefix_new_static(Network
*network
, const char *filename
,
1045 unsigned section_line
, Prefix
**ret
) {
1046 _cleanup_network_config_section_free_ NetworkConfigSection
*n
= NULL
;
1047 _cleanup_prefix_free_ Prefix
*prefix
= NULL
;
1052 assert(!!filename
== (section_line
> 0));
1055 r
= network_config_section_new(filename
, section_line
, &n
);
1060 prefix
= hashmap_get(network
->prefixes_by_section
, n
);
1070 r
= prefix_new(&prefix
);
1075 prefix
->section
= n
;
1078 r
= hashmap_put(network
->prefixes_by_section
, prefix
->section
,
1084 prefix
->network
= network
;
1085 LIST_APPEND(prefixes
, network
->static_prefixes
, prefix
);
1086 network
->n_static_prefixes
++;
1094 int config_parse_prefix(const char *unit
,
1095 const char *filename
,
1097 const char *section
,
1098 unsigned section_line
,
1105 Network
*network
= userdata
;
1106 _cleanup_prefix_free_ Prefix
*p
= NULL
;
1107 uint8_t prefixlen
= 64;
1108 union in_addr_union in6addr
;
1117 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1121 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &in6addr
, &prefixlen
);
1123 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix is invalid, ignoring assignment: %s", rvalue
);
1127 if (sd_radv_prefix_set_prefix(p
->radv_prefix
, &in6addr
.in6
, prefixlen
) < 0)
1128 return -EADDRNOTAVAIL
;
1130 log_syntax(unit
, LOG_INFO
, filename
, line
, r
, "Found prefix %s", rvalue
);
1137 int config_parse_prefix_flags(const char *unit
,
1138 const char *filename
,
1140 const char *section
,
1141 unsigned section_line
,
1147 Network
*network
= userdata
;
1148 _cleanup_prefix_free_ Prefix
*p
= NULL
;
1157 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1161 r
= parse_boolean(rvalue
);
1163 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address flag, ignoring: %s", rvalue
);
1169 if (streq(lvalue
, "OnLink"))
1170 r
= sd_radv_prefix_set_onlink(p
->radv_prefix
, val
);
1171 else if (streq(lvalue
, "AddressAutoconfiguration"))
1172 r
= sd_radv_prefix_set_address_autoconfiguration(p
->radv_prefix
, val
);
1181 int config_parse_prefix_lifetime(const char *unit
,
1182 const char *filename
,
1184 const char *section
,
1185 unsigned section_line
,
1191 Network
*network
= userdata
;
1192 _cleanup_prefix_free_ Prefix
*p
= NULL
;
1202 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1206 r
= parse_sec(rvalue
, &usec
);
1208 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Lifetime is invalid, ignoring assignment: %s", rvalue
);
1212 /* a value of 0xffffffff represents infinity */
1213 if (streq(lvalue
, "PreferredLifetimeSec"))
1214 r
= sd_radv_prefix_set_preferred_lifetime(p
->radv_prefix
,
1215 DIV_ROUND_UP(usec
, USEC_PER_SEC
));
1216 else if (streq(lvalue
, "ValidLifetimeSec"))
1217 r
= sd_radv_prefix_set_valid_lifetime(p
->radv_prefix
,
1218 DIV_ROUND_UP(usec
, USEC_PER_SEC
));