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