From 93c10b457c1e50504149754c37e27b7daaf93b9f Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Jan 10 2014 18:26:34 +0000 Subject: Merge commit 'd9c5764ddb7a90f57a3d13b542bafada9beb6d92' Conflicts: NetworkManager.spec --- diff --git a/.gitignore b/.gitignore index eff6012..778ec86 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/NetworkManager.spec b/NetworkManager.spec index 0484c57..a5fcfbf 100644 --- a/NetworkManager.spec +++ b/NetworkManager.spec @@ -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 - 0.9.9.0-23.git20131003 +- bluez-manager: fix a crash (rh #1048711) + +* Thu Dec 19 2013 Dan Williams - 0.9.9.0-22.git20131003 +- core: fix IPv6 router solicitation loop (rh #1044757) + +* Thu Dec 12 2013 Dan Williams - 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 - 0.9.9.0-20.git20131003 +- core: Fix PtP/peer address support, for OpenVPN (rh #1018317) + +>>>>>>> d9c5764ddb7a90f57a3d13b542bafada9beb6d92 * Wed Nov 20 2013 Jiří Klimeš - 0.9.9.0-19.git20131003 - dispatcher: fix crash on exit while logging from signal handler (rh #1017884) - core: workaround crash when connecting to wifi (rh #1025371) diff --git a/rh1018317-openvpn-ptp.patch b/rh1018317-openvpn-ptp.patch new file mode 100644 index 0000000..09c9a6b --- /dev/null +++ b/rh1018317-openvpn-ptp.patch @@ -0,0 +1,857 @@ +From fec50bd5fad633e57bfd6f9ee480e6192504ca5f Mon Sep 17 00:00:00 2001 +From: Dan Winship +Date: Mon, 2 Dec 2013 10:20:26 -0500 +Subject: [PATCH] platform/core: add back support for PtP/peer addresses (rh + #1018317) + +In the migration to NMPlatform, support for ptp/peer addresses was +accidentally dropped. This broke OpenVPN configurations using 'p2p' +topology, which send a different peer address than the local address +for tunX, plus the server may also push routes that use the peer +address as the next hop. NetworkManager was unable to add these +routes, because the kernel had no idea how to talk to the peer, +because the peer's address was not assigned to any interface or +reachable over any routes. + +Partly based on a patch from Dan Williams. +--- + src/nm-ip4-config.c | 44 +--------------------------- + src/nm-ip4-config.h | 4 --- + src/nm-ip6-config.c | 49 ------------------------------- + src/nm-ip6-config.h | 4 --- + src/platform/nm-fake-platform.c | 10 +++++-- + src/platform/nm-linux-platform.c | 58 ++++++++++++++++++++++++++++++++----- + src/platform/nm-platform.c | 26 +++++++++++++---- + src/platform/nm-platform.h | 14 ++++++--- + src/platform/tests/platform.c | 4 +-- + src/platform/tests/test-address.c | 12 ++++---- + src/platform/tests/test-cleanup.c | 4 +-- + src/ppp-manager/nm-ppp-manager.c | 2 +- + src/tests/test-dhcp-options.c | 5 ++-- + src/tests/test-ip4-config.c | 12 ++++---- + src/tests/test-ip6-config.c | 13 ++++----- + src/vpn-manager/nm-vpn-connection.c | 10 +++---- + 16 files changed, 118 insertions(+), 153 deletions(-) + +diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c +index 7aff888..640a1e1 100644 +--- a/src/nm-ip4-config.c ++++ b/src/nm-ip4-config.c +@@ -47,7 +47,6 @@ typedef struct { + GPtrArray *domains; + GPtrArray *searches; + guint32 mss; +- guint32 ptp_address; + GArray *nis; + char *nis_domain; + GArray *wins; +@@ -454,10 +453,6 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) + for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) + nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i)); + +- /* ptp address; only replace if src doesn't have one */ +- if (!nm_ip4_config_get_ptp_address (dst)) +- nm_ip4_config_set_ptp_address (dst, nm_ip4_config_get_ptp_address (src)); +- + /* nameservers */ + for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) + nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i)); +@@ -527,10 +522,6 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) + } + } + +- /* ptp address */ +- if (nm_ip4_config_get_ptp_address (src) == nm_ip4_config_get_ptp_address (dst)) +- nm_ip4_config_set_ptp_address (dst, 0); +- + /* nameservers */ + for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) { + guint32 src_ns = nm_ip4_config_get_nameserver (src, i); +@@ -788,12 +779,6 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev + has_minor_changes = TRUE; + } + +- /* ptp address */ +- if (src_priv->ptp_address != dst_priv->ptp_address) { +- dst_priv->ptp_address = src_priv->ptp_address; +- has_relevant_changes = TRUE; +- } +- + /* nis */ + num = nm_ip4_config_get_num_nis_servers (src); + are_equal = num == nm_ip4_config_get_num_nis_servers (dst); +@@ -873,11 +858,6 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) + } + } + +- /* ptp address */ +- tmp = nm_ip4_config_get_ptp_address (config); +- if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf))) +- g_message (" ptp: %s", buf); +- + /* default gateway */ + tmp = nm_ip4_config_get_gateway (config); + if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf))) +@@ -1314,24 +1294,6 @@ nm_ip4_config_get_mss (const NMIP4Config *config) + /******************************************************************/ + + void +-nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr) +-{ +- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); +- +- priv->ptp_address = ptp_addr; +-} +- +-guint32 +-nm_ip4_config_get_ptp_address (const NMIP4Config *config) +-{ +- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); +- +- return priv->ptp_address; +-} +- +-/******************************************************************/ +- +-void + nm_ip4_config_reset_nis_servers (NMIP4Config *config) + { + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); +@@ -1480,7 +1442,7 @@ hash_u32 (GChecksum *sum, guint32 n) + void + nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only) + { +- guint32 i, n; ++ guint32 i; + const char *s; + + g_return_if_fail (config); +@@ -1504,10 +1466,6 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only + hash_u32 (sum, route->metric); + } + +- n = nm_ip4_config_get_ptp_address (config); +- if (n) +- hash_u32 (sum, n); +- + for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++) + hash_u32 (sum, nm_ip4_config_get_nis_server (config, i)); + +diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h +index 5b76fb4..d57cd52 100644 +--- a/src/nm-ip4-config.h ++++ b/src/nm-ip4-config.h +@@ -117,10 +117,6 @@ const char * nm_ip4_config_get_search (const NMIP4Config *config, guint i); + void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); + guint32 nm_ip4_config_get_mss (const NMIP4Config *config); + +-/* PTP */ +-void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr); +-guint32 nm_ip4_config_get_ptp_address (const NMIP4Config *config); +- + /* NIS */ + void nm_ip4_config_reset_nis_servers (NMIP4Config *config); + void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis); +diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c +index 65cbd0b..8eb79f2 100644 +--- a/src/nm-ip6-config.c ++++ b/src/nm-ip6-config.c +@@ -47,7 +47,6 @@ typedef struct { + GPtrArray *domains; + GPtrArray *searches; + guint32 mss; +- struct in6_addr ptp_address; + } NMIP6ConfigPrivate; + + +@@ -457,10 +456,6 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src) + for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) + nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i)); + +- /* ptp address; only replace if src doesn't have one */ +- if (!nm_ip6_config_get_ptp_address (dst)) +- nm_ip6_config_set_ptp_address (dst, nm_ip6_config_get_ptp_address (src)); +- + /* nameservers */ + for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) + nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i)); +@@ -535,12 +530,6 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) + } + } + +- /* ptp address */ +- src_tmp = nm_ip6_config_get_ptp_address (src); +- dst_tmp = nm_ip6_config_get_ptp_address (dst); +- if (src_tmp && dst_tmp && IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp)) +- nm_ip6_config_set_ptp_address (dst, NULL); +- + /* nameservers */ + for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) { + const struct in6_addr *src_ns = nm_ip6_config_get_nameserver (src, i); +@@ -769,12 +758,6 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev + has_minor_changes = TRUE; + } + +- /* ptp address */ +- if (!IN6_ARE_ADDR_EQUAL (&src_priv->ptp_address, &dst_priv->ptp_address)) { +- nm_ip6_config_set_ptp_address (dst, &src_priv->ptp_address); +- has_relevant_changes = TRUE; +- } +- + /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes + * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ + g_assert (config_equal == !has_relevant_changes); +@@ -1219,28 +1197,6 @@ nm_ip6_config_get_mss (const NMIP6Config *config) + + /******************************************************************/ + +-void +-nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_address) +-{ +- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); +- +- if (ptp_address) +- priv->ptp_address = *ptp_address; +- else +- memset (&priv->ptp_address, 0, sizeof (priv->ptp_address)); +- +-} +- +-const struct in6_addr * +-nm_ip6_config_get_ptp_address (const NMIP6Config *config) +-{ +- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); +- +- return IN6_IS_ADDR_UNSPECIFIED (&priv->ptp_address) ? NULL : &priv->ptp_address; +-} +- +-/******************************************************************/ +- + static inline void + hash_u32 (GChecksum *sum, guint32 n) + { +@@ -1260,7 +1216,6 @@ void + nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only) + { + guint32 i; +- const struct in6_addr *in6a; + const char *s; + + g_return_if_fail (config); +@@ -1284,10 +1239,6 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only + hash_in6addr (sum, &route->gateway); + hash_u32 (sum, route->metric); + } +- +- in6a = nm_ip6_config_get_ptp_address (config); +- if (in6a) +- hash_in6addr (sum, in6a); + } + + for (i = 0; i < nm_ip6_config_get_num_nameservers (config); i++) +diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h +index aecdab2..eb93d07 100644 +--- a/src/nm-ip6-config.h ++++ b/src/nm-ip6-config.h +@@ -116,10 +116,6 @@ const char * nm_ip6_config_get_search (const NMIP6Config *config, guint i); + void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss); + guint32 nm_ip6_config_get_mss (const NMIP6Config *config); + +-/* PTP */ +-void nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_addr); +-const struct in6_addr *nm_ip6_config_get_ptp_address (const NMIP6Config *config); +- + void nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only); + gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b); + +diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c +index df5d5b8..dcbf932 100644 +--- a/src/platform/nm-fake-platform.c ++++ b/src/platform/nm-fake-platform.c +@@ -739,7 +739,9 @@ get_time (void) + } + + static gboolean +-ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred) ++ip4_address_add (NMPlatform *platform, int ifindex, ++ in_addr_t addr, in_addr_t peer_addr, ++ int plen, guint32 lifetime, guint32 preferred) + { + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP4Address address; +@@ -748,6 +750,7 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, gu + memset (&address, 0, sizeof (address)); + address.ifindex = ifindex; + address.address = addr; ++ address.peer_address = peer_addr; + address.plen = plen; + address.timestamp = get_time (); + address.lifetime = lifetime; +@@ -775,7 +778,9 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, gu + } + + static gboolean +-ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred, guint flags) ++ip6_address_add (NMPlatform *platform, int ifindex, ++ struct in6_addr addr, struct in6_addr peer_addr, ++ int plen, guint32 lifetime, guint32 preferred, guint flags) + { + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP6Address address; +@@ -784,6 +789,7 @@ ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int pl + memset (&address, 0, sizeof (address)); + address.ifindex = ifindex; + address.address = addr; ++ address.peer_address = peer_addr; + address.plen = plen; + address.timestamp = get_time (); + address.lifetime = lifetime; +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index d13abbe..50b027a 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -764,6 +764,7 @@ static void + init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr) + { + struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr); ++ struct nl_addr *nlpeer = rtnl_addr_get_peer (rtnladdr); + + g_assert (nladdr); + +@@ -776,12 +777,17 @@ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr) + address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr); + g_assert (nl_addr_get_len (nladdr) == sizeof (address->address)); + memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address)); ++ if (nlpeer) { ++ g_assert (nl_addr_get_len (nlpeer) == sizeof (address->peer_address)); ++ memcpy (&address->peer_address, nl_addr_get_binary_addr (nlpeer), sizeof (address->peer_address)); ++ } + } + + static void + init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr) + { + struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr); ++ struct nl_addr *nlpeer = rtnl_addr_get_peer (rtnladdr); + + memset (address, 0, sizeof (*address)); + +@@ -793,6 +799,10 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr) + address->flags = rtnl_addr_get_flags (rtnladdr); + g_assert (nl_addr_get_len (nladdr) == sizeof (address->address)); + memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address)); ++ if (nlpeer) { ++ g_assert (nl_addr_get_len (nlpeer) == sizeof (address->peer_address)); ++ memcpy (&address->peer_address, nl_addr_get_binary_addr (nlpeer), sizeof (address->peer_address)); ++ } + } + + static gboolean +@@ -2208,7 +2218,14 @@ ip6_address_get_all (NMPlatform *platform, int ifindex) + } + + static struct nl_object * +-build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 lifetime, guint32 preferred, guint flags) ++build_rtnl_addr (int family, ++ int ifindex, ++ gconstpointer addr, ++ gconstpointer peer_addr, ++ int plen, ++ guint32 lifetime, ++ guint32 preferred, ++ guint flags) + { + struct rtnl_addr *rtnladdr = rtnl_addr_alloc (); + int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr); +@@ -2220,6 +2237,14 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 + rtnl_addr_set_ifindex (rtnladdr, ifindex); + nle = rtnl_addr_set_local (rtnladdr, nladdr); + g_assert (!nle); ++ ++ if (peer_addr) { ++ auto_nl_addr struct nl_addr *nlpeer = nl_addr_build (family, peer_addr, addrlen); ++ ++ nle = rtnl_addr_set_peer (rtnladdr, nlpeer); ++ g_assert (!nle); ++ } ++ + rtnl_addr_set_prefixlen (rtnladdr, plen); + if (lifetime) { + rtnl_addr_set_valid_lifetime (rtnladdr, lifetime); +@@ -2232,33 +2257,50 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 + } + + static gboolean +-ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred) ++ip4_address_add (NMPlatform *platform, ++ int ifindex, ++ in_addr_t addr, ++ in_addr_t peer_addr, ++ int plen, ++ guint32 lifetime, ++ guint32 preferred) + { +- return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, lifetime, preferred, 0)); ++ return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, ++ peer_addr ? &peer_addr : NULL, ++ plen, lifetime, preferred, 0)); + } + + static gboolean +-ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred, guint flags) ++ip6_address_add (NMPlatform *platform, ++ int ifindex, ++ struct in6_addr addr, ++ struct in6_addr peer_addr, ++ int plen, ++ guint32 lifetime, ++ guint32 preferred, ++ guint flags) + { +- return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, lifetime, preferred, flags)); ++ return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, ++ memcmp (&peer_addr, &in6addr_any, sizeof (struct in6_addr)) == 0 ? NULL : &peer_addr, ++ plen, lifetime, preferred, flags)); + } + + static gboolean + ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) + { +- return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, 0, 0, 0)); ++ return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, NULL, plen, 0, 0, 0)); + } + + static gboolean + ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) + { +- return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, 0, 0, 0)); ++ return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, NULL, plen, 0, 0, 0)); + } + + static gboolean + ip_address_exists (NMPlatform *platform, int family, int ifindex, gconstpointer addr, int plen) + { +- auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, plen, 0, 0, 0); ++ auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, NULL, plen, 0, 0, 0); + auto_nl_object struct nl_object *cached_object = nl_cache_search (choose_cache (platform, object), object); + + return !!cached_object; +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index 3f7f054..4e9c8fc 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -1165,7 +1165,12 @@ nm_platform_ip6_address_get_all (int ifindex) + } + + gboolean +-nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, guint32 lifetime, guint32 preferred) ++nm_platform_ip4_address_add (int ifindex, ++ in_addr_t address, ++ in_addr_t peer_address, ++ int plen, ++ guint32 lifetime, ++ guint32 preferred) + { + reset_error (); + +@@ -1175,11 +1180,17 @@ nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, guint32 l + g_return_val_if_fail (klass->ip4_address_add, FALSE); + + debug ("address: adding or updating IPv4 address"); +- return klass->ip4_address_add (platform, ifindex, address, plen, lifetime, preferred); ++ return klass->ip4_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred); + } + + gboolean +-nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, guint32 lifetime, guint32 preferred, guint flags) ++nm_platform_ip6_address_add (int ifindex, ++ struct in6_addr address, ++ struct in6_addr peer_address, ++ int plen, ++ guint32 lifetime, ++ guint32 preferred, ++ guint flags) + { + reset_error (); + +@@ -1189,7 +1200,7 @@ nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, gui + g_return_val_if_fail (klass->ip6_address_add, FALSE); + + debug ("address: adding or updating IPv6 address"); +- return klass->ip6_address_add (platform, ifindex, address, plen, lifetime, preferred, flags); ++ return klass->ip6_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred, flags); + } + + gboolean +@@ -1350,7 +1361,7 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses) + } else + lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT; + +- if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->plen, lifetime, preferred)) ++ if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred)) + return FALSE; + } + +@@ -1407,7 +1418,8 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses) + } else + lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT; + +- if (!nm_platform_ip6_address_add (ifindex, known_address->address, known_address->plen, ++ if (!nm_platform_ip6_address_add (ifindex, known_address->address, ++ known_address->peer_address, known_address->plen, + lifetime, preferred, known_address->flags)) + return FALSE; + } +@@ -1843,6 +1855,7 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A + { + _CMP_POINTER (a, b); + _CMP_FIELD_MEMCMP (a, b, address); ++ _CMP_FIELD_MEMCMP (a, b, peer_address); + _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, timestamp); +@@ -1857,6 +1870,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A + _CMP_POINTER (a, b); + _CMP_FIELD (a, b, ifindex); + _CMP_FIELD_MEMCMP (a, b, address); ++ _CMP_FIELD_MEMCMP (a, b, peer_address); + _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, timestamp); + _CMP_FIELD (a, b, lifetime); +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index ff338fc..b742c39 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -122,6 +122,7 @@ typedef struct { + typedef struct { + int ifindex; + in_addr_t address; ++ in_addr_t peer_address; /* PTP peer address */ + int plen; + guint32 timestamp; + guint32 lifetime; +@@ -131,6 +132,7 @@ typedef struct { + typedef struct { + int ifindex; + struct in6_addr address; ++ struct in6_addr peer_address; + int plen; + guint32 timestamp; + guint32 lifetime; +@@ -280,9 +282,11 @@ typedef struct { + + GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex); + GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex); +- gboolean (*ip4_address_add) (NMPlatform *, int ifindex, in_addr_t address, int plen, +- guint32 lifetime, guint32 preferred_lft); +- gboolean (*ip6_address_add) (NMPlatform *, int ifindex, struct in6_addr address, int plen, ++ gboolean (*ip4_address_add) (NMPlatform *, int ifindex, ++ in_addr_t address, in_addr_t peer_address, int plen, ++ guint32 lifetime, guint32 preferred_lft); ++ gboolean (*ip6_address_add) (NMPlatform *, int ifindex, ++ struct in6_addr address, struct in6_addr peer_address, int plen, + guint32 lifetime, guint32 preferred_lft, guint flags); + gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen); + gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen); +@@ -402,9 +406,11 @@ gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *p + + GArray *nm_platform_ip4_address_get_all (int ifindex); + GArray *nm_platform_ip6_address_get_all (int ifindex); +-gboolean nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, +- guint32 lifetime, guint32 preferred_lft); +-gboolean nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, ++gboolean nm_platform_ip4_address_add (int ifindex, ++ in_addr_t address, in_addr_t peer_address, int plen, ++ guint32 lifetime, guint32 preferred_lft); ++gboolean nm_platform_ip6_address_add (int ifindex, ++ struct in6_addr address, struct in6_addr peer_address, int plen, + guint32 lifetime, guint32 preferred_lft, guint flags); + gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen); + gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen); +diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c +index c0b2c02..7ca2cb5 100644 +--- a/src/platform/tests/platform.c ++++ b/src/platform/tests/platform.c +@@ -523,7 +523,7 @@ do_ip4_address_add (char **argv) + guint32 lifetime = strtol (*argv++, NULL, 10); + guint32 preferred = strtol (*argv++, NULL, 10); + +- gboolean value = nm_platform_ip4_address_add (ifindex, address, plen, lifetime, preferred); ++ gboolean value = nm_platform_ip4_address_add (ifindex, address, 0, plen, lifetime, preferred); + return value; + } else + return FALSE; +@@ -541,7 +541,7 @@ do_ip6_address_add (char **argv) + guint32 preferred = strtol (*argv++, NULL, 10); + guint flags = (*argv) ? rtnl_addr_str2flags (*argv++) : 0; + +- gboolean value = nm_platform_ip6_address_add (ifindex, address, plen, lifetime, preferred, flags); ++ gboolean value = nm_platform_ip6_address_add (ifindex, address, in6addr_any, plen, lifetime, preferred, flags); + return value; + } else + return FALSE; +diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c +index 52952c3..0f0ccc8 100644 +--- a/src/platform/tests/test-address.c ++++ b/src/platform/tests/test-address.c +@@ -60,14 +60,14 @@ test_ip4_address (void) + /* Add address */ + g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); + no_error (); +- g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred)); ++ g_assert (nm_platform_ip4_address_add (ifindex, addr, 0, IP4_PLEN, lifetime, preferred)); + no_error (); + g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); + no_error (); + accept_signal (address_added); + + /* Add address again (aka update) */ +- g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred)); ++ g_assert (nm_platform_ip4_address_add (ifindex, addr, 0, IP4_PLEN, lifetime, preferred)); + no_error (); + accept_signal (address_changed); + +@@ -116,14 +116,14 @@ test_ip6_address (void) + /* Add address */ + g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); + no_error (); +- g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags)); ++ g_assert (nm_platform_ip6_address_add (ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); + no_error (); + g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); + no_error (); + accept_signal (address_added); + + /* Add address again (aka update) */ +- g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags)); ++ g_assert (nm_platform_ip6_address_add (ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); + no_error (); + accept_signal (address_changed); + +@@ -183,7 +183,7 @@ test_ip4_address_external (void) + /* Add/delete conflict */ + run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", + IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred); +- g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred)); ++ g_assert (nm_platform_ip4_address_add (ifindex, addr, 0, IP4_PLEN, lifetime, preferred)); + no_error (); + g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); + accept_signal (address_added); +@@ -222,7 +222,7 @@ test_ip6_address_external (void) + /* Add/delete conflict */ + run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", + IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred); +- g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred, flags)); ++ g_assert (nm_platform_ip6_address_add (ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); + no_error (); + g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); + accept_signal (address_added); +diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c +index f102870..d94b359 100644 +--- a/src/platform/tests/test-cleanup.c ++++ b/src/platform/tests/test-cleanup.c +@@ -41,8 +41,8 @@ test_cleanup_internal () + g_assert (ifindex > 0); + + /* Add routes and addresses */ +- g_assert (nm_platform_ip4_address_add (ifindex, addr4, plen4, lifetime, preferred)); +- g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6, lifetime, preferred, flags)); ++ g_assert (nm_platform_ip4_address_add (ifindex, addr4, 0, plen4, lifetime, preferred)); ++ g_assert (nm_platform_ip6_address_add (ifindex, addr6, in6addr_any, plen6, lifetime, preferred, flags)); + g_assert (nm_platform_ip4_route_add (ifindex, gateway4, 32, INADDR_ANY, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, network4, plen4, gateway4, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway4, metric, mss)); +diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c +index ffb1e74..b2f2326 100644 +--- a/src/ppp-manager/nm-ppp-manager.c ++++ b/src/ppp-manager/nm-ppp-manager.c +@@ -538,7 +538,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, + val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_GATEWAY); + if (val) { + nm_ip4_config_set_gateway (config, g_value_get_uint (val)); +- nm_ip4_config_set_ptp_address (config, g_value_get_uint (val)); ++ address.peer_address = g_value_get_uint (val); + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_ADDRESS); +diff --git a/src/tests/test-dhcp-options.c b/src/tests/test-dhcp-options.c +index effe658..6ef599e 100644 +--- a/src/tests/test-dhcp-options.c ++++ b/src/tests/test-dhcp-options.c +@@ -129,6 +129,8 @@ test_generic_options (const char *client) + "dhcp-generic", "couldn't convert expected IP address"); + ASSERT (address->address == tmp, + "dhcp-generic", "unexpected IP address"); ++ ASSERT (address->peer_address == 0, ++ "dhcp-generic", "unexpected PTP address"); + + ASSERT (address->plen == 24, + "dhcp-generic", "unexpected IP address prefix length"); +@@ -139,9 +141,6 @@ test_generic_options (const char *client) + ASSERT (nm_ip4_config_get_gateway (ip4_config) == tmp, + "dhcp-generic", "unexpected IP gateway"); + +- ASSERT (nm_ip4_config_get_ptp_address (ip4_config) == 0, +- "dhcp-generic", "unexpected PTP address"); +- + ASSERT (nm_ip4_config_get_num_wins (ip4_config) == 0, + "dhcp-generic", "unexpected number of WINS servers"); + +diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c +index 331897c..fde4a40 100644 +--- a/src/tests/test-ip4-config.c ++++ b/src/tests/test-ip4-config.c +@@ -25,10 +25,12 @@ + #include "nm-ip4-config.h" + + static void +-addr_init (NMPlatformIP4Address *a, const char *addr, guint plen) ++addr_init (NMPlatformIP4Address *a, const char *addr, const char *peer, guint plen) + { + memset (a, 0, sizeof (*a)); + g_assert (inet_pton (AF_INET, addr, (void *) &a->address) == 1); ++ if (peer) ++ g_assert (inet_pton (AF_INET, peer, (void *) &a->peer_address) == 1); + a->plen = plen; + } + +@@ -68,7 +70,7 @@ build_test_config (void) + /* Build up the config to subtract */ + config = nm_ip4_config_new (); + +- addr_init (&addr, "192.168.1.10", 24); ++ addr_init (&addr, "192.168.1.10", "1.2.3.4", 24); + nm_ip4_config_add_address (config, &addr); + + route_new (&route, "10.0.0.0", 8, "192.168.1.1"); +@@ -86,8 +88,6 @@ build_test_config (void) + nm_ip4_config_add_search (config, "blahblah.com"); + nm_ip4_config_add_search (config, "beatbox.com"); + +- nm_ip4_config_set_ptp_address (config, addr_to_num ("1.2.3.4")); +- + nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.9")); + nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.10")); + +@@ -121,7 +121,7 @@ test_subtract (void) + + /* add a couple more things to the test config */ + dst = build_test_config (); +- addr_init (&addr, expected_addr, expected_addr_plen); ++ addr_init (&addr, expected_addr, NULL, expected_addr_plen); + nm_ip4_config_add_address (dst, &addr); + + route_new (&route, expected_route_dest, expected_route_plen, expected_route_next_hop); +@@ -142,9 +142,9 @@ test_subtract (void) + test_addr = nm_ip4_config_get_address (dst, 0); + g_assert (test_addr != NULL); + g_assert_cmpuint (test_addr->address, ==, addr_to_num (expected_addr)); ++ g_assert_cmpuint (test_addr->peer_address, ==, 0); + g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen); + +- g_assert_cmpuint (nm_ip4_config_get_ptp_address (dst), ==, 0); + g_assert_cmpuint (nm_ip4_config_get_gateway (dst), ==, 0); + + g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1); +diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c +index 10ce3bf..b8b9c7b 100644 +--- a/src/tests/test-ip6-config.c ++++ b/src/tests/test-ip6-config.c +@@ -25,10 +25,12 @@ + #include "nm-ip6-config.h" + + static void +-addr_init (NMPlatformIP6Address *a, const char *addr, guint plen) ++addr_init (NMPlatformIP6Address *a, const char *addr, const char *peer, guint plen) + { + memset (a, 0, sizeof (*a)); + g_assert (inet_pton (AF_INET6, addr, (void *) &a->address) == 1); ++ if (peer) ++ g_assert (inet_pton (AF_INET6, peer, (void *) &a->peer_address) == 1); + a->plen = plen; + } + +@@ -61,7 +63,7 @@ build_test_config (void) + /* Build up the config to subtract */ + config = nm_ip6_config_new (); + +- addr_init (&addr, "abcd:1234:4321::cdde", 64); ++ addr_init (&addr, "abcd:1234:4321::cdde", "1:2:3:4::5", 64); + nm_ip6_config_add_address (config, &addr); + + route_new (&route, "abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2"); +@@ -82,9 +84,6 @@ build_test_config (void) + nm_ip6_config_add_search (config, "blahblah.com"); + nm_ip6_config_add_search (config, "beatbox.com"); + +- addr_to_num ("1:2:3:4::5", &tmp); +- nm_ip6_config_set_ptp_address (config, &tmp); +- + return config; + } + +@@ -111,7 +110,7 @@ test_subtract (void) + + /* add a couple more things to the test config */ + dst = build_test_config (); +- addr_init (&addr, expected_addr, expected_addr_plen); ++ addr_init (&addr, expected_addr, NULL, expected_addr_plen); + nm_ip6_config_add_address (dst, &addr); + + route_new (&route, expected_route_dest, expected_route_plen, expected_route_next_hop); +@@ -133,9 +132,9 @@ test_subtract (void) + g_assert (test_addr != NULL); + addr_to_num (expected_addr, &tmp); + g_assert (memcmp (&test_addr->address, &tmp, sizeof (tmp)) == 0); ++ g_assert (memcmp (&test_addr->peer_address, &in6addr_any, sizeof (tmp)) == 0); + g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen); + +- g_assert (nm_ip6_config_get_ptp_address (dst) == NULL); + g_assert (nm_ip6_config_get_gateway (dst) == NULL); + + g_assert_cmpuint (nm_ip6_config_get_num_routes (dst), ==, 1); +diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c +index a3b09f2..2d53449 100644 +--- a/src/vpn-manager/nm-vpn-connection.c ++++ b/src/vpn-manager/nm-vpn-connection.c +@@ -569,8 +569,7 @@ print_vpn_config (NMVPNConnection *connection) + nm_log_info (LOGD_VPN, " Internal Gateway: %s", ip_address_to_string (priv->ip4_internal_gw)); + nm_log_info (LOGD_VPN, " Internal Address: %s", ip_address_to_string (address4->address)); + nm_log_info (LOGD_VPN, " Internal Prefix: %d", address4->plen); +- nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", +- ip_address_to_string (nm_ip4_config_get_ptp_address (priv->ip4_config))); ++ nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", ip_address_to_string (address4->peer_address)); + nm_log_info (LOGD_VPN, " Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (priv->ip4_config)); + + num = nm_ip4_config_get_num_routes (priv->ip4_config); +@@ -610,8 +609,7 @@ print_vpn_config (NMVPNConnection *connection) + nm_log_info (LOGD_VPN, " Internal Gateway: %s", ip6_address_to_string (priv->ip6_internal_gw)); + nm_log_info (LOGD_VPN, " Internal Address: %s", ip6_address_to_string (&address6->address)); + nm_log_info (LOGD_VPN, " Internal Prefix: %d", address6->plen); +- nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", +- ip6_address_to_string (nm_ip6_config_get_ptp_address (priv->ip6_config))); ++ nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", ip6_address_to_string (&address6->peer_address)); + nm_log_info (LOGD_VPN, " Maximum Segment Size (MSS): %d", nm_ip6_config_get_mss (priv->ip6_config)); + + num = nm_ip6_config_get_num_routes (priv->ip6_config); +@@ -876,7 +874,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PTP); + if (val) +- nm_ip4_config_set_ptp_address (config, g_value_get_uint (val)); ++ address.peer_address = g_value_get_uint (val); + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX); + if (val) +@@ -1024,7 +1022,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, + GByteArray *ba = g_value_get_boxed (val); + + if (ba->len == sizeof (struct in6_addr)) +- nm_ip6_config_set_ptp_address (config, (struct in6_addr *)ba->data); ++ address.peer_address = *(struct in6_addr *) ba->data; + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_PREFIX); +-- +1.8.4.2 + diff --git a/rh1018317-prereq.patch b/rh1018317-prereq.patch new file mode 100644 index 0000000..e5f8f4a --- /dev/null +++ b/rh1018317-prereq.patch @@ -0,0 +1,321 @@ +From ac94d83f04d87971c8bea4e164d7a5e260720e5c Mon Sep 17 00:00:00 2001 +From: Thomas Haller +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 +--- + 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 + #include + #include ++#include + + #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 + #include + #include ++#include + + #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 , 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 + #include + #include ++#include + + #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, "" }, + { "ip6-address-get-all", "print all IPv6 addresses", do_ip6_address_get_all, 1, "" }, + { "ip4-address-add", "add IPv4 address", do_ip4_address_add, 4, "
/ <>" }, +- { "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "
/ <>" }, ++ { "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "
/ [] <>" }, + { "ip4-address-delete", "delete IPv4 address", do_ip4_address_delete, 2, + "
/" }, + { "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 + diff --git a/rh1029213-ignore-RA-default-routes.patch b/rh1029213-ignore-RA-default-routes.patch new file mode 100644 index 0000000..e5b06d4 --- /dev/null +++ b/rh1029213-ignore-RA-default-routes.patch @@ -0,0 +1,98 @@ +From 8586353b09460ec0a619058421743dd7d424a75d Mon Sep 17 00:00:00 2001 +From: Dan Williams +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 +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 + diff --git a/rh1032819-set-broadcast-address.patch b/rh1032819-set-broadcast-address.patch new file mode 100644 index 0000000..dd3c0fb --- /dev/null +++ b/rh1032819-set-broadcast-address.patch @@ -0,0 +1,86 @@ +From 7eb12a5b21f87d7592ec2c5235d1ed90c4fac132 Mon Sep 17 00:00:00 2001 +From: Dan Williams +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 + diff --git a/rh1034921-startup-link-wait.patch b/rh1034921-startup-link-wait.patch new file mode 100644 index 0000000..d851b1f --- /dev/null +++ b/rh1034921-startup-link-wait.patch @@ -0,0 +1,833 @@ +From 07281f21a71fa333288821ad863accfeedfff567 Mon Sep 17 00:00:00 2001 +From: Dan Williams +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 +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 + +(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 +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 ) 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 +--- + 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 + diff --git a/rh1044757-ipv6-solicit-infinity.patch b/rh1044757-ipv6-solicit-infinity.patch new file mode 100644 index 0000000..818a714 --- /dev/null +++ b/rh1044757-ipv6-solicit-infinity.patch @@ -0,0 +1,431 @@ +From 8d3618a07baccc8abd9cfe7cf5b000b5d8c3340b Mon Sep 17 00:00:00 2001 +From: Thomas Haller +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 +--- + 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 +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 + diff --git a/rh1048711-bluez-crash.patch b/rh1048711-bluez-crash.patch new file mode 100644 index 0000000..f8b7457 --- /dev/null +++ b/rh1048711-bluez-crash.patch @@ -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); +