]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
DHCPv4: client add support for DHCP server allow list
authorSusant Sahani <ssahani@vmware.com>
Fri, 26 Jun 2020 03:28:52 +0000 (03:28 +0000)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 6 Jul 2020 20:28:54 +0000 (22:28 +0200)
man/systemd.network.xml
src/network/networkd-dhcp4.c
src/network/networkd-dhcp4.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/fuzz/fuzz-network-parser/directives.network

index 88f00bdca633f6f5e8c54907c11e26921069c3d9..d08543c5fc547a275ce35232aa62bfad8f22bf1f 100644 (file)
         <varlistentry>
         <term><varname>DenyList=</varname></term>
         <listitem>
-          <para>A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected.</para>
+          <para>A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected. Note that
+          if <varname>AllowList=</varname> is configured then <varname>DenyList=</varname> is ignored.</para>
+        </listitem>
+        </varlistentry>
+
+        <varlistentry>
+        <term><varname>AllowList=</varname></term>
+        <listitem>
+          <para>A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are accepted.</para>
         </listitem>
         </varlistentry>
 
index 20dae6c19fa519292a2bd7afbf161393fa600e21..9a99c1e6f956d6e1e91caf5109057032db2016ed 100644 (file)
@@ -1079,6 +1079,34 @@ static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) {
         return false;
 }
 
+static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) {
+        sd_dhcp_lease *lease;
+        struct in_addr addr;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(client);
+
+        r = sd_dhcp_client_get_lease(client, &lease);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
+
+        r = sd_dhcp_lease_get_server_identifier(lease, &addr);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
+
+        if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
+                log_struct(LOG_DEBUG,
+                           LOG_LINK_INTERFACE(link),
+                           LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in allow-listed ip addresses, accepting offer",
+                                            ADDRESS_FMT_VAL(addr)));
+                return true;
+        }
+
+        return false;
+}
+
 static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
         Link *link = userdata;
         int r;
@@ -1163,12 +1191,19 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         }
                         break;
                 case SD_DHCP_CLIENT_EVENT_SELECTING:
-                        r = dhcp_server_is_deny_listed(link, client);
-                        if (r < 0)
-                                return r;
-                        if (r != 0)
-                                return -ENOMSG;
-
+                        if (!set_isempty(link->network->dhcp_allow_listed_ip)) {
+                                r = dhcp_server_is_allow_listed(link, client);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        return -ENOMSG;
+                        } else {
+                                r = dhcp_server_is_deny_listed(link, client);
+                                if (r < 0)
+                                        return r;
+                                if (r != 0)
+                                        return -ENOMSG;
+                        }
                         break;
                 default:
                         if (event < 0)
@@ -1551,7 +1586,7 @@ int config_parse_dhcp_max_attempts(
         return 0;
 }
 
-int config_parse_dhcp_deny_listed_ip_address(
+int config_parse_dhcp_acl_ip_address(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -1564,6 +1599,7 @@ int config_parse_dhcp_deny_listed_ip_address(
                 void *userdata) {
 
         Network *network = data;
+        Set **acl;
         int r;
 
         assert(filename);
@@ -1571,8 +1607,10 @@ int config_parse_dhcp_deny_listed_ip_address(
         assert(rvalue);
         assert(data);
 
+        acl = STR_IN_SET(lvalue, "DenyList", "BlackList") ? &network->dhcp_deny_listed_ip : &network->dhcp_allow_listed_ip;
+
         if (isempty(rvalue)) {
-                network->dhcp_deny_listed_ip = set_free(network->dhcp_deny_listed_ip);
+                *acl = set_free(*acl);
                 return 0;
         }
 
@@ -1583,8 +1621,8 @@ int config_parse_dhcp_deny_listed_ip_address(
                 r = extract_first_word(&p, &n, NULL, 0);
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to parse DHCP deny-listed IP address, ignoring assignment: %s",
-                                   rvalue);
+                                   "Failed to parse DHCP '%s=' IP address, ignoring assignment: %s",
+                                   lvalue, rvalue);
                         return 0;
                 }
                 if (r == 0)
@@ -1593,14 +1631,14 @@ int config_parse_dhcp_deny_listed_ip_address(
                 r = in_addr_from_string(AF_INET, n, &ip);
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "DHCP deny-listed IP address is invalid, ignoring assignment: %s", n);
+                                   "DHCP '%s=' IP address is invalid, ignoring assignment: %s", lvalue, n);
                         continue;
                 }
 
-                r = set_ensure_put(&network->dhcp_deny_listed_ip, NULL, UINT32_TO_PTR(ip.in.s_addr));
+                r = set_ensure_put(acl, NULL, UINT32_TO_PTR(ip.in.s_addr));
                 if (r < 0)
                         log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to store DHCP deny-listed IP address '%s', ignoring assignment: %m", n);
+                                   "Failed to store DHCP '%s=' IP address '%s', ignoring assignment: %m", lvalue, n);
         }
 
         return 0;
index 567ee724da9c865712514919d9650bcff5b1ec37..96ac696ce6ec53a027d03a79b2031acdf3d09c54 100644 (file)
@@ -23,7 +23,7 @@ int dhcp4_set_client_identifier(Link *link);
 int dhcp4_set_promote_secondaries(Link *link);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_deny_listed_ip_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url);
index 087358da11b5135b52a55c7c616d306e98df9eb3..6b471c51e9e0f3d0728d5184e88b31a63a99ac59 100644 (file)
@@ -197,8 +197,8 @@ DHCPv4.IAID,                                 config_parse_iaid,
 DHCPv4.ListenPort,                           config_parse_uint16,                                      0,                             offsetof(Network, dhcp_client_port)
 DHCPv4.SendRelease,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_release)
 DHCPv4.SendDecline,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_decline)
-DHCPv4.DenyList,                             config_parse_dhcp_deny_listed_ip_address,                 0,                             0
-DHCPv4.BlackList,                            config_parse_dhcp_deny_listed_ip_address,                 0,                             0
+DHCPv4.DenyList,                             config_parse_dhcp_acl_ip_address,                         0,                             0
+DHCPv4.AllowList,                            config_parse_dhcp_acl_ip_address,                         0,                             0
 DHCPv4.IPServiceType,                        config_parse_dhcp_ip_service_type,                        0,                             offsetof(Network, ip_service_type)
 DHCPv4.SendOption,                           config_parse_dhcp_send_option,                            AF_INET,                       offsetof(Network, dhcp_client_send_options)
 DHCPv4.SendVendorOption,                     config_parse_dhcp_send_option,                            0,                             offsetof(Network, dhcp_client_send_vendor_options)
@@ -414,6 +414,7 @@ TrivialLinkEqualizer.Handle,                 config_parse_qdisc_handle,
 TrivialLinkEqualizer.Id,                     config_parse_trivial_link_equalizer_id,                   QDISC_KIND_TEQL,               0
 /* backwards compatibility: do not add new entries to this section */
 Network.IPv4LL,                              config_parse_ipv4ll,                                      0,                             offsetof(Network, link_local)
+DHCPv4.BlackList,                            config_parse_dhcp_acl_ip_address,                         0,                             0
 DHCP.ClientIdentifier,                       config_parse_dhcp_client_identifier,                      0,                             offsetof(Network, dhcp_client_identifier)
 DHCP.UseDNS,                                 config_parse_dhcp_use_dns,                                0,                             0
 DHCP.UseNTP,                                 config_parse_dhcp_use_ntp,                                0,                             0
index 5316faeedb27e5d44d17f52428a6d91c637ef753..22bd06a891179bf7370e833666ec13b7b8c0d04e 100644 (file)
@@ -670,6 +670,7 @@ static Network *network_free(Network *network) {
         strv_free(network->dhcp_user_class);
         free(network->dhcp_hostname);
         set_free(network->dhcp_deny_listed_ip);
+        set_free(network->dhcp_allow_listed_ip);
         set_free(network->dhcp_request_options);
         set_free(network->dhcp6_request_options);
         free(network->mac);
index 2ce555bfc557f7686b5027fa9090b4f9a1f6b352..424298248f963b877b52b1f94635d8bd6674f171 100644 (file)
@@ -140,6 +140,7 @@ struct Network {
         DHCPUseDomains dhcp_use_domains;
         sd_ipv4acd *dhcp_acd;
         Set *dhcp_deny_listed_ip;
+        Set *dhcp_allow_listed_ip;
         Set *dhcp_request_options;
         OrderedHashmap *dhcp_client_send_options;
         OrderedHashmap *dhcp_client_send_vendor_options;
index 1754a1cd824a83c91b2387414d5f36da314df271..aa04c1192a3015f0834b3ea5c984b827811489a3 100644 (file)
@@ -107,6 +107,7 @@ UseTimezone=
 RouteTable=
 DenyList=
 BlackList=
+AllowList=
 RequestOptions=
 SendRelease=
 MaxAttempts=