chiark / gitweb /
8bdc60f19c980dd940a3820a9ece37f6757d1ba4
[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         r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
389         if (r < 0)
390                 return r;
391
392         r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
393         if (r < 0)
394                 return r;
395
396         return 0;
397 }
398
399 int manager_bus_listen(Manager *m) {
400         int r;
401
402         assert(m->event);
403
404         if (!m->bus) /* TODO: drop when we can rely on kdbus */
405                 return 0;
406
407         r = sd_bus_attach_event(m->bus, m->event, 0);
408         if (r < 0)
409                 return r;
410
411         return 0;
412 }
413
414 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
415         char buf[INET6_ADDRSTRLEN];
416         const char *address;
417
418         address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
419         if (!address) {
420                 log_warning("Invalid DNS address. Ignoring.");
421                 return;
422         }
423
424         if (*count == MAXNS)
425                 fputs("# Too many DNS servers configured, the following entries "
426                       "will be ignored\n", f);
427
428         fprintf(f, "nameserver %s\n", address);
429
430         (*count) ++;
431 }
432
433 int manager_update_resolv_conf(Manager *m) {
434         _cleanup_free_ char *temp_path = NULL;
435         _cleanup_fclose_ FILE *f = NULL;
436         Link *link;
437         Iterator i;
438         unsigned count = 0;
439         const char *domainname = NULL;
440         int r;
441
442         assert(m);
443
444         r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
445         if (r < 0)
446                 return r;
447
448         fchmod(fileno(f), 0644);
449
450         fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
451               "# Third party programs must not access this file directly, but\n"
452               "# only through the symlink at /etc/resolv.conf. To manage\n"
453               "# resolv.conf(5) in a different way, replace the symlink by a\n"
454               "# static file or a different symlink.\n\n", f);
455
456         HASHMAP_FOREACH(link, m->links, i) {
457                 if (link->dhcp_lease) {
458                         struct in_addr *nameservers;
459                         size_t nameservers_size;
460
461                         if (link->network->dhcp_dns) {
462                                 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
463                                 if (r >= 0) {
464                                         unsigned j;
465
466                                         for (j = 0; j < nameservers_size; j++)
467                                                 append_dns(f, &nameservers[j], AF_INET, &count);
468                                 }
469                         }
470
471                         if (link->network->dhcp_domainname && !domainname) {
472                                 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
473                                 if (r >= 0)
474                                        fprintf(f, "domain %s\n", domainname);
475                         }
476                 }
477         }
478
479         HASHMAP_FOREACH(link, m->links, i) {
480                 if (link->network && link->network->dns) {
481                         Address *address;
482                         Iterator j;
483
484                         SET_FOREACH(address, link->network->dns, j) {
485                                 append_dns(f, &address->in_addr.in,
486                                            address->family, &count);
487                         }
488                 }
489         }
490
491         fflush(f);
492
493         if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
494                 r = -errno;
495                 unlink("/run/systemd/network/resolv.conf");
496                 unlink(temp_path);
497                 return r;
498         }
499
500         return 0;
501 }
502
503 int manager_save(Manager *m) {
504         Link *link;
505         Iterator i;
506         _cleanup_free_ char *temp_path = NULL;
507         _cleanup_fclose_ FILE *f = NULL;
508         const char *oper_state = "unknown";
509         bool dormant = false, carrier = false;
510         int r;
511
512         assert(m);
513         assert(m->state_file);
514
515         HASHMAP_FOREACH(link, m->links, i) {
516                 if (link->flags & IFF_LOOPBACK)
517                         continue;
518
519                 if (link_has_carrier(link->flags, link->operstate))
520                         carrier = true;
521                 else if (link->operstate == IF_OPER_DORMANT)
522                         dormant = true;
523         }
524
525         if (carrier)
526                 oper_state = "carrier";
527         else if (dormant)
528                 oper_state = "dormant";
529
530         r = fopen_temporary(m->state_file, &f, &temp_path);
531         if (r < 0)
532                 goto finish;
533
534         fchmod(fileno(f), 0644);
535
536         fprintf(f,
537                 "# This is private data. Do not parse.\n"
538                 "OPER_STATE=%s\n", oper_state);
539
540         fflush(f);
541
542         if (ferror(f) || rename(temp_path, m->state_file) < 0) {
543                 r = -errno;
544                 unlink(m->state_file);
545                 unlink(temp_path);
546         }
547
548 finish:
549         if (r < 0)
550                 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
551
552         return r;
553 }