Package: systemd
Version: 215-17+deb8u1
Severity: wishlist
Tags: patch

In some setups DHCP requests are filtered if they have the broadcast
flag set. systemd-networkd in stable always sets the broadcast flag and
thus cannot be used for DHCP in such setups.

Later versions of systemd-networkd changed the default to unicast
(commit f5de5b00204f041aaec828d336c8afd9e860a5c3) and added a
configuration option RequestBroadcast to control the behaviour.

This patch backports the configuration option but leaves the default
value unchanged as it seems there is no "right" answer for all setups
and I didn't want to risk breaking setups that are currently working.

Please consider applying the patch. Adding

  [DHCP]
  RequestBroadcast=false

with this change made systemd-networkd work for us in a cloud setup that
did not work before (FWIW, this was German cloud provider Jiffybox).

Thanks and have a nice day,

        Max
From: Max Vozeler <x...@debian.org>
Date: Mon, 17 Sep 2015 10:14:01 +0200
Subject: [PATCH] Backport: sd-dhcp-client: make request broadcasts configurable

Backported from commit f5de5b00204f041aaec828d336c8afd9e860a5c3.

The upstream commit changes the default from broadcast to unicast. This seems
too risky a change for stable, so keep the default but make it configurable.

Original patch description:

It appears there is no good way to decide whether or not broadcasts should be enabled,
there is hardware that must have broadcast, and there are networks that only allow
unicast. So we give up and make this configurable.

---
 man/systemd.network.xml                  |  9 +++++++++
 src/libsystemd-network/sd-dhcp-client.c  | 18 ++++++++++++++++--
 src/network/networkd-link.c              |  4 ++++
 src/network/networkd-network-gperf.gperf |  1 +
 src/network/networkd-network.c           |  1 +
 src/network/networkd.h                   |  1 +
 src/systemd/sd-dhcp-client.h             |  1 +
 7 files changed, 33 insertions(+), 2 deletions(-)

--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -433,6 +433,15 @@
                                                 if, say, the root filesystem relies on this connection. Defaults to false.</para>
                                         </listitem>
                                 </varlistentry>
+                                <varlistentry>
+                                        <term><varname>RequestBroadcast=</varname></term>
+                                        <listitem>
+                                                <para>Request the server to use broadcast messages before the IP address has been
+                                                configured. This is necessary for devices that cannot receive RAW packets, or that
+                                                cannot receive packets at all before an IP address has been configured. On the other
+                                                hand, this must not be enabled on networks where broadcasts are filtered out.</para>
+                                        </listitem>
+                                </varlistentry>
                        </variablelist>
 
         </refsect1>
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -48,6 +48,7 @@ struct sd_dhcp_client {
         int fd;
         union sockaddr_union link;
         sd_event_source *receive_message;
+        bool request_broadcast;
         uint8_t *req_opts;
         size_t req_opts_allocated;
         size_t req_opts_size;
@@ -95,6 +96,14 @@ int sd_dhcp_client_set_callback(sd_dhcp_
         return 0;
 }
 
+int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
+        assert_return(client, -EINVAL);
+
+        client->request_broadcast = !!broadcast;
+
+        return 0;
+}
+
 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
         size_t i;
 
@@ -304,8 +313,13 @@ static int client_message_init(sd_dhcp_c
            BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
            DHCPREQUEST messages that client sends.  The BROADCAST bit will
            provide a hint to the DHCP server and BOOTP relay agent to broadcast
-           any messages to the client on the client's subnet. */
-        packet->dhcp.flags = htobe16(0x8000);
+           any messages to the client on the client's subnet.
+
+           Note: some interfaces needs this to be enabled, but some networks
+           needs this to be disabled as broadcasts are filteretd, so this
+           needs to be configurable */
+        if (client->request_broadcast)
+                packet->dhcp.flags = htobe16(0x8000);
 
         /* RFC2132 section 4.1.1:
            The client MUST include its hardware address in the ’chaddr’ field, if
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1997,6 +1997,10 @@ static int link_configure(Link *link) {
                 if (r < 0)
                         return r;
 
+                r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link->network->dhcp_broadcast);
+                if (r < 0)
+                        return r;
+
                 if (link->network->dhcp_mtu) {
                         r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
                         if (r < 0)
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -49,6 +49,7 @@ DHCP.UseHostname,            config_pars
 DHCP.UseDomainName,          config_parse_bool,                  0,                             offsetof(Network, dhcp_domainname)
 DHCP.UseRoutes,              config_parse_bool,                  0,                             offsetof(Network, dhcp_routes)
 DHCP.SendHostname,           config_parse_bool,                  0,                             offsetof(Network, dhcp_sendhost)
+DHCP.RequestBroadcast,       config_parse_bool,                  0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,     config_parse_bool,                  0,                             offsetof(Network, dhcp_critical)
 /* backwards compatibility: do not add new entries to this section */
 DHCPv4.UseDNS,               config_parse_bool,                  0,                             offsetof(Network, dhcp_dns)
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -91,6 +91,7 @@ static int network_load_one(Manager *man
         network->dhcp_domainname = true;
         network->dhcp_routes = true;
         network->dhcp_sendhost = true;
+        network->dhcp_broadcast = true;
 
         r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCP\0DHCPv4\0", config_item_perf_lookup,
                         (void*) network_network_gperf_lookup, false, false, network);
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -180,6 +180,7 @@ struct Network {
         bool dhcp_hostname;
         bool dhcp_domainname;
         bool dhcp_sendhost;
+        bool dhcp_broadcast;
         bool dhcp_critical;
         bool dhcp_routes;
         bool ipv4ll;
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -48,6 +48,7 @@ int sd_dhcp_client_set_callback(sd_dhcp_
 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
                                        const struct in_addr *last_address);
+int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
 int sd_dhcp_client_set_mac(sd_dhcp_client *client,
                            const struct ether_addr *addr);

Reply via email to