]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-netdev.c
networkd: netdev - move tunnel address parsing to networkd-tunnel.c
[thirdparty/systemd.git] / src / network / networkd-netdev.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 <net/if.h>
23
24 #include "networkd.h"
25 #include "network-internal.h"
26 #include "path-util.h"
27 #include "conf-files.h"
28 #include "conf-parser.h"
29 #include "list.h"
30 #include "siphash24.h"
31
32 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
33 [NETDEV_KIND_BRIDGE] = "bridge",
34 [NETDEV_KIND_BOND] = "bond",
35 [NETDEV_KIND_VLAN] = "vlan",
36 [NETDEV_KIND_MACVLAN] = "macvlan",
37 [NETDEV_KIND_VXLAN] = "vxlan",
38 [NETDEV_KIND_IPIP] = "ipip",
39 [NETDEV_KIND_GRE] = "gre",
40 [NETDEV_KIND_SIT] = "sit",
41 [NETDEV_KIND_VETH] = "veth",
42 [NETDEV_KIND_VTI] = "vti",
43 [NETDEV_KIND_DUMMY] = "dummy",
44 [NETDEV_KIND_TUN] = "tun",
45 [NETDEV_KIND_TAP] = "tap",
46 };
47
48 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
49 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
50
51 static void netdev_cancel_callbacks(NetDev *netdev) {
52 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
53 netdev_enslave_callback *callback;
54
55 if (!netdev)
56 return;
57
58 rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
59
60 while ((callback = netdev->callbacks)) {
61 if (m) {
62 assert(callback->link);
63 assert(callback->callback);
64 assert(netdev->manager);
65 assert(netdev->manager->rtnl);
66
67 callback->callback(netdev->manager->rtnl, m, link);
68 }
69
70 LIST_REMOVE(callbacks, netdev->callbacks, callback);
71 free(callback);
72 }
73 }
74
75 static void netdev_free(NetDev *netdev) {
76 if (!netdev)
77 return;
78
79 netdev_cancel_callbacks(netdev);
80
81 if (netdev->ifname)
82 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
83
84 free(netdev->filename);
85
86 free(netdev->description);
87 free(netdev->ifname);
88 free(netdev->ifname_peer);
89 free(netdev->mac);
90 free(netdev->mac_peer);
91 free(netdev->user_name);
92 free(netdev->group_name);
93
94 condition_free_list(netdev->match_host);
95 condition_free_list(netdev->match_virt);
96 condition_free_list(netdev->match_kernel);
97 condition_free_list(netdev->match_arch);
98
99 free(netdev);
100 }
101
102 NetDev *netdev_unref(NetDev *netdev) {
103 if (netdev && (-- netdev->n_ref <= 0))
104 netdev_free(netdev);
105
106 return NULL;
107 }
108
109 NetDev *netdev_ref(NetDev *netdev) {
110 if (netdev)
111 assert_se(++ netdev->n_ref >= 2);
112
113 return netdev;
114 }
115
116 void netdev_drop(NetDev *netdev) {
117 if (!netdev || netdev->state == NETDEV_STATE_LINGER)
118 return;
119
120 netdev->state = NETDEV_STATE_LINGER;
121
122 log_debug_netdev(netdev, "netdev removed");
123
124 netdev_cancel_callbacks(netdev);
125
126 netdev_unref(netdev);
127
128 return;
129 }
130
131 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
132 NetDev *netdev;
133
134 assert(manager);
135 assert(name);
136 assert(ret);
137
138 netdev = hashmap_get(manager->netdevs, name);
139 if (!netdev) {
140 *ret = NULL;
141 return -ENOENT;
142 }
143
144 *ret = netdev;
145
146 return 0;
147 }
148
149 static int netdev_enter_failed(NetDev *netdev) {
150 netdev->state = NETDEV_STATE_FAILED;
151
152 return 0;
153 }
154
155 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
156 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
157 int r;
158
159 assert(netdev);
160 assert(netdev->state == NETDEV_STATE_READY);
161 assert(netdev->manager);
162 assert(netdev->manager->rtnl);
163 assert(link);
164 assert(callback);
165
166 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
167 RTM_SETLINK, link->ifindex);
168 if (r < 0) {
169 log_error_netdev(netdev,
170 "Could not allocate RTM_SETLINK message: %s",
171 strerror(-r));
172 return r;
173 }
174
175 r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
176 if (r < 0) {
177 log_error_netdev(netdev,
178 "Could not append IFLA_MASTER attribute: %s",
179 strerror(-r));
180 return r;
181 }
182
183 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
184 if (r < 0) {
185 log_error_netdev(netdev,
186 "Could not send rtnetlink message: %s",
187 strerror(-r));
188 return r;
189 }
190
191 link_ref(link);
192
193 log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
194
195 return 0;
196 }
197
198 static int netdev_enter_ready(NetDev *netdev) {
199 netdev_enslave_callback *callback, *callback_next;
200 int r;
201
202 assert(netdev);
203 assert(netdev->ifname);
204
205 if (netdev->state != NETDEV_STATE_CREATING)
206 return 0;
207
208 netdev->state = NETDEV_STATE_READY;
209
210 log_info_netdev(netdev, "netdev ready");
211
212 LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) {
213 /* enslave the links that were attempted to be enslaved before the
214 * link was ready */
215 r = netdev_enslave_ready(netdev, callback->link, callback->callback);
216 if (r < 0)
217 return r;
218
219 LIST_REMOVE(callbacks, netdev->callbacks, callback);
220 link_unref(callback->link);
221 free(callback);
222 }
223
224 return 0;
225 }
226
227 /* callback for netdev's created without a backing Link */
228 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
229 _cleanup_netdev_unref_ NetDev *netdev = userdata;
230 int r;
231
232 assert(netdev->state != _NETDEV_STATE_INVALID);
233
234 r = sd_rtnl_message_get_errno(m);
235 if (r == -EEXIST)
236 log_debug_netdev(netdev, "netdev exists, using existing");
237 else if (r < 0) {
238 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
239 netdev_drop(netdev);
240
241 return 1;
242 }
243
244 return 1;
245 }
246
247 static int netdev_create(NetDev *netdev) {
248 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
249 const char *kind;
250 int r;
251
252 assert(netdev);
253 assert(netdev->ifname);
254 assert(netdev->manager);
255 assert(netdev->manager->rtnl);
256
257 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
258 if (r < 0) {
259 log_error_netdev(netdev,
260 "Could not allocate RTM_NEWLINK message: %s",
261 strerror(-r));
262 return r;
263 }
264
265 r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
266 if (r < 0) {
267 log_error_netdev(netdev,
268 "Could not append IFLA_IFNAME attribute: %s",
269 strerror(-r));
270 return r;
271 }
272
273 if (netdev->mtu) {
274 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
275 if (r < 0) {
276 log_error_netdev(netdev,
277 "Could not append IFLA_MTU attribute: %s",
278 strerror(-r));
279 return r;
280 }
281 }
282
283 if (netdev->mac) {
284 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
285 if (r < 0) {
286 log_error_netdev(netdev,
287 "Colud not append IFLA_ADDRESS attribute: %s",
288 strerror(-r));
289 return r;
290 }
291 }
292
293 r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
294 if (r < 0) {
295 log_error_netdev(netdev,
296 "Could not open IFLA_LINKINFO container: %s",
297 strerror(-r));
298 return r;
299 }
300
301 kind = netdev_kind_to_string(netdev->kind);
302 if (!kind) {
303 log_error_netdev(netdev, "Invalid kind");
304 return -EINVAL;
305 }
306
307 r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
308 if (r < 0) {
309 log_error_netdev(netdev,
310 "Could not open IFLA_INFO_DATA container: %s",
311 strerror(-r));
312 return r;
313 }
314
315 r = sd_rtnl_message_close_container(req);
316 if (r < 0) {
317 log_error_netdev(netdev,
318 "Could not close IFLA_INFO_DATA container %s",
319 strerror(-r));
320 return r;
321 }
322
323 r = sd_rtnl_message_close_container(req);
324 if (r < 0) {
325 log_error_netdev(netdev,
326 "Could not close IFLA_LINKINFO container %s",
327 strerror(-r));
328 return r;
329 }
330
331 r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
332 if (r < 0) {
333 log_error_netdev(netdev,
334 "Could not send rtnetlink message: %s", strerror(-r));
335 return r;
336 }
337
338 netdev_ref(netdev);
339
340 log_debug_netdev(netdev, "creating netdev");
341
342 netdev->state = NETDEV_STATE_CREATING;
343
344 return 0;
345 }
346
347 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
348 int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
349 int r;
350
351 switch(netdev->kind) {
352 case NETDEV_KIND_VLAN:
353 return netdev_create_vlan(netdev, link, callback);
354 case NETDEV_KIND_MACVLAN:
355 return netdev_create_macvlan(netdev, link, callback);
356 case NETDEV_KIND_VXLAN:
357 return netdev_create_vxlan(netdev, link, callback);
358 case NETDEV_KIND_IPIP:
359 case NETDEV_KIND_GRE:
360 case NETDEV_KIND_SIT:
361 case NETDEV_KIND_VTI:
362 return netdev_create_tunnel(netdev, link, callback);
363 default:
364 break;
365 }
366
367 if (netdev->state == NETDEV_STATE_READY) {
368 r = netdev_enslave_ready(netdev, link, callback);
369 if (r < 0)
370 return r;
371 } else {
372 /* the netdev is not yet read, save this request for when it is*/
373 netdev_enslave_callback *cb;
374
375 cb = new0(netdev_enslave_callback, 1);
376 if (!cb)
377 return log_oom();
378
379 cb->callback = callback;
380 cb->link = link;
381 link_ref(link);
382
383 LIST_PREPEND(callbacks, netdev->callbacks, cb);
384 }
385
386 return 0;
387 }
388
389 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
390 uint16_t type;
391 const char *kind;
392 char *received_kind;
393 char *received_name;
394 int r, ifindex;
395
396 assert(netdev);
397 assert(message);
398
399 r = sd_rtnl_message_get_type(message, &type);
400 if (r < 0) {
401 log_error_netdev(netdev, "Could not get rtnl message type");
402 return r;
403 }
404
405 if (type != RTM_NEWLINK) {
406 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
407 return -EINVAL;
408 }
409
410 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
411 if (r < 0) {
412 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
413 netdev_enter_failed(netdev);
414 return r;
415 } else if (ifindex <= 0) {
416 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
417 netdev_enter_failed(netdev);
418 return r;
419 }
420
421 if (netdev->ifindex > 0) {
422 if (netdev->ifindex != ifindex) {
423 log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
424 ifindex, netdev->ifindex);
425 netdev_enter_failed(netdev);
426 return -EEXIST;
427 } else
428 /* ifindex already set to the same for this netdev */
429 return 0;
430 }
431
432 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
433 if (r < 0) {
434 log_error_netdev(netdev, "Could not get IFNAME");
435 return r;
436 }
437
438 if (!streq(netdev->ifname, received_name)) {
439 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
440 received_name);
441 netdev_enter_failed(netdev);
442 return r;
443 }
444
445 r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
446 if (r < 0) {
447 log_error_netdev(netdev, "Could not get LINKINFO");
448 return r;
449 }
450
451 r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
452 if (r < 0) {
453 log_error_netdev(netdev, "Could not get KIND");
454 return r;
455 }
456
457 r = sd_rtnl_message_exit_container(message);
458 if (r < 0) {
459 log_error_netdev(netdev, "Could not exit container");
460 return r;
461 }
462
463 if (netdev->kind == NETDEV_KIND_TAP)
464 /* the kernel does not distinguish between tun and tap */
465 kind = "tun";
466 else {
467 kind = netdev_kind_to_string(netdev->kind);
468 if (!kind) {
469 log_error_netdev(netdev, "Could not get kind");
470 netdev_enter_failed(netdev);
471 return -EINVAL;
472 }
473 }
474
475 if (!streq(kind, received_kind)) {
476 log_error_netdev(netdev,
477 "Received newlink with wrong KIND %s, "
478 "expected %s", received_kind, kind);
479 netdev_enter_failed(netdev);
480 return r;
481 }
482
483 netdev->ifindex = ifindex;
484
485 log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
486
487 netdev_enter_ready(netdev);
488
489 return 0;
490 }
491
492 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
493
494 static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
495 _cleanup_free_ struct ether_addr *mac = NULL;
496 uint8_t result[8];
497 size_t l, sz;
498 uint8_t *v;
499 int r;
500
501 assert(ifname);
502 assert(ret);
503
504 mac = new0(struct ether_addr, 1);
505 if (!mac)
506 return -ENOMEM;
507
508 l = strlen(ifname);
509 sz = sizeof(sd_id128_t) + l;
510 v = alloca(sz);
511
512 /* fetch some persistent data unique to the machine */
513 r = sd_id128_get_machine((sd_id128_t*) v);
514 if (r < 0)
515 return r;
516
517 /* combine with some data unique (on this machine) to this
518 * netdev */
519 memcpy(v + sizeof(sd_id128_t), ifname, l);
520
521 /* Let's hash the host machine ID plus the container name. We
522 * use a fixed, but originally randomly created hash key here. */
523 siphash24(result, v, sz, HASH_KEY.bytes);
524
525 assert_cc(ETH_ALEN <= sizeof(result));
526 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
527
528 /* see eth_random_addr in the kernel */
529 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
530 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
531
532 *ret = mac;
533 mac = NULL;
534
535 return 0;
536 }
537
538 static int netdev_load_one(Manager *manager, const char *filename) {
539 _cleanup_netdev_unref_ NetDev *netdev = NULL;
540 _cleanup_fclose_ FILE *file = NULL;
541 int r;
542
543 assert(manager);
544 assert(filename);
545
546 if (null_or_empty_path(filename)) {
547 log_debug("skipping empty file: %s", filename);
548 return 0;
549 }
550
551 file = fopen(filename, "re");
552 if (!file) {
553 if (errno == ENOENT)
554 return 0;
555 else
556 return -errno;
557 }
558
559 netdev = new0(NetDev, 1);
560 if (!netdev)
561 return log_oom();
562
563 netdev->n_ref = 1;
564 netdev->manager = manager;
565 netdev->state = _NETDEV_STATE_INVALID;
566 netdev->kind = _NETDEV_KIND_INVALID;
567 netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID;
568 netdev->vlanid = VLANID_MAX + 1;
569 netdev->vxlanid = VXLAN_VID_MAX + 1;
570 netdev->tunnel_pmtudisc = true;
571 netdev->learning = true;
572
573 r = config_parse(NULL, filename, file,
574 "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0Tun\0Tap\0",
575 config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
576 false, false, netdev);
577 if (r < 0) {
578 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
579 return r;
580 }
581
582 switch (netdev->kind) {
583 case _NETDEV_KIND_INVALID:
584 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
585 return 0;
586 case NETDEV_KIND_VLAN:
587 if (netdev->vlanid > VLANID_MAX) {
588 log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
589 return 0;
590 }
591 break;
592 case NETDEV_KIND_VXLAN:
593 if (netdev->vxlanid > VXLAN_VID_MAX) {
594 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
595 return 0;
596 }
597 break;
598 case NETDEV_KIND_IPIP:
599 case NETDEV_KIND_GRE:
600 case NETDEV_KIND_SIT:
601 case NETDEV_KIND_VTI:
602 if (netdev->local.in.s_addr == INADDR_ANY) {
603 log_warning("Tunnel without local address configured in %s. Ignoring", filename);
604 return 0;
605 }
606 if (netdev->remote.in.s_addr == INADDR_ANY) {
607 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
608 return 0;
609 }
610 if (netdev->family != AF_INET) {
611 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
612 return 0;
613 }
614 break;
615 default:
616 break;
617 }
618
619 if (!netdev->ifname) {
620 log_warning("NetDev without Name configured in %s. Ignoring", filename);
621 return 0;
622 }
623
624 if (netdev->kind != NETDEV_KIND_VLAN && netdev->vlanid <= VLANID_MAX) {
625 log_warning("VLAN Id configured for a %s in %s. Ignoring",
626 netdev_kind_to_string(netdev->kind), filename);
627 return 0;
628 }
629
630 if (netdev->kind != NETDEV_KIND_VXLAN && netdev->vxlanid <= VXLAN_VID_MAX) {
631 log_warning("VXLAN Id configured for a %s in %s. Ignoring",
632 netdev_kind_to_string(netdev->kind), filename);
633 return 0;
634 }
635
636 if (netdev->kind != NETDEV_KIND_MACVLAN &&
637 netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
638 log_warning("MACVLAN Mode configured for a %s in %s. Ignoring",
639 netdev_kind_to_string(netdev->kind), filename);
640 return 0;
641 }
642
643 netdev->filename = strdup(filename);
644 if (!netdev->filename)
645 return log_oom();
646
647 if (net_match_config(NULL, NULL, NULL, NULL, NULL,
648 netdev->match_host, netdev->match_virt,
649 netdev->match_kernel, netdev->match_arch,
650 NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
651 return 0;
652
653 if (!netdev->mac) {
654 r = netdev_get_mac(netdev->ifname, &netdev->mac);
655 if (r < 0) {
656 log_error("Failed to generate predictable MAC address for %s",
657 netdev->ifname);
658 return r;
659 }
660 }
661
662 r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
663 if (r < 0)
664 return r;
665
666 LIST_HEAD_INIT(netdev->callbacks);
667
668 switch (netdev->kind) {
669 case NETDEV_KIND_VETH:
670 if (!netdev->ifname_peer) {
671 log_warning("Veth NetDev without peer name configured "
672 "in %s. Ignoring", filename);
673 return 0;
674 }
675
676 if (!netdev->mac) {
677 r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
678 if (r < 0) {
679 log_error("Failed to generate predictable MAC address for %s",
680 netdev->ifname_peer);
681 return r;
682 }
683 }
684
685 r = netdev_create_veth(netdev, netdev_create_handler);
686 if (r < 0)
687 return r;
688
689 break;
690 case NETDEV_KIND_DUMMY:
691 r = netdev_create_dummy(netdev, netdev_create_handler);
692 if (r < 0)
693 return r;
694
695 break;
696 case NETDEV_KIND_BRIDGE:
697 case NETDEV_KIND_BOND:
698 r = netdev_create(netdev);
699 if (r < 0)
700 return r;
701 break;
702
703 case NETDEV_KIND_TUN:
704 case NETDEV_KIND_TAP:
705 r = netdev_create_tuntap(netdev);
706 if (r < 0)
707 return r;
708 break;
709
710 default:
711 break;
712 }
713
714 log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
715
716 netdev = NULL;
717
718 return 0;
719 }
720
721 int netdev_load(Manager *manager) {
722 NetDev *netdev;
723 char **files, **f;
724 int r;
725
726 assert(manager);
727
728 while ((netdev = hashmap_first(manager->netdevs)))
729 netdev_unref(netdev);
730
731 r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
732 if (r < 0) {
733 log_error("Failed to enumerate netdev files: %s", strerror(-r));
734 return r;
735 }
736
737 STRV_FOREACH_BACKWARDS(f, files) {
738 r = netdev_load_one(manager, *f);
739 if (r < 0)
740 return r;
741 }
742
743 strv_free(files);
744
745 return 0;
746 }