chiark / gitweb /
61be347ebf8df64f0951d45e898417d5682ddd78
[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, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
95                          RTNLGRP_IPV6_IFADDR);
96         if (r < 0)
97                 return r;
98
99         r = sd_bus_default_system(&m->bus);
100         if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
101                 return r;
102
103         r = setup_signals(m);
104         if (r < 0)
105                 return r;
106
107         /* udev does not initialize devices inside containers,
108          * so we rely on them being already initialized before
109          * entering the container */
110         if (detect_container(NULL) <= 0) {
111                 m->udev = udev_new();
112                 if (!m->udev)
113                         return -ENOMEM;
114
115                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
116                 if (!m->udev_monitor)
117                         return -ENOMEM;
118         }
119
120         m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
121         if (!m->links)
122                 return -ENOMEM;
123
124         m->netdevs = hashmap_new(string_hash_func, string_compare_func);
125         if (!m->netdevs)
126                 return -ENOMEM;
127
128         LIST_HEAD_INIT(m->networks);
129
130         *ret = m;
131         m = NULL;
132
133         return 0;
134 }
135
136 void manager_free(Manager *m) {
137         Network *network;
138         NetDev *netdev;
139         Link *link;
140
141         if (!m)
142                 return;
143
144         free(m->state_file);
145
146         udev_monitor_unref(m->udev_monitor);
147         udev_unref(m->udev);
148         sd_bus_unref(m->bus);
149         sd_event_source_unref(m->udev_event_source);
150         sd_event_source_unref(m->sigterm_event_source);
151         sd_event_source_unref(m->sigint_event_source);
152         sd_event_unref(m->event);
153
154         while ((link = hashmap_first(m->links)))
155                 link_unref(link);
156         hashmap_free(m->links);
157
158         while ((network = m->networks))
159                 network_free(network);
160
161         while ((netdev = hashmap_first(m->netdevs)))
162                 netdev_unref(netdev);
163         hashmap_free(m->netdevs);
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         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");
259                                 return 0;
260                         }
261                 }
262
263                 if (netdev) {
264                         /* netdev exists, so make sure the ifindex matches */
265                         r = netdev_set_ifindex(netdev, message);
266                         if (r < 0) {
267                                 log_debug("could not set ifindex on netdev");
268                                 return 0;
269                         }
270                 }
271
272                 r = link_update(link, message);
273                 if (r < 0)
274                         return 0;
275
276                 break;
277
278         case RTM_DELLINK:
279                 link_drop(link);
280                 netdev_drop(netdev);
281
282                 break;
283
284         default:
285                 assert_not_reached("Received invalid RTNL message type.");
286         }
287
288         return 1;
289 }
290
291 int manager_rtnl_enumerate_links(Manager *m) {
292         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
293         sd_rtnl_message *link;
294         int r, k;
295
296         assert(m);
297         assert(m->rtnl);
298
299         r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
300         if (r < 0)
301                 return r;
302
303         r = sd_rtnl_message_request_dump(req, true);
304         if (r < 0)
305                 return r;
306
307         r = sd_rtnl_call(m->rtnl, req, 0, &reply);
308         if (r < 0)
309                 return r;
310
311         for (link = reply; link; link = sd_rtnl_message_next(link)) {
312                 uint16_t type;
313
314                 k = sd_rtnl_message_get_type(link, &type);
315                 if (k < 0)
316                         return k;
317
318                 if (type != RTM_NEWLINK)
319                         continue;
320
321                 k = manager_rtnl_process_link(m->rtnl, link, m);
322                 if (k < 0)
323                         r = k;
324         }
325
326         return r;
327 }
328
329 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
330         Manager *m = userdata;
331         struct udev_monitor *monitor = m->udev_monitor;
332         _cleanup_udev_device_unref_ struct udev_device *device = NULL;
333
334         device = udev_monitor_receive_device(monitor);
335         if (!device)
336                 return -ENOMEM;
337
338         manager_udev_process_link(m, device);
339         return 0;
340 }
341
342 int manager_udev_listen(Manager *m) {
343         int r;
344
345         if (detect_container(NULL) > 0)
346                 return 0;
347
348         assert(m->udev_monitor);
349
350         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
351         if (r < 0) {
352                 log_error("Could not add udev monitor filter: %s", strerror(-r));
353                 return r;
354         }
355
356         r = udev_monitor_enable_receiving(m->udev_monitor);
357         if (r < 0) {
358                 log_error("Could not enable udev monitor");
359                 return r;
360         }
361
362         r = sd_event_add_io(m->event,
363                         &m->udev_event_source,
364                         udev_monitor_get_fd(m->udev_monitor),
365                         EPOLLIN, manager_dispatch_link_udev,
366                         m);
367         if (r < 0)
368                 return r;
369
370         return 0;
371 }
372
373 int manager_rtnl_listen(Manager *m) {
374         int r;
375
376         r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
377         if (r < 0)
378                 return r;
379
380         r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
381         if (r < 0)
382                 return r;
383
384         r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
385         if (r < 0)
386                 return r;
387
388         return 0;
389 }
390
391 int manager_bus_listen(Manager *m) {
392         int r;
393
394         assert(m->event);
395
396         if (!m->bus) /* TODO: drop when we can rely on kdbus */
397                 return 0;
398
399         r = sd_bus_attach_event(m->bus, m->event, 0);
400         if (r < 0)
401                 return r;
402
403         return 0;
404 }
405
406 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
407         char buf[INET6_ADDRSTRLEN];
408         const char *address;
409
410         address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
411         if (!address) {
412                 log_warning("Invalid DNS address. Ignoring.");
413                 return;
414         }
415
416         if (*count == MAXNS)
417                 fputs("# Too many DNS servers configured, the following entries "
418                       "will be ignored\n", f);
419
420         fprintf(f, "nameserver %s\n", address);
421
422         (*count) ++;
423 }
424
425 int manager_update_resolv_conf(Manager *m) {
426         _cleanup_free_ char *temp_path = NULL;
427         _cleanup_fclose_ FILE *f = NULL;
428         Link *link;
429         Iterator i;
430         unsigned count = 0;
431         const char *domainname = NULL;
432         int r;
433
434         assert(m);
435
436         r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
437         if (r < 0)
438                 return r;
439
440         fchmod(fileno(f), 0644);
441
442         fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
443               "# Third party programs must not access this file directly, but\n"
444               "# only through the symlink at /etc/resolv.conf. To manage\n"
445               "# resolv.conf(5) in a different way, replace the symlink by a\n"
446               "# static file or a different symlink.\n\n", f);
447
448         HASHMAP_FOREACH(link, m->links, i) {
449                 if (link->dhcp_lease) {
450                         struct in_addr *nameservers;
451                         size_t nameservers_size;
452
453                         if (link->network->dhcp_dns) {
454                                 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
455                                 if (r >= 0) {
456                                         unsigned j;
457
458                                         for (j = 0; j < nameservers_size; j++)
459                                                 append_dns(f, &nameservers[j], AF_INET, &count);
460                                 }
461                         }
462
463                         if (link->network->dhcp_domainname && !domainname) {
464                                 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
465                                 if (r >= 0)
466                                        fprintf(f, "domain %s\n", domainname);
467                         }
468                 }
469         }
470
471         HASHMAP_FOREACH(link, m->links, i) {
472                 if (link->network && link->network->dns) {
473                         Address *address;
474                         Iterator j;
475
476                         SET_FOREACH(address, link->network->dns, j) {
477                                 append_dns(f, &address->in_addr.in,
478                                            address->family, &count);
479                         }
480                 }
481         }
482
483         fflush(f);
484
485         if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
486                 r = -errno;
487                 unlink("/run/systemd/network/resolv.conf");
488                 unlink(temp_path);
489                 return r;
490         }
491
492         return 0;
493 }
494
495 int manager_save(Manager *m) {
496         Link *link;
497         Iterator i;
498         _cleanup_free_ char *temp_path = NULL;
499         _cleanup_fclose_ FILE *f = NULL;
500         const char *oper_state = "unknown";
501         bool dormant = false, carrier = false;
502         int r;
503
504         assert(m);
505         assert(m->state_file);
506
507         HASHMAP_FOREACH(link, m->links, i) {
508                 if (link->flags & IFF_LOOPBACK)
509                         continue;
510
511                 if (link_has_carrier(link->flags, link->operstate))
512                         carrier = true;
513                 else if (link->operstate == IF_OPER_DORMANT)
514                         dormant = true;
515         }
516
517         if (carrier)
518                 oper_state = "carrier";
519         else if (dormant)
520                 oper_state = "dormant";
521
522         r = fopen_temporary(m->state_file, &f, &temp_path);
523         if (r < 0)
524                 goto finish;
525
526         fchmod(fileno(f), 0644);
527
528         fprintf(f,
529                 "# This is private data. Do not parse.\n"
530                 "OPER_STATE=%s\n", oper_state);
531
532         fflush(f);
533
534         if (ferror(f) || rename(temp_path, m->state_file) < 0) {
535                 r = -errno;
536                 unlink(m->state_file);
537                 unlink(temp_path);
538         }
539
540 finish:
541         if (r < 0)
542                 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
543
544         return r;
545 }