~ubuntu-branches/ubuntu/lucid/wpasupplicant/lucid

« back to all changes in this revision

Viewing changes to driver_bsd.c

  • Committer: Bazaar Package Importer
  • Author(s): Kyle McMartin
  • Date: 2005-02-15 00:51:28 UTC
  • Revision ID: james.westby@ubuntu.com-20050215005128-xr4m8owiunur2008
Tags: upstream-0.3.8
ImportĀ upstreamĀ versionĀ 0.3.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * WPA Supplicant - driver interaction with BSD net80211 layer
 
3
 * Copyright (c) 2004, Sam Leffler <sam@errno.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * Alternatively, this software may be distributed under the terms of BSD
 
10
 * license.
 
11
 *
 
12
 * See README and COPYING for more details.
 
13
 */
 
14
 
 
15
#include <stdlib.h>
 
16
#include <stdio.h>
 
17
#include <unistd.h>
 
18
#include <string.h>
 
19
#include <sys/ioctl.h>
 
20
#include <errno.h>
 
21
 
 
22
#include "common.h"
 
23
#include "driver.h"
 
24
#include "driver_wext.h"
 
25
#include "eloop.h"
 
26
#include "wpa_supplicant.h"
 
27
#include "l2_packet.h"
 
28
 
 
29
#include <sys/socket.h>
 
30
#include <net/if.h>
 
31
 
 
32
#include <net80211/ieee80211.h>
 
33
#include <net80211/ieee80211_crypto.h>
 
34
#include <net80211/ieee80211_ioctl.h>
 
35
 
 
36
struct wpa_driver_bsd_data {
 
37
        int     sock;                   /* open socket for 802.11 ioctls */
 
38
        int     route;                  /* routing socket for events */
 
39
        char    ifname[IFNAMSIZ+1];     /* interface name */
 
40
        void    *ctx;
 
41
};
 
42
 
 
43
static int
 
44
set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
 
45
{
 
46
        struct ieee80211req ireq;
 
47
 
 
48
        memset(&ireq, 0, sizeof(ireq));
 
49
        strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
 
50
        ireq.i_type = op;
 
51
        ireq.i_len = arg_len;
 
52
        ireq.i_data = (void *) arg;
 
53
 
 
54
        if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
 
55
                perror("ioctl[SIOCS80211]");
 
56
                return -1;
 
57
        }
 
58
        return 0;
 
59
}
 
60
 
 
61
static int
 
62
get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
 
63
{
 
64
        struct ieee80211req ireq;
 
65
 
 
66
        memset(&ireq, 0, sizeof(ireq));
 
67
        strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
 
68
        ireq.i_type = op;
 
69
        ireq.i_len = arg_len;
 
70
        ireq.i_data = arg;
 
71
 
 
72
        if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
 
73
                perror("ioctl[SIOCG80211]");
 
74
                return -1;
 
75
        }
 
76
        return ireq.i_len;
 
77
}
 
78
 
 
79
static int
 
80
set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
 
81
{
 
82
        struct ieee80211req ireq;
 
83
 
 
84
        memset(&ireq, 0, sizeof(ireq));
 
85
        strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
 
86
        ireq.i_type = op;
 
87
        ireq.i_val = arg;
 
88
 
 
89
        if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
 
90
                perror("ioctl[SIOCS80211]");
 
91
                return -1;
 
92
        }
 
93
        return 0;
 
94
}
 
95
 
 
96
static int
 
97
getifflags(struct wpa_driver_bsd_data *drv, int *flags)
 
98
{
 
99
        struct ifreq ifr;
 
100
 
 
101
        memset(&ifr, 0, sizeof(ifr));
 
102
        strncpy(ifr.ifr_name, drv->ifname, sizeof (ifr.ifr_name));
 
103
        if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
 
104
                perror("SIOCGIFFLAGS");
 
105
                return errno;
 
106
        }
 
107
        *flags = ifr.ifr_flags & 0xffff;
 
108
        return 0;
 
109
}
 
110
 
 
111
static int
 
112
setifflags(struct wpa_driver_bsd_data *drv, int flags)
 
113
{
 
114
        struct ifreq ifr;
 
115
 
 
116
        memset(&ifr, 0, sizeof(ifr));
 
117
        strncpy(ifr.ifr_name, drv->ifname, sizeof (ifr.ifr_name));
 
118
        ifr.ifr_flags = flags & 0xffff;
 
119
        if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
 
120
                perror("SIOCSIFFLAGS");
 
121
                return errno;
 
122
        }
 
123
        return 0;
 
124
}
 
125
 
 
126
static int
 
127
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
 
128
{
 
129
        struct wpa_driver_bsd_data *drv = priv;
 
130
 
 
131
        return get80211var(drv, IEEE80211_IOC_BSSID,
 
132
                bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
 
133
}
 
134
 
 
135
#if 0
 
136
static int
 
137
wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
 
138
{
 
139
        struct wpa_driver_bsd_data *drv = priv;
 
140
 
 
141
        return set80211var(drv, IEEE80211_IOC_BSSID,
 
142
                bssid, IEEE80211_ADDR_LEN);
 
143
}
 
144
#endif
 
145
 
 
146
static int
 
147
wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
 
148
{
 
149
        struct wpa_driver_bsd_data *drv = priv;
 
150
 
 
151
        return get80211var(drv, IEEE80211_IOC_SSID,
 
152
                ssid, IEEE80211_NWID_LEN);
 
153
}
 
154
 
 
155
static int
 
156
wpa_driver_bsd_set_ssid(void *priv, const char *ssid,
 
157
                             size_t ssid_len)
 
158
{
 
159
        struct wpa_driver_bsd_data *drv = priv;
 
160
 
 
161
        return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
 
162
}
 
163
 
 
164
static int
 
165
wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
 
166
        const char *wpa_ie, size_t wpa_ie_len)
 
167
{
 
168
        return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
 
169
}
 
170
 
 
171
static int
 
172
wpa_driver_bsd_set_wpa(void *priv, int enabled)
 
173
{
 
174
        struct wpa_driver_bsd_data *drv = priv;
 
175
        int ret = 0;
 
176
 
 
177
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
 
178
 
 
179
        if (!enabled && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
 
180
                ret = -1;
 
181
        if (set80211param(drv, IEEE80211_IOC_ROAMING, enabled ? 2 : 0) < 0)
 
182
                ret = -1;
 
183
        if (set80211param(drv, IEEE80211_IOC_PRIVACY, enabled) < 0)
 
184
                ret = -1;
 
185
        if (set80211param(drv, IEEE80211_IOC_WPA, enabled ? 3 : 0) < 0)
 
186
                ret = -1;
 
187
 
 
188
        return ret;
 
189
}
 
190
 
 
191
static int
 
192
wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
 
193
                       const unsigned char *addr)
 
194
{
 
195
        struct ieee80211req_del_key wk;
 
196
 
 
197
        wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
 
198
        memset(&wk, 0, sizeof(wk));
 
199
        wk.idk_keyix = key_idx;
 
200
        if (addr != NULL)
 
201
                memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
 
202
 
 
203
        return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
 
204
}
 
205
 
 
206
static int
 
207
wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
 
208
                       const unsigned char *addr, int key_idx, int set_tx,
 
209
                       const u8 *seq, size_t seq_len,
 
210
                       const u8 *key, size_t key_len)
 
211
{
 
212
        struct wpa_driver_bsd_data *drv = priv;
 
213
        struct ieee80211req_key wk;
 
214
        char *alg_name;
 
215
        u_int8_t cipher;
 
216
 
 
217
        if (alg == WPA_ALG_NONE)
 
218
                return wpa_driver_bsd_del_key(drv, key_idx, addr);
 
219
 
 
220
        switch (alg) {
 
221
        case WPA_ALG_WEP:
 
222
                alg_name = "WEP";
 
223
                cipher = IEEE80211_CIPHER_WEP;
 
224
                break;
 
225
        case WPA_ALG_TKIP:
 
226
                alg_name = "TKIP";
 
227
                cipher = IEEE80211_CIPHER_TKIP;
 
228
                break;
 
229
        case WPA_ALG_CCMP:
 
230
                alg_name = "CCMP";
 
231
                cipher = IEEE80211_CIPHER_AES_CCM;
 
232
                break;
 
233
        default:
 
234
                wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
 
235
                        __FUNCTION__, alg);
 
236
                return -1;
 
237
        }
 
238
 
 
239
        wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%d "
 
240
                   "key_len=%d", __FUNCTION__, alg_name, key_idx, set_tx,
 
241
                   seq_len, key_len);
 
242
 
 
243
        if (seq_len > sizeof(u_int64_t)) {
 
244
                wpa_printf(MSG_DEBUG, "%s: seq_len %d too big",
 
245
                        __FUNCTION__, seq_len);
 
246
                return -2;
 
247
        }
 
248
        if (key_len > sizeof(wk.ik_keydata)) {
 
249
                wpa_printf(MSG_DEBUG, "%s: key length %d too big",
 
250
                        __FUNCTION__, key_len);
 
251
                return -3;
 
252
        }
 
253
 
 
254
        memset(&wk, 0, sizeof(wk));
 
255
        wk.ik_type = cipher;
 
256
        wk.ik_flags = IEEE80211_KEY_RECV;
 
257
        if (set_tx) {
 
258
                wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
 
259
                memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
 
260
        } else
 
261
                memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
 
262
        wk.ik_keyix = key_idx;
 
263
        wk.ik_keylen = key_len;
 
264
        memcpy(&wk.ik_keyrsc, seq, seq_len);
 
265
        memcpy(wk.ik_keydata, key, key_len);
 
266
 
 
267
        return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
 
268
}
 
269
 
 
270
static int
 
271
wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
 
272
{
 
273
        struct wpa_driver_bsd_data *drv = priv;
 
274
 
 
275
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
 
276
        return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
 
277
}
 
278
 
 
279
 
 
280
static int
 
281
wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
 
282
{
 
283
        struct wpa_driver_bsd_data *drv = priv;
 
284
 
 
285
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
 
286
        return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
 
287
}
 
288
 
 
289
static int
 
290
wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
 
291
{
 
292
        struct wpa_driver_bsd_data *drv = priv;
 
293
        struct ieee80211req_mlme mlme;
 
294
 
 
295
        wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
296
        mlme.im_op = IEEE80211_MLME_DEAUTH;
 
297
        mlme.im_reason = reason_code;
 
298
        memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
 
299
        return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
 
300
}
 
301
 
 
302
static int
 
303
wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
 
304
{
 
305
        struct wpa_driver_bsd_data *drv = priv;
 
306
        struct ieee80211req_mlme mlme;
 
307
 
 
308
        wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
309
        mlme.im_op = IEEE80211_MLME_DISASSOC;
 
310
        mlme.im_reason = reason_code;
 
311
        memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
 
312
        return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
 
313
}
 
314
 
 
315
static int
 
316
wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
 
317
{
 
318
        struct wpa_driver_bsd_data *drv = priv;
 
319
        struct ieee80211req_mlme mlme;
 
320
 
 
321
        int ret = 0;
 
322
 
 
323
        wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
324
 
 
325
        /*
 
326
         * NB: Don't need to set the freq or cipher-related state as
 
327
         *     this is implied by the bssid which is used to locate
 
328
         *     the scanned node state which holds it.  The ssid is
 
329
         *     needed to disambiguate an AP that broadcasts multiple
 
330
         *     ssid's but uses the same bssid.
 
331
         */
 
332
        /* XXX error handling is wrong but unclear what to do... */
 
333
        if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
 
334
                ret = -1;
 
335
        if (wpa_driver_bsd_set_ssid(drv, params->ssid, params->ssid_len) < 0)
 
336
                ret = -1;
 
337
        memset(&mlme, 0, sizeof(mlme));
 
338
        mlme.im_op = IEEE80211_MLME_ASSOC;
 
339
        memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
 
340
        if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
 
341
                ret = -1;
 
342
 
 
343
        return ret;
 
344
}
 
345
 
 
346
static int
 
347
wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
 
348
{
 
349
        struct wpa_driver_bsd_data *drv = priv;
 
350
        int flags;
 
351
 
 
352
        /* NB: interface must be marked UP to do a scan */
 
353
        if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
 
354
                return -1;
 
355
 
 
356
        /* set desired ssid before scan */
 
357
        if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
 
358
                return -1;
 
359
 
 
360
        /* NB: net80211 delivers a scan complete event so no need to poll */
 
361
        return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
 
362
}
 
363
 
 
364
#include <net/route.h>
 
365
#include <net80211/ieee80211_freebsd.h>
 
366
 
 
367
static void
 
368
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
 
369
{
 
370
        char buf[2048];
 
371
        struct if_announcemsghdr *ifan;
 
372
        struct rt_msghdr *rtm;
 
373
        union wpa_event_data event;
 
374
        struct ieee80211_michael_event *mic;
 
375
        int n;
 
376
 
 
377
        n = read(sock, buf, sizeof(buf));
 
378
        if (n < 0) {
 
379
                if (errno != EINTR && errno != EAGAIN)
 
380
                        perror("read(PF_ROUTE)");
 
381
                return;
 
382
        }
 
383
 
 
384
        rtm = (struct rt_msghdr *) buf;
 
385
        if (rtm->rtm_version != RTM_VERSION) {
 
386
                wpa_printf(MSG_DEBUG, "Routing message version %d not "
 
387
                        "understood\n", rtm->rtm_version);
 
388
                return;
 
389
        }
 
390
        ifan = (struct if_announcemsghdr *) rtm;
 
391
        switch (rtm->rtm_type) {
 
392
        case RTM_IFANNOUNCE:
 
393
                memset(&event, 0, sizeof(event));
 
394
                /* XXX name buffer must be >= IFNAMSIZ */
 
395
                /* XXX check return value */
 
396
                if_indextoname(ifan->ifan_index, event.interface_status.ifname);
 
397
                switch (ifan->ifan_what) {
 
398
                case IFAN_ARRIVAL:
 
399
                        event.interface_status.ievent = EVENT_INTERFACE_ADDED;
 
400
                        break;
 
401
                case IFAN_DEPARTURE:
 
402
                        event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
 
403
                default:
 
404
                        return;
 
405
                }
 
406
                wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
 
407
                           event.interface_status.ifname,
 
408
                           ifan->ifan_what == IFAN_DEPARTURE ?
 
409
                                "removed" : "added");
 
410
                wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
 
411
                break;
 
412
        case RTM_IEEE80211:
 
413
                switch (ifan->ifan_what) {
 
414
                case RTM_IEEE80211_ASSOC:
 
415
                        wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
 
416
                        break;
 
417
                case RTM_IEEE80211_DISASSOC:
 
418
                        wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
 
419
                        break;
 
420
                case RTM_IEEE80211_SCAN:
 
421
                        wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
 
422
                        break;
 
423
                case RTM_IEEE80211_REASSOC:
 
424
                case RTM_IEEE80211_REPLAY:
 
425
                        /* ignore */
 
426
                        break;
 
427
                case RTM_IEEE80211_MICHAEL:
 
428
                        mic = (struct ieee80211_michael_event *) &ifan[1];
 
429
                        wpa_printf(MSG_DEBUG,
 
430
                                "Michael MIC failure wireless event: "
 
431
                                "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
 
432
                                MAC2STR(mic->iev_src));
 
433
 
 
434
                        memset(&event, 0, sizeof(event));
 
435
                        event.michael_mic_failure.unicast =
 
436
                                !IEEE80211_IS_MULTICAST(mic->iev_dst);
 
437
                        wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
 
438
                                &event);
 
439
                        break;
 
440
                }
 
441
                break;
 
442
        }
 
443
}
 
444
 
 
445
/* Compare function for sorting scan results. Return >0 if @b is consider
 
446
 * better. */
 
447
static int
 
448
wpa_scan_result_compar(const void *a, const void *b)
 
449
{
 
450
        const struct wpa_scan_result *wa = a;
 
451
        const struct wpa_scan_result *wb = b;
 
452
 
 
453
        /* WPA/WPA2 support preferred */
 
454
        if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
 
455
            !(wa->wpa_ie_len || wa->rsn_ie_len))
 
456
                return 1;
 
457
        if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
 
458
            (wa->wpa_ie_len || wa->rsn_ie_len))
 
459
                return -1;
 
460
 
 
461
        /* privacy support preferred */
 
462
        if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
 
463
            (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
 
464
                return 1;
 
465
        if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
 
466
            (wb->caps & IEEE80211_CAPINFO_PRIVACY))
 
467
                return -1;
 
468
 
 
469
        /* best/max rate preferred if signal level close enough XXX */
 
470
        if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
 
471
                return wb->maxrate - wa->maxrate;
 
472
 
 
473
        /* use freq for channel preference */
 
474
 
 
475
        /* all things being equal, use signal level */
 
476
        return wb->level - wa->level;
 
477
}
 
478
 
 
479
static int
 
480
getmaxrate(uint8_t rates[15], uint8_t nrates)
 
481
{
 
482
        int i, maxrate = -1;
 
483
 
 
484
        for (i = 0; i < nrates; i++) {
 
485
                int rate = rates[i] & IEEE80211_RATE_VAL;
 
486
                if (rate > maxrate)
 
487
                        rate = maxrate;
 
488
        }
 
489
        return maxrate;
 
490
}
 
491
 
 
492
/* unalligned little endian access */     
 
493
#define LE_READ_4(p)                                    \
 
494
        ((u_int32_t)                                    \
 
495
         ((((const u_int8_t *)(p))[0]      ) |          \
 
496
          (((const u_int8_t *)(p))[1] <<  8) |          \
 
497
          (((const u_int8_t *)(p))[2] << 16) |          \
 
498
          (((const u_int8_t *)(p))[3] << 24)))
 
499
 
 
500
static int __inline
 
501
iswpaoui(const u_int8_t *frm)
 
502
{
 
503
        return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
 
504
}
 
505
 
 
506
static int
 
507
wpa_driver_bsd_get_scan_results(void *priv,
 
508
                                     struct wpa_scan_result *results,
 
509
                                     size_t max_size)
 
510
{
 
511
#define min(a,b)        ((a)>(b)?(b):(a))
 
512
        struct wpa_driver_bsd_data *drv = priv;
 
513
        uint8_t buf[24*1024];
 
514
        uint8_t *cp, *vp;
 
515
        struct ieee80211req_scan_result *sr;
 
516
        struct wpa_scan_result *wsr;
 
517
        int len, ielen;
 
518
 
 
519
        memset(results, 0, max_size * sizeof(struct wpa_scan_result));
 
520
 
 
521
        len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
 
522
        if (len < 0)
 
523
                return -1;
 
524
        cp = buf;
 
525
        wsr = results;
 
526
        while (len >= sizeof(struct ieee80211req_scan_result)) {
 
527
                sr = (struct ieee80211req_scan_result *) cp;
 
528
                memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
 
529
                wsr->ssid_len = sr->isr_ssid_len;
 
530
                wsr->freq = sr->isr_freq;
 
531
                wsr->noise = sr->isr_noise;
 
532
                wsr->qual = sr->isr_rssi;
 
533
                wsr->level = 0;         /* XXX? */
 
534
                wsr->caps = sr->isr_capinfo;
 
535
                wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
 
536
                vp = (u_int8_t *)(sr+1);
 
537
                memcpy(wsr->ssid, vp, sr->isr_ssid_len);
 
538
                if (sr->isr_ie_len > 0) {
 
539
                        vp += sr->isr_ssid_len;
 
540
                        ielen = sr->isr_ie_len;
 
541
                        while (ielen > 0) {
 
542
                                switch (vp[0]) {
 
543
                                case IEEE80211_ELEMID_VENDOR:
 
544
                                        if (!iswpaoui(vp))
 
545
                                                break;
 
546
                                        wsr->wpa_ie_len =
 
547
                                            min(2+vp[1], SSID_MAX_WPA_IE_LEN);
 
548
                                        memcpy(wsr->wpa_ie, vp, wsr->wpa_ie_len);
 
549
                                        break;
 
550
                                case IEEE80211_ELEMID_RSN:
 
551
                                        wsr->rsn_ie_len =
 
552
                                            min(2+vp[1], SSID_MAX_WPA_IE_LEN);
 
553
                                        memcpy(wsr->rsn_ie, vp, wsr->rsn_ie_len);
 
554
                                        break;
 
555
                                }
 
556
                                ielen -= 2+vp[1];
 
557
                                vp += 2+vp[1];
 
558
                        }
 
559
                }
 
560
 
 
561
                cp += sr->isr_len, len -= sr->isr_len;
 
562
                wsr++;
 
563
        }
 
564
        qsort(results, wsr - results, sizeof(struct wpa_scan_result),
 
565
              wpa_scan_result_compar);
 
566
 
 
567
        wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
 
568
                   len, wsr - results);
 
569
 
 
570
        return wsr - results;
 
571
#undef min
 
572
}
 
573
 
 
574
static void *
 
575
wpa_driver_bsd_init(void *ctx, const char *ifname)
 
576
{
 
577
        struct wpa_driver_bsd_data *drv;
 
578
 
 
579
        drv = malloc(sizeof(*drv));
 
580
        if (drv == NULL)
 
581
                return NULL;
 
582
        memset(drv, 0, sizeof(*drv));
 
583
        drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
 
584
        if (drv->sock < 0) {
 
585
                free(drv);
 
586
                return NULL;
 
587
        }
 
588
        drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
 
589
        if (drv->route < 0) {
 
590
                close(drv->sock);
 
591
                free(drv);
 
592
                return NULL;
 
593
        }
 
594
        eloop_register_read_sock(drv->route,
 
595
                wpa_driver_bsd_event_receive, ctx, NULL);
 
596
 
 
597
        drv->ctx = ctx;
 
598
        strncpy(drv->ifname, ifname, sizeof(drv->ifname));
 
599
 
 
600
        return drv;
 
601
}
 
602
 
 
603
static void
 
604
wpa_driver_bsd_deinit(void *priv)
 
605
{
 
606
        struct wpa_driver_bsd_data *drv = priv;
 
607
        int flags;
 
608
 
 
609
        /* NB: mark interface down */
 
610
        if (getifflags(drv, &flags) == 0)
 
611
                (void) setifflags(drv, flags &~ IFF_UP);
 
612
 
 
613
        (void) close(drv->route);               /* ioctl socket */
 
614
        (void) close(drv->sock);                /* event socket */
 
615
        free(drv);
 
616
}
 
617
 
 
618
 
 
619
struct wpa_driver_ops wpa_driver_bsd_ops = {
 
620
        .name                   = "bsd",
 
621
        .desc                   = "BSD 802.11 support (Atheros, etc.)",
 
622
        .init                   = wpa_driver_bsd_init,
 
623
        .deinit                 = wpa_driver_bsd_deinit,
 
624
        .get_bssid              = wpa_driver_bsd_get_bssid,
 
625
        .get_ssid               = wpa_driver_bsd_get_ssid,
 
626
        .set_wpa                = wpa_driver_bsd_set_wpa,
 
627
        .set_key                = wpa_driver_bsd_set_key,
 
628
        .set_countermeasures    = wpa_driver_bsd_set_countermeasures,
 
629
        .set_drop_unencrypted   = wpa_driver_bsd_set_drop_unencrypted,
 
630
        .scan                   = wpa_driver_bsd_scan,
 
631
        .get_scan_results       = wpa_driver_bsd_get_scan_results,
 
632
        .deauthenticate         = wpa_driver_bsd_deauthenticate,
 
633
        .disassociate           = wpa_driver_bsd_disassociate,
 
634
        .associate              = wpa_driver_bsd_associate,
 
635
};