PATCH[1/5]: mkinitrd: add support for renaming network interfaces

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

 



Hi All,

This patch forwards port the renaming of network interfaces based on MAC (as udev does) from RHEL-5 making network booting on systems with multiple interfaces work properly.

Regards,

Hans
diff -up mkinitrd-6.0.75/mkinitrd.foo mkinitrd-6.0.75/mkinitrd
--- mkinitrd-6.0.75/mkinitrd.foo	2009-01-19 17:14:56.000000000 +0100
+++ mkinitrd-6.0.75/mkinitrd	2009-01-30 16:05:41.000000000 +0100
@@ -715,6 +715,10 @@ handlenetdev() {
             IPSTR="$IPSTR --dns $DNS1"
         fi
     fi
+    prenetwork=""
+    if [ -n "$HWADDR" ]; then
+	prenetwork="netname $HWADDR $dev"
+    fi
     network="network --device $dev --bootproto $BOOTPROTO $IPSTR"
     if [ "$BOOTPROTO" = "dhcp" ]; then
         dhclient_leases_cmd="cp /var/lib/dhclient/dhclient.leases /sysroot/dev/.dhclient-$dev.leases"
@@ -1669,6 +1673,9 @@ if [ -n "$net_list" ]; then
     for netdev in $net_list; do 
         emit "echo Bringing up $netdev"
         handlenetdev $netdev
+        if [ -n "$prenetwork" ]; then
+            emit $prenetwork
+        fi
         emit $network
     done
 fi
diff -up mkinitrd-6.0.75/nash/nash.c.foo mkinitrd-6.0.75/nash/nash.c
--- mkinitrd-6.0.75/nash/nash.c.foo	2009-01-19 17:14:56.000000000 +0100
+++ mkinitrd-6.0.75/nash/nash.c	2009-01-30 16:05:41.000000000 +0100
@@ -2883,6 +2883,33 @@ condCommand(char *cmd, char *end)
 }
 
 static int
+netnameCommand(char *cmd, char *end)
+{
+    char *hwaddr = NULL, *ifname = NULL;
+
+    cmd = getArg(cmd, end, &hwaddr);
+    if (!cmd) {
+err_missing_args:
+        eprintf("netname: missing arguments.\n");
+usage:
+        eprintf("usage: netname c0:ff:ee:ab:c1:23 eth0\n");
+        return 1;
+    }
+
+    cmd = getArg(cmd, end, &ifname);
+    if (!cmd)
+        goto err_missing_args;
+
+    cmd = getArg(cmd, end, &ifname);
+    if (cmd) {
+        eprintf("netname: extra arguments.\n");
+        goto usage;
+    }
+
+    return renameNetworkInterface(hwaddr, ifname);
+}
+
+static int
 networkCommand(char *cmd, char *end)
 {
     char *ncmd = NULL;
@@ -3160,6 +3187,7 @@ static const struct commandHandler handl
     { "mknod", mknodCommand },
     { "mkrootdev", mkrootdevCommand },
     { "mount", mountCommand },
+    { "netname", netnameCommand },
     { "network", networkCommand },
     { "null", nullCommand },
     { "plymouth", nullCommand },
diff -up mkinitrd-6.0.75/nash/net.h.foo mkinitrd-6.0.75/nash/net.h
--- mkinitrd-6.0.75/nash/net.h.foo	2009-01-19 17:14:56.000000000 +0100
+++ mkinitrd-6.0.75/nash/net.h	2009-01-30 16:05:41.000000000 +0100
@@ -39,5 +39,6 @@ typedef uint16_t u16;
 typedef uint8_t u8;
 
 int nashNetworkCommand(char * cmd);
+int renameNetworkInterface(char *hwaddr, char *ifname);
 
 #endif
diff -up mkinitrd-6.0.75/nash/network.c.foo mkinitrd-6.0.75/nash/network.c
--- mkinitrd-6.0.75/nash/network.c.foo	2009-01-19 17:14:56.000000000 +0100
+++ mkinitrd-6.0.75/nash/network.c	2009-01-30 16:27:36.000000000 +0100
@@ -42,6 +42,18 @@
 #include <netlink/route/addr.h>
 #include <netlink/route/link.h>
 
+#include <net/if.h>
+
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
+
 #include <nash.h>
 #include "util.h"
 
@@ -475,3 +487,273 @@ int nashNetworkCommand(char * cmd) {
     sleep(2);
     return 0;
 }
+
+struct nl {
+    int fd;
+    struct sockaddr_nl addr;
+    int seq;
+};
+
+static int
+rtnl_wilddump_request(struct nl *nl, int family, int type)
+{
+    struct sockaddr_nl nladdr;
+    struct {
+        struct nlmsghdr nh;
+        struct rtgenmsg g;
+    } req;
+    int status;
+
+    memset(&nladdr, '\0', sizeof(nladdr));
+    nladdr.nl_family = AF_NETLINK;
+
+    memset(&req, '\0', sizeof(req));
+    req.nh.nlmsg_len = sizeof(req);
+    req.nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST ;
+    req.nh.nlmsg_type = type;
+    req.nh.nlmsg_seq = ++nl->seq;
+    req.nh.nlmsg_pid = 0;
+    req.g.rtgen_family = family;
+
+    status = sendto(nl->fd, &req, sizeof(req), 0, (struct sockaddr *)&nladdr,
+            sizeof(nladdr));
+    if (status < 0) {
+        eprintf("rtnl_wilddump_request: sendto failed: %m\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+struct ifinfo {
+    int index;
+    char *name;
+    char *mac;
+    struct ifinfo *next;
+};
+
+static int
+rtnl_dump_recv(struct nl *nl, struct ifinfo **iftable)
+{
+    struct sockaddr_nl nladdr;
+    struct iovec iov;
+    struct msghdr msg = {
+        .msg_name = &nladdr,
+        .msg_namelen = sizeof(nladdr),
+        .msg_iov = &iov,
+        .msg_iovlen = 1,
+    };
+    char buf[16384];
+    struct ifinfo *ifentry = NULL;
+
+    iov.iov_base = buf;
+    while (1) {
+        int status;
+        struct nlmsghdr *h;
+
+        memset(buf, '\0', sizeof(buf));
+        iov.iov_len = sizeof(buf);
+        status = recvmsg(nl->fd, &msg, 0);
+
+        if (status < 0) {
+            if (errno == EINTR)
+                continue;
+            eprintf("rtnl_dump_recv: recvmsg failed: %m\n");
+            return -1;
+        }
+
+        if (status == 0) {
+            eprintf("rtnl_dump_recv: received EOF\n");
+            return -1;
+        }
+
+        h = (struct nlmsghdr *)buf;
+        while (NLMSG_OK(h, status)) {
+            struct rtattr *rta;
+            struct ifinfomsg *ifi;
+            int len;
+
+            if (h->nlmsg_type == NLMSG_DONE)
+                return 0;
+
+            if (nladdr.nl_pid != 0 || h->nlmsg_pid != nl->addr.nl_pid ||
+                    h->nlmsg_seq != nl->seq)
+                goto skip_it;
+
+            if (h->nlmsg_type == NLMSG_ERROR)
+                goto skip_it;
+
+            if (h->nlmsg_type == RTM_NEWLINK) {
+                ifentry = calloc(1, sizeof(*ifentry));
+
+                ifi = NLMSG_DATA(h);
+                ifentry->index = ifi->ifi_index;
+                len = IFLA_PAYLOAD(h);
+                rta = IFLA_RTA(ifi);
+                while (RTA_OK(rta, len)) {
+                    switch(rta->rta_type) {
+                        case IFLA_IFNAME:
+                            ifentry->name = strdup(RTA_DATA(rta));
+                            break;
+                        case IFLA_ADDRESS: {
+                            int alen = RTA_PAYLOAD(rta);
+                            int i;
+                            char *mac = calloc(alen * 2 + alen, sizeof(char));
+                            char *data, *octet;
+
+                            data = RTA_DATA(rta);
+                            octet = mac;
+
+                            for (i = 0; i < alen; i++) {
+                                sprintf(octet, "%02x:", (unsigned char)data[i]);
+                                octet += 3;
+                            }
+                            mac[i*2+i-1] = '\0';
+                            ifentry->mac = mac;
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                    rta = RTA_NEXT(rta,len);
+                }
+                ifentry->next = *iftable;
+                *iftable = ifentry;
+            }
+            
+skip_it:
+            h = NLMSG_NEXT(h, status);
+        }
+    }
+
+    return 0;
+}
+
+static int
+get_ifinfo(struct ifinfo **table)
+{
+    struct nl nl;
+    socklen_t socklen;
+    int n;
+    int rc;
+
+    memset(&nl, '\0', sizeof(nl));
+    nl.addr.nl_family = AF_NETLINK;
+    nl.seq = time(NULL);
+
+    nl.fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+    if (nl.fd < 0) {
+        eprintf("socket() failed: %m\n");
+        return -1;
+    }
+
+    n = 16384;
+    socklen = sizeof(n);
+    setsockopt(nl.fd, SOL_SOCKET, SO_SNDBUF, &n, socklen);
+    n = 16384;
+    setsockopt(nl.fd, SOL_SOCKET, SO_RCVBUF, &n, socklen);
+    bind(nl.fd, (struct sockaddr *)&nl.addr, sizeof(nl.addr));
+
+    memset(&nl.addr, 0, sizeof(nl.addr));
+    socklen = sizeof(nl.addr);
+    getsockname(nl.fd, (struct sockaddr *)&nl.addr, &socklen);
+
+    rc = rtnl_wilddump_request(&nl, AF_UNSPEC, RTM_GETLINK);
+    if (rc >= 0)
+        rc = rtnl_dump_recv(&nl, table);
+
+    close(nl.fd);
+    return rc;
+}
+
+static void
+free_ifinfo(struct ifinfo *table)
+{
+    struct ifinfo *ifentry = table;
+
+    while (ifentry) {
+        struct ifinfo *next = ifentry->next;
+
+        if (ifentry->name)
+            free(ifentry->name);
+        if (ifentry->mac)
+            free(ifentry->mac);
+        free(ifentry);
+        ifentry = next;
+    }
+}
+
+static int
+get_ctl_fd(void)
+{
+	int s_errno;
+	int fd;
+
+	fd = socket(PF_INET, SOCK_DGRAM, 0);
+	if (fd >= 0)
+		return fd;
+	s_errno = errno;
+	fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+	if (fd >= 0)
+		return fd;
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (fd >= 0)
+		return fd;
+	errno = s_errno;
+	eprintf("Cannot create control socket: %m\n");
+	return -1;
+}
+
+static int
+do_changename(const char *dev, const char *newdev)
+{
+	struct ifreq ifr;
+	int fd;
+	int err, en;
+
+	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+	strncpy(ifr.ifr_newname, newdev, IFNAMSIZ);
+	fd = get_ctl_fd();
+	if (fd < 0)
+		return -1;
+	err = ioctl(fd, SIOCSIFNAME, &ifr);
+        en = errno;
+	close(fd);
+        errno = en;
+        if (err)
+        	eprintf("Change Name failed: %m\n");
+        return err;
+}
+
+int
+renameNetworkInterface(char *hwaddr, char *ifname)
+{
+    struct ifinfo *ifinfo = NULL, *ifentry;
+    int rc = 0;
+
+    int collision = 0;
+    char *oldname;
+
+    if (get_ifinfo(&ifinfo) >= 0) {
+        for (ifentry = ifinfo; ifentry; ifentry = ifentry->next) {
+            if (!strcasecmp(hwaddr, ifentry->mac)) {
+                if (!strcmp(ifname, ifentry->name))
+                    break;
+                oldname = ifentry->name;
+            } else if (!strcmp(ifname, ifentry->name)) {
+                collision = 1;
+            }
+        }
+        if (collision)
+            rc = do_changename(ifname, "nashdevname");
+        if (rc >= 0)
+            rc = do_changename(oldname, ifname);
+        if (rc >= 0 && collision)
+            rc = do_changename("nashdevname", oldname);
+
+        free_ifinfo(ifinfo);
+    }
+
+    return rc;
+}
+
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux