linux/net/wireless/wext-core.c
<<
>>
Prefs
   1/*
   2 * This file implement the Wireless Extensions core API.
   3 *
   4 * Authors :    Jean Tourrilhes - HPL - <jt@hpl.hp.com>
   5 * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
   6 * Copyright    2009 Johannes Berg <johannes@sipsolutions.net>
   7 *
   8 * (As all part of the Linux kernel, this file is GPL)
   9 */
  10#include <linux/kernel.h>
  11#include <linux/netdevice.h>
  12#include <linux/rtnetlink.h>
  13#include <linux/slab.h>
  14#include <linux/wireless.h>
  15#include <linux/uaccess.h>
  16#include <net/cfg80211.h>
  17#include <net/iw_handler.h>
  18#include <net/netlink.h>
  19#include <net/wext.h>
  20#include <net/net_namespace.h>
  21
  22typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *,
  23                               unsigned int, struct iw_request_info *,
  24                               iw_handler);
  25
  26
  27/*
  28 * Meta-data about all the standard Wireless Extension request we
  29 * know about.
  30 */
  31static const struct iw_ioctl_description standard_ioctl[] = {
  32        [IW_IOCTL_IDX(SIOCSIWCOMMIT)] = {
  33                .header_type    = IW_HEADER_TYPE_NULL,
  34        },
  35        [IW_IOCTL_IDX(SIOCGIWNAME)] = {
  36                .header_type    = IW_HEADER_TYPE_CHAR,
  37                .flags          = IW_DESCR_FLAG_DUMP,
  38        },
  39        [IW_IOCTL_IDX(SIOCSIWNWID)] = {
  40                .header_type    = IW_HEADER_TYPE_PARAM,
  41                .flags          = IW_DESCR_FLAG_EVENT,
  42        },
  43        [IW_IOCTL_IDX(SIOCGIWNWID)] = {
  44                .header_type    = IW_HEADER_TYPE_PARAM,
  45                .flags          = IW_DESCR_FLAG_DUMP,
  46        },
  47        [IW_IOCTL_IDX(SIOCSIWFREQ)] = {
  48                .header_type    = IW_HEADER_TYPE_FREQ,
  49                .flags          = IW_DESCR_FLAG_EVENT,
  50        },
  51        [IW_IOCTL_IDX(SIOCGIWFREQ)] = {
  52                .header_type    = IW_HEADER_TYPE_FREQ,
  53                .flags          = IW_DESCR_FLAG_DUMP,
  54        },
  55        [IW_IOCTL_IDX(SIOCSIWMODE)] = {
  56                .header_type    = IW_HEADER_TYPE_UINT,
  57                .flags          = IW_DESCR_FLAG_EVENT,
  58        },
  59        [IW_IOCTL_IDX(SIOCGIWMODE)] = {
  60                .header_type    = IW_HEADER_TYPE_UINT,
  61                .flags          = IW_DESCR_FLAG_DUMP,
  62        },
  63        [IW_IOCTL_IDX(SIOCSIWSENS)] = {
  64                .header_type    = IW_HEADER_TYPE_PARAM,
  65        },
  66        [IW_IOCTL_IDX(SIOCGIWSENS)] = {
  67                .header_type    = IW_HEADER_TYPE_PARAM,
  68        },
  69        [IW_IOCTL_IDX(SIOCSIWRANGE)] = {
  70                .header_type    = IW_HEADER_TYPE_NULL,
  71        },
  72        [IW_IOCTL_IDX(SIOCGIWRANGE)] = {
  73                .header_type    = IW_HEADER_TYPE_POINT,
  74                .token_size     = 1,
  75                .max_tokens     = sizeof(struct iw_range),
  76                .flags          = IW_DESCR_FLAG_DUMP,
  77        },
  78        [IW_IOCTL_IDX(SIOCSIWPRIV)] = {
  79                .header_type    = IW_HEADER_TYPE_NULL,
  80        },
  81        [IW_IOCTL_IDX(SIOCGIWPRIV)] = { /* (handled directly by us) */
  82                .header_type    = IW_HEADER_TYPE_POINT,
  83                .token_size     = sizeof(struct iw_priv_args),
  84                .max_tokens     = 16,
  85                .flags          = IW_DESCR_FLAG_NOMAX,
  86        },
  87        [IW_IOCTL_IDX(SIOCSIWSTATS)] = {
  88                .header_type    = IW_HEADER_TYPE_NULL,
  89        },
  90        [IW_IOCTL_IDX(SIOCGIWSTATS)] = { /* (handled directly by us) */
  91                .header_type    = IW_HEADER_TYPE_POINT,
  92                .token_size     = 1,
  93                .max_tokens     = sizeof(struct iw_statistics),
  94                .flags          = IW_DESCR_FLAG_DUMP,
  95        },
  96        [IW_IOCTL_IDX(SIOCSIWSPY)] = {
  97                .header_type    = IW_HEADER_TYPE_POINT,
  98                .token_size     = sizeof(struct sockaddr),
  99                .max_tokens     = IW_MAX_SPY,
 100        },
 101        [IW_IOCTL_IDX(SIOCGIWSPY)] = {
 102                .header_type    = IW_HEADER_TYPE_POINT,
 103                .token_size     = sizeof(struct sockaddr) +
 104                                  sizeof(struct iw_quality),
 105                .max_tokens     = IW_MAX_SPY,
 106        },
 107        [IW_IOCTL_IDX(SIOCSIWTHRSPY)] = {
 108                .header_type    = IW_HEADER_TYPE_POINT,
 109                .token_size     = sizeof(struct iw_thrspy),
 110                .min_tokens     = 1,
 111                .max_tokens     = 1,
 112        },
 113        [IW_IOCTL_IDX(SIOCGIWTHRSPY)] = {
 114                .header_type    = IW_HEADER_TYPE_POINT,
 115                .token_size     = sizeof(struct iw_thrspy),
 116                .min_tokens     = 1,
 117                .max_tokens     = 1,
 118        },
 119        [IW_IOCTL_IDX(SIOCSIWAP)] = {
 120                .header_type    = IW_HEADER_TYPE_ADDR,
 121        },
 122        [IW_IOCTL_IDX(SIOCGIWAP)] = {
 123                .header_type    = IW_HEADER_TYPE_ADDR,
 124                .flags          = IW_DESCR_FLAG_DUMP,
 125        },
 126        [IW_IOCTL_IDX(SIOCSIWMLME)] = {
 127                .header_type    = IW_HEADER_TYPE_POINT,
 128                .token_size     = 1,
 129                .min_tokens     = sizeof(struct iw_mlme),
 130                .max_tokens     = sizeof(struct iw_mlme),
 131        },
 132        [IW_IOCTL_IDX(SIOCGIWAPLIST)] = {
 133                .header_type    = IW_HEADER_TYPE_POINT,
 134                .token_size     = sizeof(struct sockaddr) +
 135                                  sizeof(struct iw_quality),
 136                .max_tokens     = IW_MAX_AP,
 137                .flags          = IW_DESCR_FLAG_NOMAX,
 138        },
 139        [IW_IOCTL_IDX(SIOCSIWSCAN)] = {
 140                .header_type    = IW_HEADER_TYPE_POINT,
 141                .token_size     = 1,
 142                .min_tokens     = 0,
 143                .max_tokens     = sizeof(struct iw_scan_req),
 144        },
 145        [IW_IOCTL_IDX(SIOCGIWSCAN)] = {
 146                .header_type    = IW_HEADER_TYPE_POINT,
 147                .token_size     = 1,
 148                .max_tokens     = IW_SCAN_MAX_DATA,
 149                .flags          = IW_DESCR_FLAG_NOMAX,
 150        },
 151        [IW_IOCTL_IDX(SIOCSIWESSID)] = {
 152                .header_type    = IW_HEADER_TYPE_POINT,
 153                .token_size     = 1,
 154                .max_tokens     = IW_ESSID_MAX_SIZE,
 155                .flags          = IW_DESCR_FLAG_EVENT,
 156        },
 157        [IW_IOCTL_IDX(SIOCGIWESSID)] = {
 158                .header_type    = IW_HEADER_TYPE_POINT,
 159                .token_size     = 1,
 160                .max_tokens     = IW_ESSID_MAX_SIZE,
 161                .flags          = IW_DESCR_FLAG_DUMP,
 162        },
 163        [IW_IOCTL_IDX(SIOCSIWNICKN)] = {
 164                .header_type    = IW_HEADER_TYPE_POINT,
 165                .token_size     = 1,
 166                .max_tokens     = IW_ESSID_MAX_SIZE,
 167        },
 168        [IW_IOCTL_IDX(SIOCGIWNICKN)] = {
 169                .header_type    = IW_HEADER_TYPE_POINT,
 170                .token_size     = 1,
 171                .max_tokens     = IW_ESSID_MAX_SIZE,
 172        },
 173        [IW_IOCTL_IDX(SIOCSIWRATE)] = {
 174                .header_type    = IW_HEADER_TYPE_PARAM,
 175        },
 176        [IW_IOCTL_IDX(SIOCGIWRATE)] = {
 177                .header_type    = IW_HEADER_TYPE_PARAM,
 178        },
 179        [IW_IOCTL_IDX(SIOCSIWRTS)] = {
 180                .header_type    = IW_HEADER_TYPE_PARAM,
 181        },
 182        [IW_IOCTL_IDX(SIOCGIWRTS)] = {
 183                .header_type    = IW_HEADER_TYPE_PARAM,
 184        },
 185        [IW_IOCTL_IDX(SIOCSIWFRAG)] = {
 186                .header_type    = IW_HEADER_TYPE_PARAM,
 187        },
 188        [IW_IOCTL_IDX(SIOCGIWFRAG)] = {
 189                .header_type    = IW_HEADER_TYPE_PARAM,
 190        },
 191        [IW_IOCTL_IDX(SIOCSIWTXPOW)] = {
 192                .header_type    = IW_HEADER_TYPE_PARAM,
 193        },
 194        [IW_IOCTL_IDX(SIOCGIWTXPOW)] = {
 195                .header_type    = IW_HEADER_TYPE_PARAM,
 196        },
 197        [IW_IOCTL_IDX(SIOCSIWRETRY)] = {
 198                .header_type    = IW_HEADER_TYPE_PARAM,
 199        },
 200        [IW_IOCTL_IDX(SIOCGIWRETRY)] = {
 201                .header_type    = IW_HEADER_TYPE_PARAM,
 202        },
 203        [IW_IOCTL_IDX(SIOCSIWENCODE)] = {
 204                .header_type    = IW_HEADER_TYPE_POINT,
 205                .token_size     = 1,
 206                .max_tokens     = IW_ENCODING_TOKEN_MAX,
 207                .flags          = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
 208        },
 209        [IW_IOCTL_IDX(SIOCGIWENCODE)] = {
 210                .header_type    = IW_HEADER_TYPE_POINT,
 211                .token_size     = 1,
 212                .max_tokens     = IW_ENCODING_TOKEN_MAX,
 213                .flags          = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
 214        },
 215        [IW_IOCTL_IDX(SIOCSIWPOWER)] = {
 216                .header_type    = IW_HEADER_TYPE_PARAM,
 217        },
 218        [IW_IOCTL_IDX(SIOCGIWPOWER)] = {
 219                .header_type    = IW_HEADER_TYPE_PARAM,
 220        },
 221        [IW_IOCTL_IDX(SIOCSIWGENIE)] = {
 222                .header_type    = IW_HEADER_TYPE_POINT,
 223                .token_size     = 1,
 224                .max_tokens     = IW_GENERIC_IE_MAX,
 225        },
 226        [IW_IOCTL_IDX(SIOCGIWGENIE)] = {
 227                .header_type    = IW_HEADER_TYPE_POINT,
 228                .token_size     = 1,
 229                .max_tokens     = IW_GENERIC_IE_MAX,
 230        },
 231        [IW_IOCTL_IDX(SIOCSIWAUTH)] = {
 232                .header_type    = IW_HEADER_TYPE_PARAM,
 233        },
 234        [IW_IOCTL_IDX(SIOCGIWAUTH)] = {
 235                .header_type    = IW_HEADER_TYPE_PARAM,
 236        },
 237        [IW_IOCTL_IDX(SIOCSIWENCODEEXT)] = {
 238                .header_type    = IW_HEADER_TYPE_POINT,
 239                .token_size     = 1,
 240                .min_tokens     = sizeof(struct iw_encode_ext),
 241                .max_tokens     = sizeof(struct iw_encode_ext) +
 242                                  IW_ENCODING_TOKEN_MAX,
 243        },
 244        [IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = {
 245                .header_type    = IW_HEADER_TYPE_POINT,
 246                .token_size     = 1,
 247                .min_tokens     = sizeof(struct iw_encode_ext),
 248                .max_tokens     = sizeof(struct iw_encode_ext) +
 249                                  IW_ENCODING_TOKEN_MAX,
 250        },
 251        [IW_IOCTL_IDX(SIOCSIWPMKSA)] = {
 252                .header_type    = IW_HEADER_TYPE_POINT,
 253                .token_size     = 1,
 254                .min_tokens     = sizeof(struct iw_pmksa),
 255                .max_tokens     = sizeof(struct iw_pmksa),
 256        },
 257};
 258static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl);
 259
 260/*
 261 * Meta-data about all the additional standard Wireless Extension events
 262 * we know about.
 263 */
 264static const struct iw_ioctl_description standard_event[] = {
 265        [IW_EVENT_IDX(IWEVTXDROP)] = {
 266                .header_type    = IW_HEADER_TYPE_ADDR,
 267        },
 268        [IW_EVENT_IDX(IWEVQUAL)] = {
 269                .header_type    = IW_HEADER_TYPE_QUAL,
 270        },
 271        [IW_EVENT_IDX(IWEVCUSTOM)] = {
 272                .header_type    = IW_HEADER_TYPE_POINT,
 273                .token_size     = 1,
 274                .max_tokens     = IW_CUSTOM_MAX,
 275        },
 276        [IW_EVENT_IDX(IWEVREGISTERED)] = {
 277                .header_type    = IW_HEADER_TYPE_ADDR,
 278        },
 279        [IW_EVENT_IDX(IWEVEXPIRED)] = {
 280                .header_type    = IW_HEADER_TYPE_ADDR,
 281        },
 282        [IW_EVENT_IDX(IWEVGENIE)] = {
 283                .header_type    = IW_HEADER_TYPE_POINT,
 284                .token_size     = 1,
 285                .max_tokens     = IW_GENERIC_IE_MAX,
 286        },
 287        [IW_EVENT_IDX(IWEVMICHAELMICFAILURE)] = {
 288                .header_type    = IW_HEADER_TYPE_POINT,
 289                .token_size     = 1,
 290                .max_tokens     = sizeof(struct iw_michaelmicfailure),
 291        },
 292        [IW_EVENT_IDX(IWEVASSOCREQIE)] = {
 293                .header_type    = IW_HEADER_TYPE_POINT,
 294                .token_size     = 1,
 295                .max_tokens     = IW_GENERIC_IE_MAX,
 296        },
 297        [IW_EVENT_IDX(IWEVASSOCRESPIE)] = {
 298                .header_type    = IW_HEADER_TYPE_POINT,
 299                .token_size     = 1,
 300                .max_tokens     = IW_GENERIC_IE_MAX,
 301        },
 302        [IW_EVENT_IDX(IWEVPMKIDCAND)] = {
 303                .header_type    = IW_HEADER_TYPE_POINT,
 304                .token_size     = 1,
 305                .max_tokens     = sizeof(struct iw_pmkid_cand),
 306        },
 307};
 308static const unsigned standard_event_num = ARRAY_SIZE(standard_event);
 309
 310/* Size (in bytes) of various events */
 311static const int event_type_size[] = {
 312        IW_EV_LCP_LEN,                  /* IW_HEADER_TYPE_NULL */
 313        0,
 314        IW_EV_CHAR_LEN,                 /* IW_HEADER_TYPE_CHAR */
 315        0,
 316        IW_EV_UINT_LEN,                 /* IW_HEADER_TYPE_UINT */
 317        IW_EV_FREQ_LEN,                 /* IW_HEADER_TYPE_FREQ */
 318        IW_EV_ADDR_LEN,                 /* IW_HEADER_TYPE_ADDR */
 319        0,
 320        IW_EV_POINT_LEN,                /* Without variable payload */
 321        IW_EV_PARAM_LEN,                /* IW_HEADER_TYPE_PARAM */
 322        IW_EV_QUAL_LEN,                 /* IW_HEADER_TYPE_QUAL */
 323};
 324
 325#ifdef CONFIG_COMPAT
 326static const int compat_event_type_size[] = {
 327        IW_EV_COMPAT_LCP_LEN,           /* IW_HEADER_TYPE_NULL */
 328        0,
 329        IW_EV_COMPAT_CHAR_LEN,          /* IW_HEADER_TYPE_CHAR */
 330        0,
 331        IW_EV_COMPAT_UINT_LEN,          /* IW_HEADER_TYPE_UINT */
 332        IW_EV_COMPAT_FREQ_LEN,          /* IW_HEADER_TYPE_FREQ */
 333        IW_EV_COMPAT_ADDR_LEN,          /* IW_HEADER_TYPE_ADDR */
 334        0,
 335        IW_EV_COMPAT_POINT_LEN,         /* Without variable payload */
 336        IW_EV_COMPAT_PARAM_LEN,         /* IW_HEADER_TYPE_PARAM */
 337        IW_EV_COMPAT_QUAL_LEN,          /* IW_HEADER_TYPE_QUAL */
 338};
 339#endif
 340
 341
 342/* IW event code */
 343
 344static int __net_init wext_pernet_init(struct net *net)
 345{
 346        skb_queue_head_init(&net->wext_nlevents);
 347        return 0;
 348}
 349
 350static void __net_exit wext_pernet_exit(struct net *net)
 351{
 352        skb_queue_purge(&net->wext_nlevents);
 353}
 354
 355static struct pernet_operations wext_pernet_ops = {
 356        .init = wext_pernet_init,
 357        .exit = wext_pernet_exit,
 358};
 359
 360static int __init wireless_nlevent_init(void)
 361{
 362        return register_pernet_subsys(&wext_pernet_ops);
 363}
 364
 365subsys_initcall(wireless_nlevent_init);
 366
 367/* Process events generated by the wireless layer or the driver. */
 368static void wireless_nlevent_process(struct work_struct *work)
 369{
 370        struct sk_buff *skb;
 371        struct net *net;
 372
 373        rtnl_lock();
 374
 375        for_each_net(net) {
 376                while ((skb = skb_dequeue(&net->wext_nlevents)))
 377                        rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
 378                                    GFP_KERNEL);
 379        }
 380
 381        rtnl_unlock();
 382}
 383
 384static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
 385
 386static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
 387                                              struct sk_buff *skb)
 388{
 389        struct ifinfomsg *r;
 390        struct nlmsghdr  *nlh;
 391
 392        nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
 393        if (!nlh)
 394                return NULL;
 395
 396        r = nlmsg_data(nlh);
 397        r->ifi_family = AF_UNSPEC;
 398        r->__ifi_pad = 0;
 399        r->ifi_type = dev->type;
 400        r->ifi_index = dev->ifindex;
 401        r->ifi_flags = dev_get_flags(dev);
 402        r->ifi_change = 0;      /* Wireless changes don't affect those flags */
 403
 404        NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
 405
 406        return nlh;
 407 nla_put_failure:
 408        nlmsg_cancel(skb, nlh);
 409        return NULL;
 410}
 411
 412
 413/*
 414 * Main event dispatcher. Called from other parts and drivers.
 415 * Send the event on the appropriate channels.
 416 * May be called from interrupt context.
 417 */
 418void wireless_send_event(struct net_device *    dev,
 419                         unsigned int           cmd,
 420                         union iwreq_data *     wrqu,
 421                         const char *           extra)
 422{
 423        const struct iw_ioctl_description *     descr = NULL;
 424        int extra_len = 0;
 425        struct iw_event  *event;                /* Mallocated whole event */
 426        int event_len;                          /* Its size */
 427        int hdr_len;                            /* Size of the event header */
 428        int wrqu_off = 0;                       /* Offset in wrqu */
 429        /* Don't "optimise" the following variable, it will crash */
 430        unsigned        cmd_index;              /* *MUST* be unsigned */
 431        struct sk_buff *skb;
 432        struct nlmsghdr *nlh;
 433        struct nlattr *nla;
 434#ifdef CONFIG_COMPAT
 435        struct __compat_iw_event *compat_event;
 436        struct compat_iw_point compat_wrqu;
 437        struct sk_buff *compskb;
 438#endif
 439
 440        /*
 441         * Nothing in the kernel sends scan events with data, be safe.
 442         * This is necessary because we cannot fix up scan event data
 443         * for compat, due to being contained in 'extra', but normally
 444         * applications are required to retrieve the scan data anyway
 445         * and no data is included in the event, this codifies that
 446         * practice.
 447         */
 448        if (WARN_ON(cmd == SIOCGIWSCAN && extra))
 449                extra = NULL;
 450
 451        /* Get the description of the Event */
 452        if (cmd <= SIOCIWLAST) {
 453                cmd_index = IW_IOCTL_IDX(cmd);
 454                if (cmd_index < standard_ioctl_num)
 455                        descr = &(standard_ioctl[cmd_index]);
 456        } else {
 457                cmd_index = IW_EVENT_IDX(cmd);
 458                if (cmd_index < standard_event_num)
 459                        descr = &(standard_event[cmd_index]);
 460        }
 461        /* Don't accept unknown events */
 462        if (descr == NULL) {
 463                /* Note : we don't return an error to the driver, because
 464                 * the driver would not know what to do about it. It can't
 465                 * return an error to the user, because the event is not
 466                 * initiated by a user request.
 467                 * The best the driver could do is to log an error message.
 468                 * We will do it ourselves instead...
 469                 */
 470                printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
 471                       dev->name, cmd);
 472                return;
 473        }
 474
 475        /* Check extra parameters and set extra_len */
 476        if (descr->header_type == IW_HEADER_TYPE_POINT) {
 477                /* Check if number of token fits within bounds */
 478                if (wrqu->data.length > descr->max_tokens) {
 479                        printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
 480                        return;
 481                }
 482                if (wrqu->data.length < descr->min_tokens) {
 483                        printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
 484                        return;
 485                }
 486                /* Calculate extra_len - extra is NULL for restricted events */
 487                if (extra != NULL)
 488                        extra_len = wrqu->data.length * descr->token_size;
 489                /* Always at an offset in wrqu */
 490                wrqu_off = IW_EV_POINT_OFF;
 491        }
 492
 493        /* Total length of the event */
 494        hdr_len = event_type_size[descr->header_type];
 495        event_len = hdr_len + extra_len;
 496
 497        /*
 498         * The problem for 64/32 bit.
 499         *
 500         * On 64-bit, a regular event is laid out as follows:
 501         *      |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
 502         *      | event.len | event.cmd |     p a d d i n g     |
 503         *      | wrqu data ... (with the correct size)         |
 504         *
 505         * This padding exists because we manipulate event->u,
 506         * and 'event' is not packed.
 507         *
 508         * An iw_point event is laid out like this instead:
 509         *      |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
 510         *      | event.len | event.cmd |     p a d d i n g     |
 511         *      | iwpnt.len | iwpnt.flg |     p a d d i n g     |
 512         *      | extra data  ...
 513         *
 514         * The second padding exists because struct iw_point is extended,
 515         * but this depends on the platform...
 516         *
 517         * On 32-bit, all the padding shouldn't be there.
 518         */
 519
 520        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
 521        if (!skb)
 522                return;
 523
 524        /* Send via the RtNetlink event channel */
 525        nlh = rtnetlink_ifinfo_prep(dev, skb);
 526        if (WARN_ON(!nlh)) {
 527                kfree_skb(skb);
 528                return;
 529        }
 530
 531        /* Add the wireless events in the netlink packet */
 532        nla = nla_reserve(skb, IFLA_WIRELESS, event_len);
 533        if (!nla) {
 534                kfree_skb(skb);
 535                return;
 536        }
 537        event = nla_data(nla);
 538
 539        /* Fill event - first clear to avoid data leaking */
 540        memset(event, 0, hdr_len);
 541        event->len = event_len;
 542        event->cmd = cmd;
 543        memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
 544        if (extra_len)
 545                memcpy(((char *) event) + hdr_len, extra, extra_len);
 546
 547        nlmsg_end(skb, nlh);
 548#ifdef CONFIG_COMPAT
 549        hdr_len = compat_event_type_size[descr->header_type];
 550        event_len = hdr_len + extra_len;
 551
 552        compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
 553        if (!compskb) {
 554                kfree_skb(skb);
 555                return;
 556        }
 557
 558        /* Send via the RtNetlink event channel */
 559        nlh = rtnetlink_ifinfo_prep(dev, compskb);
 560        if (WARN_ON(!nlh)) {
 561                kfree_skb(skb);
 562                kfree_skb(compskb);
 563                return;
 564        }
 565
 566        /* Add the wireless events in the netlink packet */
 567        nla = nla_reserve(compskb, IFLA_WIRELESS, event_len);
 568        if (!nla) {
 569                kfree_skb(skb);
 570                kfree_skb(compskb);
 571                return;
 572        }
 573        compat_event = nla_data(nla);
 574
 575        compat_event->len = event_len;
 576        compat_event->cmd = cmd;
 577        if (descr->header_type == IW_HEADER_TYPE_POINT) {
 578                compat_wrqu.length = wrqu->data.length;
 579                compat_wrqu.flags = wrqu->data.flags;
 580                memcpy(&compat_event->pointer,
 581                        ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF,
 582                        hdr_len - IW_EV_COMPAT_LCP_LEN);
 583                if (extra_len)
 584                        memcpy(((char *) compat_event) + hdr_len,
 585                                extra, extra_len);
 586        } else {
 587                /* extra_len must be zero, so no if (extra) needed */
 588                memcpy(&compat_event->pointer, wrqu,
 589                        hdr_len - IW_EV_COMPAT_LCP_LEN);
 590        }
 591
 592        nlmsg_end(compskb, nlh);
 593
 594        skb_shinfo(skb)->frag_list = compskb;
 595#endif
 596        skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
 597        schedule_work(&wireless_nlevent_work);
 598}
 599EXPORT_SYMBOL(wireless_send_event);
 600
 601
 602
 603/* IW handlers */
 604
 605struct iw_statistics *get_wireless_stats(struct net_device *dev)
 606{
 607#ifdef CONFIG_WIRELESS_EXT
 608        if ((dev->wireless_handlers != NULL) &&
 609           (dev->wireless_handlers->get_wireless_stats != NULL))
 610                return dev->wireless_handlers->get_wireless_stats(dev);
 611#endif
 612
 613#ifdef CONFIG_CFG80211_WEXT
 614        if (dev->ieee80211_ptr &&
 615            dev->ieee80211_ptr->wiphy &&
 616            dev->ieee80211_ptr->wiphy->wext &&
 617            dev->ieee80211_ptr->wiphy->wext->get_wireless_stats)
 618                return dev->ieee80211_ptr->wiphy->wext->get_wireless_stats(dev);
 619#endif
 620
 621        /* not found */
 622        return NULL;
 623}
 624
 625static int iw_handler_get_iwstats(struct net_device *           dev,
 626                                  struct iw_request_info *      info,
 627                                  union iwreq_data *            wrqu,
 628                                  char *                        extra)
 629{
 630        /* Get stats from the driver */
 631        struct iw_statistics *stats;
 632
 633        stats = get_wireless_stats(dev);
 634        if (stats) {
 635                /* Copy statistics to extra */
 636                memcpy(extra, stats, sizeof(struct iw_statistics));
 637                wrqu->data.length = sizeof(struct iw_statistics);
 638
 639                /* Check if we need to clear the updated flag */
 640                if (wrqu->data.flags != 0)
 641                        stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
 642                return 0;
 643        } else
 644                return -EOPNOTSUPP;
 645}
 646
 647static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
 648{
 649        /* Don't "optimise" the following variable, it will crash */
 650        unsigned int    index;          /* *MUST* be unsigned */
 651        const struct iw_handler_def *handlers = NULL;
 652
 653#ifdef CONFIG_CFG80211_WEXT
 654        if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)
 655                handlers = dev->ieee80211_ptr->wiphy->wext;
 656#endif
 657#ifdef CONFIG_WIRELESS_EXT
 658        if (dev->wireless_handlers)
 659                handlers = dev->wireless_handlers;
 660#endif
 661
 662        if (!handlers)
 663                return NULL;
 664
 665        /* Try as a standard command */
 666        index = IW_IOCTL_IDX(cmd);
 667        if (index < handlers->num_standard)
 668                return handlers->standard[index];
 669
 670#ifdef CONFIG_WEXT_PRIV
 671        /* Try as a private command */
 672        index = cmd - SIOCIWFIRSTPRIV;
 673        if (index < handlers->num_private)
 674                return handlers->private[index];
 675#endif
 676
 677        /* Not found */
 678        return NULL;
 679}
 680
 681static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
 682                                   const struct iw_ioctl_description *descr,
 683                                   iw_handler handler, struct net_device *dev,
 684                                   struct iw_request_info *info)
 685{
 686        int err, extra_size, user_length = 0, essid_compat = 0;
 687        char *extra;
 688
 689        /* Calculate space needed by arguments. Always allocate
 690         * for max space.
 691         */
 692        extra_size = descr->max_tokens * descr->token_size;
 693
 694        /* Check need for ESSID compatibility for WE < 21 */
 695        switch (cmd) {
 696        case SIOCSIWESSID:
 697        case SIOCGIWESSID:
 698        case SIOCSIWNICKN:
 699        case SIOCGIWNICKN:
 700                if (iwp->length == descr->max_tokens + 1)
 701                        essid_compat = 1;
 702                else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
 703                        char essid[IW_ESSID_MAX_SIZE + 1];
 704                        unsigned int len;
 705                        len = iwp->length * descr->token_size;
 706
 707                        if (len > IW_ESSID_MAX_SIZE)
 708                                return -EFAULT;
 709
 710                        err = copy_from_user(essid, iwp->pointer, len);
 711                        if (err)
 712                                return -EFAULT;
 713
 714                        if (essid[iwp->length - 1] == '\0')
 715                                essid_compat = 1;
 716                }
 717                break;
 718        default:
 719                break;
 720        }
 721
 722        iwp->length -= essid_compat;
 723
 724        /* Check what user space is giving us */
 725        if (IW_IS_SET(cmd)) {
 726                /* Check NULL pointer */
 727                if (!iwp->pointer && iwp->length != 0)
 728                        return -EFAULT;
 729                /* Check if number of token fits within bounds */
 730                if (iwp->length > descr->max_tokens)
 731                        return -E2BIG;
 732                if (iwp->length < descr->min_tokens)
 733                        return -EINVAL;
 734        } else {
 735                /* Check NULL pointer */
 736                if (!iwp->pointer)
 737                        return -EFAULT;
 738                /* Save user space buffer size for checking */
 739                user_length = iwp->length;
 740
 741                /* Don't check if user_length > max to allow forward
 742                 * compatibility. The test user_length < min is
 743                 * implied by the test at the end.
 744                 */
 745
 746                /* Support for very large requests */
 747                if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
 748                    (user_length > descr->max_tokens)) {
 749                        /* Allow userspace to GET more than max so
 750                         * we can support any size GET requests.
 751                         * There is still a limit : -ENOMEM.
 752                         */
 753                        extra_size = user_length * descr->token_size;
 754
 755                        /* Note : user_length is originally a __u16,
 756                         * and token_size is controlled by us,
 757                         * so extra_size won't get negative and
 758                         * won't overflow...
 759                         */
 760                }
 761        }
 762
 763        /* kzalloc() ensures NULL-termination for essid_compat. */
 764        extra = kzalloc(extra_size, GFP_KERNEL);
 765        if (!extra)
 766                return -ENOMEM;
 767
 768        /* If it is a SET, get all the extra data in here */
 769        if (IW_IS_SET(cmd) && (iwp->length != 0)) {
 770                if (copy_from_user(extra, iwp->pointer,
 771                                   iwp->length *
 772                                   descr->token_size)) {
 773                        err = -EFAULT;
 774                        goto out;
 775                }
 776
 777                if (cmd == SIOCSIWENCODEEXT) {
 778                        struct iw_encode_ext *ee = (void *) extra;
 779
 780                        if (iwp->length < sizeof(*ee) + ee->key_len)
 781                                return -EFAULT;
 782                }
 783        }
 784
 785        if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
 786                /*
 787                 * If this is a GET, but not NOMAX, it means that the extra
 788                 * data is not bounded by userspace, but by max_tokens. Thus
 789                 * set the length to max_tokens. This matches the extra data
 790                 * allocation.
 791                 * The driver should fill it with the number of tokens it
 792                 * provided, and it may check iwp->length rather than having
 793                 * knowledge of max_tokens. If the driver doesn't change the
 794                 * iwp->length, this ioctl just copies back max_token tokens
 795                 * filled with zeroes. Hopefully the driver isn't claiming
 796                 * them to be valid data.
 797                 */
 798                iwp->length = descr->max_tokens;
 799        }
 800
 801        err = handler(dev, info, (union iwreq_data *) iwp, extra);
 802
 803        iwp->length += essid_compat;
 804
 805        /* If we have something to return to the user */
 806        if (!err && IW_IS_GET(cmd)) {
 807                /* Check if there is enough buffer up there */
 808                if (user_length < iwp->length) {
 809                        err = -E2BIG;
 810                        goto out;
 811                }
 812
 813                if (copy_to_user(iwp->pointer, extra,
 814                                 iwp->length *
 815                                 descr->token_size)) {
 816                        err = -EFAULT;
 817                        goto out;
 818                }
 819        }
 820
 821        /* Generate an event to notify listeners of the change */
 822        if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
 823            ((err == 0) || (err == -EIWCOMMIT))) {
 824                union iwreq_data *data = (union iwreq_data *) iwp;
 825
 826                if (descr->flags & IW_DESCR_FLAG_RESTRICT)
 827                        /* If the event is restricted, don't
 828                         * export the payload.
 829                         */
 830                        wireless_send_event(dev, cmd, data, NULL);
 831                else
 832                        wireless_send_event(dev, cmd, data, extra);
 833        }
 834
 835out:
 836        kfree(extra);
 837        return err;
 838}
 839
 840/*
 841 * Call the commit handler in the driver
 842 * (if exist and if conditions are right)
 843 *
 844 * Note : our current commit strategy is currently pretty dumb,
 845 * but we will be able to improve on that...
 846 * The goal is to try to agreagate as many changes as possible
 847 * before doing the commit. Drivers that will define a commit handler
 848 * are usually those that need a reset after changing parameters, so
 849 * we want to minimise the number of reset.
 850 * A cool idea is to use a timer : at each "set" command, we re-set the
 851 * timer, when the timer eventually fires, we call the driver.
 852 * Hopefully, more on that later.
 853 *
 854 * Also, I'm waiting to see how many people will complain about the
 855 * netif_running(dev) test. I'm open on that one...
 856 * Hopefully, the driver will remember to do a commit in "open()" ;-)
 857 */
 858int call_commit_handler(struct net_device *dev)
 859{
 860#ifdef CONFIG_WIRELESS_EXT
 861        if ((netif_running(dev)) &&
 862           (dev->wireless_handlers->standard[0] != NULL))
 863                /* Call the commit handler on the driver */
 864                return dev->wireless_handlers->standard[0](dev, NULL,
 865                                                           NULL, NULL);
 866        else
 867                return 0;               /* Command completed successfully */
 868#else
 869        /* cfg80211 has no commit */
 870        return 0;
 871#endif
 872}
 873
 874/*
 875 * Main IOCTl dispatcher.
 876 * Check the type of IOCTL and call the appropriate wrapper...
 877 */
 878static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
 879                                  unsigned int cmd,
 880                                  struct iw_request_info *info,
 881                                  wext_ioctl_func standard,
 882                                  wext_ioctl_func private)
 883{
 884        struct iwreq *iwr = (struct iwreq *) ifr;
 885        struct net_device *dev;
 886        iw_handler      handler;
 887
 888        /* Permissions are already checked in dev_ioctl() before calling us.
 889         * The copy_to/from_user() of ifr is also dealt with in there */
 890
 891        /* Make sure the device exist */
 892        if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)
 893                return -ENODEV;
 894
 895        /* A bunch of special cases, then the generic case...
 896         * Note that 'cmd' is already filtered in dev_ioctl() with
 897         * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
 898        if (cmd == SIOCGIWSTATS)
 899                return standard(dev, iwr, cmd, info,
 900                                &iw_handler_get_iwstats);
 901
 902#ifdef CONFIG_WEXT_PRIV
 903        if (cmd == SIOCGIWPRIV && dev->wireless_handlers)
 904                return standard(dev, iwr, cmd, info,
 905                                iw_handler_get_private);
 906#endif
 907
 908        /* Basic check */
 909        if (!netif_device_present(dev))
 910                return -ENODEV;
 911
 912        /* New driver API : try to find the handler */
 913        handler = get_handler(dev, cmd);
 914        if (handler) {
 915                /* Standard and private are not the same */
 916                if (cmd < SIOCIWFIRSTPRIV)
 917                        return standard(dev, iwr, cmd, info, handler);
 918                else if (private)
 919                        return private(dev, iwr, cmd, info, handler);
 920        }
 921        /* Old driver API : call driver ioctl handler */
 922        if (dev->netdev_ops->ndo_do_ioctl)
 923                return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
 924        return -EOPNOTSUPP;
 925}
 926
 927/* If command is `set a parameter', or `get the encoding parameters',
 928 * check if the user has the right to do it.
 929 */
 930static int wext_permission_check(unsigned int cmd)
 931{
 932        if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE ||
 933             cmd == SIOCGIWENCODEEXT) &&
 934            !capable(CAP_NET_ADMIN))
 935                return -EPERM;
 936
 937        return 0;
 938}
 939
 940/* entry point from dev ioctl */
 941static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
 942                               unsigned int cmd, struct iw_request_info *info,
 943                               wext_ioctl_func standard,
 944                               wext_ioctl_func private)
 945{
 946        int ret = wext_permission_check(cmd);
 947
 948        if (ret)
 949                return ret;
 950
 951        dev_load(net, ifr->ifr_name);
 952        rtnl_lock();
 953        ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
 954        rtnl_unlock();
 955
 956        return ret;
 957}
 958
 959/*
 960 * Wrapper to call a standard Wireless Extension handler.
 961 * We do various checks and also take care of moving data between
 962 * user space and kernel space.
 963 */
 964static int ioctl_standard_call(struct net_device *      dev,
 965                               struct iwreq             *iwr,
 966                               unsigned int             cmd,
 967                               struct iw_request_info   *info,
 968                               iw_handler               handler)
 969{
 970        const struct iw_ioctl_description *     descr;
 971        int                                     ret = -EINVAL;
 972
 973        /* Get the description of the IOCTL */
 974        if (IW_IOCTL_IDX(cmd) >= standard_ioctl_num)
 975                return -EOPNOTSUPP;
 976        descr = &(standard_ioctl[IW_IOCTL_IDX(cmd)]);
 977
 978        /* Check if we have a pointer to user space data or not */
 979        if (descr->header_type != IW_HEADER_TYPE_POINT) {
 980
 981                /* No extra arguments. Trivial to handle */
 982                ret = handler(dev, info, &(iwr->u), NULL);
 983
 984                /* Generate an event to notify listeners of the change */
 985                if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
 986                   ((ret == 0) || (ret == -EIWCOMMIT)))
 987                        wireless_send_event(dev, cmd, &(iwr->u), NULL);
 988        } else {
 989                ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr,
 990                                              handler, dev, info);
 991        }
 992
 993        /* Call commit handler if needed and defined */
 994        if (ret == -EIWCOMMIT)
 995                ret = call_commit_handler(dev);
 996
 997        /* Here, we will generate the appropriate event if needed */
 998
 999        return ret;
1000}
1001
1002
1003int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
1004                      void __user *arg)
1005{
1006        struct iw_request_info info = { .cmd = cmd, .flags = 0 };
1007        int ret;
1008
1009        ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
1010                                  ioctl_standard_call,
1011                                  ioctl_private_call);
1012        if (ret >= 0 &&
1013            IW_IS_GET(cmd) &&
1014            copy_to_user(arg, ifr, sizeof(struct iwreq)))
1015                return -EFAULT;
1016
1017        return ret;
1018}
1019
1020#ifdef CONFIG_COMPAT
1021static int compat_standard_call(struct net_device       *dev,
1022                                struct iwreq            *iwr,
1023                                unsigned int            cmd,
1024                                struct iw_request_info  *info,
1025                                iw_handler              handler)
1026{
1027        const struct iw_ioctl_description *descr;
1028        struct compat_iw_point *iwp_compat;
1029        struct iw_point iwp;
1030        int err;
1031
1032        descr = standard_ioctl + IW_IOCTL_IDX(cmd);
1033
1034        if (descr->header_type != IW_HEADER_TYPE_POINT)
1035                return ioctl_standard_call(dev, iwr, cmd, info, handler);
1036
1037        iwp_compat = (struct compat_iw_point *) &iwr->u.data;
1038        iwp.pointer = compat_ptr(iwp_compat->pointer);
1039        iwp.length = iwp_compat->length;
1040        iwp.flags = iwp_compat->flags;
1041
1042        err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info);
1043
1044        iwp_compat->pointer = ptr_to_compat(iwp.pointer);
1045        iwp_compat->length = iwp.length;
1046        iwp_compat->flags = iwp.flags;
1047
1048        return err;
1049}
1050
1051int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
1052                             unsigned long arg)
1053{
1054        void __user *argp = (void __user *)arg;
1055        struct iw_request_info info;
1056        struct iwreq iwr;
1057        char *colon;
1058        int ret;
1059
1060        if (copy_from_user(&iwr, argp, sizeof(struct iwreq)))
1061                return -EFAULT;
1062
1063        iwr.ifr_name[IFNAMSIZ-1] = 0;
1064        colon = strchr(iwr.ifr_name, ':');
1065        if (colon)
1066                *colon = 0;
1067
1068        info.cmd = cmd;
1069        info.flags = IW_REQUEST_FLAG_COMPAT;
1070
1071        ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info,
1072                                  compat_standard_call,
1073                                  compat_private_call);
1074
1075        if (ret >= 0 &&
1076            IW_IS_GET(cmd) &&
1077            copy_to_user(argp, &iwr, sizeof(struct iwreq)))
1078                return -EFAULT;
1079
1080        return ret;
1081}
1082#endif
1083