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