]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
update TODO
[thirdparty/systemd.git] / src / network / networkd-manager.c
CommitLineData
f579559b
TG
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
091a364c 22#include <sys/socket.h>
bbf7c048 23#include <linux/if.h>
3bef724f 24
2dcf7ec6 25#include "conf-parser.h"
f579559b
TG
26#include "path-util.h"
27#include "networkd.h"
e16cb2e4 28#include "network-internal.h"
f579559b 29#include "libudev-private.h"
7b77ed8c 30#include "udev-util.h"
50add290 31#include "rtnl-util.h"
3bef724f 32#include "mkdir.h"
60ad0c85 33#include "virt.h"
f579559b 34
505f8da7
TG
35#include "sd-rtnl.h"
36
2ad8416d
ZJS
37const char* const network_dirs[] = {
38 "/etc/systemd/network",
39 "/run/systemd/network",
40 "/usr/lib/systemd/network",
eed0eee8 41#ifdef HAVE_SPLIT_USR
2ad8416d
ZJS
42 "/lib/systemd/network",
43#endif
44 NULL};
45
0c2f9b84
TG
46static 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
57static 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
11bf3cce
LP
78static int setup_default_address_pool(Manager *m) {
79 AddressPool *p;
80 int r;
81
82 assert(m);
83
84 /* Add in the well-known private address ranges. */
85
86 r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7);
87 if (r < 0)
88 return r;
89
90 r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
91 if (r < 0)
92 return r;
93
94 r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12);
95 if (r < 0)
96 return r;
97
98 r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
99 if (r < 0)
100 return r;
101
102 return 0;
103}
104
f579559b
TG
105int manager_new(Manager **ret) {
106 _cleanup_manager_free_ Manager *m = NULL;
107 int r;
108
109 m = new0(Manager, 1);
110 if (!m)
111 return -ENOMEM;
112
85b5673b 113 m->state_file = strdup("/run/systemd/netif/state");
bbf7c048
TG
114 if (!m->state_file)
115 return -ENOMEM;
116
afc6adb5 117 r = sd_event_default(&m->event);
f579559b
TG
118 if (r < 0)
119 return r;
120
cde93897
LP
121 sd_event_set_watchdog(m->event, true);
122
897e184c
TG
123 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
124 RTNLGRP_IPV6_IFADDR);
f579559b
TG
125 if (r < 0)
126 return r;
127
1346b1f0 128 r = sd_bus_default_system(&m->bus);
bcbca829 129 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
1346b1f0
TG
130 return r;
131
0c2f9b84
TG
132 r = setup_signals(m);
133 if (r < 0)
134 return r;
135
60ad0c85
TG
136 /* udev does not initialize devices inside containers,
137 * so we rely on them being already initialized before
138 * entering the container */
505f8da7
TG
139 if (detect_container(NULL) <= 0) {
140 m->udev = udev_new();
141 if (!m->udev)
60ad0c85 142 return -ENOMEM;
505f8da7 143
60ad0c85
TG
144 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
145 if (!m->udev_monitor)
146 return -ENOMEM;
147 }
f579559b
TG
148
149 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
150 if (!m->links)
151 return -ENOMEM;
152
52433f6b
TG
153 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
154 if (!m->netdevs)
02b59d57
TG
155 return -ENOMEM;
156
f579559b
TG
157 LIST_HEAD_INIT(m->networks);
158
11bf3cce
LP
159 r = setup_default_address_pool(m);
160 if (r < 0)
161 return r;
162
f579559b
TG
163 *ret = m;
164 m = NULL;
165
166 return 0;
167}
168
169void manager_free(Manager *m) {
0617ffab 170 Network *network;
1a436809 171 NetDev *netdev;
0617ffab 172 Link *link;
11bf3cce 173 AddressPool *pool;
0617ffab 174
624b5a63
TG
175 if (!m)
176 return;
177
bbf7c048
TG
178 free(m->state_file);
179
f579559b
TG
180 udev_monitor_unref(m->udev_monitor);
181 udev_unref(m->udev);
1346b1f0 182 sd_bus_unref(m->bus);
f579559b 183 sd_event_source_unref(m->udev_event_source);
0c2f9b84
TG
184 sd_event_source_unref(m->sigterm_event_source);
185 sd_event_source_unref(m->sigint_event_source);
f579559b 186 sd_event_unref(m->event);
0617ffab 187
0617ffab 188 while ((link = hashmap_first(m->links)))
14b746f7 189 link_unref(link);
f579559b 190 hashmap_free(m->links);
0617ffab 191
2292547a
TG
192 while ((network = m->networks))
193 network_free(network);
194
52433f6b 195 while ((netdev = hashmap_first(m->netdevs)))
14b746f7 196 netdev_unref(netdev);
52433f6b 197 hashmap_free(m->netdevs);
02b59d57 198
11bf3cce
LP
199 while ((pool = m->address_pools))
200 address_pool_free(pool);
201
f579559b
TG
202 sd_rtnl_unref(m->rtnl);
203
204 free(m);
205}
206
02b59d57
TG
207int manager_load_config(Manager *m) {
208 int r;
209
210 /* update timestamp */
2ad8416d 211 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
02b59d57 212
52433f6b 213 r = netdev_load(m);
02b59d57
TG
214 if (r < 0)
215 return r;
216
217 r = network_load(m);
218 if (r < 0)
219 return r;
220
221 return 0;
222}
223
224bool manager_should_reload(Manager *m) {
2ad8416d 225 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
02b59d57
TG
226}
227
505f8da7 228static int manager_udev_process_link(Manager *m, struct udev_device *device) {
11a7f229 229 Link *link = NULL;
667fcc6d 230 int r, ifindex;
f579559b 231
11a7f229
TG
232 assert(m);
233 assert(device);
f579559b 234
505f8da7
TG
235 if (!streq_ptr(udev_device_get_action(device), "add"))
236 return 0;
237
667fcc6d
TG
238 ifindex = udev_device_get_ifindex(device);
239 if (ifindex <= 0) {
240 log_debug("ignoring udev ADD event for device with invalid ifindex");
241 return 0;
242 }
505f8da7 243
667fcc6d
TG
244 r = link_get(m, ifindex, &link);
245 if (r == -ENODEV)
505f8da7 246 return 0;
667fcc6d
TG
247 else if (r < 0)
248 return r;
505f8da7
TG
249
250 r = link_initialized(link, device);
251 if (r < 0)
252 return r;
11a7f229 253
505f8da7
TG
254 return 0;
255}
f579559b 256
505f8da7
TG
257static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
258 Manager *m = userdata;
259 Link *link = NULL;
4d473d5d 260 NetDev *netdev = NULL;
f2236469 261 uint16_t type;
505f8da7
TG
262 char *name;
263 int r, ifindex;
f579559b 264
505f8da7
TG
265 assert(rtnl);
266 assert(message);
f579559b
TG
267 assert(m);
268
f2236469
TG
269 r = sd_rtnl_message_get_type(message, &type);
270 if (r < 0) {
271 log_warning("rtnl: could not get message type");
272 return 0;
273 }
274
505f8da7
TG
275 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
276 if (r < 0 || ifindex <= 0) {
277 log_warning("rtnl: received link message without valid ifindex");
278 return 0;
4d473d5d
TG
279 } else
280 link_get(m, ifindex, &link);
f579559b 281
505f8da7 282 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
4d473d5d 283 if (r < 0 || !name) {
505f8da7 284 log_warning("rtnl: received link message without valid ifname");
4d473d5d
TG
285 return 0;
286 } else
f2236469 287 netdev_get(m, name, &netdev);
4d473d5d
TG
288
289 switch (type) {
290 case RTM_NEWLINK:
291 if (!link) {
292 /* link is new, so add it */
293 r = link_add(m, message, &link);
294 if (r < 0) {
295 log_debug("could not add new link");
296 return 0;
297 }
298 }
299
300 if (netdev) {
301 /* netdev exists, so make sure the ifindex matches */
505f8da7
TG
302 r = netdev_set_ifindex(netdev, message);
303 if (r < 0) {
304 log_debug("could not set ifindex on netdev");
305 return 0;
306 }
307 }
e1202047 308
f2236469
TG
309 r = link_update(link, message);
310 if (r < 0)
311 return 0;
4d473d5d
TG
312
313 break;
314
315 case RTM_DELLINK:
316 link_drop(link);
317 netdev_drop(netdev);
318
319 break;
320
321 default:
322 assert_not_reached("Received invalid RTNL message type.");
f2236469 323 }
505f8da7
TG
324
325 return 1;
326}
327
328int manager_rtnl_enumerate_links(Manager *m) {
329 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
330 sd_rtnl_message *link;
331 int r, k;
332
333 assert(m);
334 assert(m->rtnl);
335
336 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
337 if (r < 0)
338 return r;
339
340 r = sd_rtnl_message_request_dump(req, true);
f579559b 341 if (r < 0)
bf5332d2 342 return r;
f579559b 343
505f8da7
TG
344 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
345 if (r < 0)
346 return r;
f579559b 347
505f8da7
TG
348 for (link = reply; link; link = sd_rtnl_message_next(link)) {
349 uint16_t type;
350
351 k = sd_rtnl_message_get_type(link, &type);
352 if (k < 0)
353 return k;
354
355 if (type != RTM_NEWLINK)
356 continue;
f579559b 357
505f8da7 358 k = manager_rtnl_process_link(m->rtnl, link, m);
f579559b
TG
359 if (k < 0)
360 r = k;
361 }
362
f579559b
TG
363 return r;
364}
365
366static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
367 Manager *m = userdata;
368 struct udev_monitor *monitor = m->udev_monitor;
7b77ed8c 369 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
f579559b
TG
370
371 device = udev_monitor_receive_device(monitor);
372 if (!device)
373 return -ENOMEM;
374
505f8da7 375 manager_udev_process_link(m, device);
f579559b
TG
376 return 0;
377}
378
379int manager_udev_listen(Manager *m) {
380 int r;
381
505f8da7
TG
382 if (detect_container(NULL) > 0)
383 return 0;
384
385 assert(m->udev_monitor);
386
f579559b
TG
387 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
388 if (r < 0) {
389 log_error("Could not add udev monitor filter: %s", strerror(-r));
390 return r;
391 }
392
f579559b
TG
393 r = udev_monitor_enable_receiving(m->udev_monitor);
394 if (r < 0) {
395 log_error("Could not enable udev monitor");
396 return r;
397 }
398
399 r = sd_event_add_io(m->event,
151b9b96 400 &m->udev_event_source,
f579559b
TG
401 udev_monitor_get_fd(m->udev_monitor),
402 EPOLLIN, manager_dispatch_link_udev,
151b9b96 403 m);
f579559b
TG
404 if (r < 0)
405 return r;
406
407 return 0;
408}
f882c247
TG
409
410int manager_rtnl_listen(Manager *m) {
411 int r;
412
413 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
414 if (r < 0)
415 return r;
416
dd3efc09
TG
417 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
418 if (r < 0)
419 return r;
420
f2236469
TG
421 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
422 if (r < 0)
423 return r;
424
fbbeb65a 425 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
2e9f08ea
TG
426 if (r < 0)
427 return r;
428
fbbeb65a 429 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
2e9f08ea
TG
430 if (r < 0)
431 return r;
432
f882c247
TG
433 return 0;
434}
3bef724f 435
1346b1f0
TG
436int manager_bus_listen(Manager *m) {
437 int r;
438
bcbca829
TG
439 assert(m->event);
440
441 if (!m->bus) /* TODO: drop when we can rely on kdbus */
442 return 0;
443
1346b1f0
TG
444 r = sd_bus_attach_event(m->bus, m->event, 0);
445 if (r < 0)
446 return r;
447
448 return 0;
449}
450
bbf7c048
TG
451int manager_save(Manager *m) {
452 Link *link;
453 Iterator i;
454 _cleanup_free_ char *temp_path = NULL;
455 _cleanup_fclose_ FILE *f = NULL;
e375dcde
TG
456 LinkOperationalState operstate = LINK_OPERSTATE_UNKNOWN;
457 const char *operstate_str;
bbf7c048
TG
458 int r;
459
460 assert(m);
461 assert(m->state_file);
462
463 HASHMAP_FOREACH(link, m->links, i) {
464 if (link->flags & IFF_LOOPBACK)
465 continue;
466
e375dcde
TG
467 if (link->operstate > operstate)
468 operstate = link->operstate;
bbf7c048
TG
469 }
470
e375dcde
TG
471 operstate_str = link_operstate_to_string(operstate);
472 assert(operstate_str);
bbf7c048
TG
473
474 r = fopen_temporary(m->state_file, &f, &temp_path);
475 if (r < 0)
476 goto finish;
477
478 fchmod(fileno(f), 0644);
479
480 fprintf(f,
481 "# This is private data. Do not parse.\n"
e375dcde 482 "OPER_STATE=%s\n", operstate_str);
bbf7c048
TG
483
484 fflush(f);
485
486 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
487 r = -errno;
488 unlink(m->state_file);
489 unlink(temp_path);
490 }
491
492finish:
493 if (r < 0)
494 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
495
496 return r;
497}
11bf3cce
LP
498
499int manager_address_pool_acquire(Manager *m, unsigned family, unsigned prefixlen, union in_addr_union *found) {
500 AddressPool *p;
501 int r;
502
503 assert(m);
504 assert(prefixlen > 0);
505 assert(found);
506
507 LIST_FOREACH(address_pools, p, m->address_pools) {
508 if (p->family != family)
509 continue;
510
511 r = address_pool_acquire(p, prefixlen, found);
512 if (r != 0)
513 return r;
514 }
515
516 return 0;
517}