summary refs log tree commit diff
path: root/src/dhcp/nm-dhcp-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcp/nm-dhcp-utils.c')
-rw-r--r--src/dhcp/nm-dhcp-utils.c88
1 files changed, 56 insertions, 32 deletions
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
index e55a21b4..4b2d57b9 100644
--- a/src/dhcp/nm-dhcp-utils.c
+++ b/src/dhcp/nm-dhcp-utils.c
@@ -24,6 +24,8 @@
 #include <unistd.h>
 #include <arpa/inet.h>
 
+#include "nm-utils/nm-dedup-multi.h"
+
 #include "nm-dhcp-utils.h"
 #include "nm-utils.h"
 #include "NetworkManagerUtils.h"
@@ -36,7 +38,8 @@
 static gboolean
 ip4_process_dhcpcd_rfc3442_routes (const char *iface,
                                    const char *str,
-                                   guint32 priority,
+                                   guint32 route_table,
+                                   guint32 route_metric,
                                    NMIP4Config *ip4_config,
                                    guint32 *gwaddr)
 {
@@ -84,12 +87,13 @@ ip4_process_dhcpcd_rfc3442_routes (const char *iface,
 		} else {
 			_LOG2I (LOGD_DHCP4, iface, "  classless static route %s/%d gw %s", *r, rt_cidr, *(r + 1));
 			memset (&route, 0, sizeof (route));
-			route.network = rt_addr;
+			route.network = nm_utils_ip4_address_clear_host_address (rt_addr, rt_cidr);
 			route.plen = rt_cidr;
 			route.gateway = rt_route;
 			route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
-			route.metric = priority;
-			nm_ip4_config_add_route (ip4_config, &route);
+			route.metric = route_metric;
+			route.table_coerced = nm_platform_route_table_coerce (route_table);
+			nm_ip4_config_add_route (ip4_config, &route, NULL);
 		}
 	}
 
@@ -142,8 +146,7 @@ process_dhclient_rfc3442_route (const char **octets,
 			goto error;
 		}
 		g_free (str_addr);
-		tmp_addr &= nm_utils_ip4_prefix_to_netmask ((guint32) tmp);
-		route->network = tmp_addr;
+		route->network = nm_utils_ip4_address_clear_host_address (tmp_addr, tmp);
 	}
 
 	/* Handle next hop */
@@ -165,7 +168,8 @@ error:
 static gboolean
 ip4_process_dhclient_rfc3442_routes (const char *iface,
                                      const char *str,
-                                     guint32 priority,
+                                     guint32 route_table,
+                                     guint32 route_metric,
                                      NMIP4Config *ip4_config,
                                      guint32 *gwaddr)
 {
@@ -197,8 +201,9 @@ ip4_process_dhclient_rfc3442_routes (const char *iface,
 
 			/* normal route */
 			route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
-			route.metric = priority;
-			nm_ip4_config_add_route (ip4_config, &route);
+			route.metric = route_metric;
+			route.table_coerced = nm_platform_route_table_coerce (route_table);
+			nm_ip4_config_add_route (ip4_config, &route, NULL);
 
 			_LOG2I (LOGD_DHCP4, iface, "  classless static route %s/%d gw %s",
 			        nm_utils_inet4_ntop (route.network, addr), route.plen,
@@ -214,7 +219,8 @@ out:
 static gboolean
 ip4_process_classless_routes (const char *iface,
                               GHashTable *options,
-                              guint32 priority,
+                              guint32 route_table,
+                              guint32 route_metric,
                               NMIP4Config *ip4_config,
                               guint32 *gwaddr)
 {
@@ -270,16 +276,17 @@ ip4_process_classless_routes (const char *iface,
 
 	if (strchr (str, '/')) {
 		/* dhcpcd format */
-		return ip4_process_dhcpcd_rfc3442_routes (iface, str, priority, ip4_config, gwaddr);
+		return ip4_process_dhcpcd_rfc3442_routes (iface, str, route_table, route_metric, ip4_config, gwaddr);
 	}
 
-	return ip4_process_dhclient_rfc3442_routes (iface, str, priority, ip4_config, gwaddr);
+	return ip4_process_dhclient_rfc3442_routes (iface, str, route_table, route_metric, ip4_config, gwaddr);
 }
 
 static void
 process_classful_routes (const char *iface,
                          GHashTable *options,
-                         guint32 priority,
+                         guint32 route_table,
+                         guint32 route_metric,
                          NMIP4Config *ip4_config)
 {
 	const char *str;
@@ -316,16 +323,19 @@ process_classful_routes (const char *iface,
 		   The Static Routes option (option 33) does not provide a subnet mask
 		   for each route - it is assumed that the subnet mask is implicit in
 		   whatever network number is specified in each route entry */
-		route.plen = nm_utils_ip4_get_default_prefix (rt_addr);
-		if (rt_addr & ~nm_utils_ip4_prefix_to_netmask (route.plen)) {
+		route.plen = _nm_utils_ip4_get_default_prefix (rt_addr);
+		if (rt_addr & ~_nm_utils_ip4_prefix_to_netmask (route.plen)) {
 			/* RFC 943: target not "this network"; using host routing */
 			route.plen = 32;
 		}
 		route.gateway = rt_route;
 		route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
-		route.metric = priority;
+		route.metric = route_metric;
+		route.table_coerced = nm_platform_route_table_coerce (route_table);
+
+		route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen);
 
-		nm_ip4_config_add_route (ip4_config, &route);
+		nm_ip4_config_add_route (ip4_config, &route, NULL);
 		_LOG2I (LOGD_DHCP, iface, "  static route %s",
 		             nm_platform_ip4_route_to_string (&route, NULL, 0));
 	}
@@ -383,22 +393,25 @@ ip4_add_domain_search (gpointer data, gpointer user_data)
 }
 
 NMIP4Config *
-nm_dhcp_utils_ip4_config_from_options (int ifindex,
+nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
+                                       int ifindex,
                                        const char *iface,
                                        GHashTable *options,
-                                       guint32 priority)
+                                       guint32 route_table,
+                                       guint32 route_metric)
 {
 	NMIP4Config *ip4_config = NULL;
 	guint32 tmp_addr;
 	in_addr_t addr;
 	NMPlatformIP4Address address;
 	char *str = NULL;
-	guint32 gwaddr = 0;
+	gboolean gateway_has = FALSE;
+	guint32 gateway = 0;
 	guint8 plen = 0;
 
 	g_return_val_if_fail (options != NULL, NULL);
 
-	ip4_config = nm_ip4_config_new (ifindex);
+	ip4_config = nm_ip4_config_new (multi_idx, ifindex);
 	memset (&address, 0, sizeof (address));
 	address.timestamp = nm_utils_get_monotonic_timestamp_s ();
 
@@ -414,7 +427,7 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
 		_LOG2I (LOGD_DHCP4, iface, "  plen %d (%s)", plen, str);
 	} else {
 		/* Get default netmask for the IP according to appropriate class. */
-		plen = nm_utils_ip4_get_default_prefix (addr);
+		plen = _nm_utils_ip4_get_default_prefix (addr);
 		_LOG2I (LOGD_DHCP4, iface, "  plen %d (default)", plen);
 	}
 	nm_platform_ip4_address_set_addr (&address, addr, plen);
@@ -422,12 +435,12 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
 	/* Routes: if the server returns classless static routes, we MUST ignore
 	 * the 'static_routes' option.
 	 */
-	if (!ip4_process_classless_routes (iface, options, priority, ip4_config, &gwaddr))
-		process_classful_routes (iface, options, priority, ip4_config);
+	if (!ip4_process_classless_routes (iface, options, route_table, route_metric, ip4_config, &gateway))
+		process_classful_routes (iface, options, route_table, route_metric, ip4_config);
 
-	if (gwaddr) {
-		_LOG2I (LOGD_DHCP4, iface, "  gateway %s", nm_utils_inet4_ntop (gwaddr, NULL));
-		nm_ip4_config_set_gateway (ip4_config, gwaddr);
+	if (gateway) {
+		_LOG2I (LOGD_DHCP4, iface, "  gateway %s", nm_utils_inet4_ntop (gateway, NULL));
+		gateway_has = TRUE;
 	} else {
 		/* 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.
@@ -439,9 +452,9 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
 
 			for (s = routers; *s; s++) {
 				/* FIXME: how to handle multiple routers? */
-				if (inet_pton (AF_INET, *s, &gwaddr) > 0) {
-					nm_ip4_config_set_gateway (ip4_config, gwaddr);
+				if (inet_pton (AF_INET, *s, &gateway) > 0) {
 					_LOG2I (LOGD_DHCP4, iface, "  gateway %s", *s);
+					gateway_has = TRUE;
 					break;
 				} else
 					_LOG2W (LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s);
@@ -450,6 +463,17 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
 		}
 	}
 
+	if (gateway_has) {
+		const NMPlatformIP4Route r = {
+			.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+			.gateway = gateway,
+			.table_coerced = nm_platform_route_table_coerce (route_table),
+			.metric = route_metric,
+		};
+
+		nm_ip4_config_add_route (ip4_config, &r, NULL);
+	}
+
 	str = g_hash_table_lookup (options, "dhcp_lease_time");
 	if (str) {
 		address.lifetime = address.preferred = strtoul (str, NULL, 10);
@@ -616,10 +640,10 @@ nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options)
 }
 
 NMIP6Config *
-nm_dhcp_utils_ip6_config_from_options (int ifindex,
+nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx,
+                                       int ifindex,
                                        const char *iface,
                                        GHashTable *options,
-                                       guint32 priority,
                                        gboolean info_only)
 {
 	NMIP6Config *ip6_config = NULL;
@@ -633,7 +657,7 @@ nm_dhcp_utils_ip6_config_from_options (int ifindex,
 	address.plen = 128;
 	address.timestamp = nm_utils_get_monotonic_timestamp_s ();
 
-	ip6_config = nm_ip6_config_new (ifindex);
+	ip6_config = nm_ip6_config_new (multi_idx, ifindex);
 
 	str = g_hash_table_lookup (options, "max_life");
 	if (str) {