[PATCH] wireless: WE-20 compatibility for ESSID and NICKN ioctls
authorJohn W. Linville <linville@tuxdriver.com>
Tue, 17 Oct 2006 14:54:36 +0000 (10:54 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 19 Oct 2006 21:08:19 +0000 (17:08 -0400)
WE-21 changed the ABI for the SIOC[SG]IW{ESSID,NICKN} ioctls by dropping
NULL termination.  This patch adds compatibility code so that WE-21 can
work properly with WE-20 (and older) tools.

Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/core/wireless.c

index ffff0da46c6ee2a3703a9f3116eab0162b4727e6..cb1b8728d7eec0c55c6151da9fba7d00f42747e9 100644 (file)
@@ -748,11 +748,39 @@ static int ioctl_standard_call(struct net_device *        dev,
                int     extra_size;
                int     user_length = 0;
                int     err;
+               int     essid_compat = 0;
 
                /* Calculate space needed by arguments. Always allocate
                 * for max space. Easier, and won't last long... */
                extra_size = descr->max_tokens * descr->token_size;
 
+               /* Check need for ESSID compatibility for WE < 21 */
+               switch (cmd) {
+               case SIOCSIWESSID:
+               case SIOCGIWESSID:
+               case SIOCSIWNICKN:
+               case SIOCGIWNICKN:
+                       if (iwr->u.data.length == descr->max_tokens + 1)
+                               essid_compat = 1;
+                       else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
+                               char essid[IW_ESSID_MAX_SIZE + 1];
+
+                               err = copy_from_user(essid, iwr->u.data.pointer,
+                                                    iwr->u.data.length *
+                                                    descr->token_size);
+                               if (err)
+                                       return -EFAULT;
+
+                               if (essid[iwr->u.data.length - 1] == '\0')
+                                       essid_compat = 1;
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+               iwr->u.data.length -= essid_compat;
+
                /* Check what user space is giving us */
                if(IW_IS_SET(cmd)) {
                        /* Check NULL pointer */
@@ -795,7 +823,8 @@ static int ioctl_standard_call(struct net_device *  dev,
 #endif /* WE_IOCTL_DEBUG */
 
                /* Create the kernel buffer */
-               extra = kmalloc(extra_size, GFP_KERNEL);
+               /*    kzalloc ensures NULL-termination for essid_compat */
+               extra = kzalloc(extra_size, GFP_KERNEL);
                if (extra == NULL) {
                        return -ENOMEM;
                }
@@ -819,6 +848,8 @@ static int ioctl_standard_call(struct net_device *  dev,
                /* Call the handler */
                ret = handler(dev, &info, &(iwr->u), extra);
 
+               iwr->u.data.length += essid_compat;
+
                /* If we have something to return to the user */
                if (!ret && IW_IS_GET(cmd)) {
                        /* Check if there is enough buffer up there */