~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to driver_broadcom.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2007-08-26 16:06:57 UTC
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20070826160657-mxk5ivjjh65ptxlr
Tags: upstream-0.6.0+0.5.8
ImportĀ upstreamĀ versionĀ 0.6.0+0.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv,
 
410
                               drv->ctx);
 
411
        return 0;
 
412
}
 
413
 
 
414
 
 
415
static const int frequency_list[] = { 
 
416
        2412, 2417, 2422, 2427, 2432, 2437, 2442,
 
417
        2447, 2452, 2457, 2462, 2467, 2472, 2484 
 
418
};
 
419
 
 
420
struct bss_ie_hdr {
 
421
        u8 elem_id;
 
422
        u8 len;
 
423
        u8 oui[3];
 
424
        /* u8 oui_type; */
 
425
        /* u16 version; */
 
426
} __attribute__ ((packed));
 
427
 
 
428
static int
 
429
wpa_driver_broadcom_get_scan_results(void *priv,
 
430
                                     struct wpa_scan_result *results,
 
431
                                     size_t max_size)
 
432
{
 
433
        struct wpa_driver_broadcom_data *drv = priv;
 
434
        char *buf;
 
435
        wl_scan_results_t *wsr = (wl_scan_results_t *) buf;
 
436
        wl_bss_info_t *wbi;
 
437
        size_t ap_num;
 
438
 
 
439
        buf = os_malloc(WLC_IOCTL_MAXLEN);
 
440
        if (buf == NULL)
 
441
                return -1;
 
442
 
 
443
        wsr = (wl_scan_results_t *) buf;
 
444
 
 
445
        wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr);
 
446
        wsr->version = 107;
 
447
        wsr->count = 0;
 
448
 
 
449
        if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) {
 
450
                os_free(buf);
 
451
                return -1;
 
452
        }
 
453
 
 
454
        os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
 
455
 
 
456
        for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) {
 
457
                int left;
 
458
                struct bss_ie_hdr *ie;
 
459
                
 
460
                os_memcpy(results[ap_num].bssid, &wbi->BSSID, ETH_ALEN);
 
461
                os_memcpy(results[ap_num].ssid, wbi->SSID, wbi->SSID_len);
 
462
                results[ap_num].ssid_len = wbi->SSID_len;
 
463
                results[ap_num].freq = frequency_list[wbi->channel - 1];
 
464
                /* get ie's */
 
465
                wpa_hexdump(MSG_MSGDUMP, "BROADCOM: AP IEs",
 
466
                            (u8 *) wbi + sizeof(*wbi), wbi->ie_length);
 
467
                ie = (struct bss_ie_hdr *) ((u8 *) wbi + sizeof(*wbi));
 
468
                for (left = wbi->ie_length; left > 0;
 
469
                     left -= (ie->len + 2), ie = (struct bss_ie_hdr *)
 
470
                             ((u8 *) ie + 2 + ie->len)) {
 
471
                        wpa_printf(MSG_MSGDUMP, "BROADCOM: IE: id:%x, len:%d",
 
472
                                   ie->elem_id, ie->len);
 
473
                        if (ie->len >= 3) 
 
474
                                wpa_printf(MSG_MSGDUMP,
 
475
                                           "BROADCOM: oui:%02x%02x%02x",
 
476
                                           ie->oui[0], ie->oui[1], ie->oui[2]);
 
477
                        if (ie->elem_id != 0xdd ||
 
478
                            ie->len < 6 ||
 
479
                            os_memcmp(ie->oui, WPA_OUI, 3) != 0)
 
480
                                continue;
 
481
                        os_memcpy(results[ap_num].wpa_ie, ie, ie->len + 2);
 
482
                        results[ap_num].wpa_ie_len = ie->len + 2;
 
483
                        break;
 
484
                }
 
485
 
 
486
                wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length);
 
487
        }
 
488
 
 
489
        wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%d BSSes)",
 
490
                   wsr->buflen, ap_num);
 
491
        
 
492
        os_free(buf);
 
493
        return ap_num;
 
494
}
 
495
 
 
496
static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr,
 
497
                                              int reason_code)
 
498
{
 
499
        struct wpa_driver_broadcom_data *drv = priv;
 
500
        wlc_deauth_t wdt;
 
501
        wdt.val = reason_code;
 
502
        os_memcpy(&wdt.ea, addr, sizeof wdt.ea);
 
503
        wdt.res = 0x7fff;
 
504
        return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt,
 
505
                              sizeof(wdt));
 
506
}
 
507
 
 
508
static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr,
 
509
                                            int reason_code)
 
510
{
 
511
        struct wpa_driver_broadcom_data *drv = priv;
 
512
        return broadcom_ioctl(drv, WLC_DISASSOC, 0, 0);
 
513
}
 
514
 
 
515
static int
 
516
wpa_driver_broadcom_associate(void *priv,
 
517
                              struct wpa_driver_associate_params *params)
 
518
{
 
519
        struct wpa_driver_broadcom_data *drv = priv;
 
520
        wlc_ssid_t s;
 
521
        int infra = 1;
 
522
        int auth = 0;
 
523
        int wsec = 4;
 
524
        int dummy;
 
525
        int wpa_auth;
 
526
        
 
527
        s.SSID_len = params->ssid_len;
 
528
        os_memcpy(s.SSID, params->ssid, params->ssid_len);
 
529
 
 
530
        switch (params->pairwise_suite) {
 
531
        case CIPHER_WEP40:
 
532
        case CIPHER_WEP104:
 
533
                wsec = 1;
 
534
                break;
 
535
 
 
536
        case CIPHER_TKIP:
 
537
                wsec = 2;
 
538
                break;
 
539
 
 
540
        case CIPHER_CCMP:
 
541
                wsec = 4;
 
542
                break;
 
543
 
 
544
        default:
 
545
                wsec = 0;
 
546
                break;
 
547
        }
 
548
 
 
549
        switch (params->key_mgmt_suite) {
 
550
        case KEY_MGMT_802_1X:
 
551
                wpa_auth = 1;
 
552
                break;
 
553
 
 
554
        case KEY_MGMT_PSK:
 
555
                wpa_auth = 2;
 
556
                break;
 
557
 
 
558
        default:
 
559
                wpa_auth = 255;
 
560
                break;
 
561
        }
 
562
 
 
563
        /* printf("broadcom_associate: %u %u %u\n", pairwise_suite,
 
564
         * group_suite, key_mgmt_suite);
 
565
         * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec));
 
566
         * wl join uses wlc_sec_wep here, not wlc_set_wsec */
 
567
 
 
568
        if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 ||
 
569
            broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth,
 
570
                           sizeof(wpa_auth)) < 0 ||
 
571
            broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 ||
 
572
            broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 ||
 
573
            broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 ||
 
574
            broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 ||
 
575
            broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0)
 
576
                return -1;
 
577
 
 
578
        return 0;
 
579
}
 
580
 
 
581
const struct wpa_driver_ops wpa_driver_broadcom_ops = {
 
582
        .name = "broadcom",
 
583
        .desc = "Broadcom wl.o driver",
 
584
        .get_bssid = wpa_driver_broadcom_get_bssid,
 
585
        .get_ssid = wpa_driver_broadcom_get_ssid,
 
586
        .set_wpa = wpa_driver_broadcom_set_wpa,
 
587
        .set_key = wpa_driver_broadcom_set_key,
 
588
        .init = wpa_driver_broadcom_init,
 
589
        .deinit = wpa_driver_broadcom_deinit,
 
590
        .set_countermeasures = wpa_driver_broadcom_set_countermeasures,
 
591
        .set_drop_unencrypted = wpa_driver_broadcom_set_drop_unencrypted,
 
592
        .scan = wpa_driver_broadcom_scan,
 
593
        .get_scan_results = wpa_driver_broadcom_get_scan_results,
 
594
        .deauthenticate = wpa_driver_broadcom_deauthenticate,
 
595
        .disassociate = wpa_driver_broadcom_disassociate,
 
596
        .associate = wpa_driver_broadcom_associate,
 
597
};