From 1d370b2c182505ff8033fccbebcc56621d305220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 14 Nov 2020 14:50:39 +0100 Subject: [PATCH] networkd/dhcp6: allow layer3 devices without MAC Devices with multicast but without mac addresses i.e. tun devices are not getting setuped correctly: $ ip tuntap add mode tun dev tun0 $ ip addr show tun0 16: tun0: mtu 1500 qdisc fq_codel state DOWN group default qlen 500 link/none $ cat /etc/systemd/network/tun0.network [Match] Name = tun0 [Network] Address=192.168.1.1/32 $ ./systemd-networkd tun0: DHCP6 CLIENT: Failed to set identifier: Invalid argument tun0: Failed --- src/libsystemd-network/sd-dhcp6-client.c | 10 ++++++---- src/network/networkd-dhcp-common.c | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index c90179d112..30ac526fc9 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -188,8 +188,7 @@ int sd_dhcp6_client_set_mac( assert_return(client, -EINVAL); assert_return(addr, -EINVAL); - assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); - assert_return(arp_type > 0, -EINVAL); + assert_return(addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -197,8 +196,11 @@ int sd_dhcp6_client_set_mac( assert_return(addr_len == ETH_ALEN, -EINVAL); else if (arp_type == ARPHRD_INFINIBAND) assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); - else - return -EINVAL; + else { + client->arp_type = ARPHRD_NONE; + client->mac_addr_len = 0; + return 0; + } if (client->mac_addr_len == addr_len && memcmp(&client->mac_addr, addr, addr_len) == 0) diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 2537561265..c338c775a7 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -58,9 +58,16 @@ void network_adjust_dhcp(Network *network) { } } +static struct DUID fallback_duid = { .type = DUID_TYPE_EN }; DUID* link_get_duid(Link *link) { if (link->network->duid.type != _DUID_TYPE_INVALID) return &link->network->duid; + else if (link->hw_addr.length == 0 && + (link->manager->duid.type == DUID_TYPE_LLT || + link->manager->duid.type == DUID_TYPE_LL)) + /* Fallback to DUID that works without mac addresses. + * This is useful for tunnel devices without mac address. */ + return &fallback_duid; else return &link->manager->duid; }