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(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(addresses, network->addresses, address);
54 address->section = section;
55 hashmap_put(network->addresses_by_section, &address->section, address);
64 void address_free(Address *address) {
68 LIST_REMOVE(addresses, address->network->addresses, address);
71 hashmap_remove(address->network->addresses_by_section,
77 int address_drop(Address *address, Link *link,
78 sd_rtnl_message_handler_t callback) {
79 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
83 assert(address->family == AF_INET || address->family == AF_INET6);
85 assert(link->ifindex > 0);
86 assert(link->manager);
87 assert(link->manager->rtnl);
89 r = sd_rtnl_message_addr_new(RTM_DELADDR, link->ifindex,
90 address->family, address->prefixlen, 0, 0, &req);
92 log_error("Could not allocate RTM_DELADDR message: %s",
97 if (address->family == AF_INET)
98 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
99 else if (address->family == AF_INET6)
100 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
102 log_error("Could not append IFA_LOCAL attribute: %s",
107 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
109 log_error("Could not send rtnetlink message: %s", strerror(-r));
116 int address_configure(Address *address, Link *link,
117 sd_rtnl_message_handler_t callback) {
118 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
122 assert(address->family == AF_INET || address->family == AF_INET6);
124 assert(link->ifindex > 0);
125 assert(link->manager);
126 assert(link->manager->rtnl);
128 r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex,
129 address->family, address->prefixlen,
130 IFA_F_PERMANENT, RT_SCOPE_UNIVERSE, &req);
132 log_error("Could not allocate RTM_NEWADDR message: %s",
137 if (address->family == AF_INET)
138 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
139 else if (address->family == AF_INET6)
140 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
142 log_error("Could not append IFA_LOCAL attribute: %s",
147 if (address->family == AF_INET) {
148 struct in_addr broadcast;
150 broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr;
152 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &broadcast);
154 log_error("Could not append IFA_BROADCAST attribute: %s",
160 if (address->label) {
161 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
163 log_error("Could not append IFA_LABEL attribute: %s",
169 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
171 log_error("Could not send rtnetlink message: %s", strerror(-r));
178 int config_parse_address(const char *unit,
179 const char *filename,
182 unsigned section_line,
188 Network *network = userdata;
189 _cleanup_address_free_ Address *n = NULL;
190 _cleanup_free_ char *address = NULL;
200 if (streq(section, "Network")) {
201 /* we are not in an Address section, so treat
202 * this as the special '0' section */
206 r = address_new(network, section_line, &n);
210 /* Address=address/prefixlen */
213 e = strchr(rvalue, '/');
216 r = safe_atou(e + 1, &i);
218 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
219 "Interface prefix length is invalid, "
220 "ignoring assignment: %s", e + 1);
224 n->prefixlen = (unsigned char) i;
225 n->netmask.s_addr = htonl(0xfffffffflu >> n->prefixlen);
227 address = strndup(rvalue, e - rvalue);
231 address = strdup(rvalue);
236 r = net_parse_inaddr(address, &n->family, &n->in_addr);
238 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
239 "Address is invalid, ignoring assignment: %s", address);
248 int config_parse_label(const char *unit,
249 const char *filename,
252 unsigned section_line,
258 Network *network = userdata;
259 _cleanup_address_free_ Address *n = NULL;
269 r = address_new(network, section_line, &n);
273 label = strdup(rvalue);
277 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
278 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
279 "Interface label is not ASCII clean or is too"
280 " long, ignoring assignment: %s", rvalue);