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
, EINVAL
,
434 "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue
);
438 r
= in_addr_from_string(AF_INET
, rvalue
, (union in_addr_union
*) &n
->broadcast
);
440 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
441 "Broadcast is invalid, ignoring assignment: %s", rvalue
);
451 int config_parse_address(const char *unit
,
452 const char *filename
,
455 unsigned section_line
,
462 Network
*network
= userdata
;
463 _cleanup_address_free_ Address
*n
= NULL
;
464 const char *address
, *e
;
465 union in_addr_union buffer
;
474 if (streq(section
, "Network")) {
475 /* we are not in an Address section, so treat
476 * this as the special '0' section */
480 r
= address_new_static(network
, section_line
, &n
);
484 /* Address=address/prefixlen */
487 e
= strchr(rvalue
, '/');
490 r
= safe_atou(e
+ 1, &i
);
492 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
493 "Prefix length is invalid, ignoring assignment: %s", e
+ 1);
497 n
->prefixlen
= (unsigned char) i
;
499 address
= strndupa(rvalue
, e
- rvalue
);
503 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
505 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
506 "Address is invalid, ignoring assignment: %s", address
);
510 if (!e
&& f
== AF_INET
) {
511 r
= in_addr_default_prefixlen(&buffer
.in
, &n
->prefixlen
);
513 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
514 "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address
);
519 if (n
->family
!= AF_UNSPEC
&& f
!= n
->family
) {
520 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
521 "Address is incompatible, ignoring assignment: %s", address
);
527 if (streq(lvalue
, "Address"))
530 n
->in_addr_peer
= buffer
;
532 if (n
->family
== AF_INET
&& n
->broadcast
.s_addr
== 0)
533 n
->broadcast
.s_addr
= n
->in_addr
.in
.s_addr
| htonl(0xfffffffflu
>> n
->prefixlen
);
540 int config_parse_label(const char *unit
,
541 const char *filename
,
544 unsigned section_line
,
550 Network
*network
= userdata
;
551 _cleanup_address_free_ Address
*n
= NULL
;
561 r
= address_new_static(network
, section_line
, &n
);
565 label
= strdup(rvalue
);
569 if (!ascii_is_valid(label
) || strlen(label
) >= IFNAMSIZ
) {
570 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
571 "Interface label is not ASCII clean or is too"
572 " long, ignoring assignment: %s", rvalue
);
590 bool address_equal(Address
*a1
, Address
*a2
) {
595 /* one, but not both, is NULL */
599 if (a1
->family
!= a2
->family
)
602 switch (a1
->family
) {
603 /* use the same notion of equality as the kernel does */
608 if (a1
->prefixlen
!= a2
->prefixlen
)
610 else if (a1
->prefixlen
== 0)
611 /* make sure we don't try to shift by 32.
612 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
617 b1
= be32toh(a1
->in_addr
.in
.s_addr
);
618 b2
= be32toh(a2
->in_addr
.in
.s_addr
);
620 return (b1
>> (32 - a1
->prefixlen
)) == (b2
>> (32 - a1
->prefixlen
));
626 b1
= (uint64_t*)&a1
->in_addr
.in6
;
627 b2
= (uint64_t*)&a2
->in_addr
.in6
;
629 return (((b1
[0] ^ b2
[0]) | (b1
[1] ^ b2
[1])) == 0UL);
633 assert_not_reached("Invalid address family");