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/>.
23 #include "alloc-util.h"
24 #include "conf-parser.h"
25 #include "firewall-util.h"
26 #include "netlink-util.h"
27 #include "networkd-address.h"
28 #include "networkd-manager.h"
29 #include "parse-util.h"
31 #include "socket-util.h"
32 #include "string-util.h"
36 #define ADDRESSES_PER_LINK_MAX 2048U
37 #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
39 int address_new(Address
**ret
) {
40 _cleanup_address_free_ Address
*address
= NULL
;
42 address
= new0(Address
, 1);
46 address
->family
= AF_UNSPEC
;
47 address
->scope
= RT_SCOPE_UNIVERSE
;
48 address
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
49 address
->cinfo
.ifa_valid
= CACHE_INFO_INFINITY_LIFE_TIME
;
57 int address_new_static(Network
*network
, const char *filename
, unsigned section_line
, Address
**ret
) {
58 _cleanup_network_config_section_free_ NetworkConfigSection
*n
= NULL
;
59 _cleanup_address_free_ Address
*address
= NULL
;
64 assert(!!filename
== (section_line
> 0));
67 r
= network_config_section_new(filename
, section_line
, &n
);
71 address
= hashmap_get(network
->addresses_by_section
, n
);
80 if (network
->n_static_addresses
>= STATIC_ADDRESSES_PER_NETWORK_MAX
)
83 r
= address_new(&address
);
91 r
= hashmap_put(network
->addresses_by_section
, address
->section
, address
);
96 address
->network
= network
;
97 LIST_APPEND(addresses
, network
->static_addresses
, address
);
98 network
->n_static_addresses
++;
106 void address_free(Address
*address
) {
110 if (address
->network
) {
111 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
112 assert(address
->network
->n_static_addresses
> 0);
113 address
->network
->n_static_addresses
--;
115 if (address
->section
) {
116 hashmap_remove(address
->network
->addresses_by_section
, address
->section
);
117 network_config_section_free(address
->section
);
122 set_remove(address
->link
->addresses
, address
);
123 set_remove(address
->link
->addresses_foreign
, address
);
125 if (in_addr_equal(AF_INET6
, &address
->in_addr
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
))
126 memzero(&address
->link
->ipv6ll_address
, sizeof(struct in6_addr
));
132 static void address_hash_func(const void *b
, struct siphash
*state
) {
133 const Address
*a
= b
;
137 siphash24_compress(&a
->family
, sizeof(a
->family
), state
);
141 siphash24_compress(&a
->prefixlen
, sizeof(a
->prefixlen
), state
);
144 if (a
->prefixlen
!= 0) {
147 if (a
->in_addr_peer
.in
.s_addr
!= 0)
148 prefix
= be32toh(a
->in_addr_peer
.in
.s_addr
) >> (32 - a
->prefixlen
);
150 prefix
= be32toh(a
->in_addr
.in
.s_addr
) >> (32 - a
->prefixlen
);
152 siphash24_compress(&prefix
, sizeof(prefix
), state
);
158 siphash24_compress(&a
->in_addr
, FAMILY_ADDRESS_SIZE(a
->family
), state
);
162 /* treat any other address family as AF_UNSPEC */
167 static int address_compare_func(const void *c1
, const void *c2
) {
168 const Address
*a1
= c1
, *a2
= c2
;
170 if (a1
->family
< a2
->family
)
172 if (a1
->family
> a2
->family
)
175 switch (a1
->family
) {
176 /* use the same notion of equality as the kernel does */
178 if (a1
->prefixlen
< a2
->prefixlen
)
180 if (a1
->prefixlen
> a2
->prefixlen
)
183 /* compare the peer prefixes */
184 if (a1
->prefixlen
!= 0) {
185 /* make sure we don't try to shift by 32.
186 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
189 if (a1
->in_addr_peer
.in
.s_addr
!= 0)
190 b1
= be32toh(a1
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
192 b1
= be32toh(a1
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
194 if (a2
->in_addr_peer
.in
.s_addr
!= 0)
195 b2
= be32toh(a2
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
197 b2
= be32toh(a2
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
207 return memcmp(&a1
->in_addr
, &a2
->in_addr
, FAMILY_ADDRESS_SIZE(a1
->family
));
209 /* treat any other address family as AF_UNSPEC */
214 static const struct hash_ops address_hash_ops
= {
215 .hash
= address_hash_func
,
216 .compare
= address_compare_func
219 bool address_equal(Address
*a1
, Address
*a2
) {
226 return address_compare_func(a1
, a2
) == 0;
229 static int address_establish(Address
*address
, Link
*link
) {
236 masq
= link
->network
&&
237 link
->network
->ip_masquerade
&&
238 address
->family
== AF_INET
&&
239 address
->scope
< RT_SCOPE_LINK
;
241 /* Add firewall entry if this is requested */
242 if (address
->ip_masquerade_done
!= masq
) {
243 union in_addr_union masked
= address
->in_addr
;
244 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
246 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
248 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
250 address
->ip_masquerade_done
= masq
;
256 static int address_add_internal(Link
*link
, Set
**addresses
,
258 const union in_addr_union
*in_addr
,
259 unsigned char prefixlen
,
261 _cleanup_address_free_ Address
*address
= NULL
;
268 r
= address_new(&address
);
272 address
->family
= family
;
273 address
->in_addr
= *in_addr
;
274 address
->prefixlen
= prefixlen
;
275 /* Consider address tentative until we get the real flags from the kernel */
276 address
->flags
= IFA_F_TENTATIVE
;
278 r
= set_ensure_allocated(addresses
, &address_hash_ops
);
282 r
= set_put(*addresses
, address
);
286 address
->link
= link
;
296 int address_add_foreign(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
297 return address_add_internal(link
, &link
->addresses_foreign
, family
, in_addr
, prefixlen
, ret
);
300 int address_add(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
304 r
= address_get(link
, family
, in_addr
, prefixlen
, &address
);
306 /* Address does not exist, create a new one */
307 r
= address_add_internal(link
, &link
->addresses
, family
, in_addr
, prefixlen
, &address
);
311 /* Take over a foreign address */
312 r
= set_ensure_allocated(&link
->addresses
, &address_hash_ops
);
316 r
= set_put(link
->addresses
, address
);
320 set_remove(link
->addresses_foreign
, address
);
322 /* Already exists, do nothing */
333 static int address_release(Address
*address
) {
337 assert(address
->link
);
339 /* Remove masquerading firewall entry if it was added */
340 if (address
->ip_masquerade_done
) {
341 union in_addr_union masked
= address
->in_addr
;
342 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
344 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
346 log_link_warning_errno(address
->link
, r
, "Failed to disable IP masquerading: %m");
348 address
->ip_masquerade_done
= false;
358 const struct ifa_cacheinfo
*cinfo
) {
365 assert_return(address
->link
, 1);
367 if (IN_SET(address
->link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
370 ready
= address_is_ready(address
);
372 address
->flags
= flags
;
373 address
->scope
= scope
;
374 address
->cinfo
= *cinfo
;
376 link_update_operstate(address
->link
);
378 if (!ready
&& address_is_ready(address
)) {
379 link_check_ready(address
->link
);
381 if (address
->family
== AF_INET6
&&
382 in_addr_is_link_local(AF_INET6
, &address
->in_addr
) > 0 &&
383 in_addr_is_null(AF_INET6
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
) > 0) {
385 r
= link_ipv6ll_gained(address
->link
, &address
->in_addr
.in6
);
394 int address_drop(Address
*address
) {
400 ready
= address_is_ready(address
);
401 link
= address
->link
;
403 address_release(address
);
404 address_free(address
);
406 link_update_operstate(link
);
409 link_check_ready(link
);
414 int address_get(Link
*link
,
416 const union in_addr_union
*in_addr
,
417 unsigned char prefixlen
,
420 Address address
, *existing
;
425 address
= (Address
) {
428 .prefixlen
= prefixlen
,
431 existing
= set_get(link
->addresses
, &address
);
438 existing
= set_get(link
->addresses_foreign
, &address
);
451 sd_netlink_message_handler_t callback
) {
453 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
457 assert(IN_SET(address
->family
, AF_INET
, AF_INET6
));
459 assert(link
->ifindex
> 0);
460 assert(link
->manager
);
461 assert(link
->manager
->rtnl
);
463 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
464 link
->ifindex
, address
->family
);
466 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
468 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
470 return log_error_errno(r
, "Could not set prefixlen: %m");
472 if (address
->family
== AF_INET
)
473 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
474 else if (address
->family
== AF_INET6
)
475 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
477 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
479 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
481 return log_error_errno(r
, "Could not send rtnetlink message: %m");
488 static int address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
489 union in_addr_union in_addr
= {};
490 struct in_addr broadcast
= {};
491 _cleanup_address_free_ Address
*na
= NULL
;
498 /* Something useful was configured? just use it */
499 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
502 /* The address is configured to be 0.0.0.0 or [::] by the user?
503 * Then let's acquire something more useful from the pool. */
504 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
506 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
508 log_link_error(link
, "Couldn't find free address for interface, all taken.");
512 if (original
->family
== AF_INET
) {
513 /* Pick first address in range for ourselves ... */
514 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
516 /* .. and use last as broadcast address */
517 if (original
->prefixlen
> 30)
518 broadcast
.s_addr
= 0;
520 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
521 } else if (original
->family
== AF_INET6
)
522 in_addr
.in6
.s6_addr
[15] |= 1;
524 r
= address_new(&na
);
528 na
->family
= original
->family
;
529 na
->prefixlen
= original
->prefixlen
;
530 na
->scope
= original
->scope
;
531 na
->cinfo
= original
->cinfo
;
533 if (original
->label
) {
534 na
->label
= strdup(original
->label
);
539 na
->broadcast
= broadcast
;
540 na
->in_addr
= in_addr
;
542 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
550 int address_configure(
553 sd_netlink_message_handler_t callback
,
556 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
560 assert(IN_SET(address
->family
, AF_INET
, AF_INET6
));
562 assert(link
->ifindex
> 0);
563 assert(link
->manager
);
564 assert(link
->manager
->rtnl
);
566 /* If this is a new address, then refuse adding more than the limit */
567 if (address_get(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
) <= 0 &&
568 set_size(link
->addresses
) >= ADDRESSES_PER_LINK_MAX
)
571 r
= address_acquire(link
, address
, &address
);
576 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
577 link
->ifindex
, address
->family
);
579 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
580 link
->ifindex
, address
->family
);
582 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
584 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
586 return log_error_errno(r
, "Could not set prefixlen: %m");
588 address
->flags
|= IFA_F_PERMANENT
;
590 if (address
->home_address
)
591 address
->flags
|= IFA_F_HOMEADDRESS
;
593 if (address
->duplicate_address_detection
)
594 address
->flags
|= IFA_F_NODAD
;
596 if (address
->manage_temporary_address
)
597 address
->flags
|= IFA_F_MANAGETEMPADDR
;
599 if (address
->prefix_route
)
600 address
->flags
|= IFA_F_NOPREFIXROUTE
;
602 if (address
->autojoin
)
603 address
->flags
|= IFA_F_MCAUTOJOIN
;
605 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
607 return log_error_errno(r
, "Could not set flags: %m");
609 if (address
->flags
& ~0xff) {
610 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
612 return log_error_errno(r
, "Could not set extended flags: %m");
615 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
617 return log_error_errno(r
, "Could not set scope: %m");
619 if (address
->family
== AF_INET
)
620 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
621 else if (address
->family
== AF_INET6
)
622 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
624 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
626 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
627 if (address
->family
== AF_INET
)
628 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
629 else if (address
->family
== AF_INET6
)
630 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
632 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
634 if (address
->family
== AF_INET
) {
635 if (address
->prefixlen
<= 30) {
636 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
638 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
643 if (address
->label
) {
644 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
646 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
649 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
652 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
654 r
= address_establish(address
, link
);
658 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
660 address_release(address
);
661 return log_error_errno(r
, "Could not send rtnetlink message: %m");
666 r
= address_add(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
);
668 address_release(address
);
669 return log_error_errno(r
, "Could not add address: %m");
675 int config_parse_broadcast(
677 const char *filename
,
680 unsigned section_line
,
687 Network
*network
= userdata
;
688 _cleanup_address_free_ Address
*n
= NULL
;
697 r
= address_new_static(network
, filename
, section_line
, &n
);
701 if (n
->family
== AF_INET6
) {
702 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
706 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
708 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Broadcast is invalid, ignoring assignment: %s", rvalue
);
718 int config_parse_address(const char *unit
,
719 const char *filename
,
722 unsigned section_line
,
729 Network
*network
= userdata
;
730 _cleanup_address_free_ Address
*n
= NULL
;
731 const char *address
, *e
;
732 union in_addr_union buffer
;
741 if (streq(section
, "Network")) {
742 /* we are not in an Address section, so treat
743 * this as the special '0' section */
744 r
= address_new_static(network
, NULL
, 0, &n
);
746 r
= address_new_static(network
, filename
, section_line
, &n
);
751 /* Address=address/prefixlen */
754 e
= strchr(rvalue
, '/');
758 r
= safe_atou(e
+ 1, &i
);
760 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
764 n
->prefixlen
= (unsigned char) i
;
766 address
= strndupa(rvalue
, e
- rvalue
);
770 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
772 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address is invalid, ignoring assignment: %s", address
);
776 if (!e
&& f
== AF_INET
) {
777 r
= in4_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
779 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length not specified, and a default one cannot be deduced for '%s', ignoring assignment", address
);
784 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
785 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Address is incompatible, ignoring assignment: %s", address
);
791 if (streq(lvalue
, "Address"))
794 n
->in_addr_peer
= buffer
;
796 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
797 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
804 int config_parse_label(
806 const char *filename
,
809 unsigned section_line
,
816 _cleanup_address_free_ Address
*n
= NULL
;
817 Network
*network
= userdata
;
826 r
= address_new_static(network
, filename
, section_line
, &n
);
830 if (!address_label_valid(rvalue
)) {
831 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface label is too long or invalid, ignoring assignment: %s", rvalue
);
835 r
= free_and_strdup(&n
->label
, rvalue
);
844 int config_parse_lifetime(const char *unit
,
845 const char *filename
,
848 unsigned section_line
,
854 Network
*network
= userdata
;
855 _cleanup_address_free_ Address
*n
= NULL
;
865 r
= address_new_static(network
, filename
, section_line
, &n
);
869 if (STR_IN_SET(rvalue
, "forever", "infinity")) {
870 n
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
876 r
= safe_atou(rvalue
, &k
);
878 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse PreferredLifetime, ignoring: %s", rvalue
);
883 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid PreferredLifetime value, ignoring: %d", k
);
885 n
->cinfo
.ifa_prefered
= k
;
892 int config_parse_address_flags(const char *unit
,
893 const char *filename
,
896 unsigned section_line
,
902 Network
*network
= userdata
;
903 _cleanup_address_free_ Address
*n
= NULL
;
912 r
= address_new_static(network
, filename
, section_line
, &n
);
916 r
= parse_boolean(rvalue
);
918 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address flag, ignoring: %s", rvalue
);
922 if (streq(lvalue
, "HomeAddress"))
924 else if (streq(lvalue
, "DuplicateAddressDetection"))
925 n
->duplicate_address_detection
= r
;
926 else if (streq(lvalue
, "ManageTemporaryAddress"))
927 n
->manage_temporary_address
= r
;
928 else if (streq(lvalue
, "PrefixRoute"))
930 else if (streq(lvalue
, "AutoJoin"))
936 int config_parse_address_scope(const char *unit
,
937 const char *filename
,
940 unsigned section_line
,
946 Network
*network
= userdata
;
947 _cleanup_address_free_ Address
*n
= NULL
;
956 r
= address_new_static(network
, filename
, section_line
, &n
);
960 if (streq(rvalue
, "host"))
961 n
->scope
= RT_SCOPE_HOST
;
962 else if (streq(rvalue
, "link"))
963 n
->scope
= RT_SCOPE_LINK
;
964 else if (streq(rvalue
, "global"))
965 n
->scope
= RT_SCOPE_UNIVERSE
;
967 r
= safe_atou8(rvalue
, &n
->scope
);
969 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue
);
979 bool address_is_ready(const Address
*a
) {
982 if (a
->family
== AF_INET6
)
983 return !(a
->flags
& IFA_F_TENTATIVE
);
985 return !(a
->flags
& (IFA_F_TENTATIVE
| IFA_F_DEPRECATED
));