]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/dhcp4: add support for ARPHRD_RAWIP and ARPHRD_NONE network interface types
authorDarsey Litzenberger <dlitz@dlitz.net>
Wed, 9 Oct 2024 19:55:42 +0000 (13:55 -0600)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 10 Oct 2024 00:29:30 +0000 (09:29 +0900)
This should fix QMI wwan modems, as noted in
https://github.com/systemd/systemd/issues/27219

src/libsystemd-network/sd-dhcp-client.c
src/network/networkd-dhcp-common.c

index cf26bd0e487cfa5ea19d6d197d679b30ff2b1a4e..7a8996691269010ca5645040bb50034098b3a39d 100644 (file)
@@ -273,6 +273,35 @@ int sd_dhcp_client_set_mac(
 
         assert_return(client, -EINVAL);
         assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
+        assert_return(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND, ARPHRD_RAWIP, ARPHRD_NONE), -EINVAL);
+
+        static const uint8_t default_eth_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+                        default_eth_hwaddr[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+        switch (arp_type) {
+        case ARPHRD_RAWIP:
+        case ARPHRD_NONE:
+                /* Linux cellular modem drivers (e.g. qmi_wwan) present a
+                 * network interface of type ARPHRD_RAWIP(519) or
+                 * ARPHRD_NONE(65534) when in point-to-point mode, but these
+                 * are not valid DHCP hardware-type values.
+                 *
+                 * Apparently, it's best to just pretend that these are ethernet
+                 * devices.  Other approaches have been tried, but resulted in
+                 * incompatibilities with some server software.  See
+                 * https://lore.kernel.org/netdev/cover.1228948072.git.inaky@linux.intel.com/
+                 */
+                arp_type = ARPHRD_ETHER;
+                if (addr_len == 0) {
+                        assert_cc(sizeof(default_eth_hwaddr) == ETH_ALEN);
+                        assert_cc(sizeof(default_eth_bcast) == ETH_ALEN);
+                        hw_addr = default_eth_hwaddr;
+                        bcast_addr = default_eth_bcast;
+                        addr_len = ETH_ALEN;
+                }
+                break;
+        }
+
         assert_return(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND), -EINVAL);
         assert_return(hw_addr, -EINVAL);
         assert_return(addr_len == (arp_type == ARPHRD_ETHER ? ETH_ALEN : INFINIBAND_ALEN), -EINVAL);
index 9f0268d934e472432fd6506a0b377529ccd4e720..1799d042127ece8bac46984380db40db99ee355d 100644 (file)
@@ -53,8 +53,10 @@ bool link_dhcp_enabled(Link *link, int family) {
         assert(link);
         assert(IN_SET(family, AF_INET, AF_INET6));
 
-        /* Currently, sd-dhcp-client supports only ethernet and infiniband. */
-        if (family == AF_INET && !IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND))
+        /* Currently, sd-dhcp-client supports only ethernet and infiniband.
+         * (ARMHRD_RAWIP and ARMHRD_NONE are typically wwan modems and will be
+         * treated as ethernet devices.) */
+        if (family == AF_INET && !IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND, ARPHRD_RAWIP, ARPHRD_NONE))
                 return false;
 
         if (family == AF_INET6 && !socket_ipv6_is_supported())