summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-10-15 14:20:13 -0500
committerDan Williams <dcbw@redhat.com>2013-10-15 14:28:17 -0500
commitb0ec62e9a895678304f70d5dd64073bfa8856634 (patch)
treed27b48fa882e627ca63b07870c37a97b314279e8
parent1d0a26e19de1133bb1ea8294f8f5d8472bedd859 (diff)
downloadNetworkManager-dcbw/ptp-address.tar.gz
platform/core: add support for IPv4 PtP/peer addressesdcbw/ptp-address
OpenVPN's 'p2p' topology does 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. Unless NetworkManager configures the tunX interface with the peer address, the kernel refuses to add the routes with the peer nexthop, because the kernel has no idea how to talk to the peer, because the peers address is not reachable over any routes (none have yet been added) and the peer's address is not assigned to any interface yet. OR: could we just add a host route through the tunX pointing to the peer address, and leave the PtP peer address unset?
-rw-r--r--src/platform/nm-fake-platform.c3
-rw-r--r--src/platform/nm-linux-platform.c40
-rw-r--r--src/platform/nm-platform.c12
-rw-r--r--src/platform/nm-platform.h5
-rw-r--r--src/platform/tests/platform.c2
-rw-r--r--src/platform/tests/test-address.c6
-rw-r--r--src/platform/tests/test-cleanup.c2
-rw-r--r--src/ppp-manager/nm-ppp-manager.c1
-rw-r--r--src/vpn-manager/nm-vpn-connection.c4
9 files changed, 56 insertions, 19 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 6d7843f2fb..3940b1e978 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -730,7 +730,7 @@ 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;
@@ -739,6 +739,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;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 519a570dd7..766e60fc2b 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -759,6 +759,7 @@ static void
init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
{
struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr);
+ struct nl_addr *peer = rtnl_addr_get_peer (rtnladdr);
g_assert (nladdr);
@@ -771,6 +772,11 @@ 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 (peer) {
+ g_assert (nl_addr_get_len (peer) == sizeof (address->peer_address));
+ memcpy (&address->peer_address, nl_addr_get_binary_addr (peer), sizeof (address->peer_address));
+ }
}
static void
@@ -2166,7 +2172,13 @@ 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,
+ gconstpointer peer_addr,
+ int plen,
+ guint32 lifetime,
+ guint32 preferred)
{
struct rtnl_addr *rtnladdr = rtnl_addr_alloc ();
int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
@@ -2178,6 +2190,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);
@@ -2188,33 +2208,39 @@ 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));
+ return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, peer_addr ? &peer_addr : NULL, plen, lifetime, preferred));
}
static gboolean
ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred)
{
- 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, NULL, plen, lifetime, preferred));
}
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, NULL, plen, 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, NULL, plen, 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, NULL, plen, 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 f5a4c9b0f3..1c9161930e 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1067,7 +1067,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 ();
@@ -1078,7 +1083,7 @@ 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
@@ -1254,7 +1259,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;
}
@@ -1719,6 +1724,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);
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 68d2fdce32..6abb5b6901 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -120,6 +120,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;
@@ -275,7 +276,7 @@ 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,
+ 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, int plen,
guint32 lifetime, guint32 preferred_lft);
@@ -394,7 +395,7 @@ 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,
+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, int plen,
guint32 lifetime, guint32 preferred_lft);
diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c
index cd274cdad7..a74b209e96 100644
--- a/src/platform/tests/platform.c
+++ b/src/platform/tests/platform.c
@@ -522,7 +522,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;
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index e3abc12fff..256bfd7ab2 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);
@@ -182,7 +182,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);
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index cbfebe71c7..4e0bee3aac 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -40,7 +40,7 @@ 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_ip4_address_add (ifindex, addr4, 0, plen4, lifetime, preferred));
g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6, lifetime, preferred));
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));
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index ffb1e74a2f..6a664dbc3d 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -539,6 +539,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
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/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index 9f52a2a1fa..98a49417a2 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -872,8 +872,10 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
address.address = g_value_get_uint (val);
val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PTP);
- if (val)
+ 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)