scan.c 58 KB

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