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.
This commit is contained in:
@@ -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,
|
||||
IN6_IS_ADDR_UNSPECIFIED (&peer_addr) ? 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;
|
||||
|
Reference in New Issue
Block a user