ieee80211softmac_wx.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
  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 <net/iw_handler.h>
  28. int
  29. ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
  30. struct iw_request_info *info,
  31. union iwreq_data *data,
  32. char *extra)
  33. {
  34. struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
  35. return ieee80211softmac_start_scan(sm);
  36. }
  37. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
  38. int
  39. ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
  40. struct iw_request_info *info,
  41. union iwreq_data *data,
  42. char *extra)
  43. {
  44. struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
  45. return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
  46. }
  47. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
  48. int
  49. ieee80211softmac_wx_set_essid(struct net_device *net_dev,
  50. struct iw_request_info *info,
  51. union iwreq_data *data,
  52. char *extra)
  53. {
  54. struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
  55. int length = 0;
  56. unsigned long flags;
  57. spin_lock_irqsave(&sm->lock, flags);
  58. sm->associnfo.static_essid = 0;
  59. if (data->essid.flags && data->essid.length && extra /*required?*/) {
  60. length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
  61. if (length) {
  62. memcpy(sm->associnfo.req_essid.data, extra, length);
  63. sm->associnfo.static_essid = 1;
  64. }
  65. }
  66. sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
  67. /* set our requested ESSID length.
  68. * If applicable, we have already copied the data in */
  69. sm->associnfo.req_essid.len = length;
  70. /* queue lower level code to do work (if necessary) */
  71. schedule_work(&sm->associnfo.work);
  72. spin_unlock_irqrestore(&sm->lock, flags);
  73. return 0;
  74. }
  75. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
  76. int
  77. ieee80211softmac_wx_get_essid(struct net_device *net_dev,
  78. struct iw_request_info *info,
  79. union iwreq_data *data,
  80. char *extra)
  81. {
  82. struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
  83. unsigned long flags;
  84. /* avoid getting inconsistent information */
  85. spin_lock_irqsave(&sm->lock, flags);
  86. /* If all fails, return ANY (empty) */
  87. data->essid.length = 0;
  88. data->essid.flags = 0; /* active */
  89. /* If we have a statically configured ESSID then return it */
  90. if (sm->associnfo.static_essid) {
  91. data->essid.length = sm->associnfo.req_essid.len;
  92. data->essid.flags = 1; /* active */
  93. memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
  94. }
  95. /* If we're associating/associated, return that */
  96. if (sm->associated || sm->associnfo.associating) {
  97. data->essid.length = sm->associnfo.associate_essid.len;
  98. data->essid.flags = 1; /* active */
  99. memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
  100. }
  101. spin_unlock_irqrestore(&sm->lock, flags);
  102. return 0;
  103. }
  104. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
  105. int
  106. ieee80211softmac_wx_set_rate(struct net_device *net_dev,
  107. struct iw_request_info *info,
  108. union iwreq_data *data,
  109. char *extra)
  110. {
  111. struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
  112. struct ieee80211_device *ieee = mac->ieee;
  113. unsigned long flags;
  114. s32 in_rate = data->bitrate.value;
  115. u8 rate;
  116. int is_ofdm = 0;
  117. int err = -EINVAL;
  118. if (in_rate == -1) {
  119. /* automatic detect */
  120. if (ieee->modulation & IEEE80211_OFDM_MODULATION)
  121. in_rate = 54000000;
  122. else
  123. in_rate = 11000000;
  124. }
  125. switch (in_rate) {
  126. case 1000000:
  127. rate = IEEE80211_CCK_RATE_1MB;
  128. break;
  129. case 2000000:
  130. rate = IEEE80211_CCK_RATE_2MB;
  131. break;
  132. case 5500000:
  133. rate = IEEE80211_CCK_RATE_5MB;
  134. break;
  135. case 11000000:
  136. rate = IEEE80211_CCK_RATE_11MB;
  137. break;
  138. case 6000000:
  139. rate = IEEE80211_OFDM_RATE_6MB;
  140. is_ofdm = 1;
  141. break;
  142. case 9000000:
  143. rate = IEEE80211_OFDM_RATE_9MB;
  144. is_ofdm = 1;
  145. break;
  146. case 12000000:
  147. rate = IEEE80211_OFDM_RATE_12MB;
  148. is_ofdm = 1;
  149. break;
  150. case 18000000:
  151. rate = IEEE80211_OFDM_RATE_18MB;
  152. is_ofdm = 1;
  153. break;
  154. case 24000000:
  155. rate = IEEE80211_OFDM_RATE_24MB;
  156. is_ofdm = 1;
  157. break;
  158. case 36000000:
  159. rate = IEEE80211_OFDM_RATE_36MB;
  160. is_ofdm = 1;
  161. break;
  162. case 48000000:
  163. rate = IEEE80211_OFDM_RATE_48MB;
  164. is_ofdm = 1;
  165. break;
  166. case 54000000:
  167. rate = IEEE80211_OFDM_RATE_54MB;
  168. is_ofdm = 1;
  169. break;
  170. default:
  171. goto out;
  172. }
  173. spin_lock_irqsave(&mac->lock, flags);
  174. /* Check if correct modulation for this PHY. */
  175. if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
  176. goto out_unlock;
  177. mac->txrates.default_rate = rate;
  178. mac->txrates.default_fallback = lower_rate(mac, rate);
  179. err = 0;
  180. out_unlock:
  181. spin_unlock_irqrestore(&mac->lock, flags);
  182. out:
  183. return err;
  184. }
  185. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
  186. int
  187. ieee80211softmac_wx_get_rate(struct net_device *net_dev,
  188. struct iw_request_info *info,
  189. union iwreq_data *data,
  190. char *extra)
  191. {
  192. struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
  193. unsigned long flags;
  194. int err = -EINVAL;
  195. spin_lock_irqsave(&mac->lock, flags);
  196. switch (mac->txrates.default_rate) {
  197. case IEEE80211_CCK_RATE_1MB:
  198. data->bitrate.value = 1000000;
  199. break;
  200. case IEEE80211_CCK_RATE_2MB:
  201. data->bitrate.value = 2000000;
  202. break;
  203. case IEEE80211_CCK_RATE_5MB:
  204. data->bitrate.value = 5500000;
  205. break;
  206. case IEEE80211_CCK_RATE_11MB:
  207. data->bitrate.value = 11000000;
  208. break;
  209. case IEEE80211_OFDM_RATE_6MB:
  210. data->bitrate.value = 6000000;
  211. break;
  212. case IEEE80211_OFDM_RATE_9MB:
  213. data->bitrate.value = 9000000;
  214. break;
  215. case IEEE80211_OFDM_RATE_12MB:
  216. data->bitrate.value = 12000000;
  217. break;
  218. case IEEE80211_OFDM_RATE_18MB:
  219. data->bitrate.value = 18000000;
  220. break;
  221. case IEEE80211_OFDM_RATE_24MB:
  222. data->bitrate.value = 24000000;
  223. break;
  224. case IEEE80211_OFDM_RATE_36MB:
  225. data->bitrate.value = 36000000;
  226. break;
  227. case IEEE80211_OFDM_RATE_48MB:
  228. data->bitrate.value = 48000000;
  229. break;
  230. case IEEE80211_OFDM_RATE_54MB:
  231. data->bitrate.value = 54000000;
  232. break;
  233. default:
  234. assert(0);
  235. goto out_unlock;
  236. }
  237. err = 0;
  238. out_unlock:
  239. spin_unlock_irqrestore(&mac->lock, flags);
  240. return err;
  241. }
  242. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
  243. int
  244. ieee80211softmac_wx_get_wap(struct net_device *net_dev,
  245. struct iw_request_info *info,
  246. union iwreq_data *data,
  247. char *extra)
  248. {
  249. struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
  250. int err = 0;
  251. unsigned long flags;
  252. spin_lock_irqsave(&mac->lock, flags);
  253. if (mac->associnfo.bssvalid)
  254. memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
  255. else
  256. memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
  257. data->ap_addr.sa_family = ARPHRD_ETHER;
  258. spin_unlock_irqrestore(&mac->lock, flags);
  259. return err;
  260. }
  261. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
  262. int
  263. ieee80211softmac_wx_set_wap(struct net_device *net_dev,
  264. struct iw_request_info *info,
  265. union iwreq_data *data,
  266. char *extra)
  267. {
  268. struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
  269. static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  270. static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  271. unsigned long flags;
  272. /* sanity check */
  273. if (data->ap_addr.sa_family != ARPHRD_ETHER) {
  274. return -EINVAL;
  275. }
  276. spin_lock_irqsave(&mac->lock, flags);
  277. if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
  278. !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
  279. schedule_work(&mac->associnfo.work);
  280. goto out;
  281. } else {
  282. if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
  283. if (mac->associnfo.associating || mac->associated) {
  284. /* bssid unchanged and associated or associating - just return */
  285. goto out;
  286. }
  287. } else {
  288. /* copy new value in data->ap_addr.sa_data to bssid */
  289. memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
  290. }
  291. /* queue associate if new bssid or (old one again and not associated) */
  292. schedule_work(&mac->associnfo.work);
  293. }
  294. out:
  295. spin_unlock_irqrestore(&mac->lock, flags);
  296. return 0;
  297. }
  298. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
  299. int
  300. ieee80211softmac_wx_set_genie(struct net_device *dev,
  301. struct iw_request_info *info,
  302. union iwreq_data *wrqu,
  303. char *extra)
  304. {
  305. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  306. unsigned long flags;
  307. int err = 0;
  308. char *buf;
  309. int i;
  310. spin_lock_irqsave(&mac->lock, flags);
  311. /* bleh. shouldn't be locked for that kmalloc... */
  312. if (wrqu->data.length) {
  313. if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
  314. /* this is an IE, so the length must be
  315. * correct. Is it possible though that
  316. * more than one IE is passed in?
  317. */
  318. err = -EINVAL;
  319. goto out;
  320. }
  321. if (mac->wpa.IEbuflen <= wrqu->data.length) {
  322. buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
  323. if (!buf) {
  324. err = -ENOMEM;
  325. goto out;
  326. }
  327. kfree(mac->wpa.IE);
  328. mac->wpa.IE = buf;
  329. mac->wpa.IEbuflen = wrqu->data.length;
  330. }
  331. memcpy(mac->wpa.IE, extra, wrqu->data.length);
  332. dprintk(KERN_INFO PFX "generic IE set to ");
  333. for (i=0;i<wrqu->data.length;i++)
  334. dprintk("%.2x", mac->wpa.IE[i]);
  335. dprintk("\n");
  336. mac->wpa.IElen = wrqu->data.length;
  337. } else {
  338. kfree(mac->wpa.IE);
  339. mac->wpa.IE = NULL;
  340. mac->wpa.IElen = 0;
  341. mac->wpa.IEbuflen = 0;
  342. }
  343. out:
  344. spin_unlock_irqrestore(&mac->lock, flags);
  345. return err;
  346. }
  347. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
  348. int
  349. ieee80211softmac_wx_get_genie(struct net_device *dev,
  350. struct iw_request_info *info,
  351. union iwreq_data *wrqu,
  352. char *extra)
  353. {
  354. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  355. unsigned long flags;
  356. int err = 0;
  357. int space = wrqu->data.length;
  358. spin_lock_irqsave(&mac->lock, flags);
  359. wrqu->data.length = 0;
  360. if (mac->wpa.IE && mac->wpa.IElen) {
  361. wrqu->data.length = mac->wpa.IElen;
  362. if (mac->wpa.IElen <= space)
  363. memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
  364. else
  365. err = -E2BIG;
  366. }
  367. spin_unlock_irqrestore(&mac->lock, flags);
  368. return err;
  369. }
  370. EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);