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);