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_sd_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_addr_new(RTM_DELADDR, link->ifindex, address->family, &req);
110 log_error("Could not allocate RTM_DELADDR message: %s",
115 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
117 log_error("Could not set prefixlen: %s", strerror(-r));
121 if (address->family == AF_INET)
122 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
123 else if (address->family == AF_INET6)
124 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
126 log_error("Could not append IFA_LOCAL attribute: %s",
131 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
133 log_error("Could not send rtnetlink message: %s", strerror(-r));
140 int address_configure(Address *address, Link *link,
141 sd_rtnl_message_handler_t callback) {
142 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
146 assert(address->family == AF_INET || address->family == AF_INET6);
148 assert(link->ifindex > 0);
149 assert(link->manager);
150 assert(link->manager->rtnl);
152 r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex,
153 address->family, &req);
155 log_error("Could not allocate RTM_NEWADDR message: %s",
160 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
162 log_error("Could not set prefixlen: %s", strerror(-r));
166 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
168 log_error("Could not set flags: %s", strerror(-r));
172 r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_UNIVERSE);
174 log_error("Could not set scope: %s", strerror(-r));
178 if (address->family == AF_INET)
179 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
180 else if (address->family == AF_INET6)
181 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
183 log_error("Could not append IFA_LOCAL attribute: %s",
188 if (address->family == AF_INET) {
189 struct in_addr broadcast;
191 broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr;
193 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &broadcast);
195 log_error("Could not append IFA_BROADCAST attribute: %s",
201 if (address->label) {
202 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
204 log_error("Could not append IFA_LABEL attribute: %s",
210 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
212 log_error("Could not send rtnetlink message: %s", strerror(-r));
219 int config_parse_dns(const char *unit,
220 const char *filename,
223 unsigned section_line,
229 Address **dns = data;
230 _cleanup_address_free_ Address *n = NULL;
239 r = address_new_dynamic(&n);
243 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
245 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
246 "DNS address is invalid, ignoring assignment: %s", rvalue);
256 int config_parse_address(const char *unit,
257 const char *filename,
260 unsigned section_line,
266 Network *network = userdata;
267 _cleanup_address_free_ Address *n = NULL;
268 _cleanup_free_ char *address = NULL;
278 if (streq(section, "Network")) {
279 /* we are not in an Address section, so treat
280 * this as the special '0' section */
284 r = address_new_static(network, section_line, &n);
288 /* Address=address/prefixlen */
291 e = strchr(rvalue, '/');
294 r = safe_atou(e + 1, &i);
296 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
297 "Interface prefix length is invalid, "
298 "ignoring assignment: %s", e + 1);
302 n->prefixlen = (unsigned char) i;
303 n->netmask.s_addr = htonl(0xfffffffflu >> n->prefixlen);
305 address = strndup(rvalue, e - rvalue);
309 address = strdup(rvalue);
314 r = net_parse_inaddr(address, &n->family, &n->in_addr);
316 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
317 "Address is invalid, ignoring assignment: %s", address);
326 int config_parse_label(const char *unit,
327 const char *filename,
330 unsigned section_line,
336 Network *network = userdata;
337 _cleanup_address_free_ Address *n = NULL;
347 r = address_new_static(network, section_line, &n);
351 label = strdup(rvalue);
355 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
356 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
357 "Interface label is not ASCII clean or is too"
358 " long, ignoring assignment: %s", rvalue);