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