chiark / gitweb /
networkd: netdev - verify name of newlink messages
[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
24 #include "path-util.h"
25 #include "networkd.h"
26 #include "libudev-private.h"
27 #include "udev-util.h"
28 #include "rtnl-util.h"
29 #include "mkdir.h"
30 #include "virt.h"
31
32 #include "sd-rtnl.h"
33
34 const char* const network_dirs[] = {
35         "/etc/systemd/network",
36         "/run/systemd/network",
37         "/usr/lib/systemd/network",
38 #ifdef HAVE_SPLIT_USR
39         "/lib/systemd/network",
40 #endif
41         NULL};
42
43 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
44         Manager *m = userdata;
45
46         assert(m);
47
48         log_received_signal(LOG_INFO, si);
49
50         sd_event_exit(m->event, 0);
51         return 0;
52 }
53
54 static int setup_signals(Manager *m) {
55         sigset_t mask;
56         int r;
57
58         assert(m);
59
60         assert_se(sigemptyset(&mask) == 0);
61         sigset_add_many(&mask, SIGINT, SIGTERM, -1);
62         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
63
64         r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
65         if (r < 0)
66                 return r;
67
68         r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
69         if (r < 0)
70                 return r;
71
72         return 0;
73 }
74
75 int manager_new(Manager **ret) {
76         _cleanup_manager_free_ Manager *m = NULL;
77         int r;
78
79         m = new0(Manager, 1);
80         if (!m)
81                 return -ENOMEM;
82
83         r = sd_event_default(&m->event);
84         if (r < 0)
85                 return r;
86
87         sd_event_set_watchdog(m->event, true);
88
89         r = sd_rtnl_open(&m->rtnl, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
90         if (r < 0)
91                 return r;
92
93         r = sd_bus_default_system(&m->bus);
94         if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
95                 return r;
96
97         r = setup_signals(m);
98         if (r < 0)
99                 return r;
100
101         /* udev does not initialize devices inside containers,
102          * so we rely on them being already initialized before
103          * entering the container */
104         if (detect_container(NULL) <= 0) {
105                 m->udev = udev_new();
106                 if (!m->udev)
107                         return -ENOMEM;
108
109                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
110                 if (!m->udev_monitor)
111                         return -ENOMEM;
112         }
113
114         m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
115         if (!m->links)
116                 return -ENOMEM;
117
118         m->netdevs = hashmap_new(string_hash_func, string_compare_func);
119         if (!m->netdevs)
120                 return -ENOMEM;
121
122         LIST_HEAD_INIT(m->networks);
123
124         *ret = m;
125         m = NULL;
126
127         return 0;
128 }
129
130 void manager_free(Manager *m) {
131         Network *network;
132         NetDev *netdev;
133         Link *link;
134
135         if (!m)
136                 return;
137
138         udev_monitor_unref(m->udev_monitor);
139         udev_unref(m->udev);
140         sd_bus_unref(m->bus);
141         sd_event_source_unref(m->udev_event_source);
142         sd_event_source_unref(m->sigterm_event_source);
143         sd_event_source_unref(m->sigint_event_source);
144         sd_event_unref(m->event);
145
146         while ((link = hashmap_first(m->links)))
147                 link_free(link);
148         hashmap_free(m->links);
149
150         while ((network = m->networks))
151                 network_free(network);
152
153         while ((netdev = hashmap_first(m->netdevs)))
154                 netdev_free(netdev);
155         hashmap_free(m->netdevs);
156
157         sd_rtnl_unref(m->rtnl);
158
159         free(m);
160 }
161
162 int manager_load_config(Manager *m) {
163         int r;
164
165         /* update timestamp */
166         paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
167
168         r = netdev_load(m);
169         if (r < 0)
170                 return r;
171
172         r = network_load(m);
173         if (r < 0)
174                 return r;
175
176         return 0;
177 }
178
179 bool manager_should_reload(Manager *m) {
180         return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
181 }
182
183 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
184         Link *link = NULL;
185         int r;
186
187         assert(m);
188         assert(device);
189
190         if (!streq_ptr(udev_device_get_action(device), "add"))
191                 return 0;
192
193         r = link_get(m, udev_device_get_ifindex(device), &link);
194         if (r < 0)
195                 return r;
196
197         if (!link)
198                 return 0;
199
200         r = link_initialized(link, device);
201         if (r < 0)
202                 return r;
203
204         return 0;
205 }
206 /*
207         if (streq_ptr(udev_device_get_action(device), "remove")) {
208                 log_debug("%s: link removed", udev_device_get_sysname(device));
209
210                 if (link)
211                         link_free(link);
212         } else {
213                 if (link) {
214                         log_debug("%s: link already exists, ignoring",
215                                   link->ifname);
216                         return 0;
217                 }
218
219                 r = link_add(m, device, &link);
220                 if (r < 0) {
221                         log_error("%s: could not handle link: %s",
222                                   udev_device_get_sysname(device),
223                                   strerror(-r));
224                 } else
225                         log_debug("%s: link (with ifindex %" PRIu64") added",
226                                   link->ifname, link->ifindex);
227         }
228
229         return 0;
230 }
231 */
232 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
233         Manager *m = userdata;
234         Link *link = NULL;
235         char *name;
236         int r, ifindex;
237
238         assert(rtnl);
239         assert(message);
240         assert(m);
241
242         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
243         if (r < 0 || ifindex <= 0) {
244                 log_warning("rtnl: received link message without valid ifindex");
245                 return 0;
246         }
247
248         link_get(m, ifindex, &link);
249         if (!link) {
250                 /* link is new, so add it */
251                 r = link_add(m, message, &link);
252                 if (r < 0) {
253                         log_debug("could not add new link");
254                         return 0;
255                 }
256         }
257
258         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
259         if (r < 0)
260                 log_warning("rtnl: received link message without valid ifname");
261         else {
262                 NetDev *netdev;
263
264                 r = netdev_get(m, name, &netdev);
265                 if (r >= 0) {
266                         r = netdev_set_ifindex(netdev, message);
267                         if (r < 0) {
268                                 log_debug("could not set ifindex on netdev");
269                                 return 0;
270                         }
271                 }
272         }
273
274         r = link_update(link, message);
275         if (r < 0)
276                 return 0;
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         return 0;
375 }
376
377 int manager_bus_listen(Manager *m) {
378         int r;
379
380         assert(m->event);
381
382         if (!m->bus) /* TODO: drop when we can rely on kdbus */
383                 return 0;
384
385         r = sd_bus_attach_event(m->bus, m->event, 0);
386         if (r < 0)
387                 return r;
388
389         return 0;
390 }
391
392 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
393         char buf[INET6_ADDRSTRLEN];
394         const char *address;
395
396         address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
397         if (!address) {
398                 log_warning("Invalid DNS address. Ignoring.");
399                 return;
400         }
401
402         if (*count == MAXNS)
403                 fputs("# Too many DNS servers configured, the following entries "
404                       "will be ignored\n", f);
405
406         fprintf(f, "nameserver %s\n", address);
407
408         (*count) ++;
409 }
410
411 int manager_update_resolv_conf(Manager *m) {
412         _cleanup_free_ char *temp_path = NULL;
413         _cleanup_fclose_ FILE *f = NULL;
414         Link *link;
415         Iterator i;
416         unsigned count = 0;
417         const char *domainname = NULL;
418         int r;
419
420         assert(m);
421
422         r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
423         if (r < 0)
424                 return r;
425
426         fchmod(fileno(f), 0644);
427
428         fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
429               "# Third party programs must not access this file directly, but\n"
430               "# only through the symlink at /etc/resolv.conf. To manage\n"
431               "# resolv.conf(5) in a different way, replace the symlink by a\n"
432               "# static file or a different symlink.\n\n", f);
433
434         HASHMAP_FOREACH(link, m->links, i) {
435                 if (link->dhcp_lease) {
436                         struct in_addr *nameservers;
437                         size_t nameservers_size;
438
439                         if (link->network->dhcp_dns) {
440                                 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
441                                 if (r >= 0) {
442                                         unsigned j;
443
444                                         for (j = 0; j < nameservers_size; j++)
445                                                 append_dns(f, &nameservers[j], AF_INET, &count);
446                                 }
447                         }
448
449                         if (link->network->dhcp_domainname && !domainname) {
450                                 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
451                                 if (r >= 0)
452                                        fprintf(f, "domain %s\n", domainname);
453                         }
454                 }
455         }
456
457         HASHMAP_FOREACH(link, m->links, i) {
458                 if (link->network && link->network->dns) {
459                         Address *address;
460                         Iterator j;
461
462                         SET_FOREACH(address, link->network->dns, j) {
463                                 append_dns(f, &address->in_addr.in,
464                                            address->family, &count);
465                         }
466                 }
467         }
468
469         fflush(f);
470
471         if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
472                 r = -errno;
473                 unlink("/run/systemd/network/resolv.conf");
474                 unlink(temp_path);
475                 return r;
476         }
477
478         return 0;
479 }