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"
31 int address_new_static(Network *network, unsigned section, Address **ret) {
32 _cleanup_address_free_ Address *address = NULL;
35 uint64_t key = section;
36 address = hashmap_get(network->addresses_by_section, &key);
45 address = new0(Address, 1);
49 address->family = AF_UNSPEC;
51 address->network = network;
53 LIST_PREPEND(static_addresses, network->static_addresses, address);
56 address->section = section;
57 hashmap_put(network->addresses_by_section, &address->section, address);
66 int address_new_dynamic(Address **ret) {
67 _cleanup_address_free_ Address *address = NULL;
69 address = new0(Address, 1);
73 address->family = AF_UNSPEC;
81 void address_free(Address *address) {
85 if (address->network) {
86 LIST_REMOVE(static_addresses, address->network->static_addresses, address);
89 hashmap_remove(address->network->addresses_by_section,
96 int address_drop(Address *address, Link *link,
97 sd_rtnl_message_handler_t callback) {
98 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
102 assert(address->family == AF_INET || address->family == AF_INET6);
104 assert(link->ifindex > 0);
105 assert(link->manager);
106 assert(link->manager->rtnl);
108 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
109 link->ifindex, address->family);
111 log_error("Could not allocate RTM_DELADDR message: %s",
116 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
118 log_error("Could not set prefixlen: %s", strerror(-r));
122 if (address->family == AF_INET)
123 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
124 else if (address->family == AF_INET6)
125 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
127 log_error("Could not append IFA_LOCAL attribute: %s",
132 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
134 log_error("Could not send rtnetlink message: %s", strerror(-r));
141 int address_configure(Address *address, Link *link,
142 sd_rtnl_message_handler_t callback) {
143 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
147 assert(address->family == AF_INET || address->family == AF_INET6);
149 assert(link->ifindex > 0);
150 assert(link->manager);
151 assert(link->manager->rtnl);
153 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
154 link->ifindex, address->family);
156 log_error("Could not allocate RTM_NEWADDR message: %s",
161 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
163 log_error("Could not set prefixlen: %s", strerror(-r));
167 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
169 log_error("Could not set flags: %s", strerror(-r));
173 r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_UNIVERSE);
175 log_error("Could not set scope: %s", strerror(-r));
179 if (address->family == AF_INET)
180 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
181 else if (address->family == AF_INET6)
182 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
184 log_error("Could not append IFA_LOCAL attribute: %s",
189 if (address->family == AF_INET) {
190 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
192 log_error("Could not append IFA_BROADCAST attribute: %s",
198 if (address->label) {
199 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
201 log_error("Could not append IFA_LABEL attribute: %s",
207 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
209 log_error("Could not send rtnetlink message: %s", strerror(-r));
216 int config_parse_dns(const char *unit,
217 const char *filename,
220 unsigned section_line,
226 Address **dns = data;
227 _cleanup_address_free_ Address *n = NULL;
236 r = address_new_dynamic(&n);
240 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
242 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
243 "DNS address is invalid, ignoring assignment: %s", rvalue);
253 int config_parse_broadcast(const char *unit,
254 const char *filename,
257 unsigned section_line,
263 Network *network = userdata;
264 _cleanup_address_free_ Address *n = NULL;
265 _cleanup_free_ char *address = NULL;
274 r = address_new_static(network, section_line, &n);
278 if (n->family == AF_INET6) {
279 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
280 "Broadcast is not valid for IPv6 addresses, "
281 "ignoring assignment: %s", address);
285 r = net_parse_inaddr(address, &n->family, &n->broadcast);
287 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
288 "Broadcast is invalid, ignoring assignment: %s", address);
297 int config_parse_address(const char *unit,
298 const char *filename,
301 unsigned section_line,
307 Network *network = userdata;
308 _cleanup_address_free_ Address *n = NULL;
309 _cleanup_free_ char *address = NULL;
319 if (streq(section, "Network")) {
320 /* we are not in an Address section, so treat
321 * this as the special '0' section */
325 r = address_new_static(network, section_line, &n);
329 /* Address=address/prefixlen */
332 e = strchr(rvalue, '/');
335 r = safe_atou(e + 1, &i);
337 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
338 "Interface prefix length is invalid, "
339 "ignoring assignment: %s", e + 1);
343 n->prefixlen = (unsigned char) i;
345 address = strndup(rvalue, e - rvalue);
349 address = strdup(rvalue);
354 r = net_parse_inaddr(address, &n->family, &n->in_addr);
356 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
357 "Address is invalid, ignoring assignment: %s", address);
361 if (n->family == AF_INET && !n->broadcast.s_addr)
362 n->broadcast.s_addr = n->in_addr.in.s_addr |
363 htonl(0xfffffffflu >> n->prefixlen);
370 int config_parse_label(const char *unit,
371 const char *filename,
374 unsigned section_line,
380 Network *network = userdata;
381 _cleanup_address_free_ Address *n = NULL;
391 r = address_new_static(network, section_line, &n);
395 label = strdup(rvalue);
399 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
400 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
401 "Interface label is not ASCII clean or is too"
402 " long, ignoring assignment: %s", rvalue);