Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-drm-fsl-dcu.git] / net / core / wireless.c
index ffff0da46c6ee2a3703a9f3116eab0162b4727e6..64017d47b25b8808d8f47977bf36012b44c1d4d1 100644 (file)
@@ -369,7 +369,7 @@ static const struct iw_ioctl_description standard_event[] = {
                .header_type    = IW_HEADER_TYPE_ADDR,
        },
        [IWEVEXPIRED    - IWEVFIRST] = {
-               .header_type    = IW_HEADER_TYPE_ADDR, 
+               .header_type    = IW_HEADER_TYPE_ADDR,
        },
        [IWEVGENIE      - IWEVFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
@@ -377,7 +377,7 @@ static const struct iw_ioctl_description standard_event[] = {
                .max_tokens     = IW_GENERIC_IE_MAX,
        },
        [IWEVMICHAELMICFAILURE  - IWEVFIRST] = {
-               .header_type    = IW_HEADER_TYPE_POINT, 
+               .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = sizeof(struct iw_michaelmicfailure),
        },
@@ -630,11 +630,11 @@ static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,
                           dev->name, stats->status, stats->qual.qual,
                           stats->qual.updated & IW_QUAL_QUAL_UPDATED
                           ? '.' : ' ',
-                          ((__s32) stats->qual.level) - 
+                          ((__s32) stats->qual.level) -
                           ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
                           stats->qual.updated & IW_QUAL_LEVEL_UPDATED
                           ? '.' : ' ',
-                          ((__s32) stats->qual.noise) - 
+                          ((__s32) stats->qual.noise) -
                           ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
                           stats->qual.updated & IW_QUAL_NOISE_UPDATED
                           ? '.' : ' ',
@@ -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 */
@@ -831,7 +862,7 @@ static int ioctl_standard_call(struct net_device *  dev,
                                           iwr->u.data.length *
                                           descr->token_size);
                        if (err)
-                               ret =  -EFAULT;                            
+                               ret =  -EFAULT;
 #ifdef WE_IOCTL_DEBUG
                        printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
                               dev->name,
@@ -1009,7 +1040,7 @@ static inline int ioctl_private_call(struct net_device *  dev,
                        err = copy_to_user(iwr->u.data.pointer, extra,
                                           extra_size);
                        if (err)
-                               ret =  -EFAULT;                            
+                               ret =  -EFAULT;
 #ifdef WE_IOCTL_DEBUG
                        printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",
                               dev->name, iwr->u.data.length);
@@ -1049,7 +1080,7 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
        /* A bunch of special cases, then the generic case...
         * Note that 'cmd' is already filtered in dev_ioctl() with
         * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
-       switch(cmd) 
+       switch(cmd)
        {
                case SIOCGIWSTATS:
                        /* Get Wireless Stats */
@@ -1984,7 +2015,7 @@ void wireless_send_event(struct net_device *      dev,
                 * The best the driver could do is to log an error message.
                 * We will do it ourselves instead...
                 */
-               printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
+               printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
                       dev->name, cmd);
                return;
        }
@@ -1998,11 +2029,11 @@ void wireless_send_event(struct net_device *    dev,
        if(descr->header_type == IW_HEADER_TYPE_POINT) {
                /* Check if number of token fits within bounds */
                if(wrqu->data.length > descr->max_tokens) {
-                       printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
+                       printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
                        return;
                }
                if(wrqu->data.length < descr->min_tokens) {
-                       printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
+                       printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
                        return;
                }
                /* Calculate extra_len - extra is NULL for restricted events */
@@ -2099,7 +2130,7 @@ int iw_handler_set_spy(struct net_device *        dev,
         * The rtnl_lock() make sure we don't race with the other iw_handlers.
         * This make sure wireless_spy_update() "see" that the spy list
         * is temporarily disabled. */
-       wmb();
+       smp_wmb();
 
        /* Are there are addresses to copy? */
        if(wrqu->data.length > 0) {
@@ -2128,7 +2159,7 @@ int iw_handler_set_spy(struct net_device *        dev,
        }
 
        /* Make sure above is updated before re-enabling */
-       wmb();
+       smp_wmb();
 
        /* Enable addresses */
        spydata->spy_number = wrqu->data.length;