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"
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
, unsigned section
, Address
**ret
) {
57 _cleanup_address_free_ Address
*address
= NULL
;
64 address
= hashmap_get(network
->addresses_by_section
, UINT_TO_PTR(section
));
73 if (network
->n_static_addresses
>= STATIC_ADDRESSES_PER_NETWORK_MAX
)
76 r
= address_new(&address
);
81 address
->section
= section
;
82 hashmap_put(network
->addresses_by_section
, UINT_TO_PTR(address
->section
), address
);
85 address
->network
= network
;
86 LIST_APPEND(addresses
, network
->static_addresses
, address
);
87 network
->n_static_addresses
++;
95 void address_free(Address
*address
) {
99 if (address
->network
) {
100 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
101 assert(address
->network
->n_static_addresses
> 0);
102 address
->network
->n_static_addresses
--;
104 if (address
->section
)
105 hashmap_remove(address
->network
->addresses_by_section
, UINT_TO_PTR(address
->section
));
109 set_remove(address
->link
->addresses
, address
);
110 set_remove(address
->link
->addresses_foreign
, address
);
112 if (in_addr_equal(AF_INET6
, &address
->in_addr
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
))
113 memzero(&address
->link
->ipv6ll_address
, sizeof(struct in6_addr
));
119 static void address_hash_func(const void *b
, struct siphash
*state
) {
120 const Address
*a
= b
;
124 siphash24_compress(&a
->family
, sizeof(a
->family
), state
);
128 siphash24_compress(&a
->prefixlen
, sizeof(a
->prefixlen
), state
);
131 if (a
->prefixlen
!= 0) {
134 if (a
->in_addr_peer
.in
.s_addr
!= 0)
135 prefix
= be32toh(a
->in_addr_peer
.in
.s_addr
) >> (32 - a
->prefixlen
);
137 prefix
= be32toh(a
->in_addr
.in
.s_addr
) >> (32 - a
->prefixlen
);
139 siphash24_compress(&prefix
, sizeof(prefix
), state
);
145 siphash24_compress(&a
->in_addr
, FAMILY_ADDRESS_SIZE(a
->family
), state
);
149 /* treat any other address family as AF_UNSPEC */
154 static int address_compare_func(const void *c1
, const void *c2
) {
155 const Address
*a1
= c1
, *a2
= c2
;
157 if (a1
->family
< a2
->family
)
159 if (a1
->family
> a2
->family
)
162 switch (a1
->family
) {
163 /* use the same notion of equality as the kernel does */
165 if (a1
->prefixlen
< a2
->prefixlen
)
167 if (a1
->prefixlen
> a2
->prefixlen
)
170 /* compare the peer prefixes */
171 if (a1
->prefixlen
!= 0) {
172 /* make sure we don't try to shift by 32.
173 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
176 if (a1
->in_addr_peer
.in
.s_addr
!= 0)
177 b1
= be32toh(a1
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
179 b1
= be32toh(a1
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
181 if (a2
->in_addr_peer
.in
.s_addr
!= 0)
182 b2
= be32toh(a2
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
184 b2
= be32toh(a2
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
194 return memcmp(&a1
->in_addr
, &a2
->in_addr
, FAMILY_ADDRESS_SIZE(a1
->family
));
196 /* treat any other address family as AF_UNSPEC */
201 static const struct hash_ops address_hash_ops
= {
202 .hash
= address_hash_func
,
203 .compare
= address_compare_func
206 bool address_equal(Address
*a1
, Address
*a2
) {
213 return address_compare_func(a1
, a2
) == 0;
216 static int address_establish(Address
*address
, Link
*link
) {
223 masq
= link
->network
&&
224 link
->network
->ip_masquerade
&&
225 address
->family
== AF_INET
&&
226 address
->scope
< RT_SCOPE_LINK
;
228 /* Add firewall entry if this is requested */
229 if (address
->ip_masquerade_done
!= masq
) {
230 union in_addr_union masked
= address
->in_addr
;
231 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
233 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
235 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
237 address
->ip_masquerade_done
= masq
;
243 static int address_add_internal(Link
*link
, Set
**addresses
,
245 const union in_addr_union
*in_addr
,
246 unsigned char prefixlen
,
248 _cleanup_address_free_ Address
*address
= NULL
;
255 r
= address_new(&address
);
259 address
->family
= family
;
260 address
->in_addr
= *in_addr
;
261 address
->prefixlen
= prefixlen
;
262 /* Consider address tentative until we get the real flags from the kernel */
263 address
->flags
= IFA_F_TENTATIVE
;
265 r
= set_ensure_allocated(addresses
, &address_hash_ops
);
269 r
= set_put(*addresses
, address
);
273 address
->link
= link
;
283 int address_add_foreign(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
284 return address_add_internal(link
, &link
->addresses_foreign
, family
, in_addr
, prefixlen
, ret
);
287 int address_add(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
291 r
= address_get(link
, family
, in_addr
, prefixlen
, &address
);
293 /* Address does not exist, create a new one */
294 r
= address_add_internal(link
, &link
->addresses
, family
, in_addr
, prefixlen
, &address
);
298 /* Take over a foreign address */
299 r
= set_ensure_allocated(&link
->addresses
, &address_hash_ops
);
303 r
= set_put(link
->addresses
, address
);
307 set_remove(link
->addresses_foreign
, address
);
309 /* Already exists, do nothing */
320 static int address_release(Address
*address
) {
324 assert(address
->link
);
326 /* Remove masquerading firewall entry if it was added */
327 if (address
->ip_masquerade_done
) {
328 union in_addr_union masked
= address
->in_addr
;
329 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
331 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
333 log_link_warning_errno(address
->link
, r
, "Failed to disable IP masquerading: %m");
335 address
->ip_masquerade_done
= false;
345 const struct ifa_cacheinfo
*cinfo
) {
352 assert_return(address
->link
, 1);
354 if (IN_SET(address
->link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
357 ready
= address_is_ready(address
);
359 address
->flags
= flags
;
360 address
->scope
= scope
;
361 address
->cinfo
= *cinfo
;
363 link_update_operstate(address
->link
);
365 if (!ready
&& address_is_ready(address
)) {
366 link_check_ready(address
->link
);
368 if (address
->family
== AF_INET6
&&
369 in_addr_is_link_local(AF_INET6
, &address
->in_addr
) > 0 &&
370 in_addr_is_null(AF_INET6
, (const union in_addr_union
*) &address
->link
->ipv6ll_address
) > 0) {
372 r
= link_ipv6ll_gained(address
->link
, &address
->in_addr
.in6
);
381 int address_drop(Address
*address
) {
387 ready
= address_is_ready(address
);
388 link
= address
->link
;
390 address_release(address
);
391 address_free(address
);
393 link_update_operstate(link
);
396 link_check_ready(link
);
401 int address_get(Link
*link
,
403 const union in_addr_union
*in_addr
,
404 unsigned char prefixlen
,
407 Address address
, *existing
;
412 address
= (Address
) {
415 .prefixlen
= prefixlen
,
418 existing
= set_get(link
->addresses
, &address
);
425 existing
= set_get(link
->addresses_foreign
, &address
);
438 sd_netlink_message_handler_t callback
) {
440 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
444 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
446 assert(link
->ifindex
> 0);
447 assert(link
->manager
);
448 assert(link
->manager
->rtnl
);
450 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
451 link
->ifindex
, address
->family
);
453 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
455 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
457 return log_error_errno(r
, "Could not set prefixlen: %m");
459 if (address
->family
== AF_INET
)
460 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
461 else if (address
->family
== AF_INET6
)
462 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
464 return log_error_errno(r
, "Could not append IFA_LOCAL 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 address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
476 union in_addr_union in_addr
= {};
477 struct in_addr broadcast
= {};
478 _cleanup_address_free_ Address
*na
= NULL
;
485 /* Something useful was configured? just use it */
486 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
489 /* The address is configured to be 0.0.0.0 or [::] by the user?
490 * Then let's acquire something more useful from the pool. */
491 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
493 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
495 log_link_error(link
, "Couldn't find free address for interface, all taken.");
499 if (original
->family
== AF_INET
) {
500 /* Pick first address in range for ourselves ... */
501 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
503 /* .. and use last as broadcast address */
504 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
505 } else if (original
->family
== AF_INET6
)
506 in_addr
.in6
.s6_addr
[15] |= 1;
508 r
= address_new(&na
);
512 na
->family
= original
->family
;
513 na
->prefixlen
= original
->prefixlen
;
514 na
->scope
= original
->scope
;
515 na
->cinfo
= original
->cinfo
;
517 if (original
->label
) {
518 na
->label
= strdup(original
->label
);
523 na
->broadcast
= broadcast
;
524 na
->in_addr
= in_addr
;
526 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
534 int address_configure(
537 sd_netlink_message_handler_t callback
,
540 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
544 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
546 assert(link
->ifindex
> 0);
547 assert(link
->manager
);
548 assert(link
->manager
->rtnl
);
550 /* If this is a new address, then refuse adding more than the limit */
551 if (address_get(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
) <= 0 &&
552 set_size(link
->addresses
) >= ADDRESSES_PER_LINK_MAX
)
555 r
= address_acquire(link
, address
, &address
);
560 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
561 link
->ifindex
, address
->family
);
563 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
564 link
->ifindex
, address
->family
);
566 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
568 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
570 return log_error_errno(r
, "Could not set prefixlen: %m");
572 address
->flags
|= IFA_F_PERMANENT
;
574 if (address
->home_address
)
575 address
->flags
|= IFA_F_HOMEADDRESS
;
577 if (address
->duplicate_address_detection
)
578 address
->flags
|= IFA_F_NODAD
;
580 if (address
->manage_temporary_address
)
581 address
->flags
|= IFA_F_MANAGETEMPADDR
;
583 if (address
->prefix_route
)
584 address
->flags
|= IFA_F_NOPREFIXROUTE
;
586 if (address
->autojoin
)
587 address
->flags
|= IFA_F_MCAUTOJOIN
;
589 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
591 return log_error_errno(r
, "Could not set flags: %m");
593 if (address
->flags
& ~0xff) {
594 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
596 return log_error_errno(r
, "Could not set extended flags: %m");
599 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
601 return log_error_errno(r
, "Could not set scope: %m");
603 if (address
->family
== AF_INET
)
604 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
605 else if (address
->family
== AF_INET6
)
606 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
608 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
610 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
611 if (address
->family
== AF_INET
)
612 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
613 else if (address
->family
== AF_INET6
)
614 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
616 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
618 if (address
->family
== AF_INET
) {
619 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
621 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
625 if (address
->label
) {
626 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
628 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
631 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
634 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
636 r
= address_establish(address
, link
);
640 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
642 address_release(address
);
643 return log_error_errno(r
, "Could not send rtnetlink message: %m");
648 r
= address_add(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
);
650 address_release(address
);
651 return log_error_errno(r
, "Could not add address: %m");
657 int config_parse_broadcast(
659 const char *filename
,
662 unsigned section_line
,
669 Network
*network
= userdata
;
670 _cleanup_address_free_ Address
*n
= NULL
;
679 r
= address_new_static(network
, section_line
, &n
);
683 if (n
->family
== AF_INET6
) {
684 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
688 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
690 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Broadcast is invalid, ignoring assignment: %s", rvalue
);
700 int config_parse_address(const char *unit
,
701 const char *filename
,
704 unsigned section_line
,
711 Network
*network
= userdata
;
712 _cleanup_address_free_ Address
*n
= NULL
;
713 const char *address
, *e
;
714 union in_addr_union buffer
;
723 if (streq(section
, "Network")) {
724 /* we are not in an Address section, so treat
725 * this as the special '0' section */
729 r
= address_new_static(network
, section_line
, &n
);
733 /* Address=address/prefixlen */
736 e
= strchr(rvalue
, '/');
740 r
= safe_atou(e
+ 1, &i
);
742 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
746 n
->prefixlen
= (unsigned char) i
;
748 address
= strndupa(rvalue
, e
- rvalue
);
752 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
754 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address is invalid, ignoring assignment: %s", address
);
758 if (!e
&& f
== AF_INET
) {
759 r
= in_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
761 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
);
766 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
767 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Address is incompatible, ignoring assignment: %s", address
);
773 if (streq(lvalue
, "Address"))
776 n
->in_addr_peer
= buffer
;
778 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
779 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
786 int config_parse_label(
788 const char *filename
,
791 unsigned section_line
,
798 _cleanup_address_free_ Address
*n
= NULL
;
799 Network
*network
= userdata
;
808 r
= address_new_static(network
, section_line
, &n
);
812 if (!ifname_valid(rvalue
)) {
813 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface label is not valid or too long, ignoring assignment: %s", rvalue
);
817 r
= free_and_strdup(&n
->label
, rvalue
);
826 int config_parse_lifetime(const char *unit
,
827 const char *filename
,
830 unsigned section_line
,
836 Network
*network
= userdata
;
837 _cleanup_address_free_ Address
*n
= NULL
;
847 r
= address_new_static(network
, section_line
, &n
);
851 if (STR_IN_SET(rvalue
, "forever", "infinity")) {
852 n
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
858 r
= safe_atou(rvalue
, &k
);
860 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse PreferredLifetime, ignoring: %s", rvalue
);
865 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid PreferredLifetime value, ignoring: %d", k
);
867 n
->cinfo
.ifa_prefered
= k
;
874 int config_parse_address_flags(const char *unit
,
875 const char *filename
,
878 unsigned section_line
,
884 Network
*network
= userdata
;
885 _cleanup_address_free_ Address
*n
= NULL
;
894 r
= address_new_static(network
, section_line
, &n
);
898 r
= parse_boolean(rvalue
);
900 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address flag, ignoring: %s", rvalue
);
904 if (streq(lvalue
, "HomeAddress"))
906 else if (streq(lvalue
, "DuplicateAddressDetection"))
907 n
->duplicate_address_detection
= r
;
908 else if (streq(lvalue
, "ManageTemporaryAddress"))
909 n
->manage_temporary_address
= r
;
910 else if (streq(lvalue
, "PrefixRoute"))
912 else if (streq(lvalue
, "AutoJoin"))
918 bool address_is_ready(const Address
*a
) {
921 return !(a
->flags
& (IFA_F_TENTATIVE
| IFA_F_DEPRECATED
));