driver_broadcom.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. * WPA Supplicant - driver interaction with old Broadcom wl.o driver
  3. * Copyright (c) 2004, Nikki Chumkov <nikki@gattaca.ru>
  4. * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Alternatively, this software may be distributed under the terms of BSD
  11. * license.
  12. *
  13. * See README and COPYING for more details.
  14. *
  15. * Please note that the newer Broadcom driver ("hybrid Linux driver") supports
  16. * Linux wireless extensions and does not need (or even work) with this old
  17. * driver wrapper. Use driver_wext.c with that driver.
  18. */
  19. #include "includes.h"
  20. #include <sys/ioctl.h>
  21. #include "common.h"
  22. #if 0
  23. #include <netpacket/packet.h>
  24. #include <net/ethernet.h> /* the L2 protocols */
  25. #else
  26. #include <linux/if_packet.h>
  27. #include <linux/if_ether.h> /* The L2 protocols */
  28. #endif
  29. #include <net/if.h>
  30. #include <typedefs.h>
  31. /* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys
  32. * WRT54G GPL tarball. */
  33. #include <wlioctl.h>
  34. #include "driver.h"
  35. #include "eloop.h"
  36. struct wpa_driver_broadcom_data {
  37. void *ctx;
  38. int ioctl_sock;
  39. int event_sock;
  40. char ifname[IFNAMSIZ + 1];
  41. };
  42. #ifndef WLC_DEAUTHENTICATE
  43. #define WLC_DEAUTHENTICATE 143
  44. #endif
  45. #ifndef WLC_DEAUTHENTICATE_WITH_REASON
  46. #define WLC_DEAUTHENTICATE_WITH_REASON 201
  47. #endif
  48. #ifndef WLC_SET_TKIP_COUNTERMEASURES
  49. #define WLC_SET_TKIP_COUNTERMEASURES 202
  50. #endif
  51. #if !defined(PSK_ENABLED) /* NEW driver interface */
  52. #define WL_VERSION 360130
  53. /* wireless authentication bit vector */
  54. #define WPA_ENABLED 1
  55. #define PSK_ENABLED 2
  56. #define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED)
  57. #define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED)
  58. #define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED))
  59. #define WSEC_PRIMARY_KEY WL_PRIMARY_KEY
  60. typedef wl_wsec_key_t wsec_key_t;
  61. #endif
  62. typedef struct {
  63. uint32 val;
  64. struct ether_addr ea;
  65. uint16 res;
  66. } wlc_deauth_t;
  67. static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
  68. void *timeout_ctx);
  69. static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd,
  70. void *buf, int len)
  71. {
  72. struct ifreq ifr;
  73. wl_ioctl_t ioc;
  74. int ret = 0;
  75. wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)",
  76. drv->ifname, cmd, len, buf);
  77. /* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */
  78. ioc.cmd = cmd;
  79. ioc.buf = buf;
  80. ioc.len = len;
  81. os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ);
  82. ifr.ifr_data = (caddr_t) &ioc;
  83. if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) {
  84. if (cmd != WLC_GET_MAGIC)
  85. perror(ifr.ifr_name);
  86. wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d",
  87. cmd, ret);
  88. }
  89. return ret;
  90. }
  91. static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid)
  92. {
  93. struct wpa_driver_broadcom_data *drv = priv;
  94. if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0)
  95. return 0;
  96. os_memset(bssid, 0, ETH_ALEN);
  97. return -1;
  98. }
  99. static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid)
  100. {
  101. struct wpa_driver_broadcom_data *drv = priv;
  102. wlc_ssid_t s;
  103. if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1)
  104. return -1;
  105. os_memcpy(ssid, s.SSID, s.SSID_len);
  106. return s.SSID_len;
  107. }
  108. static int wpa_driver_broadcom_set_wpa(void *priv, int enable)
  109. {
  110. struct wpa_driver_broadcom_data *drv = priv;
  111. unsigned int wauth, wsec;
  112. struct ether_addr ea;
  113. os_memset(&ea, enable ? 0xff : 0, sizeof(ea));
  114. if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) ==
  115. -1 ||
  116. broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1)
  117. return -1;
  118. if (enable) {
  119. wauth = PSK_ENABLED;
  120. wsec = TKIP_ENABLED;
  121. } else {
  122. wauth = 255;
  123. wsec &= ~(TKIP_ENABLED | AES_ENABLED);
  124. }
  125. if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) ==
  126. -1 ||
  127. broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1)
  128. return -1;
  129. /* FIX: magic number / error handling? */
  130. broadcom_ioctl(drv, 122, &ea, sizeof(ea));
  131. return 0;
  132. }
  133. static int wpa_driver_broadcom_set_key(void *priv, wpa_alg alg,
  134. const u8 *addr, int key_idx, int set_tx,
  135. const u8 *seq, size_t seq_len,
  136. const u8 *key, size_t key_len)
  137. {
  138. struct wpa_driver_broadcom_data *drv = priv;
  139. int ret;
  140. wsec_key_t wkt;
  141. os_memset(&wkt, 0, sizeof wkt);
  142. wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d",
  143. set_tx ? "PRIMARY " : "", key_idx, alg);
  144. if (key && key_len > 0)
  145. wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len);
  146. switch (alg) {
  147. case WPA_ALG_NONE:
  148. wkt.algo = CRYPTO_ALGO_OFF;
  149. break;
  150. case WPA_ALG_WEP:
  151. wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */
  152. break;
  153. case WPA_ALG_TKIP:
  154. wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */
  155. break;
  156. case WPA_ALG_CCMP:
  157. wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM;
  158. * AES_OCB_MSDU, AES_OCB_MPDU? */
  159. break;
  160. default:
  161. wkt.algo = CRYPTO_ALGO_NALG;
  162. break;
  163. }
  164. if (seq && seq_len > 0)
  165. wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len);
  166. if (addr)
  167. wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN);
  168. wkt.index = key_idx;
  169. wkt.len = key_len;
  170. if (key && key_len > 0) {
  171. os_memcpy(wkt.data, key, key_len);
  172. if (key_len == 32) {
  173. /* hack hack hack XXX */
  174. os_memcpy(&wkt.data[16], &key[24], 8);
  175. os_memcpy(&wkt.data[24], &key[16], 8);
  176. }
  177. }
  178. /* wkt.algo = CRYPTO_ALGO_...; */
  179. wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY;
  180. if (addr && set_tx)
  181. os_memcpy(&wkt.ea, addr, sizeof(wkt.ea));
  182. ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt));
  183. if (addr && set_tx) {
  184. /* FIX: magic number / error handling? */
  185. broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea));
  186. }
  187. return ret;
  188. }
  189. static void wpa_driver_broadcom_event_receive(int sock, void *ctx,
  190. void *sock_ctx)
  191. {
  192. char buf[8192];
  193. int left;
  194. wl_wpa_header_t *wwh;
  195. union wpa_event_data data;
  196. if ((left = recv(sock, buf, sizeof buf, 0)) < 0)
  197. return;
  198. wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left);
  199. if ((size_t) left < sizeof(wl_wpa_header_t))
  200. return;
  201. wwh = (wl_wpa_header_t *) buf;
  202. if (wwh->snap.type != WL_WPA_ETHER_TYPE)
  203. return;
  204. if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0)
  205. return;
  206. os_memset(&data, 0, sizeof(data));
  207. switch (wwh->type) {
  208. case WLC_ASSOC_MSG:
  209. left -= WL_WPA_HEADER_LEN;
  210. wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)",
  211. left);
  212. if (left > 0) {
  213. data.assoc_info.resp_ies = os_malloc(left);
  214. if (data.assoc_info.resp_ies == NULL)
  215. return;
  216. os_memcpy(data.assoc_info.resp_ies,
  217. buf + WL_WPA_HEADER_LEN, left);
  218. data.assoc_info.resp_ies_len = left;
  219. wpa_hexdump(MSG_MSGDUMP, "BROADCOM: copying %d bytes "
  220. "into resp_ies",
  221. data.assoc_info.resp_ies, left);
  222. }
  223. /* data.assoc_info.req_ies = NULL; */
  224. /* data.assoc_info.req_ies_len = 0; */
  225. wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
  226. wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
  227. break;
  228. case WLC_DISASSOC_MSG:
  229. wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE");
  230. wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
  231. break;
  232. case WLC_PTK_MIC_MSG:
  233. wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE");
  234. data.michael_mic_failure.unicast = 1;
  235. wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
  236. break;
  237. case WLC_GTK_MIC_MSG:
  238. wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE");
  239. data.michael_mic_failure.unicast = 0;
  240. wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
  241. break;
  242. default:
  243. wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)",
  244. wwh->type);
  245. break;
  246. }
  247. os_free(data.assoc_info.resp_ies);
  248. }
  249. static void * wpa_driver_broadcom_init(void *ctx, const char *ifname)
  250. {
  251. int s;
  252. struct sockaddr_ll ll;
  253. struct wpa_driver_broadcom_data *drv;
  254. struct ifreq ifr;
  255. /* open socket to kernel */
  256. if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  257. perror("socket");
  258. return NULL;
  259. }
  260. /* do it */
  261. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  262. if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
  263. perror(ifr.ifr_name);
  264. return NULL;
  265. }
  266. drv = os_zalloc(sizeof(*drv));
  267. if (drv == NULL)
  268. return NULL;
  269. drv->ctx = ctx;
  270. os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
  271. drv->ioctl_sock = s;
  272. s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2));
  273. if (s < 0) {
  274. perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))");
  275. close(drv->ioctl_sock);
  276. os_free(drv);
  277. return NULL;
  278. }
  279. os_memset(&ll, 0, sizeof(ll));
  280. ll.sll_family = AF_PACKET;
  281. ll.sll_protocol = ntohs(ETH_P_802_2);
  282. ll.sll_ifindex = ifr.ifr_ifindex;
  283. ll.sll_hatype = 0;
  284. ll.sll_pkttype = PACKET_HOST;
  285. ll.sll_halen = 0;
  286. if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
  287. perror("bind(netlink)");
  288. close(s);
  289. close(drv->ioctl_sock);
  290. os_free(drv);
  291. return NULL;
  292. }
  293. eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx,
  294. NULL);
  295. drv->event_sock = s;
  296. return drv;
  297. }
  298. static void wpa_driver_broadcom_deinit(void *priv)
  299. {
  300. struct wpa_driver_broadcom_data *drv = priv;
  301. eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
  302. eloop_unregister_read_sock(drv->event_sock);
  303. close(drv->event_sock);
  304. close(drv->ioctl_sock);
  305. os_free(drv);
  306. }
  307. static int wpa_driver_broadcom_set_countermeasures(void *priv,
  308. int enabled)
  309. {
  310. #if 0
  311. struct wpa_driver_broadcom_data *drv = priv;
  312. /* FIX: ? */
  313. return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled,
  314. sizeof(enabled));
  315. #else
  316. return 0;
  317. #endif
  318. }
  319. static int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled)
  320. {
  321. struct wpa_driver_broadcom_data *drv = priv;
  322. /* SET_EAP_RESTRICT, SET_WEP_RESTRICT */
  323. int _restrict = (enabled ? 1 : 0);
  324. if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT,
  325. &_restrict, sizeof(_restrict)) < 0 ||
  326. broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT,
  327. &_restrict, sizeof(_restrict)) < 0)
  328. return -1;
  329. return 0;
  330. }
  331. static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
  332. void *timeout_ctx)
  333. {
  334. wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
  335. wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
  336. }
  337. static int wpa_driver_broadcom_scan(void *priv, const u8 *ssid,
  338. size_t ssid_len)
  339. {
  340. struct wpa_driver_broadcom_data *drv = priv;
  341. wlc_ssid_t wst = { 0, "" };
  342. if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) {
  343. wst.SSID_len = ssid_len;
  344. os_memcpy(wst.SSID, ssid, ssid_len);
  345. }
  346. if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0)
  347. return -1;
  348. eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
  349. eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv,
  350. drv->ctx);
  351. return 0;
  352. }
  353. static const int frequency_list[] = {
  354. 2412, 2417, 2422, 2427, 2432, 2437, 2442,
  355. 2447, 2452, 2457, 2462, 2467, 2472, 2484
  356. };
  357. struct bss_ie_hdr {
  358. u8 elem_id;
  359. u8 len;
  360. u8 oui[3];
  361. /* u8 oui_type; */
  362. /* u16 version; */
  363. } __attribute__ ((packed));
  364. static int
  365. wpa_driver_broadcom_get_scan_results(void *priv,
  366. struct wpa_scan_result *results,
  367. size_t max_size)
  368. {
  369. struct wpa_driver_broadcom_data *drv = priv;
  370. char *buf;
  371. wl_scan_results_t *wsr;
  372. wl_bss_info_t *wbi;
  373. size_t ap_num;
  374. buf = os_malloc(WLC_IOCTL_MAXLEN);
  375. if (buf == NULL)
  376. return -1;
  377. wsr = (wl_scan_results_t *) buf;
  378. wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr);
  379. wsr->version = 107;
  380. wsr->count = 0;
  381. if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) {
  382. os_free(buf);
  383. return -1;
  384. }
  385. os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
  386. for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) {
  387. int left;
  388. struct bss_ie_hdr *ie;
  389. os_memcpy(results[ap_num].bssid, &wbi->BSSID, ETH_ALEN);
  390. os_memcpy(results[ap_num].ssid, wbi->SSID, wbi->SSID_len);
  391. results[ap_num].ssid_len = wbi->SSID_len;
  392. results[ap_num].freq = frequency_list[wbi->channel - 1];
  393. /* get ie's */
  394. wpa_hexdump(MSG_MSGDUMP, "BROADCOM: AP IEs",
  395. (u8 *) wbi + sizeof(*wbi), wbi->ie_length);
  396. ie = (struct bss_ie_hdr *) ((u8 *) wbi + sizeof(*wbi));
  397. for (left = wbi->ie_length; left > 0;
  398. left -= (ie->len + 2), ie = (struct bss_ie_hdr *)
  399. ((u8 *) ie + 2 + ie->len)) {
  400. wpa_printf(MSG_MSGDUMP, "BROADCOM: IE: id:%x, len:%d",
  401. ie->elem_id, ie->len);
  402. if (ie->len >= 3)
  403. wpa_printf(MSG_MSGDUMP,
  404. "BROADCOM: oui:%02x%02x%02x",
  405. ie->oui[0], ie->oui[1], ie->oui[2]);
  406. if (ie->elem_id != 0xdd ||
  407. ie->len < 6 ||
  408. os_memcmp(ie->oui, WPA_OUI, 3) != 0)
  409. continue;
  410. os_memcpy(results[ap_num].wpa_ie, ie, ie->len + 2);
  411. results[ap_num].wpa_ie_len = ie->len + 2;
  412. break;
  413. }
  414. wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length);
  415. }
  416. wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu "
  417. "BSSes)",
  418. wsr->buflen, (unsigned long) ap_num);
  419. os_free(buf);
  420. return ap_num;
  421. }
  422. static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr,
  423. int reason_code)
  424. {
  425. struct wpa_driver_broadcom_data *drv = priv;
  426. wlc_deauth_t wdt;
  427. wdt.val = reason_code;
  428. os_memcpy(&wdt.ea, addr, sizeof wdt.ea);
  429. wdt.res = 0x7fff;
  430. return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt,
  431. sizeof(wdt));
  432. }
  433. static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr,
  434. int reason_code)
  435. {
  436. struct wpa_driver_broadcom_data *drv = priv;
  437. return broadcom_ioctl(drv, WLC_DISASSOC, NULL, 0);
  438. }
  439. static int
  440. wpa_driver_broadcom_associate(void *priv,
  441. struct wpa_driver_associate_params *params)
  442. {
  443. struct wpa_driver_broadcom_data *drv = priv;
  444. wlc_ssid_t s;
  445. int infra = 1;
  446. int auth = 0;
  447. int wsec = 4;
  448. int dummy;
  449. int wpa_auth;
  450. s.SSID_len = params->ssid_len;
  451. os_memcpy(s.SSID, params->ssid, params->ssid_len);
  452. switch (params->pairwise_suite) {
  453. case CIPHER_WEP40:
  454. case CIPHER_WEP104:
  455. wsec = 1;
  456. break;
  457. case CIPHER_TKIP:
  458. wsec = 2;
  459. break;
  460. case CIPHER_CCMP:
  461. wsec = 4;
  462. break;
  463. default:
  464. wsec = 0;
  465. break;
  466. }
  467. switch (params->key_mgmt_suite) {
  468. case KEY_MGMT_802_1X:
  469. wpa_auth = 1;
  470. break;
  471. case KEY_MGMT_PSK:
  472. wpa_auth = 2;
  473. break;
  474. default:
  475. wpa_auth = 255;
  476. break;
  477. }
  478. /* printf("broadcom_associate: %u %u %u\n", pairwise_suite,
  479. * group_suite, key_mgmt_suite);
  480. * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec));
  481. * wl join uses wlc_sec_wep here, not wlc_set_wsec */
  482. if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 ||
  483. broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth,
  484. sizeof(wpa_auth)) < 0 ||
  485. broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 ||
  486. broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 ||
  487. broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 ||
  488. broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 ||
  489. broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0)
  490. return -1;
  491. return 0;
  492. }
  493. const struct wpa_driver_ops wpa_driver_broadcom_ops = {
  494. .name = "broadcom",
  495. .desc = "Broadcom wl.o driver",
  496. .get_bssid = wpa_driver_broadcom_get_bssid,
  497. .get_ssid = wpa_driver_broadcom_get_ssid,
  498. .set_wpa = wpa_driver_broadcom_set_wpa,
  499. .set_key = wpa_driver_broadcom_set_key,
  500. .init = wpa_driver_broadcom_init,
  501. .deinit = wpa_driver_broadcom_deinit,
  502. .set_countermeasures = wpa_driver_broadcom_set_countermeasures,
  503. .set_drop_unencrypted = wpa_driver_broadcom_set_drop_unencrypted,
  504. .scan = wpa_driver_broadcom_scan,
  505. .get_scan_results = wpa_driver_broadcom_get_scan_results,
  506. .deauthenticate = wpa_driver_broadcom_deauthenticate,
  507. .disassociate = wpa_driver_broadcom_disassociate,
  508. .associate = wpa_driver_broadcom_associate,
  509. };