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