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;
50 address->scope = RT_SCOPE_UNIVERSE;
52 address->network = network;
54 LIST_PREPEND(static_addresses, network->static_addresses, address);
57 address->section = section;
58 hashmap_put(network->addresses_by_section, &address->section, address);
67 int address_new_dynamic(Address **ret) {
68 _cleanup_address_free_ Address *address = NULL;
70 address = new0(Address, 1);
74 address->family = AF_UNSPEC;
75 address->scope = RT_SCOPE_UNIVERSE;
83 void address_free(Address *address) {
87 if (address->network) {
88 LIST_REMOVE(static_addresses, address->network->static_addresses, address);
91 hashmap_remove(address->network->addresses_by_section,
98 int address_drop(Address *address, Link *link,
99 sd_rtnl_message_handler_t callback) {
100 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
104 assert(address->family == AF_INET || address->family == AF_INET6);
106 assert(link->ifindex > 0);
107 assert(link->manager);
108 assert(link->manager->rtnl);
110 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
111 link->ifindex, address->family);
113 log_error("Could not allocate RTM_DELADDR message: %s",
118 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
120 log_error("Could not set prefixlen: %s", strerror(-r));
124 if (address->family == AF_INET)
125 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
126 else if (address->family == AF_INET6)
127 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
129 log_error("Could not append IFA_LOCAL attribute: %s",
134 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
136 log_error("Could not send rtnetlink message: %s", strerror(-r));
143 int address_configure(Address *address, Link *link,
144 sd_rtnl_message_handler_t callback) {
145 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
149 assert(address->family == AF_INET || address->family == AF_INET6);
151 assert(link->ifindex > 0);
152 assert(link->manager);
153 assert(link->manager->rtnl);
155 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
156 link->ifindex, address->family);
158 log_error("Could not allocate RTM_NEWADDR message: %s",
163 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
165 log_error("Could not set prefixlen: %s", strerror(-r));
169 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
171 log_error("Could not set flags: %s", strerror(-r));
175 r = sd_rtnl_message_addr_set_scope(req, address->scope);
177 log_error("Could not set scope: %s", strerror(-r));
181 if (address->family == AF_INET)
182 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
183 else if (address->family == AF_INET6)
184 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
186 log_error("Could not append IFA_LOCAL attribute: %s",
191 if (address->family == AF_INET) {
192 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
194 log_error("Could not append IFA_BROADCAST attribute: %s",
200 if (address->label) {
201 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
203 log_error("Could not append IFA_LABEL attribute: %s",
209 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
211 log_error("Could not send rtnetlink message: %s", strerror(-r));
218 int config_parse_dns(const char *unit,
219 const char *filename,
222 unsigned section_line,
229 _cleanup_address_free_ Address *n = NULL;
238 r = address_new_dynamic(&n);
242 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
244 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
245 "DNS address is invalid, ignoring assignment: %s", rvalue);
255 int config_parse_broadcast(const char *unit,
256 const char *filename,
259 unsigned section_line,
265 Network *network = userdata;
266 _cleanup_address_free_ Address *n = NULL;
267 _cleanup_free_ char *address = NULL;
276 r = address_new_static(network, section_line, &n);
280 if (n->family == AF_INET6) {
281 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
282 "Broadcast is not valid for IPv6 addresses, "
283 "ignoring assignment: %s", address);
287 r = net_parse_inaddr(address, &n->family, &n->broadcast);
289 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
290 "Broadcast is invalid, ignoring assignment: %s", address);
299 int config_parse_address(const char *unit,
300 const char *filename,
303 unsigned section_line,
309 Network *network = userdata;
310 _cleanup_address_free_ Address *n = NULL;
311 _cleanup_free_ char *address = NULL;
321 if (streq(section, "Network")) {
322 /* we are not in an Address section, so treat
323 * this as the special '0' section */
327 r = address_new_static(network, section_line, &n);
331 /* Address=address/prefixlen */
334 e = strchr(rvalue, '/');
337 r = safe_atou(e + 1, &i);
339 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
340 "Interface prefix length is invalid, "
341 "ignoring assignment: %s", e + 1);
345 n->prefixlen = (unsigned char) i;
347 address = strndup(rvalue, e - rvalue);
351 address = strdup(rvalue);
356 r = net_parse_inaddr(address, &n->family, &n->in_addr);
358 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
359 "Address is invalid, ignoring assignment: %s", address);
363 if (n->family == AF_INET && !n->broadcast.s_addr)
364 n->broadcast.s_addr = n->in_addr.in.s_addr |
365 htonl(0xfffffffflu >> n->prefixlen);
372 int config_parse_label(const char *unit,
373 const char *filename,
376 unsigned section_line,
382 Network *network = userdata;
383 _cleanup_address_free_ Address *n = NULL;
393 r = address_new_static(network, section_line, &n);
397 label = strdup(rvalue);
401 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
402 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
403 "Interface label is not ASCII clean or is too"
404 " long, ignoring assignment: %s", rvalue);