From df016d6d7abe5b0f8e102d34527d6434f0bec924 Mon Sep 17 00:00:00 2001 From: "Anthony G. Basile" Date: Sun, 7 Apr 2013 22:19:54 -0400 Subject: [PATCH] src/udev/udev-event.c: restore code to allow rule generator to work This code was dropped while importing from upstream. It is needed to allow the legacy renaming of interfaces like eth* or wlan*. X-Eudev-Bug: 56 X-Eudev-Bug-URL: https://github.com/gentoo/eudev/issues/56 Signed-off-by: Anthony G. Basile --- configure.ac | 4 +++ src/udev/udev-event.c | 72 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/configure.ac b/configure.ac index 0ecd15832..68dd9df50 100644 --- a/configure.ac +++ b/configure.ac @@ -303,6 +303,10 @@ AC_ARG_ENABLE([rule-generator], AS_HELP_STRING([--enable-rule-generator], [enable legacy persistent network, cdrom support]), [], [enable_rule_generator=no]) +if test "x${enable_rule_generator}" != xno; then + AC_DEFINE([ENABLE_RULE_GENERATOR], [1], [Define if we are enabling rule generator]) +fi + AM_CONDITIONAL([ENABLE_RULE_GENERATOR], [test "x$enable_rule_generator" = xyes]) # ------------------------------------------------------------------------------ diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index d1880efe5..c6c5940ff 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -752,6 +752,28 @@ int udev_event_spawn(struct udev_event *event, return err; } +#ifdef ENABLE_RULE_GENERATOR +static void rename_netif_kernel_log(struct ifreq ifr) +{ + int klog; + FILE *f; + + klog = open("/dev/kmsg", O_WRONLY|O_CLOEXEC); + if (klog < 0) + return; + + f = fdopen(klog, "w"); + if (f == NULL) { + close(klog); + return; + } + + fprintf(f, "<30>udevd[%u]: renamed network interface %s to %s\n", + getpid(), ifr.ifr_name, ifr.ifr_newname); + fclose(f); +} +#endif + static int rename_netif(struct udev_event *event) { struct udev_device *dev = event->dev; @@ -773,12 +795,62 @@ static int rename_netif(struct udev_event *event) util_strscpy(ifr.ifr_name, IFNAMSIZ, udev_device_get_sysname(dev)); util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); err = ioctl(sk, SIOCSIFNAME, &ifr); + +#ifdef ENABLE_RULE_GENERATOR + int loop; + + if (err == 0) { + rename_netif_kernel_log(ifr); + goto out; + } + + /* keep trying if the destination interface name already exists */ + err = -errno; + if (err != -EEXIST) + goto out; + + /* free our own name, another process may wait for us */ + snprintf(ifr.ifr_newname, IFNAMSIZ, "rename%u", udev_device_get_ifindex(dev)); + err = ioctl(sk, SIOCSIFNAME, &ifr); + if (err < 0) { + err = -errno; + goto out; + } + + /* log temporary name */ + rename_netif_kernel_log(ifr); + + /* wait a maximum of 90 seconds for our target to become available */ + util_strscpy(ifr.ifr_name, IFNAMSIZ, ifr.ifr_newname); + util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); + loop = 90 * 20; + while (loop--) { + const struct timespec duration = { 0, 1000 * 1000 * 1000 / 20 }; + + nanosleep(&duration, NULL); + + err = ioctl(sk, SIOCSIFNAME, &ifr); + if (err == 0) { + rename_netif_kernel_log(ifr); + break; + } + err = -errno; + if (err != -EEXIST) + break; + } + +out: + if (err < 0) + log_error("error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname); +#else if (err >= 0) { print_kmsg("renamed network interface %s to %s\n", ifr.ifr_name, ifr.ifr_newname); } else { err = -errno; log_error("error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname); } +#endif + close(sk); return err; }