[PATCH] dhclient: copy leasefiles from old location if needed (rh #916233)



When the default leasefile location got moved from distro-specific
dhclient locations to a single NM-specific location, that apparently
broke scripts and external tools that depended on the old location,
like dract netbooting.

During a netboot, DHCP is started from the initramfs and gets a
lease, and the leasefile lives in the initramfs.  When the real
system is started, and the rootfs switches from the initramfs to
the actual rootfs, something needs to copy the leasefiles over to
where NetworkManager can find them.  For dracut at least, various
dracut scripts were doing this, and copying to the old location
in /var/lib/dhclient or /var/lib/dhcp.  Which means NM can no
longer find them, and proceeds to acquire a new DHCP lease when
taking over the existing connection, rather than renewing the
existing lease.  This can lead to loss of network connectivity
and thus the netboot process fails.

If no leasefile for the connection in the new location exists,
look in the old locations and copy that leasefile over to the new
location.
---
 src/dhcp-manager/nm-dhcp-dhclient.c | 47 +++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c
index 14e4825..0bb9c05 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient.c
@@ -24,7 +24,7 @@
 
 #include <glib.h>
 #include <glib/gi18n.h>
-#include <dbus/dbus.h>
+#include <gio/gio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -82,10 +82,53 @@ nm_dhcp_dhclient_get_path (const char *try_first)
 static char *
 get_dhclient_leasefile (const char * iface, const char *uuid, gboolean ipv6)
 {
-       return g_strdup_printf (NMSTATEDIR "/dhclient%s-%s-%s.lease",
+       GError *error = NULL;
+       char *path, *oldpath;
+       guint log_domain = ipv6 ? LOGD_DHCP6 : LOGD_DHCP4;
+
+       path = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s-%s.lease",
                                ipv6 ? "6" : "",
                                uuid,
                                iface);
+
+       /* If the leasefile we're looking for doesn't exist yet in the new location
+        * (eg, /var/lib/NetworkManager) then look in the old location
+        * (eg, /var/lib/dhcp or /var/lib/dhclient) and copy the file to the new
+        * location.  This maintains backwards compatibility with external tools
+        * like dracut from before we switched leasefiles to an NM specific directory.
+        */
+       if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+               /* Debian, SUSE, and Mandriva location */
+               oldpath = g_strdup_printf (LOCALSTATEDIR "/lib/dhcp/dhclient%s-%s-%s.lease",
+                                          ipv6 ? "6" : "", uuid, iface);
+               if (!g_file_test (oldpath, G_FILE_TEST_EXISTS)) {
+                       /* Red Hat and Fedora location */
+                       g_free (oldpath);
+                       oldpath = g_strdup_printf (LOCALSTATEDIR "/lib/dhclient/dhclient%s-%s-%s.lease",
+                                                  ipv6 ? "6" : "", uuid, iface);
+               }
+
+               if (g_file_test (oldpath, G_FILE_TEST_EXISTS)) {
+                       GFile *src = g_file_new_for_path (oldpath);
+                       GFile *dst = g_file_new_for_path (path);
+
+                       g_assert (src);
+                       g_assert (dst);
+                       if (!g_file_copy (src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error)) {
+                               nm_log_warn (log_domain, "Failed to copy leasefile %s to %s: (%d) %s",
+                                            oldpath, path,
+                                            error ? error->code : -1,
+                                            error && error->message ? error->message : "(unknown)");
+                               g_clear_error (&error);
+                       }
+
+                       g_object_unref (src);
+                       g_object_unref (dst);
+               }
+               g_free (oldpath);
+       }
+
+       return path;
 }
 
 static void
-- 
1.8.1.4




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]