]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: enable DHCP broadcast flag if required by interface 19346/head
authorViktor Mihajlovski <mihajlov@linux.ibm.com>
Wed, 14 Apr 2021 11:01:35 +0000 (13:01 +0200)
committerViktor Mihajlovski <mihajlov@linux.ibm.com>
Wed, 21 Apr 2021 16:11:18 +0000 (18:11 +0200)
Some interfaces require that the DHCPOFFER message is sent via broadcast
if they can't receive unicast messages before they've been configured
with an IP address.

E.g., s390 ccwgroup network interfaces operating in layer3 mode face
this limitation. This can prevent the interfaces from receiving an
IP address via DHCP, if the have been configured for layer3.

To allow DHCP over such interfaces, we're introducing a new device
property ID_NET_DHCP_BROADCAST which can be set for those.
The networkd DHCP client will check whether this property is set
for an interface, and if so will set the broadcast flag, unless
the network configuration for the interface has an explicit
RequestBroadcast setting.

Besides that, we're adding a udev rule to set this device property
for ccwgroup devices operating in layer3 mode, which is the case
if the ID_NET_DRIVER property is qeth_l3.

Supercedes #18829

rules.d/81-net-dhcp.rules [new file with mode: 0644]
rules.d/meson.build
src/network/networkd-dhcp4.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h

diff --git a/rules.d/81-net-dhcp.rules b/rules.d/81-net-dhcp.rules
new file mode 100644 (file)
index 0000000..2ef25ba
--- /dev/null
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="net_dhcp_end"
+SUBSYSTEM!="net", GOTO="net_dhcp_end"
+
+# Network interfaces requiring DHCPOFFER messages to be broadcast
+# must set ID_NET_DHCP_BROADCAST to "1". This property will be
+# checked by the networkd DHCP4 client to set the DHCP option
+
+# s390 ccwgroup interfaces in layer3 mode need broadcast DHCPOFFER
+# using the link driver to detect this condition
+ENV{ID_NET_DRIVER}=="qeth_l3", ENV{ID_NET_DHCP_BROADCAST}="1"
+
+LABEL="net_dhcp_end"
index 42fa451c6bac73102697dfb71e90dfa4fa6fb87b..4bbba09fd544000080a5d23d45ceab9585a2086e 100644 (file)
@@ -26,6 +26,7 @@ rules = files('''
         75-probe_mtd.rules
         78-sound-card.rules
         80-net-setup-link.rules
+        81-net-dhcp.rules
 '''.split())
 
 if conf.get('HAVE_KMOD') == 1
index 6f06e2218d348897461b8b66984da1fc4351d998..64ecd9ceb50cd009da0cca28a3cbc33d56b281cb 100644 (file)
@@ -1283,6 +1283,30 @@ static int dhcp4_set_request_address(Link *link) {
         return sd_dhcp_client_set_request_address(link->dhcp_client, &a->in_addr.in);
 }
 
+static bool link_needs_dhcp_broadcast(Link *link) {
+        const char *val;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        /* Return the setting in DHCP[4].RequestBroadcast if specified. Otherwise return the device property
+         * ID_NET_DHCP_BROADCAST setting, which may be set for interfaces requiring that the DHCPOFFER message
+         * is being broadcast because they can't  handle unicast messages while not fully configured.
+         * If neither is set or a failure occurs, return false, which is the default for this flag.
+         */
+        r = link->network->dhcp_broadcast;
+        if (r < 0 && link->sd_device && sd_device_get_property_value(link->sd_device, "ID_NET_DHCP_BROADCAST", &val) >= 0) {
+                r = parse_boolean(val);
+                if (r < 0)
+                        log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to parse ID_NET_DHCP_BROADCAST, ignoring: %m");
+                else
+                        log_link_debug(link, "DHCP4 CLIENT: Detected ID_NET_DHCP_BROADCAST='%d'.", r);
+
+        }
+        return r == true;
+}
+
 int dhcp4_configure(Link *link) {
         sd_dhcp_option *send_option;
         void *request_options;
@@ -1319,7 +1343,7 @@ int dhcp4_configure(Link *link) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m");
 
-        r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link->network->dhcp_broadcast);
+        r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link_needs_dhcp_broadcast(link));
         if (r < 0)
                 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m");
 
index 6c37e32453117c7b5b61e89b7a9e82a3cab75927..f50435b29365ac972634dd92a3e1834bc298c9c2 100644 (file)
@@ -207,7 +207,7 @@ DHCPv4.RequestOptions,                       config_parse_dhcp_request_options,
 DHCPv4.Anonymize,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_anonymize)
 DHCPv4.SendHostname,                         config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_hostname)
 DHCPv4.Hostname,                             config_parse_hostname,                                    0,                             offsetof(Network, dhcp_hostname)
-DHCPv4.RequestBroadcast,                     config_parse_bool,                                        0,                             offsetof(Network, dhcp_broadcast)
+DHCPv4.RequestBroadcast,                     config_parse_tristate,                                    0,                             offsetof(Network, dhcp_broadcast)
 DHCPv4.VendorClassIdentifier,                config_parse_string,                                      0,                             offsetof(Network, dhcp_vendor_class_identifier)
 DHCPv4.MUDURL,                               config_parse_dhcp_mud_url,                                0,                             0
 DHCPv4.MaxAttempts,                          config_parse_dhcp_max_attempts,                           0,                             0
@@ -475,7 +475,7 @@ DHCP.UseRoutes,                              config_parse_bool,
 DHCP.Anonymize,                              config_parse_bool,                                        0,                             offsetof(Network, dhcp_anonymize)
 DHCP.SendHostname,                           config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_hostname)
 DHCP.Hostname,                               config_parse_hostname,                                    0,                             offsetof(Network, dhcp_hostname)
-DHCP.RequestBroadcast,                       config_parse_bool,                                        0,                             offsetof(Network, dhcp_broadcast)
+DHCP.RequestBroadcast,                       config_parse_tristate,                                    0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,                     config_parse_tristate,                                    0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,                  config_parse_string,                                      0,                             offsetof(Network, dhcp_vendor_class_identifier)
 DHCP.UserClass,                              config_parse_dhcp_user_or_vendor_class,                   AF_INET,                       offsetof(Network, dhcp_user_class)
index 7f086ceae28520ed7b17f513537841693c1d9edb..bd363b7bd64db59e15b4d68b68bbb6bb92e95a61 100644 (file)
@@ -368,6 +368,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
                 .dhcp_use_timezone = false,
                 .dhcp_ip_service_type = -1,
+                .dhcp_broadcast = -1,
 
                 .dhcp6_use_address = true,
                 .dhcp6_use_dns = true,
index df77b4261926d073b2a03dcc5a874099e47ebd67..de5bd60a687fe01624beb6b9d155c788ea226367 100644 (file)
@@ -136,7 +136,7 @@ struct Network {
         int dhcp_ip_service_type;
         bool dhcp_anonymize;
         bool dhcp_send_hostname;
-        bool dhcp_broadcast;
+        int dhcp_broadcast;
         bool dhcp_use_dns;
         bool dhcp_use_dns_set;
         bool dhcp_routes_to_dns;