summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorViktor Mihajlovski <mihajlov@linux.ibm.com>2021-04-14 13:01:35 +0200
committerViktor Mihajlovski <mihajlov@linux.ibm.com>2021-04-21 18:11:18 +0200
commite70eca9b48df906a3e2d9f36d3acd4b5cb9ae553 (patch)
tree158f5af06f773e2b4e36b4c5a658af55a56f6718 /src/network
parent5c9f1c68f032287da3fa7f5c4c08dfb0bf340c0b (diff)
downloadsystemd-e70eca9b48df906a3e2d9f36d3acd4b5cb9ae553.tar.gz
network: enable DHCP broadcast flag if required by interface
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
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-dhcp4.c26
-rw-r--r--src/network/networkd-network-gperf.gperf4
-rw-r--r--src/network/networkd-network.c1
-rw-r--r--src/network/networkd-network.h2
4 files changed, 29 insertions, 4 deletions
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 6f06e2218d..64ecd9ceb5 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -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");
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 6c37e32453..f50435b293 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -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)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 7f086ceae2..bd363b7bd6 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index df77b42619..de5bd60a68 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -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;