summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonardo Chiquitto <leonardo.lists@gmail.com>2011-01-10 09:19:15 -0200
committerSimon Horman <horms@verge.net.au>2011-01-13 16:39:31 +0900
commitc75354b291d1c8cc306d02a63372d487299188b3 (patch)
tree6ee64d95177438897433246d1bf6f3ab350b2cdc
parent9cbef39baac3b18ad0d7dde9a646c1ffb24817a8 (diff)
downloadkexec-tools-c75354b291d1c8cc306d02a63372d487299188b3.tar.gz
ifdown: really set down all active interfaces
Hello, We've got a bug report of random memory corruption when using kexec. The test case to reproduce the problem sets up bonding between two tg3 NICs and transmits some data just before calling kexec to boot the new kernel. Around one in every one hundred boots would crash early with different signatures. We confirmed that the patch below resolves the problem. Please, could you review and consider it for upstream inclusion? Thanks, Leonardo Before executing the new kernel, kexec disables all network interfaces to prevent problems like random memory corruption caused by in flight DMAs. The current algorithm uses the SIOCGIFCONF to enumerate all interfaces before shutting them down. However, this ioctl returns only the interfaces that have an IP address set. This means that in some setups, kexec may skip interfaces that are up and running. A common example is in bonding, where the enslaved interfaces are up but may not have an IP address configured. This patch replaces SIOCGIFCONF with if_nameindex() to enumerate all network interfaces available, regardless of having an IP address set or not. Signed-off-by: Leonardo Chiquitto <lchiquitto@novell.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/ifdown.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/kexec/ifdown.c b/kexec/ifdown.c
index d480b3be..bc7f12f3 100644
--- a/kexec/ifdown.c
+++ b/kexec/ifdown.c
@@ -19,8 +19,6 @@ char *v_ifdown = "@(#)ifdown.c 1.11 02-Jun-1998 miquels@cistron.nl";
#include <net/if.h>
#include <netinet/in.h>
-#define MAX_IFS 64
-
/*
* First, we find all shaper devices and down them. Then we
* down all real interfaces. This is because the comment in the
@@ -29,43 +27,45 @@ char *v_ifdown = "@(#)ifdown.c 1.11 02-Jun-1998 miquels@cistron.nl";
*/
int ifdown(void)
{
- struct ifreq ifr[MAX_IFS];
- struct ifconf ifc;
- int i, fd;
- int numif;
- int shaper;
+ struct if_nameindex *ifa, *ifp;
+ struct ifreq ifr;
+ int fd, shaper;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "ifdown: ");
perror("socket");
return -1;
}
- ifc.ifc_len = sizeof(ifr);
- ifc.ifc_req = ifr;
- if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
+ if ((ifa = if_nameindex()) == NULL) {
fprintf(stderr, "ifdown: ");
- perror("SIOCGIFCONF");
- close(fd);
+ perror("if_nameindex");
return -1;
}
- numif = ifc.ifc_len / sizeof(struct ifreq);
for (shaper = 1; shaper >= 0; shaper--) {
- for (i = 0; i < numif; i++) {
+ for (ifp = ifa; ifp->if_index; ifp++) {
- if ((strncmp(ifr[i].ifr_name, "shaper", 6) == 0)
+ if ((strncmp(ifp->if_name, "shaper", 6) == 0)
!= shaper) continue;
-
- if (strcmp(ifr[i].ifr_name, "lo") == 0)
+ if (strcmp(ifp->if_name, "lo") == 0)
continue;
- if (strchr(ifr[i].ifr_name, ':') != NULL)
+ if (strchr(ifp->if_name, ':') != NULL)
continue;
- ifr[i].ifr_flags &= ~(IFF_UP);
- if (ioctl(fd, SIOCSIFFLAGS, &ifr[i]) < 0) {
+
+ strncpy(ifr.ifr_name, ifp->if_name, IFNAMSIZ);
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
fprintf(stderr, "ifdown: shutdown ");
- perror(ifr[i].ifr_name);
+ perror(ifp->if_name);
+ return -1;
}
+ ifr.ifr_flags &= ~(IFF_UP);
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+ fprintf(stderr, "ifdown: shutdown ");
+ perror(ifp->if_name);
+ return -1;
+ }
+
}
}
close(fd);