--- devinet.c.orig Fri Dec 22 12:36:33 2000 +++ devinet.c Tue Oct 2 04:29:03 2001 @@ -20,6 +20,10 @@ * Changes: * Alexey Kuznetsov: pa_* fields are replaced with ifaddr lists. * Cyrus Durgin: updated for kmod + * Matthias Andree: in devinet_ioctl, compare label and + * address (4.4BSD alias style support), + * fall back to comparing just the label + * if no match found. */ #include @@ -405,6 +409,8 @@ struct device *dev; #ifdef CONFIG_IP_ALIAS char *colon; + struct sockaddr_in sin_orig; + int tryaddrmatch = 0; #endif int exclusive = 0; int ret = 0; @@ -418,6 +424,9 @@ ifr.ifr_name[IFNAMSIZ-1] = 0; #ifdef CONFIG_IP_ALIAS + /* save original address for comparison */ + memcpy(&sin_orig, sin, sizeof(*sin)); + colon = strchr(ifr.ifr_name, ':'); if (colon) *colon = 0; @@ -436,6 +445,9 @@ so that we do not impose a lock. One day we will be forced to put shlock here (I mean SMP) */ +#ifdef CONFIG_IP_ALIAS + tryaddrmatch = (sin_orig.sin_family == AF_INET); +#endif memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; break; @@ -473,6 +485,25 @@ #endif if ((in_dev=dev->ip_ptr) != NULL) { +#ifdef CONFIG_IP_ALIAS + if (tryaddrmatch) { + /* Matthias Andree */ + /* compare label and address (4.4BSD style) */ + /* note: we only do this for a limited set of ioctls + and only if the original address family was AF_INET. + This is checked above. */ + for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) { + if ((strcmp(ifr.ifr_name, ifa->ifa_label) == 0) + && (sin_orig.sin_addr.s_addr == ifa->ifa_address)) { + break; /* found */ + } /* if */ + } /* for */ + } + /* we didn't get a match, maybe the application is + 4.3BSD-style and passed in junk so we fall back to + comparing just the label */ + if (ifa == NULL) +#endif for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0) break;