root/net/wireless/ibss.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __cfg80211_ibss_joined
  2. cfg80211_ibss_joined
  3. __cfg80211_join_ibss
  4. __cfg80211_clear_ibss
  5. cfg80211_clear_ibss
  6. __cfg80211_leave_ibss
  7. cfg80211_leave_ibss
  8. cfg80211_ibss_wext_join
  9. cfg80211_ibss_wext_siwfreq
  10. cfg80211_ibss_wext_giwfreq
  11. cfg80211_ibss_wext_siwessid
  12. cfg80211_ibss_wext_giwessid
  13. cfg80211_ibss_wext_siwap
  14. cfg80211_ibss_wext_giwap

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

/* [<][>][^][v][top][bottom][index][help] */