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"
27 #include "firewall-util.h"
28 #include "netlink-util.h"
31 #include "networkd-address.h"
33 static void address_init(Address
*address
) {
36 address
->family
= AF_UNSPEC
;
37 address
->scope
= RT_SCOPE_UNIVERSE
;
38 address
->cinfo
.ifa_prefered
= CACHE_INFO_INFINITY_LIFE_TIME
;
39 address
->cinfo
.ifa_valid
= CACHE_INFO_INFINITY_LIFE_TIME
;
42 int address_new_static(Network
*network
, unsigned section
, Address
**ret
) {
43 _cleanup_address_free_ Address
*address
= NULL
;
46 address
= hashmap_get(network
->addresses_by_section
, UINT_TO_PTR(section
));
55 address
= new0(Address
, 1);
59 address_init(address
);
61 address
->network
= network
;
63 LIST_APPEND(addresses
, network
->static_addresses
, address
);
66 address
->section
= section
;
67 hashmap_put(network
->addresses_by_section
,
68 UINT_TO_PTR(address
->section
), address
);
77 int address_new_dynamic(Address
**ret
) {
78 _cleanup_address_free_ Address
*address
= NULL
;
80 address
= new0(Address
, 1);
84 address_init(address
);
92 void address_free(Address
*address
) {
96 if (address
->network
) {
97 LIST_REMOVE(addresses
, address
->network
->static_addresses
, address
);
100 hashmap_remove(address
->network
->addresses_by_section
,
101 UINT_TO_PTR(address
->section
));
107 int address_establish(Address
*address
, Link
*link
) {
114 masq
= link
->network
&&
115 link
->network
->ip_masquerade
&&
116 address
->family
== AF_INET
&&
117 address
->scope
< RT_SCOPE_LINK
;
119 /* Add firewall entry if this is requested */
120 if (address
->ip_masquerade_done
!= masq
) {
121 union in_addr_union masked
= address
->in_addr
;
122 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
124 r
= fw_add_masquerade(masq
, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
126 log_link_warning_errno(link
, r
, "Could not enable IP masquerading: %m");
128 address
->ip_masquerade_done
= masq
;
134 int address_release(Address
*address
, Link
*link
) {
140 /* Remove masquerading firewall entry if it was added */
141 if (address
->ip_masquerade_done
) {
142 union in_addr_union masked
= address
->in_addr
;
143 in_addr_mask(address
->family
, &masked
, address
->prefixlen
);
145 r
= fw_add_masquerade(false, AF_INET
, 0, &masked
, address
->prefixlen
, NULL
, NULL
, 0);
147 log_link_warning_errno(link
, r
, "Failed to disable IP masquerading: %m");
149 address
->ip_masquerade_done
= false;
155 int address_drop(Address
*address
, Link
*link
,
156 sd_netlink_message_handler_t callback
) {
157 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
161 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
163 assert(link
->ifindex
> 0);
164 assert(link
->manager
);
165 assert(link
->manager
->rtnl
);
167 address_release(address
, link
);
169 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_DELADDR
,
170 link
->ifindex
, address
->family
);
172 return log_error_errno(r
, "Could not allocate RTM_DELADDR message: %m");
174 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
176 return log_error_errno(r
, "Could not set prefixlen: %m");
178 if (address
->family
== AF_INET
)
179 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
180 else if (address
->family
== AF_INET6
)
181 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
183 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
185 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
187 return log_error_errno(r
, "Could not send rtnetlink message: %m");
194 int address_update(Address
*address
, Link
*link
,
195 sd_netlink_message_handler_t callback
) {
196 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
200 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
201 assert(link
->ifindex
> 0);
202 assert(link
->manager
);
203 assert(link
->manager
->rtnl
);
205 r
= sd_rtnl_message_new_addr_update(link
->manager
->rtnl
, &req
,
206 link
->ifindex
, address
->family
);
208 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
210 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
212 return log_error_errno(r
, "Could not set prefixlen: %m");
214 address
->flags
|= IFA_F_PERMANENT
;
216 r
= sd_rtnl_message_addr_set_flags(req
, address
->flags
& 0xff);
218 return log_error_errno(r
, "Could not set flags: %m");
220 if (address
->flags
& ~0xff && link
->rtnl_extended_attrs
) {
221 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
223 return log_error_errno(r
, "Could not set extended flags: %m");
226 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
228 return log_error_errno(r
, "Could not set scope: %m");
230 if (address
->family
== AF_INET
)
231 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
232 else if (address
->family
== AF_INET6
)
233 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
235 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
237 if (address
->family
== AF_INET
) {
238 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
240 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
243 if (address
->label
) {
244 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
246 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
249 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
, &address
->cinfo
);
251 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
253 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
255 return log_error_errno(r
, "Could not send rtnetlink message: %m");
262 static int address_acquire(Link
*link
, Address
*original
, Address
**ret
) {
263 union in_addr_union in_addr
= {};
264 struct in_addr broadcast
= {};
265 _cleanup_address_free_ Address
*na
= NULL
;
272 /* Something useful was configured? just use it */
273 if (in_addr_is_null(original
->family
, &original
->in_addr
) <= 0)
276 /* The address is configured to be 0.0.0.0 or [::] by the user?
277 * Then let's acquire something more useful from the pool. */
278 r
= manager_address_pool_acquire(link
->manager
, original
->family
, original
->prefixlen
, &in_addr
);
280 return log_link_error_errno(link
, r
, "Failed to acquire address from pool: %m");
282 log_link_error(link
, "Couldn't find free address for interface, all taken.");
286 if (original
->family
== AF_INET
) {
287 /* Pick first address in range for ourselves ... */
288 in_addr
.in
.s_addr
= in_addr
.in
.s_addr
| htobe32(1);
290 /* .. and use last as broadcast address */
291 broadcast
.s_addr
= in_addr
.in
.s_addr
| htobe32(0xFFFFFFFFUL
>> original
->prefixlen
);
292 } else if (original
->family
== AF_INET6
)
293 in_addr
.in6
.s6_addr
[15] |= 1;
295 r
= address_new_dynamic(&na
);
299 na
->family
= original
->family
;
300 na
->prefixlen
= original
->prefixlen
;
301 na
->scope
= original
->scope
;
302 na
->cinfo
= original
->cinfo
;
304 if (original
->label
) {
305 na
->label
= strdup(original
->label
);
310 na
->broadcast
= broadcast
;
311 na
->in_addr
= in_addr
;
313 LIST_PREPEND(addresses
, link
->pool_addresses
, na
);
321 int address_configure(Address
*address
, Link
*link
,
322 sd_netlink_message_handler_t callback
) {
323 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
327 assert(address
->family
== AF_INET
|| address
->family
== AF_INET6
);
329 assert(link
->ifindex
> 0);
330 assert(link
->manager
);
331 assert(link
->manager
->rtnl
);
333 r
= address_acquire(link
, address
, &address
);
337 r
= sd_rtnl_message_new_addr(link
->manager
->rtnl
, &req
, RTM_NEWADDR
,
338 link
->ifindex
, address
->family
);
340 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
342 r
= sd_rtnl_message_addr_set_prefixlen(req
, address
->prefixlen
);
344 return log_error_errno(r
, "Could not set prefixlen: %m");
346 address
->flags
|= IFA_F_PERMANENT
;
348 r
= sd_rtnl_message_addr_set_flags(req
, (address
->flags
& 0xff));
350 return log_error_errno(r
, "Could not set flags: %m");
352 if (address
->flags
& ~0xff) {
353 r
= sd_netlink_message_append_u32(req
, IFA_FLAGS
, address
->flags
);
355 return log_error_errno(r
, "Could not set extended flags: %m");
358 r
= sd_rtnl_message_addr_set_scope(req
, address
->scope
);
360 return log_error_errno(r
, "Could not set scope: %m");
362 if (address
->family
== AF_INET
)
363 r
= sd_netlink_message_append_in_addr(req
, IFA_LOCAL
, &address
->in_addr
.in
);
364 else if (address
->family
== AF_INET6
)
365 r
= sd_netlink_message_append_in6_addr(req
, IFA_LOCAL
, &address
->in_addr
.in6
);
367 return log_error_errno(r
, "Could not append IFA_LOCAL attribute: %m");
369 if (!in_addr_is_null(address
->family
, &address
->in_addr_peer
)) {
370 if (address
->family
== AF_INET
)
371 r
= sd_netlink_message_append_in_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in
);
372 else if (address
->family
== AF_INET6
)
373 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &address
->in_addr_peer
.in6
);
375 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
377 if (address
->family
== AF_INET
) {
378 r
= sd_netlink_message_append_in_addr(req
, IFA_BROADCAST
, &address
->broadcast
);
380 return log_error_errno(r
, "Could not append IFA_BROADCAST attribute: %m");
384 if (address
->label
) {
385 r
= sd_netlink_message_append_string(req
, IFA_LABEL
, address
->label
);
387 return log_error_errno(r
, "Could not append IFA_LABEL attribute: %m");
390 r
= sd_netlink_message_append_cache_info(req
, IFA_CACHEINFO
,
393 return log_error_errno(r
, "Could not append IFA_CACHEINFO attribute: %m");
395 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
397 return log_error_errno(r
, "Could not send rtnetlink message: %m");
401 address_establish(address
, link
);
406 int config_parse_broadcast(
408 const char *filename
,
411 unsigned section_line
,
418 Network
*network
= userdata
;
419 _cleanup_address_free_ Address
*n
= NULL
;
428 r
= address_new_static(network
, section_line
, &n
);
432 if (n
->family
== AF_INET6
) {
433 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
437 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
439 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "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
, '/');
489 r
= safe_atou(e
+ 1, &i
);
491 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "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
, r
, "Address is invalid, ignoring assignment: %s", address
);
507 if (!e
&& f
== AF_INET
) {
508 r
= in_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
510 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
);
515 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
516 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Address is incompatible, ignoring assignment: %s", address
);
522 if (streq(lvalue
, "Address"))
525 n
->in_addr_peer
= buffer
;
527 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
528 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
535 int config_parse_label(const char *unit
,
536 const char *filename
,
539 unsigned section_line
,
545 Network
*network
= userdata
;
546 _cleanup_address_free_ Address
*n
= NULL
;
556 r
= address_new_static(network
, section_line
, &n
);
560 label
= strdup(rvalue
);
564 if (!ascii_is_valid(label
) || strlen(label
) >= IFNAMSIZ
) {
565 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface label is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
583 bool address_equal(Address
*a1
, Address
*a2
) {
588 /* one, but not both, is NULL */
592 if (a1
->family
!= a2
->family
)
595 switch (a1
->family
) {
596 /* use the same notion of equality as the kernel does */
601 if (a1
->prefixlen
!= a2
->prefixlen
)
603 else if (a1
->prefixlen
== 0)
604 /* make sure we don't try to shift by 32.
605 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
610 b1
= be32toh(a1
->in_addr
.in
.s_addr
);
611 b2
= be32toh(a2
->in_addr
.in
.s_addr
);
613 return (b1
>> (32 - a1
->prefixlen
)) == (b2
>> (32 - a1
->prefixlen
));
619 b1
= (uint64_t*)&a1
->in_addr
.in6
;
620 b2
= (uint64_t*)&a2
->in_addr
.in6
;
622 return (((b1
[0] ^ b2
[0]) | (b1
[1] ^ b2
[1])) == 0UL);
626 assert_not_reached("Invalid address family");