]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-address.c
remove unused includes
[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 "utf8.h"
25 #include "util.h"
26 #include "conf-parser.h"
27 #include "fw-util.h"
28 #include "networkd.h"
29 #include "networkd-link.h"
30
31 static void address_init(Address *address) {
32 assert(address);
33
34 address->family = AF_UNSPEC;
35 address->scope = RT_SCOPE_UNIVERSE;
36 address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
37 address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
38 }
39
40 int address_new_static(Network *network, unsigned section, Address **ret) {
41 _cleanup_address_free_ Address *address = NULL;
42
43 if (section) {
44 address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
45 if (address) {
46 *ret = address;
47 address = NULL;
48
49 return 0;
50 }
51 }
52
53 address = new0(Address, 1);
54 if (!address)
55 return -ENOMEM;
56
57 address_init(address);
58
59 address->network = network;
60
61 LIST_APPEND(addresses, network->static_addresses, address);
62
63 if (section) {
64 address->section = section;
65 hashmap_put(network->addresses_by_section,
66 UINT_TO_PTR(address->section), address);
67 }
68
69 *ret = address;
70 address = NULL;
71
72 return 0;
73 }
74
75 int address_new_dynamic(Address **ret) {
76 _cleanup_address_free_ Address *address = NULL;
77
78 address = new0(Address, 1);
79 if (!address)
80 return -ENOMEM;
81
82 address_init(address);
83
84 *ret = address;
85 address = NULL;
86
87 return 0;
88 }
89
90 void address_free(Address *address) {
91 if (!address)
92 return;
93
94 if (address->network) {
95 LIST_REMOVE(addresses, address->network->static_addresses, address);
96
97 if (address->section)
98 hashmap_remove(address->network->addresses_by_section,
99 UINT_TO_PTR(address->section));
100 }
101
102 free(address);
103 }
104
105 int address_establish(Address *address, Link *link) {
106 bool masq;
107 int r;
108
109 assert(address);
110 assert(link);
111
112 masq = link->network &&
113 link->network->ip_masquerade &&
114 address->family == AF_INET &&
115 address->scope < RT_SCOPE_LINK;
116
117 /* Add firewall entry if this is requested */
118 if (address->ip_masquerade_done != masq) {
119 union in_addr_union masked = address->in_addr;
120 in_addr_mask(address->family, &masked, address->prefixlen);
121
122 r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
123 if (r < 0)
124 log_link_warning_errno(link, r, "Could not enable IP masquerading: %m");
125
126 address->ip_masquerade_done = masq;
127 }
128
129 return 0;
130 }
131
132 int address_release(Address *address, Link *link) {
133 int r;
134
135 assert(address);
136 assert(link);
137
138 /* Remove masquerading firewall entry if it was added */
139 if (address->ip_masquerade_done) {
140 union in_addr_union masked = address->in_addr;
141 in_addr_mask(address->family, &masked, address->prefixlen);
142
143 r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
144 if (r < 0)
145 log_link_warning_errno(link, r, "Failed to disable IP masquerading: %m");
146
147 address->ip_masquerade_done = false;
148 }
149
150 return 0;
151 }
152
153 int address_drop(Address *address, Link *link,
154 sd_rtnl_message_handler_t callback) {
155 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
156 int r;
157
158 assert(address);
159 assert(address->family == AF_INET || address->family == AF_INET6);
160 assert(link);
161 assert(link->ifindex > 0);
162 assert(link->manager);
163 assert(link->manager->rtnl);
164
165 address_release(address, link);
166
167 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
168 link->ifindex, address->family);
169 if (r < 0)
170 return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m");
171
172 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
173 if (r < 0)
174 return log_error_errno(r, "Could not set prefixlen: %m");
175
176 if (address->family == AF_INET)
177 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
178 else if (address->family == AF_INET6)
179 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
180 if (r < 0)
181 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
182
183 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
184 if (r < 0)
185 return log_error_errno(r, "Could not send rtnetlink message: %m");
186
187 link_ref(link);
188
189 return 0;
190 }
191
192 int address_update(Address *address, Link *link,
193 sd_rtnl_message_handler_t callback) {
194 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
195 int r;
196
197 assert(address);
198 assert(address->family == AF_INET || address->family == AF_INET6);
199 assert(link->ifindex > 0);
200 assert(link->manager);
201 assert(link->manager->rtnl);
202
203 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
204 link->ifindex, address->family);
205 if (r < 0)
206 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
207
208 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
209 if (r < 0)
210 return log_error_errno(r, "Could not set prefixlen: %m");
211
212 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
213 if (r < 0)
214 return log_error_errno(r, "Could not set flags: %m");
215
216 r = sd_rtnl_message_addr_set_scope(req, address->scope);
217 if (r < 0)
218 return log_error_errno(r, "Could not set scope: %m");
219
220 if (address->family == AF_INET)
221 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
222 else if (address->family == AF_INET6)
223 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
224 if (r < 0)
225 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
226
227 if (address->family == AF_INET) {
228 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
229 if (r < 0)
230 return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
231 }
232
233 if (address->label) {
234 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
235 if (r < 0)
236 return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
237 }
238
239 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
240 if (r < 0)
241 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
242
243 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
244 if (r < 0)
245 return log_error_errno(r, "Could not send rtnetlink message: %m");
246
247 link_ref(link);
248
249 return 0;
250 }
251
252 static int address_acquire(Link *link, Address *original, Address **ret) {
253 union in_addr_union in_addr = {};
254 struct in_addr broadcast = {};
255 _cleanup_address_free_ Address *na = NULL;
256 int r;
257
258 assert(link);
259 assert(original);
260 assert(ret);
261
262 /* Something useful was configured? just use it */
263 if (in_addr_is_null(original->family, &original->in_addr) <= 0)
264 return 0;
265
266 /* The address is configured to be 0.0.0.0 or [::] by the user?
267 * Then let's acquire something more useful from the pool. */
268 r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
269 if (r < 0) {
270 log_link_error(link, "Failed to acquire address from pool: %s", strerror(-r));
271 return r;
272 }
273 if (r == 0) {
274 log_link_error(link, "Couldn't find free address for interface, all taken.");
275 return -EBUSY;
276 }
277
278 if (original->family == AF_INET) {
279 /* Pick first address in range for ourselves ... */
280 in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
281
282 /* .. and use last as broadcast address */
283 broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
284 } else if (original->family == AF_INET6)
285 in_addr.in6.s6_addr[15] |= 1;
286
287 r = address_new_dynamic(&na);
288 if (r < 0)
289 return r;
290
291 na->family = original->family;
292 na->prefixlen = original->prefixlen;
293 na->scope = original->scope;
294 na->cinfo = original->cinfo;
295
296 if (original->label) {
297 na->label = strdup(original->label);
298 if (!na->label)
299 return -ENOMEM;
300 }
301
302 na->broadcast = broadcast;
303 na->in_addr = in_addr;
304
305 LIST_PREPEND(addresses, link->pool_addresses, na);
306
307 *ret = na;
308 na = NULL;
309
310 return 0;
311 }
312
313 int address_configure(Address *address, Link *link,
314 sd_rtnl_message_handler_t callback) {
315 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
316 int r;
317
318 assert(address);
319 assert(address->family == AF_INET || address->family == AF_INET6);
320 assert(link);
321 assert(link->ifindex > 0);
322 assert(link->manager);
323 assert(link->manager->rtnl);
324
325 r = address_acquire(link, address, &address);
326 if (r < 0)
327 return r;
328
329 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
330 link->ifindex, address->family);
331 if (r < 0)
332 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
333
334 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
335 if (r < 0)
336 return log_error_errno(r, "Could not set prefixlen: %m");
337
338 r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
339 if (r < 0)
340 return log_error_errno(r, "Could not set flags: %m");
341
342 r = sd_rtnl_message_addr_set_scope(req, address->scope);
343 if (r < 0)
344 return log_error_errno(r, "Could not set scope: %m");
345
346 if (address->family == AF_INET)
347 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
348 else if (address->family == AF_INET6)
349 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
350 if (r < 0)
351 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
352
353 if (!in_addr_is_null(address->family, &address->in_addr_peer)) {
354 if (address->family == AF_INET)
355 r = sd_rtnl_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in);
356 else if (address->family == AF_INET6)
357 r = sd_rtnl_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6);
358 if (r < 0)
359 return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
360 } else {
361 if (address->family == AF_INET) {
362 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
363 if (r < 0)
364 return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
365 }
366 }
367
368 if (address->label) {
369 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
370 if (r < 0)
371 return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
372 }
373
374 r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO,
375 &address->cinfo);
376 if (r < 0)
377 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
378
379 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
380 if (r < 0)
381 return log_error_errno(r, "Could not send rtnetlink message: %m");
382
383 link_ref(link);
384
385 address_establish(address, link);
386
387 return 0;
388 }
389
390 int config_parse_broadcast(
391 const char *unit,
392 const char *filename,
393 unsigned line,
394 const char *section,
395 unsigned section_line,
396 const char *lvalue,
397 int ltype,
398 const char *rvalue,
399 void *data,
400 void *userdata) {
401
402 Network *network = userdata;
403 _cleanup_address_free_ Address *n = NULL;
404 int r;
405
406 assert(filename);
407 assert(section);
408 assert(lvalue);
409 assert(rvalue);
410 assert(data);
411
412 r = address_new_static(network, section_line, &n);
413 if (r < 0)
414 return r;
415
416 if (n->family == AF_INET6) {
417 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
418 "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
419 return 0;
420 }
421
422 r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast);
423 if (r < 0) {
424 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
425 "Broadcast is invalid, ignoring assignment: %s", rvalue);
426 return 0;
427 }
428
429 n->family = AF_INET;
430 n = NULL;
431
432 return 0;
433 }
434
435 int config_parse_address(const char *unit,
436 const char *filename,
437 unsigned line,
438 const char *section,
439 unsigned section_line,
440 const char *lvalue,
441 int ltype,
442 const char *rvalue,
443 void *data,
444 void *userdata) {
445
446 Network *network = userdata;
447 _cleanup_address_free_ Address *n = NULL;
448 const char *address, *e;
449 union in_addr_union buffer;
450 int r, f;
451
452 assert(filename);
453 assert(section);
454 assert(lvalue);
455 assert(rvalue);
456 assert(data);
457
458 if (streq(section, "Network")) {
459 /* we are not in an Address section, so treat
460 * this as the special '0' section */
461 section_line = 0;
462 }
463
464 r = address_new_static(network, section_line, &n);
465 if (r < 0)
466 return r;
467
468 /* Address=address/prefixlen */
469
470 /* prefixlen */
471 e = strchr(rvalue, '/');
472 if (e) {
473 unsigned i;
474 r = safe_atou(e + 1, &i);
475 if (r < 0) {
476 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
477 "Prefix length is invalid, ignoring assignment: %s", e + 1);
478 return 0;
479 }
480
481 n->prefixlen = (unsigned char) i;
482
483 address = strndupa(rvalue, e - rvalue);
484 } else
485 address = rvalue;
486
487 r = in_addr_from_string_auto(address, &f, &buffer);
488 if (r < 0) {
489 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
490 "Address is invalid, ignoring assignment: %s", address);
491 return 0;
492 }
493
494 if (!e && f == AF_INET) {
495 r = in_addr_default_prefixlen(&buffer.in, &n->prefixlen);
496 if (r < 0) {
497 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
498 "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address);
499 return 0;
500 }
501 }
502
503 if (n->family != AF_UNSPEC && f != n->family) {
504 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
505 "Address is incompatible, ignoring assignment: %s", address);
506 return 0;
507 }
508
509 n->family = f;
510
511 if (streq(lvalue, "Address"))
512 n->in_addr = buffer;
513 else
514 n->in_addr_peer = buffer;
515
516 if (n->family == AF_INET && n->broadcast.s_addr == 0)
517 n->broadcast.s_addr = n->in_addr.in.s_addr | htonl(0xfffffffflu >> n->prefixlen);
518
519 n = NULL;
520
521 return 0;
522 }
523
524 int config_parse_label(const char *unit,
525 const char *filename,
526 unsigned line,
527 const char *section,
528 unsigned section_line,
529 const char *lvalue,
530 int ltype,
531 const char *rvalue,
532 void *data,
533 void *userdata) {
534 Network *network = userdata;
535 _cleanup_address_free_ Address *n = NULL;
536 char *label;
537 int r;
538
539 assert(filename);
540 assert(section);
541 assert(lvalue);
542 assert(rvalue);
543 assert(data);
544
545 r = address_new_static(network, section_line, &n);
546 if (r < 0)
547 return r;
548
549 label = strdup(rvalue);
550 if (!label)
551 return log_oom();
552
553 if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
554 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
555 "Interface label is not ASCII clean or is too"
556 " long, ignoring assignment: %s", rvalue);
557 free(label);
558 return 0;
559 }
560
561 free(n->label);
562 if (*label)
563 n->label = label;
564 else {
565 free(label);
566 n->label = NULL;
567 }
568
569 n = NULL;
570
571 return 0;
572 }
573
574 bool address_equal(Address *a1, Address *a2) {
575 /* same object */
576 if (a1 == a2)
577 return true;
578
579 /* one, but not both, is NULL */
580 if (!a1 || !a2)
581 return false;
582
583 if (a1->family != a2->family)
584 return false;
585
586 switch (a1->family) {
587 /* use the same notion of equality as the kernel does */
588 case AF_UNSPEC:
589 return true;
590
591 case AF_INET:
592 if (a1->prefixlen != a2->prefixlen)
593 return false;
594 else if (a1->prefixlen == 0)
595 /* make sure we don't try to shift by 32.
596 * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
597 return true;
598 else {
599 uint32_t b1, b2;
600
601 b1 = be32toh(a1->in_addr.in.s_addr);
602 b2 = be32toh(a2->in_addr.in.s_addr);
603
604 return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
605 }
606
607 case AF_INET6: {
608 uint64_t *b1, *b2;
609
610 b1 = (uint64_t*)&a1->in_addr.in6;
611 b2 = (uint64_t*)&a2->in_addr.in6;
612
613 return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
614 }
615
616 default:
617 assert_not_reached("Invalid address family");
618 }
619 }