summary refs log tree commit diff
path: root/src/dhcp-manager/nm-dhcp-dhclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcp-manager/nm-dhcp-dhclient.c')
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient.c173
1 files changed, 31 insertions, 142 deletions
diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c
index bb5cd2e8..d8781524 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient.c
@@ -45,7 +45,11 @@ G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT)
 #define NM_DHCP_DHCLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_DHCLIENT, NMDHCPDhclientPrivate))
 
 #if defined(TARGET_DEBIAN) || defined(TARGET_SUSE) || defined(TARGET_MANDRIVA)
+#if defined(DHCLIENT_V3)
+#define NM_DHCLIENT_LEASE_DIR			LOCALSTATEDIR "/lib/dhcp3"
+#else
 #define NM_DHCLIENT_LEASE_DIR           LOCALSTATEDIR "/lib/dhcp"
+#endif
 #else
 #define NM_DHCLIENT_LEASE_DIR           LOCALSTATEDIR "/lib/dhclient"
 #endif
@@ -310,6 +314,7 @@ merge_dhclient_config (const char *iface,
                        const char *conf_file,
                        NMSettingIP4Config *s_ip4,
                        guint8 *anycast_addr,
+                       const char *hostname,
                        const char *orig_path,
                        GError **error)
 {
@@ -351,7 +356,7 @@ merge_dhclient_config (const char *iface,
 				ignore = TRUE;
 
 			if (   s_ip4
-			    && nm_setting_ip4_config_get_dhcp_hostname (s_ip4)
+			    && hostname
 			    && !strncmp (*line, DHCP_HOSTNAME_TAG, strlen (DHCP_HOSTNAME_TAG)))
 				ignore = TRUE;
 
@@ -385,7 +390,7 @@ merge_dhclient_config (const char *iface,
 			}
 
 			/* If the client ID is just hex digits and : then don't use quotes,
-			 * becuase dhclient expects either a quoted ASCII string, or a byte
+			 * because dhclient expects either a quoted ASCII string, or a byte
 			 * array formated as hex octets separated by :
 			 */
 			if (is_octets)
@@ -394,9 +399,8 @@ merge_dhclient_config (const char *iface,
 				g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT "\n", tmp);
 		}
 
-		tmp = nm_setting_ip4_config_get_dhcp_hostname (s_ip4);
-		if (tmp)
-			g_string_append_printf (new_contents, DHCP_HOSTNAME_FORMAT "\n", tmp);
+		if (hostname)
+			g_string_append_printf (new_contents, DHCP_HOSTNAME_FORMAT "\n", hostname);
 	}
 
 	if (anycast_addr) {
@@ -425,7 +429,8 @@ merge_dhclient_config (const char *iface,
 static char *
 create_dhclient_config (const char *iface,
                         NMSettingIP4Config *s_ip4,
-                        guint8 *dhcp_anycast_addr)
+                        guint8 *dhcp_anycast_addr,
+                        const char *hostname)
 {
 	char *orig = NULL, *tmp, *conf_file = NULL;
 	GError *error = NULL;
@@ -436,7 +441,11 @@ create_dhclient_config (const char *iface,
 #if defined(TARGET_SUSE)
 	orig = g_strdup (SYSCONFDIR "/dhclient.conf");
 #elif defined(TARGET_DEBIAN) || defined(TARGET_GENTOO)
+#if defined(DHCLIENT_V3)
+	orig = g_strdup (SYSCONFDIR "/dhcp3/dhclient.conf");
+#else
 	orig = g_strdup (SYSCONFDIR "/dhcp/dhclient.conf");
+#endif
 #else
 	orig = g_strdup_printf (SYSCONFDIR "/dhclient-%s.conf", iface);
 #endif
@@ -463,7 +472,7 @@ create_dhclient_config (const char *iface,
 	g_free (tmp);
 
 	error = NULL;
-	success = merge_dhclient_config (iface, conf_file, s_ip4, dhcp_anycast_addr, orig, &error);
+	success = merge_dhclient_config (iface, conf_file, s_ip4, dhcp_anycast_addr, hostname, orig, &error);
 	if (!success) {
 		nm_log_warn (LOGD_DHCP, "(%s): error creating dhclient configuration: %s",
 		             iface, error->message);
@@ -498,7 +507,6 @@ dhclient_start (NMDHCPClient *client,
 	guint log_domain;
 
 	g_return_val_if_fail (priv->pid_file == NULL, -1);
-	g_return_val_if_fail (ip_opt != NULL, -1);
 
 	iface = nm_dhcp_client_get_iface (client);
 	uuid = nm_dhcp_client_get_uuid (client);
@@ -506,6 +514,15 @@ dhclient_start (NMDHCPClient *client,
 
 	log_domain = ipv6 ? LOGD_DHCP6 : LOGD_DHCP4;
 
+#if defined(DHCLIENT_V3)
+	if (ipv6) {
+		nm_log_warn (log_domain, "(%s): ISC dhcp3 does not support IPv6", iface);
+		return -1;
+	}
+#else
+	g_return_val_if_fail (ip_opt != NULL, -1);
+#endif
+
 	priv->pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid",
 	                                  ipv6 ? "6" : "",
 	                                  iface);
@@ -535,10 +552,11 @@ dhclient_start (NMDHCPClient *client,
 
 	g_ptr_array_add (argv, (gpointer) "-d");
 
+#if !defined(DHCLIENT_V3)
 	g_ptr_array_add (argv, (gpointer) ip_opt);
-
 	if (mode_opt)
 		g_ptr_array_add (argv, (gpointer) mode_opt);
+#endif
 
 	g_ptr_array_add (argv, (gpointer) "-sf");	/* Set script file */
 	g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH );
@@ -576,14 +594,15 @@ dhclient_start (NMDHCPClient *client,
 static GPid
 real_ip4_start (NMDHCPClient *client,
                 NMSettingIP4Config *s_ip4,
-                guint8 *dhcp_anycast_addr)
+                guint8 *dhcp_anycast_addr,
+                const char *hostname)
 {
 	NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client);
 	const char *iface;
 
 	iface = nm_dhcp_client_get_iface (client);
 
-	priv->conf_file = create_dhclient_config (iface, s_ip4, dhcp_anycast_addr);
+	priv->conf_file = create_dhclient_config (iface, s_ip4, dhcp_anycast_addr, hostname);
 	if (!priv->conf_file) {
 		nm_log_warn (LOGD_DHCP4, "(%s): error creating dhclient configuration file.", iface);
 		return -1;
@@ -596,6 +615,7 @@ static GPid
 real_ip6_start (NMDHCPClient *client,
                 NMSettingIP6Config *s_ip6,
                 guint8 *dhcp_anycast_addr,
+                const char *hostname,
                 gboolean info_only)
 {
 	return dhclient_start (client, "-6", info_only ? "-S" : "-N");
@@ -615,136 +635,6 @@ real_stop (NMDHCPClient *client)
 		remove (priv->pid_file);
 }
 
-static const char **
-process_rfc3442_route (const char **octets, NMIP4Route **out_route)
-{
-	const char **o = octets;
-	int addr_len = 0, i = 0;
-	long int tmp;
-	NMIP4Route *route;
-	char *next_hop;
-	struct in_addr tmp_addr;
-
-	if (!*o)
-		return o; /* no prefix */
-
-	tmp = strtol (*o, NULL, 10);
-	if (tmp < 0 || tmp > 32)  /* 32 == max IP4 prefix length */
-		return o;
-
-	route = nm_ip4_route_new ();
-	nm_ip4_route_set_prefix (route, (guint32) tmp);
-	o++;
-
-	if (tmp > 0)
-		addr_len = ((tmp - 1) / 8) + 1;
-
-	/* ensure there's at least the address + next hop left */
-	if (g_strv_length ((char **) o) < addr_len + 4)
-		goto error;
-
-	if (tmp) {
-		const char *addr[4] = { "0", "0", "0", "0" };
-		char *str_addr;
-
-		for (i = 0; i < addr_len; i++)
-			addr[i] = *o++;
-
-		str_addr = g_strjoin (".", addr[0], addr[1], addr[2], addr[3], NULL);
-		if (inet_pton (AF_INET, str_addr, &tmp_addr) <= 0) {
-			g_free (str_addr);
-			goto error;
-		}
-		tmp_addr.s_addr &= nm_utils_ip4_prefix_to_netmask ((guint32) tmp);
-		nm_ip4_route_set_dest (route, tmp_addr.s_addr);
-	}
-
-	/* Handle next hop */
-	next_hop = g_strjoin (".", o[0], o[1], o[2], o[3], NULL);
-	if (inet_pton (AF_INET, next_hop, &tmp_addr) <= 0) {
-		g_free (next_hop);
-		goto error;
-	}
-	nm_ip4_route_set_next_hop (route, tmp_addr.s_addr);
-	g_free (next_hop);
-
-	*out_route = route;
-	return o + 4; /* advance to past the next hop */
-
-error:
-	nm_ip4_route_unref (route);
-	return o;
-}
-
-static gboolean
-real_ip4_process_classless_routes (NMDHCPClient *client,
-                                   GHashTable *options,
-                                   NMIP4Config *ip4_config,
-                                   guint32 *gwaddr)
-{
-	const char *str;
-	char **octets, **o;
-	gboolean have_routes = FALSE;
-	NMIP4Route *route = NULL;
-
-	/* dhclient doesn't have actual support for rfc3442 classless static routes
-	 * upstream.  Thus, people resort to defining the option in dhclient.conf
-	 * and using arbitrary formats like so:
-	 *
-	 * option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
-	 *
-	 * See https://lists.isc.org/pipermail/dhcp-users/2008-December/007629.html
-	 */
-
-	str = g_hash_table_lookup (options, "new_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");
-
-	if (!str || !strlen (str))
-		return FALSE;
-
-	o = octets = g_strsplit (str, " ", 0);
-	if (g_strv_length (octets) < 5) {
-		nm_log_warn (LOGD_DHCP4, "ignoring invalid classless static routes '%s'", str);
-		goto out;
-	}
-
-	while (*o) {
-		route = NULL;
-		o = (char **) process_rfc3442_route ((const char **) o, &route);
-		if (!route) {
-			nm_log_warn (LOGD_DHCP4, "ignoring invalid classless static routes");
-			break;
-		}
-
-		have_routes = TRUE;
-		if (nm_ip4_route_get_prefix (route) == 0) {
-			/* gateway passed as classless static route */
-			*gwaddr = nm_ip4_route_get_next_hop (route);
-			nm_ip4_route_unref (route);
-		} else {
-			char addr[INET_ADDRSTRLEN + 1];
-			char nh[INET_ADDRSTRLEN + 1];
-			struct in_addr tmp;
-
-			/* normal route */
-			nm_ip4_config_take_route (ip4_config, route);
-
-			tmp.s_addr = nm_ip4_route_get_dest (route);
-			inet_ntop (AF_INET, &tmp, addr, sizeof (addr));
-			tmp.s_addr = nm_ip4_route_get_next_hop (route);
-			inet_ntop (AF_INET, &tmp, nh, sizeof (nh));
-			nm_log_info (LOGD_DHCP4, "  classless static route %s/%d gw %s",
-			             addr, nm_ip4_route_get_prefix (route), nh);
-		}
-	}
-
-out:
-	g_strfreev (octets);
-	return have_routes;
-}
-
 /***************************************************/
 
 static void
@@ -781,6 +671,5 @@ nm_dhcp_dhclient_class_init (NMDHCPDhclientClass *dhclient_class)
 	client_class->ip4_start = real_ip4_start;
 	client_class->ip6_start = real_ip6_start;
 	client_class->stop = real_stop;
-	client_class->ip4_process_classless_routes = real_ip4_process_classless_routes;
 }