diff --git a/SOURCES/0026-rh1139326-address-lifetime-dhcp-expiry.patch b/SOURCES/0026-rh1139326-address-lifetime-dhcp-expiry.patch new file mode 100644 index 0000000..bcb0dce --- /dev/null +++ b/SOURCES/0026-rh1139326-address-lifetime-dhcp-expiry.patch @@ -0,0 +1,246 @@ +diff -up NetworkManager-0.9.9.1/src/dhcp-manager/nm-dhcp-dhclient-utils.c.0026-rh1139326-address-lifetime-padding.orig NetworkManager-0.9.9.1/src/dhcp-manager/nm-dhcp-dhclient-utils.c +--- NetworkManager-0.9.9.1/src/dhcp-manager/nm-dhcp-dhclient-utils.c.0026-rh1139326-address-lifetime-padding.orig 2014-11-05 12:09:08.367289245 -0600 ++++ NetworkManager-0.9.9.1/src/dhcp-manager/nm-dhcp-dhclient-utils.c 2014-11-05 12:11:32.453938494 -0600 +@@ -27,6 +27,7 @@ + #include "nm-dhcp-dhclient-utils.h" + #include "nm-ip4-config.h" + #include "nm-utils.h" ++#include "NetworkManagerUtils.h" + + #define CLIENTID_TAG "send dhcp-client-identifier" + #define CLIENTID_FORMAT CLIENTID_TAG " \"%s\"; # added by NetworkManager" +@@ -530,6 +531,7 @@ nm_dhcp_dhclient_read_lease_ip_configs ( + GSList *parsed = NULL, *iter, *leases = NULL; + char **line, **split = NULL; + GHashTable *hash = NULL; ++ gint32 now_monotonic_ts; + + g_return_val_if_fail (contents != NULL, NULL); + +@@ -570,6 +572,7 @@ nm_dhcp_dhclient_read_lease_ip_configs ( + g_date_time_ref (now); + else + now = g_date_time_new_now_utc (); ++ now_monotonic_ts = nm_utils_get_monotonic_timestamp_s (); + + for (iter = parsed; iter; iter = g_slist_next (iter)) { + NMIP4Config *ip4; +@@ -624,6 +627,7 @@ nm_dhcp_dhclient_read_lease_ip_configs ( + if (!address.plen) + address.plen = nm_utils_ip4_get_default_prefix (address.address); + ++ address.timestamp = now_monotonic_ts; + address.lifetime = address.preferred = expiry; + address.source = NM_PLATFORM_SOURCE_DHCP; + +diff -up NetworkManager-0.9.9.1/src/platform/nm-platform.c.0026-rh1139326-address-lifetime-padding.orig NetworkManager-0.9.9.1/src/platform/nm-platform.c +--- NetworkManager-0.9.9.1/src/platform/nm-platform.c.0026-rh1139326-address-lifetime-padding.orig 2014-03-26 10:07:56.000000000 -0500 ++++ NetworkManager-0.9.9.1/src/platform/nm-platform.c 2014-11-05 12:12:50.787378771 -0600 +@@ -1370,14 +1370,71 @@ array_contains_ip6_address (const GArray + return FALSE; + } + +-/* Compute (a - b) in an overflow-safe manner. */ ++/** ++ * Takes a pair @timestamp and @duration, and returns the remaining duration based ++ * on the new timestamp @now. ++ */ + static guint32 +-subtract_guint32 (guint32 a, guint32 b) ++_rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now, guint32 padding) ++{ ++ gint64 t; ++ ++ if (duration == NM_PLATFORM_LIFETIME_PERMANENT) ++ return NM_PLATFORM_LIFETIME_PERMANENT; ++ ++ if (timestamp == 0) { ++ /* if the @timestamp is zero, assume it was just left unset and that the relative ++ * @duration starts counting from @now. This is convenient to construct an address ++ * and print it in nm_platform_ip4_address_to_string(). ++ * ++ * In general it does not make sense to set the @duration without anchoring at ++ * @timestamp because you don't know the absolute expiration time when looking ++ * at the address at a later moment. */ ++ timestamp = now; ++ } ++ ++ /* For timestamp > now, just accept it and calculate the expected(?) result. */ ++ t = (gint64) timestamp + (gint64) duration - (gint64) now; ++ ++ /* Optional padding to avoid potential races. */ ++ t += (gint64) padding; ++ ++ return (guint32) CLAMP (t, 0, NM_PLATFORM_LIFETIME_PERMANENT - 1); ++} ++ ++static gboolean ++_address_get_lifetime (guint32 timestamp, ++ guint32 orig_lifetime, ++ guint32 orig_preferred, ++ guint32 now, ++ guint32 padding, ++ guint32 *out_lifetime, ++ guint32 *out_preferred) + { +- if (a == G_MAXUINT32) +- return G_MAXUINT32; ++ guint32 lifetime, preferred; ++ ++ if (orig_lifetime == 0) { ++ *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; ++ *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT; ++ } else { ++ lifetime = _rebase_relative_time_on_now (timestamp, orig_lifetime, now, padding); ++ if (!lifetime) ++ return FALSE; ++ preferred = _rebase_relative_time_on_now (timestamp, orig_preferred, now, padding); ++ ++ *out_lifetime = lifetime; ++ *out_preferred = MIN (preferred, lifetime); + +- return a > b ? a - b : 0; ++ /* Assert that non-permanent addresses have a (positive) @timestamp. _rebase_relative_time_on_now() ++ * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always ++ * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. ++ */ ++ g_return_val_if_fail ( timestamp != 0 ++ || ( orig_lifetime == NM_PLATFORM_LIFETIME_PERMANENT ++ && orig_preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE); ++ g_return_val_if_fail (preferred <= lifetime, TRUE); ++ } ++ return TRUE; + } + + /** +@@ -1417,14 +1474,9 @@ nm_platform_ip4_address_sync (int ifinde + const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i); + guint32 lifetime, preferred; + +- if (known_address->lifetime) { +- /* Pad the timestamp by 5 seconds to avoid potential races. */ +- guint32 shift = subtract_guint32 (now, known_address->timestamp + 5); +- +- lifetime = subtract_guint32 (known_address->lifetime, shift); +- preferred = subtract_guint32 (known_address->lifetime, shift); +- } else +- lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT; ++ /* add a padding of 5 seconds to avoid potential races. */ ++ if (!_address_get_lifetime (known_address->timestamp, known_address->lifetime, known_address->preferred, now, 5, &lifetime, &preferred)) ++ continue; + + if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label)) + return FALSE; +@@ -1474,14 +1526,9 @@ nm_platform_ip6_address_sync (int ifinde + const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i); + guint32 lifetime, preferred; + +- if (known_address->lifetime) { +- /* Pad the timestamp by 5 seconds to avoid potential races. */ +- guint32 shift = subtract_guint32 (now, known_address->timestamp + 5); +- +- lifetime = subtract_guint32 (known_address->lifetime, shift); +- preferred = subtract_guint32 (known_address->lifetime, shift); +- } else +- lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT; ++ /* add a padding of 5 seconds to avoid potential races. */ ++ if (!_address_get_lifetime (known_address->timestamp, known_address->lifetime, known_address->preferred, now, 5, &lifetime, &preferred)) ++ continue; + + if (!nm_platform_ip6_address_add (ifindex, known_address->address, + known_address->peer_address, known_address->plen, + +From 90a77565d4c2e92e5798c463ca1e3baa4de51662 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Tue, 23 Sep 2014 15:44:55 -0500 +Subject: [PATCH] dhcp: treat lease expiry as failure (rh #1139326) + +Lease expiry means that the DHCP configuration is no longer valid, and +that all attempts to renew/rebind the lease have failed. The IP config +needs to be removed. NetworkManager also sets prefered/valid lifetimes +on addresses, so the kernel will remove them when the lease expires +anyway. That causes removal of the default route, if the default route +was through the device whose config has now expired. + +DHCP clients will typically move to the 'renew' or 'rebind' states when +nearing lease expiry, then if no answer is received move to the 'expire' +state. Eventually they move to the 'fail' state when all attempts to +contact the server have failed. + +Previously, since NM ignored the 'expire' DHCP state it would not clear +out the DHCP IP4 config immediately when the lease expired, instead +waiting for the DHCP client to move to the 'fail' state. But if the +DHCP server appeared between the 'expire' and 'fail' states, NM would +not notice and the device's NMIP4Config would not change, and thus the +Policy would not get the "ip4-config-changed" signal to re-add the +default route that the kernel had previously removed due to the valid +lifetime reaching zero when the lease expired. + +https://bugzilla.redhat.com/show_bug.cgi?id=1139326 + +diff -up NetworkManager-0.9.9.1/src/devices/nm-device.c.foo NetworkManager-0.9.9.1/src/devices/nm-device.c +--- NetworkManager-0.9.9.1/src/devices/nm-device.c.foo 2014-11-19 14:10:04.598128259 -0600 ++++ NetworkManager-0.9.9.1/src/devices/nm-device.c 2014-11-19 14:14:11.661710806 -0600 +@@ -2749,6 +2749,10 @@ dhcp4_state_changed (NMDHCPClient *clien + case DHC_TIMEOUT: /* timed out contacting DHCP server */ + dhcp4_fail (device, TRUE); + break; ++ case DHC_EXPIRE: /* lease expired */ ++ if (priv->ip4_state != IP_DONE) ++ break; ++ /* fall through */ + case DHC_END: /* dhclient exited normally */ + case DHC_FAIL: /* all attempts to contact server timed out, sleeping */ + case DHC_ABEND: /* dhclient exited abnormally */ +@@ -3160,6 +3164,10 @@ dhcp6_state_changed (NMDHCPClient *clien + case DHC_TIMEOUT: /* timed out contacting DHCP server */ + dhcp6_fail (device, TRUE); + break; ++ case DHC_EXPIRE6: /* lease expired */ ++ if (priv->ip6_state != IP_DONE) ++ break; ++ /* fall through */ + case DHC_END: /* dhclient exited normally */ + /* In IPv6 info-only mode, the client doesn't handle leases so it + * may exit right after getting a response from the server. That's + +From acee2eb9e4954eb33b85fa10a3522b8253271126 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Tue, 23 Sep 2014 15:38:33 -0500 +Subject: [PATCH] dhcp: fail the device if DHCP fails after having succeeded + earlier (rh #1139326) + +If DHCP fails to renew or rebind a lease, fail the device since the +IP config is no longer valid. Commit e2b7c482 was actually wrong for +dhcp[4|6]_fail(), since (ip_state == IP_FAIL) will never be true if +DHCP has ever been started, as IP_FAIL is only set from +nm_device_activate_ip[4|6]_config_timeout(), which obviously will not +be called in DHCP code paths if DHCP has previously succeeded. + +diff -up NetworkManager-0.9.9.1/src/devices/nm-device.c.foo NetworkManager-0.9.9.1/src/devices/nm-device.c +--- NetworkManager-0.9.9.1/src/devices/nm-device.c.foo 2014-11-20 18:19:56.260016368 -0600 ++++ NetworkManager-0.9.9.1/src/devices/nm-device.c 2014-11-20 20:52:00.302177894 -0600 +@@ -2700,8 +2700,10 @@ dhcp4_fail (NMDevice *device, gboolean t + + if (timeout || (priv->ip4_state == IP_CONF)) + nm_device_activate_schedule_ip4_config_timeout (device); +- else if (priv->ip4_state == IP_FAIL) ++ else if (priv->ip4_state == IP_DONE) + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); ++ else ++ g_warn_if_reached (); + } + + static void +@@ -3120,8 +3122,10 @@ dhcp6_fail (NMDevice *device, gboolean t + + if (timeout || (priv->ip6_state == IP_CONF)) + nm_device_activate_schedule_ip6_config_timeout (device); +- else if (priv->ip6_state == IP_FAIL) ++ else if (priv->ip6_state == IP_DONE) + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); ++ else ++ g_warn_if_reached (); + } + + static void diff --git a/SPECS/NetworkManager.spec b/SPECS/NetworkManager.spec index 8f651b9..5441714 100644 --- a/SPECS/NetworkManager.spec +++ b/SPECS/NetworkManager.spec @@ -28,7 +28,7 @@ Name: NetworkManager Summary: Network connection manager and user applications Epoch: 1 Version: %{realversion} -Release: 28%{snapshot}%{?git_sha}%{?dist}.2 +Release: 29%{snapshot}%{?git_sha}%{?dist} Group: System Environment/Base License: GPLv2+ URL: http://www.gnome.org/projects/NetworkManager/ @@ -62,6 +62,7 @@ Patch22: 0022-rh1112020-crash-reading-bridge-sysctl.patch Patch23: 0023-rh1093231-mtu-fix.patch #Patch24: 0024-rh1083133-rh1098319-nm-ipv6ll.patch Patch25: 0025-rh1149996-ifcfg-rh-GATEWAY.patch +Patch26: 0026-rh1139326-address-lifetime-dhcp-expiry.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -236,6 +237,7 @@ by nm-connection-editor and nm-applet in a non-graphical environment. %patch23 -p1 -b .0023-rh1093231-mtu-fix.orig #%patch24 -p1 -b .0024-rh1083133-rh1098319-nm-ipv6ll.orig %patch25 -p1 -b .0025-rh1149996-ifcfg-rh-GATEWAY.orig +%patch26 -p1 -b .0026-rh1139326-address-lifetime-padding.orig %build @@ -457,6 +459,9 @@ fi %endif %changelog +* Tue Dec 2 2014 Dan Williams - 1:0.9.9.1-29.git20140326 +- core: fix address lifetime padding and DHCP lease expiry (rh #1139326) (rh #1160160) + * Wed Oct 8 2014 Jiří Klimeš - 1:0.9.9.1-28.git20140326.2 - ifcfg-rh: write GATEWAY instead of GATEWAY0 to be ifup-compatible (rh #1149996)