]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/network/networkd-manager.c
sd-rtnl: introduce sd_rtnl_new_from_netlink
[thirdparty/systemd.git] / src / network / networkd-manager.c
... / ...
CommitLineData
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 <sys/socket.h>
23#include <linux/if.h>
24
25#include "conf-parser.h"
26#include "path-util.h"
27#include "networkd.h"
28#include "networkd-netdev.h"
29#include "networkd-link.h"
30#include "network-internal.h"
31#include "libudev-private.h"
32#include "udev-util.h"
33#include "rtnl-util.h"
34#include "mkdir.h"
35#include "virt.h"
36
37#include "sd-rtnl.h"
38
39/* use 8 MB for receive socket kernel queue. */
40#define RCVBUF_SIZE (8*1024*1024)
41
42const char* const network_dirs[] = {
43 "/etc/systemd/network",
44 "/run/systemd/network",
45 "/usr/lib/systemd/network",
46#ifdef HAVE_SPLIT_USR
47 "/lib/systemd/network",
48#endif
49 NULL};
50
51static int setup_default_address_pool(Manager *m) {
52 AddressPool *p;
53 int r;
54
55 assert(m);
56
57 /* Add in the well-known private address ranges. */
58
59 r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7);
60 if (r < 0)
61 return r;
62
63 r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
64 if (r < 0)
65 return r;
66
67 r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12);
68 if (r < 0)
69 return r;
70
71 r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
72 if (r < 0)
73 return r;
74
75 return 0;
76}
77
78int manager_new(Manager **ret) {
79 _cleanup_manager_free_ Manager *m = NULL;
80 int r;
81
82 m = new0(Manager, 1);
83 if (!m)
84 return -ENOMEM;
85
86 m->state_file = strdup("/run/systemd/netif/state");
87 if (!m->state_file)
88 return -ENOMEM;
89
90 r = sd_event_default(&m->event);
91 if (r < 0)
92 return r;
93
94 sd_event_set_watchdog(m->event, true);
95
96 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
97 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
98
99 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
100 RTNLGRP_IPV6_IFADDR);
101 if (r < 0)
102 return r;
103
104 r = sd_rtnl_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
105 if (r < 0)
106 return r;
107
108 r = sd_bus_default_system(&m->bus);
109 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
110 return r;
111
112 /* udev does not initialize devices inside containers,
113 * so we rely on them being already initialized before
114 * entering the container */
115 if (detect_container(NULL) <= 0) {
116 m->udev = udev_new();
117 if (!m->udev)
118 return -ENOMEM;
119
120 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
121 if (!m->udev_monitor)
122 return -ENOMEM;
123 }
124
125 m->netdevs = hashmap_new(&string_hash_ops);
126 if (!m->netdevs)
127 return -ENOMEM;
128
129 LIST_HEAD_INIT(m->networks);
130
131 r = setup_default_address_pool(m);
132 if (r < 0)
133 return r;
134
135 *ret = m;
136 m = NULL;
137
138 return 0;
139}
140
141void manager_free(Manager *m) {
142 Network *network;
143 NetDev *netdev;
144 Link *link;
145 AddressPool *pool;
146
147 if (!m)
148 return;
149
150 free(m->state_file);
151
152 udev_monitor_unref(m->udev_monitor);
153 udev_unref(m->udev);
154 sd_bus_unref(m->bus);
155 sd_event_source_unref(m->udev_event_source);
156 sd_event_unref(m->event);
157
158 while ((link = hashmap_first(m->links)))
159 link_unref(link);
160 hashmap_free(m->links);
161
162 while ((network = m->networks))
163 network_free(network);
164
165 while ((netdev = hashmap_first(m->netdevs)))
166 netdev_unref(netdev);
167 hashmap_free(m->netdevs);
168
169 while ((pool = m->address_pools))
170 address_pool_free(pool);
171
172 sd_rtnl_unref(m->rtnl);
173
174 free(m);
175}
176
177int manager_load_config(Manager *m) {
178 int r;
179
180 /* update timestamp */
181 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
182
183 r = netdev_load(m);
184 if (r < 0)
185 return r;
186
187 r = network_load(m);
188 if (r < 0)
189 return r;
190
191 return 0;
192}
193
194bool manager_should_reload(Manager *m) {
195 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
196}
197
198static int manager_udev_process_link(Manager *m, struct udev_device *device) {
199 Link *link = NULL;
200 int r, ifindex;
201
202 assert(m);
203 assert(device);
204
205 if (!streq_ptr(udev_device_get_action(device), "add"))
206 return 0;
207
208 ifindex = udev_device_get_ifindex(device);
209 if (ifindex <= 0) {
210 log_debug("ignoring udev ADD event for device with invalid ifindex");
211 return 0;
212 }
213
214 r = link_get(m, ifindex, &link);
215 if (r == -ENODEV)
216 return 0;
217 else if (r < 0)
218 return r;
219
220 r = link_initialized(link, device);
221 if (r < 0)
222 return r;
223
224 return 0;
225}
226
227static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
228 Manager *m = userdata;
229 Link *link = NULL;
230 NetDev *netdev = NULL;
231 uint16_t type;
232 const char *name;
233 int r, ifindex;
234
235 assert(rtnl);
236 assert(message);
237 assert(m);
238
239 if (sd_rtnl_message_is_error(message)) {
240 r = sd_rtnl_message_get_errno(message);
241 if (r < 0)
242 log_warning_errno(r, "rtnl: could not receive link: %m");
243
244 return 0;
245 }
246
247 r = sd_rtnl_message_get_type(message, &type);
248 if (r < 0) {
249 log_warning_errno(r, "rtnl: could not get message type: %m");
250 return 0;
251 }
252
253 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
254 if (r < 0) {
255 log_warning_errno(r, "rtnl: could not get ifindex: %m");
256 return 0;
257 } else if (ifindex <= 0) {
258 log_warning("rtnl: received link message with invalid ifindex: %d", ifindex);
259 return 0;
260 } else
261 link_get(m, ifindex, &link);
262
263 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
264 if (r < 0) {
265 log_warning_errno(r, "rtnl: received link message without ifname: %m");
266 return 0;
267 } else
268 netdev_get(m, name, &netdev);
269
270 switch (type) {
271 case RTM_NEWLINK:
272 if (!link) {
273 /* link is new, so add it */
274 r = link_add(m, message, &link);
275 if (r < 0) {
276 log_warning_errno(r, "could not add new link: %m");
277 return 0;
278 }
279 }
280
281 if (netdev) {
282 /* netdev exists, so make sure the ifindex matches */
283 r = netdev_set_ifindex(netdev, message);
284 if (r < 0) {
285 log_warning_errno(r, "could not set ifindex on netdev: %m");
286 return 0;
287 }
288 }
289
290 r = link_update(link, message);
291 if (r < 0)
292 return 0;
293
294 break;
295
296 case RTM_DELLINK:
297 link_drop(link);
298 netdev_drop(netdev);
299
300 break;
301
302 default:
303 assert_not_reached("Received invalid RTNL message type.");
304 }
305
306 return 1;
307}
308
309int manager_rtnl_enumerate_links(Manager *m) {
310 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
311 sd_rtnl_message *link;
312 int r;
313
314 assert(m);
315 assert(m->rtnl);
316
317 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
318 if (r < 0)
319 return r;
320
321 r = sd_rtnl_message_request_dump(req, true);
322 if (r < 0)
323 return r;
324
325 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
326 if (r < 0)
327 return r;
328
329 for (link = reply; link; link = sd_rtnl_message_next(link)) {
330 int k;
331
332 k = manager_rtnl_process_link(m->rtnl, link, m);
333 if (k < 0)
334 r = k;
335 }
336
337 return r;
338}
339
340int manager_rtnl_enumerate_addresses(Manager *m) {
341 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
342 sd_rtnl_message *addr;
343 int r;
344
345 assert(m);
346 assert(m->rtnl);
347
348 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
349 if (r < 0)
350 return r;
351
352 r = sd_rtnl_message_request_dump(req, true);
353 if (r < 0)
354 return r;
355
356 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
357 if (r < 0)
358 return r;
359
360 for (addr = reply; addr; addr = sd_rtnl_message_next(addr)) {
361 int k;
362
363 k = link_rtnl_process_address(m->rtnl, addr, m);
364 if (k < 0)
365 r = k;
366 }
367
368 return r;
369}
370
371static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
372 Manager *m = userdata;
373 struct udev_monitor *monitor = m->udev_monitor;
374 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
375
376 device = udev_monitor_receive_device(monitor);
377 if (!device)
378 return -ENOMEM;
379
380 manager_udev_process_link(m, device);
381 return 0;
382}
383
384int manager_udev_listen(Manager *m) {
385 int r;
386
387 if (detect_container(NULL) > 0)
388 return 0;
389
390 assert(m->udev_monitor);
391
392 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
393 if (r < 0)
394 return log_error_errno(r, "Could not add udev monitor filter: %m");
395
396 r = udev_monitor_enable_receiving(m->udev_monitor);
397 if (r < 0) {
398 log_error("Could not enable udev monitor");
399 return r;
400 }
401
402 r = sd_event_add_io(m->event,
403 &m->udev_event_source,
404 udev_monitor_get_fd(m->udev_monitor),
405 EPOLLIN, manager_dispatch_link_udev,
406 m);
407 if (r < 0)
408 return r;
409
410 r = sd_event_source_set_description(m->udev_event_source, "networkd-udev");
411 if (r < 0)
412 return r;
413
414 return 0;
415}
416
417int manager_rtnl_listen(Manager *m) {
418 int r;
419
420 assert(m);
421
422 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
423 if (r < 0)
424 return r;
425
426 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
427 if (r < 0)
428 return r;
429
430 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
431 if (r < 0)
432 return r;
433
434 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
435 if (r < 0)
436 return r;
437
438 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
439 if (r < 0)
440 return r;
441
442 return 0;
443}
444
445int manager_bus_listen(Manager *m) {
446 int r;
447
448 assert(m->event);
449
450 if (!m->bus) /* TODO: drop when we can rely on kdbus */
451 return 0;
452
453 r = sd_bus_attach_event(m->bus, m->event, 0);
454 if (r < 0)
455 return r;
456
457 return 0;
458}
459
460static int set_put_in_addr(Set *s, const struct in_addr *address) {
461 char *p;
462 int r;
463
464 assert(s);
465
466 r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
467 if (r < 0)
468 return r;
469
470 r = set_consume(s, p);
471 if (r == -EEXIST)
472 return 0;
473
474 return r;
475}
476
477static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
478 int r, i, c = 0;
479
480 assert(s);
481 assert(n <= 0 || addresses);
482
483 for (i = 0; i < n; i++) {
484 r = set_put_in_addr(s, addresses+i);
485 if (r < 0)
486 return r;
487
488 c += r;
489 }
490
491 return c;
492}
493
494static void print_string_set(FILE *f, const char *field, Set *s) {
495 bool space = false;
496 Iterator i;
497 char *p;
498
499 if (set_isempty(s))
500 return;
501
502 fputs(field, f);
503
504 SET_FOREACH(p, s, i) {
505 if (space)
506 fputc(' ', f);
507 fputs(p, f);
508 space = true;
509 }
510 fputc('\n', f);
511}
512
513int manager_save(Manager *m) {
514 _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
515 Link *link;
516 Iterator i;
517 _cleanup_free_ char *temp_path = NULL;
518 _cleanup_fclose_ FILE *f = NULL;
519 LinkOperationalState operstate = LINK_OPERSTATE_OFF;
520 const char *operstate_str;
521 int r;
522
523 assert(m);
524 assert(m->state_file);
525
526 /* We add all NTP and DNS server to a set, to filter out duplicates */
527 dns = set_new(&string_hash_ops);
528 if (!dns)
529 return -ENOMEM;
530
531 ntp = set_new(&string_hash_ops);
532 if (!ntp)
533 return -ENOMEM;
534
535 domains = set_new(&string_hash_ops);
536 if (!domains)
537 return -ENOMEM;
538
539 HASHMAP_FOREACH(link, m->links, i) {
540 if (link->flags & IFF_LOOPBACK)
541 continue;
542
543 if (link->operstate > operstate)
544 operstate = link->operstate;
545
546 if (!link->network)
547 continue;
548
549 /* First add the static configured entries */
550 r = set_put_strdupv(dns, link->network->dns);
551 if (r < 0)
552 return r;
553
554 r = set_put_strdupv(ntp, link->network->ntp);
555 if (r < 0)
556 return r;
557
558 r = set_put_strdupv(domains, link->network->domains);
559 if (r < 0)
560 return r;
561
562 if (!link->dhcp_lease)
563 continue;
564
565 /* Secondly, add the entries acquired via DHCP */
566 if (link->network->dhcp_dns) {
567 const struct in_addr *addresses;
568
569 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
570 if (r > 0) {
571 r = set_put_in_addrv(dns, addresses, r);
572 if (r < 0)
573 return r;
574 } else if (r < 0 && r != -ENOENT)
575 return r;
576 }
577
578 if (link->network->dhcp_ntp) {
579 const struct in_addr *addresses;
580
581 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
582 if (r > 0) {
583 r = set_put_in_addrv(ntp, addresses, r);
584 if (r < 0)
585 return r;
586 } else if (r < 0 && r != -ENOENT)
587 return r;
588 }
589
590 if (link->network->dhcp_domains) {
591 const char *domainname;
592
593 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
594 if (r >= 0) {
595 r = set_put_strdup(domains, domainname);
596 if (r < 0)
597 return r;
598 } else if (r != -ENOENT)
599 return r;
600 }
601 }
602
603 operstate_str = link_operstate_to_string(operstate);
604 assert(operstate_str);
605
606 r = fopen_temporary(m->state_file, &f, &temp_path);
607 if (r < 0)
608 return r;
609
610 fchmod(fileno(f), 0644);
611
612 fprintf(f,
613 "# This is private data. Do not parse.\n"
614 "OPER_STATE=%s\n", operstate_str);
615
616 print_string_set(f, "DNS=", dns);
617 print_string_set(f, "NTP=", ntp);
618 print_string_set(f, "DOMAINS=", domains);
619
620 r = fflush_and_check(f);
621 if (r < 0)
622 goto fail;
623
624 if (rename(temp_path, m->state_file) < 0) {
625 r = -errno;
626 goto fail;
627 }
628
629 return 0;
630
631fail:
632 log_error_errno(r, "Failed to save network state to %s: %m", m->state_file);
633 unlink(m->state_file);
634 unlink(temp_path);
635 return r;
636}
637
638int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
639 AddressPool *p;
640 int r;
641
642 assert(m);
643 assert(prefixlen > 0);
644 assert(found);
645
646 LIST_FOREACH(address_pools, p, m->address_pools) {
647 if (p->family != family)
648 continue;
649
650 r = address_pool_acquire(p, prefixlen, found);
651 if (r != 0)
652 return r;
653 }
654
655 return 0;
656}
657
658const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
659 if (b == ADDRESS_FAMILY_YES ||
660 b == ADDRESS_FAMILY_NO)
661 return yes_no(b == ADDRESS_FAMILY_YES);
662
663 if (b == ADDRESS_FAMILY_IPV4)
664 return "ipv4";
665 if (b == ADDRESS_FAMILY_IPV6)
666 return "ipv6";
667
668 return NULL;
669}
670
671AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
672 int r;
673
674 /* Make this a true superset of a boolean */
675
676 r = parse_boolean(s);
677 if (r > 0)
678 return ADDRESS_FAMILY_YES;
679 if (r == 0)
680 return ADDRESS_FAMILY_NO;
681
682 if (streq(s, "ipv4"))
683 return ADDRESS_FAMILY_IPV4;
684 if (streq(s, "ipv6"))
685 return ADDRESS_FAMILY_IPV6;
686
687 return _ADDRESS_FAMILY_BOOLEAN_INVALID;
688}
689
690DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");