linux/net/wireless/ibss.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Some IBSS support code for cfg80211.
   4 *
   5 * Copyright 2009       Johannes Berg <johannes@sipsolutions.net>
   6 * Copyright (C) 2020-2021 Intel Corporation
   7 */
   8
   9#include <linux/etherdevice.h>
  10#include <linux/if_arp.h>
  11#include <linux/slab.h>
  12#include <linux/export.h>
  13#include <net/cfg80211.h>
  14#include "wext-compat.h"
  15#include "nl80211.h"
  16#include "rdev-ops.h"
  17
  18
  19void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
  20                            struct ieee80211_channel *channel)
  21{
  22        struct wireless_dev *wdev = dev->ieee80211_ptr;
  23        struct cfg80211_bss *bss;
  24#ifdef CONFIG_CFG80211_WEXT
  25        union iwreq_data wrqu;
  26#endif
  27
  28        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
  29                return;
  30
  31        if (!wdev->ssid_len)
  32                return;
  33
  34        bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
  35                               IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY);
  36
  37        if (WARN_ON(!bss))
  38                return;
  39
  40        if (wdev->current_bss) {
  41                cfg80211_unhold_bss(wdev->current_bss);
  42                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
  43        }
  44
  45        cfg80211_hold_bss(bss_from_pub(bss));
  46        wdev->current_bss = bss_from_pub(bss);
  47
  48        if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP))
  49                cfg80211_upload_connect_keys(wdev);
  50
  51        nl80211_send_ibss_bssid(wiphy_to_rdev(wdev->wiphy), dev, bssid,
  52                                GFP_KERNEL);
  53#ifdef CONFIG_CFG80211_WEXT
  54        memset(&wrqu, 0, sizeof(wrqu));
  55        memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
  56        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
  57#endif
  58}
  59
  60void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
  61                          struct ieee80211_channel *channel, gfp_t gfp)
  62{
  63        struct wireless_dev *wdev = dev->ieee80211_ptr;
  64        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
  65        struct cfg80211_event *ev;
  66        unsigned long flags;
  67
  68        trace_cfg80211_ibss_joined(dev, bssid, channel);
  69
  70        if (WARN_ON(!channel))
  71                return;
  72
  73        ev = kzalloc(sizeof(*ev), gfp);
  74        if (!ev)
  75                return;
  76
  77        ev->type = EVENT_IBSS_JOINED;
  78        memcpy(ev->ij.bssid, bssid, ETH_ALEN);
  79        ev->ij.channel = channel;
  80
  81        spin_lock_irqsave(&wdev->event_lock, flags);
  82        list_add_tail(&ev->list, &wdev->event_list);
  83        spin_unlock_irqrestore(&wdev->event_lock, flags);
  84        queue_work(cfg80211_wq, &rdev->event_work);
  85}
  86EXPORT_SYMBOL(cfg80211_ibss_joined);
  87
  88int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
  89                         struct net_device *dev,
  90                         struct cfg80211_ibss_params *params,
  91                         struct cfg80211_cached_keys *connkeys)
  92{
  93        struct wireless_dev *wdev = dev->ieee80211_ptr;
  94        int err;
  95
  96        lockdep_assert_held(&rdev->wiphy.mtx);
  97        ASSERT_WDEV_LOCK(wdev);
  98
  99        if (wdev->ssid_len)
 100                return -EALREADY;
 101
 102        if (!params->basic_rates) {
 103                /*
 104                * If no rates were explicitly configured,
 105                * use the mandatory rate set for 11b or
 106                * 11a for maximum compatibility.
 107                */
 108                struct ieee80211_supported_band *sband;
 109                enum nl80211_band band;
 110                u32 flag;
 111                int j;
 112
 113                band = params->chandef.chan->band;
 114                if (band == NL80211_BAND_5GHZ ||
 115                    band == NL80211_BAND_6GHZ)
 116                        flag = IEEE80211_RATE_MANDATORY_A;
 117                else
 118                        flag = IEEE80211_RATE_MANDATORY_B;
 119
 120                sband = rdev->wiphy.bands[band];
 121                for (j = 0; j < sband->n_bitrates; j++) {
 122                        if (sband->bitrates[j].flags & flag)
 123                                params->basic_rates |= BIT(j);
 124                }
 125        }
 126
 127        if (WARN_ON(connkeys && connkeys->def < 0))
 128                return -EINVAL;
 129
 130        if (WARN_ON(wdev->connect_keys))
 131                kfree_sensitive(wdev->connect_keys);
 132        wdev->connect_keys = connkeys;
 133
 134        wdev->ibss_fixed = params->channel_fixed;
 135        wdev->ibss_dfs_possible = params->userspace_handles_dfs;
 136        wdev->chandef = params->chandef;
 137        if (connkeys) {
 138                params->wep_keys = connkeys->params;
 139                params->wep_tx_key = connkeys->def;
 140        }
 141
 142#ifdef CONFIG_CFG80211_WEXT
 143        wdev->wext.ibss.chandef = params->chandef;
 144#endif
 145        err = rdev_join_ibss(rdev, dev, params);
 146        if (err) {
 147                wdev->connect_keys = NULL;
 148                return err;
 149        }
 150
 151        memcpy(wdev->ssid, params->ssid, params->ssid_len);
 152        wdev->ssid_len = params->ssid_len;
 153
 154        return 0;
 155}
 156
 157static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
 158{
 159        struct wireless_dev *wdev = dev->ieee80211_ptr;
 160        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 161        int i;
 162
 163        ASSERT_WDEV_LOCK(wdev);
 164
 165        kfree_sensitive(wdev->connect_keys);
 166        wdev->connect_keys = NULL;
 167
 168        rdev_set_qos_map(rdev, dev, NULL);
 169
 170        /*
 171         * Delete all the keys ... pairwise keys can't really
 172         * exist any more anyway, but default keys might.
 173         */
 174        if (rdev->ops->del_key)
 175                for (i = 0; i < 6; i++)
 176                        rdev_del_key(rdev, dev, i, false, NULL);
 177
 178        if (wdev->current_bss) {
 179                cfg80211_unhold_bss(wdev->current_bss);
 180                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
 181        }
 182
 183        wdev->current_bss = NULL;
 184        wdev->ssid_len = 0;
 185        memset(&wdev->chandef, 0, sizeof(wdev->chandef));
 186#ifdef CONFIG_CFG80211_WEXT
 187        if (!nowext)
 188                wdev->wext.ibss.ssid_len = 0;
 189#endif
 190        cfg80211_sched_dfs_chan_update(rdev);
 191}
 192
 193void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
 194{
 195        struct wireless_dev *wdev = dev->ieee80211_ptr;
 196
 197        wdev_lock(wdev);
 198        __cfg80211_clear_ibss(dev, nowext);
 199        wdev_unlock(wdev);
 200}
 201
 202int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
 203                          struct net_device *dev, bool nowext)
 204{
 205        struct wireless_dev *wdev = dev->ieee80211_ptr;
 206        int err;
 207
 208        ASSERT_WDEV_LOCK(wdev);
 209
 210        if (!wdev->ssid_len)
 211                return -ENOLINK;
 212
 213        err = rdev_leave_ibss(rdev, dev);
 214
 215        if (err)
 216                return err;
 217
 218        wdev->conn_owner_nlportid = 0;
 219        __cfg80211_clear_ibss(dev, nowext);
 220
 221        return 0;
 222}
 223
 224int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
 225                        struct net_device *dev, bool nowext)
 226{
 227        struct wireless_dev *wdev = dev->ieee80211_ptr;
 228        int err;
 229
 230        wdev_lock(wdev);
 231        err = __cfg80211_leave_ibss(rdev, dev, nowext);
 232        wdev_unlock(wdev);
 233
 234        return err;
 235}
 236
 237#ifdef CONFIG_CFG80211_WEXT
 238int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 239                            struct wireless_dev *wdev)
 240{
 241        struct cfg80211_cached_keys *ck = NULL;
 242        enum nl80211_band band;
 243        int i, err;
 244
 245        ASSERT_WDEV_LOCK(wdev);
 246
 247        if (!wdev->wext.ibss.beacon_interval)
 248                wdev->wext.ibss.beacon_interval = 100;
 249
 250        /* try to find an IBSS channel if none requested ... */
 251        if (!wdev->wext.ibss.chandef.chan) {
 252                struct ieee80211_channel *new_chan = NULL;
 253
 254                for (band = 0; band < NUM_NL80211_BANDS; band++) {
 255                        struct ieee80211_supported_band *sband;
 256                        struct ieee80211_channel *chan;
 257
 258                        sband = rdev->wiphy.bands[band];
 259                        if (!sband)
 260                                continue;
 261
 262                        for (i = 0; i < sband->n_channels; i++) {
 263                                chan = &sband->channels[i];
 264                                if (chan->flags & IEEE80211_CHAN_NO_IR)
 265                                        continue;
 266                                if (chan->flags & IEEE80211_CHAN_DISABLED)
 267                                        continue;
 268                                new_chan = chan;
 269                                break;
 270                        }
 271
 272                        if (new_chan)
 273                                break;
 274                }
 275
 276                if (!new_chan)
 277                        return -EINVAL;
 278
 279                cfg80211_chandef_create(&wdev->wext.ibss.chandef, new_chan,
 280                                        NL80211_CHAN_NO_HT);
 281        }
 282
 283        /* don't join -- SSID is not there */
 284        if (!wdev->wext.ibss.ssid_len)
 285                return 0;
 286
 287        if (!netif_running(wdev->netdev))
 288                return 0;
 289
 290        if (wdev->wext.keys)
 291                wdev->wext.keys->def = wdev->wext.default_key;
 292
 293        wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
 294
 295        if (wdev->wext.keys && wdev->wext.keys->def != -1) {
 296                ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
 297                if (!ck)
 298                        return -ENOMEM;
 299                for (i = 0; i < CFG80211_MAX_WEP_KEYS; i++)
 300                        ck->params[i].key = ck->data[i];
 301        }
 302        err = __cfg80211_join_ibss(rdev, wdev->netdev,
 303                                   &wdev->wext.ibss, ck);
 304        if (err)
 305                kfree(ck);
 306
 307        return err;
 308}
 309
 310int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
 311                               struct iw_request_info *info,
 312                               struct iw_freq *wextfreq, char *extra)
 313{
 314        struct wireless_dev *wdev = dev->ieee80211_ptr;
 315        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 316        struct ieee80211_channel *chan = NULL;
 317        int err, freq;
 318
 319        /* call only for ibss! */
 320        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 321                return -EINVAL;
 322
 323        if (!rdev->ops->join_ibss)
 324                return -EOPNOTSUPP;
 325
 326        freq = cfg80211_wext_freq(wextfreq);
 327        if (freq < 0)
 328                return freq;
 329
 330        if (freq) {
 331                chan = ieee80211_get_channel(wdev->wiphy, freq);
 332                if (!chan)
 333                        return -EINVAL;
 334                if (chan->flags & IEEE80211_CHAN_NO_IR ||
 335                    chan->flags & IEEE80211_CHAN_DISABLED)
 336                        return -EINVAL;
 337        }
 338
 339        if (wdev->wext.ibss.chandef.chan == chan)
 340                return 0;
 341
 342        wdev_lock(wdev);
 343        err = 0;
 344        if (wdev->ssid_len)
 345                err = __cfg80211_leave_ibss(rdev, dev, true);
 346        wdev_unlock(wdev);
 347
 348        if (err)
 349                return err;
 350
 351        if (chan) {
 352                cfg80211_chandef_create(&wdev->wext.ibss.chandef, chan,
 353                                        NL80211_CHAN_NO_HT);
 354                wdev->wext.ibss.channel_fixed = true;
 355        } else {
 356                /* cfg80211_ibss_wext_join will pick one if needed */
 357                wdev->wext.ibss.channel_fixed = false;
 358        }
 359
 360        wdev_lock(wdev);
 361        err = cfg80211_ibss_wext_join(rdev, wdev);
 362        wdev_unlock(wdev);
 363
 364        return err;
 365}
 366
 367int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
 368                               struct iw_request_info *info,
 369                               struct iw_freq *freq, char *extra)
 370{
 371        struct wireless_dev *wdev = dev->ieee80211_ptr;
 372        struct ieee80211_channel *chan = NULL;
 373
 374        /* call only for ibss! */
 375        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 376                return -EINVAL;
 377
 378        wdev_lock(wdev);
 379        if (wdev->current_bss)
 380                chan = wdev->current_bss->pub.channel;
 381        else if (wdev->wext.ibss.chandef.chan)
 382                chan = wdev->wext.ibss.chandef.chan;
 383        wdev_unlock(wdev);
 384
 385        if (chan) {
 386                freq->m = chan->center_freq;
 387                freq->e = 6;
 388                return 0;
 389        }
 390
 391        /* no channel if not joining */
 392        return -EINVAL;
 393}
 394
 395int cfg80211_ibss_wext_siwessid(struct net_device *dev,
 396                                struct iw_request_info *info,
 397                                struct iw_point *data, char *ssid)
 398{
 399        struct wireless_dev *wdev = dev->ieee80211_ptr;
 400        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 401        size_t len = data->length;
 402        int err;
 403
 404        /* call only for ibss! */
 405        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 406                return -EINVAL;
 407
 408        if (!rdev->ops->join_ibss)
 409                return -EOPNOTSUPP;
 410
 411        wdev_lock(wdev);
 412        err = 0;
 413        if (wdev->ssid_len)
 414                err = __cfg80211_leave_ibss(rdev, dev, true);
 415        wdev_unlock(wdev);
 416
 417        if (err)
 418                return err;
 419
 420        /* iwconfig uses nul termination in SSID.. */
 421        if (len > 0 && ssid[len - 1] == '\0')
 422                len--;
 423
 424        memcpy(wdev->ssid, ssid, len);
 425        wdev->wext.ibss.ssid = wdev->ssid;
 426        wdev->wext.ibss.ssid_len = len;
 427
 428        wdev_lock(wdev);
 429        err = cfg80211_ibss_wext_join(rdev, wdev);
 430        wdev_unlock(wdev);
 431
 432        return err;
 433}
 434
 435int cfg80211_ibss_wext_giwessid(struct net_device *dev,
 436                                struct iw_request_info *info,
 437                                struct iw_point *data, char *ssid)
 438{
 439        struct wireless_dev *wdev = dev->ieee80211_ptr;
 440
 441        /* call only for ibss! */
 442        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 443                return -EINVAL;
 444
 445        data->flags = 0;
 446
 447        wdev_lock(wdev);
 448        if (wdev->ssid_len) {
 449                data->flags = 1;
 450                data->length = wdev->ssid_len;
 451                memcpy(ssid, wdev->ssid, data->length);
 452        } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) {
 453                data->flags = 1;
 454                data->length = wdev->wext.ibss.ssid_len;
 455                memcpy(ssid, wdev->wext.ibss.ssid, data->length);
 456        }
 457        wdev_unlock(wdev);
 458
 459        return 0;
 460}
 461
 462int cfg80211_ibss_wext_siwap(struct net_device *dev,
 463                             struct iw_request_info *info,
 464                             struct sockaddr *ap_addr, char *extra)
 465{
 466        struct wireless_dev *wdev = dev->ieee80211_ptr;
 467        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 468        u8 *bssid = ap_addr->sa_data;
 469        int err;
 470
 471        /* call only for ibss! */
 472        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 473                return -EINVAL;
 474
 475        if (!rdev->ops->join_ibss)
 476                return -EOPNOTSUPP;
 477
 478        if (ap_addr->sa_family != ARPHRD_ETHER)
 479                return -EINVAL;
 480
 481        /* automatic mode */
 482        if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
 483                bssid = NULL;
 484
 485        if (bssid && !is_valid_ether_addr(bssid))
 486                return -EINVAL;
 487
 488        /* both automatic */
 489        if (!bssid && !wdev->wext.ibss.bssid)
 490                return 0;
 491
 492        /* fixed already - and no change */
 493        if (wdev->wext.ibss.bssid && bssid &&
 494            ether_addr_equal(bssid, wdev->wext.ibss.bssid))
 495                return 0;
 496
 497        wdev_lock(wdev);
 498        err = 0;
 499        if (wdev->ssid_len)
 500                err = __cfg80211_leave_ibss(rdev, dev, true);
 501        wdev_unlock(wdev);
 502
 503        if (err)
 504                return err;
 505
 506        if (bssid) {
 507                memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
 508                wdev->wext.ibss.bssid = wdev->wext.bssid;
 509        } else
 510                wdev->wext.ibss.bssid = NULL;
 511
 512        wdev_lock(wdev);
 513        err = cfg80211_ibss_wext_join(rdev, wdev);
 514        wdev_unlock(wdev);
 515
 516        return err;
 517}
 518
 519int cfg80211_ibss_wext_giwap(struct net_device *dev,
 520                             struct iw_request_info *info,
 521                             struct sockaddr *ap_addr, char *extra)
 522{
 523        struct wireless_dev *wdev = dev->ieee80211_ptr;
 524
 525        /* call only for ibss! */
 526        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 527                return -EINVAL;
 528
 529        ap_addr->sa_family = ARPHRD_ETHER;
 530
 531        wdev_lock(wdev);
 532        if (wdev->current_bss)
 533                memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
 534        else if (wdev->wext.ibss.bssid)
 535                memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
 536        else
 537                eth_zero_addr(ap_addr->sa_data);
 538
 539        wdev_unlock(wdev);
 540
 541        return 0;
 542}
 543#endif
 544