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_rtnl_message_handler_t callback) {
155 _cleanup_rtnl_message_unref_ sd_rtnl_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_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
178 else if (address->family == AF_INET6)
179 r = sd_rtnl_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_rtnl_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_rtnl_message_handler_t callback) {
194 _cleanup_rtnl_message_unref_ sd_rtnl_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) {
219 r = sd_rtnl_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_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
230 else if (address->family == AF_INET6)
231 r = sd_rtnl_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_rtnl_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_rtnl_message_append_string(req, IFA_LABEL, address->label);
244 return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
247 r = sd_rtnl_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_rtnl_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 log_link_error(link, "Failed to acquire address from pool: %s", strerror(-r));
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_rtnl_message_handler_t callback) {
323 _cleanup_rtnl_message_unref_ sd_rtnl_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_rtnl_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_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
364 else if (address->family == AF_INET6)
365 r = sd_rtnl_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_rtnl_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in);
372 else if (address->family == AF_INET6)
373 r = sd_rtnl_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_rtnl_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_rtnl_message_append_string(req, IFA_LABEL, address->label);
387 return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
390 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO,
393 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
395 r = sd_rtnl_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");