chiark / gitweb /
d4b05bb98710e6ca06e50eabc27cdf9afadd0325
[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         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 }