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