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"
28 #include "network-internal.h"
30 #include "networkd-link.h"
32 static void address_init(Address *address) {
35 address->family = AF_UNSPEC;
36 address->scope = RT_SCOPE_UNIVERSE;
37 address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
38 address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
41 int address_new_static(Network *network, unsigned section, Address **ret) {
42 _cleanup_address_free_ Address *address = NULL;
45 address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
54 address = new0(Address, 1);
58 address_init(address);
60 address->network = network;
62 LIST_APPEND(addresses, network->static_addresses, address);
65 address->section = section;
66 hashmap_put(network->addresses_by_section,
67 UINT_TO_PTR(address->section), address);
76 int address_new_dynamic(Address **ret) {
77 _cleanup_address_free_ Address *address = NULL;
79 address = new0(Address, 1);
83 address_init(address);
91 void address_free(Address *address) {
95 if (address->network) {
96 LIST_REMOVE(addresses, address->network->static_addresses, address);
99 hashmap_remove(address->network->addresses_by_section,
100 UINT_TO_PTR(address->section));
106 int address_establish(Address *address, Link *link) {
113 masq = link->network &&
114 link->network->ip_masquerade &&
115 address->family == AF_INET &&
116 address->scope < RT_SCOPE_LINK;
118 /* Add firewall entry if this is requested */
119 if (address->ip_masquerade_done != masq) {
120 union in_addr_union masked = address->in_addr;
121 in_addr_mask(address->family, &masked, address->prefixlen);
123 r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
125 log_link_warning_errno(link, r, "Could not enable IP masquerading: %m");
127 address->ip_masquerade_done = masq;
133 int address_release(Address *address, Link *link) {
139 /* Remove masquerading firewall entry if it was added */
140 if (address->ip_masquerade_done) {
141 union in_addr_union masked = address->in_addr;
142 in_addr_mask(address->family, &masked, address->prefixlen);
144 r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
146 log_link_warning_errno(link, r, "Failed to disable IP masquerading: %m");
148 address->ip_masquerade_done = false;
154 int address_drop(Address *address, Link *link,
155 sd_rtnl_message_handler_t callback) {
156 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
160 assert(address->family == AF_INET || address->family == AF_INET6);
162 assert(link->ifindex > 0);
163 assert(link->manager);
164 assert(link->manager->rtnl);
166 address_release(address, link);
168 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
169 link->ifindex, address->family);
171 return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m");
173 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
175 return log_error_errno(r, "Could not set prefixlen: %m");
177 if (address->family == AF_INET)
178 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
179 else if (address->family == AF_INET6)
180 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
182 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
184 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
186 return log_error_errno(r, "Could not send rtnetlink message: %m");
193 int address_update(Address *address, Link *link,
194 sd_rtnl_message_handler_t callback) {
195 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
199 assert(address->family == AF_INET || address->family == AF_INET6);
200 assert(link->ifindex > 0);
201 assert(link->manager);
202 assert(link->manager->rtnl);
204 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
205 link->ifindex, address->family);
207 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
209 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
211 return log_error_errno(r, "Could not set prefixlen: %m");
213 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
215 return log_error_errno(r, "Could not set flags: %m");
217 r = sd_rtnl_message_addr_set_scope(req, address->scope);
219 return log_error_errno(r, "Could not set scope: %m");
221 if (address->family == AF_INET)
222 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
223 else if (address->family == AF_INET6)
224 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
226 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
228 if (address->family == AF_INET) {
229 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
231 return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
234 if (address->label) {
235 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
237 return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
240 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
242 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
244 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
246 return log_error_errno(r, "Could not send rtnetlink message: %m");
253 static int address_acquire(Link *link, Address *original, Address **ret) {
254 union in_addr_union in_addr = {};
255 struct in_addr broadcast = {};
256 _cleanup_address_free_ Address *na = NULL;
263 /* Something useful was configured? just use it */
264 if (in_addr_is_null(original->family, &original->in_addr) <= 0)
267 /* The address is configured to be 0.0.0.0 or [::] by the user?
268 * Then let's acquire something more useful from the pool. */
269 r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
271 log_link_error(link, "Failed to acquire address from pool: %s", strerror(-r));
275 log_link_error(link, "Couldn't find free address for interface, all taken.");
279 if (original->family == AF_INET) {
280 /* Pick first address in range for ourselves ... */
281 in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
283 /* .. and use last as broadcast address */
284 broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
285 } else if (original->family == AF_INET6)
286 in_addr.in6.s6_addr[15] |= 1;
288 r = address_new_dynamic(&na);
292 na->family = original->family;
293 na->prefixlen = original->prefixlen;
294 na->scope = original->scope;
295 na->cinfo = original->cinfo;
297 if (original->label) {
298 na->label = strdup(original->label);
303 na->broadcast = broadcast;
304 na->in_addr = in_addr;
306 LIST_PREPEND(addresses, link->pool_addresses, na);
314 int address_configure(Address *address, Link *link,
315 sd_rtnl_message_handler_t callback) {
316 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
320 assert(address->family == AF_INET || address->family == AF_INET6);
322 assert(link->ifindex > 0);
323 assert(link->manager);
324 assert(link->manager->rtnl);
326 r = address_acquire(link, address, &address);
330 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
331 link->ifindex, address->family);
333 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
335 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
337 return log_error_errno(r, "Could not set prefixlen: %m");
339 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
341 return log_error_errno(r, "Could not set flags: %m");
343 r = sd_rtnl_message_addr_set_scope(req, address->scope);
345 return log_error_errno(r, "Could not set scope: %m");
347 if (address->family == AF_INET)
348 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
349 else if (address->family == AF_INET6)
350 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
352 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
354 if (!in_addr_is_null(address->family, &address->in_addr_peer)) {
355 if (address->family == AF_INET)
356 r = sd_rtnl_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in);
357 else if (address->family == AF_INET6)
358 r = sd_rtnl_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6);
360 return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
362 if (address->family == AF_INET) {
363 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
365 return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
369 if (address->label) {
370 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
372 return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
375 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO,
378 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
380 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
382 return log_error_errno(r, "Could not send rtnetlink message: %m");
386 address_establish(address, link);
391 int config_parse_broadcast(
393 const char *filename,
396 unsigned section_line,
403 Network *network = userdata;
404 _cleanup_address_free_ Address *n = NULL;
413 r = address_new_static(network, section_line, &n);
417 if (n->family == AF_INET6) {
418 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
419 "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
423 r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast);
425 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
426 "Broadcast is invalid, ignoring assignment: %s", rvalue);
436 int config_parse_address(const char *unit,
437 const char *filename,
440 unsigned section_line,
447 Network *network = userdata;
448 _cleanup_address_free_ Address *n = NULL;
449 const char *address, *e;
450 union in_addr_union buffer;
459 if (streq(section, "Network")) {
460 /* we are not in an Address section, so treat
461 * this as the special '0' section */
465 r = address_new_static(network, section_line, &n);
469 /* Address=address/prefixlen */
472 e = strchr(rvalue, '/');
475 r = safe_atou(e + 1, &i);
477 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
478 "Prefix length is invalid, ignoring assignment: %s", e + 1);
482 n->prefixlen = (unsigned char) i;
484 address = strndupa(rvalue, e - rvalue);
488 r = in_addr_from_string_auto(address, &f, &buffer);
490 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
491 "Address is invalid, ignoring assignment: %s", address);
495 if (!e && f == AF_INET) {
496 r = in_addr_default_prefixlen(&buffer.in, &n->prefixlen);
498 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
499 "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address);
504 if (n->family != AF_UNSPEC && f != n->family) {
505 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
506 "Address is incompatible, ignoring assignment: %s", address);
512 if (streq(lvalue, "Address"))
515 n->in_addr_peer = buffer;
517 if (n->family == AF_INET && n->broadcast.s_addr == 0)
518 n->broadcast.s_addr = n->in_addr.in.s_addr | htonl(0xfffffffflu >> n->prefixlen);
525 int config_parse_label(const char *unit,
526 const char *filename,
529 unsigned section_line,
535 Network *network = userdata;
536 _cleanup_address_free_ Address *n = NULL;
546 r = address_new_static(network, section_line, &n);
550 label = strdup(rvalue);
554 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
555 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
556 "Interface label is not ASCII clean or is too"
557 " long, ignoring assignment: %s", rvalue);
575 bool address_equal(Address *a1, Address *a2) {
580 /* one, but not both, is NULL */
584 if (a1->family != a2->family)
587 switch (a1->family) {
588 /* use the same notion of equality as the kernel does */
593 if (a1->prefixlen != a2->prefixlen)
598 b1 = be32toh(a1->in_addr.in.s_addr);
599 b2 = be32toh(a2->in_addr.in.s_addr);
601 return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
607 b1 = (uint64_t*)&a1->in_addr.in6;
608 b2 = (uint64_t*)&a2->in_addr.in6;
610 return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
614 assert_not_reached("Invalid address family");