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/>.
26 #include "conf-parser.h"
29 #include "networkd-link.h"
31 static void address_init(Address
*address
) {
34 address
->family
= AF_UNSPEC
;
35 address
->scope
= RT_SCOPE_UNIVERSE
;
36 address
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
37 address
->cinfo
.ifa_valid
= CACHE_INFO_INFINITY_LIFE_TIME
;
40 int address_new_static(Network
*network
, unsigned section
, Address
**ret
) {
41 _cleanup_address_free_ Address
*address
= NULL
;
44 address
= hashmap_get(network
->addresses_by_section
, UINT_TO_PTR(section
));
53 address
= new0(Address
, 1);
57 address_init(address
);
59 address
->network
= network
;
61 LIST_APPEND(addresses
, network
->static_addresses
, address
);
64 address
->section
= section
;
65 hashmap_put(network
->addresses_by_section
,
66 UINT_TO_PTR(address
->section
), address
);
75 int address_new_dynamic(Address
**ret
) {
76 _cleanup_address_free_ Address
*address
= NULL
;
78 address
= new0(Address
, 1);
82 address_init(address
);
90 void address_free(Address
*address
) {
94 if (address
->network
) {
95 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
98 hashmap_remove(address
->network
->addresses_by_section
,
99 UINT_TO_PTR(address
->section
));
105 int address_establish(Address
*address
, Link
*link
) {
112 masq
= link
->network
&&
113 link
->network
->ip_masquerade
&&
114 address
->family
== AF_INET
&&
115 address
->scope
< RT_SCOPE_LINK
;
117 /* Add firewall entry if this is requested */
118 if (address
->ip_masquerade_done
!= masq
) {
119 union in_addr_union masked
= address
->in_addr
;
120 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
122 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
124 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
126 address
->ip_masquerade_done
= masq
;
132 int address_release(Address
*address
, Link
*link
) {
138 /* Remove masquerading firewall entry if it was added */
139 if (address
->ip_masquerade_done
) {
140 union in_addr_union masked
= address
->in_addr
;
141 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
143 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
145 log_link_warning_errno(link
, r
, "Failed to disable IP masquerading: %m");
147 address
->ip_masquerade_done
= false;
153 int address_drop(Address
*address
, Link
*link
,
154 sd_netlink_message_handler_t callback
) {
155 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
159 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
161 assert(link
->ifindex
> 0);
162 assert(link
->manager
);
163 assert(link
->manager
->rtnl
);
165 address_release(address
, link
);
167 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
168 link
->ifindex
, address
->family
);
170 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
172 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
174 return log_error_errno(r
, "Could not set prefixlen: %m");
176 if (address
->family
== AF_INET
)
177 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
178 else if (address
->family
== AF_INET6
)
179 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
181 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
183 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
185 return log_error_errno(r
, "Could not send rtnetlink message: %m");
192 int address_update(Address
*address
, Link
*link
,
193 sd_netlink_message_handler_t callback
) {
194 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
198 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
199 assert(link
->ifindex
> 0);
200 assert(link
->manager
);
201 assert(link
->manager
->rtnl
);
203 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
204 link
->ifindex
, address
->family
);
206 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
208 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
210 return log_error_errno(r
, "Could not set prefixlen: %m");
212 address
->flags
|= IFA_F_PERMANENT
;
214 r
= sd_rtnl_message_addr_set_flags(req
, address
->flags
& 0xff);
216 return log_error_errno(r
, "Could not set flags: %m");
218 if (address
->flags
& ~0xff && link
->rtnl_extended_attrs
) {
219 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
221 return log_error_errno(r
, "Could not set extended flags: %m");
224 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
226 return log_error_errno(r
, "Could not set scope: %m");
228 if (address
->family
== AF_INET
)
229 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
230 else if (address
->family
== AF_INET6
)
231 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
233 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
235 if (address
->family
== AF_INET
) {
236 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
238 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
241 if (address
->label
) {
242 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
244 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
247 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
, &address
->cinfo
);
249 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
251 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
253 return log_error_errno(r
, "Could not send rtnetlink message: %m");
260 static int address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
261 union in_addr_union in_addr
= {};
262 struct in_addr broadcast
= {};
263 _cleanup_address_free_ Address
*na
= NULL
;
270 /* Something useful was configured? just use it */
271 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
274 /* The address is configured to be 0.0.0.0 or [::] by the user?
275 * Then let's acquire something more useful from the pool. */
276 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
278 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
280 log_link_error(link
, "Couldn't find free address for interface, all taken.");
284 if (original
->family
== AF_INET
) {
285 /* Pick first address in range for ourselves ... */
286 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
288 /* .. and use last as broadcast address */
289 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
290 } else if (original
->family
== AF_INET6
)
291 in_addr
.in6
.s6_addr
[15] |= 1;
293 r
= address_new_dynamic(&na
);
297 na
->family
= original
->family
;
298 na
->prefixlen
= original
->prefixlen
;
299 na
->scope
= original
->scope
;
300 na
->cinfo
= original
->cinfo
;
302 if (original
->label
) {
303 na
->label
= strdup(original
->label
);
308 na
->broadcast
= broadcast
;
309 na
->in_addr
= in_addr
;
311 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
319 int address_configure(Address
*address
, Link
*link
,
320 sd_netlink_message_handler_t callback
) {
321 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
325 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
327 assert(link
->ifindex
> 0);
328 assert(link
->manager
);
329 assert(link
->manager
->rtnl
);
331 r
= address_acquire(link
, address
, &address
);
335 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
336 link
->ifindex
, address
->family
);
338 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
340 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
342 return log_error_errno(r
, "Could not set prefixlen: %m");
344 address
->flags
|= IFA_F_PERMANENT
;
346 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
348 return log_error_errno(r
, "Could not set flags: %m");
350 if (address
->flags
& ~0xff) {
351 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
353 return log_error_errno(r
, "Could not set extended flags: %m");
356 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
358 return log_error_errno(r
, "Could not set scope: %m");
360 if (address
->family
== AF_INET
)
361 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
362 else if (address
->family
== AF_INET6
)
363 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
365 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
367 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
368 if (address
->family
== AF_INET
)
369 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
370 else if (address
->family
== AF_INET6
)
371 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
373 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
375 if (address
->family
== AF_INET
) {
376 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
378 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
382 if (address
->label
) {
383 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
385 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
388 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
391 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
393 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
395 return log_error_errno(r
, "Could not send rtnetlink message: %m");
399 address_establish(address
, link
);
404 int config_parse_broadcast(
406 const char *filename
,
409 unsigned section_line
,
416 Network
*network
= userdata
;
417 _cleanup_address_free_ Address
*n
= NULL
;
426 r
= address_new_static(network
, section_line
, &n
);
430 if (n
->family
== AF_INET6
) {
431 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
432 "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
436 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
438 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
439 "Broadcast is invalid, ignoring assignment: %s", rvalue
);
449 int config_parse_address(const char *unit
,
450 const char *filename
,
453 unsigned section_line
,
460 Network
*network
= userdata
;
461 _cleanup_address_free_ Address
*n
= NULL
;
462 const char *address
, *e
;
463 union in_addr_union buffer
;
472 if (streq(section
, "Network")) {
473 /* we are not in an Address section, so treat
474 * this as the special '0' section */
478 r
= address_new_static(network
, section_line
, &n
);
482 /* Address=address/prefixlen */
485 e
= strchr(rvalue
, '/');
488 r
= safe_atou(e
+ 1, &i
);
490 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
491 "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
495 n
->prefixlen
= (unsigned char) i
;
497 address
= strndupa(rvalue
, e
- rvalue
);
501 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
503 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
504 "Address is invalid, ignoring assignment: %s", address
);
508 if (!e
&& f
== AF_INET
) {
509 r
= in_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
511 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
512 "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address
);
517 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
518 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
519 "Address is incompatible, ignoring assignment: %s", address
);
525 if (streq(lvalue
, "Address"))
528 n
->in_addr_peer
= buffer
;
530 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
531 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
538 int config_parse_label(const char *unit
,
539 const char *filename
,
542 unsigned section_line
,
548 Network
*network
= userdata
;
549 _cleanup_address_free_ Address
*n
= NULL
;
559 r
= address_new_static(network
, section_line
, &n
);
563 label
= strdup(rvalue
);
567 if (!ascii_is_valid(label
) || strlen(label
) >= IFNAMSIZ
) {
568 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
569 "Interface label is not ASCII clean or is too"
570 " long, ignoring assignment: %s", rvalue
);
588 bool address_equal(Address
*a1
, Address
*a2
) {
593 /* one, but not both, is NULL */
597 if (a1
->family
!= a2
->family
)
600 switch (a1
->family
) {
601 /* use the same notion of equality as the kernel does */
606 if (a1
->prefixlen
!= a2
->prefixlen
)
608 else if (a1
->prefixlen
== 0)
609 /* make sure we don't try to shift by 32.
610 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
615 b1
= be32toh(a1
->in_addr
.in
.s_addr
);
616 b2
= be32toh(a2
->in_addr
.in
.s_addr
);
618 return (b1
>> (32 - a1
->prefixlen
)) == (b2
>> (32 - a1
->prefixlen
));
624 b1
= (uint64_t*)&a1
->in_addr
.in6
;
625 b2
= (uint64_t*)&a2
->in_addr
.in6
;
627 return (((b1
[0] ^ b2
[0]) | (b1
[1] ^ b2
[1])) == 0UL);
631 assert_not_reached("Invalid address family");