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