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

« back to all changes in this revision

Viewing changes to src/drivers/driver_broadcom.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

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