1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant - driver interaction with old Broadcom wl.o driver
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004, Nikki Chumkov <nikki@gattaca.ru>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Please note that the newer Broadcom driver ("hybrid Linux driver") supports
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Linux wireless extensions and does not need (or even work) with this old
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * driver wrapper. Use driver_wext.c with that driver.
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/ioctl.h>
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if 0
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <netpacket/packet.h>
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/ethernet.h>     /* the L2 protocols */
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <linux/if_packet.h>
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <linux/if_ether.h>   /* The L2 protocols */
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/if.h>
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <typedefs.h>
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WRT54G GPL tarball. */
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <wlioctl.h>
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "driver.h"
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h"
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_driver_broadcom_data {
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	void *ctx;
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ioctl_sock;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int event_sock;
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char ifname[IFNAMSIZ + 1];
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WLC_DEAUTHENTICATE
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WLC_DEAUTHENTICATE 143
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WLC_DEAUTHENTICATE_WITH_REASON
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WLC_DEAUTHENTICATE_WITH_REASON 201
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WLC_SET_TKIP_COUNTERMEASURES
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WLC_SET_TKIP_COUNTERMEASURES 202
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if !defined(PSK_ENABLED) /* NEW driver interface */
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WL_VERSION 360130
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* wireless authentication bit vector */
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WPA_ENABLED 1
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define PSK_ENABLED 2
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WAUTH_WPA_ENABLED(wauth)  ((wauth) & WPA_ENABLED)
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WAUTH_PSK_ENABLED(wauth)  ((wauth) & PSK_ENABLED)
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WAUTH_ENABLED(wauth)    ((wauth) & (WPA_ENABLED | PSK_ENABLED))
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WSEC_PRIMARY_KEY WL_PRIMARY_KEY
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidttypedef wl_wsec_key_t wsec_key_t;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidttypedef struct {
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	uint32 val;
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ether_addr ea;
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	uint16 res;
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} wlc_deauth_t;
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     void *timeout_ctx);
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd,
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  void *buf, int len)
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ifreq ifr;
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wl_ioctl_t ioc;
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = 0;
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)",
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   drv->ifname, cmd, len, buf);
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ioc.cmd = cmd;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ioc.buf = buf;
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ioc.len = len;
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ);
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ifr.ifr_data = (caddr_t) &ioc;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) {
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (cmd != WLC_GET_MAGIC)
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			perror(ifr.ifr_name);
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d",
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   cmd, ret);
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid)
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0)
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(bssid, 0, ETH_ALEN);
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid)
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wlc_ssid_t s;
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1)
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(ssid, s.SSID, s.SSID_len);
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return s.SSID_len;
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_set_wpa(void *priv, int enable)
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	unsigned int wauth, wsec;
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ether_addr ea;
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&ea, enable ? 0xff : 0, sizeof(ea));
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) ==
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    -1 ||
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1)
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (enable) {
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wauth = PSK_ENABLED;
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wsec = TKIP_ENABLED;
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wauth = 255;
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wsec &= ~(TKIP_ENABLED | AES_ENABLED);
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) ==
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    -1 ||
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1)
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* FIX: magic number / error handling? */
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	broadcom_ioctl(drv, 122, &ea, sizeof(ea));
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_set_key(void *priv, wpa_alg alg,
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       const u8 *addr, int key_idx, int set_tx,
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       const u8 *seq, size_t seq_len,
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       const u8 *key, size_t key_len)
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret;
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wsec_key_t wkt;
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&wkt, 0, sizeof wkt);
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d",
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   set_tx ? "PRIMARY " : "", key_idx, alg);
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (key && key_len > 0)
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len);
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (alg) {
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WPA_ALG_NONE:
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wkt.algo = CRYPTO_ALGO_OFF;
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WPA_ALG_WEP:
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WPA_ALG_TKIP:
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WPA_ALG_CCMP:
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM;
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       * AES_OCB_MSDU, AES_OCB_MPDU? */
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wkt.algo = CRYPTO_ALGO_NALG;
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (seq && seq_len > 0)
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len);
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (addr)
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN);
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wkt.index = key_idx;
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wkt.len = key_len;
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (key && key_len > 0) {
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(wkt.data, key, key_len);
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (key_len == 32) {
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			/* hack hack hack XXX */
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(&wkt.data[16], &key[24], 8);
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(&wkt.data[24], &key[16], 8);
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* wkt.algo = CRYPTO_ALGO_...; */
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY;
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (addr && set_tx)
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(&wkt.ea, addr, sizeof(wkt.ea));
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt));
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (addr && set_tx) {
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* FIX: magic number / error handling? */
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea));
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_broadcom_event_receive(int sock, void *ctx,
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					      void *sock_ctx)
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[8192];
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int left;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wl_wpa_header_t *wwh;
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((left = recv(sock, buf, sizeof buf, 0)) < 0)
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left);
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((size_t) left < sizeof(wl_wpa_header_t))
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wwh = (wl_wpa_header_t *) buf;
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wwh->snap.type != WL_WPA_ETHER_TYPE)
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0)
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (wwh->type) {
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WLC_ASSOC_MSG:
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		left -= WL_WPA_HEADER_LEN;
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)",
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   left);
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (left > 0) {
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			data.assoc_info.resp_ies = os_malloc(left);
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (data.assoc_info.resp_ies == NULL)
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				return;
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(data.assoc_info.resp_ies,
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  buf + WL_WPA_HEADER_LEN, left);
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			data.assoc_info.resp_ies_len = left;
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "BROADCOM: copying %d bytes "
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    "into resp_ies",
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    data.assoc_info.resp_ies, left);
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* data.assoc_info.req_ies = NULL; */
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* data.assoc_info.req_ies_len = 0; */
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WLC_DISASSOC_MSG:
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE");
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WLC_PTK_MIC_MSG:
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE");
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data.michael_mic_failure.unicast = 1;
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case WLC_GTK_MIC_MSG:
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE");
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data.michael_mic_failure.unicast = 0;
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)",
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   wwh->type);
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(data.assoc_info.resp_ies);
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * wpa_driver_broadcom_init(void *ctx, const char *ifname)
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int s;
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct sockaddr_ll ll;
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv;
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ifreq ifr;
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* open socket to kernel */
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("socket");
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* do it */
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror(ifr.ifr_name);
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv = os_zalloc(sizeof(*drv));
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv == NULL)
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->ctx = ctx;
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->ioctl_sock = s;
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2));
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (s < 0) {
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))");
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(drv->ioctl_sock);
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv);
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&ll, 0, sizeof(ll));
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ll.sll_family = AF_PACKET;
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ll.sll_protocol = ntohs(ETH_P_802_2);
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ll.sll_ifindex = ifr.ifr_ifindex;
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ll.sll_hatype = 0;
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ll.sll_pkttype = PACKET_HOST;
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ll.sll_halen = 0;
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("bind(netlink)");
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(s);
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(drv->ioctl_sock);
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv);
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx,
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				 NULL);
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->event_sock = s;
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return drv;
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_broadcom_deinit(void *priv)
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_unregister_read_sock(drv->event_sock);
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	close(drv->event_sock);
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	close(drv->ioctl_sock);
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(drv);
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_set_countermeasures(void *priv,
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						   int enabled)
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if 0
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* FIX: ? */
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled,
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      sizeof(enabled));
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled)
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* SET_EAP_RESTRICT, SET_WEP_RESTRICT */
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int restrict = (enabled ? 1 : 0);
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT,
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   &restrict, sizeof(restrict)) < 0 ||
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT,
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   &restrict, sizeof(restrict)) < 0)
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     void *timeout_ctx)
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_scan(void *priv, const u8 *ssid,
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    size_t ssid_len)
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wlc_ssid_t wst = { 0, "" };
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) {
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wst.SSID_len = ssid_len;
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(wst.SSID, ssid, ssid_len);
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0)
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv,
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       drv->ctx);
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const int frequency_list[] = {
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	2412, 2417, 2422, 2427, 2432, 2437, 2442,
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	2447, 2452, 2457, 2462, 2467, 2472, 2484
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct bss_ie_hdr {
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 elem_id;
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 len;
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 oui[3];
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* u8 oui_type; */
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* u16 version; */
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} __attribute__ ((packed));
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_driver_broadcom_get_scan_results(void *priv,
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     struct wpa_scan_result *results,
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     size_t max_size)
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *buf;
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wl_scan_results_t *wsr;
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wl_bss_info_t *wbi;
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t ap_num;
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf = os_malloc(WLC_IOCTL_MAXLEN);
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (buf == NULL)
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wsr = (wl_scan_results_t *) buf;
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr);
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wsr->version = 107;
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wsr->count = 0;
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) {
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) {
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		int left;
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct bss_ie_hdr *ie;
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(results[ap_num].bssid, &wbi->BSSID, ETH_ALEN);
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(results[ap_num].ssid, wbi->SSID, wbi->SSID_len);
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		results[ap_num].ssid_len = wbi->SSID_len;
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		results[ap_num].freq = frequency_list[wbi->channel - 1];
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* get ie's */
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "BROADCOM: AP IEs",
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    (u8 *) wbi + sizeof(*wbi), wbi->ie_length);
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ie = (struct bss_ie_hdr *) ((u8 *) wbi + sizeof(*wbi));
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (left = wbi->ie_length; left > 0;
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		     left -= (ie->len + 2), ie = (struct bss_ie_hdr *)
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     ((u8 *) ie + 2 + ie->len)) {
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_MSGDUMP, "BROADCOM: IE: id:%x, len:%d",
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   ie->elem_id, ie->len);
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (ie->len >= 3)
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_MSGDUMP,
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "BROADCOM: oui:%02x%02x%02x",
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   ie->oui[0], ie->oui[1], ie->oui[2]);
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (ie->elem_id != 0xdd ||
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    ie->len < 6 ||
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    os_memcmp(ie->oui, WPA_OUI, 3) != 0)
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				continue;
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(results[ap_num].wpa_ie, ie, ie->len + 2);
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			results[ap_num].wpa_ie_len = ie->len + 2;
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length);
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu "
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "BSSes)",
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   wsr->buflen, (unsigned long) ap_num);
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(buf);
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ap_num;
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr,
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					      int reason_code)
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wlc_deauth_t wdt;
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wdt.val = reason_code;
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&wdt.ea, addr, sizeof wdt.ea);
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wdt.res = 0x7fff;
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt,
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      sizeof(wdt));
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr,
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					    int reason_code)
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return broadcom_ioctl(drv, WLC_DISASSOC, 0, 0);
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_driver_broadcom_associate(void *priv,
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      struct wpa_driver_associate_params *params)
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_broadcom_data *drv = priv;
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wlc_ssid_t s;
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int infra = 1;
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int auth = 0;
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int wsec = 4;
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int dummy;
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int wpa_auth;
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	s.SSID_len = params->ssid_len;
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(s.SSID, params->ssid, params->ssid_len);
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (params->pairwise_suite) {
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CIPHER_WEP40:
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CIPHER_WEP104:
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wsec = 1;
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CIPHER_TKIP:
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wsec = 2;
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CIPHER_CCMP:
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wsec = 4;
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wsec = 0;
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (params->key_mgmt_suite) {
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case KEY_MGMT_802_1X:
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_auth = 1;
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case KEY_MGMT_PSK:
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_auth = 2;
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_auth = 255;
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* printf("broadcom_associate: %u %u %u\n", pairwise_suite,
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * group_suite, key_mgmt_suite);
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec));
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * wl join uses wlc_sec_wep here, not wlc_set_wsec */
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 ||
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth,
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   sizeof(wpa_auth)) < 0 ||
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 ||
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 ||
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 ||
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 ||
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0)
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtconst struct wpa_driver_ops wpa_driver_broadcom_ops = {
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.name = "broadcom",
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.desc = "Broadcom wl.o driver",
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.get_bssid = wpa_driver_broadcom_get_bssid,
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.get_ssid = wpa_driver_broadcom_get_ssid,
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.set_wpa = wpa_driver_broadcom_set_wpa,
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.set_key = wpa_driver_broadcom_set_key,
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.init = wpa_driver_broadcom_init,
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.deinit = wpa_driver_broadcom_deinit,
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.set_countermeasures = wpa_driver_broadcom_set_countermeasures,
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.set_drop_unencrypted = wpa_driver_broadcom_set_drop_unencrypted,
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.scan = wpa_driver_broadcom_scan,
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.get_scan_results = wpa_driver_broadcom_get_scan_results,
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.deauthenticate = wpa_driver_broadcom_deauthenticate,
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.disassociate = wpa_driver_broadcom_disassociate,
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	.associate = wpa_driver_broadcom_associate,
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
605