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