]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd/dhcp6: allow layer3 devices without MAC
authorJörg Thalheim <joerg@thalheim.io>
Sat, 14 Nov 2020 13:50:39 +0000 (14:50 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 23 Nov 2020 12:56:48 +0000 (13:56 +0100)
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: <NO-CARRIER,POINTOPOINT,MULTICAST,NOARP,UP> 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
src/network/networkd-dhcp-common.c

index c90179d1126b70f26f15ba67fd9a80d1474d1c15..30ac526fc90a0605222183246e42528265875ce6 100644 (file)
@@ -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)
index 253756126554628789e8b9cfbb8eba5a94d962bb..c338c775a72be24acde8a287b6f22332fecad8b4 100644 (file)
@@ -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;
 }