]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-manager.c
networkd: netdev - introduce vtable for netdev kinds
[thirdparty/systemd.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 "networkd-netdev.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 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
74 int 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
82 m->state_file = strdup("/run/systemd/netif/state");
83 if (!m->state_file)
84 return -ENOMEM;
85
86 r = sd_event_default(&m->event);
87 if (r < 0)
88 return r;
89
90 sd_event_set_watchdog(m->event, true);
91
92 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
93 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
94
95 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
96 RTNLGRP_IPV6_IFADDR);
97 if (r < 0)
98 return r;
99
100 r = sd_bus_default_system(&m->bus);
101 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
102 return r;
103
104 /* udev does not initialize devices inside containers,
105 * so we rely on them being already initialized before
106 * entering the container */
107 if (detect_container(NULL) <= 0) {
108 m->udev = udev_new();
109 if (!m->udev)
110 return -ENOMEM;
111
112 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
113 if (!m->udev_monitor)
114 return -ENOMEM;
115 }
116
117 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
118 if (!m->links)
119 return -ENOMEM;
120
121 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
122 if (!m->netdevs)
123 return -ENOMEM;
124
125 LIST_HEAD_INIT(m->networks);
126
127 r = setup_default_address_pool(m);
128 if (r < 0)
129 return r;
130
131 *ret = m;
132 m = NULL;
133
134 return 0;
135 }
136
137 void manager_free(Manager *m) {
138 Network *network;
139 NetDev *netdev;
140 Link *link;
141 AddressPool *pool;
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 while ((pool = m->address_pools))
168 address_pool_free(pool);
169
170 sd_rtnl_unref(m->rtnl);
171
172 free(m);
173 }
174
175 int manager_load_config(Manager *m) {
176 int r;
177
178 /* update timestamp */
179 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
180
181 r = netdev_load(m);
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
192 bool manager_should_reload(Manager *m) {
193 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
194 }
195
196 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
197 Link *link = NULL;
198 int r, ifindex;
199
200 assert(m);
201 assert(device);
202
203 if (!streq_ptr(udev_device_get_action(device), "add"))
204 return 0;
205
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 }
211
212 r = link_get(m, ifindex, &link);
213 if (r == -ENODEV)
214 return 0;
215 else if (r < 0)
216 return r;
217
218 r = link_initialized(link, device);
219 if (r < 0)
220 return r;
221
222 return 0;
223 }
224
225 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
226 Manager *m = userdata;
227 Link *link = NULL;
228 NetDev *netdev = NULL;
229 uint16_t type;
230 char *name;
231 int r, ifindex;
232
233 assert(rtnl);
234 assert(message);
235 assert(m);
236
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
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;
247 } else
248 link_get(m, ifindex, &link);
249
250 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
251 if (r < 0 || !name) {
252 log_warning("rtnl: received link message without valid ifname");
253 return 0;
254 } else
255 netdev_get(m, name, &netdev);
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) {
263 log_debug("could not add new link: %s",
264 strerror(-r));
265 return 0;
266 }
267 }
268
269 if (netdev) {
270 /* netdev exists, so make sure the ifindex matches */
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 }
277
278 r = link_update(link, message);
279 if (r < 0)
280 return 0;
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.");
292 }
293
294 return 1;
295 }
296
297 int 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);
310 if (r < 0)
311 return r;
312
313 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
314 if (r < 0)
315 return r;
316
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;
326
327 k = manager_rtnl_process_link(m->rtnl, link, m);
328 if (k < 0)
329 r = k;
330 }
331
332 return r;
333 }
334
335 static 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;
338 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
339
340 device = udev_monitor_receive_device(monitor);
341 if (!device)
342 return -ENOMEM;
343
344 manager_udev_process_link(m, device);
345 return 0;
346 }
347
348 int manager_udev_listen(Manager *m) {
349 int r;
350
351 if (detect_container(NULL) > 0)
352 return 0;
353
354 assert(m->udev_monitor);
355
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
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,
369 &m->udev_event_source,
370 udev_monitor_get_fd(m->udev_monitor),
371 EPOLLIN, manager_dispatch_link_udev,
372 m);
373 if (r < 0)
374 return r;
375
376 return 0;
377 }
378
379 int manager_rtnl_listen(Manager *m) {
380 int r;
381
382 assert(m);
383
384 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
385 if (r < 0)
386 return r;
387
388 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
389 if (r < 0)
390 return r;
391
392 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
393 if (r < 0)
394 return r;
395
396 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
397 if (r < 0)
398 return r;
399
400 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
401 if (r < 0)
402 return r;
403
404 return 0;
405 }
406
407 int manager_bus_listen(Manager *m) {
408 int r;
409
410 assert(m->event);
411
412 if (!m->bus) /* TODO: drop when we can rely on kdbus */
413 return 0;
414
415 r = sd_bus_attach_event(m->bus, m->event, 0);
416 if (r < 0)
417 return r;
418
419 return 0;
420 }
421
422 int manager_save(Manager *m) {
423 Link *link;
424 Iterator i;
425 _cleanup_free_ char *temp_path = NULL;
426 _cleanup_fclose_ FILE *f = NULL;
427 LinkOperationalState operstate = LINK_OPERSTATE_UNKNOWN;
428 const char *operstate_str;
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
438 if (link->operstate > operstate)
439 operstate = link->operstate;
440 }
441
442 operstate_str = link_operstate_to_string(operstate);
443 assert(operstate_str);
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"
453 "OPER_STATE=%s\n", operstate_str);
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
463 finish:
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 }
469
470 int 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 }