Commit 31d19f51 authored by Dan Williams's avatar Dan Williams

dhcp: filter DHCP options when setting them

Don't bother storing all the options, only store the ones we care
about and ones we export through the NMDHCP4Config and NMDHCP6Config
objects.
parent 4ce6e39a
......@@ -2604,11 +2604,9 @@ dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
}
static void
dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data)
dhcp4_add_option_cb (const char *key, const char *value, gpointer user_data)
{
nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data),
(const char *) key,
(const char *) value);
nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data), key, value);
}
static gboolean
......@@ -3023,11 +3021,9 @@ dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
}
static void
dhcp6_add_option_cb (gpointer key, gpointer value, gpointer user_data)
dhcp6_add_option_cb (const char *key, const char *value, gpointer user_data)
{
nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data),
(const char *) key,
(const char *) value);
nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data), key, value);
}
static gboolean
......
......@@ -596,25 +596,47 @@ garray_to_string (GArray *array, const char *key)
return converted;
}
#define OLD_TAG "old_"
#define NEW_TAG "new_"
static void
copy_option (gpointer key,
gpointer value,
copy_option (const char * key,
GValue *value,
gpointer user_data)
{
GHashTable *hash = user_data;
const char *str_key = (const char *) key;
char *str_value = NULL;
const char **p;
static const char *ignored_keys[] = {
"interface",
"pid",
"reason",
"dhcp_message_type",
NULL
};
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY)) {
nm_log_warn (LOGD_DHCP, "key %s value type was not DBUS_TYPE_G_UCHAR_ARRAY", key);
return;
}
if (G_VALUE_TYPE (value) != DBUS_TYPE_G_UCHAR_ARRAY) {
nm_log_warn (LOGD_DHCP, "unexpected key %s value type was not "
"DBUS_TYPE_G_UCHAR_ARRAY",
str_key);
if (g_str_has_prefix (key, OLD_TAG))
return;
/* Filter out stuff that's not actually new DHCP options */
for (p = ignored_keys; *p; p++) {
if (!strcmp (*p, key))
return;
}
str_value = garray_to_string ((GArray *) g_value_get_boxed (value), str_key);
if (g_str_has_prefix (key, NEW_TAG))
key += STRLEN (NEW_TAG);
if (!key[0])
return;
str_value = garray_to_string ((GArray *) g_value_get_boxed (value), key);
if (str_value)
g_hash_table_insert (hash, g_strdup (str_key), str_value);
g_hash_table_insert (hash, g_strdup (key), str_value);
}
void
......@@ -636,7 +658,7 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
/* Clear old and save new DHCP options */
g_hash_table_remove_all (priv->options);
g_hash_table_foreach (options, copy_option, priv->options);
g_hash_table_foreach (options, (GHFunc) copy_option, priv->options);
/* dhclient sends same-state transitions for RENEW/REBIND events, but
* the lease may have changed, so handle same-state transitions for
......@@ -661,20 +683,17 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
nm_dhcp_client_set_state (self, new_state);
}
#define NEW_TAG "new_"
#define OLD_TAG "old_"
gboolean
nm_dhcp_client_foreach_option (NMDHCPClient *self,
GHFunc func,
NMDhcpClientForeachFunc callback,
gpointer user_data)
{
NMDHCPClientPrivate *priv;
GHashTableIter iter;
gpointer iterkey, itervalue;
const char *key, *value;
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
g_return_val_if_fail (func != NULL, FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
......@@ -686,32 +705,9 @@ nm_dhcp_client_foreach_option (NMDHCPClient *self,
}
g_hash_table_iter_init (&iter, priv->options);
while (g_hash_table_iter_next (&iter, &iterkey, &itervalue)) {
const char *key = iterkey, *value = itervalue;
const char **p;
static const char *filter_options[] = {
"interface", "pid", "reason", "dhcp_message_type", NULL
};
gboolean ignore = FALSE;
/* Filter out stuff that's not actually new DHCP options */
for (p = filter_options; *p; p++) {
if (!strcmp (*p, key) || !strncmp (key, OLD_TAG, strlen (OLD_TAG))) {
ignore = TRUE;
break;
}
}
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
callback (key, value, user_data);
if (!ignore) {
const char *tmp_key = key;
/* Remove the "new_" prefix that dhclient passes back */
if (!strncmp (key, NEW_TAG, strlen (NEW_TAG)))
tmp_key = key + strlen (NEW_TAG);
func ((gpointer) tmp_key, (gpointer) value, user_data);
}
}
return TRUE;
}
......
......@@ -121,8 +121,12 @@ void nm_dhcp_client_new_options (NMDHCPClient *self,
GHashTable *options,
const char *reason);
typedef void (*NMDhcpClientForeachFunc) (const char *key,
const char *value,
gpointer user_data);
gboolean nm_dhcp_client_foreach_option (NMDHCPClient *self,
GHFunc func,
NMDhcpClientForeachFunc callback,
gpointer user_data);
/* Backend helpers for subclasses */
......
......@@ -232,7 +232,7 @@ ip4_process_classless_routes (GHashTable *options,
*
* 192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41
*/
str = g_hash_table_lookup (options, "new_classless_static_routes");
str = g_hash_table_lookup (options, "classless_static_routes");
/* dhclient doesn't have actual support for rfc3442 classless static routes
* upstream. Thus, people resort to defining the option in dhclient.conf
......@@ -243,11 +243,11 @@ ip4_process_classless_routes (GHashTable *options,
* See https://lists.isc.org/pipermail/dhcp-users/2008-December/007629.html
*/
if (!str)
str = g_hash_table_lookup (options, "new_rfc3442_classless_static_routes");
str = g_hash_table_lookup (options, "rfc3442_classless_static_routes");
/* Microsoft version; same as rfc3442 but with a different option # (249) */
if (!str)
str = g_hash_table_lookup (options, "new_ms_classless_static_routes");
str = g_hash_table_lookup (options, "ms_classless_static_routes");
if (!str || !strlen (str))
return FALSE;
......@@ -275,7 +275,7 @@ process_classful_routes (GHashTable *options, guint priority, NMIP4Config *ip4_c
const char *str;
char **searches, **s;
str = g_hash_table_lookup (options, "new_static_routes");
str = g_hash_table_lookup (options, "static_routes");
if (!str)
return;
......@@ -386,14 +386,14 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
memset (&address, 0, sizeof (address));
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
str = g_hash_table_lookup (options, "new_ip_address");
str = g_hash_table_lookup (options, "ip_address");
if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) {
address.address = tmp_addr;
nm_log_info (LOGD_DHCP4, " address %s", str);
} else
goto error;
str = g_hash_table_lookup (options, "new_subnet_mask");
str = g_hash_table_lookup (options, "subnet_mask");
if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) {
plen = nm_utils_ip4_netmask_to_prefix (tmp_addr);
nm_log_info (LOGD_DHCP4, " plen %d (%s)", plen, str);
......@@ -417,7 +417,7 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
/* If the gateway wasn't provided as a classless static route with a
* subnet length of 0, try to find it using the old-style 'routers' option.
*/
str = g_hash_table_lookup (options, "new_routers");
str = g_hash_table_lookup (options, "routers");
if (str) {
char **routers = g_strsplit (str, " ", 0);
char **s;
......@@ -447,7 +447,7 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
* dhcp server may not be reachable via unicast, and a host
* specific route is needed.
**/
str = g_hash_table_lookup (options, "new_dhcp_server_identifier");
str = g_hash_table_lookup (options, "dhcp_server_identifier");
if (str) {
if (inet_pton (AF_INET, str, &tmp_addr) > 0) {
NMPlatformIP4Route route;
......@@ -472,7 +472,7 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
nm_log_warn (LOGD_DHCP4, "ignoring invalid server identifier '%s'", str);
}
str = g_hash_table_lookup (options, "new_dhcp_lease_time");
str = g_hash_table_lookup (options, "dhcp_lease_time");
if (str) {
address.lifetime = address.preferred = strtoul (str, NULL, 10);
nm_log_info (LOGD_DHCP4, " lease time %d", address.lifetime);
......@@ -481,11 +481,11 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
address.source = NM_PLATFORM_SOURCE_DHCP;
nm_ip4_config_add_address (ip4_config, &address);
str = g_hash_table_lookup (options, "new_host_name");
str = g_hash_table_lookup (options, "host_name");
if (str)
nm_log_info (LOGD_DHCP4, " hostname '%s'", str);
str = g_hash_table_lookup (options, "new_domain_name_servers");
str = g_hash_table_lookup (options, "domain_name_servers");
if (str) {
char **searches = g_strsplit (str, " ", 0);
char **s;
......@@ -500,7 +500,7 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
g_strfreev (searches);
}
str = g_hash_table_lookup (options, "new_domain_name");
str = g_hash_table_lookup (options, "domain_name");
if (str) {
char **domains = g_strsplit (str, " ", 0);
char **s;
......@@ -512,11 +512,11 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
g_strfreev (domains);
}
str = g_hash_table_lookup (options, "new_domain_search");
str = g_hash_table_lookup (options, "domain_search");
if (str)
process_domain_search (str, ip4_add_domain_search, ip4_config);
str = g_hash_table_lookup (options, "new_netbios_name_servers");
str = g_hash_table_lookup (options, "netbios_name_servers");
if (str) {
char **searches = g_strsplit (str, " ", 0);
char **s;
......@@ -531,7 +531,7 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
g_strfreev (searches);
}
str = g_hash_table_lookup (options, "new_interface_mtu");
str = g_hash_table_lookup (options, "interface_mtu");
if (str) {
int int_mtu;
......@@ -544,13 +544,13 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
nm_ip4_config_set_mtu (ip4_config, int_mtu);
}
str = g_hash_table_lookup (options, "new_nis_domain");
str = g_hash_table_lookup (options, "nis_domain");
if (str) {
nm_log_info (LOGD_DHCP4, " NIS domain '%s'", str);
nm_ip4_config_set_nis_domain (ip4_config, str);
}
str = g_hash_table_lookup (options, "new_nis_servers");
str = g_hash_table_lookup (options, "nis_servers");
if (str) {
char **searches = g_strsplit (str, " ", 0);
char **s;
......@@ -607,19 +607,19 @@ nm_dhcp_utils_ip6_config_from_options (const char *iface,
ip6_config = nm_ip6_config_new ();
str = g_hash_table_lookup (options, "new_max_life");
str = g_hash_table_lookup (options, "max_life");
if (str) {
address.lifetime = strtoul (str, NULL, 10);
nm_log_info (LOGD_DHCP6, " valid_lft %d", address.lifetime);
}
str = g_hash_table_lookup (options, "new_preferred_life");
str = g_hash_table_lookup (options, "preferred_life");
if (str) {
address.preferred = strtoul (str, NULL, 10);
nm_log_info (LOGD_DHCP6, " preferred_lft %d", address.preferred);
}
str = g_hash_table_lookup (options, "new_ip6_address");
str = g_hash_table_lookup (options, "ip6_address");
if (str) {
if (!inet_pton (AF_INET6, str, &tmp_addr)) {
nm_log_warn (LOGD_DHCP6, "(%s): DHCP returned invalid address '%s'",
......@@ -636,11 +636,11 @@ nm_dhcp_utils_ip6_config_from_options (const char *iface,
goto error;
}
str = g_hash_table_lookup (options, "new_host_name");
str = g_hash_table_lookup (options, "host_name");
if (str)
nm_log_info (LOGD_DHCP6, " hostname '%s'", str);
str = g_hash_table_lookup (options, "new_dhcp6_name_servers");
str = g_hash_table_lookup (options, "dhcp6_name_servers");
if (str) {
char **searches = g_strsplit (str, " ", 0);
char **s;
......@@ -655,7 +655,7 @@ nm_dhcp_utils_ip6_config_from_options (const char *iface,
g_strfreev (searches);
}
str = g_hash_table_lookup (options, "new_dhcp6_domain_search");
str = g_hash_table_lookup (options, "dhcp6_domain_search");
if (str)
process_domain_search (str, ip6_add_domain_search, ip6_config);
......
......@@ -47,23 +47,21 @@ fill_table (Option *test_options, GHashTable *table)
}
static Option generic_options[] = {
{ "new_subnet_mask", "255.255.255.0" },
{ "new_ip_address", "192.168.1.106" },
{ "new_network_number", "192.168.1.0" },
{ "interface", "eth0" },
{ "reason", "BOUND" },
{ "new_expiry", "1232324877" },
{ "new_dhcp_lease_time", "3600" },
{ "new_dhcp_server_identifier", "192.168.1.1" },
{ "new_routers", "192.168.1.1" },
{ "new_domain_name_servers", "216.254.95.2 216.231.41.2" },
{ "new_dhcp_message_type", "5" },
{ "new_broadcast_address", "192.168.1.255" },
{ "new_domain_search", "foobar.com blah.foobar.com" },
{ "new_host_name", "nmreallywhipsthe" },
{ "new_domain_name", "lamasass.com" },
{ "new_interface_mtu", "987" },
{ "new_static_routes", "10.1.1.5 10.1.1.1 100.99.88.56 10.1.1.1" },
{ "subnet_mask", "255.255.255.0" },
{ "ip_address", "192.168.1.106" },
{ "network_number", "192.168.1.0" },
{ "expiry", "1232324877" },
{ "dhcp_lease_time", "3600" },
{ "dhcp_server_identifier", "192.168.1.1" },
{ "routers", "192.168.1.1" },
{ "domain_name_servers", "216.254.95.2 216.231.41.2" },
{ "dhcp_message_type", "5" },
{ "broadcast_address", "192.168.1.255" },
{ "domain_search", "foobar.com blah.foobar.com" },
{ "host_name", "nmreallywhipsthe" },
{ "domain_name", "lamasass.com" },
{ "interface_mtu", "987" },
{ "static_routes", "10.1.1.5 10.1.1.1 100.99.88.56 10.1.1.1" },
{ NULL, NULL }
};
......@@ -180,7 +178,7 @@ test_generic_options (void)
}
static Option wins_options[] = {
{ "new_netbios_name_servers", "63.12.199.5 150.4.88.120" },
{ "netbios_name_servers", "63.12.199.5 150.4.88.120" },
{ NULL, NULL }
};
......@@ -275,7 +273,7 @@ test_classless_static_routes_1 (void)
const char *expected_route2_gw = "10.17.66.41";
static Option data[] = {
/* dhclient custom format */
{ "new_rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 8 10 10 17 66 41" },
{ "rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 8 10 10 17 66 41" },
{ NULL, NULL }
};
......@@ -307,7 +305,7 @@ test_classless_static_routes_2 (void)
const char *expected_route2_gw = "10.17.66.41";
static Option data[] = {
/* dhcpcd format */
{ "new_classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41" },
{ "classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41" },
{ NULL, NULL }
};
......@@ -340,7 +338,7 @@ test_fedora_dhclient_classless_static_routes (void)
const char *expected_gateway = "192.168.0.113";
static Option data[] = {
/* Fedora dhclient format */
{ "new_classless_static_routes", "0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6" },
{ "classless_static_routes", "0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6" },
{ NULL, NULL }
};
......@@ -373,7 +371,7 @@ test_dhclient_invalid_classless_routes_1 (void)
const char *expected_route1_gw = "192.168.1.1";
static Option data[] = {
/* dhclient format */
{ "new_rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41" },
{ "rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41" },
{ NULL, NULL }
};
......@@ -408,7 +406,7 @@ test_dhcpcd_invalid_classless_routes_1 (void)
const char *expected_route2_gw = "10.1.1.1";
static Option data[] = {
/* dhcpcd format */
{ "new_classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41" },
{ "classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41" },
{ NULL, NULL }
};
......@@ -445,7 +443,7 @@ test_dhclient_invalid_classless_routes_2 (void)
const char *expected_route2_dest = "100.99.88.56";
const char *expected_route2_gw = "10.1.1.1";
static Option data[] = {
{ "new_rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1" },
{ "rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1" },
{ NULL, NULL }
};
......@@ -482,7 +480,7 @@ test_dhcpcd_invalid_classless_routes_2 (void)
const char *expected_route2_dest = "100.99.88.56";
const char *expected_route2_gw = "10.1.1.1";
static Option data[] = {
{ "new_classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1" },
{ "classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1" },
{ NULL, NULL }
};
......@@ -519,7 +517,7 @@ test_dhclient_invalid_classless_routes_3 (void)
const char *expected_route1_dest = "192.168.10.0";
const char *expected_route1_gw = "192.168.1.1";
static Option data[] = {
{ "new_rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41" },
{ "rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41" },
{ NULL, NULL }
};
......@@ -550,7 +548,7 @@ test_dhcpcd_invalid_classless_routes_3 (void)
const char *expected_route1_dest = "192.168.10.0";
const char *expected_route1_gw = "192.168.1.1";
static Option data[] = {
{ "new_classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41" },
{ "classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41" },
{ NULL, NULL }
};
......@@ -582,7 +580,7 @@ test_dhclient_gw_in_classless_routes (void)
const char *expected_route1_gw = "192.168.1.1";
const char *expected_gateway = "192.2.3.4";
static Option data[] = {
{ "new_rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 0 192 2 3 4" },
{ "rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 0 192 2 3 4" },
{ NULL, NULL }
};
......@@ -613,7 +611,7 @@ test_dhcpcd_gw_in_classless_routes (void)
const char *expected_route1_gw = "192.168.1.1";
const char *expected_gateway = "192.2.3.4";
static Option data[] = {
{ "new_classless_static_routes", "192.168.10.0/24 192.168.1.1 0.0.0.0/0 192.2.3.4" },
{ "classless_static_routes", "192.168.10.0/24 192.168.1.1 0.0.0.0/0 192.2.3.4" },
{ NULL, NULL }
};
......@@ -636,7 +634,7 @@ test_dhcpcd_gw_in_classless_routes (void)
}
static Option escaped_searches_options[] = {
{ "new_domain_search", "host1\\032host2\\032host3" },
{ "domain_search", "host1\\032host2\\032host3" },
{ NULL, NULL }
};
......@@ -669,7 +667,7 @@ test_escaped_domain_searches (void)
}
static Option invalid_escaped_searches_options[] = {
{ "new_domain_search", "host1\\aahost2\\032host3" },
{ "domain_search", "host1\\aahost2\\032host3" },
{ NULL, NULL }
};
......@@ -704,8 +702,8 @@ test_ip4_missing_prefix (const char *ip, guint32 expected_prefix)
const NMPlatformIP4Address *address;
options = fill_table (generic_options, NULL);
g_hash_table_insert (options, "new_ip_address", (gpointer) ip);
g_hash_table_remove (options, "new_subnet_mask");
g_hash_table_insert (options, "ip_address", (gpointer) ip);
g_hash_table_remove (options, "subnet_mask");
ip4_config = nm_dhcp_utils_ip4_config_from_options ("eth0", options, 0);
ASSERT (ip4_config != NULL,
......@@ -756,8 +754,8 @@ test_ip4_prefix_classless (void)
*/
options = fill_table (generic_options, NULL);
g_hash_table_insert (options, "new_ip_address", "172.16.54.22");
g_hash_table_insert (options, "new_subnet_mask", "255.255.252.0");
g_hash_table_insert (options, "ip_address", "172.16.54.22");
g_hash_table_insert (options, "subnet_mask", "255.255.252.0");
ip4_config = nm_dhcp_utils_ip4_config_from_options ("eth0", options, 0);
ASSERT (ip4_config != NULL,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment