Messages in this thread Patch in this message | | | Date | Tue, 20 Jun 2006 16:54:25 +0530 | From | "Aneesh Kumar" <> | Subject | sparse and devinet_ioctl |
| |
How do i make sure i can call devinet_ioctl from kernel without having a sparse warning.
The call i want to use was SIOCGIFADDR
Right now i am patching it as below
_devinet_ioctl(SIOCGIFADDR, &ifr)
Is this the correct way ? But then I don't want to patch any core kernel files. In that case how will i achieve the results.
-aneesh diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 54419b2..e8e9eaa 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -532,11 +532,10 @@ static __inline__ int inet_abc_len(u32 a } -int devinet_ioctl(unsigned int cmd, void __user *arg) +int _devinet_ioctl(unsigned int cmd, struct ifreq *ifr) { - struct ifreq ifr; struct sockaddr_in sin_orig; - struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; + struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; struct in_device *in_dev; struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; @@ -545,23 +544,17 @@ int devinet_ioctl(unsigned int cmd, void int ret = -EFAULT; int tryaddrmatch = 0; - /* - * Fetch the caller's info block into kernel space - */ - - if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) - goto out; - ifr.ifr_name[IFNAMSIZ - 1] = 0; + ifr->ifr_name[IFNAMSIZ - 1] = 0; /* save original address for comparison */ memcpy(&sin_orig, sin, sizeof(*sin)); - colon = strchr(ifr.ifr_name, ':'); + colon = strchr(ifr->ifr_name, ':'); if (colon) *colon = 0; #ifdef CONFIG_KMOD - dev_load(ifr.ifr_name); + dev_load(ifr->ifr_name); #endif switch(cmd) { @@ -602,7 +595,7 @@ #endif rtnl_lock(); ret = -ENODEV; - if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL) + if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) goto done; if (colon) @@ -617,7 +610,7 @@ #endif 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) && + if (!strcmp(ifr->ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == ifa->ifa_address) { break; /* found */ @@ -630,7 +623,7 @@ #endif if (!ifa) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) - if (!strcmp(ifr.ifr_name, ifa->ifa_label)) + if (!strcmp(ifr->ifr_name, ifa->ifa_label)) break; } } @@ -662,11 +655,11 @@ #endif if (!ifa) break; ret = 0; - if (!(ifr.ifr_flags & IFF_UP)) + if (!(ifr->ifr_flags & IFF_UP)) inet_del_ifa(in_dev, ifap, 1); break; } - ret = dev_change_flags(dev, ifr.ifr_flags); + ret = dev_change_flags(dev, ifr->ifr_flags); break; case SIOCSIFADDR: /* Set interface address (and family) */ @@ -679,7 +672,7 @@ #endif if ((ifa = inet_alloc_ifa()) == NULL) break; if (colon) - memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); + memcpy(ifa->ifa_label, ifr->ifr_name, IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); } else { @@ -767,9 +760,26 @@ out: return ret; rarok: rtnl_unlock(); - ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0; goto out; } +int devinet_ioctl(unsigned int cmd, void __user *arg) +{ + struct ifreq ifr; + int ret; + + /* + * Fetch the caller's info block into kernel space + */ + + if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) + return -EFAULT; + + if ((ret = _devinet_ioctl(cmd, &ifr)) == 0 ) { + ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0; + } + return ret; + +} static int inet_gifconf(struct net_device *dev, char __user *buf, int len) { | |