chiark / gitweb /
networkd: network - store DNS servers in List rather than Set
[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 #include <libkmod.h>
25
26 #include "path-util.h"
27 #include "networkd.h"
28 #include "network-internal.h"
29 #include "libudev-private.h"
30 #include "udev-util.h"
31 #include "rtnl-util.h"
32 #include "mkdir.h"
33 #include "virt.h"
34
35 #include "sd-rtnl.h"
36
37 const char* const network_dirs[] = {
38         "/etc/systemd/network",
39         "/run/systemd/network",
40         "/usr/lib/systemd/network",
41 #ifdef HAVE_SPLIT_USR
42         "/lib/systemd/network",
43 #endif
44         NULL};
45
46 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
47         Manager *m = userdata;
48
49         assert(m);
50
51         log_received_signal(LOG_INFO, si);
52
53         sd_event_exit(m->event, 0);
54         return 0;
55 }
56
57 static int setup_signals(Manager *m) {
58         sigset_t mask;
59         int r;
60
61         assert(m);
62
63         assert_se(sigemptyset(&mask) == 0);
64         sigset_add_many(&mask, SIGINT, SIGTERM, -1);
65         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
66
67         r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
68         if (r < 0)
69                 return r;
70
71         r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
72         if (r < 0)
73                 return r;
74
75         return 0;
76 }
77
78 static int set_fallback_dns(Manager *m, const char *string) {
79         char *word, *state;
80         size_t length;
81         int r;
82
83         assert(m);
84         assert(string);
85
86         FOREACH_WORD_QUOTED(word, length, string, state) {
87                 _cleanup_address_free_ Address *address = NULL;
88                 Address *tail;
89                 _cleanup_free_ char *addrstr = NULL;
90
91                 r = address_new_dynamic(&address);
92                 if (r < 0)
93                         return r;
94
95                 addrstr = strndup(word, length);
96                 if (!addrstr)
97                         return -ENOMEM;
98
99                 r = net_parse_inaddr(addrstr, &address->family, &address->in_addr);
100                 if (r < 0) {
101                         log_debug("Ignoring invalid DNS address '%s'", addrstr);
102                         continue;
103                 }
104
105                 LIST_FIND_TAIL(addresses, m->fallback_dns, tail);
106                 LIST_INSERT_AFTER(addresses, m->fallback_dns, tail, address);
107                 address = NULL;
108         }
109
110         return 0;
111 }
112
113 int manager_new(Manager **ret) {
114         _cleanup_manager_free_ Manager *m = NULL;
115         int r;
116
117         m = new0(Manager, 1);
118         if (!m)
119                 return -ENOMEM;
120
121         m->state_file = strdup("/run/systemd/network/state");
122         if (!m->state_file)
123                 return -ENOMEM;
124
125         r = set_fallback_dns(m, DNS_SERVERS);
126         if (r < 0)
127                 return r;
128
129         r = sd_event_default(&m->event);
130         if (r < 0)
131                 return r;
132
133         sd_event_set_watchdog(m->event, true);
134
135         r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
136                          RTNLGRP_IPV6_IFADDR);
137         if (r < 0)
138                 return r;
139
140         r = sd_bus_default_system(&m->bus);
141         if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
142                 return r;
143
144         r = setup_signals(m);
145         if (r < 0)
146                 return r;
147
148         /* udev does not initialize devices inside containers,
149          * so we rely on them being already initialized before
150          * entering the container */
151         if (detect_container(NULL) <= 0) {
152                 m->udev = udev_new();
153                 if (!m->udev)
154                         return -ENOMEM;
155
156                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
157                 if (!m->udev_monitor)
158                         return -ENOMEM;
159         }
160
161         m->kmod_ctx = kmod_new(NULL, NULL);
162         if (!m->kmod_ctx)
163                 return -ENOMEM;
164
165         m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
166         if (!m->links)
167                 return -ENOMEM;
168
169         m->netdevs = hashmap_new(string_hash_func, string_compare_func);
170         if (!m->netdevs)
171                 return -ENOMEM;
172
173         LIST_HEAD_INIT(m->networks);
174
175         *ret = m;
176         m = NULL;
177
178         return 0;
179 }
180
181 void manager_free(Manager *m) {
182         Network *network;
183         NetDev *netdev;
184         Link *link;
185
186         if (!m)
187                 return;
188
189         free(m->state_file);
190
191         kmod_unref(m->kmod_ctx);
192         udev_monitor_unref(m->udev_monitor);
193         udev_unref(m->udev);
194         sd_bus_unref(m->bus);
195         sd_event_source_unref(m->udev_event_source);
196         sd_event_source_unref(m->sigterm_event_source);
197         sd_event_source_unref(m->sigint_event_source);
198         sd_event_unref(m->event);
199
200         while ((link = hashmap_first(m->links)))
201                 link_unref(link);
202         hashmap_free(m->links);
203
204         while ((network = m->networks))
205                 network_free(network);
206
207         while ((netdev = hashmap_first(m->netdevs)))
208                 netdev_unref(netdev);
209         hashmap_free(m->netdevs);
210
211         sd_rtnl_unref(m->rtnl);
212
213         free(m);
214 }
215
216 int manager_load_config(Manager *m) {
217         int r;
218
219         /* update timestamp */
220         paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
221
222         r = netdev_load(m);
223         if (r < 0)
224                 return r;
225
226         r = network_load(m);
227         if (r < 0)
228                 return r;
229
230         return 0;
231 }
232
233 bool manager_should_reload(Manager *m) {
234         return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
235 }
236
237 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
238         Link *link = NULL;
239         int r, ifindex;
240
241         assert(m);
242         assert(device);
243
244         if (!streq_ptr(udev_device_get_action(device), "add"))
245                 return 0;
246
247         ifindex = udev_device_get_ifindex(device);
248         if (ifindex <= 0) {
249                 log_debug("ignoring udev ADD event for device with invalid ifindex");
250                 return 0;
251         }
252
253         r = link_get(m, ifindex, &link);
254         if (r == -ENODEV)
255                 return 0;
256         else if (r < 0)
257                 return r;
258
259         r = link_initialized(link, device);
260         if (r < 0)
261                 return r;
262
263         return 0;
264 }
265
266 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
267         Manager *m = userdata;
268         Link *link = NULL;
269         NetDev *netdev = NULL;
270         uint16_t type;
271         char *name;
272         int r, ifindex;
273
274         assert(rtnl);
275         assert(message);
276         assert(m);
277
278         r = sd_rtnl_message_get_type(message, &type);
279         if (r < 0) {
280                 log_warning("rtnl: could not get message type");
281                 return 0;
282         }
283
284         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
285         if (r < 0 || ifindex <= 0) {
286                 log_warning("rtnl: received link message without valid ifindex");
287                 return 0;
288         } else
289                 link_get(m, ifindex, &link);
290
291         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
292         if (r < 0 || !name) {
293                 log_warning("rtnl: received link message without valid ifname");
294                 return 0;
295         } else
296                 netdev_get(m, name, &netdev);
297
298         switch (type) {
299         case RTM_NEWLINK:
300                 if (!link) {
301                         /* link is new, so add it */
302                         r = link_add(m, message, &link);
303                         if (r < 0) {
304                                 log_debug("could not add new link");
305                                 return 0;
306                         }
307                 }
308
309                 if (netdev) {
310                         /* netdev exists, so make sure the ifindex matches */
311                         r = netdev_set_ifindex(netdev, message);
312                         if (r < 0) {
313                                 log_debug("could not set ifindex on netdev");
314                                 return 0;
315                         }
316                 }
317
318                 r = link_update(link, message);
319                 if (r < 0)
320                         return 0;
321
322                 break;
323
324         case RTM_DELLINK:
325                 link_drop(link);
326                 netdev_drop(netdev);
327
328                 break;
329
330         default:
331                 assert_not_reached("Received invalid RTNL message type.");
332         }
333
334         return 1;
335 }
336
337 int manager_rtnl_enumerate_links(Manager *m) {
338         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
339         sd_rtnl_message *link;
340         int r, k;
341
342         assert(m);
343         assert(m->rtnl);
344
345         r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
346         if (r < 0)
347                 return r;
348
349         r = sd_rtnl_message_request_dump(req, true);
350         if (r < 0)
351                 return r;
352
353         r = sd_rtnl_call(m->rtnl, req, 0, &reply);
354         if (r < 0)
355                 return r;
356
357         for (link = reply; link; link = sd_rtnl_message_next(link)) {
358                 uint16_t type;
359
360                 k = sd_rtnl_message_get_type(link, &type);
361                 if (k < 0)
362                         return k;
363
364                 if (type != RTM_NEWLINK)
365                         continue;
366
367                 k = manager_rtnl_process_link(m->rtnl, link, m);
368                 if (k < 0)
369                         r = k;
370         }
371
372         return r;
373 }
374
375 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
376         Manager *m = userdata;
377         struct udev_monitor *monitor = m->udev_monitor;
378         _cleanup_udev_device_unref_ struct udev_device *device = NULL;
379
380         device = udev_monitor_receive_device(monitor);
381         if (!device)
382                 return -ENOMEM;
383
384         manager_udev_process_link(m, device);
385         return 0;
386 }
387
388 int manager_udev_listen(Manager *m) {
389         int r;
390
391         if (detect_container(NULL) > 0)
392                 return 0;
393
394         assert(m->udev_monitor);
395
396         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
397         if (r < 0) {
398                 log_error("Could not add udev monitor filter: %s", strerror(-r));
399                 return r;
400         }
401
402         r = udev_monitor_enable_receiving(m->udev_monitor);
403         if (r < 0) {
404                 log_error("Could not enable udev monitor");
405                 return r;
406         }
407
408         r = sd_event_add_io(m->event,
409                         &m->udev_event_source,
410                         udev_monitor_get_fd(m->udev_monitor),
411                         EPOLLIN, manager_dispatch_link_udev,
412                         m);
413         if (r < 0)
414                 return r;
415
416         return 0;
417 }
418
419 int manager_rtnl_listen(Manager *m) {
420         int r;
421
422         r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
423         if (r < 0)
424                 return r;
425
426         r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
427         if (r < 0)
428                 return r;
429
430         r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
431         if (r < 0)
432                 return r;
433
434         r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
435         if (r < 0)
436                 return r;
437
438         r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
439         if (r < 0)
440                 return r;
441
442         return 0;
443 }
444
445 int manager_bus_listen(Manager *m) {
446         int r;
447
448         assert(m->event);
449
450         if (!m->bus) /* TODO: drop when we can rely on kdbus */
451                 return 0;
452
453         r = sd_bus_attach_event(m->bus, m->event, 0);
454         if (r < 0)
455                 return r;
456
457         return 0;
458 }
459
460 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
461         char buf[INET6_ADDRSTRLEN];
462         const char *address;
463
464         address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
465         if (!address) {
466                 log_warning("Invalid DNS address. Ignoring.");
467                 return;
468         }
469
470         if (*count == MAXNS)
471                 fputs("# Too many DNS servers configured, the following entries "
472                       "will be ignored\n", f);
473
474         fprintf(f, "nameserver %s\n", address);
475
476         (*count) ++;
477 }
478
479 int manager_update_resolv_conf(Manager *m) {
480         _cleanup_free_ char *temp_path = NULL;
481         _cleanup_fclose_ FILE *f = NULL;
482         Link *link;
483         Iterator i;
484         unsigned count = 0;
485         const char *domainname = NULL;
486         int r;
487
488         assert(m);
489
490         r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
491         if (r < 0)
492                 return r;
493
494         fchmod(fileno(f), 0644);
495
496         fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
497               "# Third party programs must not access this file directly, but\n"
498               "# only through the symlink at /etc/resolv.conf. To manage\n"
499               "# resolv.conf(5) in a different way, replace the symlink by a\n"
500               "# static file or a different symlink.\n\n", f);
501
502         HASHMAP_FOREACH(link, m->links, i) {
503                 if (link->dhcp_lease) {
504                         struct in_addr *nameservers;
505                         size_t nameservers_size;
506
507                         if (link->network->dhcp_dns) {
508                                 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
509                                 if (r >= 0) {
510                                         unsigned j;
511
512                                         for (j = 0; j < nameservers_size; j++)
513                                                 append_dns(f, &nameservers[j], AF_INET, &count);
514                                 }
515                         }
516
517                         if (link->network->dhcp_domainname && !domainname) {
518                                 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
519                                 if (r >= 0)
520                                        fprintf(f, "domain %s\n", domainname);
521                         }
522                 }
523         }
524
525         HASHMAP_FOREACH(link, m->links, i) {
526                 if (link->network && link->network->dns) {
527                         Address *address;
528
529                         LIST_FOREACH(addresses, address, link->network->dns) {
530                                 append_dns(f, &address->in_addr.in,
531                                            address->family, &count);
532                         }
533                 }
534         }
535
536         if (!count) {
537                 Address *address;
538
539                 LIST_FOREACH(addresses, address, m->fallback_dns)
540                         append_dns(f, &address->in_addr.in,
541                                    address->family, &count);
542         }
543
544         fflush(f);
545
546         if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
547                 r = -errno;
548                 unlink("/run/systemd/network/resolv.conf");
549                 unlink(temp_path);
550                 return r;
551         }
552
553         return 0;
554 }
555
556 int manager_save(Manager *m) {
557         Link *link;
558         Iterator i;
559         _cleanup_free_ char *temp_path = NULL;
560         _cleanup_fclose_ FILE *f = NULL;
561         const char *oper_state = "unknown";
562         bool dormant = false, carrier = false;
563         int r;
564
565         assert(m);
566         assert(m->state_file);
567
568         HASHMAP_FOREACH(link, m->links, i) {
569                 if (link->flags & IFF_LOOPBACK)
570                         continue;
571
572                 if (link_has_carrier(link->flags, link->operstate))
573                         carrier = true;
574                 else if (link->operstate == IF_OPER_DORMANT)
575                         dormant = true;
576         }
577
578         if (carrier)
579                 oper_state = "carrier";
580         else if (dormant)
581                 oper_state = "dormant";
582
583         r = fopen_temporary(m->state_file, &f, &temp_path);
584         if (r < 0)
585                 goto finish;
586
587         fchmod(fileno(f), 0644);
588
589         fprintf(f,
590                 "# This is private data. Do not parse.\n"
591                 "OPER_STATE=%s\n", oper_state);
592
593         fflush(f);
594
595         if (ferror(f) || rename(temp_path, m->state_file) < 0) {
596                 r = -errno;
597                 unlink(m->state_file);
598                 unlink(temp_path);
599         }
600
601 finish:
602         if (r < 0)
603                 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
604
605         return r;
606 }