chiark / gitweb /
sd-dhcp-client: make request broadcasts opt-in
authorTom Gundersen <teg@jklm.no>
Tue, 15 Jul 2014 16:55:31 +0000 (18:55 +0200)
committerTom Gundersen <teg@jklm.no>
Tue, 15 Jul 2014 16:55:31 +0000 (18:55 +0200)
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.

By default, unicast is used, but if the kernel were to inform us abotu certain
interfaces requiring broadcast, we could change this to opt-in by default in
those cases.

man/systemd.network.xml
src/libsystemd-network/sd-dhcp-client.c
src/network/networkd-link.c
src/network/networkd-network-gperf.gperf
src/network/networkd.h
src/systemd/sd-dhcp-client.h

index 3c4fdd20c8c890ea683fb87048b3df4cdabf9fdd..7c5f69895a7e1c5e544f0aa32dd059338a4734a1 100644 (file)
                                                 if, say, the root filesystem relies on this connection. Defaults to false.</para>
                                         </listitem>
                                 </varlistentry>
-                                    <varlistentry>
+                                <varlistentry>
                                         <term><varname>VendorClassIdentifier=</varname></term>
                                         <listitem>
                                                 <para>The vendor class identifier used to identify vendor type and configuration.</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>
index 3c389931cd17583a9ce01646dbcdb962f796a56e..f7a4018540508d316a15f0e8ed8b9462ce36a2c4 100644 (file)
@@ -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;
@@ -96,6 +97,14 @@ int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
         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;
 
@@ -322,8 +331,13 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
            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
index 877b7a9be2c1e7ad4a5a3cc894456434f0ab5921..0fb323b9a54b7299d48b7bf7e6225bdea8bfd0a6 100644 (file)
@@ -1998,6 +1998,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)
index 61dd8ef5f6511eb2ea66cedc29e4a2442bd98af5..f5156b43b2e2726db754c1f396f7e91df449d088 100644 (file)
@@ -51,6 +51,7 @@ DHCP.UseHostname,            config_parse_bool,                  0,
 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)
 DHCP.VendorClassIdentifier,  config_parse_string,                0,                             offsetof(Network, dhcp_vendor_class_identifier)
 /* backwards compatibility: do not add new entries to this section */
index 3f0ef5d0ec0c7933c2bf3da71b3a67beaf41ded2..9abc0d46ec0c511a8fbea86fdf3f8d15216bae60 100644 (file)
@@ -92,6 +92,7 @@ struct Network {
         bool dhcp_hostname;
         bool dhcp_domainname;
         bool dhcp_sendhost;
+        bool dhcp_broadcast;
         bool dhcp_critical;
         bool dhcp_routes;
         bool ipv4ll;
index 9ab6105e5b67d9870fb2f583e9e4c26a183f88cc..08aa0dca69221aaac8ba32319dfe9b9eb11ea113 100644 (file)
@@ -48,6 +48,7 @@ int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
 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);