about summary refs log tree commit diff
path: root/debian/patches
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2008-01-24 21:59:21 +0000
committerMichael Biebl <biebl@debian.org>2008-01-24 21:59:21 +0000
commit2d192e860a94462247e73bda6eeece5768fbb0fd (patch)
tree9d6f572e23b3af8e24ac5db8c6c2a7f5923cdba7 /debian/patches
parent2436bc7c43c54d14e8ec514f86e69c2938a79dc8 (diff)
* Rebuild against libnl1. (Closes: #461922)
* debian/patches/24-get_mode_fix_r3122.patch
  - Pull r3122 from upstream stable branch.
  - Fix getting mode of device.
* debian/patches/25-libnl_unique_pid_r3155.patch
  - Pull r3155 from stable branch.
  - Ensures that the pid acquired by libnl is unique.
* debian/patches/26-libnl_1.0-pre8_r3206.patch
  - Pull r3206 from upstream stable branch.
  - Replaces 24-libnl1-pre8_fix.patch, which has been removed.
  - Fixes a FTBFS on architectures using SIGTRAP in G_BREAKPOINT().
    (Closes: #459740)
* debian/patches/13-validate_mac_addr.patch
  - Drop APs with an invalid MAC address. (Closes: #461500)
    Thanks to Sjoerd Simons for the patch.

git-svn-id: svn+ssh://svn.debian.org/svn/pkg-utopia/packages/unstable/networkmanager@2056 ceb527fc-18e6-0310-9fe2-813c157c29e7
Diffstat (limited to 'debian/patches')
-rw-r--r--debian/patches/13-validate_mac_addr.patch33
-rw-r--r--debian/patches/24-get_mode_fix_r3122.patch13
-rw-r--r--debian/patches/24-libnl1-pre8_fix.patch46
-rw-r--r--debian/patches/25-libnl_unique_pid_r3155.patch417
-rw-r--r--debian/patches/26-libnl_1.0-pre8_r3206.patch202
5 files changed, 665 insertions, 46 deletions
diff --git a/debian/patches/13-validate_mac_addr.patch b/debian/patches/13-validate_mac_addr.patch
new file mode 100644
index 00000000..47a81e19
--- /dev/null
+++ b/debian/patches/13-validate_mac_addr.patch
@@ -0,0 +1,33 @@
+--- network-manager-0.6.5.orig/src/nm-device-802-11-wireless.c
++++ network-manager-0.6.5/src/nm-device-802-11-wireless.c
+@@ -3439,6 +3439,20 @@
+ }
+ 
+ static gboolean
++has_valid_ether_addr (NMAccessPoint *ap)
++{
++	struct ether_addr *addr;
++	int i;
++
++	addr = nm_ap_get_address (ap);
++	for (i = 0 ; i < ETH_ALEN; i++)
++		if (addr->ether_addr_octet[i] != 0)
++			return TRUE;
++
++	return FALSE;
++}
++
++static gboolean
+ process_scan_results (NMDevice80211Wireless *dev,
+                       const guint8 *res_buf,
+                       guint32 res_buf_len)
+@@ -3474,7 +3488,8 @@
+ 
+ 				/* Merge previous AP */
+ 				if (ap) {
+-					add_new_ap_to_device_list (dev, ap);
++					if (has_valid_ether_addr (ap))
++						add_new_ap_to_device_list (dev, ap);
+ 					nm_ap_unref (ap);
+ 					ap = NULL;
+ 				}
diff --git a/debian/patches/24-get_mode_fix_r3122.patch b/debian/patches/24-get_mode_fix_r3122.patch
new file mode 100644
index 00000000..f89db8d5
--- /dev/null
+++ b/debian/patches/24-get_mode_fix_r3122.patch
@@ -0,0 +1,13 @@
+Index: src/nm-device-802-11-wireless.c
+===================================================================
+--- src/nm-device-802-11-wireless.c	(Revision 3121)
++++ src/nm-device-802-11-wireless.c	(Revision 3122)
+@@ -1144,7 +1144,7 @@
+ #endif
+ 		if (iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (NM_DEVICE (self)), SIOCGIWMODE, &wrq) == 0)
+ 		{
+-			if ((mode == IW_MODE_ADHOC) || (mode == IW_MODE_INFRA))
++			if ((wrq.u.mode == IW_MODE_ADHOC) || (wrq.u.mode == IW_MODE_INFRA))
+ 				mode = wrq.u.mode;
+ 		}
+ 		else
diff --git a/debian/patches/24-libnl1-pre8_fix.patch b/debian/patches/24-libnl1-pre8_fix.patch
deleted file mode 100644
index 26a54e7b..00000000
--- a/debian/patches/24-libnl1-pre8_fix.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-=== modified file 'src/NetworkManagerSystem.c'
---- src/NetworkManagerSystem.c	2007-12-20 06:06:27 +0000
-+++ src/NetworkManagerSystem.c	2007-12-20 06:57:47 +0000
-@@ -224,16 +224,33 @@
- 
- static struct nl_handle * new_nl_handle (void)
- {
--	struct nl_handle *	nlh = NULL;
--
--	nlh = nl_handle_alloc_nondefault(NL_CB_VERBOSE);
--	nl_handle_set_pid (nlh, (pthread_self() << 16 | getpid()));
--	if (nl_connect(nlh, NETLINK_ROUTE) < 0)
--	{
--		nm_warning ("%s: couldn't connecto to netlink: %s", __func__, nl_geterror());
-+	struct nl_handle * nlh = NULL;
-+	struct nl_cb *cb;
-+
-+	cb = nl_cb_alloc (NL_CB_VERBOSE);
-+	nlh = nl_handle_alloc_cb (cb);
-+
-+	if (!nlh) {
-+		nm_warning ("couldn't allocate netlink handle.");
-+		return NULL;
-+	}
-+
-+	if (nl_connect (nlh, NETLINK_ROUTE) < 0) {
-+        	/* HACK: try one more time. Because the netlink monitor for link state
-+                 * inits before we get here, it grabs the port that matches the PID
-+                 * of the NM process, which also happens to be the PID that libnl uses
-+                 * the first time too.  The real fix is to convert nm-netlink-monitor.c
-+                 * over to use libnl.
-+                 */
- 		nl_handle_destroy (nlh);
- 		nlh = NULL;
--	}
-+
-+		nlh = new_nl_handle ();
-+		if (!nlh) {
-+			nm_error ("couldn't connect to netlink: %s", nl_geterror ());
-+			return NULL;
-+		}
-+        }
- 
- 	return nlh;
- }
-
diff --git a/debian/patches/25-libnl_unique_pid_r3155.patch b/debian/patches/25-libnl_unique_pid_r3155.patch
new file mode 100644
index 00000000..a14aad83
--- /dev/null
+++ b/debian/patches/25-libnl_unique_pid_r3155.patch
@@ -0,0 +1,417 @@
+Index: src/NetworkManagerSystem.c
+===================================================================
+--- src/NetworkManagerSystem.c	(Revision 3154)
++++ src/NetworkManagerSystem.c	(Revision 3155)
+@@ -177,24 +177,6 @@
+ }
+ 
+ 
+-static struct nl_cache * get_link_cache (struct nl_handle *nlh)
+-{
+-	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+-	static struct nl_cache * link_cache = NULL;
+-
+-	g_static_mutex_lock (&mutex);
+-	if (!link_cache)
+-		link_cache = rtnl_link_alloc_cache (nlh);
+-	if (!link_cache)
+-		nm_warning ("ERROR: couldn't allocate rtnl link cache!");
+-	else
+-		nl_cache_update (nlh, link_cache);
+-	g_static_mutex_unlock (&mutex);
+-
+-	return link_cache;
+-}
+-
+-
+ static void iface_to_rtnl_index (const char *iface, struct nl_handle *nlh, struct rtnl_addr *addr)
+ {
+ 	struct nl_cache *	cache = NULL;
+@@ -204,14 +186,17 @@
+ 	g_return_if_fail (nlh != NULL);
+ 	g_return_if_fail (addr != NULL);
+ 
+-	if ((cache = get_link_cache (nlh)))
+-	{
+-		i = rtnl_link_name2i (cache, iface);
+-		if (RTNL_LINK_NOT_FOUND != i)
+-			rtnl_addr_set_ifindex (addr, i);
++	cache = rtnl_link_alloc_cache (nlh);
++	if (!cache) {
++		nm_warning ("%s: couldn't allocate link cache.", __func__);
++		return;
+ 	}
+-	else
+-		nm_warning ("iface_to_rtnl_link() couldn't allocate link cache.");
++
++	nl_cache_update (nlh, cache);
++	i = rtnl_link_name2i (cache, iface);
++	if (RTNL_LINK_NOT_FOUND != i)
++		rtnl_addr_set_ifindex (addr, i);
++	nl_cache_destroy_and_free (cache);
+ }
+ 
+ 
+@@ -223,45 +208,104 @@
+ 	g_return_val_if_fail (iface != NULL, NULL);
+ 	g_return_val_if_fail (nlh != NULL, NULL);
+ 
+-	if ((cache = get_link_cache (nlh)))
+-		have_link = rtnl_link_get_by_name (cache, iface);
+-	else
+-		nm_warning ("iface_to_rtnl_link() couldn't allocate link cache.");
++	cache = rtnl_link_alloc_cache (nlh);
++	if (!cache) {
++		nm_warning ("%s: couldn't allocate link cache.", __func__);
++		return NULL;
++	}
+ 
++	nl_cache_update (nlh, cache);
++	have_link = rtnl_link_get_by_name (cache, iface);
++	nl_cache_destroy_and_free (cache);
++
+ 	return have_link;
+ }
+ 
++static GStaticMutex nlh_mutex = G_STATIC_MUTEX_INIT;
+ 
+-static struct nl_handle * new_nl_handle (void)
++GHashTable *nl_pids = NULL;
++
++static struct
++nl_handle * new_nl_handle (void)
+ {
+-	struct nl_handle *	nlh = NULL;
++	struct nl_handle * nlh = NULL;
++	guint32 nl_pid;
++	int i = 0;
+ 
+-	nlh = nl_handle_alloc_nondefault(NL_CB_VERBOSE);
+-	nl_handle_set_pid (nlh, (pthread_self() << 16 | getpid()));
+-	if (nl_connect(nlh, NETLINK_ROUTE) < 0)
+-	{
+-		nm_warning ("%s: couldn't connecto to netlink: %s", __func__, nl_geterror());
+-		nl_handle_destroy (nlh);
+-		nlh = NULL;
++	g_static_mutex_lock (&nlh_mutex);
++
++	if (nl_pids == NULL) {
++		nl_pids = g_hash_table_new (g_direct_hash, g_direct_equal);
++		g_assert (nl_pids);
++
++		/* Insert the PID used by nm-netlink-monitor.c */
++		g_hash_table_insert (nl_pids, GUINT_TO_POINTER (getpid ()), GUINT_TO_POINTER (1));
+ 	}
+ 
++	while (i++ < 10) {
++		nl_pid = g_random_int ();
++		if (!g_hash_table_lookup (nl_pids, GUINT_TO_POINTER (nl_pid)))
++			break;
++	}
++
++	if (i < 10) {
++		nlh = nl_handle_alloc_nondefault (NL_CB_VERBOSE);
++		nl_handle_set_pid (nlh, nl_pid);
++
++		if (nl_connect (nlh, NETLINK_ROUTE) < 0) {
++			nm_warning ("%s: couldn't connect to netlink: %s", __func__, nl_geterror ());
++			nl_handle_destroy (nlh);
++			nlh = NULL;
++		} else {
++			g_hash_table_insert (nl_pids, GUINT_TO_POINTER (nl_pid), GUINT_TO_POINTER (1));
++		}
++	} else {
++		g_warning ("%s: couldn't find free netlink pid.", __func__);
++	}
++
++	g_static_mutex_unlock (&nlh_mutex);
++
+ 	return nlh;
+ }
+ 
++static void
++destroy_nl_handle (struct nl_handle *nlh)
++{
++	g_return_if_fail (nlh != NULL);
+ 
++	g_static_mutex_lock (&nlh_mutex);
++	g_hash_table_remove (nl_pids, GUINT_TO_POINTER (nl_handle_get_pid (nlh)));
++	g_static_mutex_unlock (&nlh_mutex);
++
++	nl_close (nlh);
++	nl_handle_destroy (nlh);
++
++}
++
++
+ int
+ nm_system_get_rtnl_index_from_iface (const char *iface)
+ {
+ 	struct nl_handle *	nlh = NULL;
+-	struct nl_cache *	cache = NULL;
++	struct nl_cache *	cache;
+ 	int				i = RTNL_LINK_NOT_FOUND;
+ 
+ 	nlh = new_nl_handle ();
+-	if (nlh && (cache = get_link_cache (nlh)))
+-		i = rtnl_link_name2i (cache, iface);
+-	nl_close (nlh);
+-	nl_handle_destroy (nlh);
++	if (!nlh)
++		return RTNL_LINK_NOT_FOUND;
+ 
++	cache = rtnl_link_alloc_cache (nlh);
++	if (!cache) {
++		nm_warning ("%s: couldn't allocate link cache.");
++		goto out;
++	}
++
++	nl_cache_update (nlh, cache);
++	i = rtnl_link_name2i (cache, iface);
++	nl_cache_destroy_and_free (cache);
++
++out:
++	destroy_nl_handle (nlh);
+ 	return i;
+ }
+ 
+@@ -275,18 +319,31 @@
+ 	char *			buf = NULL;
+ 
+ 	nlh = new_nl_handle ();
+-	if (nlh && (cache = get_link_cache (nlh)))
+-	{
+-		buf = g_malloc0 (MAX_IFACE_LEN);
+-		if (!rtnl_link_i2name (cache, rtnl_index, buf, MAX_IFACE_LEN - 1))
+-		{
+-			g_free (buf);
+-			buf = NULL;
+-		}
++	if (!nlh)
++		return NULL;
++
++	cache = rtnl_link_alloc_cache (nlh);
++	if (!cache) {
++		nm_warning ("%s: couldn't allocate link cache.");
++		goto out;
+ 	}
+-	nl_close (nlh);
+-	nl_handle_destroy (nlh);
+ 
++	nl_cache_update (nlh, cache);
++
++	buf = g_malloc0 (MAX_IFACE_LEN);
++	if (!buf)
++		goto destroy_cache;
++
++	if (!rtnl_link_i2name (cache, rtnl_index, buf, MAX_IFACE_LEN - 1)) {
++		g_free (buf);
++		buf = NULL;
++	}
++
++destroy_cache:
++	nl_cache_destroy_and_free (cache);
++
++out:
++	destroy_nl_handle (nlh);
+ 	return buf;
+ }
+ 
+@@ -313,13 +370,15 @@
+ 	config = nm_device_get_ip4_config (dev);
+ 	g_return_val_if_fail (config != NULL, FALSE);
+ 
++	nlh = new_nl_handle ();
++	if (!nlh)
++		return FALSE;
++
+ 	nm_system_delete_default_route ();
+ 	nm_system_device_flush_addresses (dev);
+ 	nm_system_device_flush_routes (dev);
+ 	nm_system_flush_arp_cache ();
+ 
+-	nlh = new_nl_handle ();
+-
+ 	if ((addr = nm_ip4_config_to_rtnl_addr (config, NM_RTNL_ADDR_DEFAULT)))
+ 	{
+ 		iface_to_rtnl_index (nm_device_get_iface (dev), nlh, addr);
+@@ -330,8 +389,7 @@
+ 	else
+ 		nm_warning ("nm_system_device_set_from_ip4_config(): couldn't create rtnl address!\n");
+ 
+-	nl_close (nlh);
+-	nl_handle_destroy (nlh);
++	destroy_nl_handle (nlh);
+ 
+ 	sleep (1);
+ 	nm_system_device_set_ip4_route (dev, nm_ip4_config_get_gateway (config), 0, 0, nm_ip4_config_get_mss (config));
+@@ -424,7 +482,13 @@
+  * Set IPv4 configuration of a VPN device from an NMIP4Config object.
+  *
+  */
+-gboolean nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named, NMDevice *active_device, const char *iface, NMIP4Config *config, char **routes, int num_routes)
++gboolean
++nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named,
++                                          NMDevice *active_device,
++                                          const char *iface,
++                                          NMIP4Config *config,
++                                          char **routes,
++                                          int num_routes)
+ {
+ 	NMIP4Config *		ad_config = NULL;
+ 	struct nl_handle *	nlh = NULL;
+@@ -437,71 +501,73 @@
+ 	if (active_device && (ad_config = nm_device_get_ip4_config (active_device)))
+ 		nm_system_device_set_ip4_route (active_device, nm_ip4_config_get_gateway (ad_config), nm_ip4_config_get_gateway (config), 0xFFFFFFFF, nm_ip4_config_get_mss (config));
+ 
+-	if (iface != NULL && strlen (iface))
+-	{
+-		nm_system_device_set_up_down_with_iface (iface, TRUE);
++	if (!iface || !strlen (iface))
++		goto done;
+ 
+-		nlh = new_nl_handle ();
++	nlh = new_nl_handle ();
++	if (!nlh)
++		goto done;
+ 
+-		if ((addr = nm_ip4_config_to_rtnl_addr (config, NM_RTNL_ADDR_PTP_DEFAULT)))
+-		{
+-			int err = 0;
+-			iface_to_rtnl_index (iface, nlh, addr);
+-			if ((err = rtnl_addr_add (nlh, addr, 0)) < 0)
+-				nm_warning ("nm_system_device_set_from_ip4_config(): error %d returned from rtnl_addr_add():\n%s", err, nl_geterror());
+-			rtnl_addr_put (addr);
+-		}
+-		else
+-			nm_warning ("nm_system_vpn_device_set_from_ip4_config(): couldn't create rtnl address!\n");
++	nm_system_device_set_up_down_with_iface (iface, TRUE);
+ 
+-		/* Set the MTU */
+-		if ((request = rtnl_link_alloc ()))
+-		{
+-			struct rtnl_link * old;
++	if ((addr = nm_ip4_config_to_rtnl_addr (config, NM_RTNL_ADDR_PTP_DEFAULT)))
++	{
++		int err = 0;
++		iface_to_rtnl_index (iface, nlh, addr);
++		if ((err = rtnl_addr_add (nlh, addr, 0)) < 0)
++			nm_warning ("nm_system_device_set_from_ip4_config(): error %d returned from rtnl_addr_add():\n%s", err, nl_geterror());
++		rtnl_addr_put (addr);
++	}
++	else
++		nm_warning ("nm_system_vpn_device_set_from_ip4_config(): couldn't create rtnl address!\n");
+ 
+-			old = iface_to_rtnl_link (iface, nlh);
+-			rtnl_link_set_mtu (request, 1412);
+-			rtnl_link_change (nlh, old, request, 0);
++	/* Set the MTU */
++	if ((request = rtnl_link_alloc ()))
++	{
++		struct rtnl_link * old;
+ 
+-			rtnl_link_put (old);
+-			rtnl_link_put (request);
+-		}
++		old = iface_to_rtnl_link (iface, nlh);
++		rtnl_link_set_mtu (request, 1412);
++		rtnl_link_change (nlh, old, request, 0);
+ 
+-		nl_close (nlh);
+-		nl_handle_destroy (nlh);
++		rtnl_link_put (old);
++		rtnl_link_put (request);
++	}
+ 
+-		sleep (1);
++	destroy_nl_handle (nlh);
+ 
+-		nm_system_device_flush_routes_with_iface (iface);
+-		if (num_routes <= 0)
++	sleep (1);
++
++	nm_system_device_flush_routes_with_iface (iface);
++	if (num_routes <= 0)
++	{
++		nm_system_delete_default_route ();
++		nm_system_device_add_default_route_via_device_with_iface (iface);
++	}
++	else
++	{
++		int i;
++		for (i = 0; i < num_routes; i++)
+ 		{
+-			nm_system_delete_default_route ();
+-			nm_system_device_add_default_route_via_device_with_iface (iface);
+-		}
+-		else
+-		{
+-			int i;
+-			for (i = 0; i < num_routes; i++)
++			char *valid_ip4_route;
++
++			/* Make sure the route is valid, otherwise it's a security risk as the route
++			 * text is simply taken from the user, and passed directly to system().  If
++			 * we did not check the route, think of:
++			 *
++			 *     system("/sbin/ip route add `rm -rf /` dev eth0")
++			 *
++			 * where `rm -rf /` was the route text.  As UID 0 (root), we have to be careful.
++			 */
++			if ((valid_ip4_route = validate_ip4_route (routes[i])))
+ 			{
+-				char *valid_ip4_route;
+-
+-				/* Make sure the route is valid, otherwise it's a security risk as the route
+-				 * text is simply taken from the user, and passed directly to system().  If
+-				 * we did not check the route, think of:
+-				 *
+-				 *     system("/sbin/ip route add `rm -rf /` dev eth0")
+-				 *
+-				 * where `rm -rf /` was the route text.  As UID 0 (root), we have to be careful.
+-				 */
+-				if ((valid_ip4_route = validate_ip4_route (routes[i])))
+-				{
+-					nm_system_device_add_route_via_device_with_iface (iface, valid_ip4_route);
+-					g_free (valid_ip4_route);
+-				}
++				nm_system_device_add_route_via_device_with_iface (iface, valid_ip4_route);
++				g_free (valid_ip4_route);
+ 			}
+ 		}
+ 	}
+ 
++done:
+ 	nm_named_manager_add_ip4_config (named, config);
+ 
+ 	return TRUE;
+@@ -548,7 +614,8 @@
+ 
+ 	g_return_val_if_fail (iface != NULL, FALSE);
+ 
+-	if (!(nlh = new_nl_handle ()))
++	nlh = new_nl_handle ();
++	if (!nlh)
+ 		return FALSE;
+ 
+ 	if (!(request = rtnl_link_alloc ()))
+@@ -569,9 +636,7 @@
+ 	success = TRUE;
+ 
+ out:
+-	nl_close (nlh);
+-	nl_handle_destroy (nlh);
+-
++	destroy_nl_handle (nlh);
+ 	return success;
+ }
+ 
+@@ -614,6 +679,6 @@
+ out_request:
+ 	rtnl_link_put (request);
+ out_nl_close:
+-	nl_close (nlh);
+-	nl_handle_destroy (nlh);
++	destroy_nl_handle (nlh);
+ }
++
diff --git a/debian/patches/26-libnl_1.0-pre8_r3206.patch b/debian/patches/26-libnl_1.0-pre8_r3206.patch
new file mode 100644
index 00000000..6f96215d
--- /dev/null
+++ b/debian/patches/26-libnl_1.0-pre8_r3206.patch
@@ -0,0 +1,202 @@
+Index: src/nm-netlink-monitor.c
+===================================================================
+--- src/nm-netlink-monitor.c	(Revision 3205)
++++ src/nm-netlink-monitor.c	(Revision 3206)
+@@ -174,7 +174,7 @@
+ 	}
+ 
+ 	monitor_address.nl_family = AF_NETLINK;
+-	monitor_address.nl_pid = getpid ();
++	monitor_address.nl_pid = UINT_MAX;
+ 	monitor_address.nl_groups = RTMGRP_LINK;
+ 
+ 	if (bind (fd, 
+@@ -365,7 +365,7 @@
+ 	packet.header.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtgenmsg));
+ 	packet.header.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ 	packet.header.nlmsg_type = RTM_GETLINK;
+-	packet.header.nlmsg_pid = getpid ();
++	packet.header.nlmsg_pid = UINT_MAX;
+ 	/* Might be good to generate a unique sequence number and track
+ 	   the response */
+ 	packet.header.nlmsg_seq = sequence_number << 16;
+Index: src/NetworkManagerSystem.c
+===================================================================
+--- src/NetworkManagerSystem.c	(Revision 3205)
++++ src/NetworkManagerSystem.c	(Revision 3206)
+@@ -196,7 +196,7 @@
+ 	i = rtnl_link_name2i (cache, iface);
+ 	if (RTNL_LINK_NOT_FOUND != i)
+ 		rtnl_addr_set_ifindex (addr, i);
+-	nl_cache_destroy_and_free (cache);
++	nl_cache_free (cache);
+ }
+ 
+ 
+@@ -216,55 +216,42 @@
+ 
+ 	nl_cache_update (nlh, cache);
+ 	have_link = rtnl_link_get_by_name (cache, iface);
+-	nl_cache_destroy_and_free (cache);
++	nl_cache_free (cache);
+ 
+ 	return have_link;
+ }
+ 
+-static GStaticMutex nlh_mutex = G_STATIC_MUTEX_INIT;
+-
+-GHashTable *nl_pids = NULL;
+-
+ static struct
+-nl_handle * new_nl_handle (void)
++nl_handle *new_nl_handle (gboolean recursive)
+ {
+-	struct nl_handle * nlh = NULL;
+-	guint32 nl_pid;
+-	int i = 0;
++	struct nl_handle *nlh = NULL;
++	struct nl_cb *cb;
+ 
+-	g_static_mutex_lock (&nlh_mutex);
+-
+-	if (nl_pids == NULL) {
+-		nl_pids = g_hash_table_new (g_direct_hash, g_direct_equal);
+-		g_assert (nl_pids);
+-
+-		/* Insert the PID used by nm-netlink-monitor.c */
+-		g_hash_table_insert (nl_pids, GUINT_TO_POINTER (getpid ()), GUINT_TO_POINTER (1));
++	cb = nl_cb_alloc (NL_CB_VERBOSE);
++	nlh = nl_handle_alloc_cb (cb);
++	if (!nlh) {
++		nm_warning ("%s: couldn't allocate netlink handle: %s", __func__, nl_geterror ());
++		return NULL;
+ 	}
+ 
+-	while (i++ < 10) {
+-		nl_pid = g_random_int ();
+-		if (!g_hash_table_lookup (nl_pids, GUINT_TO_POINTER (nl_pid)))
+-			break;
+-	}
++	if (nl_connect (nlh, NETLINK_ROUTE) < 0) {
++		/* HACK: try one more time. Because the netlink monitor for link state
++		 * inits before we get here, it grabs the port that matches the PID
++		 * of the NM process, which also happens to be the PID that libnl uses
++		 * the first time too.  The real fix is to convert nm-netlink-monitor.c
++		 * over to use libnl.
++		 */
++		nl_handle_destroy (nlh);
++		if (recursive)
++			return NULL;
+ 
+-	if (i < 10) {
+-		nlh = nl_handle_alloc_nondefault (NL_CB_VERBOSE);
+-		nl_handle_set_pid (nlh, nl_pid);
+-
+-		if (nl_connect (nlh, NETLINK_ROUTE) < 0) {
++		nlh = new_nl_handle (TRUE);
++		if (!nlh) {
+ 			nm_warning ("%s: couldn't connect to netlink: %s", __func__, nl_geterror ());
+-			nl_handle_destroy (nlh);
+-			nlh = NULL;
+-		} else {
+-			g_hash_table_insert (nl_pids, GUINT_TO_POINTER (nl_pid), GUINT_TO_POINTER (1));
++			return NULL;
+ 		}
+-	} else {
+-		g_warning ("%s: couldn't find free netlink pid.", __func__);
+ 	}
+ 
+-	g_static_mutex_unlock (&nlh_mutex);
+-
+ 	return nlh;
+ }
+ 
+@@ -273,16 +260,10 @@
+ {
+ 	g_return_if_fail (nlh != NULL);
+ 
+-	g_static_mutex_lock (&nlh_mutex);
+-	g_hash_table_remove (nl_pids, GUINT_TO_POINTER (nl_handle_get_pid (nlh)));
+-	g_static_mutex_unlock (&nlh_mutex);
+-
+ 	nl_close (nlh);
+ 	nl_handle_destroy (nlh);
+-
+ }
+ 
+-
+ int
+ nm_system_get_rtnl_index_from_iface (const char *iface)
+ {
+@@ -290,7 +271,7 @@
+ 	struct nl_cache *	cache;
+ 	int				i = RTNL_LINK_NOT_FOUND;
+ 
+-	nlh = new_nl_handle ();
++	nlh = new_nl_handle (FALSE);
+ 	if (!nlh)
+ 		return RTNL_LINK_NOT_FOUND;
+ 
+@@ -302,7 +283,7 @@
+ 
+ 	nl_cache_update (nlh, cache);
+ 	i = rtnl_link_name2i (cache, iface);
+-	nl_cache_destroy_and_free (cache);
++	nl_cache_free (cache);
+ 
+ out:
+ 	destroy_nl_handle (nlh);
+@@ -318,7 +299,7 @@
+ 	struct nl_cache *	cache = NULL;
+ 	char *			buf = NULL;
+ 
+-	nlh = new_nl_handle ();
++	nlh = new_nl_handle (FALSE);
+ 	if (!nlh)
+ 		return NULL;
+ 
+@@ -340,7 +321,7 @@
+ 	}
+ 
+ destroy_cache:
+-	nl_cache_destroy_and_free (cache);
++	nl_cache_free (cache);
+ 
+ out:
+ 	destroy_nl_handle (nlh);
+@@ -370,7 +351,7 @@
+ 	config = nm_device_get_ip4_config (dev);
+ 	g_return_val_if_fail (config != NULL, FALSE);
+ 
+-	nlh = new_nl_handle ();
++	nlh = new_nl_handle (FALSE);
+ 	if (!nlh)
+ 		return FALSE;
+ 
+@@ -504,7 +485,7 @@
+ 	if (!iface || !strlen (iface))
+ 		goto done;
+ 
+-	nlh = new_nl_handle ();
++	nlh = new_nl_handle (FALSE);
+ 	if (!nlh)
+ 		goto done;
+ 
+@@ -614,7 +595,7 @@
+ 
+ 	g_return_val_if_fail (iface != NULL, FALSE);
+ 
+-	nlh = new_nl_handle ();
++	nlh = new_nl_handle (FALSE);
+ 	if (!nlh)
+ 		return FALSE;
+ 
+@@ -658,7 +639,7 @@
+ 	if (!mtu)
+ 		return;
+ 
+-	nlh = new_nl_handle ();
++	nlh = new_nl_handle (FALSE);
+ 	if (!nlh)
+ 		return;
+