1/** 2 * Functions implementing wlan scan IOCTL and firmware command APIs 3 * 4 * IOCTL handlers as well as command preperation and response routines 5 * for sending scan commands to the firmware. 6 */ 7#include <linux/ctype.h> 8#include <linux/if.h> 9#include <linux/netdevice.h> 10#include <linux/wireless.h> 11#include <linux/etherdevice.h> 12 13#include <net/ieee80211.h> 14#include <net/iw_handler.h> 15 16#include "host.h" 17#include "decl.h" 18#include "dev.h" 19#include "scan.h" 20 21//! Approximate amount of data needed to pass a scan result back to iwlist 22#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ 23 + IW_ESSID_MAX_SIZE \ 24 + IW_EV_UINT_LEN \ 25 + IW_EV_FREQ_LEN \ 26 + IW_EV_QUAL_LEN \ 27 + IW_ESSID_MAX_SIZE \ 28 + IW_EV_PARAM_LEN \ 29 + 40) /* 40 for WPAIE */ 30 31//! Memory needed to store a max sized channel List TLV for a firmware scan 32#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvlietypesheader) \ 33 + (MRVDRV_MAX_CHANNELS_PER_SCAN \ 34 * sizeof(struct chanscanparamset))) 35 36//! Memory needed to store a max number/size SSID TLV for a firmware scan 37#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) 38 39//! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max 40#define MAX_SCAN_CFG_ALLOC (sizeof(struct wlan_scan_cmd_config) \ 41 + sizeof(struct mrvlietypes_numprobes) \ 42 + CHAN_TLV_MAX_SIZE \ 43 + SSID_TLV_MAX_SIZE) 44 45//! The maximum number of channels the firmware can scan per command 46#define MRVDRV_MAX_CHANNELS_PER_SCAN 14 47 48/** 49 * @brief Number of channels to scan per firmware scan command issuance. 50 * 51 * Number restricted to prevent hitting the limit on the amount of scan data 52 * returned in a single firmware scan command. 53 */ 54#define MRVDRV_CHANNELS_PER_SCAN_CMD 4 55 56//! Scan time specified in the channel TLV for each channel for passive scans 57#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100 58 59//! Scan time specified in the channel TLV for each channel for active scans 60#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 61 62static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 63static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 64 65static inline void clear_bss_descriptor (struct bss_descriptor * bss) 66{ 67 /* Don't blow away ->list, just BSS data */ 68 memset(bss, 0, offsetof(struct bss_descriptor, list)); 69} 70 71static inline int match_bss_no_security(struct wlan_802_11_security * secinfo, 72 struct bss_descriptor * match_bss) 73{ 74 if ( !secinfo->wep_enabled 75 && !secinfo->WPAenabled 76 && !secinfo->WPA2enabled 77 && match_bss->wpa_ie[0] != WPA_IE 78 && match_bss->rsn_ie[0] != WPA2_IE 79 && !match_bss->privacy) { 80 return 1; 81 } 82 return 0; 83} 84 85static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo, 86 struct bss_descriptor * match_bss) 87{ 88 if ( secinfo->wep_enabled 89 && !secinfo->WPAenabled 90 && !secinfo->WPA2enabled 91 && match_bss->privacy) { 92 return 1; 93 } 94 return 0; 95} 96 97static inline int match_bss_wpa(struct wlan_802_11_security * secinfo, 98 struct bss_descriptor * match_bss) 99{ 100 if ( !secinfo->wep_enabled 101 && secinfo->WPAenabled 102 && (match_bss->wpa_ie[0] == WPA_IE) 103 /* privacy bit may NOT be set in some APs like LinkSys WRT54G 104 && bss->privacy */ 105 ) { 106 return 1; 107 } 108 return 0; 109} 110 111static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo, 112 struct bss_descriptor * match_bss) 113{ 114 if ( !secinfo->wep_enabled 115 && secinfo->WPA2enabled 116 && (match_bss->rsn_ie[0] == WPA2_IE) 117 /* privacy bit may NOT be set in some APs like LinkSys WRT54G 118 && bss->privacy */ 119 ) { 120 return 1; 121 } 122 return 0; 123} 124 125static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo, 126 struct bss_descriptor * match_bss) 127{ 128 if ( !secinfo->wep_enabled 129 && !secinfo->WPAenabled 130 && !secinfo->WPA2enabled 131 && (match_bss->wpa_ie[0] != WPA_IE) 132 && (match_bss->rsn_ie[0] != WPA2_IE) 133 && match_bss->privacy) { 134 return 1; 135 } 136 return 0; 137} 138 139/** 140 * @brief Check if a scanned network compatible with the driver settings 141 * 142 * WEP WPA WPA2 ad-hoc encrypt Network 143 * enabled enabled enabled AES mode privacy WPA WPA2 Compatible 144 * 0 0 0 0 NONE 0 0 0 yes No security 145 * 1 0 0 0 NONE 1 0 0 yes Static WEP 146 * 0 1 0 0 x 1x 1 x yes WPA 147 * 0 0 1 0 x 1x x 1 yes WPA2 148 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES 149 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP 150 * 151 * 152 * @param adapter A pointer to wlan_adapter 153 * @param index Index in scantable to check against current driver settings 154 * @param mode Network mode: Infrastructure or IBSS 155 * 156 * @return Index in scantable, or error code if negative 157 */ 158static int is_network_compatible(wlan_adapter * adapter, 159 struct bss_descriptor * bss, u8 mode) 160{ 161 int matched = 0; 162 163 lbs_deb_enter(LBS_DEB_ASSOC); 164 165 if (bss->mode != mode) 166 goto done; 167 168 if ((matched = match_bss_no_security(&adapter->secinfo, bss))) { 169 goto done; 170 } else if ((matched = match_bss_static_wep(&adapter->secinfo, bss))) { 171 goto done; 172 } else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) { 173 lbs_deb_scan( 174 "is_network_compatible() WPA: wpa_ie=%#x " 175 "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " 176 "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0], 177 adapter->secinfo.wep_enabled ? "e" : "d", 178 adapter->secinfo.WPAenabled ? "e" : "d", 179 adapter->secinfo.WPA2enabled ? "e" : "d", 180 bss->privacy); 181 goto done; 182 } else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) { 183 lbs_deb_scan( 184 "is_network_compatible() WPA2: wpa_ie=%#x " 185 "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " 186 "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0], 187 adapter->secinfo.wep_enabled ? "e" : "d", 188 adapter->secinfo.WPAenabled ? "e" : "d", 189 adapter->secinfo.WPA2enabled ? "e" : "d", 190 bss->privacy); 191 goto done; 192 } else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) { 193 lbs_deb_scan( 194 "is_network_compatible() dynamic WEP: " 195 "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n", 196 bss->wpa_ie[0], 197 bss->rsn_ie[0], 198 bss->privacy); 199 goto done; 200 } 201 202 /* bss security settings don't match those configured on card */ 203 lbs_deb_scan( 204 "is_network_compatible() FAILED: wpa_ie=%#x " 205 "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n", 206 bss->wpa_ie[0], bss->rsn_ie[0], 207 adapter->secinfo.wep_enabled ? "e" : "d", 208 adapter->secinfo.WPAenabled ? "e" : "d", 209 adapter->secinfo.WPA2enabled ? "e" : "d", 210 bss->privacy); 211 212done: 213 lbs_deb_leave(LBS_DEB_SCAN); 214 return matched; 215} 216 217/** 218 * @brief Create a channel list for the driver to scan based on region info 219 * 220 * Use the driver region/band information to construct a comprehensive list 221 * of channels to scan. This routine is used for any scan that is not 222 * provided a specific channel list to scan. 223 * 224 * @param priv A pointer to wlan_private structure 225 * @param scanchanlist Output parameter: resulting channel list to scan 226 * @param filteredscan Flag indicating whether or not a BSSID or SSID filter 227 * is being sent in the command to firmware. Used to 228 * increase the number of channels sent in a scan 229 * command and to disable the firmware channel scan 230 * filter. 231 * 232 * @return void 233 */ 234static void wlan_scan_create_channel_list(wlan_private * priv, 235 struct chanscanparamset * scanchanlist, 236 u8 filteredscan) 237{ 238 239 wlan_adapter *adapter = priv->adapter; 240 struct region_channel *scanregion; 241 struct chan_freq_power *cfp; 242 int rgnidx; 243 int chanidx; 244 int nextchan; 245 u8 scantype; 246 247 chanidx = 0; 248 249 /* Set the default scan type to the user specified type, will later 250 * be changed to passive on a per channel basis if restricted by 251 * regulatory requirements (11d or 11h) 252 */ 253 scantype = adapter->scantype; 254 255 for (rgnidx = 0; rgnidx < ARRAY_SIZE(adapter->region_channel); rgnidx++) { 256 if (priv->adapter->enable11d && 257 adapter->connect_status != libertas_connected) { 258 /* Scan all the supported chan for the first scan */ 259 if (!adapter->universal_channel[rgnidx].valid) 260 continue; 261 scanregion = &adapter->universal_channel[rgnidx]; 262 263 /* clear the parsed_region_chan for the first scan */ 264 memset(&adapter->parsed_region_chan, 0x00, 265 sizeof(adapter->parsed_region_chan)); 266 } else { 267 if (!adapter->region_channel[rgnidx].valid) 268 continue; 269 scanregion = &adapter->region_channel[rgnidx]; 270 } 271 272 for (nextchan = 0; 273 nextchan < scanregion->nrcfp; nextchan++, chanidx++) { 274 275 cfp = scanregion->CFP + nextchan; 276 277 if (priv->adapter->enable11d) { 278 scantype = 279 libertas_get_scan_type_11d(cfp->channel, 280 &adapter-> 281 parsed_region_chan); 282 } 283 284 switch (scanregion->band) { 285 case BAND_B: 286 case BAND_G: 287 default: 288 scanchanlist[chanidx].radiotype = 289 cmd_scan_radio_type_bg; 290 break; 291 } 292 293 if (scantype == cmd_scan_type_passive) { 294 scanchanlist[chanidx].maxscantime = 295 cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); 296 scanchanlist[chanidx].chanscanmode.passivescan = 297 1; 298 } else { 299 scanchanlist[chanidx].maxscantime = 300 cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); 301 scanchanlist[chanidx].chanscanmode.passivescan = 302 0; 303 } 304 305 scanchanlist[chanidx].channumber = cfp->channel; 306 307 if (filteredscan) { 308 scanchanlist[chanidx].chanscanmode. 309 disablechanfilt = 1; 310 } 311 } 312 } 313} 314 315/** 316 * @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds 317 * 318 * Application layer or other functions can invoke wlan_scan_networks 319 * with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct. 320 * This structure is used as the basis of one or many wlan_scan_cmd_config 321 * commands that are sent to the command processing module and sent to 322 * firmware. 323 * 324 * Create a wlan_scan_cmd_config based on the following user supplied 325 * parameters (if present): 326 * - SSID filter 327 * - BSSID filter 328 * - Number of Probes to be sent 329 * - channel list 330 * 331 * If the SSID or BSSID filter is not present, disable/clear the filter. 332 * If the number of probes is not set, use the adapter default setting 333 * Qualify the channel 334 * 335 * @param priv A pointer to wlan_private structure 336 * @param puserscanin NULL or pointer to scan configuration parameters 337 * @param ppchantlvout Output parameter: Pointer to the start of the 338 * channel TLV portion of the output scan config 339 * @param pscanchanlist Output parameter: Pointer to the resulting channel 340 * list to scan 341 * @param pmaxchanperscan Output parameter: Number of channels to scan for 342 * each issuance of the firmware scan command 343 * @param pfilteredscan Output parameter: Flag indicating whether or not 344 * a BSSID or SSID filter is being sent in the 345 * command to firmware. Used to increase the number 346 * of channels sent in a scan command and to 347 * disable the firmware channel scan filter. 348 * @param pscancurrentonly Output parameter: Flag indicating whether or not 349 * we are only scanning our current active channel 350 * 351 * @return resulting scan configuration 352 */ 353static struct wlan_scan_cmd_config * 354wlan_scan_setup_scan_config(wlan_private * priv, 355 const struct wlan_ioctl_user_scan_cfg * puserscanin, 356 struct mrvlietypes_chanlistparamset ** ppchantlvout, 357 struct chanscanparamset * pscanchanlist, 358 int *pmaxchanperscan, 359 u8 * pfilteredscan, 360 u8 * pscancurrentonly) 361{ 362 wlan_adapter *adapter = priv->adapter; 363 struct mrvlietypes_numprobes *pnumprobestlv; 364 struct mrvlietypes_ssidparamset *pssidtlv; 365 struct wlan_scan_cmd_config * pscancfgout = NULL; 366 u8 *ptlvpos; 367 u16 numprobes; 368 int chanidx; 369 int scantype; 370 int scandur; 371 int channel; 372 int radiotype; 373 374 pscancfgout = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); 375 if (pscancfgout == NULL) 376 goto out; 377 378 /* The tlvbufferlen is calculated for each scan command. The TLVs added 379 * in this routine will be preserved since the routine that sends 380 * the command will append channelTLVs at *ppchantlvout. The difference 381 * between the *ppchantlvout and the tlvbuffer start will be used 382 * to calculate the size of anything we add in this routine. 383 */ 384 pscancfgout->tlvbufferlen = 0; 385 386 /* Running tlv pointer. Assigned to ppchantlvout at end of function 387 * so later routines know where channels can be added to the command buf 388 */ 389 ptlvpos = pscancfgout->tlvbuffer; 390 391 /* 392 * Set the initial scan paramters for progressive scanning. If a specific 393 * BSSID or SSID is used, the number of channels in the scan command 394 * will be increased to the absolute maximum 395 */ 396 *pmaxchanperscan = MRVDRV_CHANNELS_PER_SCAN_CMD; 397 398 /* Initialize the scan as un-filtered by firmware, set to TRUE below if 399 * a SSID or BSSID filter is sent in the command 400 */ 401 *pfilteredscan = 0; 402 403 /* Initialize the scan as not being only on the current channel. If 404 * the channel list is customized, only contains one channel, and 405 * is the active channel, this is set true and data flow is not halted. 406 */ 407 *pscancurrentonly = 0; 408 409 if (puserscanin) { 410 411 /* Set the bss type scan filter, use adapter setting if unset */ 412 pscancfgout->bsstype = 413 (puserscanin->bsstype ? puserscanin->bsstype : adapter-> 414 scanmode); 415 416 /* Set the number of probes to send, use adapter setting if unset */ 417 numprobes = (puserscanin->numprobes ? puserscanin->numprobes : 418 adapter->scanprobes); 419 420 /* 421 * Set the BSSID filter to the incoming configuration, 422 * if non-zero. If not set, it will remain disabled (all zeros). 423 */ 424 memcpy(pscancfgout->bssid, puserscanin->bssid, 425 sizeof(pscancfgout->bssid)); 426 427 if (puserscanin->ssid_len) { 428 pssidtlv = 429 (struct mrvlietypes_ssidparamset *) pscancfgout-> 430 tlvbuffer; 431 pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID); 432 pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len); 433 memcpy(pssidtlv->ssid, puserscanin->ssid, 434 puserscanin->ssid_len); 435 ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len; 436 } 437 438 /* 439 * The default number of channels sent in the command is low to 440 * ensure the response buffer from the firmware does not truncate 441 * scan results. That is not an issue with an SSID or BSSID 442 * filter applied to the scan results in the firmware. 443 */ 444 if ( puserscanin->ssid_len 445 || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) { 446 *pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN; 447 *pfilteredscan = 1; 448 } 449 } else { 450 pscancfgout->bsstype = adapter->scanmode; 451 numprobes = adapter->scanprobes; 452 } 453 454 /* If the input config or adapter has the number of Probes set, add tlv */ 455 if (numprobes) { 456 pnumprobestlv = (struct mrvlietypes_numprobes *) ptlvpos; 457 pnumprobestlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); 458 pnumprobestlv->header.len = cpu_to_le16(2); 459 pnumprobestlv->numprobes = cpu_to_le16(numprobes); 460 461 ptlvpos += sizeof(*pnumprobestlv); 462 } 463 464 /* 465 * Set the output for the channel TLV to the address in the tlv buffer 466 * past any TLVs that were added in this fuction (SSID, numprobes). 467 * channel TLVs will be added past this for each scan command, preserving 468 * the TLVs that were previously added. 469 */ 470 *ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos; 471 472 if (puserscanin && puserscanin->chanlist[0].channumber) { 473 474 lbs_deb_scan("Scan: Using supplied channel list\n"); 475 476 for (chanidx = 0; 477 chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX 478 && puserscanin->chanlist[chanidx].channumber; chanidx++) { 479 480 channel = puserscanin->chanlist[chanidx].channumber; 481 (pscanchanlist + chanidx)->channumber = channel; 482 483 radiotype = puserscanin->chanlist[chanidx].radiotype; 484 (pscanchanlist + chanidx)->radiotype = radiotype; 485 486 scantype = puserscanin->chanlist[chanidx].scantype; 487 488 if (scantype == cmd_scan_type_passive) { 489 (pscanchanlist + 490 chanidx)->chanscanmode.passivescan = 1; 491 } else { 492 (pscanchanlist + 493 chanidx)->chanscanmode.passivescan = 0; 494 } 495 496 if (puserscanin->chanlist[chanidx].scantime) { 497 scandur = 498 puserscanin->chanlist[chanidx].scantime; 499 } else { 500 if (scantype == cmd_scan_type_passive) { 501 scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME; 502 } else { 503 scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME; 504 } 505 } 506 507 (pscanchanlist + chanidx)->minscantime = 508 cpu_to_le16(scandur); 509 (pscanchanlist + chanidx)->maxscantime = 510 cpu_to_le16(scandur); 511 } 512 513 /* Check if we are only scanning the current channel */ 514 if ((chanidx == 1) && (puserscanin->chanlist[0].channumber 515 == 516 priv->adapter->curbssparams.channel)) { 517 *pscancurrentonly = 1; 518 lbs_deb_scan("Scan: Scanning current channel only"); 519 } 520 521 } else { 522 lbs_deb_scan("Scan: Creating full region channel list\n"); 523 wlan_scan_create_channel_list(priv, pscanchanlist, 524 *pfilteredscan); 525 } 526 527out: 528 return pscancfgout; 529} 530 531/** 532 * @brief Construct and send multiple scan config commands to the firmware 533 * 534 * Previous routines have created a wlan_scan_cmd_config with any requested 535 * TLVs. This function splits the channel TLV into maxchanperscan lists 536 * and sends the portion of the channel TLV along with the other TLVs 537 * to the wlan_cmd routines for execution in the firmware. 538 * 539 * @param priv A pointer to wlan_private structure 540 * @param maxchanperscan Maximum number channels to be included in each 541 * scan command sent to firmware 542 * @param filteredscan Flag indicating whether or not a BSSID or SSID 543 * filter is being used for the firmware command 544 * scan command sent to firmware 545 * @param pscancfgout Scan configuration used for this scan. 546 * @param pchantlvout Pointer in the pscancfgout where the channel TLV 547 * should start. This is past any other TLVs that 548 * must be sent down in each firmware command. 549 * @param pscanchanlist List of channels to scan in maxchanperscan segments 550 * 551 * @return 0 or error return otherwise 552 */ 553static int wlan_scan_channel_list(wlan_private * priv, 554 int maxchanperscan, 555 u8 filteredscan, 556 struct wlan_scan_cmd_config * pscancfgout, 557 struct mrvlietypes_chanlistparamset * pchantlvout, 558 struct chanscanparamset * pscanchanlist, 559 const struct wlan_ioctl_user_scan_cfg * puserscanin, 560 int full_scan) 561{ 562 struct chanscanparamset *ptmpchan; 563 struct chanscanparamset *pstartchan; 564 u8 scanband; 565 int doneearly; 566 int tlvidx; 567 int ret = 0; 568 int scanned = 0; 569 union iwreq_data wrqu; 570 571 lbs_deb_enter(LBS_DEB_ASSOC); 572 573 if (pscancfgout == 0 || pchantlvout == 0 || pscanchanlist == 0) { 574 lbs_deb_scan("Scan: Null detect: %p, %p, %p\n", 575 pscancfgout, pchantlvout, pscanchanlist); 576 return -1; 577 } 578 579 pchantlvout->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 580 581 /* Set the temp channel struct pointer to the start of the desired list */ 582 ptmpchan = pscanchanlist; 583 584 if (priv->adapter->last_scanned_channel && !puserscanin) 585 ptmpchan += priv->adapter->last_scanned_channel; 586 587 /* Loop through the desired channel list, sending a new firmware scan 588 * commands for each maxchanperscan channels (or for 1,6,11 individually 589 * if configured accordingly) 590 */ 591 while (ptmpchan->channumber) { 592 593 tlvidx = 0; 594 pchantlvout->header.len = 0; 595 scanband = ptmpchan->radiotype; 596 pstartchan = ptmpchan; 597 doneearly = 0; 598 599 /* Construct the channel TLV for the scan command. Continue to 600 * insert channel TLVs until: 601 * - the tlvidx hits the maximum configured per scan command 602 * - the next channel to insert is 0 (end of desired channel list) 603 * - doneearly is set (controlling individual scanning of 1,6,11) 604 */ 605 while (tlvidx < maxchanperscan && ptmpchan->channumber 606 && !doneearly && scanned < 2) { 607 608 lbs_deb_scan( 609 "Scan: Chan(%3d), Radio(%d), mode(%d,%d), Dur(%d)\n", 610 ptmpchan->channumber, ptmpchan->radiotype, 611 ptmpchan->chanscanmode.passivescan, 612 ptmpchan->chanscanmode.disablechanfilt, 613 ptmpchan->maxscantime); 614 615 /* Copy the current channel TLV to the command being prepared */ 616 memcpy(pchantlvout->chanscanparam + tlvidx, 617 ptmpchan, sizeof(pchantlvout->chanscanparam)); 618 619 /* Increment the TLV header length by the size appended */ 620 /* Ew, it would be _so_ nice if we could just declare the 621 variable little-endian and let GCC handle it for us */ 622 pchantlvout->header.len = 623 cpu_to_le16(le16_to_cpu(pchantlvout->header.len) + 624 sizeof(pchantlvout->chanscanparam)); 625 626 /* 627 * The tlv buffer length is set to the number of bytes of the 628 * between the channel tlv pointer and the start of the 629 * tlv buffer. This compensates for any TLVs that were appended 630 * before the channel list. 631 */ 632 pscancfgout->tlvbufferlen = ((u8 *) pchantlvout 633 - pscancfgout->tlvbuffer); 634 635 /* Add the size of the channel tlv header and the data length */ 636 pscancfgout->tlvbufferlen += 637 (sizeof(pchantlvout->header) 638 + le16_to_cpu(pchantlvout->header.len)); 639 640 /* Increment the index to the channel tlv we are constructing */ 641 tlvidx++; 642 643 doneearly = 0; 644 645 /* Stop the loop if the *current* channel is in the 1,6,11 set 646 * and we are not filtering on a BSSID or SSID. 647 */ 648 if (!filteredscan && (ptmpchan->channumber == 1 649 || ptmpchan->channumber == 6 650 || ptmpchan->channumber == 11)) { 651 doneearly = 1; 652 } 653 654 /* Increment the tmp pointer to the next channel to be scanned */ 655 ptmpchan++; 656 scanned++; 657 658 /* Stop the loop if the *next* channel is in the 1,6,11 set. 659 * This will cause it to be the only channel scanned on the next 660 * interation 661 */ 662 if (!filteredscan && (ptmpchan->channumber == 1 663 || ptmpchan->channumber == 6 664 || ptmpchan->channumber == 11)) { 665 doneearly = 1; 666 } 667 } 668 669 /* Send the scan command to the firmware with the specified cfg */ 670 ret = libertas_prepare_and_send_command(priv, cmd_802_11_scan, 0, 671 0, 0, pscancfgout); 672 if (scanned >= 2 && !full_scan) { 673 ret = 0; 674 goto done; 675 } 676 scanned = 0; 677 } 678 679done: 680 priv->adapter->last_scanned_channel = ptmpchan->channumber; 681 682 /* Tell userspace the scan table has been updated */ 683 memset(&wrqu, 0, sizeof(union iwreq_data)); 684 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); 685 686 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); 687 return ret; 688} 689 690static void 691clear_selected_scan_list_entries(wlan_adapter * adapter, 692 const struct wlan_ioctl_user_scan_cfg * scan_cfg) 693{ 694 struct bss_descriptor * bss; 695 struct bss_descriptor * safe; 696 u32 clear_ssid_flag = 0, clear_bssid_flag = 0; 697 698 if (!scan_cfg) 699 return; 700 701 if (scan_cfg->clear_ssid && scan_cfg->ssid_len) 702 clear_ssid_flag = 1; 703 704 if (scan_cfg->clear_bssid 705 && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0) 706 && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) { 707 clear_bssid_flag = 1; 708 } 709 710 if (!clear_ssid_flag && !clear_bssid_flag) 711 return; 712 713 mutex_lock(&adapter->lock); 714 list_for_each_entry_safe (bss, safe, &adapter->network_list, list) { 715 u32 clear = 0; 716 717 /* Check for an SSID match */ 718 if ( clear_ssid_flag 719 && (bss->ssid_len == scan_cfg->ssid_len) 720 && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len)) 721 clear = 1; 722 723 /* Check for a BSSID match */ 724 if ( clear_bssid_flag 725 && !compare_ether_addr(bss->bssid, scan_cfg->bssid)) 726 clear = 1; 727 728 if (clear) { 729 list_move_tail (&bss->list, &adapter->network_free_list); 730 clear_bss_descriptor(bss); 731 } 732 } 733 mutex_unlock(&adapter->lock); 734} 735 736 737/** 738 * @brief Internal function used to start a scan based on an input config 739 * 740 * Use the input user scan configuration information when provided in 741 * order to send the appropriate scan commands to firmware to populate or 742 * update the internal driver scan table 743 * 744 * @param priv A pointer to wlan_private structure 745 * @param puserscanin Pointer to the input configuration for the requested 746 * scan. 747 * 748 * @return 0 or < 0 if error 749 */ 750int wlan_scan_networks(wlan_private * priv, 751 const struct wlan_ioctl_user_scan_cfg * puserscanin, 752 int full_scan) 753{ 754 wlan_adapter * adapter = priv->adapter; 755 struct mrvlietypes_chanlistparamset *pchantlvout; 756 struct chanscanparamset * scan_chan_list = NULL; 757 struct wlan_scan_cmd_config * scan_cfg = NULL; 758 u8 filteredscan; 759 u8 scancurrentchanonly; 760 int maxchanperscan; 761 int ret; 762#ifdef CONFIG_LIBERTAS_DEBUG 763 struct bss_descriptor * iter_bss; 764 int i = 0; 765#endif 766 767 lbs_deb_enter(LBS_DEB_ASSOC); 768 769 scan_chan_list = kzalloc(sizeof(struct chanscanparamset) * 770 WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); 771 if (scan_chan_list == NULL) { 772 ret = -ENOMEM; 773 goto out; 774 } 775 776 scan_cfg = wlan_scan_setup_scan_config(priv, 777 puserscanin, 778 &pchantlvout, 779 scan_chan_list, 780 &maxchanperscan, 781 &filteredscan, 782 &scancurrentchanonly); 783 if (scan_cfg == NULL) { 784 ret = -ENOMEM; 785 goto out; 786 } 787 788 clear_selected_scan_list_entries(adapter, puserscanin); 789 790 /* Keep the data path active if we are only scanning our current channel */ 791 if (!scancurrentchanonly) { 792 netif_stop_queue(priv->dev); 793 netif_carrier_off(priv->dev); 794 netif_stop_queue(priv->mesh_dev); 795 netif_carrier_off(priv->mesh_dev); 796 } 797 798 ret = wlan_scan_channel_list(priv, 799 maxchanperscan, 800 filteredscan, 801 scan_cfg, 802 pchantlvout, 803 scan_chan_list, 804 puserscanin, 805 full_scan); 806 807#ifdef CONFIG_LIBERTAS_DEBUG 808 /* Dump the scan table */ 809 mutex_lock(&adapter->lock); 810 list_for_each_entry (iter_bss, &adapter->network_list, list) { 811 lbs_deb_scan("Scan:(%02d) " MAC_FMT ", RSSI[%03d], SSID[%s]\n", 812 i++, MAC_ARG(iter_bss->bssid), (s32) iter_bss->rssi, 813 escape_essid(iter_bss->ssid, iter_bss->ssid_len)); 814 } 815 mutex_unlock(&adapter->lock); 816#endif 817 818 if (priv->adapter->connect_status == libertas_connected) { 819 netif_carrier_on(priv->dev); 820 netif_wake_queue(priv->dev); 821 netif_carrier_on(priv->mesh_dev); 822 netif_wake_queue(priv->mesh_dev); 823 } 824 825out: 826 if (scan_cfg) 827 kfree(scan_cfg); 828 829 if (scan_chan_list) 830 kfree(scan_chan_list); 831 832 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); 833 return ret; 834} 835 836/** 837 * @brief Inspect the scan response buffer for pointers to expected TLVs 838 * 839 * TLVs can be included at the end of the scan response BSS information. 840 * Parse the data in the buffer for pointers to TLVs that can potentially 841 * be passed back in the response 842 * 843 * @param ptlv Pointer to the start of the TLV buffer to parse 844 * @param tlvbufsize size of the TLV buffer 845 * @param ptsftlv Output parameter: Pointer to the TSF TLV if found 846 * 847 * @return void 848 */ 849static 850void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv, 851 int tlvbufsize, 852 struct mrvlietypes_tsftimestamp ** ptsftlv) 853{ 854 struct mrvlietypes_data *pcurrenttlv; 855 int tlvbufleft; 856 u16 tlvtype; 857 u16 tlvlen; 858 859 pcurrenttlv = ptlv; 860 tlvbufleft = tlvbufsize; 861 *ptsftlv = NULL; 862 863 lbs_deb_scan("SCAN_RESP: tlvbufsize = %d\n", tlvbufsize); 864 lbs_dbg_hex("SCAN_RESP: TLV Buf", (u8 *) ptlv, tlvbufsize); 865 866 while (tlvbufleft >= sizeof(struct mrvlietypesheader)) { 867 tlvtype = le16_to_cpu(pcurrenttlv->header.type); 868 tlvlen = le16_to_cpu(pcurrenttlv->header.len); 869 870 switch (tlvtype) { 871 case TLV_TYPE_TSFTIMESTAMP: 872 *ptsftlv = (struct mrvlietypes_tsftimestamp *) pcurrenttlv; 873 break; 874 875 default: 876 lbs_deb_scan("SCAN_RESP: Unhandled TLV = %d\n", 877 tlvtype); 878 /* Give up, this seems corrupted */ 879 return; 880 } /* switch */ 881 882 tlvbufleft -= (sizeof(ptlv->header) + tlvlen); 883 pcurrenttlv = 884 (struct mrvlietypes_data *) (pcurrenttlv->Data + tlvlen); 885 } /* while */ 886} 887 888/** 889 * @brief Interpret a BSS scan response returned from the firmware 890 * 891 * Parse the various fixed fields and IEs passed back for a a BSS probe 892 * response or beacon from the scan command. Record information as needed 893 * in the scan table struct bss_descriptor for that entry. 894 * 895 * @param bss Output parameter: Pointer to the BSS Entry 896 * 897 * @return 0 or -1 898 */ 899static int libertas_process_bss(struct bss_descriptor * bss, 900 u8 ** pbeaconinfo, int *bytesleft) 901{ 902 enum ieeetypes_elementid elemID; 903 struct ieeetypes_fhparamset *pFH; 904 struct ieeetypes_dsparamset *pDS; 905 struct ieeetypes_cfparamset *pCF; 906 struct ieeetypes_ibssparamset *pibss; 907 struct ieeetypes_capinfo *pcap; 908 struct WLAN_802_11_FIXED_IEs fixedie; 909 u8 *pcurrentptr; 910 u8 *pRate; 911 u8 elemlen; 912 u8 bytestocopy; 913 u8 ratesize; 914 u16 beaconsize; 915 u8 founddatarateie; 916 int bytesleftforcurrentbeacon; 917 int ret; 918 919 struct IE_WPA *pIe; 920 const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 }; 921 922 struct ieeetypes_countryinfoset *pcountryinfo; 923 924 lbs_deb_enter(LBS_DEB_ASSOC); 925 926 founddatarateie = 0; 927 ratesize = 0; 928 beaconsize = 0; 929 930 if (*bytesleft >= sizeof(beaconsize)) { 931 /* Extract & convert beacon size from the command buffer */ 932 beaconsize = le16_to_cpup((void *)*pbeaconinfo); 933 *bytesleft -= sizeof(beaconsize); 934 *pbeaconinfo += sizeof(beaconsize); 935 } 936 937 if (beaconsize == 0 || beaconsize > *bytesleft) { 938 939 *pbeaconinfo += *bytesleft; 940 *bytesleft = 0; 941 942 return -1; 943 } 944 945 /* Initialize the current working beacon pointer for this BSS iteration */ 946 pcurrentptr = *pbeaconinfo; 947 948 /* Advance the return beacon pointer past the current beacon */ 949 *pbeaconinfo += beaconsize; 950 *bytesleft -= beaconsize; 951 952 bytesleftforcurrentbeacon = beaconsize; 953 954 memcpy(bss->bssid, pcurrentptr, ETH_ALEN); 955 lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid)); 956 957 pcurrentptr += ETH_ALEN; 958 bytesleftforcurrentbeacon -= ETH_ALEN; 959 960 if (bytesleftforcurrentbeacon < 12) { 961 lbs_deb_scan("process_bss: Not enough bytes left\n"); 962 return -1; 963 } 964 965 /* 966 * next 4 fields are RSSI, time stamp, beacon interval, 967 * and capability information 968 */ 969 970 /* RSSI is 1 byte long */ 971 bss->rssi = *pcurrentptr; 972 lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr); 973 pcurrentptr += 1; 974 bytesleftforcurrentbeacon -= 1; 975 976 /* time stamp is 8 bytes long */ 977 fixedie.timestamp = bss->timestamp = le64_to_cpup((void *)pcurrentptr); 978 pcurrentptr += 8; 979 bytesleftforcurrentbeacon -= 8; 980 981 /* beacon interval is 2 bytes long */ 982 fixedie.beaconinterval = bss->beaconperiod = le16_to_cpup((void *)pcurrentptr); 983 pcurrentptr += 2; 984 bytesleftforcurrentbeacon -= 2; 985 986 /* capability information is 2 bytes long */ 987 memcpy(&fixedie.capabilities, pcurrentptr, 2); 988 lbs_deb_scan("process_bss: fixedie.capabilities=0x%X\n", 989 fixedie.capabilities); 990 pcap = (struct ieeetypes_capinfo *) & fixedie.capabilities; 991 memcpy(&bss->cap, pcap, sizeof(struct ieeetypes_capinfo)); 992 pcurrentptr += 2; 993 bytesleftforcurrentbeacon -= 2; 994 995 /* rest of the current buffer are IE's */ 996 lbs_deb_scan("process_bss: IE length for this AP = %d\n", 997 bytesleftforcurrentbeacon); 998 999 lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr, 1000 bytesleftforcurrentbeacon); 1001 1002 if (pcap->privacy) { 1003 lbs_deb_scan("process_bss: AP WEP enabled\n"); 1004 bss->privacy = wlan802_11privfilter8021xWEP; 1005 } else { 1006 bss->privacy = wlan802_11privfilteracceptall; 1007 } 1008 1009 if (pcap->ibss == 1) { 1010 bss->mode = IW_MODE_ADHOC; 1011 } else { 1012 bss->mode = IW_MODE_INFRA; 1013 } 1014 1015 /* process variable IE */ 1016 while (bytesleftforcurrentbeacon >= 2) { 1017 elemID = (enum ieeetypes_elementid) (*((u8 *) pcurrentptr)); 1018 elemlen = *((u8 *) pcurrentptr + 1); 1019 1020 if (bytesleftforcurrentbeacon < elemlen) { 1021 lbs_deb_scan("process_bss: error in processing IE, " 1022 "bytes left < IE length\n"); 1023 bytesleftforcurrentbeacon = 0; 1024 continue; 1025 } 1026 1027 switch (elemID) { 1028 case SSID: 1029 bss->ssid_len = elemlen; 1030 memcpy(bss->ssid, (pcurrentptr + 2), elemlen); 1031 lbs_deb_scan("ssid '%s', ssid length %u\n", 1032 escape_essid(bss->ssid, bss->ssid_len), 1033 bss->ssid_len); 1034 break; 1035 1036 case SUPPORTED_RATES: 1037 memcpy(bss->datarates, (pcurrentptr + 2), elemlen); 1038 memmove(bss->libertas_supported_rates, (pcurrentptr + 2), 1039 elemlen); 1040 ratesize = elemlen; 1041 founddatarateie = 1; 1042 break; 1043 1044 case EXTRA_IE: 1045 lbs_deb_scan("process_bss: EXTRA_IE Found!\n"); 1046 break; 1047 1048 case FH_PARAM_SET: 1049 pFH = (struct ieeetypes_fhparamset *) pcurrentptr; 1050 memmove(&bss->phyparamset.fhparamset, pFH, 1051 sizeof(struct ieeetypes_fhparamset)); 1052 break; 1053 1054 case DS_PARAM_SET: 1055 pDS = (struct ieeetypes_dsparamset *) pcurrentptr; 1056 bss->channel = pDS->currentchan; 1057 memcpy(&bss->phyparamset.dsparamset, pDS, 1058 sizeof(struct ieeetypes_dsparamset)); 1059 break; 1060 1061 case CF_PARAM_SET: 1062 pCF = (struct ieeetypes_cfparamset *) pcurrentptr; 1063 memcpy(&bss->ssparamset.cfparamset, pCF, 1064 sizeof(struct ieeetypes_cfparamset)); 1065 break; 1066 1067 case IBSS_PARAM_SET: 1068 pibss = (struct ieeetypes_ibssparamset *) pcurrentptr; 1069 bss->atimwindow = le32_to_cpu(pibss->atimwindow); 1070 memmove(&bss->ssparamset.ibssparamset, pibss, 1071 sizeof(struct ieeetypes_ibssparamset)); 1072 break; 1073 1074 /* Handle Country Info IE */ 1075 case COUNTRY_INFO: 1076 pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr; 1077 if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) 1078 || pcountryinfo->len > 254) { 1079 lbs_deb_scan("process_bss: 11D- Err " 1080 "CountryInfo len =%d min=%zd max=254\n", 1081 pcountryinfo->len, 1082 sizeof(pcountryinfo->countrycode)); 1083 ret = -1; 1084 goto done; 1085 } 1086 1087 memcpy(&bss->countryinfo, 1088 pcountryinfo, pcountryinfo->len + 2); 1089 lbs_dbg_hex("process_bss: 11D- CountryInfo:", 1090 (u8 *) pcountryinfo, 1091 (u32) (pcountryinfo->len + 2)); 1092 break; 1093 1094 case EXTENDED_SUPPORTED_RATES: 1095 /* 1096 * only process extended supported rate 1097 * if data rate is already found. 1098 * data rate IE should come before 1099 * extended supported rate IE 1100 */ 1101 if (founddatarateie) { 1102 if ((elemlen + ratesize) > WLAN_SUPPORTED_RATES) { 1103 bytestocopy = 1104 (WLAN_SUPPORTED_RATES - ratesize); 1105 } else { 1106 bytestocopy = elemlen; 1107 } 1108 1109 pRate = (u8 *) bss->datarates; 1110 pRate += ratesize; 1111 memmove(pRate, (pcurrentptr + 2), bytestocopy); 1112 pRate = (u8 *) bss->libertas_supported_rates; 1113 pRate += ratesize; 1114 memmove(pRate, (pcurrentptr + 2), bytestocopy); 1115 } 1116 break; 1117 1118 case VENDOR_SPECIFIC_221: 1119#define IE_ID_LEN_FIELDS_BYTES 2 1120 pIe = (struct IE_WPA *)pcurrentptr; 1121 1122 if (memcmp(pIe->oui, oui01, sizeof(oui01))) 1123 break; 1124 1125 bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, 1126 MAX_WPA_IE_LEN); 1127 memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len); 1128 lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen); 1129 break; 1130 case WPA2_IE: 1131 pIe = (struct IE_WPA *)pcurrentptr; 1132 bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, 1133 MAX_WPA_IE_LEN); 1134 memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len); 1135 lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen); 1136 break; 1137 case TIM: 1138 break; 1139 1140 case CHALLENGE_TEXT: 1141 break; 1142 } 1143 1144 pcurrentptr += elemlen + 2; 1145 1146 /* need to account for IE ID and IE len */ 1147 bytesleftforcurrentbeacon -= (elemlen + 2); 1148 1149 } /* while (bytesleftforcurrentbeacon > 2) */ 1150 1151 /* Timestamp */ 1152 bss->last_scanned = jiffies; 1153 1154 ret = 0; 1155 1156done: 1157 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); 1158 return ret; 1159} 1160 1161/** 1162 * @brief Compare two SSIDs 1163 * 1164 * @param ssid1 A pointer to ssid to compare 1165 * @param ssid2 A pointer to ssid to compare 1166 * 1167 * @return 0--ssid is same, otherwise is different 1168 */ 1169int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) 1170{ 1171 if (ssid1_len != ssid2_len) 1172 return -1; 1173 1174 return memcmp(ssid1, ssid2, ssid1_len); 1175} 1176 1177/** 1178 * @brief This function finds a specific compatible BSSID in the scan list 1179 * 1180 * @param adapter A pointer to wlan_adapter 1181 * @param bssid BSSID to find in the scan list 1182 * @param mode Network mode: Infrastructure or IBSS 1183 * 1184 * @return index in BSSID list, or error return code (< 0) 1185 */ 1186struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter, 1187 u8 * bssid, u8 mode) 1188{ 1189 struct bss_descriptor * iter_bss; 1190 struct bss_descriptor * found_bss = NULL; 1191 1192 if (!bssid) 1193 return NULL; 1194 1195 lbs_dbg_hex("libertas_find_BSSID_in_list: looking for ", 1196 bssid, ETH_ALEN); 1197 1198 /* Look through the scan table for a compatible match. The loop will 1199 * continue past a matched bssid that is not compatible in case there 1200 * is an AP with multiple SSIDs assigned to the same BSSID 1201 */ 1202 mutex_lock(&adapter->lock); 1203 list_for_each_entry (iter_bss, &adapter->network_list, list) { 1204 if (compare_ether_addr(iter_bss->bssid, bssid)) 1205 continue; /* bssid doesn't match */ 1206 switch (mode) { 1207 case IW_MODE_INFRA: 1208 case IW_MODE_ADHOC: 1209 if (!is_network_compatible(adapter, iter_bss, mode)) 1210 break; 1211 found_bss = iter_bss; 1212 break; 1213 default: 1214 found_bss = iter_bss; 1215 break; 1216 } 1217 } 1218 mutex_unlock(&adapter->lock); 1219 1220 return found_bss; 1221} 1222 1223/** 1224 * @brief This function finds ssid in ssid list. 1225 * 1226 * @param adapter A pointer to wlan_adapter 1227 * @param ssid SSID to find in the list 1228 * @param bssid BSSID to qualify the SSID selection (if provided) 1229 * @param mode Network mode: Infrastructure or IBSS 1230 * 1231 * @return index in BSSID list 1232 */ 1233struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter, 1234 u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, 1235 int channel) 1236{ 1237 u8 bestrssi = 0; 1238 struct bss_descriptor * iter_bss = NULL; 1239 struct bss_descriptor * found_bss = NULL; 1240 struct bss_descriptor * tmp_oldest = NULL; 1241 1242 mutex_lock(&adapter->lock); 1243 1244 list_for_each_entry (iter_bss, &adapter->network_list, list) { 1245 if ( !tmp_oldest 1246 || (iter_bss->last_scanned < tmp_oldest->last_scanned)) 1247 tmp_oldest = iter_bss; 1248 1249 if (libertas_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, 1250 ssid, ssid_len) != 0) 1251 continue; /* ssid doesn't match */ 1252 if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) 1253 continue; /* bssid doesn't match */ 1254 if ((channel > 0) && (iter_bss->channel != channel)) 1255 continue; /* channel doesn't match */ 1256 1257 switch (mode) { 1258 case IW_MODE_INFRA: 1259 case IW_MODE_ADHOC: 1260 if (!is_network_compatible(adapter, iter_bss, mode)) 1261 break; 1262 1263 if (bssid) { 1264 /* Found requested BSSID */ 1265 found_bss = iter_bss; 1266 goto out; 1267 } 1268 1269 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { 1270 bestrssi = SCAN_RSSI(iter_bss->rssi); 1271 found_bss = iter_bss; 1272 } 1273 break; 1274 case IW_MODE_AUTO: 1275 default: 1276 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { 1277 bestrssi = SCAN_RSSI(iter_bss->rssi); 1278 found_bss = iter_bss; 1279 } 1280 break; 1281 } 1282 } 1283 1284out: 1285 mutex_unlock(&adapter->lock); 1286 return found_bss; 1287} 1288 1289/** 1290 * @brief This function finds the best SSID in the Scan List 1291 * 1292 * Search the scan table for the best SSID that also matches the current 1293 * adapter network preference (infrastructure or adhoc) 1294 * 1295 * @param adapter A pointer to wlan_adapter 1296 * 1297 * @return index in BSSID list 1298 */ 1299struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter, 1300 u8 mode) 1301{ 1302 u8 bestrssi = 0; 1303 struct bss_descriptor * iter_bss; 1304 struct bss_descriptor * best_bss = NULL; 1305 1306 mutex_lock(&adapter->lock); 1307 1308 list_for_each_entry (iter_bss, &adapter->network_list, list) { 1309 switch (mode) { 1310 case IW_MODE_INFRA: 1311 case IW_MODE_ADHOC: 1312 if (!is_network_compatible(adapter, iter_bss, mode)) 1313 break; 1314 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) 1315 break; 1316 bestrssi = SCAN_RSSI(iter_bss->rssi); 1317 best_bss = iter_bss; 1318 break; 1319 case IW_MODE_AUTO: 1320 default: 1321 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) 1322 break; 1323 bestrssi = SCAN_RSSI(iter_bss->rssi); 1324 best_bss = iter_bss; 1325 break; 1326 } 1327 } 1328 1329 mutex_unlock(&adapter->lock); 1330 return best_bss; 1331} 1332 1333/** 1334 * @brief Find the AP with specific ssid in the scan list 1335 * 1336 * @param priv A pointer to wlan_private structure 1337 * @param pSSID A pointer to AP's ssid 1338 * 1339 * @return 0--success, otherwise--fail 1340 */ 1341int libertas_find_best_network_ssid(wlan_private * priv, 1342 u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode) 1343{ 1344 wlan_adapter *adapter = priv->adapter; 1345 int ret = -1; 1346 struct bss_descriptor * found; 1347 1348 lbs_deb_enter(LBS_DEB_ASSOC); 1349 1350 wlan_scan_networks(priv, NULL, 1); 1351 if (adapter->surpriseremoved) 1352 return -1; 1353 1354 wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); 1355 1356 found = libertas_find_best_ssid_in_list(adapter, preferred_mode); 1357 if (found && (found->ssid_len > 0)) { 1358 memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); 1359 *out_ssid_len = found->ssid_len; 1360 *out_mode = found->mode; 1361 ret = 0; 1362 } 1363 1364 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); 1365 return ret; 1366} 1367 1368/** 1369 * @brief Scan Network 1370 * 1371 * @param dev A pointer to net_device structure 1372 * @param info A pointer to iw_request_info structure 1373 * @param vwrq A pointer to iw_param structure 1374 * @param extra A pointer to extra data buf 1375 * 1376 * @return 0 --success, otherwise fail 1377 */ 1378int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, 1379 struct iw_param *vwrq, char *extra) 1380{ 1381 wlan_private *priv = dev->priv; 1382 wlan_adapter *adapter = priv->adapter; 1383 1384 lbs_deb_enter(LBS_DEB_SCAN); 1385 1386 wlan_scan_networks(priv, NULL, 0); 1387 1388 if (adapter->surpriseremoved) 1389 return -1; 1390 1391 lbs_deb_leave(LBS_DEB_SCAN); 1392 return 0; 1393} 1394 1395/** 1396 * @brief Send a scan command for all available channels filtered on a spec 1397 * 1398 * @param priv A pointer to wlan_private structure 1399 * @param prequestedssid A pointer to AP's ssid 1400 * @param keeppreviousscan Flag used to save/clear scan table before scan 1401 * 1402 * @return 0-success, otherwise fail 1403 */ 1404int libertas_send_specific_ssid_scan(wlan_private * priv, 1405 u8 *ssid, u8 ssid_len, u8 clear_ssid) 1406{ 1407 wlan_adapter *adapter = priv->adapter; 1408 struct wlan_ioctl_user_scan_cfg scancfg; 1409 int ret = 0; 1410 1411 lbs_deb_enter(LBS_DEB_ASSOC); 1412 1413 if (!ssid_len) 1414 goto out; 1415 1416 memset(&scancfg, 0x00, sizeof(scancfg)); 1417 memcpy(scancfg.ssid, ssid, ssid_len); 1418 scancfg.ssid_len = ssid_len; 1419 scancfg.clear_ssid = clear_ssid; 1420 1421 wlan_scan_networks(priv, &scancfg, 1); 1422 if (adapter->surpriseremoved) 1423 return -1; 1424 wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); 1425 1426out: 1427 lbs_deb_leave(LBS_DEB_ASSOC); 1428 return ret; 1429} 1430 1431/** 1432 * @brief scan an AP with specific BSSID 1433 * 1434 * @param priv A pointer to wlan_private structure 1435 * @param bssid A pointer to AP's bssid 1436 * @param keeppreviousscan Flag used to save/clear scan table before scan 1437 * 1438 * @return 0-success, otherwise fail 1439 */ 1440int libertas_send_specific_bssid_scan(wlan_private * priv, u8 * bssid, u8 clear_bssid) 1441{ 1442 struct wlan_ioctl_user_scan_cfg scancfg; 1443 1444 lbs_deb_enter(LBS_DEB_ASSOC); 1445 1446 if (bssid == NULL) 1447 goto out; 1448 1449 memset(&scancfg, 0x00, sizeof(scancfg)); 1450 memcpy(scancfg.bssid, bssid, ETH_ALEN); 1451 scancfg.clear_bssid = clear_bssid; 1452 1453 wlan_scan_networks(priv, &scancfg, 1); 1454 if (priv->adapter->surpriseremoved) 1455 return -1; 1456 wait_event_interruptible(priv->adapter->cmd_pending, 1457 !priv->adapter->nr_cmd_pending); 1458 1459out: 1460 lbs_deb_leave(LBS_DEB_ASSOC); 1461 return 0; 1462} 1463 1464static inline char *libertas_translate_scan(wlan_private *priv, 1465 char *start, char *stop, 1466 struct bss_descriptor *bss) 1467{ 1468 wlan_adapter *adapter = priv->adapter; 1469 struct chan_freq_power *cfp; 1470 char *current_val; /* For rates */ 1471 struct iw_event iwe; /* Temporary buffer */ 1472 int j; 1473#define PERFECT_RSSI ((u8)50) 1474#define WORST_RSSI ((u8)0) 1475#define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) 1476 u8 rssi; 1477 1478 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, bss->channel); 1479 if (!cfp) { 1480 lbs_deb_scan("Invalid channel number %d\n", bss->channel); 1481 return NULL; 1482 } 1483 1484 /* First entry *MUST* be the AP BSSID */ 1485 iwe.cmd = SIOCGIWAP; 1486 iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 1487 memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); 1488 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); 1489 1490 /* SSID */ 1491 iwe.cmd = SIOCGIWESSID; 1492 iwe.u.data.flags = 1; 1493 iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE); 1494 start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); 1495 1496 /* Mode */ 1497 iwe.cmd = SIOCGIWMODE; 1498 iwe.u.mode = bss->mode; 1499 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); 1500 1501 /* Frequency */ 1502 iwe.cmd = SIOCGIWFREQ; 1503 iwe.u.freq.m = (long)cfp->freq * 100000; 1504 iwe.u.freq.e = 1; 1505 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); 1506 1507 /* Add quality statistics */ 1508 iwe.cmd = IWEVQUAL; 1509 iwe.u.qual.updated = IW_QUAL_ALL_UPDATED; 1510 iwe.u.qual.level = SCAN_RSSI(bss->rssi); 1511 1512 rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; 1513 iwe.u.qual.qual = 1514 (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * 1515 (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / 1516 (RSSI_DIFF * RSSI_DIFF); 1517 if (iwe.u.qual.qual > 100) 1518 iwe.u.qual.qual = 100; 1519 1520 if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { 1521 iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; 1522 } else { 1523 iwe.u.qual.noise = 1524 CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); 1525 } 1526 1527 /* Locally created ad-hoc BSSs won't have beacons if this is the 1528 * only station in the adhoc network; so get signal strength 1529 * from receive statistics. 1530 */ 1531 if ((adapter->mode == IW_MODE_ADHOC) 1532 && adapter->adhoccreate 1533 && !libertas_ssid_cmp(adapter->curbssparams.ssid, 1534 adapter->curbssparams.ssid_len, 1535 bss->ssid, bss->ssid_len)) { 1536 int snr, nf; 1537 snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; 1538 nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; 1539 iwe.u.qual.level = CAL_RSSI(snr, nf); 1540 } 1541 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); 1542 1543 /* Add encryption capability */ 1544 iwe.cmd = SIOCGIWENCODE; 1545 if (bss->privacy) { 1546 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 1547 } else { 1548 iwe.u.data.flags = IW_ENCODE_DISABLED; 1549 } 1550 iwe.u.data.length = 0; 1551 start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); 1552 1553 current_val = start + IW_EV_LCP_LEN; 1554 1555 iwe.cmd = SIOCGIWRATE; 1556 iwe.u.bitrate.fixed = 0; 1557 iwe.u.bitrate.disabled = 0; 1558 iwe.u.bitrate.value = 0; 1559 1560 for (j = 0; j < sizeof(bss->libertas_supported_rates); j++) { 1561 u8 rate = bss->libertas_supported_rates[j]; 1562 if (rate == 0) 1563 break; /* no more rates */ 1564 /* Bit rate given in 500 kb/s units (+ 0x80) */ 1565 iwe.u.bitrate.value = (rate & 0x7f) * 500000; 1566 current_val = iwe_stream_add_value(start, current_val, 1567 stop, &iwe, IW_EV_PARAM_LEN); 1568 } 1569 if ((bss->mode == IW_MODE_ADHOC) 1570 && !libertas_ssid_cmp(adapter->curbssparams.ssid, 1571 adapter->curbssparams.ssid_len, 1572 bss->ssid, bss->ssid_len) 1573 && adapter->adhoccreate) { 1574 iwe.u.bitrate.value = 22 * 500000; 1575 current_val = iwe_stream_add_value(start, current_val, 1576 stop, &iwe, IW_EV_PARAM_LEN); 1577 } 1578 /* Check if we added any event */ 1579 if((current_val - start) > IW_EV_LCP_LEN) 1580 start = current_val; 1581 1582 memset(&iwe, 0, sizeof(iwe)); 1583 if (bss->wpa_ie_len) { 1584 char buf[MAX_WPA_IE_LEN]; 1585 memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); 1586 iwe.cmd = IWEVGENIE; 1587 iwe.u.data.length = bss->wpa_ie_len; 1588 start = iwe_stream_add_point(start, stop, &iwe, buf); 1589 } 1590 1591 memset(&iwe, 0, sizeof(iwe)); 1592 if (bss->rsn_ie_len) { 1593 char buf[MAX_WPA_IE_LEN]; 1594 memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); 1595 iwe.cmd = IWEVGENIE; 1596 iwe.u.data.length = bss->rsn_ie_len; 1597 start = iwe_stream_add_point(start, stop, &iwe, buf); 1598 } 1599 1600 return start; 1601} 1602 1603/** 1604 * @brief Retrieve the scan table entries via wireless tools IOCTL call 1605 * 1606 * @param dev A pointer to net_device structure 1607 * @param info A pointer to iw_request_info structure 1608 * @param dwrq A pointer to iw_point structure 1609 * @param extra A pointer to extra data buf 1610 * 1611 * @return 0 --success, otherwise fail 1612 */ 1613int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, 1614 struct iw_point *dwrq, char *extra) 1615{ 1616#define SCAN_ITEM_SIZE 128 1617 wlan_private *priv = dev->priv; 1618 wlan_adapter *adapter = priv->adapter; 1619 int err = 0; 1620 char *ev = extra; 1621 char *stop = ev + dwrq->length; 1622 struct bss_descriptor * iter_bss; 1623 struct bss_descriptor * safe; 1624 1625 lbs_deb_enter(LBS_DEB_ASSOC); 1626 1627 /* If we've got an uncompleted scan, schedule the next part */ 1628 if (!adapter->nr_cmd_pending && adapter->last_scanned_channel) 1629 wlan_scan_networks(priv, NULL, 0); 1630 1631 /* Update RSSI if current BSS is a locally created ad-hoc BSS */ 1632 if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) { 1633 libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0, 1634 cmd_option_waitforrsp, 0, NULL); 1635 } 1636 1637 mutex_lock(&adapter->lock); 1638 list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) { 1639 char * next_ev; 1640 unsigned long stale_time; 1641 1642 if (stop - ev < SCAN_ITEM_SIZE) { 1643 err = -E2BIG; 1644 break; 1645 } 1646 1647 /* Prune old an old scan result */ 1648 stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; 1649 if (time_after(jiffies, stale_time)) { 1650 list_move_tail (&iter_bss->list, 1651 &adapter->network_free_list); 1652 clear_bss_descriptor(iter_bss); 1653 continue; 1654 } 1655 1656 /* Translate to WE format this entry */ 1657 next_ev = libertas_translate_scan(priv, ev, stop, iter_bss); 1658 if (next_ev == NULL) 1659 continue; 1660 ev = next_ev; 1661 } 1662 mutex_unlock(&adapter->lock); 1663 1664 dwrq->length = (ev - extra); 1665 dwrq->flags = 0; 1666 1667 lbs_deb_leave(LBS_DEB_ASSOC); 1668 return err; 1669} 1670 1671/** 1672 * @brief Prepare a scan command to be sent to the firmware 1673 * 1674 * Use the wlan_scan_cmd_config sent to the command processing module in 1675 * the libertas_prepare_and_send_command to configure a cmd_ds_802_11_scan command 1676 * struct to send to firmware. 1677 * 1678 * The fixed fields specifying the BSS type and BSSID filters as well as a 1679 * variable number/length of TLVs are sent in the command to firmware. 1680 * 1681 * @param priv A pointer to wlan_private structure 1682 * @param cmd A pointer to cmd_ds_command structure to be sent to 1683 * firmware with the cmd_DS_801_11_SCAN structure 1684 * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used 1685 * to set the fields/TLVs for the command sent to firmware 1686 * 1687 * @return 0 or -1 1688 * 1689 * @sa wlan_scan_create_channel_list 1690 */ 1691int libertas_cmd_80211_scan(wlan_private * priv, 1692 struct cmd_ds_command *cmd, void *pdata_buf) 1693{ 1694 struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; 1695 struct wlan_scan_cmd_config *pscancfg; 1696 1697 lbs_deb_enter(LBS_DEB_ASSOC); 1698 1699 pscancfg = pdata_buf; 1700 1701 /* Set fixed field variables in scan command */ 1702 pscan->bsstype = pscancfg->bsstype; 1703 memcpy(pscan->BSSID, pscancfg->bssid, sizeof(pscan->BSSID)); 1704 memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); 1705 1706 cmd->command = cpu_to_le16(cmd_802_11_scan); 1707 1708 /* size is equal to the sizeof(fixed portions) + the TLV len + header */ 1709 cmd->size = cpu_to_le16(sizeof(pscan->bsstype) 1710 + sizeof(pscan->BSSID) 1711 + pscancfg->tlvbufferlen + S_DS_GEN); 1712 1713 lbs_deb_scan("SCAN_CMD: command=%x, size=%x, seqnum=%x\n", 1714 le16_to_cpu(cmd->command), le16_to_cpu(cmd->size), 1715 le16_to_cpu(cmd->seqnum)); 1716 1717 lbs_deb_leave(LBS_DEB_ASSOC); 1718 return 0; 1719} 1720 1721static inline int is_same_network(struct bss_descriptor *src, 1722 struct bss_descriptor *dst) 1723{ 1724 /* A network is only a duplicate if the channel, BSSID, and ESSID 1725 * all match. We treat all <hidden> with the same BSSID and channel 1726 * as one network */ 1727 return ((src->ssid_len == dst->ssid_len) && 1728 (src->channel == dst->channel) && 1729 !compare_ether_addr(src->bssid, dst->bssid) && 1730 !memcmp(src->ssid, dst->ssid, src->ssid_len)); 1731} 1732 1733/** 1734 * @brief This function handles the command response of scan 1735 * 1736 * The response buffer for the scan command has the following 1737 * memory layout: 1738 * 1739 * .-----------------------------------------------------------. 1740 * | header (4 * sizeof(u16)): Standard command response hdr | 1741 * .-----------------------------------------------------------. 1742 * | bufsize (u16) : sizeof the BSS Description data | 1743 * .-----------------------------------------------------------. 1744 * | NumOfSet (u8) : Number of BSS Descs returned | 1745 * .-----------------------------------------------------------. 1746 * | BSSDescription data (variable, size given in bufsize) | 1747 * .-----------------------------------------------------------. 1748 * | TLV data (variable, size calculated using header->size, | 1749 * | bufsize and sizeof the fixed fields above) | 1750 * .-----------------------------------------------------------. 1751 * 1752 * @param priv A pointer to wlan_private structure 1753 * @param resp A pointer to cmd_ds_command 1754 * 1755 * @return 0 or -1 1756 */ 1757int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp) 1758{ 1759 wlan_adapter *adapter = priv->adapter; 1760 struct cmd_ds_802_11_scan_rsp *pscan; 1761 struct mrvlietypes_data *ptlv; 1762 struct mrvlietypes_tsftimestamp *ptsftlv; 1763 struct bss_descriptor * iter_bss; 1764 struct bss_descriptor * safe; 1765 u8 *pbssinfo; 1766 u16 scanrespsize; 1767 int bytesleft; 1768 int idx; 1769 int tlvbufsize; 1770 int ret; 1771 1772 lbs_deb_enter(LBS_DEB_ASSOC); 1773 1774 /* Prune old entries from scan table */ 1775 list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) { 1776 unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; 1777 if (time_before(jiffies, stale_time)) 1778 continue; 1779 list_move_tail (&iter_bss->list, &adapter->network_free_list); 1780 clear_bss_descriptor(iter_bss); 1781 } 1782 1783 pscan = &resp->params.scanresp; 1784 1785 if (pscan->nr_sets > MAX_NETWORK_COUNT) { 1786 lbs_deb_scan( 1787 "SCAN_RESP: too many scan results (%d, max %d)!!\n", 1788 pscan->nr_sets, MAX_NETWORK_COUNT); 1789 ret = -1; 1790 goto done; 1791 } 1792 1793 bytesleft = le16_to_cpu(pscan->bssdescriptsize); 1794 lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); 1795 1796 scanrespsize = le16_to_cpu(resp->size); 1797 lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n", 1798 pscan->nr_sets); 1799 1800 pbssinfo = pscan->bssdesc_and_tlvbuffer; 1801 1802 /* The size of the TLV buffer is equal to the entire command response 1803 * size (scanrespsize) minus the fixed fields (sizeof()'s), the 1804 * BSS Descriptions (bssdescriptsize as bytesLef) and the command 1805 * response header (S_DS_GEN) 1806 */ 1807 tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize) 1808 + sizeof(pscan->nr_sets) 1809 + S_DS_GEN); 1810 1811 ptlv = (struct mrvlietypes_data *) (pscan->bssdesc_and_tlvbuffer + bytesleft); 1812 1813 /* Search the TLV buffer space in the scan response for any valid TLVs */ 1814 wlan_ret_802_11_scan_get_tlv_ptrs(ptlv, tlvbufsize, &ptsftlv); 1815 1816 /* 1817 * Process each scan response returned (pscan->nr_sets). Save 1818 * the information in the newbssentry and then insert into the 1819 * driver scan table either as an update to an existing entry 1820 * or as an addition at the end of the table 1821 */ 1822 for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) { 1823 struct bss_descriptor new; 1824 struct bss_descriptor * found = NULL; 1825 struct bss_descriptor * oldest = NULL; 1826 1827 /* Process the data fields and IEs returned for this BSS */ 1828 memset(&new, 0, sizeof (struct bss_descriptor)); 1829 if (libertas_process_bss(&new, &pbssinfo, &bytesleft) != 0) { 1830 /* error parsing the scan response, skipped */ 1831 lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); 1832 continue; 1833 } 1834 1835 /* Try to find this bss in the scan table */ 1836 list_for_each_entry (iter_bss, &adapter->network_list, list) { 1837 if (is_same_network(iter_bss, &new)) { 1838 found = iter_bss; 1839 break; 1840 } 1841 1842 if ((oldest == NULL) || 1843 (iter_bss->last_scanned < oldest->last_scanned)) 1844 oldest = iter_bss; 1845 } 1846 1847 if (found) { 1848 /* found, clear it */ 1849 clear_bss_descriptor(found); 1850 } else if (!list_empty(&adapter->network_free_list)) { 1851 /* Pull one from the free list */ 1852 found = list_entry(adapter->network_free_list.next, 1853 struct bss_descriptor, list); 1854 list_move_tail(&found->list, &adapter->network_list); 1855 } else if (oldest) { 1856 /* If there are no more slots, expire the oldest */ 1857 found = oldest; 1858 clear_bss_descriptor(found); 1859 list_move_tail(&found->list, &adapter->network_list); 1860 } else { 1861 continue; 1862 } 1863 1864 lbs_deb_scan("SCAN_RESP: BSSID = " MAC_FMT "\n", 1865 new.bssid[0], new.bssid[1], new.bssid[2], 1866 new.bssid[3], new.bssid[4], new.bssid[5]); 1867 1868 /* 1869 * If the TSF TLV was appended to the scan results, save the 1870 * this entries TSF value in the networktsf field. The 1871 * networktsf is the firmware's TSF value at the time the 1872 * beacon or probe response was received. 1873 */ 1874 if (ptsftlv) { 1875 new.networktsf = le64_to_cpup(&ptsftlv->tsftable[idx]); 1876 } 1877 1878 /* Copy the locally created newbssentry to the scan table */ 1879 memcpy(found, &new, offsetof(struct bss_descriptor, list)); 1880 } 1881 1882 ret = 0; 1883 1884done: 1885 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); 1886 return ret; 1887} 1888