Merge commit 'd9c5764ddb7a90f57a3d13b542bafada9beb6d92'

Conflicts:
	NetworkManager.spec
This commit is contained in:
Adam Williamson 2014-01-10 10:26:34 -08:00
commit 93c10b457c
9 changed files with 2691 additions and 0 deletions

3
.gitignore vendored
View File

@ -293,3 +293,6 @@ network-manager-applet-0.8.1.tar.bz2
/NetworkManager-0.9.9.0.git20130603.tar.bz2
/NetworkManager-0.9.9.0.git20130724.tar.bz2
/NetworkManager-0.9.9.0.git20130807.tar.bz2
/NetworkManager-0.9.9.0.git20130913.tar.bz2
/NetworkManager-0.9.9.0.git20131001.tar.bz2
/NetworkManager-0.9.9.0.git20131003.tar.bz2

View File

@ -19,7 +19,11 @@ Name: NetworkManager
Summary: Network connection manager and user applications
Epoch: 1
Version: 0.9.9.0
<<<<<<< HEAD
Release: 19%{snapshot}%{?dist}
=======
Release: 23%{snapshot}%{?dist}
>>>>>>> d9c5764ddb7a90f57a3d13b542bafada9beb6d92
Group: System Environment/Base
License: GPLv2+
URL: http://www.gnome.org/projects/NetworkManager/
@ -43,6 +47,16 @@ 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
<<<<<<< HEAD
=======
Patch17: rh1018317-prereq.patch
Patch18: rh1018317-openvpn-ptp.patch
Patch19: rh1034921-startup-link-wait.patch
Patch20: rh1029213-ignore-RA-default-routes.patch
Patch21: rh1032819-set-broadcast-address.patch
Patch22: rh1044757-ipv6-solicit-infinity.patch
Patch23: rh1048711-bluez-crash.patch
>>>>>>> d9c5764ddb7a90f57a3d13b542bafada9beb6d92
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@ -182,6 +196,16 @@ deployments.
%patch14 -p1 -b .device-no-MAC
%patch15 -p1 -b .libnm-glib-editor
%patch16 -p1 -b .ifcfg-rh-update
<<<<<<< HEAD
=======
%patch17 -p1 -b .ipv6-flags
%patch18 -p1 -b .openvpn-ptp
%patch19 -p1 -b .startup-linkwait
%patch20 -p1 -b .ignore-RA-default-routes
%patch21 -p1 -b .broadcast-addr
%patch22 -p1 -b .ipv6-solicit-infinity
%patch23 -p1 -b .bluez-crash
>>>>>>> d9c5764ddb7a90f57a3d13b542bafada9beb6d92
%build
@ -380,6 +404,23 @@ fi
%config %{_sysconfdir}/%{name}/conf.d/00-server.conf
%changelog
<<<<<<< HEAD
=======
* Mon Jan 6 2014 Dan Winship <danw@redhat.com> - 0.9.9.0-23.git20131003
- bluez-manager: fix a crash (rh #1048711)
* Thu Dec 19 2013 Dan Williams <dcbw@redhat.com> - 0.9.9.0-22.git20131003
- core: fix IPv6 router solicitation loop (rh #1044757)
* Thu Dec 12 2013 Dan Williams <dcbw@redhat.com> - 0.9.9.0-21.git20131003
- core: wait for link before declaring startup complete (rh #1034921)
- core: ignore RA-provided IPv6 default routes (rh #1029213)
- core: set IPv4 broadcast address correctly (rh #1032819)
* Mon Dec 2 2013 Dan Winship <danw@redhat.com> - 0.9.9.0-20.git20131003
- core: Fix PtP/peer address support, for OpenVPN (rh #1018317)
>>>>>>> d9c5764ddb7a90f57a3d13b542bafada9beb6d92
* Wed Nov 20 2013 Jiří Klimeš <jklimes@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)

857
rh1018317-openvpn-ptp.patch Normal file
View File

@ -0,0 +1,857 @@
From fec50bd5fad633e57bfd6f9ee480e6192504ca5f Mon Sep 17 00:00:00 2001
From: Dan Winship <danw@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

321
rh1018317-prereq.patch Normal file
View File

@ -0,0 +1,321 @@
From ac94d83f04d87971c8bea4e164d7a5e260720e5c Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@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@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

View File

@ -0,0 +1,98 @@
From 8586353b09460ec0a619058421743dd7d424a75d Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Wed, 20 Nov 2013 13:40:07 -0600
Subject: [PATCH] core: ignore RA-provided default routes (rh #1029213)
The router has no idea what the local configuration or user preferences are,
so sending routes with a prefix length of 0 is at best misinformed and at
worst breaks things. The kernel also ignores plen=0 routes in its in-kernel
RA processing code in net/ipv6/ndisc.c.
https://bugzilla.redhat.com/show_bug.cgi?id=1029213
---
src/devices/nm-device.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index f03ecbb..d92a94b 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -3283,20 +3283,26 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
/* Rebuild route list from router discovery cache. */
nm_ip6_config_reset_routes (priv->ac_ip6_config);
for (i = 0; i < rdisc->routes->len; i++) {
NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i);
NMPlatformIP6Route route;
- memset (&route, 0, sizeof (route));
- route.network = discovered_route->network;
- route.plen = discovered_route->plen;
- route.gateway = discovered_route->gateway;
+ /* Only accept non-default routes. The router has no idea what the
+ * local configuration or user preferences are, so sending routes
+ * with a prefix length of 0 is quite rude and thus ignored.
+ */
+ if (discovered_route->plen > 0) {
+ memset (&route, 0, sizeof (route));
+ route.network = discovered_route->network;
+ route.plen = discovered_route->plen;
+ route.gateway = discovered_route->gateway;
- nm_ip6_config_add_route (priv->ac_ip6_config, &route);
+ nm_ip6_config_add_route (priv->ac_ip6_config, &route);
+ }
}
}
if (changed & NM_RDISC_CONFIG_DNS_SERVERS) {
/* Rebuild DNS server list from router discovery cache. */
nm_ip6_config_reset_nameservers (priv->ac_ip6_config);
--
1.8.3.1
From 6e73f01b6e69f44f8d9da4872fb796b9d80acac1 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Tue, 3 Dec 2013 14:12:55 -0600
Subject: [PATCH] platform: fix possible out-of-bounds access with RA route
masking
If the prefix length was 128, that could cause an access beyond the
end of the array. Found by Thomas Haller.
---
src/rdisc/nm-lndp-rdisc.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
index abcc3c2..3299b32 100644
--- a/src/rdisc/nm-lndp-rdisc.c
+++ b/src/rdisc/nm-lndp-rdisc.c
@@ -411,17 +411,21 @@ set_address_masked (struct in6_addr *dst, struct in6_addr *src, guint8 plen)
guint nbytes = plen / 8;
guint nbits = plen % 8;
g_return_if_fail (plen <= 128);
g_assert (src);
g_assert (dst);
- memset (dst, 0, sizeof (*dst));
- memcpy (dst, src, nbytes);
- dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
+ if (plen >= 128)
+ *dst = *src;
+ else {
+ memset (dst, 0, sizeof (*dst));
+ memcpy (dst, src, nbytes);
+ dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
+ }
}
static int
receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
{
NMRDisc *rdisc = (NMRDisc *) user_data;
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
--
1.8.3.1

View File

@ -0,0 +1,86 @@
From 7eb12a5b21f87d7592ec2c5235d1ed90c4fac132 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Tue, 3 Dec 2013 11:42:28 -0600
Subject: [PATCH] platform: set IPv4 broadcast address too (rh #1032819)
When moving over the platform, setting of the IPv4 broadcast address
got lost. Bring it back.
https://bugzilla.redhat.com/show_bug.cgi?id=1032819
---
src/platform/nm-linux-platform.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 8f0e077..3f57925 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -2213,14 +2213,33 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
nl_object_unmark (object);
}
}
return addresses;
}
+static void
+addr4_to_broadcast (struct in_addr *dst, const struct in_addr *src, guint8 plen)
+{
+ guint nbytes = plen / 8;
+ guint nbits = plen % 8;
+
+ g_return_if_fail (plen <= 32);
+ g_assert (src);
+ g_assert (dst);
+
+ if (plen >= 32)
+ *dst = *src;
+ else {
+ dst->s_addr = 0xFFFFFFFF;
+ memcpy (dst, src, nbytes);
+ ((guint8 *) dst)[nbytes] = (((const guint8 *) src)[nbytes] | (0xFF >> nbits));
+ }
+}
+
static struct nl_object *
build_rtnl_addr (int family,
int ifindex,
gconstpointer addr,
gconstpointer peer_addr,
int plen,
guint32 lifetime,
@@ -2230,18 +2249,31 @@ build_rtnl_addr (int family,
struct rtnl_addr *rtnladdr = rtnl_addr_alloc ();
int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
auto_nl_addr struct nl_addr *nladdr = nl_addr_build (family, addr, addrlen);
int nle;
g_assert (rtnladdr && nladdr);
+ /* IP address */
rtnl_addr_set_ifindex (rtnladdr, ifindex);
nle = rtnl_addr_set_local (rtnladdr, nladdr);
g_assert (!nle);
+ /* IPv4 Broadcast address */
+ if (family == AF_INET) {
+ struct in_addr bcast;
+ auto_nl_addr struct nl_addr *bcaddr = NULL;
+
+ addr4_to_broadcast (&bcast, addr, plen);
+ bcaddr = nl_addr_build (family, &bcast, addrlen);
+ g_assert (bcaddr);
+ rtnl_addr_set_broadcast (rtnladdr, bcaddr);
+ }
+
+ /* Peer/point-to-point address */
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);
}
--
1.8.3.1

View File

@ -0,0 +1,833 @@
From 07281f21a71fa333288821ad863accfeedfff567 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Mon, 9 Dec 2013 12:55:04 -0600
Subject: [PATCH] core: delay startup complete until carrier is found or
timeout (rh #1034921) (rh #1030583)
---
src/devices/nm-device.c | 177 ++++++++++++++++++++++++++++++++++-----------
src/nm-active-connection.c | 8 ++
2 files changed, 142 insertions(+), 43 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 578ccb0..96a5d44 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -184,15 +184,15 @@ typedef struct {
gboolean initialized;
gboolean in_state_changed;
NMDeviceState state;
NMDeviceStateReason state_reason;
QueuedState queued_state;
guint queued_ip_config_id;
- guint pending_actions;
+ GArray *pending_actions;
char * udi;
char * path;
char * iface; /* may change, could be renamed by user */
int ifindex;
gboolean is_software;
char * ip_iface;
@@ -224,14 +224,15 @@ typedef struct {
gpointer act_source6_func;
/* Link stuff */
guint link_connected_id;
guint link_disconnected_id;
guint carrier_defer_id;
gboolean carrier;
+ guint carrier_wait_id;
gboolean ignore_carrier;
/* Generic DHCP stuff */
NMDHCPManager * dhcp_manager;
guint32 dhcp_timeout;
GByteArray * dhcp_anycast_address;
@@ -390,14 +391,15 @@ nm_device_init (NMDevice *self)
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
priv->state = NM_DEVICE_STATE_UNMANAGED;
priv->state_reason = NM_DEVICE_STATE_REASON_NONE;
priv->dhcp_timeout = 0;
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
priv->autoconnect = DEFAULT_AUTOCONNECT;
priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
+ priv->pending_actions = g_array_sized_new (FALSE, TRUE, sizeof (GQuark), 5);
}
static void
update_accept_ra_save (NMDevice *self)
{
NMDevicePrivate *priv;
const char *ip_iface;
@@ -1154,14 +1156,20 @@ nm_device_set_carrier (NMDevice *device, gboolean carrier)
if (priv->carrier) {
nm_log_info (LOGD_DEVICE, "(%s): link connected", iface);
if (priv->carrier_defer_id) {
g_source_remove (priv->carrier_defer_id);
priv->carrier_defer_id = 0;
}
klass->carrier_changed (device, TRUE);
+
+ if (priv->carrier_wait_id) {
+ g_source_remove (priv->carrier_wait_id);
+ priv->carrier_wait_id = 0;
+ nm_device_remove_pending_action (device, "carrier wait");
+ }
} else if (state <= NM_DEVICE_STATE_DISCONNECTED) {
nm_log_info (LOGD_DEVICE, "(%s): link disconnected", iface);
klass->carrier_changed (device, FALSE);
} else {
nm_log_info (LOGD_DEVICE, "(%s): link disconnected (deferring action for %d seconds)",
iface, LINK_DISCONNECT_DELAY);
priv->carrier_defer_id = g_timeout_add_seconds (LINK_DISCONNECT_DELAY,
@@ -5110,17 +5118,28 @@ nm_device_start_ip_check (NMDevice *self)
/* If no ping was started, just advance to SECONDARIES */
if (!priv->gw_ping.pid)
nm_device_queue_state (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
}
/****************************************************************/
+static gboolean
+carrier_wait_timeout (gpointer user_data)
+{
+ NMDevice *self = NM_DEVICE (user_data);
+
+ NM_DEVICE_GET_PRIVATE (self)->carrier_wait_id = 0;
+ nm_device_remove_pending_action (self, "carrier wait");
+ return G_SOURCE_REMOVE;
+}
+
gboolean
nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean success;
guint32 tries = 0;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (nm_device_is_up (self))
goto out;
@@ -5138,14 +5157,28 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
g_usleep (200);
if (!nm_device_is_up (self)) {
nm_log_warn (LOGD_HW, "(%s): device not up after timeout!", nm_device_get_iface (self));
return FALSE;
}
+ /* Devices that support carrier detect must be IFF_UP to report carrier
+ * changes; so after setting the device IFF_UP we must suppress startup
+ * complete (via a pending action) until either the carrier turns on, or
+ * a timeout is reached.
+ */
+ if (device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
+ if (priv->carrier_wait_id) {
+ g_source_remove (priv->carrier_wait_id);
+ nm_device_remove_pending_action (self, "carrier wait");
+ }
+ priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self);
+ nm_device_add_pending_action (self, "carrier wait");
+ }
+
out:
/* Can only get HW address of some devices when they are up */
nm_device_update_hw_address (self);
_update_ip4_address (self);
return TRUE;
}
@@ -5301,14 +5334,19 @@ dispose (GObject *object)
}
if (priv->cp_updated_id) {
g_signal_handler_disconnect (priv->con_provider, priv->cp_updated_id);
priv->cp_updated_id = 0;
}
+ if (priv->carrier_wait_id) {
+ g_source_remove (priv->carrier_wait_id);
+ priv->carrier_wait_id = 0;
+ }
+
g_hash_table_unref (priv->available_connections);
priv->available_connections = NULL;
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
clear_act_request (self);
@@ -5331,14 +5369,17 @@ finalize (GObject *object)
if (priv->dhcp_manager)
g_object_unref (priv->dhcp_manager);
if (priv->fw_manager)
g_object_unref (priv->fw_manager);
+ g_array_free (priv->pending_actions, TRUE);
+ priv->pending_actions = NULL;
+
g_free (priv->udi);
g_free (priv->path);
g_free (priv->iface);
g_free (priv->ip_iface);
g_free (priv->driver);
g_free (priv->driver_version);
g_free (priv->firmware_version);
@@ -5931,46 +5972,54 @@ nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing)
gboolean
nm_device_get_firmware_missing (NMDevice *self)
{
return NM_DEVICE_GET_PRIVATE (self)->firmware_missing;
}
+#define QUEUED_PREFIX "queued state change to "
+
static const char *
-state_to_string (NMDeviceState state)
+queued_state_to_string (NMDeviceState state)
{
switch (state) {
case NM_DEVICE_STATE_UNMANAGED:
- return "unmanaged";
+ return QUEUED_PREFIX "unmanaged";
case NM_DEVICE_STATE_UNAVAILABLE:
- return "unavailable";
+ return QUEUED_PREFIX "unavailable";
case NM_DEVICE_STATE_DISCONNECTED:
- return "disconnected";
+ return QUEUED_PREFIX "disconnected";
case NM_DEVICE_STATE_PREPARE:
- return "prepare";
+ return QUEUED_PREFIX "prepare";
case NM_DEVICE_STATE_CONFIG:
- return "config";
+ return QUEUED_PREFIX "config";
case NM_DEVICE_STATE_NEED_AUTH:
- return "need-auth";
+ return QUEUED_PREFIX "need-auth";
case NM_DEVICE_STATE_IP_CONFIG:
- return "ip-config";
+ return QUEUED_PREFIX "ip-config";
case NM_DEVICE_STATE_IP_CHECK:
- return "ip-check";
+ return QUEUED_PREFIX "ip-check";
case NM_DEVICE_STATE_SECONDARIES:
- return "secondaries";
+ return QUEUED_PREFIX "secondaries";
case NM_DEVICE_STATE_ACTIVATED:
- return "activated";
+ return QUEUED_PREFIX "activated";
case NM_DEVICE_STATE_DEACTIVATING:
- return "deactivating";
+ return QUEUED_PREFIX "deactivating";
case NM_DEVICE_STATE_FAILED:
- return "failed";
+ return QUEUED_PREFIX "failed";
default:
break;
}
- return "unknown";
+ return QUEUED_PREFIX "unknown";
+}
+
+static const char *
+state_to_string (NMDeviceState state)
+{
+ return queued_state_to_string (state) + strlen (QUEUED_PREFIX);
}
static const char *
reason_to_string (NMDeviceStateReason reason)
{
switch (reason) {
case NM_DEVICE_STATE_REASON_NONE:
@@ -6083,21 +6132,14 @@ reason_to_string (NMDeviceStateReason reason)
return "secondary-connection-failed";
default:
break;
}
return "unknown";
}
-static inline gboolean
-state_implies_pending_action (NMDeviceState state)
-{
- return ( state >= NM_DEVICE_STATE_PREPARE
- && state < NM_DEVICE_STATE_ACTIVATED);
-}
-
void
nm_device_state_changed (NMDevice *device,
NMDeviceState state,
NMDeviceStateReason reason)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
NMDeviceState old_state;
@@ -6131,18 +6173,14 @@ nm_device_state_changed (NMDevice *device,
return;
}
old_state = priv->state;
priv->state = state;
priv->state_reason = reason;
- if ( state_implies_pending_action (state)
- && !state_implies_pending_action (old_state))
- nm_device_add_pending_action (device, "activation");
-
nm_log_info (LOGD_DEVICE, "(%s): device state change: %s -> %s (reason '%s') [%d %d %d]",
nm_device_get_iface (device),
state_to_string (old_state),
state_to_string (state),
reason_to_string (reason),
old_state,
state,
@@ -6300,18 +6338,14 @@ nm_device_state_changed (NMDevice *device,
if (old_state == NM_DEVICE_STATE_ACTIVATED)
nm_dispatcher_call (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), device, NULL, NULL);
/* Dispose of the cached activation request */
if (req)
g_object_unref (req);
- if ( state_implies_pending_action (old_state)
- && !state_implies_pending_action (state))
- nm_device_remove_pending_action (device, "activation");
-
priv->in_state_changed = FALSE;
}
static gboolean
queued_set_state (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
@@ -6330,15 +6364,15 @@ queued_set_state (gpointer user_data)
*/
priv->queued_state.id = 0;
new_state = priv->queued_state.state;
new_reason = priv->queued_state.reason;
nm_device_queued_state_clear (self);
nm_device_state_changed (self, new_state, new_reason);
- nm_device_remove_pending_action (self, "queued state change");
+ nm_device_remove_pending_action (self, queued_state_to_string (new_state));
} else {
g_warn_if_fail (priv->queued_state.state == NM_DEVICE_STATE_UNKNOWN);
g_warn_if_fail (priv->queued_state.reason == NM_DEVICE_STATE_REASON_NONE);
}
return FALSE;
}
@@ -6349,29 +6383,37 @@ nm_device_queue_state (NMDevice *self,
{
NMDevicePrivate *priv;
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
+ /* "lock" the pending actions so that if there was a previously
+ * queued action that's about to be cleared, that doesn't drop
+ * the pending actions to 0 before we add the new pending action.
+ */
+ nm_device_add_pending_action (self, "queued state lock");
+
/* We should only ever have one delayed state transition at a time */
if (priv->queued_state.id) {
if (priv->queued_state.state == state)
return;
nm_log_warn (LOGD_DEVICE, "(%s): overwriting previously queued state change to %s (%s)",
nm_device_get_iface (self),
state_to_string (priv->queued_state.state),
reason_to_string (priv->queued_state.reason));
nm_device_queued_state_clear (self);
}
priv->queued_state.state = state;
priv->queued_state.reason = reason;
priv->queued_state.id = g_idle_add (queued_set_state, self);
- nm_device_add_pending_action (self, "queued state change");
+ nm_device_add_pending_action (self, queued_state_to_string (state));
+
+ nm_device_remove_pending_action (self, "queued state lock");
nm_log_dbg (LOGD_DEVICE, "(%s): queued state change to %s due to %s (id %d)",
nm_device_get_iface (self), state_to_string (state), reason_to_string (reason),
priv->queued_state.id);
}
NMDeviceState
@@ -6391,15 +6433,15 @@ nm_device_queued_state_clear (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->queued_state.id) {
nm_log_dbg (LOGD_DEVICE, "(%s): clearing queued state transition (id %d)",
nm_device_get_iface (self), priv->queued_state.id);
g_source_remove (priv->queued_state.id);
- nm_device_remove_pending_action (self, "queued state change");
+ nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state));
}
memset (&priv->queued_state, 0, sizeof (priv->queued_state));
}
NMDeviceState
nm_device_get_state (NMDevice *device)
{
@@ -7102,40 +7144,89 @@ nm_device_set_hw_addr (NMDevice *device, const guint8 *addr,
}
nm_device_bring_up (device, TRUE, NULL);
g_free (mac_str);
return success;
}
+/**
+ * nm_device_add_pending_action():
+ * @device: the #NMDevice to add the pending action to
+ * @action: a static string that identifies the action
+ *
+ * Adds a pending action to the device.
+ */
void
nm_device_add_pending_action (NMDevice *device, const char *action)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+ GQuark qaction;
+ guint i;
- priv->pending_actions++;
- nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): %s",
- nm_device_get_iface (device), priv->pending_actions, action);
+ qaction = g_quark_from_static_string (action);
- if (priv->pending_actions == 1)
+ /* Shouldn't ever add the same pending action twice */
+ for (i = 0; i < priv->pending_actions->len; i++) {
+ if (qaction == g_array_index (priv->pending_actions, GQuark, i)) {
+ nm_log_warn (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s' already added",
+ nm_device_get_iface (device),
+ priv->pending_actions->len,
+ action);
+ g_warn_if_reached ();
+ return;
+ }
+ }
+
+ g_array_prepend_val (priv->pending_actions, qaction);
+ nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s'",
+ nm_device_get_iface (device),
+ priv->pending_actions->len,
+ action);
+
+ if (priv->pending_actions->len == 1)
g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
}
+/**
+ * nm_device_remove_pending_action():
+ * @device: the #NMDevice to remove the pending action from
+ * @action: a static string that identifies the action
+ *
+ * Removes a pending action previously added by nm_device_add_pending_action().
+ */
void
nm_device_remove_pending_action (NMDevice *device, const char *action)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+ GQuark qaction;
+ guint i;
- priv->pending_actions--;
- nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): %s",
- nm_device_get_iface (device), priv->pending_actions, action);
+ qaction = g_quark_from_static_string (action);
- if (priv->pending_actions == 0)
- g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
+ /* Shouldn't ever add the same pending action twice */
+ for (i = 0; i < priv->pending_actions->len; i++) {
+ if (qaction == g_array_index (priv->pending_actions, GQuark, i)) {
+ g_array_remove_index_fast (priv->pending_actions, i);
+ nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s'",
+ nm_device_get_iface (device),
+ priv->pending_actions->len,
+ action);
+
+ if (priv->pending_actions->len == 0)
+ g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
+ return;
+ }
+ }
+
+ nm_log_warn (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s' never added",
+ nm_device_get_iface (device),
+ priv->pending_actions->len,
+ action);
}
gboolean
nm_device_has_pending_action (NMDevice *device)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
- return priv->pending_actions > 0;
+ return priv->pending_actions->len > 0;
}
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 6a825bc..34f438c 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -135,14 +135,20 @@ nm_active_connection_set_state (NMActiveConnection *self,
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (priv->connection),
(guint64) time (NULL), TRUE);
}
+ if (priv->device) {
+ if ( old_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED
+ && new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
+ nm_device_remove_pending_action (priv->device, "activation");
+ }
+
if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
/* Device is no longer relevant when deactivated */
g_clear_object (&priv->device);
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES);
}
}
@@ -262,8 +268,10 @@ set_property (GObject *object, guint pro
case PROP_INT_DEVICE:
g_warn_if_fail (priv->device == NULL);
priv->device = g_value_dup_object (value);
- if (priv->device)
+ if (priv->device) {
g_warn_if_fail (priv->device != priv->master);
+ nm_device_add_pending_action (priv->device, "activation");
+ }
break;
case PROP_INT_USER_REQUESTED:
priv->user_requested = g_value_get_boolean (value);
--
1.8.3.1
From 813ea5995bb5a35c115c46f30eefe18db2886afb Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Mon, 16 Dec 2013 16:52:36 +0100
Subject: [PATCH 1/2] core: allow dynamic strings for pending action names
Use a GSList of the string values, instead of an array of GQuarks.
Using GQuarks does not allow to add arbitrary strings, because they
would leak the internalized strings. The next patch will begin
using unique, non-const action strings.
Given the rather small number of expected pending states, a singly
linked list seems appropriate.
Signed-off-by: Thomas Haller <thaller@redhat.com>
(some fixes and simplifications by dcbw based on patch reviews)
---
src/devices/nm-device.c | 49 +++++++++++++++++++++++++------------------------
1 file changed, 25 insertions(+), 24 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index c1c7c69..e4644bf 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -184,15 +184,15 @@ typedef struct {
gboolean initialized;
gboolean in_state_changed;
NMDeviceState state;
NMDeviceStateReason state_reason;
QueuedState queued_state;
guint queued_ip_config_id;
- GArray *pending_actions;
+ GSList *pending_actions;
char * udi;
char * path;
char * iface; /* may change, could be renamed by user */
int ifindex;
gboolean is_software;
char * ip_iface;
@@ -391,15 +391,14 @@ nm_device_init (NMDevice *self)
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
priv->state = NM_DEVICE_STATE_UNMANAGED;
priv->state_reason = NM_DEVICE_STATE_REASON_NONE;
priv->dhcp_timeout = 0;
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
priv->autoconnect = DEFAULT_AUTOCONNECT;
priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
- priv->pending_actions = g_array_sized_new (FALSE, TRUE, sizeof (GQuark), 5);
}
static void
update_accept_ra_save (NMDevice *self)
{
NMDevicePrivate *priv;
const char *ip_iface;
@@ -5368,16 +5367,15 @@ finalize (GObject *object)
if (priv->dhcp_manager)
g_object_unref (priv->dhcp_manager);
if (priv->fw_manager)
g_object_unref (priv->fw_manager);
- g_array_free (priv->pending_actions, TRUE);
- priv->pending_actions = NULL;
+ g_slist_free_full (priv->pending_actions, g_free);
g_free (priv->udi);
g_free (priv->path);
g_free (priv->iface);
g_free (priv->ip_iface);
g_free (priv->driver);
g_free (priv->driver_version);
@@ -7153,78 +7152,80 @@ nm_device_set_hw_addr (NMDevice *device, const guint8 *addr,
*
* Adds a pending action to the device.
*/
void
nm_device_add_pending_action (NMDevice *device, const char *action)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
- GQuark qaction;
- guint i;
+ GSList *iter;
+ guint count;
- qaction = g_quark_from_static_string (action);
+ g_return_if_fail (action);
/* Shouldn't ever add the same pending action twice */
- for (i = 0; i < priv->pending_actions->len; i++) {
- if (qaction == g_array_index (priv->pending_actions, GQuark, i)) {
+ for (iter = priv->pending_actions; iter; iter = iter->next) {
+ if (!strcmp (action, iter->data)) {
nm_log_warn (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s' already added",
nm_device_get_iface (device),
- priv->pending_actions->len,
+ g_slist_length (priv->pending_actions),
action);
- g_warn_if_reached ();
- return;
+ g_return_val_if_reached (FALSE);
}
}
- g_array_prepend_val (priv->pending_actions, qaction);
+ priv->pending_actions = g_slist_append (priv->pending_actions, g_strdup (action));
+ count = g_slist_length (priv->pending_actions);
+
nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s'",
nm_device_get_iface (device),
- priv->pending_actions->len,
+ count,
action);
- if (priv->pending_actions->len == 1)
+ if (count == 1)
g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
}
/**
* nm_device_remove_pending_action():
* @device: the #NMDevice to remove the pending action from
* @action: a static string that identifies the action
*
* Removes a pending action previously added by nm_device_add_pending_action().
*/
void
nm_device_remove_pending_action (NMDevice *device, const char *action)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
- GQuark qaction;
- guint i;
+ GSList *iter;
- qaction = g_quark_from_static_string (action);
+ g_return_if_fail (action);
/* Shouldn't ever add the same pending action twice */
- for (i = 0; i < priv->pending_actions->len; i++) {
- if (qaction == g_array_index (priv->pending_actions, GQuark, i)) {
- g_array_remove_index_fast (priv->pending_actions, i);
+ for (iter = priv->pending_actions; iter; iter = iter->next) {
+ if (!strcmp (action, iter->data)) {
+ g_free (iter->data);
+ priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter);
nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s'",
nm_device_get_iface (device),
- priv->pending_actions->len,
+ g_slist_length (priv->pending_actions),
action);
- if (priv->pending_actions->len == 0)
+ if (priv->pending_actions == NULL)
g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
return;
}
}
nm_log_warn (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s' never added",
nm_device_get_iface (device),
- priv->pending_actions->len,
+ g_slist_length (priv->pending_actions),
action);
+ g_return_if_reached ();
}
gboolean
nm_device_has_pending_action (NMDevice *device)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
- return priv->pending_actions->len > 0;
+ return !!priv->pending_actions;
}
--
1.8.3.1
From b6ef165cfefba44a496cc336e1f91bb93b28f3ff Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Mon, 16 Dec 2013 15:02:38 +0100
Subject: [PATCH 2/2] core: fix NMActiveConnection to properly add/remove
pending action "activation"
When a new activation request is received, NetworkManager creates a new
NMActiveConnection to track that request. The device may already be activated,
in which case NetworkManager stops the old activation and starts the new one,
but both exist in parallel for a short period of time. If the old
NMActiveConnection is activating and already has a pending 'activation'
action, when the new NMActiveConnection adds its own 'activating' action,
they will clash. This is fixed by making each NMActiveConnection's activation
pending action uniquely named.
This fixes a g_warning with the following back trace:
#0 0x000000328224edfd in g_logv () from /lib64/libglib-2.0.so.0
#1 0x000000328224efe2 in g_log () from /lib64/libglib-2.0.so.0
#2 0x000000328224f2e6 in g_warn_message () from /lib64/libglib-2.0.so.0
#3 0x0000000000440aee in nm_device_add_pending_action (device=0x14002e0, action=0x50704a "activation") at devices/nm-device.c:7172
#4 0x000000000047525c in nm_active_connection_set_device (self=0x141b3c0, device=0x14002e0) at nm-active-connection.c:364
#5 0x0000000000475ec1 in set_property (object=0x141b3c0, prop_id=11, value=0x7fff7ff36c20, pspec=0x1405f70) at nm-active-connection.c:647
#6 0x0000003282615d3e in g_object_newv () from /lib64/libgobject-2.0.so.0
#7 0x00000032826162e6 in g_object_new_valist () from /lib64/libgobject-2.0.so.0
#8 0x0000003282616654 in g_object_new () from /lib64/libgobject-2.0.so.0
#9 0x0000000000474193 in nm_act_request_new (connection=0x13bb0e0, specific_object=0x0, subject=0x1447740, device=0x14002e0) at nm-activation-request.c:376
#10 0x000000000048e477 in _new_active_connection (self=0x13e8060, connection=0x13bb0e0, specific_object=0x0, device=0x14002e0, subject=0x1447740, error=0x7fff7ff36f90) at nm-manager.c:2947
#11 0x000000000048ed77 in impl_manager_activate_connection (self=0x13e8060, connection_path=0x134d590 "/org/freedesktop/NetworkManager/Settings/9", device_path=0x134d550 "/org/freedesktop/NetworkManager/Devices/1",
specific_object_path=0x0, context=0x143a9b0) at nm-manager.c:3206
#12 0x00000000004876c8 in dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (closure=0x7fff7ff37220, return_value=0x0, n_param_values=5, param_values=0x1448830, invocation_hint=0x0,
marshal_data=0x48e9dd <impl_manager_activate_connection>) at nm-manager-glue.h:189
#13 0x0000003284a0d6a9 in object_registration_message () from /lib64/libdbus-glib-1.so.2
#14 0x000000348ea1ce66 in _dbus_object_tree_dispatch_and_unlock () from /lib64/libdbus-1.so.3
#15 0x000000348ea0fa31 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#16 0x0000003284a0acc5 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#17 0x0000003282247df6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#18 0x0000003282248148 in g_main_context_iterate.isra.22 () from /lib64/libglib-2.0.so.0
#19 0x000000328224854a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#20 0x000000000042c6c0 in main (argc=1, argv=0x7fff7ff379b8) at main.c:629
Signed-off-by: Thomas Haller <thaller@redhat.com>
---
src/nm-active-connection.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index cb42417..a8a422c 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -42,14 +42,16 @@ G_DEFINE_ABSTRACT_TYPE (NMActiveConnection, nm_active_connection, G_TYPE_OBJECT)
NMDevice *device;
gboolean is_default;
gboolean is_default6;
NMActiveConnectionState state;
gboolean vpn;
+ char *pending_activation_id;
+
gboolean user_requested;
gulong user_uid;
NMDevice *master;
} NMActiveConnectionPrivate;
enum {
PROP_0,
@@ -138,16 +140,20 @@ nm_active_connection_set_state (NMActiveConnection *self,
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (priv->connection),
(guint64) time (NULL), TRUE);
}
if (priv->device) {
if ( old_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED
- && new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
- nm_device_remove_pending_action (priv->device, "activation");
+ && new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
+ priv->pending_activation_id)
+ {
+ nm_device_remove_pending_action (priv->device, priv->pending_activation_id);
+ g_clear_pointer (&priv->pending_activation_id, g_free);
+ }
}
if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
/* Device is no longer relevant when deactivated */
g_clear_object (&priv->device);
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES);
}
@@ -357,15 +363,16 @@ set_property (GObject *object, guint prop_id,
priv->connection = g_value_dup_object (value);
break;
case PROP_INT_DEVICE:
g_warn_if_fail (priv->device == NULL);
priv->device = g_value_dup_object (value);
if (priv->device) {
g_warn_if_fail (priv->device != priv->master);
- nm_device_add_pending_action (priv->device, "activation");
+ priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)object);
+ nm_device_add_pending_action (priv->device, priv->pending_activation_id);
}
break;
case PROP_INT_USER_REQUESTED:
priv->user_requested = g_value_get_boolean (value);
break;
case PROP_INT_USER_UID:
priv->user_uid = g_value_get_ulong (value);
@@ -732,14 +739,18 @@ static void
g_free (priv->path);
priv->path = NULL;
g_free (priv->specific_object);
priv->specific_object = NULL;
g_clear_object (&priv->connection);
+ if (priv->pending_activation_id) {
+ nm_device_remove_pending_action (priv->device, priv->pending_activation_id);
+ g_clear_pointer (&priv->pending_activation_id, g_free);
+ }
g_clear_object (&priv->device);
g_clear_object (&priv->master);
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
}
static void
--
1.8.3.1

View File

@ -0,0 +1,431 @@
From 8d3618a07baccc8abd9cfe7cf5b000b5d8c3340b Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 23 Oct 2013 18:37:02 +0200
Subject: [PATCH] rdisc: emit config_change signal for update of address
lifetime
Signed-off-by: Thomas Haller <thaller@redhat.com>
---
src/rdisc/nm-lndp-rdisc.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
index 3299b32..f94d82a 100644
--- a/src/rdisc/nm-lndp-rdisc.c
+++ b/src/rdisc/nm-lndp-rdisc.c
@@ -101,16 +101,19 @@ add_address (NMRDisc *rdisc, const NMRDiscAddress *new)
{
int i;
for (i = 0; i < rdisc->addresses->len; i++) {
NMRDiscAddress *item = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
- memcpy (item, new, sizeof (*new));
- return FALSE;
+ gboolean changed = item->timestamp + item->lifetime != new->timestamp + new->lifetime ||
+ item->timestamp + item->preferred != new->timestamp + new->preferred;
+
+ *item = *new;
+ return changed;
}
}
g_array_insert_val (rdisc->addresses, i, *new);
return TRUE;
}
--
1.8.3.1
From 4f3f789fa5dad459a2aecabd77ef4a595dec5013 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Thu, 19 Dec 2013 10:58:46 -0600
Subject: [PATCH] rdisc: ensure RDNSS and DNSSL lifetimes are updated (rh
#1044757) (bgo #720760)
The DNS server and domain timestamps and lifetimes weren't updated
when a new RA was received. When half the lifetime for either of
them had passed, clean_dns_servers() and clean_domains() request a
Router Solicitation to ensure the DNS information does not expire.
This obviously results in a new Router Advertisement, but since the
timestamps don't get updated, clean_dns_servers() and clean_domains()
simply request another solicitation because 'now' is still greater
than half the old lifetime. This casues another solicit request,
which causes another RA, which... etc.
https://bugzilla.redhat.com/show_bug.cgi?id=1044757
https://bugzilla.gnome.org/show_bug.cgi?id=720760
---
src/devices/nm-device.c | 9 +++--
src/rdisc/nm-lndp-rdisc.c | 97 +++++++++++++++++++++++++++++------------------
2 files changed, 67 insertions(+), 39 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 74d443d..6f2383b 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -3315,14 +3315,17 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
NMRDiscDNSServer *discovered_server = &g_array_index (rdisc->dns_servers, NMRDiscDNSServer, i);
nm_ip6_config_add_nameserver (priv->ac_ip6_config, &discovered_server->address);
}
}
if (changed & NM_RDISC_CONFIG_DNS_DOMAINS) {
+ /* Rebuild domain list from router discovery cache. */
+ nm_ip6_config_reset_domains (priv->ac_ip6_config);
+
for (i = 0; i < rdisc->dns_domains->len; i++) {
NMRDiscDNSDomain *discovered_domain = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i);
nm_ip6_config_add_domain (priv->ac_ip6_config, discovered_domain->domain);
}
}
@@ -3357,28 +3360,29 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
static gboolean
addrconf6_start (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMConnection *connection;
+ const char *ip_iface = nm_device_get_ip_iface (self);
connection = nm_device_get_connection (self);
g_assert (connection);
g_warn_if_fail (priv->ac_ip6_config == NULL);
if (priv->ac_ip6_config) {
g_object_unref (priv->ac_ip6_config);
priv->ac_ip6_config = NULL;
}
- priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), nm_device_get_ip_iface (self));
+ priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface);
nm_platform_sysctl_set (priv->ip6_accept_ra_path, "0");
if (!priv->rdisc) {
- nm_log_err (LOGD_IP6, "Failed to start router discovery.");
+ nm_log_err (LOGD_IP6, "(%s): failed to start router discovery.", ip_iface);
return FALSE;
}
priv->rdisc_config_changed_sigid = g_signal_connect (
priv->rdisc, NM_RDISC_CONFIG_CHANGED, G_CALLBACK (rdisc_config_changed), self);
/* FIXME: what if interface has no lladdr, like PPP? */
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
index f94d82a..2e22fd9 100644
--- a/src/rdisc/nm-lndp-rdisc.c
+++ b/src/rdisc/nm-lndp-rdisc.c
@@ -140,44 +140,68 @@ add_route (NMRDisc *rdisc, const NMRDiscRoute *new)
}
g_array_insert_val (rdisc->routes, i, *new);
return TRUE;
}
static gboolean
-add_server (NMRDisc *rdisc, const NMRDiscDNSServer *new)
+add_dns_server (NMRDisc *rdisc, const NMRDiscDNSServer *new)
{
int i;
for (i = 0; i < rdisc->dns_servers->len; i++) {
NMRDiscDNSServer *item = &g_array_index (rdisc->dns_servers, NMRDiscDNSServer, i);
- if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address))
- return FALSE;
+ if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
+ gboolean changed = item->timestamp != new->timestamp ||
+ item->lifetime != new->lifetime;
+ if (changed) {
+ item->timestamp = new->timestamp;
+ item->lifetime = new->lifetime;
+ }
+ return changed;
+ }
}
+ /* DNS server should no longer be used */
+ if (new->lifetime == 0)
+ return FALSE;
+
g_array_insert_val (rdisc->dns_servers, i, *new);
-
return TRUE;
}
+/* Always copies new->domain */
static gboolean
add_domain (NMRDisc *rdisc, const NMRDiscDNSDomain *new)
{
+ NMRDiscDNSDomain *item;
int i;
for (i = 0; i < rdisc->dns_domains->len; i++) {
- NMRDiscDNSDomain *item = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i);
+ item = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i);
- if (!g_strcmp0 (item->domain, new->domain))
- return FALSE;
+ if (!g_strcmp0 (item->domain, new->domain)) {
+ gboolean changed = item->timestamp != new->timestamp ||
+ item->lifetime != new->lifetime;
+ if (changed) {
+ item->timestamp = new->timestamp;
+ item->lifetime = new->lifetime;
+ }
+ return changed;
+ }
}
+ /* Domain should no longer be used */
+ if (new->lifetime == 0)
+ return FALSE;
+
g_array_insert_val (rdisc->dns_domains, i, *new);
-
+ item = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i);
+ item->domain = g_strdup (new->domain);
return TRUE;
}
#define RETRY 10
static gboolean
send_rs (NMRDisc *rdisc)
@@ -186,15 +210,15 @@ send_rs (NMRDisc *rdisc)
struct ndp_msg *msg;
int error;
error = ndp_msg_new (&msg, NDP_MSG_RS);
g_assert (!error);
ndp_msg_ifindex_set (msg, rdisc->ifindex);
- debug ("(%s): sending router solicitation: %d", rdisc->ifname, rdisc->ifindex);
+ debug ("(%s): sending router solicitation", rdisc->ifname);
error = ndp_msg_send (priv->ndp, msg);
if (error)
error ("(%s): cannot send router solicitation: %d.", rdisc->ifname, error);
ndp_msg_destroy (msg);
@@ -218,139 +242,140 @@ solicit (NMRDisc *rdisc)
static void
clean_gateways (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap *changed, guint32 *nextevent)
{
int i;
for (i = 0; i < rdisc->gateways->len; i++) {
NMRDiscGateway *item = &g_array_index (rdisc->gateways, NMRDiscGateway, i);
- guint32 expiry = item->timestamp + item->lifetime;
+ guint64 expiry = item->timestamp + item->lifetime;
- if (item->lifetime == UINT_MAX)
+ if (item->lifetime == G_MAXUINT32)
continue;
if (now >= expiry) {
g_array_remove_index (rdisc->gateways, i--);
*changed |= NM_RDISC_CONFIG_GATEWAYS;
} else if (*nextevent > expiry)
- *nextevent = expiry;
+ *nextevent = (guint32) expiry;
}
}
static void
clean_addresses (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap *changed, guint32 *nextevent)
{
int i;
for (i = 0; i < rdisc->addresses->len; i++) {
NMRDiscAddress *item = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
- guint32 expiry = item->timestamp + item->lifetime;
+ guint64 expiry = item->timestamp + item->lifetime;
- if (item->lifetime == UINT_MAX)
+ if (item->lifetime == G_MAXUINT32)
continue;
if (now >= expiry) {
g_array_remove_index (rdisc->addresses, i--);
*changed |= NM_RDISC_CONFIG_ADDRESSES;
} else if (*nextevent > expiry)
- *nextevent = expiry;
+ *nextevent = (guint32) expiry;
}
}
static void
clean_routes (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap *changed, guint32 *nextevent)
{
int i;
for (i = 0; i < rdisc->routes->len; i++) {
NMRDiscRoute *item = &g_array_index (rdisc->routes, NMRDiscRoute, i);
- guint32 expiry = item->timestamp + item->lifetime;
+ guint64 expiry = item->timestamp + item->lifetime;
- if (item->lifetime == UINT_MAX)
+ if (item->lifetime == G_MAXUINT32)
continue;
if (now >= expiry) {
g_array_remove_index (rdisc->routes, i--);
*changed |= NM_RDISC_CONFIG_ROUTES;
} else if (*nextevent > expiry)
- *nextevent = expiry;
+ *nextevent = (guint32) expiry;
}
}
static void
-clean_servers (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap *changed, guint32 *nextevent)
+clean_dns_servers (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap *changed, guint32 *nextevent)
{
int i;
for (i = 0; i < rdisc->dns_servers->len; i++) {
NMRDiscDNSServer *item = &g_array_index (rdisc->dns_servers, NMRDiscDNSServer, i);
- guint32 expiry = item->timestamp + item->lifetime;
- guint32 refresh = item->timestamp + item->lifetime / 2;
+ guint64 expiry = item->timestamp + item->lifetime;
+ guint64 refresh = item->timestamp + item->lifetime / 2;
- if (item->lifetime == UINT_MAX)
+ if (item->lifetime == G_MAXUINT32)
continue;
if (now >= expiry) {
g_array_remove_index (rdisc->dns_servers, i--);
- *changed |= NM_RDISC_CONFIG_ROUTES;
+ *changed |= NM_RDISC_CONFIG_DNS_SERVERS;
} else if (now >= refresh)
solicit (rdisc);
else if (*nextevent > refresh)
- *nextevent = refresh;
+ *nextevent = (guint32) refresh;
}
}
static void
clean_domains (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap *changed, guint32 *nextevent)
{
int i;
for (i = 0; i < rdisc->dns_domains->len; i++) {
NMRDiscDNSDomain *item = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i);
- guint32 expiry = item->timestamp + item->lifetime;
- guint32 refresh = item->timestamp + item->lifetime / 2;
+ guint64 expiry = item->timestamp + item->lifetime;
+ guint64 refresh = item->timestamp + item->lifetime / 2;
- if (item->lifetime == UINT_MAX)
+ if (item->lifetime == G_MAXUINT32)
continue;
if (now >= expiry) {
+ g_free (item->domain);
g_array_remove_index (rdisc->dns_domains, i--);
- *changed |= NM_RDISC_CONFIG_ROUTES;
+ *changed |= NM_RDISC_CONFIG_DNS_DOMAINS;
} else if (now >= refresh)
solicit (rdisc);
else if (*nextevent >=refresh)
- *nextevent = refresh;
+ *nextevent = (guint32) refresh;
}
}
static gboolean timeout_cb (gpointer user_data);
static void
check_timestamps (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap changed)
{
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
- /* Use a magic date in distant enough future as there's no guint32 max macro. */
- guint32 never = G_MAXINT32;
+ /* Use a magic date in the distant future (~68 years) */
+ guint32 never = G_MAXINT32;
guint32 nextevent = never;
if (priv->timeout_id) {
g_source_remove (priv->timeout_id);
priv->timeout_id = 0;
}
clean_gateways (rdisc, now, &changed, &nextevent);
clean_addresses (rdisc, now, &changed, &nextevent);
clean_routes (rdisc, now, &changed, &nextevent);
- clean_servers (rdisc, now, &changed, &nextevent);
+ clean_dns_servers (rdisc, now, &changed, &nextevent);
clean_domains (rdisc, now, &changed, &nextevent);
if (changed)
g_signal_emit_by_name (rdisc, NM_RDISC_CONFIG_CHANGED, changed);
if (nextevent != never) {
- debug ("Scheduling next now/lifetime check: %d seconds", (int) nextevent);
+ debug ("(%s): scheduling next now/lifetime check: %u seconds", rdisc->ifname, nextevent);
priv->timeout_id = g_timeout_add_seconds (nextevent, timeout_cb, rdisc);
}
}
static guint32
get_time (void)
{
@@ -450,15 +475,15 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
*
* The biggest difference from good old DHCP is that all configuration
* items have their own lifetimes and they are merged from various
* sources. Router discovery is *not* contract-based, so there is *no*
* single time when the configuration is finished and updates can
* come at any time.
*/
- debug ("Recieved router advertisement: %d at %d", rdisc->ifindex, (int) now);
+ debug ("(%s): received router advertisement at %u", rdisc->ifname, now);
if (priv->send_rs_id) {
g_source_remove (priv->send_rs_id);
priv->send_rs_id = 0;
}
/* DHCP level:
@@ -559,27 +584,27 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
/* Pad the lifetime somewhat to give a bit of slack in cases
* where one RA gets lost or something (which can happen on unreliable
* links like WiFi where certain types of frames are not retransmitted).
* Note that 0 has special meaning and is therefore not adjusted.
*/
if (dns_server.lifetime && dns_server.lifetime < 7200)
dns_server.lifetime = 7200;
- if (add_server (rdisc, &dns_server))
+ if (add_dns_server (rdisc, &dns_server))
changed |= NM_RDISC_CONFIG_DNS_SERVERS;
}
}
ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_DNSSL) {
char *domain;
int domain_index;
ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) {
NMRDiscDNSDomain dns_domain;
memset (&dns_domain, 0, sizeof (dns_domain));
- dns_domain.domain = g_strdup (domain);
+ dns_domain.domain = domain;
dns_domain.timestamp = now;
dns_domain.lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset);
/* Pad the lifetime somewhat to give a bit of slack in cases
* where one RA gets lost or something (which can happen on unreliable
* links like WiFi where certain types of frames are not retransmitted).
* Note that 0 has special meaning and is therefore not adjusted.
*/
--
1.8.3.1

View File

@ -0,0 +1,21 @@
diff -up NetworkManager-0.9.9.0/src/bluez-manager/nm-bluez-device.c.bluez-crash NetworkManager-0.9.9.0/src/bluez-manager/nm-bluez-device.c
--- NetworkManager-0.9.9.0/src/bluez-manager/nm-bluez-device.c.bluez-crash 2013-10-03 15:00:51.000000000 -0400
+++ NetworkManager-0.9.9.0/src/bluez-manager/nm-bluez-device.c 2014-01-06 12:09:14.449583005 -0500
@@ -686,7 +686,7 @@ static void
on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
{
NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
- GError *error;
+ GError *error = NULL;
GVariant *v;
priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error);
@@ -923,7 +923,7 @@ static void
on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
{
NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
- GError *error;
+ GError *error = NULL;
priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error);