]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-manager.c
networkd: manager - refactor link tracking a bit
[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 <resolv.h>
23 #include <linux/if.h>
24
25 #include "path-util.h"
26 #include "networkd.h"
27 #include "libudev-private.h"
28 #include "udev-util.h"
29 #include "rtnl-util.h"
30 #include "mkdir.h"
31 #include "virt.h"
32
33 #include "sd-rtnl.h"
34
35 const char* const network_dirs[] = {
36 "/etc/systemd/network",
37 "/run/systemd/network",
38 "/usr/lib/systemd/network",
39 #ifdef HAVE_SPLIT_USR
40 "/lib/systemd/network",
41 #endif
42 NULL};
43
44 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
45 Manager *m = userdata;
46
47 assert(m);
48
49 log_received_signal(LOG_INFO, si);
50
51 sd_event_exit(m->event, 0);
52 return 0;
53 }
54
55 static int setup_signals(Manager *m) {
56 sigset_t mask;
57 int r;
58
59 assert(m);
60
61 assert_se(sigemptyset(&mask) == 0);
62 sigset_add_many(&mask, SIGINT, SIGTERM, -1);
63 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
64
65 r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
66 if (r < 0)
67 return r;
68
69 r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
70 if (r < 0)
71 return r;
72
73 return 0;
74 }
75
76 int manager_new(Manager **ret) {
77 _cleanup_manager_free_ Manager *m = NULL;
78 int r;
79
80 m = new0(Manager, 1);
81 if (!m)
82 return -ENOMEM;
83
84 m->state_file = strdup("/run/systemd/network/state");
85 if (!m->state_file)
86 return -ENOMEM;
87
88 r = sd_event_default(&m->event);
89 if (r < 0)
90 return r;
91
92 sd_event_set_watchdog(m->event, true);
93
94 r = sd_rtnl_open(&m->rtnl, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
95 if (r < 0)
96 return r;
97
98 r = sd_bus_default_system(&m->bus);
99 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
100 return r;
101
102 r = setup_signals(m);
103 if (r < 0)
104 return r;
105
106 /* udev does not initialize devices inside containers,
107 * so we rely on them being already initialized before
108 * entering the container */
109 if (detect_container(NULL) <= 0) {
110 m->udev = udev_new();
111 if (!m->udev)
112 return -ENOMEM;
113
114 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
115 if (!m->udev_monitor)
116 return -ENOMEM;
117 }
118
119 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
120 if (!m->links)
121 return -ENOMEM;
122
123 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
124 if (!m->netdevs)
125 return -ENOMEM;
126
127 LIST_HEAD_INIT(m->networks);
128
129 *ret = m;
130 m = NULL;
131
132 return 0;
133 }
134
135 void manager_free(Manager *m) {
136 Network *network;
137 NetDev *netdev;
138 Link *link;
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_source_unref(m->sigterm_event_source);
150 sd_event_source_unref(m->sigint_event_source);
151 sd_event_unref(m->event);
152
153 while ((link = hashmap_first(m->links)))
154 link_unref(link);
155 hashmap_free(m->links);
156
157 while ((network = m->networks))
158 network_free(network);
159
160 while ((netdev = hashmap_first(m->netdevs)))
161 netdev_unref(netdev);
162 hashmap_free(m->netdevs);
163
164 sd_rtnl_unref(m->rtnl);
165
166 free(m);
167 }
168
169 int manager_load_config(Manager *m) {
170 int r;
171
172 /* update timestamp */
173 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
174
175 r = netdev_load(m);
176 if (r < 0)
177 return r;
178
179 r = network_load(m);
180 if (r < 0)
181 return r;
182
183 return 0;
184 }
185
186 bool manager_should_reload(Manager *m) {
187 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
188 }
189
190 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
191 Link *link = NULL;
192 int r, ifindex;
193
194 assert(m);
195 assert(device);
196
197 if (!streq_ptr(udev_device_get_action(device), "add"))
198 return 0;
199
200 ifindex = udev_device_get_ifindex(device);
201 if (ifindex <= 0) {
202 log_debug("ignoring udev ADD event for device with invalid ifindex");
203 return 0;
204 }
205
206 r = link_get(m, ifindex, &link);
207 if (r == -ENODEV)
208 return 0;
209 else if (r < 0)
210 return r;
211
212 r = link_initialized(link, device);
213 if (r < 0)
214 return r;
215
216 return 0;
217 }
218
219 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
220 Manager *m = userdata;
221 Link *link = NULL;
222 NetDev *netdev = NULL;
223 uint16_t type;
224 char *name;
225 int r, ifindex;
226
227 assert(rtnl);
228 assert(message);
229 assert(m);
230
231 r = sd_rtnl_message_get_type(message, &type);
232 if (r < 0) {
233 log_warning("rtnl: could not get message type");
234 return 0;
235 }
236
237 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
238 if (r < 0 || ifindex <= 0) {
239 log_warning("rtnl: received link message without valid ifindex");
240 return 0;
241 } else
242 link_get(m, ifindex, &link);
243
244 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
245 if (r < 0 || !name) {
246 log_warning("rtnl: received link message without valid ifname");
247 return 0;
248 } else
249 netdev_get(m, name, &netdev);
250
251 switch (type) {
252 case RTM_NEWLINK:
253 if (!link) {
254 /* link is new, so add it */
255 r = link_add(m, message, &link);
256 if (r < 0) {
257 log_debug("could not add new link");
258 return 0;
259 }
260 }
261
262 if (netdev) {
263 /* netdev exists, so make sure the ifindex matches */
264 r = netdev_set_ifindex(netdev, message);
265 if (r < 0) {
266 log_debug("could not set ifindex on netdev");
267 return 0;
268 }
269 }
270
271 r = link_update(link, message);
272 if (r < 0)
273 return 0;
274
275 break;
276
277 case RTM_DELLINK:
278 link_drop(link);
279 netdev_drop(netdev);
280
281 break;
282
283 default:
284 assert_not_reached("Received invalid RTNL message type.");
285 }
286
287 return 1;
288 }
289
290 int manager_rtnl_enumerate_links(Manager *m) {
291 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
292 sd_rtnl_message *link;
293 int r, k;
294
295 assert(m);
296 assert(m->rtnl);
297
298 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
299 if (r < 0)
300 return r;
301
302 r = sd_rtnl_message_request_dump(req, true);
303 if (r < 0)
304 return r;
305
306 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
307 if (r < 0)
308 return r;
309
310 for (link = reply; link; link = sd_rtnl_message_next(link)) {
311 uint16_t type;
312
313 k = sd_rtnl_message_get_type(link, &type);
314 if (k < 0)
315 return k;
316
317 if (type != RTM_NEWLINK)
318 continue;
319
320 k = manager_rtnl_process_link(m->rtnl, link, m);
321 if (k < 0)
322 r = k;
323 }
324
325 return r;
326 }
327
328 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
329 Manager *m = userdata;
330 struct udev_monitor *monitor = m->udev_monitor;
331 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
332
333 device = udev_monitor_receive_device(monitor);
334 if (!device)
335 return -ENOMEM;
336
337 manager_udev_process_link(m, device);
338 return 0;
339 }
340
341 int manager_udev_listen(Manager *m) {
342 int r;
343
344 if (detect_container(NULL) > 0)
345 return 0;
346
347 assert(m->udev_monitor);
348
349 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
350 if (r < 0) {
351 log_error("Could not add udev monitor filter: %s", strerror(-r));
352 return r;
353 }
354
355 r = udev_monitor_enable_receiving(m->udev_monitor);
356 if (r < 0) {
357 log_error("Could not enable udev monitor");
358 return r;
359 }
360
361 r = sd_event_add_io(m->event,
362 &m->udev_event_source,
363 udev_monitor_get_fd(m->udev_monitor),
364 EPOLLIN, manager_dispatch_link_udev,
365 m);
366 if (r < 0)
367 return r;
368
369 return 0;
370 }
371
372 int manager_rtnl_listen(Manager *m) {
373 int r;
374
375 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
376 if (r < 0)
377 return r;
378
379 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
380 if (r < 0)
381 return r;
382
383 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
384 if (r < 0)
385 return r;
386
387 return 0;
388 }
389
390 int manager_bus_listen(Manager *m) {
391 int r;
392
393 assert(m->event);
394
395 if (!m->bus) /* TODO: drop when we can rely on kdbus */
396 return 0;
397
398 r = sd_bus_attach_event(m->bus, m->event, 0);
399 if (r < 0)
400 return r;
401
402 return 0;
403 }
404
405 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
406 char buf[INET6_ADDRSTRLEN];
407 const char *address;
408
409 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
410 if (!address) {
411 log_warning("Invalid DNS address. Ignoring.");
412 return;
413 }
414
415 if (*count == MAXNS)
416 fputs("# Too many DNS servers configured, the following entries "
417 "will be ignored\n", f);
418
419 fprintf(f, "nameserver %s\n", address);
420
421 (*count) ++;
422 }
423
424 int manager_update_resolv_conf(Manager *m) {
425 _cleanup_free_ char *temp_path = NULL;
426 _cleanup_fclose_ FILE *f = NULL;
427 Link *link;
428 Iterator i;
429 unsigned count = 0;
430 const char *domainname = NULL;
431 int r;
432
433 assert(m);
434
435 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
436 if (r < 0)
437 return r;
438
439 fchmod(fileno(f), 0644);
440
441 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
442 "# Third party programs must not access this file directly, but\n"
443 "# only through the symlink at /etc/resolv.conf. To manage\n"
444 "# resolv.conf(5) in a different way, replace the symlink by a\n"
445 "# static file or a different symlink.\n\n", f);
446
447 HASHMAP_FOREACH(link, m->links, i) {
448 if (link->dhcp_lease) {
449 struct in_addr *nameservers;
450 size_t nameservers_size;
451
452 if (link->network->dhcp_dns) {
453 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
454 if (r >= 0) {
455 unsigned j;
456
457 for (j = 0; j < nameservers_size; j++)
458 append_dns(f, &nameservers[j], AF_INET, &count);
459 }
460 }
461
462 if (link->network->dhcp_domainname && !domainname) {
463 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
464 if (r >= 0)
465 fprintf(f, "domain %s\n", domainname);
466 }
467 }
468 }
469
470 HASHMAP_FOREACH(link, m->links, i) {
471 if (link->network && link->network->dns) {
472 Address *address;
473 Iterator j;
474
475 SET_FOREACH(address, link->network->dns, j) {
476 append_dns(f, &address->in_addr.in,
477 address->family, &count);
478 }
479 }
480 }
481
482 fflush(f);
483
484 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
485 r = -errno;
486 unlink("/run/systemd/network/resolv.conf");
487 unlink(temp_path);
488 return r;
489 }
490
491 return 0;
492 }
493
494 int manager_save(Manager *m) {
495 Link *link;
496 Iterator i;
497 _cleanup_free_ char *temp_path = NULL;
498 _cleanup_fclose_ FILE *f = NULL;
499 const char *oper_state = "unknown";
500 bool dormant, carrier;
501 int r;
502
503 assert(m);
504 assert(m->state_file);
505
506 HASHMAP_FOREACH(link, m->links, i) {
507 if (link->flags & IFF_LOOPBACK)
508 continue;
509
510 if (link_has_carrier(link->flags, link->operstate))
511 carrier = true;
512 else if (link->operstate == IF_OPER_DORMANT)
513 dormant = true;
514 }
515
516 if (carrier)
517 oper_state = "carrier";
518 else if (dormant)
519 oper_state = "dormant";
520
521 r = fopen_temporary(m->state_file, &f, &temp_path);
522 if (r < 0)
523 goto finish;
524
525 fchmod(fileno(f), 0644);
526
527 fprintf(f,
528 "# This is private data. Do not parse.\n"
529 "OPER_STATE=%s\n", oper_state);
530
531 fflush(f);
532
533 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
534 r = -errno;
535 unlink(m->state_file);
536 unlink(temp_path);
537 }
538
539 finish:
540 if (r < 0)
541 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
542
543 return r;
544 }