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->network = network;
51 LIST_PREPEND(static_addresses, network->static_addresses, address);
54 address->section = section;
55 hashmap_put(network->addresses_by_section, &address->section, address);
64 int address_new_dynamic(Address **ret) {
65 _cleanup_address_free_ Address *address = NULL;
67 address = new0(Address, 1);
77 void address_free(Address *address) {
81 if (address->network) {
82 LIST_REMOVE(static_addresses, address->network->static_addresses, address);
85 hashmap_remove(address->network->addresses_by_section,
92 int address_drop(Address *address, Link *link,
93 sd_rtnl_message_handler_t callback) {
94 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
98 assert(address->family == AF_INET || address->family == AF_INET6);
100 assert(link->ifindex > 0);
101 assert(link->manager);
102 assert(link->manager->rtnl);
104 r = sd_rtnl_message_addr_new(RTM_DELADDR, link->ifindex,
105 address->family, address->prefixlen, 0, 0, &req);
107 log_error("Could not allocate RTM_DELADDR message: %s",
112 if (address->family == AF_INET)
113 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
114 else if (address->family == AF_INET6)
115 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
117 log_error("Could not append IFA_LOCAL attribute: %s",
122 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
124 log_error("Could not send rtnetlink message: %s", strerror(-r));
131 int address_configure(Address *address, Link *link,
132 sd_rtnl_message_handler_t callback) {
133 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
137 assert(address->family == AF_INET || address->family == AF_INET6);
139 assert(link->ifindex > 0);
140 assert(link->manager);
141 assert(link->manager->rtnl);
143 r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex,
144 address->family, address->prefixlen,
145 IFA_F_PERMANENT, RT_SCOPE_UNIVERSE, &req);
147 log_error("Could not allocate RTM_NEWADDR message: %s",
152 if (address->family == AF_INET)
153 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
154 else if (address->family == AF_INET6)
155 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
157 log_error("Could not append IFA_LOCAL attribute: %s",
162 if (address->family == AF_INET) {
163 struct in_addr broadcast;
165 broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr;
167 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &broadcast);
169 log_error("Could not append IFA_BROADCAST attribute: %s",
175 if (address->label) {
176 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
178 log_error("Could not append IFA_LABEL attribute: %s",
184 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
186 log_error("Could not send rtnetlink message: %s", strerror(-r));
193 int config_parse_dns(const char *unit,
194 const char *filename,
197 unsigned section_line,
203 Address **dns = data;
204 _cleanup_address_free_ Address *n = NULL;
213 r = address_new_dynamic(&n);
217 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
219 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
220 "DNS address is invalid, ignoring assignment: %s", rvalue);
230 int config_parse_address(const char *unit,
231 const char *filename,
234 unsigned section_line,
240 Network *network = userdata;
241 _cleanup_address_free_ Address *n = NULL;
242 _cleanup_free_ char *address = NULL;
252 if (streq(section, "Network")) {
253 /* we are not in an Address section, so treat
254 * this as the special '0' section */
258 r = address_new_static(network, section_line, &n);
262 /* Address=address/prefixlen */
265 e = strchr(rvalue, '/');
268 r = safe_atou(e + 1, &i);
270 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
271 "Interface prefix length is invalid, "
272 "ignoring assignment: %s", e + 1);
276 n->prefixlen = (unsigned char) i;
277 n->netmask.s_addr = htonl(0xfffffffflu >> n->prefixlen);
279 address = strndup(rvalue, e - rvalue);
283 address = strdup(rvalue);
288 r = net_parse_inaddr(address, &n->family, &n->in_addr);
290 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
291 "Address is invalid, ignoring assignment: %s", address);
300 int config_parse_label(const char *unit,
301 const char *filename,
304 unsigned section_line,
310 Network *network = userdata;
311 _cleanup_address_free_ Address *n = NULL;
321 r = address_new_static(network, section_line, &n);
325 label = strdup(rvalue);
329 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
330 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
331 "Interface label is not ASCII clean or is too"
332 " long, ignoring assignment: %s", rvalue);