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/>.
28 #include "conf-parser.h"
29 #include "network-internal.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_PREPEND(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_drop(Address *address, Link *link,
106 sd_rtnl_message_handler_t callback) {
107 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
111 assert(address->family == AF_INET || address->family == AF_INET6);
113 assert(link->ifindex > 0);
114 assert(link->manager);
115 assert(link->manager->rtnl);
117 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
118 link->ifindex, address->family);
120 log_error("Could not allocate RTM_DELADDR message: %s",
125 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
127 log_error("Could not set prefixlen: %s", strerror(-r));
131 if (address->family == AF_INET)
132 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
133 else if (address->family == AF_INET6)
134 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
136 log_error("Could not append IFA_LOCAL attribute: %s",
141 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
143 log_error("Could not send rtnetlink message: %s", strerror(-r));
152 int address_update(Address *address, Link *link,
153 sd_rtnl_message_handler_t callback) {
154 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
158 assert(address->family == AF_INET || address->family == AF_INET6);
159 assert(link->ifindex > 0);
160 assert(link->manager);
161 assert(link->manager->rtnl);
163 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
164 link->ifindex, address->family);
166 log_error("Could not allocate RTM_NEWADDR message: %s",
171 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
173 log_error("Could not set prefixlen: %s", strerror(-r));
177 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
179 log_error("Could not set flags: %s", strerror(-r));
183 r = sd_rtnl_message_addr_set_scope(req, address->scope);
185 log_error("Could not set scope: %s", strerror(-r));
189 if (address->family == AF_INET)
190 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
191 else if (address->family == AF_INET6)
192 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
194 log_error("Could not append IFA_LOCAL attribute: %s",
199 if (address->family == AF_INET) {
200 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
202 log_error("Could not append IFA_BROADCAST attribute: %s",
208 if (address->label) {
209 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
211 log_error("Could not append IFA_LABEL attribute: %s",
217 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
219 log_error("Could not append IFA_CACHEINFO attribute: %s",
224 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
226 log_error("Could not send rtnetlink message: %s", strerror(-r));
235 static int address_acquire(Link *link, Address *original, Address **ret) {
236 union in_addr_union in_addr = {};
237 struct in_addr broadcast = {};
238 _cleanup_address_free_ Address *na = NULL;
245 /* Something useful was configured? just use it */
246 if (in_addr_is_null(original->family, &original->in_addr) <= 0)
249 /* The address is configured to be 0.0.0.0 or [::] by the user?
250 * Then let's acquire something more useful from the pool. */
251 r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
253 log_error_link(link, "Failed to acquire address from pool: %s", strerror(-r));
257 log_error_link(link, "Couldn't find free address for interface, all taken.");
261 if (original->family == AF_INET) {
262 /* Pick first address in range for ourselves ...*/
263 in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
265 /* .. and use last as broadcast address */
266 broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
267 } else if (original->family == AF_INET6)
268 in_addr.in6.s6_addr[15] |= 1;
270 r = address_new_dynamic(&na);
274 na->family = original->family;
275 na->prefixlen = original->prefixlen;
276 na->scope = original->scope;
277 na->cinfo = original->cinfo;
279 if (original->label) {
280 na->label = strdup(original->label);
285 na->broadcast = broadcast;
286 na->in_addr = in_addr;
288 LIST_PREPEND(addresses, link->pool_addresses, na);
296 int address_configure(Address *address, Link *link,
297 sd_rtnl_message_handler_t callback) {
298 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
302 assert(address->family == AF_INET || address->family == AF_INET6);
304 assert(link->ifindex > 0);
305 assert(link->manager);
306 assert(link->manager->rtnl);
308 r = address_acquire(link, address, &address);
312 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
313 link->ifindex, address->family);
315 log_error("Could not allocate RTM_NEWADDR message: %s",
320 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
322 log_error("Could not set prefixlen: %s", strerror(-r));
326 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
328 log_error("Could not set flags: %s", strerror(-r));
332 r = sd_rtnl_message_addr_set_scope(req, address->scope);
334 log_error("Could not set scope: %s", strerror(-r));
338 if (address->family == AF_INET)
339 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
340 else if (address->family == AF_INET6)
341 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
343 log_error("Could not append IFA_LOCAL attribute: %s",
348 if (!in_addr_is_null(address->family, &address->in_addr_peer)) {
349 if (address->family == AF_INET)
350 r = sd_rtnl_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in);
351 else if (address->family == AF_INET6)
352 r = sd_rtnl_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6);
354 log_error("Could not append IFA_ADDRESS attribute: %s",
359 if (address->family == AF_INET) {
360 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
362 log_error("Could not append IFA_BROADCAST attribute: %s",
369 if (address->label) {
370 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
372 log_error("Could not append IFA_LABEL attribute: %s",
378 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO,
381 log_error("Could not append IFA_CACHEINFO attribute: %s",
386 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
388 log_error("Could not send rtnetlink message: %s", strerror(-r));
397 int config_parse_broadcast(const char *unit,
398 const char *filename,
401 unsigned section_line,
407 Network *network = userdata;
408 _cleanup_address_free_ Address *n = NULL;
409 _cleanup_free_ char *address = NULL;
418 r = address_new_static(network, section_line, &n);
422 if (n->family == AF_INET6) {
423 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
424 "Broadcast is not valid for IPv6 addresses, "
425 "ignoring assignment: %s", address);
429 r = net_parse_inaddr(address, &n->family, &n->broadcast);
431 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
432 "Broadcast is invalid, ignoring assignment: %s", address);
441 int config_parse_address(const char *unit,
442 const char *filename,
445 unsigned section_line,
451 Network *network = userdata;
452 _cleanup_address_free_ Address *n = NULL;
453 _cleanup_free_ char *address = NULL;
454 union in_addr_union *addr;
464 if (streq(section, "Network")) {
465 /* we are not in an Address section, so treat
466 * this as the special '0' section */
470 r = address_new_static(network, section_line, &n);
474 if (streq(lvalue, "Address"))
477 addr = &n->in_addr_peer;
479 /* Address=address/prefixlen */
482 e = strchr(rvalue, '/');
485 r = safe_atou(e + 1, &i);
487 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
488 "Interface prefix length is invalid, "
489 "ignoring assignment: %s", e + 1);
493 n->prefixlen = (unsigned char) i;
495 address = strndup(rvalue, e - rvalue);
499 address = strdup(rvalue);
504 r = net_parse_inaddr(address, &n->family, addr);
506 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
507 "Address is invalid, ignoring assignment: %s", address);
511 if (n->family == AF_INET && !n->broadcast.s_addr)
512 n->broadcast.s_addr = n->in_addr.in.s_addr |
513 htonl(0xfffffffflu >> n->prefixlen);
520 int config_parse_label(const char *unit,
521 const char *filename,
524 unsigned section_line,
530 Network *network = userdata;
531 _cleanup_address_free_ Address *n = NULL;
541 r = address_new_static(network, section_line, &n);
545 label = strdup(rvalue);
549 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
550 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
551 "Interface label is not ASCII clean or is too"
552 " long, ignoring assignment: %s", rvalue);
570 bool address_equal(Address *a1, Address *a2) {
575 /* one, but not both, is NULL */
579 if (a1->family != a2->family)
582 switch (a1->family) {
583 /* use the same notion of equality as the kernel does */
588 if (a1->prefixlen != a2->prefixlen)
593 b1 = be32toh(a1->in_addr.in.s_addr);
594 b2 = be32toh(a2->in_addr.in.s_addr);
596 return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
603 b1 = (uint64_t*)&a1->in_addr.in6;
604 b2 = (uint64_t*)&a2->in_addr.in6;
606 return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
609 assert_not_reached("Invalid address family");