chiark / gitweb /
install: improve paths we show the user when enabling/disabling
[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 <sys/socket.h>
23 #include <linux/if.h>
24
25 #include "conf-parser.h"
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 int manager_new(Manager **ret) {
79         _cleanup_manager_free_ Manager *m = NULL;
80         int r;
81
82         m = new0(Manager, 1);
83         if (!m)
84                 return -ENOMEM;
85
86         m->state_file = strdup("/run/systemd/netif/state");
87         if (!m->state_file)
88                 return -ENOMEM;
89
90         r = sd_event_default(&m->event);
91         if (r < 0)
92                 return r;
93
94         sd_event_set_watchdog(m->event, true);
95
96         r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
97                          RTNLGRP_IPV6_IFADDR);
98         if (r < 0)
99                 return r;
100
101         r = sd_bus_default_system(&m->bus);
102         if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
103                 return r;
104
105         r = setup_signals(m);
106         if (r < 0)
107                 return r;
108
109         /* udev does not initialize devices inside containers,
110          * so we rely on them being already initialized before
111          * entering the container */
112         if (detect_container(NULL) <= 0) {
113                 m->udev = udev_new();
114                 if (!m->udev)
115                         return -ENOMEM;
116
117                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
118                 if (!m->udev_monitor)
119                         return -ENOMEM;
120         }
121
122         m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
123         if (!m->links)
124                 return -ENOMEM;
125
126         m->netdevs = hashmap_new(string_hash_func, string_compare_func);
127         if (!m->netdevs)
128                 return -ENOMEM;
129
130         LIST_HEAD_INIT(m->networks);
131
132         *ret = m;
133         m = NULL;
134
135         return 0;
136 }
137
138 void manager_free(Manager *m) {
139         Network *network;
140         NetDev *netdev;
141         Link *link;
142
143         if (!m)
144                 return;
145
146         free(m->state_file);
147
148         udev_monitor_unref(m->udev_monitor);
149         udev_unref(m->udev);
150         sd_bus_unref(m->bus);
151         sd_event_source_unref(m->udev_event_source);
152         sd_event_source_unref(m->sigterm_event_source);
153         sd_event_source_unref(m->sigint_event_source);
154         sd_event_unref(m->event);
155
156         while ((link = hashmap_first(m->links)))
157                 link_unref(link);
158         hashmap_free(m->links);
159
160         while ((network = m->networks))
161                 network_free(network);
162
163         while ((netdev = hashmap_first(m->netdevs)))
164                 netdev_unref(netdev);
165         hashmap_free(m->netdevs);
166
167         sd_rtnl_unref(m->rtnl);
168
169         free(m);
170 }
171
172 int manager_load_config(Manager *m) {
173         int r;
174
175         /* update timestamp */
176         paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
177
178         r = netdev_load(m);
179         if (r < 0)
180                 return r;
181
182         r = network_load(m);
183         if (r < 0)
184                 return r;
185
186         return 0;
187 }
188
189 bool manager_should_reload(Manager *m) {
190         return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
191 }
192
193 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
194         Link *link = NULL;
195         int r, ifindex;
196
197         assert(m);
198         assert(device);
199
200         if (!streq_ptr(udev_device_get_action(device), "add"))
201                 return 0;
202
203         ifindex = udev_device_get_ifindex(device);
204         if (ifindex <= 0) {
205                 log_debug("ignoring udev ADD event for device with invalid ifindex");
206                 return 0;
207         }
208
209         r = link_get(m, ifindex, &link);
210         if (r == -ENODEV)
211                 return 0;
212         else if (r < 0)
213                 return r;
214
215         r = link_initialized(link, device);
216         if (r < 0)
217                 return r;
218
219         return 0;
220 }
221
222 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
223         Manager *m = userdata;
224         Link *link = NULL;
225         NetDev *netdev = NULL;
226         uint16_t type;
227         char *name;
228         int r, ifindex;
229
230         assert(rtnl);
231         assert(message);
232         assert(m);
233
234         r = sd_rtnl_message_get_type(message, &type);
235         if (r < 0) {
236                 log_warning("rtnl: could not get message type");
237                 return 0;
238         }
239
240         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
241         if (r < 0 || ifindex <= 0) {
242                 log_warning("rtnl: received link message without valid ifindex");
243                 return 0;
244         } else
245                 link_get(m, ifindex, &link);
246
247         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
248         if (r < 0 || !name) {
249                 log_warning("rtnl: received link message without valid ifname");
250                 return 0;
251         } else
252                 netdev_get(m, name, &netdev);
253
254         switch (type) {
255         case RTM_NEWLINK:
256                 if (!link) {
257                         /* link is new, so add it */
258                         r = link_add(m, message, &link);
259                         if (r < 0) {
260                                 log_debug("could not add new link");
261                                 return 0;
262                         }
263                 }
264
265                 if (netdev) {
266                         /* netdev exists, so make sure the ifindex matches */
267                         r = netdev_set_ifindex(netdev, message);
268                         if (r < 0) {
269                                 log_debug("could not set ifindex on netdev");
270                                 return 0;
271                         }
272                 }
273
274                 r = link_update(link, message);
275                 if (r < 0)
276                         return 0;
277
278                 break;
279
280         case RTM_DELLINK:
281                 link_drop(link);
282                 netdev_drop(netdev);
283
284                 break;
285
286         default:
287                 assert_not_reached("Received invalid RTNL message type.");
288         }
289
290         return 1;
291 }
292
293 int manager_rtnl_enumerate_links(Manager *m) {
294         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
295         sd_rtnl_message *link;
296         int r, k;
297
298         assert(m);
299         assert(m->rtnl);
300
301         r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
302         if (r < 0)
303                 return r;
304
305         r = sd_rtnl_message_request_dump(req, true);
306         if (r < 0)
307                 return r;
308
309         r = sd_rtnl_call(m->rtnl, req, 0, &reply);
310         if (r < 0)
311                 return r;
312
313         for (link = reply; link; link = sd_rtnl_message_next(link)) {
314                 uint16_t type;
315
316                 k = sd_rtnl_message_get_type(link, &type);
317                 if (k < 0)
318                         return k;
319
320                 if (type != RTM_NEWLINK)
321                         continue;
322
323                 k = manager_rtnl_process_link(m->rtnl, link, m);
324                 if (k < 0)
325                         r = k;
326         }
327
328         return r;
329 }
330
331 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
332         Manager *m = userdata;
333         struct udev_monitor *monitor = m->udev_monitor;
334         _cleanup_udev_device_unref_ struct udev_device *device = NULL;
335
336         device = udev_monitor_receive_device(monitor);
337         if (!device)
338                 return -ENOMEM;
339
340         manager_udev_process_link(m, device);
341         return 0;
342 }
343
344 int manager_udev_listen(Manager *m) {
345         int r;
346
347         if (detect_container(NULL) > 0)
348                 return 0;
349
350         assert(m->udev_monitor);
351
352         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
353         if (r < 0) {
354                 log_error("Could not add udev monitor filter: %s", strerror(-r));
355                 return r;
356         }
357
358         r = udev_monitor_enable_receiving(m->udev_monitor);
359         if (r < 0) {
360                 log_error("Could not enable udev monitor");
361                 return r;
362         }
363
364         r = sd_event_add_io(m->event,
365                         &m->udev_event_source,
366                         udev_monitor_get_fd(m->udev_monitor),
367                         EPOLLIN, manager_dispatch_link_udev,
368                         m);
369         if (r < 0)
370                 return r;
371
372         return 0;
373 }
374
375 int manager_rtnl_listen(Manager *m) {
376         int r;
377
378         r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
379         if (r < 0)
380                 return r;
381
382         r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
383         if (r < 0)
384                 return r;
385
386         r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
387         if (r < 0)
388                 return r;
389
390         r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
391         if (r < 0)
392                 return r;
393
394         r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
395         if (r < 0)
396                 return r;
397
398         return 0;
399 }
400
401 int manager_bus_listen(Manager *m) {
402         int r;
403
404         assert(m->event);
405
406         if (!m->bus) /* TODO: drop when we can rely on kdbus */
407                 return 0;
408
409         r = sd_bus_attach_event(m->bus, m->event, 0);
410         if (r < 0)
411                 return r;
412
413         return 0;
414 }
415
416 int manager_save(Manager *m) {
417         Link *link;
418         Iterator i;
419         _cleanup_free_ char *temp_path = NULL;
420         _cleanup_fclose_ FILE *f = NULL;
421         LinkOperationalState operstate = LINK_OPERSTATE_UNKNOWN;
422         const char *operstate_str;
423         int r;
424
425         assert(m);
426         assert(m->state_file);
427
428         HASHMAP_FOREACH(link, m->links, i) {
429                 if (link->flags & IFF_LOOPBACK)
430                         continue;
431
432                 if (link->operstate > operstate)
433                         operstate = link->operstate;
434         }
435
436         operstate_str = link_operstate_to_string(operstate);
437         assert(operstate_str);
438
439         r = fopen_temporary(m->state_file, &f, &temp_path);
440         if (r < 0)
441                 goto finish;
442
443         fchmod(fileno(f), 0644);
444
445         fprintf(f,
446                 "# This is private data. Do not parse.\n"
447                 "OPER_STATE=%s\n", operstate_str);
448
449         fflush(f);
450
451         if (ferror(f) || rename(temp_path, m->state_file) < 0) {
452                 r = -errno;
453                 unlink(m->state_file);
454                 unlink(temp_path);
455         }
456
457 finish:
458         if (r < 0)
459                 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
460
461         return r;
462 }