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/>.
25 #include "network-internal.h"
26 #include "path-util.h"
27 #include "conf-files.h"
28 #include "conf-parser.h"
30 #include "siphash24.h"
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",
46 DEFINE_STRING_TABLE_LOOKUP(netdev_kind
, NetDevKind
);
47 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind
, netdev_kind
, NetDevKind
, "Failed to parse netdev kind");
49 static void netdev_cancel_callbacks(NetDev
*netdev
) {
50 _cleanup_rtnl_message_unref_ sd_rtnl_message
*m
= NULL
;
51 netdev_enslave_callback
*callback
;
56 rtnl_message_new_synthetic_error(-ENODEV
, 0, &m
);
58 while ((callback
= netdev
->callbacks
)) {
60 assert(callback
->link
);
61 assert(callback
->callback
);
62 assert(netdev
->manager
);
63 assert(netdev
->manager
->rtnl
);
65 callback
->callback(netdev
->manager
->rtnl
, m
, link
);
68 LIST_REMOVE(callbacks
, netdev
->callbacks
, callback
);
73 static void netdev_free(NetDev
*netdev
) {
77 netdev_cancel_callbacks(netdev
);
80 hashmap_remove(netdev
->manager
->netdevs
, netdev
->ifname
);
82 free(netdev
->filename
);
84 free(netdev
->description
);
86 free(netdev
->ifname_peer
);
88 free(netdev
->mac_peer
);
90 condition_free_list(netdev
->match_host
);
91 condition_free_list(netdev
->match_virt
);
92 condition_free_list(netdev
->match_kernel
);
93 condition_free_list(netdev
->match_arch
);
98 NetDev
*netdev_unref(NetDev
*netdev
) {
99 if (netdev
&& (-- netdev
->n_ref
<= 0))
105 NetDev
*netdev_ref(NetDev
*netdev
) {
107 assert_se(++ netdev
->n_ref
>= 2);
112 void netdev_drop(NetDev
*netdev
) {
113 if (!netdev
|| netdev
->state
== NETDEV_STATE_LINGER
)
116 netdev
->state
= NETDEV_STATE_LINGER
;
118 log_debug_netdev(netdev
, "netdev removed");
120 netdev_cancel_callbacks(netdev
);
122 netdev_unref(netdev
);
127 int netdev_get(Manager
*manager
, const char *name
, NetDev
**ret
) {
134 netdev
= hashmap_get(manager
->netdevs
, name
);
145 static int netdev_enter_failed(NetDev
*netdev
) {
146 netdev
->state
= NETDEV_STATE_FAILED
;
151 static int netdev_enslave_ready(NetDev
*netdev
, Link
* link
, sd_rtnl_message_handler_t callback
) {
152 _cleanup_rtnl_message_unref_ sd_rtnl_message
*req
= NULL
;
156 assert(netdev
->state
== NETDEV_STATE_READY
);
157 assert(netdev
->manager
);
158 assert(netdev
->manager
->rtnl
);
162 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &req
,
163 RTM_SETLINK
, link
->ifindex
);
165 log_error_netdev(netdev
,
166 "Could not allocate RTM_SETLINK message: %s",
171 r
= sd_rtnl_message_append_u32(req
, IFLA_MASTER
, netdev
->ifindex
);
173 log_error_netdev(netdev
,
174 "Could not append IFLA_MASTER attribute: %s",
179 r
= sd_rtnl_call_async(netdev
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
181 log_error_netdev(netdev
,
182 "Could not send rtnetlink message: %s",
189 log_debug_netdev(netdev
, "enslaving link '%s'", link
->ifname
);
194 static int netdev_enter_ready(NetDev
*netdev
) {
195 netdev_enslave_callback
*callback
;
198 assert(netdev
->ifname
);
200 if (netdev
->state
!= NETDEV_STATE_CREATING
)
203 netdev
->state
= NETDEV_STATE_READY
;
205 log_info_netdev(netdev
, "netdev ready");
207 LIST_FOREACH(callbacks
, callback
, netdev
->callbacks
) {
208 /* enslave the links that were attempted to be enslaved before the
210 netdev_enslave_ready(netdev
, callback
->link
, callback
->callback
);
216 /* callback for netdev's created without a backing Link */
217 static int netdev_create_handler(sd_rtnl
*rtnl
, sd_rtnl_message
*m
, void *userdata
) {
218 _cleanup_netdev_unref_ NetDev
*netdev
= userdata
;
221 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
223 r
= sd_rtnl_message_get_errno(m
);
225 log_debug_netdev(netdev
, "netdev exists, using existing");
227 log_warning_netdev(netdev
, "netdev could not be created: %s", strerror(-r
));
236 int config_parse_tunnel_address(const char *unit
,
237 const char *filename
,
240 unsigned section_line
,
247 unsigned char family
= AF_INET
;
255 r
= net_parse_inaddr(rvalue
, &family
, n
);
257 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
258 "Tunnel address is invalid, ignoring assignment: %s", rvalue
);
264 static int netdev_create(NetDev
*netdev
) {
265 _cleanup_rtnl_message_unref_ sd_rtnl_message
*req
= NULL
;
270 assert(netdev
->ifname
);
271 assert(netdev
->manager
);
272 assert(netdev
->manager
->rtnl
);
274 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &req
, RTM_NEWLINK
, 0);
276 log_error_netdev(netdev
,
277 "Could not allocate RTM_NEWLINK message: %s",
282 r
= sd_rtnl_message_append_string(req
, IFLA_IFNAME
, netdev
->ifname
);
284 log_error_netdev(netdev
,
285 "Could not append IFLA_IFNAME attribute: %s",
291 r
= sd_rtnl_message_append_u32(req
, IFLA_MTU
, netdev
->mtu
);
293 log_error_netdev(netdev
,
294 "Could not append IFLA_MTU attribute: %s",
301 r
= sd_rtnl_message_append_ether_addr(req
, IFLA_ADDRESS
, netdev
->mac
);
303 log_error_netdev(netdev
,
304 "Colud not append IFLA_ADDRESS attribute: %s",
310 r
= sd_rtnl_message_open_container(req
, IFLA_LINKINFO
);
312 log_error_netdev(netdev
,
313 "Could not open IFLA_LINKINFO container: %s",
318 kind
= netdev_kind_to_string(netdev
->kind
);
320 log_error_netdev(netdev
, "Invalid kind");
324 r
= sd_rtnl_message_open_container_union(req
, IFLA_INFO_DATA
, kind
);
326 log_error_netdev(netdev
,
327 "Could not open IFLA_INFO_DATA container: %s",
332 r
= sd_rtnl_message_close_container(req
);
334 log_error_netdev(netdev
,
335 "Could not close IFLA_INFO_DATA container %s",
340 r
= sd_rtnl_message_close_container(req
);
342 log_error_netdev(netdev
,
343 "Could not close IFLA_LINKINFO container %s",
348 r
= sd_rtnl_call_async(netdev
->manager
->rtnl
, req
, &netdev_create_handler
, netdev
, 0, NULL
);
350 log_error_netdev(netdev
,
351 "Could not send rtnetlink message: %s", strerror(-r
));
357 log_debug_netdev(netdev
, "creating netdev");
359 netdev
->state
= NETDEV_STATE_CREATING
;
364 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
365 int netdev_enslave(NetDev
*netdev
, Link
*link
, sd_rtnl_message_handler_t callback
) {
368 switch(netdev
->kind
) {
369 case NETDEV_KIND_VLAN
:
370 return netdev_create_vlan(netdev
, link
, callback
);
371 case NETDEV_KIND_MACVLAN
:
372 return netdev_create_macvlan(netdev
, link
, callback
);
373 case NETDEV_KIND_VXLAN
:
374 return netdev_create_vxlan(netdev
, link
, callback
);
375 case NETDEV_KIND_IPIP
:
376 case NETDEV_KIND_GRE
:
377 case NETDEV_KIND_SIT
:
378 case NETDEV_KIND_VTI
:
379 return netdev_create_tunnel(netdev
, link
, callback
);
384 if (netdev
->state
== NETDEV_STATE_READY
) {
385 r
= netdev_enslave_ready(netdev
, link
, callback
);
389 /* the netdev is not yet read, save this request for when it is*/
390 netdev_enslave_callback
*cb
;
392 cb
= new0(netdev_enslave_callback
, 1);
396 cb
->callback
= callback
;
400 LIST_PREPEND(callbacks
, netdev
->callbacks
, cb
);
406 int netdev_set_ifindex(NetDev
*netdev
, sd_rtnl_message
*message
) {
416 r
= sd_rtnl_message_get_type(message
, &type
);
418 log_error_netdev(netdev
, "Could not get rtnl message type");
422 if (type
!= RTM_NEWLINK
) {
423 log_error_netdev(netdev
, "Can not set ifindex from unexpected rtnl message type");
427 r
= sd_rtnl_message_link_get_ifindex(message
, &ifindex
);
429 log_error_netdev(netdev
, "Could not get ifindex: %s", strerror(-r
));
430 netdev_enter_failed(netdev
);
432 } else if (ifindex
<= 0) {
433 log_error_netdev(netdev
, "Got invalid ifindex: %d", ifindex
);
434 netdev_enter_failed(netdev
);
438 if (netdev
->ifindex
> 0) {
439 if (netdev
->ifindex
!= ifindex
) {
440 log_error_netdev(netdev
, "Could not set ifindex to %d, already set to %d",
441 ifindex
, netdev
->ifindex
);
442 netdev_enter_failed(netdev
);
445 /* ifindex already set to the same for this netdev */
449 r
= sd_rtnl_message_read_string(message
, IFLA_IFNAME
, &received_name
);
451 log_error_netdev(netdev
, "Could not get IFNAME");
455 if (!streq(netdev
->ifname
, received_name
)) {
456 log_error_netdev(netdev
, "Received newlink with wrong IFNAME %s",
458 netdev_enter_failed(netdev
);
462 r
= sd_rtnl_message_enter_container(message
, IFLA_LINKINFO
);
464 log_error_netdev(netdev
, "Could not get LINKINFO");
468 r
= sd_rtnl_message_read_string(message
, IFLA_INFO_KIND
, &received_kind
);
470 log_error_netdev(netdev
, "Could not get KIND");
474 r
= sd_rtnl_message_exit_container(message
);
476 log_error_netdev(netdev
, "Could not exit container");
480 kind
= netdev_kind_to_string(netdev
->kind
);
482 log_error_netdev(netdev
, "Could not get kind");
483 netdev_enter_failed(netdev
);
487 if (!streq(kind
, received_kind
)) {
488 log_error_netdev(netdev
, "Received newlink with wrong KIND %s, "
489 "expected %s", received_kind
, kind
);
490 netdev_enter_failed(netdev
);
494 netdev
->ifindex
= ifindex
;
496 log_debug_netdev(netdev
, "netdev has index %d", netdev
->ifindex
);
498 netdev_enter_ready(netdev
);
503 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
505 static int netdev_get_mac(const char *ifname
, struct ether_addr
**ret
) {
506 _cleanup_free_
struct ether_addr
*mac
= NULL
;
515 mac
= new0(struct ether_addr
, 1);
520 sz
= sizeof(sd_id128_t
) + l
;
523 /* fetch some persistent data unique to the machine */
524 r
= sd_id128_get_machine((sd_id128_t
*) v
);
528 /* combine with some data unique (on this machine) to this
530 memcpy(v
+ sizeof(sd_id128_t
), ifname
, l
);
532 /* Let's hash the host machine ID plus the container name. We
533 * use a fixed, but originally randomly created hash key here. */
534 siphash24(result
, v
, sz
, HASH_KEY
.bytes
);
536 assert_cc(ETH_ALEN
<= sizeof(result
));
537 memcpy(mac
->ether_addr_octet
, result
, ETH_ALEN
);
539 /* see eth_random_addr in the kernel */
540 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
541 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
549 static int netdev_load_one(Manager
*manager
, const char *filename
) {
550 _cleanup_netdev_unref_ NetDev
*netdev
= NULL
;
551 _cleanup_fclose_
FILE *file
= NULL
;
557 if (null_or_empty_path(filename
)) {
558 log_debug("skipping empty file: %s", filename
);
562 file
= fopen(filename
, "re");
570 netdev
= new0(NetDev
, 1);
575 netdev
->manager
= manager
;
576 netdev
->state
= _NETDEV_STATE_INVALID
;
577 netdev
->kind
= _NETDEV_KIND_INVALID
;
578 netdev
->macvlan_mode
= _NETDEV_MACVLAN_MODE_INVALID
;
579 netdev
->vlanid
= VLANID_MAX
+ 1;
580 netdev
->vxlanid
= VXLAN_VID_MAX
+ 1;
581 netdev
->tunnel_pmtudisc
= true;
582 netdev
->learning
= true;
584 r
= config_parse(NULL
, filename
, file
,
585 "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0",
586 config_item_perf_lookup
, (void*) network_netdev_gperf_lookup
,
587 false, false, netdev
);
589 log_warning("Could not parse config file %s: %s", filename
, strerror(-r
));
593 if (netdev
->kind
== _NETDEV_KIND_INVALID
) {
594 log_warning("NetDev without Kind configured in %s. Ignoring", filename
);
598 if (!netdev
->ifname
) {
599 log_warning("NetDev without Name configured in %s. Ignoring", filename
);
603 if (netdev
->kind
== NETDEV_KIND_VLAN
&& netdev
->vlanid
> VLANID_MAX
) {
604 log_warning("VLAN without valid Id configured in %s. Ignoring", filename
);
608 if (netdev
->kind
== NETDEV_KIND_VXLAN
&& netdev
->vxlanid
> VXLAN_VID_MAX
) {
609 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename
);
613 if (netdev
->kind
!= NETDEV_KIND_VLAN
&& netdev
->vlanid
<= VLANID_MAX
) {
614 log_warning("VLAN Id configured for a %s in %s. Ignoring",
615 netdev_kind_to_string(netdev
->kind
), filename
);
619 if (netdev
->kind
!= NETDEV_KIND_VXLAN
&& netdev
->vxlanid
<= VXLAN_VID_MAX
) {
620 log_warning("VXLAN Id configured for a %s in %s. Ignoring",
621 netdev_kind_to_string(netdev
->kind
), filename
);
625 if (netdev
->kind
!= NETDEV_KIND_MACVLAN
&&
626 netdev
->macvlan_mode
!= _NETDEV_MACVLAN_MODE_INVALID
) {
627 log_warning("MACVLAN Mode configured for a %s in %s. Ignoring",
628 netdev_kind_to_string(netdev
->kind
), filename
);
632 netdev
->filename
= strdup(filename
);
633 if (!netdev
->filename
)
636 if (net_match_config(NULL
, NULL
, NULL
, NULL
, NULL
,
637 netdev
->match_host
, netdev
->match_virt
,
638 netdev
->match_kernel
, netdev
->match_arch
,
639 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) <= 0)
643 r
= netdev_get_mac(netdev
->ifname
, &netdev
->mac
);
645 log_error("Failed to generate predictable MAC address for %s",
651 r
= hashmap_put(netdev
->manager
->netdevs
, netdev
->ifname
, netdev
);
655 LIST_HEAD_INIT(netdev
->callbacks
);
657 switch (netdev
->kind
) {
658 case NETDEV_KIND_VETH
:
659 if (!netdev
->ifname_peer
) {
660 log_warning("Veth NetDev without peer name configured "
661 "in %s. Ignoring", filename
);
666 r
= netdev_get_mac(netdev
->ifname_peer
, &netdev
->mac_peer
);
668 log_error("Failed to generate predictable MAC address for %s",
669 netdev
->ifname_peer
);
674 r
= netdev_create_veth(netdev
, netdev_create_handler
);
679 case NETDEV_KIND_DUMMY
:
680 r
= netdev_create_dummy(netdev
, netdev_create_handler
);
685 case NETDEV_KIND_BRIDGE
:
686 case NETDEV_KIND_BOND
:
687 r
= netdev_create(netdev
);
695 log_debug_netdev(netdev
, "loaded %s", netdev_kind_to_string(netdev
->kind
));
702 int netdev_load(Manager
*manager
) {
709 while ((netdev
= hashmap_first(manager
->netdevs
)))
710 netdev_unref(netdev
);
712 r
= conf_files_list_strv(&files
, ".netdev", NULL
, network_dirs
);
714 log_error("Failed to enumerate netdev files: %s", strerror(-r
));
718 STRV_FOREACH_BACKWARDS(f
, files
) {
719 r
= netdev_load_one(manager
, *f
);