1 /* 2 * Copyright 2002-2005, Instant802 Networks, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc. 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * utilities for mac80211 12 */ 13 14 #include <net/mac80211.h> 15 #include <linux/netdevice.h> 16 #include <linux/types.h> 17 #include <linux/slab.h> 18 #include <linux/skbuff.h> 19 #include <linux/etherdevice.h> 20 #include <linux/if_arp.h> 21 #include <linux/bitmap.h> 22 #include <linux/crc32.h> 23 #include <net/net_namespace.h> 24 #include <net/cfg80211.h> 25 #include <net/rtnetlink.h> 26 27 #include "ieee80211_i.h" 28 #include "driver-ops.h" 29 #include "rate.h" 30 #include "mesh.h" 31 #include "wme.h" 32 #include "led.h" 33 #include "wep.h" 34 35 /* privid for wiphys to determine whether they belong to us or not */ 36 void *mac80211_wiphy_privid = &mac80211_wiphy_privid; 37 38 struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) 39 { 40 struct ieee80211_local *local; 41 BUG_ON(!wiphy); 42 43 local = wiphy_priv(wiphy); 44 return &local->hw; 45 } 46 EXPORT_SYMBOL(wiphy_to_ieee80211_hw); 47 48 u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, 49 enum nl80211_iftype type) 50 { 51 __le16 fc = hdr->frame_control; 52 53 /* drop ACK/CTS frames and incorrect hdr len (ctrl) */ 54 if (len < 16) 55 return NULL; 56 57 if (ieee80211_is_data(fc)) { 58 if (len < 24) /* drop incorrect hdr len (data) */ 59 return NULL; 60 61 if (ieee80211_has_a4(fc)) 62 return NULL; 63 if (ieee80211_has_tods(fc)) 64 return hdr->addr1; 65 if (ieee80211_has_fromds(fc)) 66 return hdr->addr2; 67 68 return hdr->addr3; 69 } 70 71 if (ieee80211_is_mgmt(fc)) { 72 if (len < 24) /* drop incorrect hdr len (mgmt) */ 73 return NULL; 74 return hdr->addr3; 75 } 76 77 if (ieee80211_is_ctl(fc)) { 78 if(ieee80211_is_pspoll(fc)) 79 return hdr->addr1; 80 81 if (ieee80211_is_back_req(fc)) { 82 switch (type) { 83 case NL80211_IFTYPE_STATION: 84 return hdr->addr2; 85 case NL80211_IFTYPE_AP: 86 case NL80211_IFTYPE_AP_VLAN: 87 return hdr->addr1; 88 default: 89 break; /* fall through to the return */ 90 } 91 } 92 } 93 94 return NULL; 95 } 96 97 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) 98 { 99 struct sk_buff *skb = tx->skb; 100 struct ieee80211_hdr *hdr; 101 102 do { 103 hdr = (struct ieee80211_hdr *) skb->data; 104 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 105 } while ((skb = skb->next)); 106 } 107 108 int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 109 int rate, int erp, int short_preamble) 110 { 111 int dur; 112 113 /* calculate duration (in microseconds, rounded up to next higher 114 * integer if it includes a fractional microsecond) to send frame of 115 * len bytes (does not include FCS) at the given rate. Duration will 116 * also include SIFS. 117 * 118 * rate is in 100 kbps, so divident is multiplied by 10 in the 119 * DIV_ROUND_UP() operations. 120 */ 121 122 if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { 123 /* 124 * OFDM: 125 * 126 * N_DBPS = DATARATE x 4 127 * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS) 128 * (16 = SIGNAL time, 6 = tail bits) 129 * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext 130 * 131 * T_SYM = 4 usec 132 * 802.11a - 17.5.2: aSIFSTime = 16 usec 133 * 802.11g - 19.8.4: aSIFSTime = 10 usec + 134 * signal ext = 6 usec 135 */ 136 dur = 16; /* SIFS + signal ext */ 137 dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ 138 dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ 139 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, 140 4 * rate); /* T_SYM x N_SYM */ 141 } else { 142 /* 143 * 802.11b or 802.11g with 802.11b compatibility: 144 * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime + 145 * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0. 146 * 147 * 802.11 (DS): 15.3.3, 802.11b: 18.3.4 148 * aSIFSTime = 10 usec 149 * aPreambleLength = 144 usec or 72 usec with short preamble 150 * aPLCPHeaderLength = 48 usec or 24 usec with short preamble 151 */ 152 dur = 10; /* aSIFSTime = 10 usec */ 153 dur += short_preamble ? (72 + 24) : (144 + 48); 154 155 dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate); 156 } 157 158 return dur; 159 } 160 161 /* Exported duration function for driver use */ 162 __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, 163 struct ieee80211_vif *vif, 164 size_t frame_len, 165 struct ieee80211_rate *rate) 166 { 167 struct ieee80211_local *local = hw_to_local(hw); 168 struct ieee80211_sub_if_data *sdata; 169 u16 dur; 170 int erp; 171 bool short_preamble = false; 172 173 erp = 0; 174 if (vif) { 175 sdata = vif_to_sdata(vif); 176 short_preamble = sdata->vif.bss_conf.use_short_preamble; 177 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 178 erp = rate->flags & IEEE80211_RATE_ERP_G; 179 } 180 181 dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, 182 short_preamble); 183 184 return cpu_to_le16(dur); 185 } 186 EXPORT_SYMBOL(ieee80211_generic_frame_duration); 187 188 __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, 189 struct ieee80211_vif *vif, size_t frame_len, 190 const struct ieee80211_tx_info *frame_txctl) 191 { 192 struct ieee80211_local *local = hw_to_local(hw); 193 struct ieee80211_rate *rate; 194 struct ieee80211_sub_if_data *sdata; 195 bool short_preamble; 196 int erp; 197 u16 dur; 198 struct ieee80211_supported_band *sband; 199 200 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 201 202 short_preamble = false; 203 204 rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; 205 206 erp = 0; 207 if (vif) { 208 sdata = vif_to_sdata(vif); 209 short_preamble = sdata->vif.bss_conf.use_short_preamble; 210 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 211 erp = rate->flags & IEEE80211_RATE_ERP_G; 212 } 213 214 /* CTS duration */ 215 dur = ieee80211_frame_duration(local, 10, rate->bitrate, 216 erp, short_preamble); 217 /* Data frame duration */ 218 dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, 219 erp, short_preamble); 220 /* ACK duration */ 221 dur += ieee80211_frame_duration(local, 10, rate->bitrate, 222 erp, short_preamble); 223 224 return cpu_to_le16(dur); 225 } 226 EXPORT_SYMBOL(ieee80211_rts_duration); 227 228 __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, 229 struct ieee80211_vif *vif, 230 size_t frame_len, 231 const struct ieee80211_tx_info *frame_txctl) 232 { 233 struct ieee80211_local *local = hw_to_local(hw); 234 struct ieee80211_rate *rate; 235 struct ieee80211_sub_if_data *sdata; 236 bool short_preamble; 237 int erp; 238 u16 dur; 239 struct ieee80211_supported_band *sband; 240 241 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 242 243 short_preamble = false; 244 245 rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; 246 erp = 0; 247 if (vif) { 248 sdata = vif_to_sdata(vif); 249 short_preamble = sdata->vif.bss_conf.use_short_preamble; 250 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 251 erp = rate->flags & IEEE80211_RATE_ERP_G; 252 } 253 254 /* Data frame duration */ 255 dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, 256 erp, short_preamble); 257 if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { 258 /* ACK duration */ 259 dur += ieee80211_frame_duration(local, 10, rate->bitrate, 260 erp, short_preamble); 261 } 262 263 return cpu_to_le16(dur); 264 } 265 EXPORT_SYMBOL(ieee80211_ctstoself_duration); 266 267 static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, 268 enum queue_stop_reason reason) 269 { 270 struct ieee80211_local *local = hw_to_local(hw); 271 struct ieee80211_sub_if_data *sdata; 272 273 if (WARN_ON(queue >= hw->queues)) 274 return; 275 276 __clear_bit(reason, &local->queue_stop_reasons[queue]); 277 278 if (local->queue_stop_reasons[queue] != 0) 279 /* someone still has this queue stopped */ 280 return; 281 282 if (skb_queue_empty(&local->pending[queue])) { 283 rcu_read_lock(); 284 list_for_each_entry_rcu(sdata, &local->interfaces, list) 285 netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); 286 rcu_read_unlock(); 287 } else 288 tasklet_schedule(&local->tx_pending_tasklet); 289 } 290 291 void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 292 enum queue_stop_reason reason) 293 { 294 struct ieee80211_local *local = hw_to_local(hw); 295 unsigned long flags; 296 297 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 298 __ieee80211_wake_queue(hw, queue, reason); 299 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 300 } 301 302 void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) 303 { 304 ieee80211_wake_queue_by_reason(hw, queue, 305 IEEE80211_QUEUE_STOP_REASON_DRIVER); 306 } 307 EXPORT_SYMBOL(ieee80211_wake_queue); 308 309 static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, 310 enum queue_stop_reason reason) 311 { 312 struct ieee80211_local *local = hw_to_local(hw); 313 struct ieee80211_sub_if_data *sdata; 314 315 if (WARN_ON(queue >= hw->queues)) 316 return; 317 318 __set_bit(reason, &local->queue_stop_reasons[queue]); 319 320 rcu_read_lock(); 321 list_for_each_entry_rcu(sdata, &local->interfaces, list) 322 netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue)); 323 rcu_read_unlock(); 324 } 325 326 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 327 enum queue_stop_reason reason) 328 { 329 struct ieee80211_local *local = hw_to_local(hw); 330 unsigned long flags; 331 332 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 333 __ieee80211_stop_queue(hw, queue, reason); 334 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 335 } 336 337 void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) 338 { 339 ieee80211_stop_queue_by_reason(hw, queue, 340 IEEE80211_QUEUE_STOP_REASON_DRIVER); 341 } 342 EXPORT_SYMBOL(ieee80211_stop_queue); 343 344 void ieee80211_add_pending_skb(struct ieee80211_local *local, 345 struct sk_buff *skb) 346 { 347 struct ieee80211_hw *hw = &local->hw; 348 unsigned long flags; 349 int queue = skb_get_queue_mapping(skb); 350 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 351 352 if (WARN_ON(!info->control.vif)) { 353 kfree_skb(skb); 354 return; 355 } 356 357 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 358 __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 359 __skb_queue_tail(&local->pending[queue], skb); 360 __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 361 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 362 } 363 364 int ieee80211_add_pending_skbs(struct ieee80211_local *local, 365 struct sk_buff_head *skbs) 366 { 367 struct ieee80211_hw *hw = &local->hw; 368 struct sk_buff *skb; 369 unsigned long flags; 370 int queue, ret = 0, i; 371 372 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 373 for (i = 0; i < hw->queues; i++) 374 __ieee80211_stop_queue(hw, i, 375 IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 376 377 while ((skb = skb_dequeue(skbs))) { 378 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 379 380 if (WARN_ON(!info->control.vif)) { 381 kfree_skb(skb); 382 continue; 383 } 384 385 ret++; 386 queue = skb_get_queue_mapping(skb); 387 __skb_queue_tail(&local->pending[queue], skb); 388 } 389 390 for (i = 0; i < hw->queues; i++) 391 __ieee80211_wake_queue(hw, i, 392 IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 393 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 394 395 return ret; 396 } 397 398 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 399 enum queue_stop_reason reason) 400 { 401 struct ieee80211_local *local = hw_to_local(hw); 402 unsigned long flags; 403 int i; 404 405 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 406 407 for (i = 0; i < hw->queues; i++) 408 __ieee80211_stop_queue(hw, i, reason); 409 410 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 411 } 412 413 void ieee80211_stop_queues(struct ieee80211_hw *hw) 414 { 415 ieee80211_stop_queues_by_reason(hw, 416 IEEE80211_QUEUE_STOP_REASON_DRIVER); 417 } 418 EXPORT_SYMBOL(ieee80211_stop_queues); 419 420 int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) 421 { 422 struct ieee80211_local *local = hw_to_local(hw); 423 unsigned long flags; 424 int ret; 425 426 if (WARN_ON(queue >= hw->queues)) 427 return true; 428 429 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 430 ret = !!local->queue_stop_reasons[queue]; 431 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 432 return ret; 433 } 434 EXPORT_SYMBOL(ieee80211_queue_stopped); 435 436 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 437 enum queue_stop_reason reason) 438 { 439 struct ieee80211_local *local = hw_to_local(hw); 440 unsigned long flags; 441 int i; 442 443 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 444 445 for (i = 0; i < hw->queues; i++) 446 __ieee80211_wake_queue(hw, i, reason); 447 448 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 449 } 450 451 void ieee80211_wake_queues(struct ieee80211_hw *hw) 452 { 453 ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER); 454 } 455 EXPORT_SYMBOL(ieee80211_wake_queues); 456 457 void ieee80211_iterate_active_interfaces( 458 struct ieee80211_hw *hw, 459 void (*iterator)(void *data, u8 *mac, 460 struct ieee80211_vif *vif), 461 void *data) 462 { 463 struct ieee80211_local *local = hw_to_local(hw); 464 struct ieee80211_sub_if_data *sdata; 465 466 mutex_lock(&local->iflist_mtx); 467 468 list_for_each_entry(sdata, &local->interfaces, list) { 469 switch (sdata->vif.type) { 470 case __NL80211_IFTYPE_AFTER_LAST: 471 case NL80211_IFTYPE_UNSPECIFIED: 472 case NL80211_IFTYPE_MONITOR: 473 case NL80211_IFTYPE_AP_VLAN: 474 continue; 475 case NL80211_IFTYPE_AP: 476 case NL80211_IFTYPE_STATION: 477 case NL80211_IFTYPE_ADHOC: 478 case NL80211_IFTYPE_WDS: 479 case NL80211_IFTYPE_MESH_POINT: 480 break; 481 } 482 if (ieee80211_sdata_running(sdata)) 483 iterator(data, sdata->vif.addr, 484 &sdata->vif); 485 } 486 487 mutex_unlock(&local->iflist_mtx); 488 } 489 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 490 491 void ieee80211_iterate_active_interfaces_atomic( 492 struct ieee80211_hw *hw, 493 void (*iterator)(void *data, u8 *mac, 494 struct ieee80211_vif *vif), 495 void *data) 496 { 497 struct ieee80211_local *local = hw_to_local(hw); 498 struct ieee80211_sub_if_data *sdata; 499 500 rcu_read_lock(); 501 502 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 503 switch (sdata->vif.type) { 504 case __NL80211_IFTYPE_AFTER_LAST: 505 case NL80211_IFTYPE_UNSPECIFIED: 506 case NL80211_IFTYPE_MONITOR: 507 case NL80211_IFTYPE_AP_VLAN: 508 continue; 509 case NL80211_IFTYPE_AP: 510 case NL80211_IFTYPE_STATION: 511 case NL80211_IFTYPE_ADHOC: 512 case NL80211_IFTYPE_WDS: 513 case NL80211_IFTYPE_MESH_POINT: 514 break; 515 } 516 if (ieee80211_sdata_running(sdata)) 517 iterator(data, sdata->vif.addr, 518 &sdata->vif); 519 } 520 521 rcu_read_unlock(); 522 } 523 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 524 525 /* 526 * Nothing should have been stuffed into the workqueue during 527 * the suspend->resume cycle. If this WARN is seen then there 528 * is a bug with either the driver suspend or something in 529 * mac80211 stuffing into the workqueue which we haven't yet 530 * cleared during mac80211's suspend cycle. 531 */ 532 static bool ieee80211_can_queue_work(struct ieee80211_local *local) 533 { 534 if (WARN(local->suspended && !local->resuming, 535 "queueing ieee80211 work while going to suspend\n")) 536 return false; 537 538 return true; 539 } 540 541 void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work) 542 { 543 struct ieee80211_local *local = hw_to_local(hw); 544 545 if (!ieee80211_can_queue_work(local)) 546 return; 547 548 queue_work(local->workqueue, work); 549 } 550 EXPORT_SYMBOL(ieee80211_queue_work); 551 552 void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, 553 struct delayed_work *dwork, 554 unsigned long delay) 555 { 556 struct ieee80211_local *local = hw_to_local(hw); 557 558 if (!ieee80211_can_queue_work(local)) 559 return; 560 561 queue_delayed_work(local->workqueue, dwork, delay); 562 } 563 EXPORT_SYMBOL(ieee80211_queue_delayed_work); 564 565 void ieee802_11_parse_elems(u8 *start, size_t len, 566 struct ieee802_11_elems *elems) 567 { 568 ieee802_11_parse_elems_crc(start, len, elems, 0, 0); 569 } 570 571 u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, 572 struct ieee802_11_elems *elems, 573 u64 filter, u32 crc) 574 { 575 size_t left = len; 576 u8 *pos = start; 577 bool calc_crc = filter != 0; 578 579 memset(elems, 0, sizeof(*elems)); 580 elems->ie_start = start; 581 elems->total_len = len; 582 583 while (left >= 2) { 584 u8 id, elen; 585 586 id = *pos++; 587 elen = *pos++; 588 left -= 2; 589 590 if (elen > left) 591 break; 592 593 if (calc_crc && id < 64 && (filter & (1ULL << id))) 594 crc = crc32_be(crc, pos - 2, elen + 2); 595 596 switch (id) { 597 case WLAN_EID_SSID: 598 elems->ssid = pos; 599 elems->ssid_len = elen; 600 break; 601 case WLAN_EID_SUPP_RATES: 602 elems->supp_rates = pos; 603 elems->supp_rates_len = elen; 604 break; 605 case WLAN_EID_FH_PARAMS: 606 elems->fh_params = pos; 607 elems->fh_params_len = elen; 608 break; 609 case WLAN_EID_DS_PARAMS: 610 elems->ds_params = pos; 611 elems->ds_params_len = elen; 612 break; 613 case WLAN_EID_CF_PARAMS: 614 elems->cf_params = pos; 615 elems->cf_params_len = elen; 616 break; 617 case WLAN_EID_TIM: 618 if (elen >= sizeof(struct ieee80211_tim_ie)) { 619 elems->tim = (void *)pos; 620 elems->tim_len = elen; 621 } 622 break; 623 case WLAN_EID_IBSS_PARAMS: 624 elems->ibss_params = pos; 625 elems->ibss_params_len = elen; 626 break; 627 case WLAN_EID_CHALLENGE: 628 elems->challenge = pos; 629 elems->challenge_len = elen; 630 break; 631 case WLAN_EID_VENDOR_SPECIFIC: 632 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && 633 pos[2] == 0xf2) { 634 /* Microsoft OUI (00:50:F2) */ 635 636 if (calc_crc) 637 crc = crc32_be(crc, pos - 2, elen + 2); 638 639 if (pos[3] == 1) { 640 /* OUI Type 1 - WPA IE */ 641 elems->wpa = pos; 642 elems->wpa_len = elen; 643 } else if (elen >= 5 && pos[3] == 2) { 644 /* OUI Type 2 - WMM IE */ 645 if (pos[4] == 0) { 646 elems->wmm_info = pos; 647 elems->wmm_info_len = elen; 648 } else if (pos[4] == 1) { 649 elems->wmm_param = pos; 650 elems->wmm_param_len = elen; 651 } 652 } 653 } 654 break; 655 case WLAN_EID_RSN: 656 elems->rsn = pos; 657 elems->rsn_len = elen; 658 break; 659 case WLAN_EID_ERP_INFO: 660 elems->erp_info = pos; 661 elems->erp_info_len = elen; 662 break; 663 case WLAN_EID_EXT_SUPP_RATES: 664 elems->ext_supp_rates = pos; 665 elems->ext_supp_rates_len = elen; 666 break; 667 case WLAN_EID_HT_CAPABILITY: 668 if (elen >= sizeof(struct ieee80211_ht_cap)) 669 elems->ht_cap_elem = (void *)pos; 670 break; 671 case WLAN_EID_HT_INFORMATION: 672 if (elen >= sizeof(struct ieee80211_ht_info)) 673 elems->ht_info_elem = (void *)pos; 674 break; 675 case WLAN_EID_MESH_ID: 676 elems->mesh_id = pos; 677 elems->mesh_id_len = elen; 678 break; 679 case WLAN_EID_MESH_CONFIG: 680 if (elen >= sizeof(struct ieee80211_meshconf_ie)) 681 elems->mesh_config = (void *)pos; 682 break; 683 case WLAN_EID_PEER_LINK: 684 elems->peer_link = pos; 685 elems->peer_link_len = elen; 686 break; 687 case WLAN_EID_PREQ: 688 elems->preq = pos; 689 elems->preq_len = elen; 690 break; 691 case WLAN_EID_PREP: 692 elems->prep = pos; 693 elems->prep_len = elen; 694 break; 695 case WLAN_EID_PERR: 696 elems->perr = pos; 697 elems->perr_len = elen; 698 break; 699 case WLAN_EID_RANN: 700 if (elen >= sizeof(struct ieee80211_rann_ie)) 701 elems->rann = (void *)pos; 702 break; 703 case WLAN_EID_CHANNEL_SWITCH: 704 elems->ch_switch_elem = pos; 705 elems->ch_switch_elem_len = elen; 706 break; 707 case WLAN_EID_QUIET: 708 if (!elems->quiet_elem) { 709 elems->quiet_elem = pos; 710 elems->quiet_elem_len = elen; 711 } 712 elems->num_of_quiet_elem++; 713 break; 714 case WLAN_EID_COUNTRY: 715 elems->country_elem = pos; 716 elems->country_elem_len = elen; 717 break; 718 case WLAN_EID_PWR_CONSTRAINT: 719 elems->pwr_constr_elem = pos; 720 elems->pwr_constr_elem_len = elen; 721 break; 722 case WLAN_EID_TIMEOUT_INTERVAL: 723 elems->timeout_int = pos; 724 elems->timeout_int_len = elen; 725 break; 726 default: 727 break; 728 } 729 730 left -= elen; 731 pos += elen; 732 } 733 734 return crc; 735 } 736 737 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) 738 { 739 struct ieee80211_local *local = sdata->local; 740 struct ieee80211_tx_queue_params qparam; 741 int queue; 742 bool use_11b; 743 int aCWmin, aCWmax; 744 745 if (!local->ops->conf_tx) 746 return; 747 748 memset(&qparam, 0, sizeof(qparam)); 749 750 use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && 751 !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); 752 753 for (queue = 0; queue < local_to_hw(local)->queues; queue++) { 754 /* Set defaults according to 802.11-2007 Table 7-37 */ 755 aCWmax = 1023; 756 if (use_11b) 757 aCWmin = 31; 758 else 759 aCWmin = 15; 760 761 switch (queue) { 762 case 3: /* AC_BK */ 763 qparam.cw_max = aCWmax; 764 qparam.cw_min = aCWmin; 765 qparam.txop = 0; 766 qparam.aifs = 7; 767 break; 768 default: /* never happens but let's not leave undefined */ 769 case 2: /* AC_BE */ 770 qparam.cw_max = aCWmax; 771 qparam.cw_min = aCWmin; 772 qparam.txop = 0; 773 qparam.aifs = 3; 774 break; 775 case 1: /* AC_VI */ 776 qparam.cw_max = aCWmin; 777 qparam.cw_min = (aCWmin + 1) / 2 - 1; 778 if (use_11b) 779 qparam.txop = 6016/32; 780 else 781 qparam.txop = 3008/32; 782 qparam.aifs = 2; 783 break; 784 case 0: /* AC_VO */ 785 qparam.cw_max = (aCWmin + 1) / 2 - 1; 786 qparam.cw_min = (aCWmin + 1) / 4 - 1; 787 if (use_11b) 788 qparam.txop = 3264/32; 789 else 790 qparam.txop = 1504/32; 791 qparam.aifs = 2; 792 break; 793 } 794 795 qparam.uapsd = false; 796 797 drv_conf_tx(local, queue, &qparam); 798 } 799 } 800 801 void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, 802 const size_t supp_rates_len, 803 const u8 *supp_rates) 804 { 805 struct ieee80211_local *local = sdata->local; 806 int i, have_higher_than_11mbit = 0; 807 808 /* cf. IEEE 802.11 9.2.12 */ 809 for (i = 0; i < supp_rates_len; i++) 810 if ((supp_rates[i] & 0x7f) * 5 > 110) 811 have_higher_than_11mbit = 1; 812 813 if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && 814 have_higher_than_11mbit) 815 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; 816 else 817 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 818 819 ieee80211_set_wmm_default(sdata); 820 } 821 822 u32 ieee80211_mandatory_rates(struct ieee80211_local *local, 823 enum ieee80211_band band) 824 { 825 struct ieee80211_supported_band *sband; 826 struct ieee80211_rate *bitrates; 827 u32 mandatory_rates; 828 enum ieee80211_rate_flags mandatory_flag; 829 int i; 830 831 sband = local->hw.wiphy->bands[band]; 832 if (!sband) { 833 WARN_ON(1); 834 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 835 } 836 837 if (band == IEEE80211_BAND_2GHZ) 838 mandatory_flag = IEEE80211_RATE_MANDATORY_B; 839 else 840 mandatory_flag = IEEE80211_RATE_MANDATORY_A; 841 842 bitrates = sband->bitrates; 843 mandatory_rates = 0; 844 for (i = 0; i < sband->n_bitrates; i++) 845 if (bitrates[i].flags & mandatory_flag) 846 mandatory_rates |= BIT(i); 847 return mandatory_rates; 848 } 849 850 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 851 u16 transaction, u16 auth_alg, 852 u8 *extra, size_t extra_len, const u8 *bssid, 853 const u8 *key, u8 key_len, u8 key_idx) 854 { 855 struct ieee80211_local *local = sdata->local; 856 struct sk_buff *skb; 857 struct ieee80211_mgmt *mgmt; 858 int err; 859 860 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 861 sizeof(*mgmt) + 6 + extra_len); 862 if (!skb) { 863 printk(KERN_DEBUG "%s: failed to allocate buffer for auth " 864 "frame\n", sdata->name); 865 return; 866 } 867 skb_reserve(skb, local->hw.extra_tx_headroom); 868 869 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); 870 memset(mgmt, 0, 24 + 6); 871 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 872 IEEE80211_STYPE_AUTH); 873 memcpy(mgmt->da, bssid, ETH_ALEN); 874 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 875 memcpy(mgmt->bssid, bssid, ETH_ALEN); 876 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); 877 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); 878 mgmt->u.auth.status_code = cpu_to_le16(0); 879 if (extra) 880 memcpy(skb_put(skb, extra_len), extra, extra_len); 881 882 if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) { 883 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 884 err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx); 885 WARN_ON(err); 886 } 887 888 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 889 ieee80211_tx_skb(sdata, skb); 890 } 891 892 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 893 const u8 *ie, size_t ie_len, 894 enum ieee80211_band band) 895 { 896 struct ieee80211_supported_band *sband; 897 u8 *pos; 898 size_t offset = 0, noffset; 899 int supp_rates_len, i; 900 901 sband = local->hw.wiphy->bands[band]; 902 903 pos = buffer; 904 905 supp_rates_len = min_t(int, sband->n_bitrates, 8); 906 907 *pos++ = WLAN_EID_SUPP_RATES; 908 *pos++ = supp_rates_len; 909 910 for (i = 0; i < supp_rates_len; i++) { 911 int rate = sband->bitrates[i].bitrate; 912 *pos++ = (u8) (rate / 5); 913 } 914 915 /* insert "request information" if in custom IEs */ 916 if (ie && ie_len) { 917 static const u8 before_extrates[] = { 918 WLAN_EID_SSID, 919 WLAN_EID_SUPP_RATES, 920 WLAN_EID_REQUEST, 921 }; 922 noffset = ieee80211_ie_split(ie, ie_len, 923 before_extrates, 924 ARRAY_SIZE(before_extrates), 925 offset); 926 memcpy(pos, ie + offset, noffset - offset); 927 pos += noffset - offset; 928 offset = noffset; 929 } 930 931 if (sband->n_bitrates > i) { 932 *pos++ = WLAN_EID_EXT_SUPP_RATES; 933 *pos++ = sband->n_bitrates - i; 934 935 for (; i < sband->n_bitrates; i++) { 936 int rate = sband->bitrates[i].bitrate; 937 *pos++ = (u8) (rate / 5); 938 } 939 } 940 941 /* insert custom IEs that go before HT */ 942 if (ie && ie_len) { 943 static const u8 before_ht[] = { 944 WLAN_EID_SSID, 945 WLAN_EID_SUPP_RATES, 946 WLAN_EID_REQUEST, 947 WLAN_EID_EXT_SUPP_RATES, 948 WLAN_EID_DS_PARAMS, 949 WLAN_EID_SUPPORTED_REGULATORY_CLASSES, 950 }; 951 noffset = ieee80211_ie_split(ie, ie_len, 952 before_ht, ARRAY_SIZE(before_ht), 953 offset); 954 memcpy(pos, ie + offset, noffset - offset); 955 pos += noffset - offset; 956 offset = noffset; 957 } 958 959 if (sband->ht_cap.ht_supported) { 960 u16 cap = sband->ht_cap.cap; 961 __le16 tmp; 962 963 if (ieee80211_disable_40mhz_24ghz && 964 sband->band == IEEE80211_BAND_2GHZ) { 965 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 966 cap &= ~IEEE80211_HT_CAP_SGI_40; 967 } 968 969 *pos++ = WLAN_EID_HT_CAPABILITY; 970 *pos++ = sizeof(struct ieee80211_ht_cap); 971 memset(pos, 0, sizeof(struct ieee80211_ht_cap)); 972 tmp = cpu_to_le16(cap); 973 memcpy(pos, &tmp, sizeof(u16)); 974 pos += sizeof(u16); 975 *pos++ = sband->ht_cap.ampdu_factor | 976 (sband->ht_cap.ampdu_density << 977 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); 978 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); 979 pos += sizeof(sband->ht_cap.mcs); 980 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ 981 } 982 983 /* 984 * If adding more here, adjust code in main.c 985 * that calculates local->scan_ies_len. 986 */ 987 988 /* add any remaining custom IEs */ 989 if (ie && ie_len) { 990 noffset = ie_len; 991 memcpy(pos, ie + offset, noffset - offset); 992 pos += noffset - offset; 993 } 994 995 return pos - buffer; 996 } 997 998 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 999 const u8 *ssid, size_t ssid_len, 1000 const u8 *ie, size_t ie_len) 1001 { 1002 struct ieee80211_local *local = sdata->local; 1003 struct sk_buff *skb; 1004 struct ieee80211_mgmt *mgmt; 1005 size_t buf_len; 1006 u8 *buf; 1007 1008 /* FIXME: come up with a proper value */ 1009 buf = kmalloc(200 + ie_len, GFP_KERNEL); 1010 if (!buf) { 1011 printk(KERN_DEBUG "%s: failed to allocate temporary IE " 1012 "buffer\n", sdata->name); 1013 return; 1014 } 1015 1016 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, 1017 local->hw.conf.channel->band); 1018 1019 skb = ieee80211_probereq_get(&local->hw, &sdata->vif, 1020 ssid, ssid_len, 1021 buf, buf_len); 1022 1023 if (dst) { 1024 mgmt = (struct ieee80211_mgmt *) skb->data; 1025 memcpy(mgmt->da, dst, ETH_ALEN); 1026 memcpy(mgmt->bssid, dst, ETH_ALEN); 1027 } 1028 1029 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 1030 ieee80211_tx_skb(sdata, skb); 1031 kfree(buf); 1032 } 1033 1034 u32 ieee80211_sta_get_rates(struct ieee80211_local *local, 1035 struct ieee802_11_elems *elems, 1036 enum ieee80211_band band) 1037 { 1038 struct ieee80211_supported_band *sband; 1039 struct ieee80211_rate *bitrates; 1040 size_t num_rates; 1041 u32 supp_rates; 1042 int i, j; 1043 sband = local->hw.wiphy->bands[band]; 1044 1045 if (!sband) { 1046 WARN_ON(1); 1047 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 1048 } 1049 1050 bitrates = sband->bitrates; 1051 num_rates = sband->n_bitrates; 1052 supp_rates = 0; 1053 for (i = 0; i < elems->supp_rates_len + 1054 elems->ext_supp_rates_len; i++) { 1055 u8 rate = 0; 1056 int own_rate; 1057 if (i < elems->supp_rates_len) 1058 rate = elems->supp_rates[i]; 1059 else if (elems->ext_supp_rates) 1060 rate = elems->ext_supp_rates 1061 [i - elems->supp_rates_len]; 1062 own_rate = 5 * (rate & 0x7f); 1063 for (j = 0; j < num_rates; j++) 1064 if (bitrates[j].bitrate == own_rate) 1065 supp_rates |= BIT(j); 1066 } 1067 return supp_rates; 1068 } 1069 1070 void ieee80211_stop_device(struct ieee80211_local *local) 1071 { 1072 ieee80211_led_radio(local, false); 1073 1074 cancel_work_sync(&local->reconfig_filter); 1075 1076 flush_workqueue(local->workqueue); 1077 drv_stop(local); 1078 } 1079 1080 int ieee80211_reconfig(struct ieee80211_local *local) 1081 { 1082 struct ieee80211_hw *hw = &local->hw; 1083 struct ieee80211_sub_if_data *sdata; 1084 struct sta_info *sta; 1085 int res; 1086 1087 if (local->suspended) 1088 local->resuming = true; 1089 1090 /* restart hardware */ 1091 if (local->open_count) { 1092 /* 1093 * Upon resume hardware can sometimes be goofy due to 1094 * various platform / driver / bus issues, so restarting 1095 * the device may at times not work immediately. Propagate 1096 * the error. 1097 */ 1098 res = drv_start(local); 1099 if (res) { 1100 WARN(local->suspended, "Hardware became unavailable " 1101 "upon resume. This could be a software issue " 1102 "prior to suspend or a hardware issue.\n"); 1103 return res; 1104 } 1105 1106 ieee80211_led_radio(local, true); 1107 } 1108 1109 /* add interfaces */ 1110 list_for_each_entry(sdata, &local->interfaces, list) { 1111 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1112 sdata->vif.type != NL80211_IFTYPE_MONITOR && 1113 ieee80211_sdata_running(sdata)) 1114 res = drv_add_interface(local, &sdata->vif); 1115 } 1116 1117 /* add STAs back */ 1118 mutex_lock(&local->sta_mtx); 1119 list_for_each_entry(sta, &local->sta_list, list) { 1120 if (sta->uploaded) { 1121 sdata = sta->sdata; 1122 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1123 sdata = container_of(sdata->bss, 1124 struct ieee80211_sub_if_data, 1125 u.ap); 1126 1127 WARN_ON(drv_sta_add(local, sdata, &sta->sta)); 1128 } 1129 } 1130 mutex_unlock(&local->sta_mtx); 1131 1132 /* Clear Suspend state so that ADDBA requests can be processed */ 1133 1134 rcu_read_lock(); 1135 1136 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 1137 list_for_each_entry_rcu(sta, &local->sta_list, list) { 1138 clear_sta_flags(sta, WLAN_STA_SUSPEND); 1139 } 1140 } 1141 1142 rcu_read_unlock(); 1143 1144 /* setup RTS threshold */ 1145 drv_set_rts_threshold(local, hw->wiphy->rts_threshold); 1146 1147 /* reconfigure hardware */ 1148 ieee80211_hw_config(local, ~0); 1149 1150 ieee80211_configure_filter(local); 1151 1152 /* Finally also reconfigure all the BSS information */ 1153 list_for_each_entry(sdata, &local->interfaces, list) { 1154 u32 changed = ~0; 1155 if (!ieee80211_sdata_running(sdata)) 1156 continue; 1157 switch (sdata->vif.type) { 1158 case NL80211_IFTYPE_STATION: 1159 /* disable beacon change bits */ 1160 changed &= ~(BSS_CHANGED_BEACON | 1161 BSS_CHANGED_BEACON_ENABLED); 1162 /* fall through */ 1163 case NL80211_IFTYPE_ADHOC: 1164 case NL80211_IFTYPE_AP: 1165 case NL80211_IFTYPE_MESH_POINT: 1166 ieee80211_bss_info_change_notify(sdata, changed); 1167 break; 1168 case NL80211_IFTYPE_WDS: 1169 break; 1170 case NL80211_IFTYPE_AP_VLAN: 1171 case NL80211_IFTYPE_MONITOR: 1172 /* ignore virtual */ 1173 break; 1174 case NL80211_IFTYPE_UNSPECIFIED: 1175 case __NL80211_IFTYPE_AFTER_LAST: 1176 WARN_ON(1); 1177 break; 1178 } 1179 } 1180 1181 rcu_read_lock(); 1182 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 1183 list_for_each_entry_rcu(sta, &local->sta_list, list) { 1184 ieee80211_sta_tear_down_BA_sessions(sta); 1185 } 1186 } 1187 rcu_read_unlock(); 1188 1189 /* add back keys */ 1190 list_for_each_entry(sdata, &local->interfaces, list) 1191 if (ieee80211_sdata_running(sdata)) 1192 ieee80211_enable_keys(sdata); 1193 1194 ieee80211_wake_queues_by_reason(hw, 1195 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 1196 1197 /* 1198 * If this is for hw restart things are still running. 1199 * We may want to change that later, however. 1200 */ 1201 if (!local->suspended) 1202 return 0; 1203 1204 #ifdef CONFIG_PM 1205 /* first set suspended false, then resuming */ 1206 local->suspended = false; 1207 mb(); 1208 local->resuming = false; 1209 1210 list_for_each_entry(sdata, &local->interfaces, list) { 1211 switch(sdata->vif.type) { 1212 case NL80211_IFTYPE_STATION: 1213 ieee80211_sta_restart(sdata); 1214 break; 1215 case NL80211_IFTYPE_ADHOC: 1216 ieee80211_ibss_restart(sdata); 1217 break; 1218 case NL80211_IFTYPE_MESH_POINT: 1219 ieee80211_mesh_restart(sdata); 1220 break; 1221 default: 1222 break; 1223 } 1224 } 1225 1226 add_timer(&local->sta_cleanup); 1227 1228 mutex_lock(&local->sta_mtx); 1229 list_for_each_entry(sta, &local->sta_list, list) 1230 mesh_plink_restart(sta); 1231 mutex_unlock(&local->sta_mtx); 1232 #else 1233 WARN_ON(1); 1234 #endif 1235 return 0; 1236 } 1237 1238 static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, 1239 enum ieee80211_smps_mode *smps_mode) 1240 { 1241 if (ifmgd->associated) { 1242 *smps_mode = ifmgd->ap_smps; 1243 1244 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) { 1245 if (ifmgd->powersave) 1246 *smps_mode = IEEE80211_SMPS_DYNAMIC; 1247 else 1248 *smps_mode = IEEE80211_SMPS_OFF; 1249 } 1250 1251 return 1; 1252 } 1253 1254 return 0; 1255 } 1256 1257 /* must hold iflist_mtx */ 1258 void ieee80211_recalc_smps(struct ieee80211_local *local, 1259 struct ieee80211_sub_if_data *forsdata) 1260 { 1261 struct ieee80211_sub_if_data *sdata; 1262 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; 1263 int count = 0; 1264 1265 if (forsdata) 1266 WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx)); 1267 1268 WARN_ON(!mutex_is_locked(&local->iflist_mtx)); 1269 1270 /* 1271 * This function could be improved to handle multiple 1272 * interfaces better, but right now it makes any 1273 * non-station interfaces force SM PS to be turned 1274 * off. If there are multiple station interfaces it 1275 * could also use the best possible mode, e.g. if 1276 * one is in static and the other in dynamic then 1277 * dynamic is ok. 1278 */ 1279 1280 list_for_each_entry(sdata, &local->interfaces, list) { 1281 if (!netif_running(sdata->dev)) 1282 continue; 1283 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1284 goto set; 1285 if (sdata != forsdata) { 1286 /* 1287 * This nested is ok -- we are holding the iflist_mtx 1288 * so can't get here twice or so. But it's required 1289 * since normally we acquire it first and then the 1290 * iflist_mtx. 1291 */ 1292 mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING); 1293 count += check_mgd_smps(&sdata->u.mgd, &smps_mode); 1294 mutex_unlock(&sdata->u.mgd.mtx); 1295 } else 1296 count += check_mgd_smps(&sdata->u.mgd, &smps_mode); 1297 1298 if (count > 1) { 1299 smps_mode = IEEE80211_SMPS_OFF; 1300 break; 1301 } 1302 } 1303 1304 if (smps_mode == local->smps_mode) 1305 return; 1306 1307 set: 1308 local->smps_mode = smps_mode; 1309 /* changed flag is auto-detected for this */ 1310 ieee80211_hw_config(local, 0); 1311 } 1312 1313 static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) 1314 { 1315 int i; 1316 1317 for (i = 0; i < n_ids; i++) 1318 if (ids[i] == id) 1319 return true; 1320 return false; 1321 } 1322 1323 /** 1324 * ieee80211_ie_split - split an IE buffer according to ordering 1325 * 1326 * @ies: the IE buffer 1327 * @ielen: the length of the IE buffer 1328 * @ids: an array with element IDs that are allowed before 1329 * the split 1330 * @n_ids: the size of the element ID array 1331 * @offset: offset where to start splitting in the buffer 1332 * 1333 * This function splits an IE buffer by updating the @offset 1334 * variable to point to the location where the buffer should be 1335 * split. 1336 * 1337 * It assumes that the given IE buffer is well-formed, this 1338 * has to be guaranteed by the caller! 1339 * 1340 * It also assumes that the IEs in the buffer are ordered 1341 * correctly, if not the result of using this function will not 1342 * be ordered correctly either, i.e. it does no reordering. 1343 * 1344 * The function returns the offset where the next part of the 1345 * buffer starts, which may be @ielen if the entire (remainder) 1346 * of the buffer should be used. 1347 */ 1348 size_t ieee80211_ie_split(const u8 *ies, size_t ielen, 1349 const u8 *ids, int n_ids, size_t offset) 1350 { 1351 size_t pos = offset; 1352 1353 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) 1354 pos += 2 + ies[pos + 1]; 1355 1356 return pos; 1357 } 1358 1359 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) 1360 { 1361 size_t pos = offset; 1362 1363 while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC) 1364 pos += 2 + ies[pos + 1]; 1365 1366 return pos; 1367 } 1368