linux/net/wireless/nl80211.c
<<
>>
Prefs
   1/*
   2 * This is the new netlink-based wireless configuration interface.
   3 *
   4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
   5 */
   6
   7#include <linux/if.h>
   8#include <linux/module.h>
   9#include <linux/err.h>
  10#include <linux/mutex.h>
  11#include <linux/list.h>
  12#include <linux/if_ether.h>
  13#include <linux/ieee80211.h>
  14#include <linux/nl80211.h>
  15#include <linux/rtnetlink.h>
  16#include <linux/netlink.h>
  17#include <net/genetlink.h>
  18#include <net/cfg80211.h>
  19#include "core.h"
  20#include "nl80211.h"
  21#include "reg.h"
  22
  23/* the netlink family */
  24static struct genl_family nl80211_fam = {
  25        .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
  26        .name = "nl80211",      /* have users key off the name instead */
  27        .hdrsize = 0,           /* no private header */
  28        .version = 1,           /* no particular meaning now */
  29        .maxattr = NL80211_ATTR_MAX,
  30};
  31
  32/* internal helper: get drv and dev */
  33static int get_drv_dev_by_info_ifindex(struct nlattr **attrs,
  34                                       struct cfg80211_registered_device **drv,
  35                                       struct net_device **dev)
  36{
  37        int ifindex;
  38
  39        if (!attrs[NL80211_ATTR_IFINDEX])
  40                return -EINVAL;
  41
  42        ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
  43        *dev = dev_get_by_index(&init_net, ifindex);
  44        if (!*dev)
  45                return -ENODEV;
  46
  47        *drv = cfg80211_get_dev_from_ifindex(ifindex);
  48        if (IS_ERR(*drv)) {
  49                dev_put(*dev);
  50                return PTR_ERR(*drv);
  51        }
  52
  53        return 0;
  54}
  55
  56/* policy for the attributes */
  57static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
  58        [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
  59        [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
  60                                      .len = BUS_ID_SIZE-1 },
  61
  62        [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
  63        [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
  64        [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
  65
  66        [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
  67
  68        [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
  69                                    .len = WLAN_MAX_KEY_LEN },
  70        [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
  71        [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
  72        [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
  73
  74        [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
  75        [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
  76        [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
  77                                       .len = IEEE80211_MAX_DATA_LEN },
  78        [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
  79                                       .len = IEEE80211_MAX_DATA_LEN },
  80        [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
  81        [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
  82        [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
  83        [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
  84                                               .len = NL80211_MAX_SUPP_RATES },
  85        [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
  86        [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
  87        [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
  88        [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
  89                                .len = IEEE80211_MAX_MESH_ID_LEN },
  90        [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
  91
  92        [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
  93        [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
  94
  95        [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
  96        [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
  97        [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
  98
  99        [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
 100                                         .len = NL80211_HT_CAPABILITY_LEN },
 101};
 102
 103/* message building helper */
 104static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
 105                                   int flags, u8 cmd)
 106{
 107        /* since there is no private header just add the generic one */
 108        return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
 109}
 110
 111/* netlink command implementations */
 112
 113static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 114                              struct cfg80211_registered_device *dev)
 115{
 116        void *hdr;
 117        struct nlattr *nl_bands, *nl_band;
 118        struct nlattr *nl_freqs, *nl_freq;
 119        struct nlattr *nl_rates, *nl_rate;
 120        struct nlattr *nl_modes;
 121        enum ieee80211_band band;
 122        struct ieee80211_channel *chan;
 123        struct ieee80211_rate *rate;
 124        int i;
 125        u16 ifmodes = dev->wiphy.interface_modes;
 126
 127        hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
 128        if (!hdr)
 129                return -1;
 130
 131        NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
 132        NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
 133
 134        nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
 135        if (!nl_modes)
 136                goto nla_put_failure;
 137
 138        i = 0;
 139        while (ifmodes) {
 140                if (ifmodes & 1)
 141                        NLA_PUT_FLAG(msg, i);
 142                ifmodes >>= 1;
 143                i++;
 144        }
 145
 146        nla_nest_end(msg, nl_modes);
 147
 148        nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
 149        if (!nl_bands)
 150                goto nla_put_failure;
 151
 152        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 153                if (!dev->wiphy.bands[band])
 154                        continue;
 155
 156                nl_band = nla_nest_start(msg, band);
 157                if (!nl_band)
 158                        goto nla_put_failure;
 159
 160                /* add frequencies */
 161                nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
 162                if (!nl_freqs)
 163                        goto nla_put_failure;
 164
 165                for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
 166                        nl_freq = nla_nest_start(msg, i);
 167                        if (!nl_freq)
 168                                goto nla_put_failure;
 169
 170                        chan = &dev->wiphy.bands[band]->channels[i];
 171                        NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
 172                                    chan->center_freq);
 173
 174                        if (chan->flags & IEEE80211_CHAN_DISABLED)
 175                                NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
 176                        if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 177                                NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
 178                        if (chan->flags & IEEE80211_CHAN_NO_IBSS)
 179                                NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
 180                        if (chan->flags & IEEE80211_CHAN_RADAR)
 181                                NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
 182
 183                        nla_nest_end(msg, nl_freq);
 184                }
 185
 186                nla_nest_end(msg, nl_freqs);
 187
 188                /* add bitrates */
 189                nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
 190                if (!nl_rates)
 191                        goto nla_put_failure;
 192
 193                for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
 194                        nl_rate = nla_nest_start(msg, i);
 195                        if (!nl_rate)
 196                                goto nla_put_failure;
 197
 198                        rate = &dev->wiphy.bands[band]->bitrates[i];
 199                        NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
 200                                    rate->bitrate);
 201                        if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
 202                                NLA_PUT_FLAG(msg,
 203                                        NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
 204
 205                        nla_nest_end(msg, nl_rate);
 206                }
 207
 208                nla_nest_end(msg, nl_rates);
 209
 210                nla_nest_end(msg, nl_band);
 211        }
 212        nla_nest_end(msg, nl_bands);
 213
 214        return genlmsg_end(msg, hdr);
 215
 216 nla_put_failure:
 217        genlmsg_cancel(msg, hdr);
 218        return -EMSGSIZE;
 219}
 220
 221static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
 222{
 223        int idx = 0;
 224        int start = cb->args[0];
 225        struct cfg80211_registered_device *dev;
 226
 227        mutex_lock(&cfg80211_drv_mutex);
 228        list_for_each_entry(dev, &cfg80211_drv_list, list) {
 229                if (++idx <= start)
 230                        continue;
 231                if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
 232                                       cb->nlh->nlmsg_seq, NLM_F_MULTI,
 233                                       dev) < 0) {
 234                        idx--;
 235                        break;
 236                }
 237        }
 238        mutex_unlock(&cfg80211_drv_mutex);
 239
 240        cb->args[0] = idx;
 241
 242        return skb->len;
 243}
 244
 245static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
 246{
 247        struct sk_buff *msg;
 248        struct cfg80211_registered_device *dev;
 249
 250        dev = cfg80211_get_dev_from_info(info);
 251        if (IS_ERR(dev))
 252                return PTR_ERR(dev);
 253
 254        msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
 255        if (!msg)
 256                goto out_err;
 257
 258        if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
 259                goto out_free;
 260
 261        cfg80211_put_dev(dev);
 262
 263        return genlmsg_unicast(msg, info->snd_pid);
 264
 265 out_free:
 266        nlmsg_free(msg);
 267 out_err:
 268        cfg80211_put_dev(dev);
 269        return -ENOBUFS;
 270}
 271
 272static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 273{
 274        struct cfg80211_registered_device *rdev;
 275        int result;
 276
 277        if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
 278                return -EINVAL;
 279
 280        rdev = cfg80211_get_dev_from_info(info);
 281        if (IS_ERR(rdev))
 282                return PTR_ERR(rdev);
 283
 284        result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
 285
 286        cfg80211_put_dev(rdev);
 287        return result;
 288}
 289
 290
 291static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 292                              struct net_device *dev)
 293{
 294        void *hdr;
 295
 296        hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
 297        if (!hdr)
 298                return -1;
 299
 300        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
 301        NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
 302        NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
 303        return genlmsg_end(msg, hdr);
 304
 305 nla_put_failure:
 306        genlmsg_cancel(msg, hdr);
 307        return -EMSGSIZE;
 308}
 309
 310static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
 311{
 312        int wp_idx = 0;
 313        int if_idx = 0;
 314        int wp_start = cb->args[0];
 315        int if_start = cb->args[1];
 316        struct cfg80211_registered_device *dev;
 317        struct wireless_dev *wdev;
 318
 319        mutex_lock(&cfg80211_drv_mutex);
 320        list_for_each_entry(dev, &cfg80211_drv_list, list) {
 321                if (wp_idx < wp_start) {
 322                        wp_idx++;
 323                        continue;
 324                }
 325                if_idx = 0;
 326
 327                mutex_lock(&dev->devlist_mtx);
 328                list_for_each_entry(wdev, &dev->netdev_list, list) {
 329                        if (if_idx < if_start) {
 330                                if_idx++;
 331                                continue;
 332                        }
 333                        if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
 334                                               cb->nlh->nlmsg_seq, NLM_F_MULTI,
 335                                               wdev->netdev) < 0) {
 336                                mutex_unlock(&dev->devlist_mtx);
 337                                goto out;
 338                        }
 339                        if_idx++;
 340                }
 341                mutex_unlock(&dev->devlist_mtx);
 342
 343                wp_idx++;
 344        }
 345 out:
 346        mutex_unlock(&cfg80211_drv_mutex);
 347
 348        cb->args[0] = wp_idx;
 349        cb->args[1] = if_idx;
 350
 351        return skb->len;
 352}
 353
 354static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
 355{
 356        struct sk_buff *msg;
 357        struct cfg80211_registered_device *dev;
 358        struct net_device *netdev;
 359        int err;
 360
 361        err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev);
 362        if (err)
 363                return err;
 364
 365        msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
 366        if (!msg)
 367                goto out_err;
 368
 369        if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
 370                goto out_free;
 371
 372        dev_put(netdev);
 373        cfg80211_put_dev(dev);
 374
 375        return genlmsg_unicast(msg, info->snd_pid);
 376
 377 out_free:
 378        nlmsg_free(msg);
 379 out_err:
 380        dev_put(netdev);
 381        cfg80211_put_dev(dev);
 382        return -ENOBUFS;
 383}
 384
 385static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
 386        [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
 387        [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
 388        [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
 389        [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
 390        [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
 391};
 392
 393static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
 394{
 395        struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
 396        int flag;
 397
 398        *mntrflags = 0;
 399
 400        if (!nla)
 401                return -EINVAL;
 402
 403        if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
 404                             nla, mntr_flags_policy))
 405                return -EINVAL;
 406
 407        for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
 408                if (flags[flag])
 409                        *mntrflags |= (1<<flag);
 410
 411        return 0;
 412}
 413
 414static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
 415{
 416        struct cfg80211_registered_device *drv;
 417        struct vif_params params;
 418        int err, ifindex;
 419        enum nl80211_iftype type;
 420        struct net_device *dev;
 421        u32 _flags, *flags = NULL;
 422
 423        memset(&params, 0, sizeof(params));
 424
 425        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 426        if (err)
 427                return err;
 428        ifindex = dev->ifindex;
 429        type = dev->ieee80211_ptr->iftype;
 430        dev_put(dev);
 431
 432        err = -EINVAL;
 433        if (info->attrs[NL80211_ATTR_IFTYPE]) {
 434                type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
 435                if (type > NL80211_IFTYPE_MAX)
 436                        goto unlock;
 437        }
 438
 439        if (!drv->ops->change_virtual_intf ||
 440            !(drv->wiphy.interface_modes & (1 << type))) {
 441                err = -EOPNOTSUPP;
 442                goto unlock;
 443        }
 444
 445        if (info->attrs[NL80211_ATTR_MESH_ID]) {
 446                if (type != NL80211_IFTYPE_MESH_POINT) {
 447                        err = -EINVAL;
 448                        goto unlock;
 449                }
 450                params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
 451                params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
 452        }
 453
 454        if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
 455                if (type != NL80211_IFTYPE_MONITOR) {
 456                        err = -EINVAL;
 457                        goto unlock;
 458                }
 459                err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
 460                                          &_flags);
 461                if (!err)
 462                        flags = &_flags;
 463        }
 464        rtnl_lock();
 465        err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
 466                                            type, flags, &params);
 467
 468        dev = __dev_get_by_index(&init_net, ifindex);
 469        WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
 470
 471        rtnl_unlock();
 472
 473 unlock:
 474        cfg80211_put_dev(drv);
 475        return err;
 476}
 477
 478static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
 479{
 480        struct cfg80211_registered_device *drv;
 481        struct vif_params params;
 482        int err;
 483        enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
 484        u32 flags;
 485
 486        memset(&params, 0, sizeof(params));
 487
 488        if (!info->attrs[NL80211_ATTR_IFNAME])
 489                return -EINVAL;
 490
 491        if (info->attrs[NL80211_ATTR_IFTYPE]) {
 492                type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
 493                if (type > NL80211_IFTYPE_MAX)
 494                        return -EINVAL;
 495        }
 496
 497        drv = cfg80211_get_dev_from_info(info);
 498        if (IS_ERR(drv))
 499                return PTR_ERR(drv);
 500
 501        if (!drv->ops->add_virtual_intf ||
 502            !(drv->wiphy.interface_modes & (1 << type))) {
 503                err = -EOPNOTSUPP;
 504                goto unlock;
 505        }
 506
 507        if (type == NL80211_IFTYPE_MESH_POINT &&
 508            info->attrs[NL80211_ATTR_MESH_ID]) {
 509                params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
 510                params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
 511        }
 512
 513        rtnl_lock();
 514        err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
 515                                  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
 516                                  &flags);
 517        err = drv->ops->add_virtual_intf(&drv->wiphy,
 518                nla_data(info->attrs[NL80211_ATTR_IFNAME]),
 519                type, err ? NULL : &flags, &params);
 520        rtnl_unlock();
 521
 522
 523 unlock:
 524        cfg80211_put_dev(drv);
 525        return err;
 526}
 527
 528static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
 529{
 530        struct cfg80211_registered_device *drv;
 531        int ifindex, err;
 532        struct net_device *dev;
 533
 534        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 535        if (err)
 536                return err;
 537        ifindex = dev->ifindex;
 538        dev_put(dev);
 539
 540        if (!drv->ops->del_virtual_intf) {
 541                err = -EOPNOTSUPP;
 542                goto out;
 543        }
 544
 545        rtnl_lock();
 546        err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
 547        rtnl_unlock();
 548
 549 out:
 550        cfg80211_put_dev(drv);
 551        return err;
 552}
 553
 554struct get_key_cookie {
 555        struct sk_buff *msg;
 556        int error;
 557};
 558
 559static void get_key_callback(void *c, struct key_params *params)
 560{
 561        struct get_key_cookie *cookie = c;
 562
 563        if (params->key)
 564                NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
 565                        params->key_len, params->key);
 566
 567        if (params->seq)
 568                NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
 569                        params->seq_len, params->seq);
 570
 571        if (params->cipher)
 572                NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
 573                            params->cipher);
 574
 575        return;
 576 nla_put_failure:
 577        cookie->error = 1;
 578}
 579
 580static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 581{
 582        struct cfg80211_registered_device *drv;
 583        int err;
 584        struct net_device *dev;
 585        u8 key_idx = 0;
 586        u8 *mac_addr = NULL;
 587        struct get_key_cookie cookie = {
 588                .error = 0,
 589        };
 590        void *hdr;
 591        struct sk_buff *msg;
 592
 593        if (info->attrs[NL80211_ATTR_KEY_IDX])
 594                key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 595
 596        if (key_idx > 3)
 597                return -EINVAL;
 598
 599        if (info->attrs[NL80211_ATTR_MAC])
 600                mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 601
 602        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 603        if (err)
 604                return err;
 605
 606        if (!drv->ops->get_key) {
 607                err = -EOPNOTSUPP;
 608                goto out;
 609        }
 610
 611        msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
 612        if (!msg) {
 613                err = -ENOMEM;
 614                goto out;
 615        }
 616
 617        hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 618                             NL80211_CMD_NEW_KEY);
 619
 620        if (IS_ERR(hdr)) {
 621                err = PTR_ERR(hdr);
 622                goto out;
 623        }
 624
 625        cookie.msg = msg;
 626
 627        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
 628        NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
 629        if (mac_addr)
 630                NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
 631
 632        rtnl_lock();
 633        err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
 634                                &cookie, get_key_callback);
 635        rtnl_unlock();
 636
 637        if (err)
 638                goto out;
 639
 640        if (cookie.error)
 641                goto nla_put_failure;
 642
 643        genlmsg_end(msg, hdr);
 644        err = genlmsg_unicast(msg, info->snd_pid);
 645        goto out;
 646
 647 nla_put_failure:
 648        err = -ENOBUFS;
 649        nlmsg_free(msg);
 650 out:
 651        cfg80211_put_dev(drv);
 652        dev_put(dev);
 653        return err;
 654}
 655
 656static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 657{
 658        struct cfg80211_registered_device *drv;
 659        int err;
 660        struct net_device *dev;
 661        u8 key_idx;
 662
 663        if (!info->attrs[NL80211_ATTR_KEY_IDX])
 664                return -EINVAL;
 665
 666        key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 667
 668        if (key_idx > 3)
 669                return -EINVAL;
 670
 671        /* currently only support setting default key */
 672        if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
 673                return -EINVAL;
 674
 675        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 676        if (err)
 677                return err;
 678
 679        if (!drv->ops->set_default_key) {
 680                err = -EOPNOTSUPP;
 681                goto out;
 682        }
 683
 684        rtnl_lock();
 685        err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
 686        rtnl_unlock();
 687
 688 out:
 689        cfg80211_put_dev(drv);
 690        dev_put(dev);
 691        return err;
 692}
 693
 694static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
 695{
 696        struct cfg80211_registered_device *drv;
 697        int err;
 698        struct net_device *dev;
 699        struct key_params params;
 700        u8 key_idx = 0;
 701        u8 *mac_addr = NULL;
 702
 703        memset(&params, 0, sizeof(params));
 704
 705        if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
 706                return -EINVAL;
 707
 708        if (info->attrs[NL80211_ATTR_KEY_DATA]) {
 709                params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
 710                params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
 711        }
 712
 713        if (info->attrs[NL80211_ATTR_KEY_IDX])
 714                key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 715
 716        params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
 717
 718        if (info->attrs[NL80211_ATTR_MAC])
 719                mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 720
 721        if (key_idx > 3)
 722                return -EINVAL;
 723
 724        /*
 725         * Disallow pairwise keys with non-zero index unless it's WEP
 726         * (because current deployments use pairwise WEP keys with
 727         * non-zero indizes but 802.11i clearly specifies to use zero)
 728         */
 729        if (mac_addr && key_idx &&
 730            params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
 731            params.cipher != WLAN_CIPHER_SUITE_WEP104)
 732                return -EINVAL;
 733
 734        /* TODO: add definitions for the lengths to linux/ieee80211.h */
 735        switch (params.cipher) {
 736        case WLAN_CIPHER_SUITE_WEP40:
 737                if (params.key_len != 5)
 738                        return -EINVAL;
 739                break;
 740        case WLAN_CIPHER_SUITE_TKIP:
 741                if (params.key_len != 32)
 742                        return -EINVAL;
 743                break;
 744        case WLAN_CIPHER_SUITE_CCMP:
 745                if (params.key_len != 16)
 746                        return -EINVAL;
 747                break;
 748        case WLAN_CIPHER_SUITE_WEP104:
 749                if (params.key_len != 13)
 750                        return -EINVAL;
 751                break;
 752        default:
 753                return -EINVAL;
 754        }
 755
 756        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 757        if (err)
 758                return err;
 759
 760        if (!drv->ops->add_key) {
 761                err = -EOPNOTSUPP;
 762                goto out;
 763        }
 764
 765        rtnl_lock();
 766        err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
 767        rtnl_unlock();
 768
 769 out:
 770        cfg80211_put_dev(drv);
 771        dev_put(dev);
 772        return err;
 773}
 774
 775static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
 776{
 777        struct cfg80211_registered_device *drv;
 778        int err;
 779        struct net_device *dev;
 780        u8 key_idx = 0;
 781        u8 *mac_addr = NULL;
 782
 783        if (info->attrs[NL80211_ATTR_KEY_IDX])
 784                key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 785
 786        if (key_idx > 3)
 787                return -EINVAL;
 788
 789        if (info->attrs[NL80211_ATTR_MAC])
 790                mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 791
 792        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 793        if (err)
 794                return err;
 795
 796        if (!drv->ops->del_key) {
 797                err = -EOPNOTSUPP;
 798                goto out;
 799        }
 800
 801        rtnl_lock();
 802        err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
 803        rtnl_unlock();
 804
 805 out:
 806        cfg80211_put_dev(drv);
 807        dev_put(dev);
 808        return err;
 809}
 810
 811static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
 812{
 813        int (*call)(struct wiphy *wiphy, struct net_device *dev,
 814                    struct beacon_parameters *info);
 815        struct cfg80211_registered_device *drv;
 816        int err;
 817        struct net_device *dev;
 818        struct beacon_parameters params;
 819        int haveinfo = 0;
 820
 821        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 822        if (err)
 823                return err;
 824
 825        switch (info->genlhdr->cmd) {
 826        case NL80211_CMD_NEW_BEACON:
 827                /* these are required for NEW_BEACON */
 828                if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
 829                    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
 830                    !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
 831                        err = -EINVAL;
 832                        goto out;
 833                }
 834
 835                call = drv->ops->add_beacon;
 836                break;
 837        case NL80211_CMD_SET_BEACON:
 838                call = drv->ops->set_beacon;
 839                break;
 840        default:
 841                WARN_ON(1);
 842                err = -EOPNOTSUPP;
 843                goto out;
 844        }
 845
 846        if (!call) {
 847                err = -EOPNOTSUPP;
 848                goto out;
 849        }
 850
 851        memset(&params, 0, sizeof(params));
 852
 853        if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
 854                params.interval =
 855                    nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
 856                haveinfo = 1;
 857        }
 858
 859        if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
 860                params.dtim_period =
 861                    nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
 862                haveinfo = 1;
 863        }
 864
 865        if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
 866                params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
 867                params.head_len =
 868                    nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
 869                haveinfo = 1;
 870        }
 871
 872        if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
 873                params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
 874                params.tail_len =
 875                    nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
 876                haveinfo = 1;
 877        }
 878
 879        if (!haveinfo) {
 880                err = -EINVAL;
 881                goto out;
 882        }
 883
 884        rtnl_lock();
 885        err = call(&drv->wiphy, dev, &params);
 886        rtnl_unlock();
 887
 888 out:
 889        cfg80211_put_dev(drv);
 890        dev_put(dev);
 891        return err;
 892}
 893
 894static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
 895{
 896        struct cfg80211_registered_device *drv;
 897        int err;
 898        struct net_device *dev;
 899
 900        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 901        if (err)
 902                return err;
 903
 904        if (!drv->ops->del_beacon) {
 905                err = -EOPNOTSUPP;
 906                goto out;
 907        }
 908
 909        rtnl_lock();
 910        err = drv->ops->del_beacon(&drv->wiphy, dev);
 911        rtnl_unlock();
 912
 913 out:
 914        cfg80211_put_dev(drv);
 915        dev_put(dev);
 916        return err;
 917}
 918
 919static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
 920        [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
 921        [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
 922        [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
 923};
 924
 925static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 926{
 927        struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
 928        int flag;
 929
 930        *staflags = 0;
 931
 932        if (!nla)
 933                return 0;
 934
 935        if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
 936                             nla, sta_flags_policy))
 937                return -EINVAL;
 938
 939        *staflags = STATION_FLAG_CHANGED;
 940
 941        for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
 942                if (flags[flag])
 943                        *staflags |= (1<<flag);
 944
 945        return 0;
 946}
 947
 948static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 949                                int flags, struct net_device *dev,
 950                                u8 *mac_addr, struct station_info *sinfo)
 951{
 952        void *hdr;
 953        struct nlattr *sinfoattr;
 954
 955        hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 956        if (!hdr)
 957                return -1;
 958
 959        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
 960        NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
 961
 962        sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
 963        if (!sinfoattr)
 964                goto nla_put_failure;
 965        if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
 966                NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
 967                            sinfo->inactive_time);
 968        if (sinfo->filled & STATION_INFO_RX_BYTES)
 969                NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
 970                            sinfo->rx_bytes);
 971        if (sinfo->filled & STATION_INFO_TX_BYTES)
 972                NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
 973                            sinfo->tx_bytes);
 974        if (sinfo->filled & STATION_INFO_LLID)
 975                NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
 976                            sinfo->llid);
 977        if (sinfo->filled & STATION_INFO_PLID)
 978                NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
 979                            sinfo->plid);
 980        if (sinfo->filled & STATION_INFO_PLINK_STATE)
 981                NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 982                            sinfo->plink_state);
 983
 984        nla_nest_end(msg, sinfoattr);
 985
 986        return genlmsg_end(msg, hdr);
 987
 988 nla_put_failure:
 989        genlmsg_cancel(msg, hdr);
 990        return -EMSGSIZE;
 991}
 992
 993static int nl80211_dump_station(struct sk_buff *skb,
 994                                struct netlink_callback *cb)
 995{
 996        struct station_info sinfo;
 997        struct cfg80211_registered_device *dev;
 998        struct net_device *netdev;
 999        u8 mac_addr[ETH_ALEN];
1000        int ifidx = cb->args[0];
1001        int sta_idx = cb->args[1];
1002        int err;
1003
1004        if (!ifidx) {
1005                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1006                                  nl80211_fam.attrbuf, nl80211_fam.maxattr,
1007                                  nl80211_policy);
1008                if (err)
1009                        return err;
1010
1011                if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1012                        return -EINVAL;
1013
1014                ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1015                if (!ifidx)
1016                        return -EINVAL;
1017        }
1018
1019        netdev = dev_get_by_index(&init_net, ifidx);
1020        if (!netdev)
1021                return -ENODEV;
1022
1023        dev = cfg80211_get_dev_from_ifindex(ifidx);
1024        if (IS_ERR(dev)) {
1025                err = PTR_ERR(dev);
1026                goto out_put_netdev;
1027        }
1028
1029        if (!dev->ops->dump_station) {
1030                err = -ENOSYS;
1031                goto out_err;
1032        }
1033
1034        rtnl_lock();
1035
1036        while (1) {
1037                err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
1038                                             mac_addr, &sinfo);
1039                if (err == -ENOENT)
1040                        break;
1041                if (err)
1042                        goto out_err_rtnl;
1043
1044                if (nl80211_send_station(skb,
1045                                NETLINK_CB(cb->skb).pid,
1046                                cb->nlh->nlmsg_seq, NLM_F_MULTI,
1047                                netdev, mac_addr,
1048                                &sinfo) < 0)
1049                        goto out;
1050
1051                sta_idx++;
1052        }
1053
1054
1055 out:
1056        cb->args[1] = sta_idx;
1057        err = skb->len;
1058 out_err_rtnl:
1059        rtnl_unlock();
1060 out_err:
1061        cfg80211_put_dev(dev);
1062 out_put_netdev:
1063        dev_put(netdev);
1064
1065        return err;
1066}
1067
1068static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1069{
1070        struct cfg80211_registered_device *drv;
1071        int err;
1072        struct net_device *dev;
1073        struct station_info sinfo;
1074        struct sk_buff *msg;
1075        u8 *mac_addr = NULL;
1076
1077        memset(&sinfo, 0, sizeof(sinfo));
1078
1079        if (!info->attrs[NL80211_ATTR_MAC])
1080                return -EINVAL;
1081
1082        mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1083
1084        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1085        if (err)
1086                return err;
1087
1088        if (!drv->ops->get_station) {
1089                err = -EOPNOTSUPP;
1090                goto out;
1091        }
1092
1093        rtnl_lock();
1094        err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
1095        rtnl_unlock();
1096
1097        if (err)
1098                goto out;
1099
1100        msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1101        if (!msg)
1102                goto out;
1103
1104        if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
1105                                 dev, mac_addr, &sinfo) < 0)
1106                goto out_free;
1107
1108        err = genlmsg_unicast(msg, info->snd_pid);
1109        goto out;
1110
1111 out_free:
1112        nlmsg_free(msg);
1113
1114 out:
1115        cfg80211_put_dev(drv);
1116        dev_put(dev);
1117        return err;
1118}
1119
1120/*
1121 * Get vlan interface making sure it is on the right wiphy.
1122 */
1123static int get_vlan(struct nlattr *vlanattr,
1124                    struct cfg80211_registered_device *rdev,
1125                    struct net_device **vlan)
1126{
1127        *vlan = NULL;
1128
1129        if (vlanattr) {
1130                *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
1131                if (!*vlan)
1132                        return -ENODEV;
1133                if (!(*vlan)->ieee80211_ptr)
1134                        return -EINVAL;
1135                if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1136                        return -EINVAL;
1137        }
1138        return 0;
1139}
1140
1141static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1142{
1143        struct cfg80211_registered_device *drv;
1144        int err;
1145        struct net_device *dev;
1146        struct station_parameters params;
1147        u8 *mac_addr = NULL;
1148
1149        memset(&params, 0, sizeof(params));
1150
1151        params.listen_interval = -1;
1152
1153        if (info->attrs[NL80211_ATTR_STA_AID])
1154                return -EINVAL;
1155
1156        if (!info->attrs[NL80211_ATTR_MAC])
1157                return -EINVAL;
1158
1159        mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1160
1161        if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
1162                params.supported_rates =
1163                        nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1164                params.supported_rates_len =
1165                        nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1166        }
1167
1168        if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1169                params.listen_interval =
1170                    nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1171
1172        if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1173                params.ht_capa =
1174                        nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1175
1176        if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1177                                &params.station_flags))
1178                return -EINVAL;
1179
1180        if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
1181                params.plink_action =
1182                    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1183
1184        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1185        if (err)
1186                return err;
1187
1188        err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1189        if (err)
1190                goto out;
1191
1192        if (!drv->ops->change_station) {
1193                err = -EOPNOTSUPP;
1194                goto out;
1195        }
1196
1197        rtnl_lock();
1198        err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
1199        rtnl_unlock();
1200
1201 out:
1202        if (params.vlan)
1203                dev_put(params.vlan);
1204        cfg80211_put_dev(drv);
1205        dev_put(dev);
1206        return err;
1207}
1208
1209static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1210{
1211        struct cfg80211_registered_device *drv;
1212        int err;
1213        struct net_device *dev;
1214        struct station_parameters params;
1215        u8 *mac_addr = NULL;
1216
1217        memset(&params, 0, sizeof(params));
1218
1219        if (!info->attrs[NL80211_ATTR_MAC])
1220                return -EINVAL;
1221
1222        if (!info->attrs[NL80211_ATTR_STA_AID])
1223                return -EINVAL;
1224
1225        if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1226                return -EINVAL;
1227
1228        if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
1229                return -EINVAL;
1230
1231        mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1232        params.supported_rates =
1233                nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1234        params.supported_rates_len =
1235                nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1236        params.listen_interval =
1237                nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1238        params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1239        if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1240                params.ht_capa =
1241                        nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1242
1243        if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1244                                &params.station_flags))
1245                return -EINVAL;
1246
1247        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1248        if (err)
1249                return err;
1250
1251        err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1252        if (err)
1253                goto out;
1254
1255        if (!drv->ops->add_station) {
1256                err = -EOPNOTSUPP;
1257                goto out;
1258        }
1259
1260        rtnl_lock();
1261        err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
1262        rtnl_unlock();
1263
1264 out:
1265        if (params.vlan)
1266                dev_put(params.vlan);
1267        cfg80211_put_dev(drv);
1268        dev_put(dev);
1269        return err;
1270}
1271
1272static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1273{
1274        struct cfg80211_registered_device *drv;
1275        int err;
1276        struct net_device *dev;
1277        u8 *mac_addr = NULL;
1278
1279        if (info->attrs[NL80211_ATTR_MAC])
1280                mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1281
1282        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1283        if (err)
1284                return err;
1285
1286        if (!drv->ops->del_station) {
1287                err = -EOPNOTSUPP;
1288                goto out;
1289        }
1290
1291        rtnl_lock();
1292        err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1293        rtnl_unlock();
1294
1295 out:
1296        cfg80211_put_dev(drv);
1297        dev_put(dev);
1298        return err;
1299}
1300
1301static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
1302                                int flags, struct net_device *dev,
1303                                u8 *dst, u8 *next_hop,
1304                                struct mpath_info *pinfo)
1305{
1306        void *hdr;
1307        struct nlattr *pinfoattr;
1308
1309        hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1310        if (!hdr)
1311                return -1;
1312
1313        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1314        NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
1315        NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
1316
1317        pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
1318        if (!pinfoattr)
1319                goto nla_put_failure;
1320        if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
1321                NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
1322                            pinfo->frame_qlen);
1323        if (pinfo->filled & MPATH_INFO_DSN)
1324                NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
1325                            pinfo->dsn);
1326        if (pinfo->filled & MPATH_INFO_METRIC)
1327                NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
1328                            pinfo->metric);
1329        if (pinfo->filled & MPATH_INFO_EXPTIME)
1330                NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
1331                            pinfo->exptime);
1332        if (pinfo->filled & MPATH_INFO_FLAGS)
1333                NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
1334                            pinfo->flags);
1335        if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
1336                NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
1337                            pinfo->discovery_timeout);
1338        if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
1339                NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
1340                            pinfo->discovery_retries);
1341
1342        nla_nest_end(msg, pinfoattr);
1343
1344        return genlmsg_end(msg, hdr);
1345
1346 nla_put_failure:
1347        genlmsg_cancel(msg, hdr);
1348        return -EMSGSIZE;
1349}
1350
1351static int nl80211_dump_mpath(struct sk_buff *skb,
1352                              struct netlink_callback *cb)
1353{
1354        struct mpath_info pinfo;
1355        struct cfg80211_registered_device *dev;
1356        struct net_device *netdev;
1357        u8 dst[ETH_ALEN];
1358        u8 next_hop[ETH_ALEN];
1359        int ifidx = cb->args[0];
1360        int path_idx = cb->args[1];
1361        int err;
1362
1363        if (!ifidx) {
1364                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1365                                  nl80211_fam.attrbuf, nl80211_fam.maxattr,
1366                                  nl80211_policy);
1367                if (err)
1368                        return err;
1369
1370                if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1371                        return -EINVAL;
1372
1373                ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1374                if (!ifidx)
1375                        return -EINVAL;
1376        }
1377
1378        netdev = dev_get_by_index(&init_net, ifidx);
1379        if (!netdev)
1380                return -ENODEV;
1381
1382        dev = cfg80211_get_dev_from_ifindex(ifidx);
1383        if (IS_ERR(dev)) {
1384                err = PTR_ERR(dev);
1385                goto out_put_netdev;
1386        }
1387
1388        if (!dev->ops->dump_mpath) {
1389                err = -ENOSYS;
1390                goto out_err;
1391        }
1392
1393        rtnl_lock();
1394
1395        while (1) {
1396                err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
1397                                           dst, next_hop, &pinfo);
1398                if (err == -ENOENT)
1399                        break;
1400                if (err)
1401                        goto out_err_rtnl;
1402
1403                if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
1404                                       cb->nlh->nlmsg_seq, NLM_F_MULTI,
1405                                       netdev, dst, next_hop,
1406                                       &pinfo) < 0)
1407                        goto out;
1408
1409                path_idx++;
1410        }
1411
1412
1413 out:
1414        cb->args[1] = path_idx;
1415        err = skb->len;
1416 out_err_rtnl:
1417        rtnl_unlock();
1418 out_err:
1419        cfg80211_put_dev(dev);
1420 out_put_netdev:
1421        dev_put(netdev);
1422
1423        return err;
1424}
1425
1426static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1427{
1428        struct cfg80211_registered_device *drv;
1429        int err;
1430        struct net_device *dev;
1431        struct mpath_info pinfo;
1432        struct sk_buff *msg;
1433        u8 *dst = NULL;
1434        u8 next_hop[ETH_ALEN];
1435
1436        memset(&pinfo, 0, sizeof(pinfo));
1437
1438        if (!info->attrs[NL80211_ATTR_MAC])
1439                return -EINVAL;
1440
1441        dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1442
1443        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1444        if (err)
1445                return err;
1446
1447        if (!drv->ops->get_mpath) {
1448                err = -EOPNOTSUPP;
1449                goto out;
1450        }
1451
1452        rtnl_lock();
1453        err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
1454        rtnl_unlock();
1455
1456        if (err)
1457                goto out;
1458
1459        msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1460        if (!msg)
1461                goto out;
1462
1463        if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
1464                                 dev, dst, next_hop, &pinfo) < 0)
1465                goto out_free;
1466
1467        err = genlmsg_unicast(msg, info->snd_pid);
1468        goto out;
1469
1470 out_free:
1471        nlmsg_free(msg);
1472
1473 out:
1474        cfg80211_put_dev(drv);
1475        dev_put(dev);
1476        return err;
1477}
1478
1479static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
1480{
1481        struct cfg80211_registered_device *drv;
1482        int err;
1483        struct net_device *dev;
1484        u8 *dst = NULL;
1485        u8 *next_hop = NULL;
1486
1487        if (!info->attrs[NL80211_ATTR_MAC])
1488                return -EINVAL;
1489
1490        if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1491                return -EINVAL;
1492
1493        dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1494        next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1495
1496        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1497        if (err)
1498                return err;
1499
1500        if (!drv->ops->change_mpath) {
1501                err = -EOPNOTSUPP;
1502                goto out;
1503        }
1504
1505        rtnl_lock();
1506        err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
1507        rtnl_unlock();
1508
1509 out:
1510        cfg80211_put_dev(drv);
1511        dev_put(dev);
1512        return err;
1513}
1514static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
1515{
1516        struct cfg80211_registered_device *drv;
1517        int err;
1518        struct net_device *dev;
1519        u8 *dst = NULL;
1520        u8 *next_hop = NULL;
1521
1522        if (!info->attrs[NL80211_ATTR_MAC])
1523                return -EINVAL;
1524
1525        if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1526                return -EINVAL;
1527
1528        dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1529        next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1530
1531        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1532        if (err)
1533                return err;
1534
1535        if (!drv->ops->add_mpath) {
1536                err = -EOPNOTSUPP;
1537                goto out;
1538        }
1539
1540        rtnl_lock();
1541        err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
1542        rtnl_unlock();
1543
1544 out:
1545        cfg80211_put_dev(drv);
1546        dev_put(dev);
1547        return err;
1548}
1549
1550static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
1551{
1552        struct cfg80211_registered_device *drv;
1553        int err;
1554        struct net_device *dev;
1555        u8 *dst = NULL;
1556
1557        if (info->attrs[NL80211_ATTR_MAC])
1558                dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1559
1560        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1561        if (err)
1562                return err;
1563
1564        if (!drv->ops->del_mpath) {
1565                err = -EOPNOTSUPP;
1566                goto out;
1567        }
1568
1569        rtnl_lock();
1570        err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
1571        rtnl_unlock();
1572
1573 out:
1574        cfg80211_put_dev(drv);
1575        dev_put(dev);
1576        return err;
1577}
1578
1579static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
1580{
1581        struct cfg80211_registered_device *drv;
1582        int err;
1583        struct net_device *dev;
1584        struct bss_parameters params;
1585
1586        memset(&params, 0, sizeof(params));
1587        /* default to not changing parameters */
1588        params.use_cts_prot = -1;
1589        params.use_short_preamble = -1;
1590        params.use_short_slot_time = -1;
1591
1592        if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
1593                params.use_cts_prot =
1594                    nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
1595        if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
1596                params.use_short_preamble =
1597                    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
1598        if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
1599                params.use_short_slot_time =
1600                    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
1601
1602        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1603        if (err)
1604                return err;
1605
1606        if (!drv->ops->change_bss) {
1607                err = -EOPNOTSUPP;
1608                goto out;
1609        }
1610
1611        rtnl_lock();
1612        err = drv->ops->change_bss(&drv->wiphy, dev, &params);
1613        rtnl_unlock();
1614
1615 out:
1616        cfg80211_put_dev(drv);
1617        dev_put(dev);
1618        return err;
1619}
1620
1621static const struct nla_policy
1622        reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
1623        [NL80211_ATTR_REG_RULE_FLAGS]           = { .type = NLA_U32 },
1624        [NL80211_ATTR_FREQ_RANGE_START]         = { .type = NLA_U32 },
1625        [NL80211_ATTR_FREQ_RANGE_END]           = { .type = NLA_U32 },
1626        [NL80211_ATTR_FREQ_RANGE_MAX_BW]        = { .type = NLA_U32 },
1627        [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]  = { .type = NLA_U32 },
1628        [NL80211_ATTR_POWER_RULE_MAX_EIRP]      = { .type = NLA_U32 },
1629};
1630
1631static int parse_reg_rule(struct nlattr *tb[],
1632        struct ieee80211_reg_rule *reg_rule)
1633{
1634        struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
1635        struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
1636
1637        if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
1638                return -EINVAL;
1639        if (!tb[NL80211_ATTR_FREQ_RANGE_START])
1640                return -EINVAL;
1641        if (!tb[NL80211_ATTR_FREQ_RANGE_END])
1642                return -EINVAL;
1643        if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
1644                return -EINVAL;
1645        if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
1646                return -EINVAL;
1647
1648        reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
1649
1650        freq_range->start_freq_khz =
1651                nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
1652        freq_range->end_freq_khz =
1653                nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
1654        freq_range->max_bandwidth_khz =
1655                nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
1656
1657        power_rule->max_eirp =
1658                nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
1659
1660        if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
1661                power_rule->max_antenna_gain =
1662                        nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
1663
1664        return 0;
1665}
1666
1667static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1668{
1669        int r;
1670        char *data = NULL;
1671
1672        if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
1673                return -EINVAL;
1674
1675        data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
1676
1677#ifdef CONFIG_WIRELESS_OLD_REGULATORY
1678        /* We ignore world regdom requests with the old regdom setup */
1679        if (is_world_regdom(data))
1680                return -EINVAL;
1681#endif
1682        mutex_lock(&cfg80211_drv_mutex);
1683        r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, NULL);
1684        mutex_unlock(&cfg80211_drv_mutex);
1685        return r;
1686}
1687
1688static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
1689{
1690        struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
1691        struct nlattr *nl_reg_rule;
1692        char *alpha2 = NULL;
1693        int rem_reg_rules = 0, r = 0;
1694        u32 num_rules = 0, rule_idx = 0, size_of_regd;
1695        struct ieee80211_regdomain *rd = NULL;
1696
1697        if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
1698                return -EINVAL;
1699
1700        if (!info->attrs[NL80211_ATTR_REG_RULES])
1701                return -EINVAL;
1702
1703        alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
1704
1705        nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1706                        rem_reg_rules) {
1707                num_rules++;
1708                if (num_rules > NL80211_MAX_SUPP_REG_RULES)
1709                        goto bad_reg;
1710        }
1711
1712        if (!reg_is_valid_request(alpha2))
1713                return -EINVAL;
1714
1715        size_of_regd = sizeof(struct ieee80211_regdomain) +
1716                (num_rules * sizeof(struct ieee80211_reg_rule));
1717
1718        rd = kzalloc(size_of_regd, GFP_KERNEL);
1719        if (!rd)
1720                return -ENOMEM;
1721
1722        rd->n_reg_rules = num_rules;
1723        rd->alpha2[0] = alpha2[0];
1724        rd->alpha2[1] = alpha2[1];
1725
1726        nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1727                        rem_reg_rules) {
1728                nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
1729                        nla_data(nl_reg_rule), nla_len(nl_reg_rule),
1730                        reg_rule_policy);
1731                r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
1732                if (r)
1733                        goto bad_reg;
1734
1735                rule_idx++;
1736
1737                if (rule_idx > NL80211_MAX_SUPP_REG_RULES)
1738                        goto bad_reg;
1739        }
1740
1741        BUG_ON(rule_idx != num_rules);
1742
1743        mutex_lock(&cfg80211_drv_mutex);
1744        r = set_regdom(rd);
1745        mutex_unlock(&cfg80211_drv_mutex);
1746        if (r)
1747                goto bad_reg;
1748
1749        return r;
1750
1751bad_reg:
1752        kfree(rd);
1753        return -EINVAL;
1754}
1755
1756static struct genl_ops nl80211_ops[] = {
1757        {
1758                .cmd = NL80211_CMD_GET_WIPHY,
1759                .doit = nl80211_get_wiphy,
1760                .dumpit = nl80211_dump_wiphy,
1761                .policy = nl80211_policy,
1762                /* can be retrieved by unprivileged users */
1763        },
1764        {
1765                .cmd = NL80211_CMD_SET_WIPHY,
1766                .doit = nl80211_set_wiphy,
1767                .policy = nl80211_policy,
1768                .flags = GENL_ADMIN_PERM,
1769        },
1770        {
1771                .cmd = NL80211_CMD_GET_INTERFACE,
1772                .doit = nl80211_get_interface,
1773                .dumpit = nl80211_dump_interface,
1774                .policy = nl80211_policy,
1775                /* can be retrieved by unprivileged users */
1776        },
1777        {
1778                .cmd = NL80211_CMD_SET_INTERFACE,
1779                .doit = nl80211_set_interface,
1780                .policy = nl80211_policy,
1781                .flags = GENL_ADMIN_PERM,
1782        },
1783        {
1784                .cmd = NL80211_CMD_NEW_INTERFACE,
1785                .doit = nl80211_new_interface,
1786                .policy = nl80211_policy,
1787                .flags = GENL_ADMIN_PERM,
1788        },
1789        {
1790                .cmd = NL80211_CMD_DEL_INTERFACE,
1791                .doit = nl80211_del_interface,
1792                .policy = nl80211_policy,
1793                .flags = GENL_ADMIN_PERM,
1794        },
1795        {
1796                .cmd = NL80211_CMD_GET_KEY,
1797                .doit = nl80211_get_key,
1798                .policy = nl80211_policy,
1799                .flags = GENL_ADMIN_PERM,
1800        },
1801        {
1802                .cmd = NL80211_CMD_SET_KEY,
1803                .doit = nl80211_set_key,
1804                .policy = nl80211_policy,
1805                .flags = GENL_ADMIN_PERM,
1806        },
1807        {
1808                .cmd = NL80211_CMD_NEW_KEY,
1809                .doit = nl80211_new_key,
1810                .policy = nl80211_policy,
1811                .flags = GENL_ADMIN_PERM,
1812        },
1813        {
1814                .cmd = NL80211_CMD_DEL_KEY,
1815                .doit = nl80211_del_key,
1816                .policy = nl80211_policy,
1817                .flags = GENL_ADMIN_PERM,
1818        },
1819        {
1820                .cmd = NL80211_CMD_SET_BEACON,
1821                .policy = nl80211_policy,
1822                .flags = GENL_ADMIN_PERM,
1823                .doit = nl80211_addset_beacon,
1824        },
1825        {
1826                .cmd = NL80211_CMD_NEW_BEACON,
1827                .policy = nl80211_policy,
1828                .flags = GENL_ADMIN_PERM,
1829                .doit = nl80211_addset_beacon,
1830        },
1831        {
1832                .cmd = NL80211_CMD_DEL_BEACON,
1833                .policy = nl80211_policy,
1834                .flags = GENL_ADMIN_PERM,
1835                .doit = nl80211_del_beacon,
1836        },
1837        {
1838                .cmd = NL80211_CMD_GET_STATION,
1839                .doit = nl80211_get_station,
1840                .dumpit = nl80211_dump_station,
1841                .policy = nl80211_policy,
1842                .flags = GENL_ADMIN_PERM,
1843        },
1844        {
1845                .cmd = NL80211_CMD_SET_STATION,
1846                .doit = nl80211_set_station,
1847                .policy = nl80211_policy,
1848                .flags = GENL_ADMIN_PERM,
1849        },
1850        {
1851                .cmd = NL80211_CMD_NEW_STATION,
1852                .doit = nl80211_new_station,
1853                .policy = nl80211_policy,
1854                .flags = GENL_ADMIN_PERM,
1855        },
1856        {
1857                .cmd = NL80211_CMD_DEL_STATION,
1858                .doit = nl80211_del_station,
1859                .policy = nl80211_policy,
1860                .flags = GENL_ADMIN_PERM,
1861        },
1862        {
1863                .cmd = NL80211_CMD_GET_MPATH,
1864                .doit = nl80211_get_mpath,
1865                .dumpit = nl80211_dump_mpath,
1866                .policy = nl80211_policy,
1867                .flags = GENL_ADMIN_PERM,
1868        },
1869        {
1870                .cmd = NL80211_CMD_SET_MPATH,
1871                .doit = nl80211_set_mpath,
1872                .policy = nl80211_policy,
1873                .flags = GENL_ADMIN_PERM,
1874        },
1875        {
1876                .cmd = NL80211_CMD_NEW_MPATH,
1877                .doit = nl80211_new_mpath,
1878                .policy = nl80211_policy,
1879                .flags = GENL_ADMIN_PERM,
1880        },
1881        {
1882                .cmd = NL80211_CMD_DEL_MPATH,
1883                .doit = nl80211_del_mpath,
1884                .policy = nl80211_policy,
1885                .flags = GENL_ADMIN_PERM,
1886        },
1887        {
1888                .cmd = NL80211_CMD_SET_BSS,
1889                .doit = nl80211_set_bss,
1890                .policy = nl80211_policy,
1891                .flags = GENL_ADMIN_PERM,
1892        },
1893        {
1894                .cmd = NL80211_CMD_SET_REG,
1895                .doit = nl80211_set_reg,
1896                .policy = nl80211_policy,
1897                .flags = GENL_ADMIN_PERM,
1898        },
1899        {
1900                .cmd = NL80211_CMD_REQ_SET_REG,
1901                .doit = nl80211_req_set_reg,
1902                .policy = nl80211_policy,
1903                .flags = GENL_ADMIN_PERM,
1904        },
1905};
1906
1907/* multicast groups */
1908static struct genl_multicast_group nl80211_config_mcgrp = {
1909        .name = "config",
1910};
1911
1912/* notification functions */
1913
1914void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1915{
1916        struct sk_buff *msg;
1917
1918        msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1919        if (!msg)
1920                return;
1921
1922        if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1923                nlmsg_free(msg);
1924                return;
1925        }
1926
1927        genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1928}
1929
1930/* initialisation/exit functions */
1931
1932int nl80211_init(void)
1933{
1934        int err, i;
1935
1936        err = genl_register_family(&nl80211_fam);
1937        if (err)
1938                return err;
1939
1940        for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1941                err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1942                if (err)
1943                        goto err_out;
1944        }
1945
1946        err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1947        if (err)
1948                goto err_out;
1949
1950        return 0;
1951 err_out:
1952        genl_unregister_family(&nl80211_fam);
1953        return err;
1954}
1955
1956void nl80211_exit(void)
1957{
1958        genl_unregister_family(&nl80211_fam);
1959}
1960
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.