chiark / gitweb /
networkd: link - handle links coming back to life
[elogind.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         uint16_t type;
223         char *name;
224         int r, ifindex;
225
226         assert(rtnl);
227         assert(message);
228         assert(m);
229
230         r = sd_rtnl_message_get_type(message, &type);
231         if (r < 0) {
232                 log_warning("rtnl: could not get message type");
233                 return 0;
234         }
235
236         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
237         if (r < 0 || ifindex <= 0) {
238                 log_warning("rtnl: received link message without valid ifindex");
239                 return 0;
240         }
241
242         link_get(m, ifindex, &link);
243         if (type == RTM_DELLINK)
244                 link_drop(link);
245         else if (!link) {
246                 /* link is new, so add it */
247                 r = link_add(m, message, &link);
248                 if (r < 0) {
249                         log_debug("could not add new link");
250                         return 0;
251                 }
252         }
253
254         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
255         if (r < 0)
256                 log_warning("rtnl: received link message without valid ifname");
257         else {
258                 NetDev *netdev = NULL;
259
260                 netdev_get(m, name, &netdev);
261                 if (type == RTM_DELLINK)
262                         netdev_drop(netdev);
263                 else if (netdev) {
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
272         if (type == RTM_NEWLINK) {
273                 r = link_update(link, message);
274                 if (r < 0)
275                         return 0;
276         }
277
278         return 1;
279 }
280
281 int manager_rtnl_enumerate_links(Manager *m) {
282         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
283         sd_rtnl_message *link;
284         int r, k;
285
286         assert(m);
287         assert(m->rtnl);
288
289         r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
290         if (r < 0)
291                 return r;
292
293         r = sd_rtnl_message_request_dump(req, true);
294         if (r < 0)
295                 return r;
296
297         r = sd_rtnl_call(m->rtnl, req, 0, &reply);
298         if (r < 0)
299                 return r;
300
301         for (link = reply; link; link = sd_rtnl_message_next(link)) {
302                 uint16_t type;
303
304                 k = sd_rtnl_message_get_type(link, &type);
305                 if (k < 0)
306                         return k;
307
308                 if (type != RTM_NEWLINK)
309                         continue;
310
311                 k = manager_rtnl_process_link(m->rtnl, link, m);
312                 if (k < 0)
313                         r = k;
314         }
315
316         return r;
317 }
318
319 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
320         Manager *m = userdata;
321         struct udev_monitor *monitor = m->udev_monitor;
322         _cleanup_udev_device_unref_ struct udev_device *device = NULL;
323
324         device = udev_monitor_receive_device(monitor);
325         if (!device)
326                 return -ENOMEM;
327
328         manager_udev_process_link(m, device);
329         return 0;
330 }
331
332 int manager_udev_listen(Manager *m) {
333         int r;
334
335         if (detect_container(NULL) > 0)
336                 return 0;
337
338         assert(m->udev_monitor);
339
340         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
341         if (r < 0) {
342                 log_error("Could not add udev monitor filter: %s", strerror(-r));
343                 return r;
344         }
345
346         r = udev_monitor_enable_receiving(m->udev_monitor);
347         if (r < 0) {
348                 log_error("Could not enable udev monitor");
349                 return r;
350         }
351
352         r = sd_event_add_io(m->event,
353                         &m->udev_event_source,
354                         udev_monitor_get_fd(m->udev_monitor),
355                         EPOLLIN, manager_dispatch_link_udev,
356                         m);
357         if (r < 0)
358                 return r;
359
360         return 0;
361 }
362
363 int manager_rtnl_listen(Manager *m) {
364         int r;
365
366         r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
367         if (r < 0)
368                 return r;
369
370         r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
371         if (r < 0)
372                 return r;
373
374         r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
375         if (r < 0)
376                 return r;
377
378         return 0;
379 }
380
381 int manager_bus_listen(Manager *m) {
382         int r;
383
384         assert(m->event);
385
386         if (!m->bus) /* TODO: drop when we can rely on kdbus */
387                 return 0;
388
389         r = sd_bus_attach_event(m->bus, m->event, 0);
390         if (r < 0)
391                 return r;
392
393         return 0;
394 }
395
396 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
397         char buf[INET6_ADDRSTRLEN];
398         const char *address;
399
400         address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
401         if (!address) {
402                 log_warning("Invalid DNS address. Ignoring.");
403                 return;
404         }
405
406         if (*count == MAXNS)
407                 fputs("# Too many DNS servers configured, the following entries "
408                       "will be ignored\n", f);
409
410         fprintf(f, "nameserver %s\n", address);
411
412         (*count) ++;
413 }
414
415 int manager_update_resolv_conf(Manager *m) {
416         _cleanup_free_ char *temp_path = NULL;
417         _cleanup_fclose_ FILE *f = NULL;
418         Link *link;
419         Iterator i;
420         unsigned count = 0;
421         const char *domainname = NULL;
422         int r;
423
424         assert(m);
425
426         r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
427         if (r < 0)
428                 return r;
429
430         fchmod(fileno(f), 0644);
431
432         fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
433               "# Third party programs must not access this file directly, but\n"
434               "# only through the symlink at /etc/resolv.conf. To manage\n"
435               "# resolv.conf(5) in a different way, replace the symlink by a\n"
436               "# static file or a different symlink.\n\n", f);
437
438         HASHMAP_FOREACH(link, m->links, i) {
439                 if (link->dhcp_lease) {
440                         struct in_addr *nameservers;
441                         size_t nameservers_size;
442
443                         if (link->network->dhcp_dns) {
444                                 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
445                                 if (r >= 0) {
446                                         unsigned j;
447
448                                         for (j = 0; j < nameservers_size; j++)
449                                                 append_dns(f, &nameservers[j], AF_INET, &count);
450                                 }
451                         }
452
453                         if (link->network->dhcp_domainname && !domainname) {
454                                 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
455                                 if (r >= 0)
456                                        fprintf(f, "domain %s\n", domainname);
457                         }
458                 }
459         }
460
461         HASHMAP_FOREACH(link, m->links, i) {
462                 if (link->network && link->network->dns) {
463                         Address *address;
464                         Iterator j;
465
466                         SET_FOREACH(address, link->network->dns, j) {
467                                 append_dns(f, &address->in_addr.in,
468                                            address->family, &count);
469                         }
470                 }
471         }
472
473         fflush(f);
474
475         if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
476                 r = -errno;
477                 unlink("/run/systemd/network/resolv.conf");
478                 unlink(temp_path);
479                 return r;
480         }
481
482         return 0;
483 }
484
485 int manager_save(Manager *m) {
486         Link *link;
487         Iterator i;
488         _cleanup_free_ char *temp_path = NULL;
489         _cleanup_fclose_ FILE *f = NULL;
490         const char *oper_state = "unknown";
491         bool dormant, carrier;
492         int r;
493
494         assert(m);
495         assert(m->state_file);
496
497         HASHMAP_FOREACH(link, m->links, i) {
498                 if (link->flags & IFF_LOOPBACK)
499                         continue;
500
501                 if (link_has_carrier(link->flags, link->operstate))
502                         carrier = true;
503                 else if (link->operstate == IF_OPER_DORMANT)
504                         dormant = true;
505         }
506
507         if (carrier)
508                 oper_state = "carrier";
509         else if (dormant)
510                 oper_state = "dormant";
511
512         r = fopen_temporary(m->state_file, &f, &temp_path);
513         if (r < 0)
514                 goto finish;
515
516         fchmod(fileno(f), 0644);
517
518         fprintf(f,
519                 "# This is private data. Do not parse.\n"
520                 "OPER_STATE=%s\n", oper_state);
521
522         fflush(f);
523
524         if (ferror(f) || rename(temp_path, m->state_file) < 0) {
525                 r = -errno;
526                 unlink(m->state_file);
527                 unlink(temp_path);
528         }
529
530 finish:
531         if (r < 0)
532                 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
533
534         return r;
535 }