1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Tom Gundersen <teg@jklm.no>
8 #include "alloc-util.h"
9 #include "conf-parser.h"
10 #include "firewall-util.h"
11 #include "netlink-util.h"
12 #include "networkd-address.h"
13 #include "networkd-manager.h"
14 #include "parse-util.h"
16 #include "socket-util.h"
17 #include "string-util.h"
21 #define ADDRESSES_PER_LINK_MAX 2048U
22 #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
24 int address_new(Address
**ret
) {
25 _cleanup_(address_freep
) Address
*address
= NULL
;
27 address
= new0(Address
, 1);
31 address
->family
= AF_UNSPEC
;
32 address
->scope
= RT_SCOPE_UNIVERSE
;
33 address
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
34 address
->cinfo
.ifa_valid
= CACHE_INFO_INFINITY_LIFE_TIME
;
36 *ret
= TAKE_PTR(address
);
41 int address_new_static(Network
*network
, const char *filename
, unsigned section_line
, Address
**ret
) {
42 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
43 _cleanup_(address_freep
) Address
*address
= NULL
;
48 assert(!!filename
== (section_line
> 0));
51 r
= network_config_section_new(filename
, section_line
, &n
);
55 address
= hashmap_get(network
->addresses_by_section
, n
);
57 *ret
= TAKE_PTR(address
);
63 if (network
->n_static_addresses
>= STATIC_ADDRESSES_PER_NETWORK_MAX
)
66 r
= address_new(&address
);
71 address
->section
= TAKE_PTR(n
);
73 r
= hashmap_put(network
->addresses_by_section
, address
->section
, address
);
78 address
->network
= network
;
79 LIST_APPEND(addresses
, network
->static_addresses
, address
);
80 network
->n_static_addresses
++;
82 *ret
= TAKE_PTR(address
);
87 void address_free(Address
*address
) {
91 if (address
->network
) {
92 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
93 assert(address
->network
->n_static_addresses
> 0);
94 address
->network
->n_static_addresses
--;
96 if (address
->section
) {
97 hashmap_remove(address
->network
->addresses_by_section
, address
->section
);
98 network_config_section_free(address
->section
);
103 set_remove(address
->link
->addresses
, address
);
104 set_remove(address
->link
->addresses_foreign
, address
);
106 if (in_addr_equal(AF_INET6
, &address
->in_addr
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
))
107 memzero(&address
->link
->ipv6ll_address
, sizeof(struct in6_addr
));
113 static void address_hash_func(const void *b
, struct siphash
*state
) {
114 const Address
*a
= b
;
118 siphash24_compress(&a
->family
, sizeof(a
->family
), state
);
122 siphash24_compress(&a
->prefixlen
, sizeof(a
->prefixlen
), state
);
125 if (a
->prefixlen
!= 0) {
128 if (a
->in_addr_peer
.in
.s_addr
!= 0)
129 prefix
= be32toh(a
->in_addr_peer
.in
.s_addr
) >> (32 - a
->prefixlen
);
131 prefix
= be32toh(a
->in_addr
.in
.s_addr
) >> (32 - a
->prefixlen
);
133 siphash24_compress(&prefix
, sizeof(prefix
), state
);
139 siphash24_compress(&a
->in_addr
, FAMILY_ADDRESS_SIZE(a
->family
), state
);
143 /* treat any other address family as AF_UNSPEC */
148 static int address_compare_func(const void *c1
, const void *c2
) {
149 const Address
*a1
= c1
, *a2
= c2
;
151 if (a1
->family
< a2
->family
)
153 if (a1
->family
> a2
->family
)
156 switch (a1
->family
) {
157 /* use the same notion of equality as the kernel does */
159 if (a1
->prefixlen
< a2
->prefixlen
)
161 if (a1
->prefixlen
> a2
->prefixlen
)
164 /* compare the peer prefixes */
165 if (a1
->prefixlen
!= 0) {
166 /* make sure we don't try to shift by 32.
167 * See ISO/IEC 9899:TC3 § 6.5.7.3. */
170 if (a1
->in_addr_peer
.in
.s_addr
!= 0)
171 b1
= be32toh(a1
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
173 b1
= be32toh(a1
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
175 if (a2
->in_addr_peer
.in
.s_addr
!= 0)
176 b2
= be32toh(a2
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
178 b2
= be32toh(a2
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
188 return memcmp(&a1
->in_addr
, &a2
->in_addr
, FAMILY_ADDRESS_SIZE(a1
->family
));
190 /* treat any other address family as AF_UNSPEC */
195 static const struct hash_ops address_hash_ops
= {
196 .hash
= address_hash_func
,
197 .compare
= address_compare_func
200 bool address_equal(Address
*a1
, Address
*a2
) {
207 return address_compare_func(a1
, a2
) == 0;
210 static int address_establish(Address
*address
, Link
*link
) {
217 masq
= link
->network
&&
218 link
->network
->ip_masquerade
&&
219 address
->family
== AF_INET
&&
220 address
->scope
< RT_SCOPE_LINK
;
222 /* Add firewall entry if this is requested */
223 if (address
->ip_masquerade_done
!= masq
) {
224 union in_addr_union masked
= address
->in_addr
;
225 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
227 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
229 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
231 address
->ip_masquerade_done
= masq
;
237 static int address_add_internal(Link
*link
, Set
**addresses
,
239 const union in_addr_union
*in_addr
,
240 unsigned char prefixlen
,
242 _cleanup_(address_freep
) Address
*address
= NULL
;
249 r
= address_new(&address
);
253 address
->family
= family
;
254 address
->in_addr
= *in_addr
;
255 address
->prefixlen
= prefixlen
;
256 /* Consider address tentative until we get the real flags from the kernel */
257 address
->flags
= IFA_F_TENTATIVE
;
259 r
= set_ensure_allocated(addresses
, &address_hash_ops
);
263 r
= set_put(*addresses
, address
);
267 address
->link
= link
;
277 int address_add_foreign(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
278 return address_add_internal(link
, &link
->addresses_foreign
, family
, in_addr
, prefixlen
, ret
);
281 int address_add(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
285 r
= address_get(link
, family
, in_addr
, prefixlen
, &address
);
287 /* Address does not exist, create a new one */
288 r
= address_add_internal(link
, &link
->addresses
, family
, in_addr
, prefixlen
, &address
);
292 /* Take over a foreign address */
293 r
= set_ensure_allocated(&link
->addresses
, &address_hash_ops
);
297 r
= set_put(link
->addresses
, address
);
301 set_remove(link
->addresses_foreign
, address
);
303 /* Already exists, do nothing */
314 static int address_release(Address
*address
) {
318 assert(address
->link
);
320 /* Remove masquerading firewall entry if it was added */
321 if (address
->ip_masquerade_done
) {
322 union in_addr_union masked
= address
->in_addr
;
323 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
325 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
327 log_link_warning_errno(address
->link
, r
, "Failed to disable IP masquerading: %m");
329 address
->ip_masquerade_done
= false;
339 const struct ifa_cacheinfo
*cinfo
) {
346 assert_return(address
->link
, 1);
348 if (IN_SET(address
->link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
351 ready
= address_is_ready(address
);
353 address
->flags
= flags
;
354 address
->scope
= scope
;
355 address
->cinfo
= *cinfo
;
357 link_update_operstate(address
->link
);
359 if (!ready
&& address_is_ready(address
)) {
360 link_check_ready(address
->link
);
362 if (address
->family
== AF_INET6
&&
363 in_addr_is_link_local(AF_INET6
, &address
->in_addr
) > 0 &&
364 in_addr_is_null(AF_INET6
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
) > 0) {
366 r
= link_ipv6ll_gained(address
->link
, &address
->in_addr
.in6
);
375 int address_drop(Address
*address
) {
381 ready
= address_is_ready(address
);
382 link
= address
->link
;
384 address_release(address
);
385 address_free(address
);
387 link_update_operstate(link
);
390 link_check_ready(link
);
395 int address_get(Link
*link
,
397 const union in_addr_union
*in_addr
,
398 unsigned char prefixlen
,
401 Address address
, *existing
;
406 address
= (Address
) {
409 .prefixlen
= prefixlen
,
412 existing
= set_get(link
->addresses
, &address
);
419 existing
= set_get(link
->addresses_foreign
, &address
);
432 sd_netlink_message_handler_t callback
) {
434 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
438 assert(IN_SET(address
->family
, AF_INET
, AF_INET6
));
440 assert(link
->ifindex
> 0);
441 assert(link
->manager
);
442 assert(link
->manager
->rtnl
);
444 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
445 link
->ifindex
, address
->family
);
447 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
449 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
451 return log_error_errno(r
, "Could not set prefixlen: %m");
453 if (address
->family
== AF_INET
)
454 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
455 else if (address
->family
== AF_INET6
)
456 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
458 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
460 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
462 return log_error_errno(r
, "Could not send rtnetlink message: %m");
469 static int address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
470 union in_addr_union in_addr
= {};
471 struct in_addr broadcast
= {};
472 _cleanup_(address_freep
) Address
*na
= NULL
;
479 /* Something useful was configured? just use it */
480 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
483 /* The address is configured to be 0.0.0.0 or [::] by the user?
484 * Then let's acquire something more useful from the pool. */
485 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
487 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
489 log_link_error(link
, "Couldn't find free address for interface, all taken.");
493 if (original
->family
== AF_INET
) {
494 /* Pick first address in range for ourselves ... */
495 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
497 /* .. and use last as broadcast address */
498 if (original
->prefixlen
> 30)
499 broadcast
.s_addr
= 0;
501 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
502 } else if (original
->family
== AF_INET6
)
503 in_addr
.in6
.s6_addr
[15] |= 1;
505 r
= address_new(&na
);
509 na
->family
= original
->family
;
510 na
->prefixlen
= original
->prefixlen
;
511 na
->scope
= original
->scope
;
512 na
->cinfo
= original
->cinfo
;
514 if (original
->label
) {
515 na
->label
= strdup(original
->label
);
520 na
->broadcast
= broadcast
;
521 na
->in_addr
= in_addr
;
523 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
530 int address_configure(
533 sd_netlink_message_handler_t callback
,
536 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
540 assert(IN_SET(address
->family
, AF_INET
, AF_INET6
));
542 assert(link
->ifindex
> 0);
543 assert(link
->manager
);
544 assert(link
->manager
->rtnl
);
546 /* If this is a new address, then refuse adding more than the limit */
547 if (address_get(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
) <= 0 &&
548 set_size(link
->addresses
) >= ADDRESSES_PER_LINK_MAX
)
551 r
= address_acquire(link
, address
, &address
);
556 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
557 link
->ifindex
, address
->family
);
559 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
560 link
->ifindex
, address
->family
);
562 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
564 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
566 return log_error_errno(r
, "Could not set prefixlen: %m");
568 address
->flags
|= IFA_F_PERMANENT
;
570 if (address
->home_address
)
571 address
->flags
|= IFA_F_HOMEADDRESS
;
573 if (address
->duplicate_address_detection
)
574 address
->flags
|= IFA_F_NODAD
;
576 if (address
->manage_temporary_address
)
577 address
->flags
|= IFA_F_MANAGETEMPADDR
;
579 if (address
->prefix_route
)
580 address
->flags
|= IFA_F_NOPREFIXROUTE
;
582 if (address
->autojoin
)
583 address
->flags
|= IFA_F_MCAUTOJOIN
;
585 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
587 return log_error_errno(r
, "Could not set flags: %m");
589 if (address
->flags
& ~0xff) {
590 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
592 return log_error_errno(r
, "Could not set extended flags: %m");
595 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
597 return log_error_errno(r
, "Could not set scope: %m");
599 if (address
->family
== AF_INET
)
600 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
601 else if (address
->family
== AF_INET6
)
602 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
604 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
606 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
607 if (address
->family
== AF_INET
)
608 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
609 else if (address
->family
== AF_INET6
)
610 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
612 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
614 if (address
->family
== AF_INET
) {
615 if (address
->prefixlen
<= 30) {
616 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
618 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
623 if (address
->label
) {
624 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
626 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
629 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
632 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
634 r
= address_establish(address
, link
);
638 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
640 address_release(address
);
641 return log_error_errno(r
, "Could not send rtnetlink message: %m");
646 r
= address_add(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
);
648 address_release(address
);
649 return log_error_errno(r
, "Could not add address: %m");
655 int config_parse_broadcast(
657 const char *filename
,
660 unsigned section_line
,
667 Network
*network
= userdata
;
668 _cleanup_(address_freep
) Address
*n
= NULL
;
677 r
= address_new_static(network
, filename
, section_line
, &n
);
681 if (n
->family
== AF_INET6
) {
682 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
686 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
688 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Broadcast is invalid, ignoring assignment: %s", rvalue
);
698 int config_parse_address(const char *unit
,
699 const char *filename
,
702 unsigned section_line
,
709 Network
*network
= userdata
;
710 _cleanup_(address_freep
) Address
*n
= NULL
;
711 const char *address
, *e
;
712 union in_addr_union buffer
;
721 if (streq(section
, "Network")) {
722 /* we are not in an Address section, so treat
723 * this as the special '0' section */
724 r
= address_new_static(network
, NULL
, 0, &n
);
726 r
= address_new_static(network
, filename
, section_line
, &n
);
731 /* Address=address/prefixlen */
734 e
= strchr(rvalue
, '/');
738 r
= safe_atou(e
+ 1, &i
);
740 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
744 n
->prefixlen
= (unsigned char) i
;
746 address
= strndupa(rvalue
, e
- rvalue
);
750 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
752 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address is invalid, ignoring assignment: %s", address
);
756 if (!e
&& f
== AF_INET
) {
757 r
= in4_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
759 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length not specified, and a default one cannot be deduced for '%s', ignoring assignment", address
);
764 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
765 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Address is incompatible, ignoring assignment: %s", address
);
771 if (streq(lvalue
, "Address"))
774 n
->in_addr_peer
= buffer
;
776 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
777 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
784 int config_parse_label(
786 const char *filename
,
789 unsigned section_line
,
796 _cleanup_(address_freep
) Address
*n
= NULL
;
797 Network
*network
= userdata
;
806 r
= address_new_static(network
, filename
, section_line
, &n
);
810 if (!address_label_valid(rvalue
)) {
811 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface label is too long or invalid, ignoring assignment: %s", rvalue
);
815 r
= free_and_strdup(&n
->label
, rvalue
);
824 int config_parse_lifetime(const char *unit
,
825 const char *filename
,
828 unsigned section_line
,
834 Network
*network
= userdata
;
835 _cleanup_(address_freep
) Address
*n
= NULL
;
845 r
= address_new_static(network
, filename
, section_line
, &n
);
849 if (STR_IN_SET(rvalue
, "forever", "infinity")) {
850 n
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
856 r
= safe_atou(rvalue
, &k
);
858 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse PreferredLifetime, ignoring: %s", rvalue
);
863 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid PreferredLifetime value, ignoring: %d", k
);
865 n
->cinfo
.ifa_prefered
= k
;
872 int config_parse_address_flags(const char *unit
,
873 const char *filename
,
876 unsigned section_line
,
882 Network
*network
= userdata
;
883 _cleanup_(address_freep
) Address
*n
= NULL
;
892 r
= address_new_static(network
, filename
, section_line
, &n
);
896 r
= parse_boolean(rvalue
);
898 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address flag, ignoring: %s", rvalue
);
902 if (streq(lvalue
, "HomeAddress"))
904 else if (streq(lvalue
, "DuplicateAddressDetection"))
905 n
->duplicate_address_detection
= r
;
906 else if (streq(lvalue
, "ManageTemporaryAddress"))
907 n
->manage_temporary_address
= r
;
908 else if (streq(lvalue
, "PrefixRoute"))
910 else if (streq(lvalue
, "AutoJoin"))
916 int config_parse_address_scope(const char *unit
,
917 const char *filename
,
920 unsigned section_line
,
926 Network
*network
= userdata
;
927 _cleanup_(address_freep
) Address
*n
= NULL
;
936 r
= address_new_static(network
, filename
, section_line
, &n
);
940 if (streq(rvalue
, "host"))
941 n
->scope
= RT_SCOPE_HOST
;
942 else if (streq(rvalue
, "link"))
943 n
->scope
= RT_SCOPE_LINK
;
944 else if (streq(rvalue
, "global"))
945 n
->scope
= RT_SCOPE_UNIVERSE
;
947 r
= safe_atou8(rvalue
, &n
->scope
);
949 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue
);
959 bool address_is_ready(const Address
*a
) {
962 if (a
->family
== AF_INET6
)
963 return !(a
->flags
& IFA_F_TENTATIVE
);
965 return !(a
->flags
& (IFA_F_TENTATIVE
| IFA_F_DEPRECATED
));