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 uint64_t key = section;
45 address = hashmap_get(network->addresses_by_section, &key);
54 address = new0(Address, 1);
58 address_init(address);
60 address->network = network;
62 LIST_PREPEND(addresses, network->static_addresses, address);
65 address->section = section;
66 hashmap_put(network->addresses_by_section, &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,
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));
150 int address_update(Address *address, Link *link,
151 sd_rtnl_message_handler_t callback) {
152 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
156 assert(address->family == AF_INET || address->family == AF_INET6);
157 assert(link->ifindex > 0);
158 assert(link->manager);
159 assert(link->manager->rtnl);
161 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
162 link->ifindex, address->family);
164 log_error("Could not allocate RTM_NEWADDR message: %s",
169 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
171 log_error("Could not set prefixlen: %s", strerror(-r));
175 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
177 log_error("Could not set flags: %s", strerror(-r));
181 r = sd_rtnl_message_addr_set_scope(req, address->scope);
183 log_error("Could not set scope: %s", strerror(-r));
187 if (address->family == AF_INET)
188 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
189 else if (address->family == AF_INET6)
190 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
192 log_error("Could not append IFA_LOCAL attribute: %s",
197 if (address->family == AF_INET) {
198 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
200 log_error("Could not append IFA_BROADCAST attribute: %s",
206 if (address->label) {
207 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
209 log_error("Could not append IFA_LABEL attribute: %s",
215 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
217 log_error("Could not append IFA_CACHEINFO attribute: %s",
222 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
224 log_error("Could not send rtnetlink message: %s", strerror(-r));
231 int address_configure(Address *address, Link *link,
232 sd_rtnl_message_handler_t callback) {
233 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
237 assert(address->family == AF_INET || address->family == AF_INET6);
239 assert(link->ifindex > 0);
240 assert(link->manager);
241 assert(link->manager->rtnl);
243 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
244 link->ifindex, address->family);
246 log_error("Could not allocate RTM_NEWADDR message: %s",
251 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
253 log_error("Could not set prefixlen: %s", strerror(-r));
257 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
259 log_error("Could not set flags: %s", strerror(-r));
263 r = sd_rtnl_message_addr_set_scope(req, address->scope);
265 log_error("Could not set scope: %s", strerror(-r));
269 if (address->family == AF_INET)
270 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
271 else if (address->family == AF_INET6)
272 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
274 log_error("Could not append IFA_LOCAL attribute: %s",
279 if (address->family == AF_INET) {
280 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
282 log_error("Could not append IFA_BROADCAST attribute: %s",
288 if (address->label) {
289 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
291 log_error("Could not append IFA_LABEL attribute: %s",
297 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
299 log_error("Could not send rtnetlink message: %s", strerror(-r));
306 int config_parse_dns(const char *unit,
307 const char *filename,
310 unsigned section_line,
316 Network *network = userdata;
318 _cleanup_address_free_ Address *n = NULL;
327 r = address_new_dynamic(&n);
331 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
333 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
334 "DNS address is invalid, ignoring assignment: %s", rvalue);
338 if (streq(lvalue, "DNS")) {
339 LIST_FIND_TAIL(addresses, network->dns, tail);
340 LIST_INSERT_AFTER(addresses, network->dns, tail, n);
341 } else if (streq(lvalue, "NTP")) {
342 LIST_FIND_TAIL(addresses, network->ntp, tail);
343 LIST_INSERT_AFTER(addresses, network->ntp, tail, n);
345 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
346 "Key is invalid, ignoring assignment: %s=%s", lvalue, rvalue);
355 int config_parse_broadcast(const char *unit,
356 const char *filename,
359 unsigned section_line,
365 Network *network = userdata;
366 _cleanup_address_free_ Address *n = NULL;
367 _cleanup_free_ char *address = NULL;
376 r = address_new_static(network, section_line, &n);
380 if (n->family == AF_INET6) {
381 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
382 "Broadcast is not valid for IPv6 addresses, "
383 "ignoring assignment: %s", address);
387 r = net_parse_inaddr(address, &n->family, &n->broadcast);
389 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
390 "Broadcast is invalid, ignoring assignment: %s", address);
399 int config_parse_address(const char *unit,
400 const char *filename,
403 unsigned section_line,
409 Network *network = userdata;
410 _cleanup_address_free_ Address *n = NULL;
411 _cleanup_free_ char *address = NULL;
421 if (streq(section, "Network")) {
422 /* we are not in an Address section, so treat
423 * this as the special '0' section */
427 r = address_new_static(network, section_line, &n);
431 /* Address=address/prefixlen */
434 e = strchr(rvalue, '/');
437 r = safe_atou(e + 1, &i);
439 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
440 "Interface prefix length is invalid, "
441 "ignoring assignment: %s", e + 1);
445 n->prefixlen = (unsigned char) i;
447 address = strndup(rvalue, e - rvalue);
451 address = strdup(rvalue);
456 r = net_parse_inaddr(address, &n->family, &n->in_addr);
458 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
459 "Address is invalid, ignoring assignment: %s", address);
463 if (n->family == AF_INET && !n->broadcast.s_addr)
464 n->broadcast.s_addr = n->in_addr.in.s_addr |
465 htonl(0xfffffffflu >> n->prefixlen);
472 int config_parse_label(const char *unit,
473 const char *filename,
476 unsigned section_line,
482 Network *network = userdata;
483 _cleanup_address_free_ Address *n = NULL;
493 r = address_new_static(network, section_line, &n);
497 label = strdup(rvalue);
501 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
502 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
503 "Interface label is not ASCII clean or is too"
504 " long, ignoring assignment: %s", rvalue);
522 bool address_equal(Address *a1, Address *a2) {
527 /* one, but not both, is NULL */
531 if (a1->family != a2->family)
534 switch (a1->family) {
535 /* use the same notion of equality as the kernel does */
540 if (a1->prefixlen != a2->prefixlen)
545 b1 = be32toh(a1->in_addr.in.s_addr);
546 b2 = be32toh(a2->in_addr.in.s_addr);
548 return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
555 b1 = (uint64_t*)&a1->in_addr.in6;
556 b2 = (uint64_t*)&a2->in_addr.in6;
558 return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
561 assert_not_reached("Invalid address family");