]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-address.c
rtnl: drop "sd_" prefix from cleanup macros
[thirdparty/systemd.git] / src / network / networkd-address.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <net/if.h>
23
24 #include "networkd.h"
25
26 #include "utf8.h"
27 #include "util.h"
28 #include "conf-parser.h"
29 #include "net-util.h"
30
31 int address_new_static(Network *network, unsigned section, Address **ret) {
32 _cleanup_address_free_ Address *address = NULL;
33
34 if (section) {
35 uint64_t key = section;
36 address = hashmap_get(network->addresses_by_section, &key);
37 if (address) {
38 *ret = address;
39 address = NULL;
40
41 return 0;
42 }
43 }
44
45 address = new0(Address, 1);
46 if (!address)
47 return -ENOMEM;
48
49 address->family = AF_UNSPEC;
50
51 address->network = network;
52
53 LIST_PREPEND(static_addresses, network->static_addresses, address);
54
55 if (section) {
56 address->section = section;
57 hashmap_put(network->addresses_by_section, &address->section, address);
58 }
59
60 *ret = address;
61 address = NULL;
62
63 return 0;
64 }
65
66 int address_new_dynamic(Address **ret) {
67 _cleanup_address_free_ Address *address = NULL;
68
69 address = new0(Address, 1);
70 if (!address)
71 return -ENOMEM;
72
73 address->family = AF_UNSPEC;
74
75 *ret = address;
76 address = NULL;
77
78 return 0;
79 }
80
81 void address_free(Address *address) {
82 if (!address)
83 return;
84
85 if (address->network) {
86 LIST_REMOVE(static_addresses, address->network->static_addresses, address);
87
88 if (address->section)
89 hashmap_remove(address->network->addresses_by_section,
90 &address->section);
91 }
92
93 free(address);
94 }
95
96 int address_drop(Address *address, Link *link,
97 sd_rtnl_message_handler_t callback) {
98 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
99 int r;
100
101 assert(address);
102 assert(address->family == AF_INET || address->family == AF_INET6);
103 assert(link);
104 assert(link->ifindex > 0);
105 assert(link->manager);
106 assert(link->manager->rtnl);
107
108 r = sd_rtnl_message_addr_new(RTM_DELADDR, link->ifindex, address->family, &req);
109 if (r < 0) {
110 log_error("Could not allocate RTM_DELADDR message: %s",
111 strerror(-r));
112 return r;
113 }
114
115 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
116 if (r < 0) {
117 log_error("Could not set prefixlen: %s", strerror(-r));
118 return r;
119 }
120
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);
125 if (r < 0) {
126 log_error("Could not append IFA_LOCAL attribute: %s",
127 strerror(-r));
128 return r;
129 }
130
131 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
132 if (r < 0) {
133 log_error("Could not send rtnetlink message: %s", strerror(-r));
134 return r;
135 }
136
137 return 0;
138 }
139
140 int address_configure(Address *address, Link *link,
141 sd_rtnl_message_handler_t callback) {
142 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
143 int r;
144
145 assert(address);
146 assert(address->family == AF_INET || address->family == AF_INET6);
147 assert(link);
148 assert(link->ifindex > 0);
149 assert(link->manager);
150 assert(link->manager->rtnl);
151
152 r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex,
153 address->family, &req);
154 if (r < 0) {
155 log_error("Could not allocate RTM_NEWADDR message: %s",
156 strerror(-r));
157 return r;
158 }
159
160 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
161 if (r < 0) {
162 log_error("Could not set prefixlen: %s", strerror(-r));
163 return r;
164 }
165
166 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
167 if (r < 0) {
168 log_error("Could not set flags: %s", strerror(-r));
169 return r;
170 }
171
172 r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_UNIVERSE);
173 if (r < 0) {
174 log_error("Could not set scope: %s", strerror(-r));
175 return r;
176 }
177
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);
182 if (r < 0) {
183 log_error("Could not append IFA_LOCAL attribute: %s",
184 strerror(-r));
185 return r;
186 }
187
188 if (address->family == AF_INET) {
189 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
190 if (r < 0) {
191 log_error("Could not append IFA_BROADCAST attribute: %s",
192 strerror(-r));
193 return r;
194 }
195 }
196
197 if (address->label) {
198 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
199 if (r < 0) {
200 log_error("Could not append IFA_LABEL attribute: %s",
201 strerror(-r));
202 return r;
203 }
204 }
205
206 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
207 if (r < 0) {
208 log_error("Could not send rtnetlink message: %s", strerror(-r));
209 return r;
210 }
211
212 return 0;
213 }
214
215 int config_parse_dns(const char *unit,
216 const char *filename,
217 unsigned line,
218 const char *section,
219 unsigned section_line,
220 const char *lvalue,
221 int ltype,
222 const char *rvalue,
223 void *data,
224 void *userdata) {
225 Address **dns = data;
226 _cleanup_address_free_ Address *n = NULL;
227 int r;
228
229 assert(filename);
230 assert(section);
231 assert(lvalue);
232 assert(rvalue);
233 assert(data);
234
235 r = address_new_dynamic(&n);
236 if (r < 0)
237 return r;
238
239 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
240 if (r < 0) {
241 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
242 "DNS address is invalid, ignoring assignment: %s", rvalue);
243 return 0;
244 }
245
246 *dns = n;
247 n = NULL;
248
249 return 0;
250 }
251
252 int config_parse_broadcast(const char *unit,
253 const char *filename,
254 unsigned line,
255 const char *section,
256 unsigned section_line,
257 const char *lvalue,
258 int ltype,
259 const char *rvalue,
260 void *data,
261 void *userdata) {
262 Network *network = userdata;
263 _cleanup_address_free_ Address *n = NULL;
264 _cleanup_free_ char *address = NULL;
265 int r;
266
267 assert(filename);
268 assert(section);
269 assert(lvalue);
270 assert(rvalue);
271 assert(data);
272
273 r = address_new_static(network, section_line, &n);
274 if (r < 0)
275 return r;
276
277 r = net_parse_inaddr(address, &n->family, &n->broadcast);
278 if (r < 0) {
279 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
280 "Broadcast is invalid, ignoring assignment: %s", address);
281 return 0;
282 }
283
284 n = NULL;
285
286 return 0;
287 }
288
289 int config_parse_address(const char *unit,
290 const char *filename,
291 unsigned line,
292 const char *section,
293 unsigned section_line,
294 const char *lvalue,
295 int ltype,
296 const char *rvalue,
297 void *data,
298 void *userdata) {
299 Network *network = userdata;
300 _cleanup_address_free_ Address *n = NULL;
301 _cleanup_free_ char *address = NULL;
302 const char *e;
303 int r;
304
305 assert(filename);
306 assert(section);
307 assert(lvalue);
308 assert(rvalue);
309 assert(data);
310
311 if (streq(section, "Network")) {
312 /* we are not in an Address section, so treat
313 * this as the special '0' section */
314 section_line = 0;
315 }
316
317 r = address_new_static(network, section_line, &n);
318 if (r < 0)
319 return r;
320
321 /* Address=address/prefixlen */
322
323 /* prefixlen */
324 e = strchr(rvalue, '/');
325 if (e) {
326 unsigned i;
327 r = safe_atou(e + 1, &i);
328 if (r < 0) {
329 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
330 "Interface prefix length is invalid, "
331 "ignoring assignment: %s", e + 1);
332 return 0;
333 }
334
335 n->prefixlen = (unsigned char) i;
336
337 address = strndup(rvalue, e - rvalue);
338 if (!address)
339 return log_oom();
340 } else {
341 address = strdup(rvalue);
342 if (!address)
343 return log_oom();
344 }
345
346 r = net_parse_inaddr(address, &n->family, &n->in_addr);
347 if (r < 0) {
348 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
349 "Address is invalid, ignoring assignment: %s", address);
350 return 0;
351 }
352
353 if (n->family == AF_INET && !n->broadcast.s_addr)
354 n->broadcast.s_addr = n->in_addr.in.s_addr |
355 htonl(0xfffffffflu >> n->prefixlen);
356
357 n = NULL;
358
359 return 0;
360 }
361
362 int config_parse_label(const char *unit,
363 const char *filename,
364 unsigned line,
365 const char *section,
366 unsigned section_line,
367 const char *lvalue,
368 int ltype,
369 const char *rvalue,
370 void *data,
371 void *userdata) {
372 Network *network = userdata;
373 _cleanup_address_free_ Address *n = NULL;
374 char *label;
375 int r;
376
377 assert(filename);
378 assert(section);
379 assert(lvalue);
380 assert(rvalue);
381 assert(data);
382
383 r = address_new_static(network, section_line, &n);
384 if (r < 0)
385 return r;
386
387 label = strdup(rvalue);
388 if (!label)
389 return log_oom();
390
391 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
392 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
393 "Interface label is not ASCII clean or is too"
394 " long, ignoring assignment: %s", rvalue);
395 free(label);
396 return 0;
397 }
398
399 free(n->label);
400 if (*label)
401 n->label = label;
402 else {
403 free(label);
404 n->label = NULL;
405 }
406
407 n = NULL;
408
409 return 0;
410 }