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_address(const char *unit,
194 const char *filename,
197 unsigned section_line,
203 Network *network = userdata;
204 _cleanup_address_free_ Address *n = NULL;
205 _cleanup_free_ char *address = NULL;
215 if (streq(section, "Network")) {
216 /* we are not in an Address section, so treat
217 * this as the special '0' section */
221 r = address_new_static(network, section_line, &n);
225 /* Address=address/prefixlen */
228 e = strchr(rvalue, '/');
231 r = safe_atou(e + 1, &i);
233 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
234 "Interface prefix length is invalid, "
235 "ignoring assignment: %s", e + 1);
239 n->prefixlen = (unsigned char) i;
240 n->netmask.s_addr = htonl(0xfffffffflu >> n->prefixlen);
242 address = strndup(rvalue, e - rvalue);
246 address = strdup(rvalue);
251 r = net_parse_inaddr(address, &n->family, &n->in_addr);
253 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
254 "Address is invalid, ignoring assignment: %s", address);
263 int config_parse_label(const char *unit,
264 const char *filename,
267 unsigned section_line,
273 Network *network = userdata;
274 _cleanup_address_free_ Address *n = NULL;
284 r = address_new_static(network, section_line, &n);
288 label = strdup(rvalue);
292 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
293 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
294 "Interface label is not ASCII clean or is too"
295 " long, ignoring assignment: %s", rvalue);