[NetworkManager/f20] core: Fix PtP/peer address support, for OpenVPN

Dan Winship danw at fedoraproject.org
Mon Dec 2 20:02:30 UTC 2013


commit 7212c621a9ba9a1f55357fdd52c99d6c80e0bec1
Author: Dan Winship <danw at gnome.org>
Date:   Mon Dec 2 15:02:03 2013 -0500

    core: Fix PtP/peer address support, for OpenVPN

 NetworkManager.spec         |    9 +-
 rh1018317-openvpn-ptp.patch |  857 +++++++++++++++++++++++++++++++++++++++++++
 rh1018317-prereq.patch      |  321 ++++++++++++++++
 3 files changed, 1186 insertions(+), 1 deletions(-)
---
diff --git a/NetworkManager.spec b/NetworkManager.spec
index 0484c57..360cf15 100644
--- a/NetworkManager.spec
+++ b/NetworkManager.spec
@@ -19,7 +19,7 @@ Name: NetworkManager
 Summary: Network connection manager and user applications
 Epoch: 1
 Version: 0.9.9.0
-Release: 19%{snapshot}%{?dist}
+Release: 20%{snapshot}%{?dist}
 Group: System Environment/Base
 License: GPLv2+
 URL: http://www.gnome.org/projects/NetworkManager/
@@ -43,6 +43,8 @@ Patch13: rh1025371-wifi-potential-crash.patch
 Patch14: rh1029053-fix-crash-device-no-MAC.patch
 Patch15: rh1030403-editor-crash-remote-connection.patch
 Patch16: fix-ifcfg-rh-con-update.patch
+Patch17: rh1018317-prereq.patch
+Patch18: rh1018317-openvpn-ptp.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -182,6 +184,8 @@ deployments.
 %patch14 -p1 -b .device-no-MAC
 %patch15 -p1 -b .libnm-glib-editor
 %patch16 -p1 -b .ifcfg-rh-update
+%patch17 -p1 -b .ipv6-flags
+%patch18 -p1 -b .openvpn-ptp
 
 %build
 
@@ -380,6 +384,9 @@ fi
 %config %{_sysconfdir}/%{name}/conf.d/00-server.conf
 
 %changelog
+* Mon Dec  2 2013 Dan Winship <danw at redhat.com> - 0.9.9.0-20.git20131003
+- core: Fix PtP/peer address support, for OpenVPN (rh #1018317)
+
 * Wed Nov 20 2013 Jiří Klimeš <jklimes at redhat.com> - 0.9.9.0-19.git20131003
 - dispatcher: fix crash on exit while logging from signal handler (rh #1017884)
 - core: workaround crash when connecting to wifi (rh #1025371)
diff --git a/rh1018317-openvpn-ptp.patch b/rh1018317-openvpn-ptp.patch
new file mode 100644
index 0000000..09c9a6b
--- /dev/null
+++ b/rh1018317-openvpn-ptp.patch
@@ -0,0 +1,857 @@
+From fec50bd5fad633e57bfd6f9ee480e6192504ca5f Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw at gnome.org>
+Date: Mon, 2 Dec 2013 10:20:26 -0500
+Subject: [PATCH] platform/core: add back support for PtP/peer addresses (rh
+ #1018317)
+
+In the migration to NMPlatform, support for ptp/peer addresses was
+accidentally dropped. This broke OpenVPN configurations using 'p2p'
+topology, which send a different peer address than the local address
+for tunX, plus the server may also push routes that use the peer
+address as the next hop. NetworkManager was unable to add these
+routes, because the kernel had no idea how to talk to the peer,
+because the peer's address was not assigned to any interface or
+reachable over any routes.
+
+Partly based on a patch from Dan Williams.
+---
+ src/nm-ip4-config.c                 | 44 +---------------------------
+ src/nm-ip4-config.h                 |  4 ---
+ src/nm-ip6-config.c                 | 49 -------------------------------
+ src/nm-ip6-config.h                 |  4 ---
+ src/platform/nm-fake-platform.c     | 10 +++++--
+ src/platform/nm-linux-platform.c    | 58 ++++++++++++++++++++++++++++++++-----
+ src/platform/nm-platform.c          | 26 +++++++++++++----
+ src/platform/nm-platform.h          | 14 ++++++---
+ src/platform/tests/platform.c       |  4 +--
+ src/platform/tests/test-address.c   | 12 ++++----
+ src/platform/tests/test-cleanup.c   |  4 +--
+ src/ppp-manager/nm-ppp-manager.c    |  2 +-
+ src/tests/test-dhcp-options.c       |  5 ++--
+ src/tests/test-ip4-config.c         | 12 ++++----
+ src/tests/test-ip6-config.c         | 13 ++++-----
+ src/vpn-manager/nm-vpn-connection.c | 10 +++----
+ 16 files changed, 118 insertions(+), 153 deletions(-)
+
+diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
+index 7aff888..640a1e1 100644
+--- a/src/nm-ip4-config.c
++++ b/src/nm-ip4-config.c
+@@ -47,7 +47,6 @@ typedef struct {
+ 	GPtrArray *domains;
+ 	GPtrArray *searches;
+ 	guint32 mss;
+-	guint32 ptp_address;
+ 	GArray *nis;
+ 	char *nis_domain;
+ 	GArray *wins;
+@@ -454,10 +453,6 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
+ 	for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++)
+ 		nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i));
+ 
+-	/* ptp address; only replace if src doesn't have one */
+-	if (!nm_ip4_config_get_ptp_address (dst))
+-		nm_ip4_config_set_ptp_address (dst, nm_ip4_config_get_ptp_address (src));
+-
+ 	/* nameservers */
+ 	for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++)
+ 		nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
+@@ -527,10 +522,6 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
+ 		}
+ 	}
+ 
+-	/* ptp address */
+-	if (nm_ip4_config_get_ptp_address (src) == nm_ip4_config_get_ptp_address (dst))
+-		nm_ip4_config_set_ptp_address (dst, 0);
+-
+ 	/* nameservers */
+ 	for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
+ 		guint32 src_ns = nm_ip4_config_get_nameserver (src, i);
+@@ -788,12 +779,6 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
+ 		has_minor_changes = TRUE;
+ 	}
+ 
+-	/* ptp address */
+-	if (src_priv->ptp_address != dst_priv->ptp_address) {
+-		dst_priv->ptp_address = src_priv->ptp_address;
+-		has_relevant_changes = TRUE;
+-	}
+-
+ 	/* nis */
+ 	num = nm_ip4_config_get_num_nis_servers (src);
+ 	are_equal = num == nm_ip4_config_get_num_nis_servers (dst);
+@@ -873,11 +858,6 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail)
+ 		}
+ 	}
+ 
+-	/* ptp address */
+-	tmp = nm_ip4_config_get_ptp_address (config);
+-	if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf)))
+-		g_message ("    ptp: %s", buf);
+-
+ 	/* default gateway */
+ 	tmp = nm_ip4_config_get_gateway (config);
+ 	if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf)))
+@@ -1314,24 +1294,6 @@ nm_ip4_config_get_mss (const NMIP4Config *config)
+ /******************************************************************/
+ 
+ void
+-nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr)
+-{
+-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+-
+-	priv->ptp_address = ptp_addr;
+-}
+-
+-guint32
+-nm_ip4_config_get_ptp_address (const NMIP4Config *config)
+-{
+-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+-
+-	return priv->ptp_address;
+-}
+-
+-/******************************************************************/
+-
+-void
+ nm_ip4_config_reset_nis_servers (NMIP4Config *config)
+ {
+ 	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+@@ -1480,7 +1442,7 @@ hash_u32 (GChecksum *sum, guint32 n)
+ void
+ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only)
+ {
+-	guint32 i, n;
++	guint32 i;
+ 	const char *s;
+ 
+ 	g_return_if_fail (config);
+@@ -1504,10 +1466,6 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only
+ 			hash_u32 (sum, route->metric);
+ 		}
+ 
+-		n = nm_ip4_config_get_ptp_address (config);
+-		if (n)
+-			hash_u32 (sum, n);
+-
+ 		for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++)
+ 			hash_u32 (sum, nm_ip4_config_get_nis_server (config, i));
+ 
+diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
+index 5b76fb4..d57cd52 100644
+--- a/src/nm-ip4-config.h
++++ b/src/nm-ip4-config.h
+@@ -117,10 +117,6 @@ const char * nm_ip4_config_get_search (const NMIP4Config *config, guint i);
+ void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss);
+ guint32 nm_ip4_config_get_mss (const NMIP4Config *config);
+ 
+-/* PTP */
+-void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr);
+-guint32 nm_ip4_config_get_ptp_address (const NMIP4Config *config);
+-
+ /* NIS */
+ void nm_ip4_config_reset_nis_servers (NMIP4Config *config);
+ void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis);
+diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
+index 65cbd0b..8eb79f2 100644
+--- a/src/nm-ip6-config.c
++++ b/src/nm-ip6-config.c
+@@ -47,7 +47,6 @@ typedef struct {
+ 	GPtrArray *domains;
+ 	GPtrArray *searches;
+ 	guint32 mss;
+-	struct in6_addr ptp_address;
+ } NMIP6ConfigPrivate;
+ 
+ 
+@@ -457,10 +456,6 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src)
+ 	for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++)
+ 		nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i));
+ 
+-	/* ptp address; only replace if src doesn't have one */
+-	if (!nm_ip6_config_get_ptp_address (dst))
+-		nm_ip6_config_set_ptp_address (dst, nm_ip6_config_get_ptp_address (src));
+-
+ 	/* nameservers */
+ 	for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
+ 		nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
+@@ -535,12 +530,6 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
+ 		}
+ 	}
+ 
+-	/* ptp address */
+-	src_tmp = nm_ip6_config_get_ptp_address (src);
+-	dst_tmp = nm_ip6_config_get_ptp_address (dst);
+-	if (src_tmp && dst_tmp && IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp))
+-		nm_ip6_config_set_ptp_address (dst, NULL);
+-
+ 	/* nameservers */
+ 	for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) {
+ 		const struct in6_addr *src_ns = nm_ip6_config_get_nameserver (src, i);
+@@ -769,12 +758,6 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
+ 		has_minor_changes = TRUE;
+ 	}
+ 
+-	/* ptp address */
+-	if (!IN6_ARE_ADDR_EQUAL (&src_priv->ptp_address, &dst_priv->ptp_address)) {
+-		nm_ip6_config_set_ptp_address (dst, &src_priv->ptp_address);
+-		has_relevant_changes = TRUE;
+-	}
+-
+ 	/* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
+ 	 * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
+ 	g_assert (config_equal == !has_relevant_changes);
+@@ -1219,28 +1197,6 @@ nm_ip6_config_get_mss (const NMIP6Config *config)
+ 
+ /******************************************************************/
+ 
+-void
+-nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_address)
+-{
+-	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+-
+-	if (ptp_address)
+-		priv->ptp_address = *ptp_address;
+-	else
+-		memset (&priv->ptp_address, 0, sizeof (priv->ptp_address));
+-
+-}
+-
+-const struct in6_addr *
+-nm_ip6_config_get_ptp_address (const NMIP6Config *config)
+-{
+-	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+-
+-	return IN6_IS_ADDR_UNSPECIFIED (&priv->ptp_address) ? NULL : &priv->ptp_address;
+-}
+-
+-/******************************************************************/
+-
+ static inline void
+ hash_u32 (GChecksum *sum, guint32 n)
+ {
+@@ -1260,7 +1216,6 @@ void
+ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only)
+ {
+ 	guint32 i;
+-	const struct in6_addr *in6a;
+ 	const char *s;
+ 
+ 	g_return_if_fail (config);
+@@ -1284,10 +1239,6 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only
+ 			hash_in6addr (sum, &route->gateway);
+ 			hash_u32 (sum, route->metric);
+ 		}
+-
+-		in6a = nm_ip6_config_get_ptp_address (config);
+-		if (in6a)
+-			hash_in6addr (sum, in6a);
+ 	}
+ 
+ 	for (i = 0; i < nm_ip6_config_get_num_nameservers (config); i++)
+diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
+index aecdab2..eb93d07 100644
+--- a/src/nm-ip6-config.h
++++ b/src/nm-ip6-config.h
+@@ -116,10 +116,6 @@ const char * nm_ip6_config_get_search (const NMIP6Config *config, guint i);
+ void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss);
+ guint32 nm_ip6_config_get_mss (const NMIP6Config *config);
+ 
+-/* PTP */
+-void nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_addr);
+-const struct in6_addr *nm_ip6_config_get_ptp_address (const NMIP6Config *config);
+-
+ void nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only);
+ gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b);
+ 
+diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
+index df5d5b8..dcbf932 100644
+--- a/src/platform/nm-fake-platform.c
++++ b/src/platform/nm-fake-platform.c
+@@ -739,7 +739,9 @@ get_time (void)
+ }
+ 
+ static gboolean
+-ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred)
++ip4_address_add (NMPlatform *platform, int ifindex,
++                 in_addr_t addr, in_addr_t peer_addr,
++                 int plen, guint32 lifetime, guint32 preferred)
+ {
+ 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
+ 	NMPlatformIP4Address address;
+@@ -748,6 +750,7 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, gu
+ 	memset (&address, 0, sizeof (address));
+ 	address.ifindex = ifindex;
+ 	address.address = addr;
++	address.peer_address = peer_addr;
+ 	address.plen = plen;
+ 	address.timestamp = get_time ();
+ 	address.lifetime = lifetime;
+@@ -775,7 +778,9 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, gu
+ }
+ 
+ static gboolean
+-ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred, guint flags)
++ip6_address_add (NMPlatform *platform, int ifindex,
++                 struct in6_addr addr, struct in6_addr peer_addr,
++                 int plen, guint32 lifetime, guint32 preferred, guint flags)
+ {
+ 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
+ 	NMPlatformIP6Address address;
+@@ -784,6 +789,7 @@ ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int pl
+ 	memset (&address, 0, sizeof (address));
+ 	address.ifindex = ifindex;
+ 	address.address = addr;
++	address.peer_address = peer_addr;
+ 	address.plen = plen;
+ 	address.timestamp = get_time ();
+ 	address.lifetime = lifetime;
+diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
+index d13abbe..50b027a 100644
+--- a/src/platform/nm-linux-platform.c
++++ b/src/platform/nm-linux-platform.c
+@@ -764,6 +764,7 @@ static void
+ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
+ {
+ 	struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr);
++	struct nl_addr *nlpeer = rtnl_addr_get_peer (rtnladdr);
+ 
+ 	g_assert (nladdr);
+ 
+@@ -776,12 +777,17 @@ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
+ 	address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
+ 	g_assert (nl_addr_get_len (nladdr) == sizeof (address->address));
+ 	memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address));
++	if (nlpeer) {
++		g_assert (nl_addr_get_len (nlpeer) == sizeof (address->peer_address));
++		memcpy (&address->peer_address, nl_addr_get_binary_addr (nlpeer), sizeof (address->peer_address));
++	}
+ }
+ 
+ static void
+ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
+ {
+ 	struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr);
++	struct nl_addr *nlpeer = rtnl_addr_get_peer (rtnladdr);
+ 
+ 	memset (address, 0, sizeof (*address));
+ 
+@@ -793,6 +799,10 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
+ 	address->flags = rtnl_addr_get_flags (rtnladdr);
+ 	g_assert (nl_addr_get_len (nladdr) == sizeof (address->address));
+ 	memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address));
++	if (nlpeer) {
++		g_assert (nl_addr_get_len (nlpeer) == sizeof (address->peer_address));
++		memcpy (&address->peer_address, nl_addr_get_binary_addr (nlpeer), sizeof (address->peer_address));
++	}
+ }
+ 
+ static gboolean
+@@ -2208,7 +2218,14 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
+ }
+ 
+ static struct nl_object *
+-build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 lifetime, guint32 preferred, guint flags)
++build_rtnl_addr (int family,
++                 int ifindex,
++                 gconstpointer addr,
++                 gconstpointer peer_addr,
++                 int plen,
++                 guint32 lifetime,
++                 guint32 preferred,
++                 guint flags)
+ {
+ 	struct rtnl_addr *rtnladdr = rtnl_addr_alloc ();
+ 	int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+@@ -2220,6 +2237,14 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32
+ 	rtnl_addr_set_ifindex (rtnladdr, ifindex);
+ 	nle = rtnl_addr_set_local (rtnladdr, nladdr);
+ 	g_assert (!nle);
++
++	if (peer_addr) {
++		auto_nl_addr struct nl_addr *nlpeer = nl_addr_build (family, peer_addr, addrlen);
++
++		nle = rtnl_addr_set_peer (rtnladdr, nlpeer);
++		g_assert (!nle);
++	}
++
+ 	rtnl_addr_set_prefixlen (rtnladdr, plen);
+ 	if (lifetime) {
+ 		rtnl_addr_set_valid_lifetime (rtnladdr, lifetime);
+@@ -2232,33 +2257,50 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32
+ }
+ 
+ static gboolean
+-ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred)
++ip4_address_add (NMPlatform *platform,
++                 int ifindex,
++                 in_addr_t addr,
++                 in_addr_t peer_addr,
++                 int plen,
++                 guint32 lifetime,
++                 guint32 preferred)
+ {
+-	return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, lifetime, preferred, 0));
++	return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr,
++	                                              peer_addr ? &peer_addr : NULL,
++	                                              plen, lifetime, preferred, 0));
+ }
+ 
+ static gboolean
+-ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred, guint flags)
++ip6_address_add (NMPlatform *platform,
++                 int ifindex,
++                 struct in6_addr addr,
++                 struct in6_addr peer_addr,
++                 int plen,
++                 guint32 lifetime,
++                 guint32 preferred,
++                 guint flags)
+ {
+-	return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, lifetime, preferred, flags));
++	return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr,
++	                                              memcmp (&peer_addr, &in6addr_any, sizeof (struct in6_addr)) == 0 ? NULL : &peer_addr,
++	                                              plen, lifetime, preferred, flags));
+ }
+ 
+ static gboolean
+ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
+ {
+-	return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, 0, 0, 0));
++	return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, NULL, plen, 0, 0, 0));
+ }
+ 
+ static gboolean
+ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
+ {
+-	return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, 0, 0, 0));
++	return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, NULL, plen, 0, 0, 0));
+ }
+ 
+ static gboolean
+ ip_address_exists (NMPlatform *platform, int family, int ifindex, gconstpointer addr, int plen)
+ {
+-	auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, plen, 0, 0, 0);
++	auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, NULL, plen, 0, 0, 0);
+ 	auto_nl_object struct nl_object *cached_object = nl_cache_search (choose_cache (platform, object), object);
+ 
+ 	return !!cached_object;
+diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
+index 3f7f054..4e9c8fc 100644
+--- a/src/platform/nm-platform.c
++++ b/src/platform/nm-platform.c
+@@ -1165,7 +1165,12 @@ nm_platform_ip6_address_get_all (int ifindex)
+ }
+ 
+ gboolean
+-nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, guint32 lifetime, guint32 preferred)
++nm_platform_ip4_address_add (int ifindex,
++                             in_addr_t address,
++                             in_addr_t peer_address,
++                             int plen,
++                             guint32 lifetime,
++                             guint32 preferred)
+ {
+ 	reset_error ();
+ 
+@@ -1175,11 +1180,17 @@ nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, guint32 l
+ 	g_return_val_if_fail (klass->ip4_address_add, FALSE);
+ 
+ 	debug ("address: adding or updating IPv4 address");
+-	return klass->ip4_address_add (platform, ifindex, address, plen, lifetime, preferred);
++	return klass->ip4_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred);
+ }
+ 
+ gboolean
+-nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, guint32 lifetime, guint32 preferred, guint flags)
++nm_platform_ip6_address_add (int ifindex,
++                             struct in6_addr address,
++                             struct in6_addr peer_address,
++                             int plen,
++                             guint32 lifetime,
++                             guint32 preferred,
++                             guint flags)
+ {
+ 	reset_error ();
+ 
+@@ -1189,7 +1200,7 @@ nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, gui
+ 	g_return_val_if_fail (klass->ip6_address_add, FALSE);
+ 
+ 	debug ("address: adding or updating IPv6 address");
+-	return klass->ip6_address_add (platform, ifindex, address, plen, lifetime, preferred, flags);
++	return klass->ip6_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred, flags);
+ }
+ 
+ gboolean
+@@ -1350,7 +1361,7 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
+ 		} else
+ 			lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
+ 
+-		if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->plen, lifetime, preferred))
++		if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred))
+ 			return FALSE;
+ 	}
+ 
+@@ -1407,7 +1418,8 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
+ 		} else
+ 			lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
+ 
+-		if (!nm_platform_ip6_address_add (ifindex, known_address->address, known_address->plen,
++		if (!nm_platform_ip6_address_add (ifindex, known_address->address,
++		                                  known_address->peer_address, known_address->plen,
+ 		                                  lifetime, preferred, known_address->flags))
+ 			return FALSE;
+ 	}
+@@ -1843,6 +1855,7 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A
+ {
+ 	_CMP_POINTER (a, b);
+ 	_CMP_FIELD_MEMCMP (a, b, address);
++	_CMP_FIELD_MEMCMP (a, b, peer_address);
+ 	_CMP_FIELD (a, b, ifindex);
+ 	_CMP_FIELD (a, b, plen);
+ 	_CMP_FIELD (a, b, timestamp);
+@@ -1857,6 +1870,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
+ 	_CMP_POINTER (a, b);
+ 	_CMP_FIELD (a, b, ifindex);
+ 	_CMP_FIELD_MEMCMP (a, b, address);
++	_CMP_FIELD_MEMCMP (a, b, peer_address);
+ 	_CMP_FIELD (a, b, plen);
+ 	_CMP_FIELD (a, b, timestamp);
+ 	_CMP_FIELD (a, b, lifetime);
+diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
+index ff338fc..b742c39 100644
+--- a/src/platform/nm-platform.h
++++ b/src/platform/nm-platform.h
+@@ -122,6 +122,7 @@ typedef struct {
+ typedef struct {
+ 	int ifindex;
+ 	in_addr_t address;
++	in_addr_t peer_address;  /* PTP peer address */
+ 	int plen;
+ 	guint32 timestamp;
+ 	guint32 lifetime;
+@@ -131,6 +132,7 @@ typedef struct {
+ typedef struct {
+ 	int ifindex;
+ 	struct in6_addr address;
++	struct in6_addr peer_address;
+ 	int plen;
+ 	guint32 timestamp;
+ 	guint32 lifetime;
+@@ -280,9 +282,11 @@ typedef struct {
+ 
+ 	GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex);
+ 	GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex);
+-	gboolean (*ip4_address_add) (NMPlatform *, int ifindex, in_addr_t address, int plen,
+-			guint32 lifetime, guint32 preferred_lft);
+-	gboolean (*ip6_address_add) (NMPlatform *, int ifindex, struct in6_addr address, int plen,
++	gboolean (*ip4_address_add) (NMPlatform *, int ifindex,
++	                             in_addr_t address, in_addr_t peer_address, int plen,
++	                             guint32 lifetime, guint32 preferred_lft);
++	gboolean (*ip6_address_add) (NMPlatform *, int ifindex,
++	                             struct in6_addr address, struct in6_addr peer_address, int plen,
+ 	                             guint32 lifetime, guint32 preferred_lft, guint flags);
+ 	gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen);
+ 	gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
+@@ -402,9 +406,11 @@ gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *p
+ 
+ GArray *nm_platform_ip4_address_get_all (int ifindex);
+ GArray *nm_platform_ip6_address_get_all (int ifindex);
+-gboolean nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen,
+-		guint32 lifetime, guint32 preferred_lft);
+-gboolean nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen,
++gboolean nm_platform_ip4_address_add (int ifindex,
++                                      in_addr_t address, in_addr_t peer_address, int plen,
++                                      guint32 lifetime, guint32 preferred_lft);
++gboolean nm_platform_ip6_address_add (int ifindex,
++                                      struct in6_addr address, struct in6_addr peer_address, int plen,
+                                       guint32 lifetime, guint32 preferred_lft, guint flags);
+ gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen);
+ gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen);
+diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c
+index c0b2c02..7ca2cb5 100644
+--- a/src/platform/tests/platform.c
++++ b/src/platform/tests/platform.c
+@@ -523,7 +523,7 @@ do_ip4_address_add (char **argv)
+ 		guint32 lifetime = strtol (*argv++, NULL, 10);
+ 		guint32 preferred = strtol (*argv++, NULL, 10);
+ 
+-		gboolean value = nm_platform_ip4_address_add (ifindex, address, plen, lifetime, preferred);
++		gboolean value = nm_platform_ip4_address_add (ifindex, address, 0, plen, lifetime, preferred);
+ 		return value;
+ 	} else
+ 		return FALSE;
+@@ -541,7 +541,7 @@ do_ip6_address_add (char **argv)
+ 		guint32 preferred = strtol (*argv++, NULL, 10);
+ 		guint flags = (*argv) ? rtnl_addr_str2flags (*argv++) : 0;
+ 
+-		gboolean value = nm_platform_ip6_address_add (ifindex, address, plen, lifetime, preferred, flags);
++		gboolean value = nm_platform_ip6_address_add (ifindex, address, in6addr_any, plen, lifetime, preferred, flags);
+ 		return value;
+ 	} else
+ 		return FALSE;
+diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
+index 52952c3..0f0ccc8 100644
+--- a/src/platform/tests/test-address.c
++++ b/src/platform/tests/test-address.c
+@@ -60,14 +60,14 @@ test_ip4_address (void)
+ 	/* Add address */
+ 	g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
+ 	no_error ();
+-	g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred));
++	g_assert (nm_platform_ip4_address_add (ifindex, addr, 0, IP4_PLEN, lifetime, preferred));
+ 	no_error ();
+ 	g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
+ 	no_error ();
+ 	accept_signal (address_added);
+ 
+ 	/* Add address again (aka update) */
+-	g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred));
++	g_assert (nm_platform_ip4_address_add (ifindex, addr, 0, IP4_PLEN, lifetime, preferred));
+ 	no_error ();
+ 	accept_signal (address_changed);
+ 
+@@ -116,14 +116,14 @@ test_ip6_address (void)
+ 	/* Add address */
+ 	g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
+ 	no_error ();
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
+ 	no_error ();
+ 	g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
+ 	no_error ();
+ 	accept_signal (address_added);
+ 
+ 	/* Add address again (aka update) */
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
+ 	no_error ();
+ 	accept_signal (address_changed);
+ 
+@@ -183,7 +183,7 @@ test_ip4_address_external (void)
+ 	/* Add/delete conflict */
+ 	run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
+ 			IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred);
+-	g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred));
++	g_assert (nm_platform_ip4_address_add (ifindex, addr, 0, IP4_PLEN, lifetime, preferred));
+ 	no_error ();
+ 	g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
+ 	accept_signal (address_added);
+@@ -222,7 +222,7 @@ test_ip6_address_external (void)
+ 	/* Add/delete conflict */
+ 	run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", 
+ 			IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
+ 	no_error ();
+ 	g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
+ 	accept_signal (address_added);
+diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
+index f102870..d94b359 100644
+--- a/src/platform/tests/test-cleanup.c
++++ b/src/platform/tests/test-cleanup.c
+@@ -41,8 +41,8 @@ test_cleanup_internal ()
+ 	g_assert (ifindex > 0);
+ 
+ 	/* Add routes and addresses */
+-	g_assert (nm_platform_ip4_address_add (ifindex, addr4, plen4, lifetime, preferred));
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6, lifetime, preferred, flags));
++	g_assert (nm_platform_ip4_address_add (ifindex, addr4, 0, plen4, lifetime, preferred));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr6, in6addr_any, plen6, lifetime, preferred, flags));
+ 	g_assert (nm_platform_ip4_route_add (ifindex, gateway4, 32, INADDR_ANY, metric, mss));
+ 	g_assert (nm_platform_ip4_route_add (ifindex, network4, plen4, gateway4, metric, mss));
+ 	g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway4, metric, mss));
+diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
+index ffb1e74..b2f2326 100644
+--- a/src/ppp-manager/nm-ppp-manager.c
++++ b/src/ppp-manager/nm-ppp-manager.c
+@@ -538,7 +538,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
+ 	val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_GATEWAY);
+ 	if (val) {
+ 		nm_ip4_config_set_gateway (config, g_value_get_uint (val));
+-		nm_ip4_config_set_ptp_address (config, g_value_get_uint (val));
++		address.peer_address = g_value_get_uint (val);
+ 	}
+ 
+ 	val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_ADDRESS);
+diff --git a/src/tests/test-dhcp-options.c b/src/tests/test-dhcp-options.c
+index effe658..6ef599e 100644
+--- a/src/tests/test-dhcp-options.c
++++ b/src/tests/test-dhcp-options.c
+@@ -129,6 +129,8 @@ test_generic_options (const char *client)
+ 	        "dhcp-generic", "couldn't convert expected IP address");
+ 	ASSERT (address->address == tmp,
+ 	        "dhcp-generic", "unexpected IP address");
++	ASSERT (address->peer_address == 0,
++	        "dhcp-generic", "unexpected PTP address");
+ 
+ 	ASSERT (address->plen == 24,
+ 	        "dhcp-generic", "unexpected IP address prefix length");
+@@ -139,9 +141,6 @@ test_generic_options (const char *client)
+ 	ASSERT (nm_ip4_config_get_gateway (ip4_config) == tmp,
+ 	        "dhcp-generic", "unexpected IP gateway");
+ 
+-	ASSERT (nm_ip4_config_get_ptp_address (ip4_config) == 0,
+-	        "dhcp-generic", "unexpected PTP address");
+-
+ 	ASSERT (nm_ip4_config_get_num_wins (ip4_config) == 0,
+ 	        "dhcp-generic", "unexpected number of WINS servers");
+ 
+diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
+index 331897c..fde4a40 100644
+--- a/src/tests/test-ip4-config.c
++++ b/src/tests/test-ip4-config.c
+@@ -25,10 +25,12 @@
+ #include "nm-ip4-config.h"
+ 
+ static void
+-addr_init (NMPlatformIP4Address *a, const char *addr, guint plen)
++addr_init (NMPlatformIP4Address *a, const char *addr, const char *peer, guint plen)
+ {
+ 	memset (a, 0, sizeof (*a));
+ 	g_assert (inet_pton (AF_INET, addr, (void *) &a->address) == 1);
++	if (peer)
++		g_assert (inet_pton (AF_INET, peer, (void *) &a->peer_address) == 1);
+ 	a->plen = plen;
+ }
+ 
+@@ -68,7 +70,7 @@ build_test_config (void)
+ 	/* Build up the config to subtract */
+ 	config = nm_ip4_config_new ();
+ 
+-	addr_init (&addr, "192.168.1.10", 24);
++	addr_init (&addr, "192.168.1.10", "1.2.3.4", 24);
+ 	nm_ip4_config_add_address (config, &addr);
+ 	
+ 	route_new (&route, "10.0.0.0", 8, "192.168.1.1");
+@@ -86,8 +88,6 @@ build_test_config (void)
+ 	nm_ip4_config_add_search (config, "blahblah.com");
+ 	nm_ip4_config_add_search (config, "beatbox.com");
+ 
+-	nm_ip4_config_set_ptp_address (config, addr_to_num ("1.2.3.4"));
+-
+ 	nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.9"));
+ 	nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.10"));
+ 
+@@ -121,7 +121,7 @@ test_subtract (void)
+ 
+ 	/* add a couple more things to the test config */
+ 	dst = build_test_config ();
+-	addr_init (&addr, expected_addr, expected_addr_plen);
++	addr_init (&addr, expected_addr, NULL, expected_addr_plen);
+ 	nm_ip4_config_add_address (dst, &addr);
+ 	
+ 	route_new (&route, expected_route_dest, expected_route_plen, expected_route_next_hop);
+@@ -142,9 +142,9 @@ test_subtract (void)
+ 	test_addr = nm_ip4_config_get_address (dst, 0);
+ 	g_assert (test_addr != NULL);
+ 	g_assert_cmpuint (test_addr->address, ==, addr_to_num (expected_addr));
++	g_assert_cmpuint (test_addr->peer_address, ==, 0);
+ 	g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
+ 
+-	g_assert_cmpuint (nm_ip4_config_get_ptp_address (dst), ==, 0);
+ 	g_assert_cmpuint (nm_ip4_config_get_gateway (dst), ==, 0);
+ 
+ 	g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1);
+diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c
+index 10ce3bf..b8b9c7b 100644
+--- a/src/tests/test-ip6-config.c
++++ b/src/tests/test-ip6-config.c
+@@ -25,10 +25,12 @@
+ #include "nm-ip6-config.h"
+ 
+ static void
+-addr_init (NMPlatformIP6Address *a, const char *addr, guint plen)
++addr_init (NMPlatformIP6Address *a, const char *addr, const char *peer, guint plen)
+ {
+ 	memset (a, 0, sizeof (*a));
+ 	g_assert (inet_pton (AF_INET6, addr, (void *) &a->address) == 1);
++	if (peer)
++		g_assert (inet_pton (AF_INET6, peer, (void *) &a->peer_address) == 1);
+ 	a->plen = plen;
+ }
+ 
+@@ -61,7 +63,7 @@ build_test_config (void)
+ 	/* Build up the config to subtract */
+ 	config = nm_ip6_config_new ();
+ 
+-	addr_init (&addr, "abcd:1234:4321::cdde", 64);
++	addr_init (&addr, "abcd:1234:4321::cdde", "1:2:3:4::5", 64);
+ 	nm_ip6_config_add_address (config, &addr);
+ 
+ 	route_new (&route, "abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2");
+@@ -82,9 +84,6 @@ build_test_config (void)
+ 	nm_ip6_config_add_search (config, "blahblah.com");
+ 	nm_ip6_config_add_search (config, "beatbox.com");
+ 
+-	addr_to_num ("1:2:3:4::5", &tmp);
+-	nm_ip6_config_set_ptp_address (config, &tmp);
+-
+ 	return config;
+ }
+ 
+@@ -111,7 +110,7 @@ test_subtract (void)
+ 
+ 	/* add a couple more things to the test config */
+ 	dst = build_test_config ();
+-	addr_init (&addr, expected_addr, expected_addr_plen);
++	addr_init (&addr, expected_addr, NULL, expected_addr_plen);
+ 	nm_ip6_config_add_address (dst, &addr);
+ 
+ 	route_new (&route, expected_route_dest, expected_route_plen, expected_route_next_hop);
+@@ -133,9 +132,9 @@ test_subtract (void)
+ 	g_assert (test_addr != NULL);
+ 	addr_to_num (expected_addr, &tmp);
+ 	g_assert (memcmp (&test_addr->address, &tmp, sizeof (tmp)) == 0);
++	g_assert (memcmp (&test_addr->peer_address, &in6addr_any, sizeof (tmp)) == 0);
+ 	g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
+ 
+-	g_assert (nm_ip6_config_get_ptp_address (dst) == NULL);
+ 	g_assert (nm_ip6_config_get_gateway (dst) == NULL);
+ 
+ 	g_assert_cmpuint (nm_ip6_config_get_num_routes (dst), ==, 1);
+diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
+index a3b09f2..2d53449 100644
+--- a/src/vpn-manager/nm-vpn-connection.c
++++ b/src/vpn-manager/nm-vpn-connection.c
+@@ -569,8 +569,7 @@ print_vpn_config (NMVPNConnection *connection)
+ 			nm_log_info (LOGD_VPN, "  Internal Gateway: %s", ip_address_to_string (priv->ip4_internal_gw));
+ 		nm_log_info (LOGD_VPN, "  Internal Address: %s", ip_address_to_string (address4->address));
+ 		nm_log_info (LOGD_VPN, "  Internal Prefix: %d", address4->plen);
+-		nm_log_info (LOGD_VPN, "  Internal Point-to-Point Address: %s",
+-					 ip_address_to_string (nm_ip4_config_get_ptp_address (priv->ip4_config)));
++		nm_log_info (LOGD_VPN, "  Internal Point-to-Point Address: %s", ip_address_to_string (address4->peer_address));
+ 		nm_log_info (LOGD_VPN, "  Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (priv->ip4_config));
+ 
+ 		num = nm_ip4_config_get_num_routes (priv->ip4_config);
+@@ -610,8 +609,7 @@ print_vpn_config (NMVPNConnection *connection)
+ 			nm_log_info (LOGD_VPN, "  Internal Gateway: %s", ip6_address_to_string (priv->ip6_internal_gw));
+ 		nm_log_info (LOGD_VPN, "  Internal Address: %s", ip6_address_to_string (&address6->address));
+ 		nm_log_info (LOGD_VPN, "  Internal Prefix: %d", address6->plen);
+-		nm_log_info (LOGD_VPN, "  Internal Point-to-Point Address: %s",
+-					 ip6_address_to_string (nm_ip6_config_get_ptp_address (priv->ip6_config)));
++		nm_log_info (LOGD_VPN, "  Internal Point-to-Point Address: %s", ip6_address_to_string (&address6->peer_address));
+ 		nm_log_info (LOGD_VPN, "  Maximum Segment Size (MSS): %d", nm_ip6_config_get_mss (priv->ip6_config));
+ 
+ 		num = nm_ip6_config_get_num_routes (priv->ip6_config);
+@@ -876,7 +874,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
+ 
+ 	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PTP);
+ 	if (val)
+-		nm_ip4_config_set_ptp_address (config, g_value_get_uint (val));
++		address.peer_address = g_value_get_uint (val);
+ 
+ 	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX);
+ 	if (val)
+@@ -1024,7 +1022,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy,
+ 		GByteArray *ba = g_value_get_boxed (val);
+ 
+ 		if (ba->len == sizeof (struct in6_addr))
+-			nm_ip6_config_set_ptp_address (config, (struct in6_addr *)ba->data);
++			address.peer_address = *(struct in6_addr *) ba->data;
+ 	}
+ 
+ 	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_PREFIX);
+-- 
+1.8.4.2
+
diff --git a/rh1018317-prereq.patch b/rh1018317-prereq.patch
new file mode 100644
index 0000000..e5f8f4a
--- /dev/null
+++ b/rh1018317-prereq.patch
@@ -0,0 +1,321 @@
+From ac94d83f04d87971c8bea4e164d7a5e260720e5c Mon Sep 17 00:00:00 2001
+From: Thomas Haller <thaller at redhat.com>
+Date: Tue, 15 Oct 2013 20:44:59 +0200
+Subject: [PATCH] core: add ifa_flags to NMPlatformIP6Address structure
+
+Add a field 'flags' to NMPlatformIP6Address that holds the
+IFA_F_* flags as reported over netlink.
+
+Signed-off-by: Thomas Haller <thaller at redhat.com>
+---
+ src/platform/nm-fake-platform.c   |  3 ++-
+ src/platform/nm-linux-platform.c  | 17 ++++++++++-------
+ src/platform/nm-platform.c        | 20 +++++++++++++++-----
+ src/platform/nm-platform.h        |  6 ++++--
+ src/platform/tests/platform.c     |  6 ++++--
+ src/platform/tests/test-address.c |  8 +++++---
+ src/platform/tests/test-cleanup.c |  3 ++-
+ 7 files changed, 42 insertions(+), 21 deletions(-)
+
+diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
+index 491e23e..df5d5b8 100644
+--- a/src/platform/nm-fake-platform.c
++++ b/src/platform/nm-fake-platform.c
+@@ -775,7 +775,7 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, gu
+ }
+ 
+ static gboolean
+-ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred)
++ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred, guint flags)
+ {
+ 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
+ 	NMPlatformIP6Address address;
+@@ -788,6 +788,7 @@ ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int pl
+ 	address.timestamp = get_time ();
+ 	address.lifetime = lifetime;
+ 	address.preferred = preferred;
++	address.flags = flags;
+ 
+ 	for (i = 0; i < priv->ip6_addresses->len; i++) {
+ 		NMPlatformIP6Address *item = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
+diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
+index 0f67180..e3d6357 100644
+--- a/src/platform/nm-linux-platform.c
++++ b/src/platform/nm-linux-platform.c
+@@ -790,6 +790,7 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
+ 	address->timestamp = rtnl_addr_get_create_time (rtnladdr);
+ 	address->lifetime = rtnl_addr_get_valid_lifetime (rtnladdr);
+ 	address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
++	address->flags = rtnl_addr_get_flags (rtnladdr);
+ 	g_assert (nl_addr_get_len (nladdr) == sizeof (address->address));
+ 	memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address));
+ }
+@@ -2198,7 +2199,7 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
+ }
+ 
+ static struct nl_object *
+-build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 lifetime, guint32 preferred)
++build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 lifetime, guint32 preferred, guint flags)
+ {
+ 	struct rtnl_addr *rtnladdr = rtnl_addr_alloc ();
+ 	int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+@@ -2215,6 +2216,8 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32
+ 		rtnl_addr_set_valid_lifetime (rtnladdr, lifetime);
+ 		rtnl_addr_set_preferred_lifetime (rtnladdr, preferred);
+ 	}
++	if (flags)
++		rtnl_addr_set_flags (rtnladdr, flags);
+ 
+ 	return (struct nl_object *) rtnladdr;
+ }
+@@ -2222,31 +2225,31 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32
+ static gboolean
+ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred)
+ {
+-	return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, lifetime, preferred));
++	return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, lifetime, preferred, 0));
+ }
+ 
+ static gboolean
+-ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred)
++ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred, guint flags)
+ {
+-	return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, lifetime, preferred));
++	return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, lifetime, preferred, flags));
+ }
+ 
+ static gboolean
+ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
+ {
+-	return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, 0, 0));
++	return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, 0, 0, 0));
+ }
+ 
+ static gboolean
+ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
+ {
+-	return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, 0, 0));
++	return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, 0, 0, 0));
+ }
+ 
+ static gboolean
+ ip_address_exists (NMPlatform *platform, int family, int ifindex, gconstpointer addr, int plen)
+ {
+-	auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, plen, 0, 0);
++	auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, plen, 0, 0, 0);
+ 	auto_nl_object struct nl_object *cached_object = nl_cache_search (choose_cache (platform, object), object);
+ 
+ 	return !!cached_object;
+diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
+index 5a5e464..3f645ed 100644
+--- a/src/platform/nm-platform.c
++++ b/src/platform/nm-platform.c
+@@ -24,6 +24,7 @@
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <string.h>
++#include <netlink/route/addr.h>
+ 
+ #include "nm-platform.h"
+ #include "nm-logging.h"
+@@ -1100,7 +1101,7 @@ nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, guint32 l
+ }
+ 
+ gboolean
+-nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, guint32 lifetime, guint32 preferred)
++nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, guint32 lifetime, guint32 preferred, guint flags)
+ {
+ 	reset_error ();
+ 
+@@ -1111,7 +1112,7 @@ nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, gui
+ 	g_return_val_if_fail (klass->ip6_address_add, FALSE);
+ 
+ 	debug ("address: adding or updating IPv6 address");
+-	return klass->ip6_address_add (platform, ifindex, address, plen, lifetime, preferred);
++	return klass->ip6_address_add (platform, ifindex, address, plen, lifetime, preferred, flags);
+ }
+ 
+ gboolean
+@@ -1329,7 +1330,8 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
+ 		} else
+ 			lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
+ 
+-		if (!nm_platform_ip6_address_add (ifindex, known_address->address, known_address->plen, lifetime, preferred))
++		if (!nm_platform_ip6_address_add (ifindex, known_address->address, known_address->plen,
++		                                  lifetime, preferred, known_address->flags))
+ 			return FALSE;
+ 	}
+ 
+@@ -1637,8 +1639,10 @@ const char *
+ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
+ {
+ 	static char buffer[256];
++	char s_flags[256];
+ 	char s_address[INET6_ADDRSTRLEN];
+ 	const char *s_dev;
++	char *str_flags;
+ 
+ 	g_return_val_if_fail (address, "(unknown)");
+ 
+@@ -1648,7 +1652,12 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
+ 	s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL;
+ 
+-	g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u dev %s",
++	rtnl_addr_flags2str(address->flags, s_flags, sizeof(s_flags));
++	str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL;
++
++	g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u dev %s%s",
+ 	            s_address, address->plen, (guint)address->lifetime, (guint)address->preferred,
+-	            (guint)address->timestamp, s_dev ? s_dev : "-");
++	            (guint)address->timestamp, s_dev ? s_dev : "-",
++	            str_flags ? str_flags : "");
++	g_free (str_flags);
+ 	return buffer;
+ }
+@@ -1775,6 +1784,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
+ 	_CMP_FIELD (a, b, timestamp);
+ 	_CMP_FIELD (a, b, lifetime);
+ 	_CMP_FIELD (a, b, preferred);
++	_CMP_FIELD (a, b, flags);
+ 	return 0;
+ }
+ 
+diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
+index eae5465..7de0280 100644
+--- a/src/platform/nm-platform.h
++++ b/src/platform/nm-platform.h
+@@ -24,6 +24,7 @@
+ #include <glib-object.h>
+ #include <netinet/in.h>
+ #include <linux/if.h>
++#include <linux/if_addr.h>
+ 
+ #define NM_TYPE_PLATFORM            (nm_platform_get_type ())
+ #define NM_PLATFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
+@@ -134,6 +135,7 @@ typedef struct {
+ 	guint32 timestamp;
+ 	guint32 lifetime;
+ 	guint32 preferred;
++	guint flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
+ } NMPlatformIP6Address;
+ 
+ typedef struct {
+@@ -281,7 +283,7 @@ typedef struct {
+ 	gboolean (*ip4_address_add) (NMPlatform *, int ifindex, in_addr_t address, int plen,
+			guint32 lifetime, guint32 preferred_lft);
+ 	gboolean (*ip6_address_add) (NMPlatform *, int ifindex, struct in6_addr address, int plen,
+-			guint32 lifetime, guint32 preferred_lft);
++	                             guint32 lifetime, guint32 preferred_lft, guint flags);
+ 	gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen);
+ 	gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
+ 	gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen);
+@@ -402,7 +404,7 @@ GArray *nm_platform_ip6_address_get_all (int ifindex);
+ gboolean nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen,
+		guint32 lifetime, guint32 preferred_lft);
+ gboolean nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen,
+-		guint32 lifetime, guint32 preferred_lft);
++                                      guint32 lifetime, guint32 preferred_lft, guint flags);
+ gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen);
+ gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen);
+ gboolean nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen);
+diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c
+index cd274cd..c0b2c02 100644
+--- a/src/platform/tests/platform.c
++++ b/src/platform/tests/platform.c
+@@ -22,6 +22,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <arpa/inet.h>
++#include <netlink/route/addr.h>
+ 
+ #include "nm-platform.h"
+ #include "nm-linux-platform.h"
+@@ -538,8 +539,9 @@ do_ip6_address_add (char **argv)
+ 	if (ifindex && parse_ip6_address (*argv++, &address, &plen)) {
+ 		guint32 lifetime = strtol (*argv++, NULL, 10);
+ 		guint32 preferred = strtol (*argv++, NULL, 10);
++		guint flags = (*argv) ? rtnl_addr_str2flags (*argv++) : 0;
+ 
+-		gboolean value = nm_platform_ip6_address_add (ifindex, address, plen, lifetime, preferred);
++		gboolean value = nm_platform_ip6_address_add (ifindex, address, plen, lifetime, preferred, flags);
+ 		return value;
+ 	} else
+ 		return FALSE;
+@@ -765,7 +767,7 @@ static const command_t commands[] = {
+ 	{ "ip4-address-get-all", "print all IPv4 addresses", do_ip4_address_get_all, 1, "<ifname/ifindex>" },
+ 	{ "ip6-address-get-all", "print all IPv6 addresses", do_ip6_address_get_all, 1, "<ifname/ifindex>" },
+ 	{ "ip4-address-add", "add IPv4 address", do_ip4_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
+-	{ "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
++	{ "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> [<flags>] <>" },
+ 	{ "ip4-address-delete", "delete IPv4 address", do_ip4_address_delete, 2,
+ 		"<ifname/ifindex> <address>/<plen>" },
+ 	{ "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2,
+diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
+index ff11384..52952c3 100644
+--- a/src/platform/tests/test-address.c
++++ b/src/platform/tests/test-address.c
+@@ -109,20 +109,21 @@ test_ip6_address (void)
+ 	struct in6_addr addr;
+ 	guint32 lifetime = 2000;
+ 	guint32 preferred = 1000;
++	guint flags = 0;
+ 
+ 	inet_pton (AF_INET6, IP6_ADDRESS, &addr);
+ 
+ 	/* Add address */
+ 	g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
+ 	no_error ();
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags));
+ 	no_error ();
+ 	g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
+ 	no_error ();
+ 	accept_signal (address_added);
+ 
+ 	/* Add address again (aka update) */
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags));
+ 	no_error ();
+ 	accept_signal (address_changed);
+ 
+@@ -205,6 +206,7 @@ test_ip6_address_external (void)
+ 	struct in6_addr addr;
+ 	guint32 lifetime = 2000;
+ 	guint32 preferred = 1000;
++	guint flags = 0;
+ 
+ 	inet_pton (AF_INET6, IP6_ADDRESS, &addr);
+ 
+@@ -220,7 +222,7 @@ test_ip6_address_external (void)
+ 	/* Add/delete conflict */
+ 	run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", 
+ 			IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags));
+ 	no_error ();
+ 	g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
+ 	accept_signal (address_added);
+diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
+index cbfebe7..f102870 100644
+--- a/src/platform/tests/test-cleanup.c
++++ b/src/platform/tests/test-cleanup.c
+@@ -23,6 +23,7 @@ test_cleanup_internal ()
+ 	int preferred = NM_PLATFORM_LIFETIME_PERMANENT;
+ 	int metric = 20;
+ 	int mss = 1000;
++	guint flags = 0;
+ 
+ 	inet_pton (AF_INET, "192.0.2.1", &addr4);
+ 	inet_pton (AF_INET, "192.0.3.0", &network4);
+@@ -41,7 +42,7 @@ test_cleanup_internal ()
+ 
+ 	/* Add routes and addresses */
+ 	g_assert (nm_platform_ip4_address_add (ifindex, addr4, plen4, lifetime, preferred));
+-	g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6, lifetime, preferred));
++	g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6, lifetime, preferred, flags));
+ 	g_assert (nm_platform_ip4_route_add (ifindex, gateway4, 32, INADDR_ANY, metric, mss));
+ 	g_assert (nm_platform_ip4_route_add (ifindex, network4, plen4, gateway4, metric, mss));
+ 	g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway4, metric, mss));
+-- 
+1.8.4.2
+


More information about the scm-commits mailing list