1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
24 #include "alloc-util.h"
25 #include "conf-files.h"
26 #include "conf-parser.h"
29 #include "netlink-util.h"
30 #include "network-internal.h"
31 #include "networkd-netdev.h"
33 #include "siphash24.h"
34 #include "stat-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
38 const NetDevVTable
* const netdev_vtable
[_NETDEV_KIND_MAX
] = {
40 [NETDEV_KIND_BRIDGE
] = &bridge_vtable
,
41 [NETDEV_KIND_BOND
] = &bond_vtable
,
42 [NETDEV_KIND_VLAN
] = &vlan_vtable
,
43 [NETDEV_KIND_MACVLAN
] = &macvlan_vtable
,
44 [NETDEV_KIND_MACVTAP
] = &macvtap_vtable
,
45 [NETDEV_KIND_IPVLAN
] = &ipvlan_vtable
,
46 [NETDEV_KIND_VXLAN
] = &vxlan_vtable
,
47 [NETDEV_KIND_IPIP
] = &ipip_vtable
,
48 [NETDEV_KIND_GRE
] = &gre_vtable
,
49 [NETDEV_KIND_GRETAP
] = &gretap_vtable
,
50 [NETDEV_KIND_IP6GRE
] = &ip6gre_vtable
,
51 [NETDEV_KIND_IP6GRETAP
] = &ip6gretap_vtable
,
52 [NETDEV_KIND_SIT
] = &sit_vtable
,
53 [NETDEV_KIND_VTI
] = &vti_vtable
,
54 [NETDEV_KIND_VTI6
] = &vti6_vtable
,
55 [NETDEV_KIND_VETH
] = &veth_vtable
,
56 [NETDEV_KIND_DUMMY
] = &dummy_vtable
,
57 [NETDEV_KIND_TUN
] = &tun_vtable
,
58 [NETDEV_KIND_TAP
] = &tap_vtable
,
59 [NETDEV_KIND_IP6TNL
] = &ip6tnl_vtable
,
62 static const char* const netdev_kind_table
[_NETDEV_KIND_MAX
] = {
63 [NETDEV_KIND_BRIDGE
] = "bridge",
64 [NETDEV_KIND_BOND
] = "bond",
65 [NETDEV_KIND_VLAN
] = "vlan",
66 [NETDEV_KIND_MACVLAN
] = "macvlan",
67 [NETDEV_KIND_MACVTAP
] = "macvtap",
68 [NETDEV_KIND_IPVLAN
] = "ipvlan",
69 [NETDEV_KIND_VXLAN
] = "vxlan",
70 [NETDEV_KIND_IPIP
] = "ipip",
71 [NETDEV_KIND_GRE
] = "gre",
72 [NETDEV_KIND_GRETAP
] = "gretap",
73 [NETDEV_KIND_IP6GRE
] = "ip6gre",
74 [NETDEV_KIND_IP6GRETAP
] = "ip6gretap",
75 [NETDEV_KIND_SIT
] = "sit",
76 [NETDEV_KIND_VETH
] = "veth",
77 [NETDEV_KIND_VTI
] = "vti",
78 [NETDEV_KIND_VTI6
] = "vti6",
79 [NETDEV_KIND_DUMMY
] = "dummy",
80 [NETDEV_KIND_TUN
] = "tun",
81 [NETDEV_KIND_TAP
] = "tap",
82 [NETDEV_KIND_IP6TNL
] = "ip6tnl",
85 DEFINE_STRING_TABLE_LOOKUP(netdev_kind
, NetDevKind
);
86 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind
, netdev_kind
, NetDevKind
, "Failed to parse netdev kind");
88 static void netdev_cancel_callbacks(NetDev
*netdev
) {
89 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
90 netdev_join_callback
*callback
;
95 rtnl_message_new_synthetic_error(-ENODEV
, 0, &m
);
97 while ((callback
= netdev
->callbacks
)) {
99 assert(callback
->link
);
100 assert(callback
->callback
);
101 assert(netdev
->manager
);
102 assert(netdev
->manager
->rtnl
);
104 callback
->callback(netdev
->manager
->rtnl
, m
, callback
->link
);
107 LIST_REMOVE(callbacks
, netdev
->callbacks
, callback
);
108 link_unref(callback
->link
);
113 static void netdev_free(NetDev
*netdev
) {
117 netdev_cancel_callbacks(netdev
);
120 hashmap_remove(netdev
->manager
->netdevs
, netdev
->ifname
);
122 free(netdev
->filename
);
124 free(netdev
->description
);
125 free(netdev
->ifname
);
128 condition_free_list(netdev
->match_host
);
129 condition_free_list(netdev
->match_virt
);
130 condition_free_list(netdev
->match_kernel
);
131 condition_free_list(netdev
->match_arch
);
133 if (NETDEV_VTABLE(netdev
) &&
134 NETDEV_VTABLE(netdev
)->done
)
135 NETDEV_VTABLE(netdev
)->done(netdev
);
140 NetDev
*netdev_unref(NetDev
*netdev
) {
141 if (netdev
&& (-- netdev
->n_ref
<= 0))
147 NetDev
*netdev_ref(NetDev
*netdev
) {
149 assert_se(++ netdev
->n_ref
>= 2);
154 void netdev_drop(NetDev
*netdev
) {
155 if (!netdev
|| netdev
->state
== NETDEV_STATE_LINGER
)
158 netdev
->state
= NETDEV_STATE_LINGER
;
160 log_netdev_debug(netdev
, "netdev removed");
162 netdev_cancel_callbacks(netdev
);
164 netdev_unref(netdev
);
169 int netdev_get(Manager
*manager
, const char *name
, NetDev
**ret
) {
176 netdev
= hashmap_get(manager
->netdevs
, name
);
187 static int netdev_enter_failed(NetDev
*netdev
) {
188 netdev
->state
= NETDEV_STATE_FAILED
;
190 netdev_cancel_callbacks(netdev
);
195 static int netdev_enslave_ready(NetDev
*netdev
, Link
* link
, sd_netlink_message_handler_t callback
) {
196 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
200 assert(netdev
->state
== NETDEV_STATE_READY
);
201 assert(netdev
->manager
);
202 assert(netdev
->manager
->rtnl
);
203 assert(IN_SET(netdev
->kind
, NETDEV_KIND_BRIDGE
, NETDEV_KIND_BOND
));
207 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
209 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_SETLINK message: %m");
211 r
= sd_netlink_message_append_u32(req
, IFLA_MASTER
, netdev
->ifindex
);
213 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MASTER attribute: %m");
215 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
217 return log_netdev_error(netdev
, "Could not send rtnetlink message: %m");
221 log_netdev_debug(netdev
, "Enslaving link '%s'", link
->ifname
);
226 static int netdev_enter_ready(NetDev
*netdev
) {
227 netdev_join_callback
*callback
, *callback_next
;
231 assert(netdev
->ifname
);
233 if (netdev
->state
!= NETDEV_STATE_CREATING
)
236 netdev
->state
= NETDEV_STATE_READY
;
238 log_netdev_info(netdev
, "netdev ready");
240 LIST_FOREACH_SAFE(callbacks
, callback
, callback_next
, netdev
->callbacks
) {
241 /* enslave the links that were attempted to be enslaved before the
243 r
= netdev_enslave_ready(netdev
, callback
->link
, callback
->callback
);
247 LIST_REMOVE(callbacks
, netdev
->callbacks
, callback
);
248 link_unref(callback
->link
);
252 if (NETDEV_VTABLE(netdev
)->post_create
)
253 NETDEV_VTABLE(netdev
)->post_create(netdev
, NULL
, NULL
);
258 /* callback for netdev's created without a backing Link */
259 static int netdev_create_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
260 _cleanup_netdev_unref_ NetDev
*netdev
= userdata
;
263 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
265 r
= sd_netlink_message_get_errno(m
);
267 log_netdev_info(netdev
, "netdev exists, using existing without changing its parameters");
269 log_netdev_warning_errno(netdev
, r
, "netdev could not be created: %m");
275 log_netdev_debug(netdev
, "Created");
280 int netdev_enslave(NetDev
*netdev
, Link
*link
, sd_netlink_message_handler_t callback
) {
284 assert(netdev
->manager
);
285 assert(netdev
->manager
->rtnl
);
286 assert(IN_SET(netdev
->kind
, NETDEV_KIND_BRIDGE
, NETDEV_KIND_BOND
));
288 if (netdev
->state
== NETDEV_STATE_READY
) {
289 r
= netdev_enslave_ready(netdev
, link
, callback
);
292 } else if (IN_SET(netdev
->state
, NETDEV_STATE_LINGER
, NETDEV_STATE_FAILED
)) {
293 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
295 r
= rtnl_message_new_synthetic_error(-ENODEV
, 0, &m
);
297 callback(netdev
->manager
->rtnl
, m
, link
);
299 /* the netdev is not yet read, save this request for when it is */
300 netdev_join_callback
*cb
;
302 cb
= new0(netdev_join_callback
, 1);
306 cb
->callback
= callback
;
310 LIST_PREPEND(callbacks
, netdev
->callbacks
, cb
);
312 log_netdev_debug(netdev
, "Will enslave '%s', when ready", link
->ifname
);
318 int netdev_set_ifindex(NetDev
*netdev
, sd_netlink_message
*message
) {
321 const char *received_kind
;
322 const char *received_name
;
328 r
= sd_netlink_message_get_type(message
, &type
);
330 return log_netdev_error_errno(netdev
, r
, "Could not get rtnl message type: %m");
332 if (type
!= RTM_NEWLINK
) {
333 log_netdev_error(netdev
, "Cannot set ifindex from unexpected rtnl message type.");
337 r
= sd_rtnl_message_link_get_ifindex(message
, &ifindex
);
339 log_netdev_error_errno(netdev
, r
, "Could not get ifindex: %m");
340 netdev_enter_failed(netdev
);
342 } else if (ifindex
<= 0) {
343 log_netdev_error(netdev
, "Got invalid ifindex: %d", ifindex
);
344 netdev_enter_failed(netdev
);
348 if (netdev
->ifindex
> 0) {
349 if (netdev
->ifindex
!= ifindex
) {
350 log_netdev_error(netdev
, "Could not set ifindex to %d, already set to %d",
351 ifindex
, netdev
->ifindex
);
352 netdev_enter_failed(netdev
);
355 /* ifindex already set to the same for this netdev */
359 r
= sd_netlink_message_read_string(message
, IFLA_IFNAME
, &received_name
);
361 return log_netdev_error_errno(netdev
, r
, "Could not get IFNAME: %m");
363 if (!streq(netdev
->ifname
, received_name
)) {
364 log_netdev_error(netdev
, "Received newlink with wrong IFNAME %s", received_name
);
365 netdev_enter_failed(netdev
);
369 r
= sd_netlink_message_enter_container(message
, IFLA_LINKINFO
);
371 return log_netdev_error_errno(netdev
, r
, "Could not get LINKINFO: %m");
373 r
= sd_netlink_message_read_string(message
, IFLA_INFO_KIND
, &received_kind
);
375 return log_netdev_error_errno(netdev
, r
, "Could not get KIND: %m");
377 r
= sd_netlink_message_exit_container(message
);
379 return log_netdev_error_errno(netdev
, r
, "Could not exit container: %m");
381 if (netdev
->kind
== NETDEV_KIND_TAP
)
382 /* the kernel does not distinguish between tun and tap */
385 kind
= netdev_kind_to_string(netdev
->kind
);
387 log_netdev_error(netdev
, "Could not get kind");
388 netdev_enter_failed(netdev
);
393 if (!streq(kind
, received_kind
)) {
394 log_netdev_error(netdev
,
395 "Received newlink with wrong KIND %s, "
396 "expected %s", received_kind
, kind
);
397 netdev_enter_failed(netdev
);
401 netdev
->ifindex
= ifindex
;
403 log_netdev_debug(netdev
, "netdev has index %d", netdev
->ifindex
);
405 netdev_enter_ready(netdev
);
410 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
412 int netdev_get_mac(const char *ifname
, struct ether_addr
**ret
) {
413 _cleanup_free_
struct ether_addr
*mac
= NULL
;
422 mac
= new0(struct ether_addr
, 1);
427 sz
= sizeof(sd_id128_t
) + l
;
430 /* fetch some persistent data unique to the machine */
431 r
= sd_id128_get_machine((sd_id128_t
*) v
);
435 /* combine with some data unique (on this machine) to this
437 memcpy(v
+ sizeof(sd_id128_t
), ifname
, l
);
439 /* Let's hash the host machine ID plus the container name. We
440 * use a fixed, but originally randomly created hash key here. */
441 result
= siphash24(v
, sz
, HASH_KEY
.bytes
);
443 assert_cc(ETH_ALEN
<= sizeof(result
));
444 memcpy(mac
->ether_addr_octet
, &result
, ETH_ALEN
);
446 /* see eth_random_addr in the kernel */
447 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
448 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
456 static int netdev_create(NetDev
*netdev
, Link
*link
,
457 sd_netlink_message_handler_t callback
) {
461 assert(!link
|| callback
);
464 if (NETDEV_VTABLE(netdev
)->create
) {
467 r
= NETDEV_VTABLE(netdev
)->create(netdev
);
471 log_netdev_debug(netdev
, "Created");
473 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
475 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &m
, RTM_NEWLINK
, 0);
477 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_NEWLINK message: %m");
479 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, netdev
->ifname
);
481 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IFNAME, attribute: %m");
484 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, netdev
->mac
);
486 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_ADDRESS attribute: %m");
490 r
= sd_netlink_message_append_u32(m
, IFLA_MTU
, netdev
->mtu
);
492 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MTU attribute: %m");
496 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, link
->ifindex
);
498 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINK attribute: %m");
501 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
503 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
505 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, netdev_kind_to_string(netdev
->kind
));
507 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
509 if (NETDEV_VTABLE(netdev
)->fill_message_create
) {
510 r
= NETDEV_VTABLE(netdev
)->fill_message_create(netdev
, link
, m
);
515 r
= sd_netlink_message_close_container(m
);
517 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
519 r
= sd_netlink_message_close_container(m
);
521 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
524 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, m
, callback
, link
, 0, NULL
);
526 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
530 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, m
, netdev_create_handler
, netdev
, 0, NULL
);
532 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
537 netdev
->state
= NETDEV_STATE_CREATING
;
539 log_netdev_debug(netdev
, "Creating");
545 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
546 int netdev_join(NetDev
*netdev
, Link
*link
, sd_netlink_message_handler_t callback
) {
550 assert(netdev
->manager
);
551 assert(netdev
->manager
->rtnl
);
552 assert(NETDEV_VTABLE(netdev
));
554 switch (NETDEV_VTABLE(netdev
)->create_type
) {
555 case NETDEV_CREATE_MASTER
:
556 r
= netdev_enslave(netdev
, link
, callback
);
561 case NETDEV_CREATE_STACKED
:
562 r
= netdev_create(netdev
, link
, callback
);
568 assert_not_reached("Can not join independent netdev");
574 static int netdev_load_one(Manager
*manager
, const char *filename
) {
575 _cleanup_netdev_unref_ NetDev
*netdev
= NULL
;
576 _cleanup_free_ NetDev
*netdev_raw
= NULL
;
577 _cleanup_fclose_
FILE *file
= NULL
;
583 file
= fopen(filename
, "re");
591 if (null_or_empty_fd(fileno(file
))) {
592 log_debug("Skipping empty file: %s", filename
);
596 netdev_raw
= new0(NetDev
, 1);
600 netdev_raw
->kind
= _NETDEV_KIND_INVALID
;
602 r
= config_parse(NULL
, filename
, file
,
604 config_item_perf_lookup
, network_netdev_gperf_lookup
,
605 true, false, true, netdev_raw
);
609 r
= fseek(file
, 0, SEEK_SET
);
613 /* skip out early if configuration does not match the environment */
614 if (net_match_config(NULL
, NULL
, NULL
, NULL
, NULL
,
615 netdev_raw
->match_host
, netdev_raw
->match_virt
,
616 netdev_raw
->match_kernel
, netdev_raw
->match_arch
,
617 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) <= 0)
620 if (!NETDEV_VTABLE(netdev_raw
)) {
621 log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename
);
625 if (!netdev_raw
->ifname
) {
626 log_warning("NetDev without Name configured in %s. Ignoring", filename
);
630 netdev
= malloc0(NETDEV_VTABLE(netdev_raw
)->object_size
);
635 netdev
->manager
= manager
;
636 netdev
->state
= _NETDEV_STATE_INVALID
;
637 netdev
->kind
= netdev_raw
->kind
;
638 netdev
->ifname
= netdev_raw
->ifname
;
640 if (NETDEV_VTABLE(netdev
)->init
)
641 NETDEV_VTABLE(netdev
)->init(netdev
);
643 r
= config_parse(NULL
, filename
, file
,
644 NETDEV_VTABLE(netdev
)->sections
,
645 config_item_perf_lookup
, network_netdev_gperf_lookup
,
646 false, false, false, netdev
);
650 /* verify configuration */
651 if (NETDEV_VTABLE(netdev
)->config_verify
) {
652 r
= NETDEV_VTABLE(netdev
)->config_verify(netdev
, filename
);
657 netdev
->filename
= strdup(filename
);
658 if (!netdev
->filename
)
662 r
= netdev_get_mac(netdev
->ifname
, &netdev
->mac
);
664 return log_error_errno(r
, "Failed to generate predictable MAC address for %s: %m", netdev
->ifname
);
667 r
= hashmap_put(netdev
->manager
->netdevs
, netdev
->ifname
, netdev
);
671 LIST_HEAD_INIT(netdev
->callbacks
);
673 log_netdev_debug(netdev
, "loaded %s", netdev_kind_to_string(netdev
->kind
));
675 switch (NETDEV_VTABLE(netdev
)->create_type
) {
676 case NETDEV_CREATE_MASTER
:
677 case NETDEV_CREATE_INDEPENDENT
:
678 r
= netdev_create(netdev
, NULL
, NULL
);
692 int netdev_load(Manager
*manager
) {
693 _cleanup_strv_free_
char **files
= NULL
;
700 while ((netdev
= hashmap_first(manager
->netdevs
)))
701 netdev_unref(netdev
);
703 r
= conf_files_list_strv(&files
, ".netdev", NULL
, network_dirs
);
705 return log_error_errno(r
, "Failed to enumerate netdev files: %m");
707 STRV_FOREACH_BACKWARDS(f
, files
) {
708 r
= netdev_load_one(manager
, *f
);