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