1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "conf-parser.h"
25 #include "firewall-util.h"
26 #include "netlink-util.h"
32 #include "networkd-address.h"
34 int address_new(Address
**ret
) {
35 _cleanup_address_free_ Address
*address
= NULL
;
37 address
= new0(Address
, 1);
41 address
->family
= AF_UNSPEC
;
42 address
->scope
= RT_SCOPE_UNIVERSE
;
43 address
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
44 address
->cinfo
.ifa_valid
= CACHE_INFO_INFINITY_LIFE_TIME
;
52 int address_new_static(Network
*network
, unsigned section
, Address
**ret
) {
53 _cleanup_address_free_ Address
*address
= NULL
;
57 address
= hashmap_get(network
->addresses_by_section
, UINT_TO_PTR(section
));
66 r
= address_new(&address
);
70 address
->network
= network
;
72 LIST_APPEND(addresses
, network
->static_addresses
, address
);
75 address
->section
= section
;
76 hashmap_put(network
->addresses_by_section
,
77 UINT_TO_PTR(address
->section
), address
);
86 void address_free(Address
*address
) {
90 if (address
->network
) {
91 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
94 hashmap_remove(address
->network
->addresses_by_section
,
95 UINT_TO_PTR(address
->section
));
99 set_remove(address
->link
->addresses
, address
);
100 set_remove(address
->link
->addresses_foreign
, address
);
101 link_save(address
->link
);
107 static void address_hash_func(const void *b
, struct siphash
*state
) {
108 const Address
*a
= b
;
112 siphash24_compress(&a
->family
, sizeof(a
->family
), state
);
116 siphash24_compress(&a
->prefixlen
, sizeof(a
->prefixlen
), state
);
119 if (a
->prefixlen
!= 0) {
122 if (a
->in_addr_peer
.in
.s_addr
!= 0)
123 prefix
= be32toh(a
->in_addr_peer
.in
.s_addr
) >> (32 - a
->prefixlen
);
125 prefix
= be32toh(a
->in_addr
.in
.s_addr
) >> (32 - a
->prefixlen
);
127 siphash24_compress(&prefix
, sizeof(prefix
), state
);
133 siphash24_compress(&a
->in_addr
, FAMILY_ADDRESS_SIZE(a
->family
), state
);
137 /* treat any other address family as AF_UNSPEC */
142 static int address_compare_func(const void *c1
, const void *c2
) {
143 const Address
*a1
= c1
, *a2
= c2
;
145 if (a1
->family
< a2
->family
)
147 if (a1
->family
> a2
->family
)
150 switch (a1
->family
) {
151 /* use the same notion of equality as the kernel does */
153 if (a1
->prefixlen
< a2
->prefixlen
)
155 if (a1
->prefixlen
> a2
->prefixlen
)
158 /* compare the peer prefixes */
159 if (a1
->prefixlen
!= 0) {
160 /* make sure we don't try to shift by 32.
161 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
164 if (a1
->in_addr_peer
.in
.s_addr
!= 0)
165 b1
= be32toh(a1
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
167 b1
= be32toh(a1
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
169 if (a2
->in_addr_peer
.in
.s_addr
!= 0)
170 b2
= be32toh(a2
->in_addr_peer
.in
.s_addr
) >> (32 - a1
->prefixlen
);
172 b2
= be32toh(a2
->in_addr
.in
.s_addr
) >> (32 - a1
->prefixlen
);
182 return memcmp(&a1
->in_addr
, &a2
->in_addr
, FAMILY_ADDRESS_SIZE(a1
->family
));
184 /* treat any other address family as AF_UNSPEC */
189 static const struct hash_ops address_hash_ops
= {
190 .hash
= address_hash_func
,
191 .compare
= address_compare_func
194 bool address_equal(Address
*a1
, Address
*a2
) {
201 return address_compare_func(a1
, a2
) == 0;
204 static int address_establish(Address
*address
, Link
*link
) {
211 masq
= link
->network
&&
212 link
->network
->ip_masquerade
&&
213 address
->family
== AF_INET
&&
214 address
->scope
< RT_SCOPE_LINK
;
216 /* Add firewall entry if this is requested */
217 if (address
->ip_masquerade_done
!= masq
) {
218 union in_addr_union masked
= address
->in_addr
;
219 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
221 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
223 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
225 address
->ip_masquerade_done
= masq
;
231 static int address_add_internal(Link
*link
, Set
**addresses
,
233 const union in_addr_union
*in_addr
,
234 unsigned char prefixlen
,
236 _cleanup_address_free_ Address
*address
= NULL
;
243 r
= address_new(&address
);
247 address
->family
= family
;
248 address
->in_addr
= *in_addr
;
249 address
->prefixlen
= prefixlen
;
251 r
= set_ensure_allocated(addresses
, &address_hash_ops
);
255 r
= set_put(*addresses
, address
);
259 address
->link
= link
;
269 int address_add_foreign(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
270 return address_add_internal(link
, &link
->addresses_foreign
, family
, in_addr
, prefixlen
, ret
);
273 static int address_add(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
276 r
= address_add_internal(link
, &link
->addresses
, family
, in_addr
, prefixlen
, ret
);
285 static int address_release(Address
*address
) {
289 assert(address
->link
);
291 /* Remove masquerading firewall entry if it was added */
292 if (address
->ip_masquerade_done
) {
293 union in_addr_union masked
= address
->in_addr
;
294 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
296 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
298 log_link_warning_errno(address
->link
, r
, "Failed to disable IP masquerading: %m");
300 address
->ip_masquerade_done
= false;
306 int address_update(Address
*address
, unsigned char flags
, unsigned char scope
, struct ifa_cacheinfo
*cinfo
) {
312 ready
= address_is_ready(address
);
314 address
->added
= true;
315 address
->flags
= flags
;
316 address
->scope
= scope
;
317 address
->cinfo
= *cinfo
;
319 if (!ready
&& address_is_ready(address
) && address
->link
)
320 link_check_ready(address
->link
);
325 int address_drop(Address
*address
) {
331 ready
= address_is_ready(address
);
332 link
= address
->link
;
334 address_release(address
);
335 address_free(address
);
338 link_check_ready(link
);
343 int address_get(Link
*link
, int family
, const union in_addr_union
*in_addr
, unsigned char prefixlen
, Address
**ret
) {
344 Address address
= {}, *existing
;
350 address
.family
= family
;
351 address
.in_addr
= *in_addr
;
352 address
.prefixlen
= prefixlen
;
354 existing
= set_get(link
->addresses
, &address
);
356 existing
= set_get(link
->addresses_foreign
, &address
);
366 int address_remove(Address
*address
, Link
*link
,
367 sd_netlink_message_handler_t callback
) {
368 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
372 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
374 assert(link
->ifindex
> 0);
375 assert(link
->manager
);
376 assert(link
->manager
->rtnl
);
378 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
379 link
->ifindex
, address
->family
);
381 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
383 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
385 return log_error_errno(r
, "Could not set prefixlen: %m");
387 if (address
->family
== AF_INET
)
388 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
389 else if (address
->family
== AF_INET6
)
390 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
392 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
394 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
396 return log_error_errno(r
, "Could not send rtnetlink message: %m");
403 static int address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
404 union in_addr_union in_addr
= {};
405 struct in_addr broadcast
= {};
406 _cleanup_address_free_ Address
*na
= NULL
;
413 /* Something useful was configured? just use it */
414 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
417 /* The address is configured to be 0.0.0.0 or [::] by the user?
418 * Then let's acquire something more useful from the pool. */
419 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
421 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
423 log_link_error(link
, "Couldn't find free address for interface, all taken.");
427 if (original
->family
== AF_INET
) {
428 /* Pick first address in range for ourselves ... */
429 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
431 /* .. and use last as broadcast address */
432 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
433 } else if (original
->family
== AF_INET6
)
434 in_addr
.in6
.s6_addr
[15] |= 1;
436 r
= address_new(&na
);
440 na
->family
= original
->family
;
441 na
->prefixlen
= original
->prefixlen
;
442 na
->scope
= original
->scope
;
443 na
->cinfo
= original
->cinfo
;
445 if (original
->label
) {
446 na
->label
= strdup(original
->label
);
451 na
->broadcast
= broadcast
;
452 na
->in_addr
= in_addr
;
454 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
462 int address_configure(Address
*address
, Link
*link
, sd_netlink_message_handler_t callback
, bool update
) {
463 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
467 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
469 assert(link
->ifindex
> 0);
470 assert(link
->manager
);
471 assert(link
->manager
->rtnl
);
473 r
= address_acquire(link
, address
, &address
);
478 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
479 link
->ifindex
, address
->family
);
481 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
482 link
->ifindex
, address
->family
);
484 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
486 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
488 return log_error_errno(r
, "Could not set prefixlen: %m");
490 address
->flags
|= IFA_F_PERMANENT
;
492 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
494 return log_error_errno(r
, "Could not set flags: %m");
496 if (address
->flags
& ~0xff) {
497 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
499 return log_error_errno(r
, "Could not set extended flags: %m");
502 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
504 return log_error_errno(r
, "Could not set scope: %m");
506 if (address
->family
== AF_INET
)
507 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
508 else if (address
->family
== AF_INET6
)
509 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
511 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
513 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
514 if (address
->family
== AF_INET
)
515 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
516 else if (address
->family
== AF_INET6
)
517 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
519 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
521 if (address
->family
== AF_INET
) {
522 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
524 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
528 if (address
->label
) {
529 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
531 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
534 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
537 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
539 r
= address_establish(address
, link
);
543 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
545 address_release(address
);
546 return log_error_errno(r
, "Could not send rtnetlink message: %m");
551 r
= address_add(link
, address
->family
, &address
->in_addr
, address
->prefixlen
, NULL
);
553 address_release(address
);
554 return log_error_errno(r
, "Could not add address: %m");
560 int config_parse_broadcast(
562 const char *filename
,
565 unsigned section_line
,
572 Network
*network
= userdata
;
573 _cleanup_address_free_ Address
*n
= NULL
;
582 r
= address_new_static(network
, section_line
, &n
);
586 if (n
->family
== AF_INET6
) {
587 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
591 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
593 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Broadcast is invalid, ignoring assignment: %s", rvalue
);
603 int config_parse_address(const char *unit
,
604 const char *filename
,
607 unsigned section_line
,
614 Network
*network
= userdata
;
615 _cleanup_address_free_ Address
*n
= NULL
;
616 const char *address
, *e
;
617 union in_addr_union buffer
;
626 if (streq(section
, "Network")) {
627 /* we are not in an Address section, so treat
628 * this as the special '0' section */
632 r
= address_new_static(network
, section_line
, &n
);
636 /* Address=address/prefixlen */
639 e
= strchr(rvalue
, '/');
643 r
= safe_atou(e
+ 1, &i
);
645 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
649 n
->prefixlen
= (unsigned char) i
;
651 address
= strndupa(rvalue
, e
- rvalue
);
655 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
657 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address is invalid, ignoring assignment: %s", address
);
661 if (!e
&& f
== AF_INET
) {
662 r
= in_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
664 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
);
669 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
670 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Address is incompatible, ignoring assignment: %s", address
);
676 if (streq(lvalue
, "Address"))
679 n
->in_addr_peer
= buffer
;
681 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
682 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
689 int config_parse_label(const char *unit
,
690 const char *filename
,
693 unsigned section_line
,
699 Network
*network
= userdata
;
700 _cleanup_address_free_ Address
*n
= NULL
;
710 r
= address_new_static(network
, section_line
, &n
);
714 label
= strdup(rvalue
);
718 if (!ascii_is_valid(label
) || strlen(label
) >= IFNAMSIZ
) {
719 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface label is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
737 bool address_is_ready(const Address
*a
) {
740 return a
->added
&& !(a
->flags
& (IFA_F_TENTATIVE
| IFA_F_DEPRECATED
));