ieee80211softmac_module.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. /*
  2. * Contains some basic softmac functions along with module registration code etc.
  3. *
  4. * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
  5. * Joseph Jezak <josejx@gentoo.org>
  6. * Larry Finger <Larry.Finger@lwfinger.net>
  7. * Danny van Dyk <kugelfang@gentoo.org>
  8. * Michael Buesch <mbuesch@freenet.de>
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of version 2 of the GNU General Public License as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  17. * more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * The full GNU General Public License is included in this distribution in the
  24. * file called COPYING.
  25. */
  26. #include "ieee80211softmac_priv.h"
  27. #include <linux/sort.h>
  28. #include <linux/etherdevice.h>
  29. struct net_device *alloc_ieee80211softmac(int sizeof_priv)
  30. {
  31. struct ieee80211softmac_device *softmac;
  32. struct net_device *dev;
  33. dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv);
  34. softmac = ieee80211_priv(dev);
  35. softmac->dev = dev;
  36. softmac->ieee = netdev_priv(dev);
  37. spin_lock_init(&softmac->lock);
  38. softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
  39. softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
  40. softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
  41. softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
  42. softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
  43. softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
  44. softmac->scaninfo = NULL;
  45. softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
  46. /* TODO: initialise all the other callbacks in the ieee struct
  47. * (once they're written)
  48. */
  49. INIT_LIST_HEAD(&softmac->auth_queue);
  50. INIT_LIST_HEAD(&softmac->network_list);
  51. INIT_LIST_HEAD(&softmac->events);
  52. mutex_init(&softmac->associnfo.mutex);
  53. INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work);
  54. INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout);
  55. softmac->start_scan = ieee80211softmac_start_scan_implementation;
  56. softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
  57. softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
  58. /* to start with, we can't send anything ... */
  59. netif_carrier_off(dev);
  60. return dev;
  61. }
  62. EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
  63. /* Clears the pending work queue items, stops all scans, etc. */
  64. void
  65. ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
  66. {
  67. unsigned long flags;
  68. struct ieee80211softmac_event *eventptr, *eventtmp;
  69. struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
  70. struct ieee80211softmac_network *netptr, *nettmp;
  71. ieee80211softmac_stop_scan(sm);
  72. ieee80211softmac_wait_for_scan(sm);
  73. spin_lock_irqsave(&sm->lock, flags);
  74. sm->running = 0;
  75. /* Free all pending assoc work items */
  76. cancel_delayed_work(&sm->associnfo.work);
  77. /* Free all pending scan work items */
  78. if(sm->scaninfo != NULL)
  79. cancel_delayed_work(&sm->scaninfo->softmac_scan);
  80. /* Free all pending auth work items */
  81. list_for_each_entry(authptr, &sm->auth_queue, list)
  82. cancel_delayed_work(&authptr->work);
  83. /* delete all pending event calls and work items */
  84. list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
  85. cancel_delayed_work(&eventptr->work);
  86. spin_unlock_irqrestore(&sm->lock, flags);
  87. flush_scheduled_work();
  88. /* now we should be save and no longer need locking... */
  89. spin_lock_irqsave(&sm->lock, flags);
  90. /* Free all pending auth work items */
  91. list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) {
  92. list_del(&authptr->list);
  93. kfree(authptr);
  94. }
  95. /* delete all pending event calls and work items */
  96. list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
  97. list_del(&eventptr->list);
  98. kfree(eventptr);
  99. }
  100. /* Free all networks */
  101. list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
  102. ieee80211softmac_del_network_locked(sm, netptr);
  103. if(netptr->challenge != NULL)
  104. kfree(netptr->challenge);
  105. kfree(netptr);
  106. }
  107. spin_unlock_irqrestore(&sm->lock, flags);
  108. }
  109. EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work);
  110. void free_ieee80211softmac(struct net_device *dev)
  111. {
  112. struct ieee80211softmac_device *sm = ieee80211_priv(dev);
  113. ieee80211softmac_clear_pending_work(sm);
  114. kfree(sm->scaninfo);
  115. kfree(sm->wpa.IE);
  116. free_ieee80211(dev);
  117. }
  118. EXPORT_SYMBOL_GPL(free_ieee80211softmac);
  119. static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac)
  120. {
  121. struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
  122. /* I took out the sorting check, we're seperating by modulation now. */
  123. if (ri->count)
  124. return;
  125. /* otherwise assume we hav'em all! */
  126. if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) {
  127. ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB;
  128. ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB;
  129. ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB;
  130. ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB;
  131. }
  132. if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) {
  133. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB;
  134. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB;
  135. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB;
  136. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB;
  137. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB;
  138. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB;
  139. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB;
  140. ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB;
  141. }
  142. }
  143. int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
  144. {
  145. int search;
  146. u8 search_rate;
  147. for (search = 0; search < ri->count; search++) {
  148. search_rate = ri->rates[search];
  149. search_rate &= ~IEEE80211_BASIC_RATE_MASK;
  150. if (rate == search_rate)
  151. return 1;
  152. }
  153. return 0;
  154. }
  155. u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
  156. struct ieee80211softmac_ratesinfo *ri, int basic_only)
  157. {
  158. u8 user_rate = mac->txrates.user_rate;
  159. int i;
  160. if (ri->count == 0)
  161. return IEEE80211_CCK_RATE_1MB;
  162. for (i = ri->count - 1; i >= 0; i--) {
  163. u8 rate = ri->rates[i];
  164. if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
  165. continue;
  166. rate &= ~IEEE80211_BASIC_RATE_MASK;
  167. if (rate > user_rate)
  168. continue;
  169. if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
  170. return rate;
  171. }
  172. /* If we haven't found a suitable rate by now, just trust the user */
  173. return user_rate;
  174. }
  175. EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
  176. void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
  177. u8 erp_value)
  178. {
  179. int use_protection;
  180. int short_preamble;
  181. u32 changes = 0;
  182. /* Barker preamble mode */
  183. short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
  184. && mac->associnfo.short_preamble_available) ? 1 : 0;
  185. /* Protection needed? */
  186. use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
  187. if (mac->bssinfo.short_preamble != short_preamble) {
  188. changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
  189. mac->bssinfo.short_preamble = short_preamble;
  190. }
  191. if (mac->bssinfo.use_protection != use_protection) {
  192. changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
  193. mac->bssinfo.use_protection = use_protection;
  194. }
  195. if (mac->bssinfo_change && changes)
  196. mac->bssinfo_change(mac->dev, changes);
  197. }
  198. void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
  199. {
  200. struct ieee80211softmac_txrates *txrates = &mac->txrates;
  201. u32 change = 0;
  202. change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
  203. txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
  204. change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
  205. txrates->default_fallback = lower_rate(mac, txrates->default_rate);
  206. change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
  207. txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
  208. if (mac->txrates_change)
  209. mac->txrates_change(mac->dev, change);
  210. }
  211. void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
  212. {
  213. struct ieee80211_device *ieee = mac->ieee;
  214. u32 change = 0;
  215. struct ieee80211softmac_txrates *txrates = &mac->txrates;
  216. struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
  217. /* TODO: We need some kind of state machine to lower the default rates
  218. * if we loose too many packets.
  219. */
  220. /* Change the default txrate to the highest possible value.
  221. * The txrate machine will lower it, if it is too high.
  222. */
  223. if (ieee->modulation & IEEE80211_OFDM_MODULATION)
  224. txrates->user_rate = IEEE80211_OFDM_RATE_24MB;
  225. else
  226. txrates->user_rate = IEEE80211_CCK_RATE_11MB;
  227. txrates->default_rate = IEEE80211_CCK_RATE_1MB;
  228. change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
  229. txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
  230. change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
  231. txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
  232. change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
  233. txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
  234. change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
  235. if (mac->txrates_change)
  236. mac->txrates_change(mac->dev, change);
  237. change = 0;
  238. bssinfo->supported_rates.count = 0;
  239. memset(bssinfo->supported_rates.rates, 0,
  240. sizeof(bssinfo->supported_rates.rates));
  241. change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
  242. bssinfo->short_preamble = 0;
  243. change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
  244. bssinfo->use_protection = 0;
  245. change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
  246. if (mac->bssinfo_change)
  247. mac->bssinfo_change(mac->dev, change);
  248. mac->running = 1;
  249. }
  250. void ieee80211softmac_start(struct net_device *dev)
  251. {
  252. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  253. ieee80211softmac_start_check_rates(mac);
  254. ieee80211softmac_init_bss(mac);
  255. }
  256. EXPORT_SYMBOL_GPL(ieee80211softmac_start);
  257. void ieee80211softmac_stop(struct net_device *dev)
  258. {
  259. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  260. ieee80211softmac_clear_pending_work(mac);
  261. }
  262. EXPORT_SYMBOL_GPL(ieee80211softmac_stop);
  263. void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates)
  264. {
  265. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  266. unsigned long flags;
  267. spin_lock_irqsave(&mac->lock, flags);
  268. memcpy(mac->ratesinfo.rates, rates, count);
  269. mac->ratesinfo.count = count;
  270. spin_unlock_irqrestore(&mac->lock, flags);
  271. }
  272. EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates);
  273. static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate)
  274. {
  275. int i;
  276. struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
  277. for (i=0; i<ri->count-1; i++) {
  278. if (ri->rates[i] == rate)
  279. return ri->rates[i+1];
  280. }
  281. /* I guess we can't go any higher... */
  282. return ri->rates[ri->count];
  283. }
  284. u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta)
  285. {
  286. int i;
  287. struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
  288. for (i=delta; i<ri->count; i++) {
  289. if (ri->rates[i] == rate)
  290. return ri->rates[i-delta];
  291. }
  292. /* I guess we can't go any lower... */
  293. return ri->rates[0];
  294. }
  295. static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
  296. int amount)
  297. {
  298. u8 default_rate = mac->txrates.default_rate;
  299. u8 default_fallback = mac->txrates.default_fallback;
  300. u32 changes = 0;
  301. //TODO: This is highly experimental code.
  302. // Maybe the dynamic rate selection does not work
  303. // and it has to be removed again.
  304. printk("badness %d\n", mac->txrate_badness);
  305. mac->txrate_badness += amount;
  306. if (mac->txrate_badness <= -1000) {
  307. /* Very small badness. Try a faster bitrate. */
  308. default_rate = raise_rate(mac, default_rate);
  309. changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
  310. default_fallback = get_fallback_rate(mac, default_rate);
  311. changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
  312. mac->txrate_badness = 0;
  313. printk("Bitrate raised to %u\n", default_rate);
  314. } else if (mac->txrate_badness >= 10000) {
  315. /* Very high badness. Try a slower bitrate. */
  316. default_rate = lower_rate(mac, default_rate);
  317. changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
  318. default_fallback = get_fallback_rate(mac, default_rate);
  319. changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
  320. mac->txrate_badness = 0;
  321. printk("Bitrate lowered to %u\n", default_rate);
  322. }
  323. mac->txrates.default_rate = default_rate;
  324. mac->txrates.default_fallback = default_fallback;
  325. if (changes && mac->txrates_change)
  326. mac->txrates_change(mac->dev, changes);
  327. }
  328. void ieee80211softmac_fragment_lost(struct net_device *dev,
  329. u16 wl_seq)
  330. {
  331. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  332. unsigned long flags;
  333. spin_lock_irqsave(&mac->lock, flags);
  334. ieee80211softmac_add_txrates_badness(mac, 1000);
  335. //TODO
  336. spin_unlock_irqrestore(&mac->lock, flags);
  337. }
  338. EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost);
  339. static int rate_cmp(const void *a_, const void *b_) {
  340. u8 *a, *b;
  341. a = (u8*)a_;
  342. b = (u8*)b_;
  343. return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK));
  344. }
  345. /* Allocate a softmac network struct and fill it from a network */
  346. struct ieee80211softmac_network *
  347. ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
  348. struct ieee80211_network *net)
  349. {
  350. struct ieee80211softmac_network *softnet;
  351. softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC);
  352. if(softnet == NULL)
  353. return NULL;
  354. memcpy(softnet->bssid, net->bssid, ETH_ALEN);
  355. softnet->channel = net->channel;
  356. softnet->essid.len = net->ssid_len;
  357. memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
  358. /* copy rates over */
  359. softnet->supported_rates.count = net->rates_len;
  360. memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
  361. memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
  362. softnet->supported_rates.count += net->rates_ex_len;
  363. sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
  364. /* we save the ERP value because it is needed at association time, and
  365. * many AP's do not include an ERP IE in the association response. */
  366. softnet->erp_value = net->erp_value;
  367. softnet->capabilities = net->capability;
  368. return softnet;
  369. }
  370. /* Add a network to the list, while locked */
  371. void
  372. ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
  373. struct ieee80211softmac_network *add_net)
  374. {
  375. struct list_head *list_ptr;
  376. struct ieee80211softmac_network *softmac_net = NULL;
  377. list_for_each(list_ptr, &mac->network_list) {
  378. softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
  379. if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
  380. break;
  381. else
  382. softmac_net = NULL;
  383. }
  384. if(softmac_net == NULL)
  385. list_add(&(add_net->list), &mac->network_list);
  386. }
  387. /* Add a network to the list, with locking */
  388. void
  389. ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
  390. struct ieee80211softmac_network *add_net)
  391. {
  392. unsigned long flags;
  393. spin_lock_irqsave(&mac->lock, flags);
  394. ieee80211softmac_add_network_locked(mac, add_net);
  395. spin_unlock_irqrestore(&mac->lock, flags);
  396. }
  397. /* Delete a network from the list, while locked*/
  398. void
  399. ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
  400. struct ieee80211softmac_network *del_net)
  401. {
  402. list_del(&(del_net->list));
  403. }
  404. /* Delete a network from the list with locking */
  405. void
  406. ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
  407. struct ieee80211softmac_network *del_net)
  408. {
  409. unsigned long flags;
  410. spin_lock_irqsave(&mac->lock, flags);
  411. ieee80211softmac_del_network_locked(mac, del_net);
  412. spin_unlock_irqrestore(&mac->lock, flags);
  413. }
  414. /* Get a network from the list by MAC while locked */
  415. struct ieee80211softmac_network *
  416. ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
  417. u8 *bssid)
  418. {
  419. struct list_head *list_ptr;
  420. struct ieee80211softmac_network *softmac_net = NULL;
  421. list_for_each(list_ptr, &mac->network_list) {
  422. softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
  423. if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
  424. break;
  425. else
  426. softmac_net = NULL;
  427. }
  428. return softmac_net;
  429. }
  430. /* Get a network from the list by BSSID with locking */
  431. struct ieee80211softmac_network *
  432. ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac,
  433. u8 *bssid)
  434. {
  435. unsigned long flags;
  436. struct ieee80211softmac_network *softmac_net;
  437. spin_lock_irqsave(&mac->lock, flags);
  438. softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
  439. spin_unlock_irqrestore(&mac->lock, flags);
  440. return softmac_net;
  441. }
  442. /* Get a network from the list by ESSID while locked */
  443. struct ieee80211softmac_network *
  444. ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
  445. struct ieee80211softmac_essid *essid)
  446. {
  447. struct list_head *list_ptr;
  448. struct ieee80211softmac_network *softmac_net = NULL;
  449. list_for_each(list_ptr, &mac->network_list) {
  450. softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
  451. if (softmac_net->essid.len == essid->len &&
  452. !memcmp(softmac_net->essid.data, essid->data, essid->len))
  453. return softmac_net;
  454. }
  455. return NULL;
  456. }
  457. /* Get a network from the list by ESSID with locking */
  458. struct ieee80211softmac_network *
  459. ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
  460. struct ieee80211softmac_essid *essid)
  461. {
  462. unsigned long flags;
  463. struct ieee80211softmac_network *softmac_net = NULL;
  464. spin_lock_irqsave(&mac->lock, flags);
  465. softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
  466. spin_unlock_irqrestore(&mac->lock, flags);
  467. return softmac_net;
  468. }
  469. MODULE_LICENSE("GPL");
  470. MODULE_AUTHOR("Johannes Berg");
  471. MODULE_AUTHOR("Joseph Jezak");
  472. MODULE_AUTHOR("Larry Finger");
  473. MODULE_AUTHOR("Danny van Dyk");
  474. MODULE_AUTHOR("Michael Buesch");
  475. MODULE_DESCRIPTION("802.11 software MAC");