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