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