~ubuntu-branches/ubuntu/precise/wpasupplicant/precise-security

« back to all changes in this revision

Viewing changes to .pc/21_kfreebsd.patch/src/drivers/driver_bsd.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 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 "includes.h"
16
 
#include <sys/ioctl.h>
17
 
 
18
 
#include "common.h"
19
 
#include "driver.h"
20
 
#include "eloop.h"
21
 
#include "ieee802_11_defs.h"
22
 
 
23
 
#include <net/if.h>
24
 
 
25
 
#ifdef __NetBSD__
26
 
#include <net/if_ether.h>
27
 
#define COMPAT_FREEBSD_NET80211
28
 
#else
29
 
#include <net/ethernet.h>
30
 
#endif
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
 
        unsigned int ifindex;           /* interface index */
41
 
        void    *ctx;
42
 
        int     prev_roaming;           /* roaming state to restore on deinit */
43
 
        int     prev_privacy;           /* privacy state to restore on deinit */
44
 
        int     prev_wpa;               /* wpa state to restore on deinit */
45
 
};
46
 
 
47
 
static int
48
 
set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
49
 
{
50
 
        struct ieee80211req ireq;
51
 
 
52
 
        os_memset(&ireq, 0, sizeof(ireq));
53
 
        os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
54
 
        ireq.i_type = op;
55
 
        ireq.i_len = arg_len;
56
 
        ireq.i_data = (void *) arg;
57
 
 
58
 
        if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
59
 
                fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
60
 
                        op, arg_len, strerror(errno));
61
 
                return -1;
62
 
        }
63
 
        return 0;
64
 
}
65
 
 
66
 
static int
67
 
get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
68
 
{
69
 
        struct ieee80211req ireq;
70
 
 
71
 
        os_memset(&ireq, 0, sizeof(ireq));
72
 
        os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
73
 
        ireq.i_type = op;
74
 
        ireq.i_len = arg_len;
75
 
        ireq.i_data = arg;
76
 
 
77
 
        if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
78
 
                fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
79
 
                        op, arg_len, strerror(errno));
80
 
                return -1;
81
 
        }
82
 
        return ireq.i_len;
83
 
}
84
 
 
85
 
static int
86
 
set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
87
 
{
88
 
        struct ieee80211req ireq;
89
 
 
90
 
        os_memset(&ireq, 0, sizeof(ireq));
91
 
        os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
92
 
        ireq.i_type = op;
93
 
        ireq.i_val = arg;
94
 
 
95
 
        if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
96
 
                fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
97
 
                        op, arg, strerror(errno));
98
 
                return -1;
99
 
        }
100
 
        return 0;
101
 
}
102
 
 
103
 
static int
104
 
get80211param(struct wpa_driver_bsd_data *drv, int op)
105
 
{
106
 
        struct ieee80211req ireq;
107
 
 
108
 
        os_memset(&ireq, 0, sizeof(ireq));
109
 
        os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
110
 
        ireq.i_type = op;
111
 
 
112
 
        if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
113
 
                fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
114
 
                        op, strerror(errno));
115
 
                return -1;
116
 
        }
117
 
        return ireq.i_val;
118
 
}
119
 
 
120
 
static int
121
 
getifflags(struct wpa_driver_bsd_data *drv, int *flags)
122
 
{
123
 
        struct ifreq ifr;
124
 
 
125
 
        os_memset(&ifr, 0, sizeof(ifr));
126
 
        os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
127
 
        if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
128
 
                perror("SIOCGIFFLAGS");
129
 
                return errno;
130
 
        }
131
 
        *flags = ifr.ifr_flags & 0xffff;
132
 
        return 0;
133
 
}
134
 
 
135
 
static int
136
 
setifflags(struct wpa_driver_bsd_data *drv, int flags)
137
 
{
138
 
        struct ifreq ifr;
139
 
 
140
 
        os_memset(&ifr, 0, sizeof(ifr));
141
 
        os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
142
 
        ifr.ifr_flags = flags & 0xffff;
143
 
        if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
144
 
                perror("SIOCSIFFLAGS");
145
 
                return errno;
146
 
        }
147
 
        return 0;
148
 
}
149
 
 
150
 
static int
151
 
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
152
 
{
153
 
        struct wpa_driver_bsd_data *drv = priv;
154
 
 
155
 
        return get80211var(drv, IEEE80211_IOC_BSSID,
156
 
                bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
157
 
}
158
 
 
159
 
#if 0
160
 
static int
161
 
wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
162
 
{
163
 
        struct wpa_driver_bsd_data *drv = priv;
164
 
 
165
 
        return set80211var(drv, IEEE80211_IOC_BSSID,
166
 
                bssid, IEEE80211_ADDR_LEN);
167
 
}
168
 
#endif
169
 
 
170
 
static int
171
 
wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
172
 
{
173
 
        struct wpa_driver_bsd_data *drv = priv;
174
 
 
175
 
        return get80211var(drv, IEEE80211_IOC_SSID,
176
 
                ssid, IEEE80211_NWID_LEN);
177
 
}
178
 
 
179
 
static int
180
 
wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid,
181
 
                             size_t ssid_len)
182
 
{
183
 
        struct wpa_driver_bsd_data *drv = priv;
184
 
 
185
 
        return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
186
 
}
187
 
 
188
 
static int
189
 
wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
190
 
        const u8 *wpa_ie, size_t wpa_ie_len)
191
 
{
192
 
        return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
193
 
}
194
 
 
195
 
static int
196
 
wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
197
 
{
198
 
        struct wpa_driver_bsd_data *drv = priv;
199
 
        int ret = 0;
200
 
 
201
 
        wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
202
 
                __FUNCTION__, wpa, privacy);
203
 
 
204
 
        if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
205
 
                ret = -1;
206
 
        if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
207
 
                ret = -1;
208
 
        if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
209
 
                ret = -1;
210
 
 
211
 
        return ret;
212
 
}
213
 
 
214
 
static int
215
 
wpa_driver_bsd_set_wpa(void *priv, int enabled)
216
 
{
217
 
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
218
 
 
219
 
        return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
220
 
}
221
 
 
222
 
static int
223
 
wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
224
 
                       const unsigned char *addr)
225
 
{
226
 
        struct ieee80211req_del_key wk;
227
 
 
228
 
        os_memset(&wk, 0, sizeof(wk));
229
 
        if (addr != NULL &&
230
 
            bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) {
231
 
                struct ether_addr ea;
232
 
 
233
 
                os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
234
 
                wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d",
235
 
                        __func__, ether_ntoa(&ea), key_idx);
236
 
                os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
237
 
                wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE;
238
 
        } else {
239
 
                wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx);
240
 
                wk.idk_keyix = key_idx;
241
 
        }
242
 
        return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
243
 
}
244
 
 
245
 
static int
246
 
wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
247
 
                       const unsigned char *addr, int key_idx, int set_tx,
248
 
                       const u8 *seq, size_t seq_len,
249
 
                       const u8 *key, size_t key_len)
250
 
{
251
 
        struct wpa_driver_bsd_data *drv = priv;
252
 
        struct ieee80211req_key wk;
253
 
        struct ether_addr ea;
254
 
        char *alg_name;
255
 
        u_int8_t cipher;
256
 
 
257
 
        if (alg == WPA_ALG_NONE)
258
 
                return wpa_driver_bsd_del_key(drv, key_idx, addr);
259
 
 
260
 
        switch (alg) {
261
 
        case WPA_ALG_WEP:
262
 
                alg_name = "WEP";
263
 
                cipher = IEEE80211_CIPHER_WEP;
264
 
                break;
265
 
        case WPA_ALG_TKIP:
266
 
                alg_name = "TKIP";
267
 
                cipher = IEEE80211_CIPHER_TKIP;
268
 
                break;
269
 
        case WPA_ALG_CCMP:
270
 
                alg_name = "CCMP";
271
 
                cipher = IEEE80211_CIPHER_AES_CCM;
272
 
                break;
273
 
        default:
274
 
                wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
275
 
                        __func__, alg);
276
 
                return -1;
277
 
        }
278
 
 
279
 
        os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
280
 
        wpa_printf(MSG_DEBUG,
281
 
                "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
282
 
                __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
283
 
                seq_len, key_len);
284
 
 
285
 
        if (seq_len > sizeof(u_int64_t)) {
286
 
                wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
287
 
                        __func__, seq_len);
288
 
                return -2;
289
 
        }
290
 
        if (key_len > sizeof(wk.ik_keydata)) {
291
 
                wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
292
 
                        __func__, key_len);
293
 
                return -3;
294
 
        }
295
 
 
296
 
        os_memset(&wk, 0, sizeof(wk));
297
 
        wk.ik_type = cipher;
298
 
        wk.ik_flags = IEEE80211_KEY_RECV;
299
 
        if (set_tx)
300
 
                wk.ik_flags |= IEEE80211_KEY_XMIT;
301
 
        os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
302
 
        /*
303
 
         * Deduce whether group/global or unicast key by checking
304
 
         * the address (yech).  Note also that we can only mark global
305
 
         * keys default; doing this for a unicast key is an error.
306
 
         */
307
 
        if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
308
 
                wk.ik_flags |= IEEE80211_KEY_GROUP;
309
 
                wk.ik_keyix = key_idx;
310
 
        } else {
311
 
                wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
312
 
        }
313
 
        if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
314
 
                wk.ik_flags |= IEEE80211_KEY_DEFAULT;
315
 
        wk.ik_keylen = key_len;
316
 
        os_memcpy(&wk.ik_keyrsc, seq, seq_len);
317
 
        os_memcpy(wk.ik_keydata, key, key_len);
318
 
 
319
 
        return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
320
 
}
321
 
 
322
 
static int
323
 
wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
324
 
{
325
 
        struct wpa_driver_bsd_data *drv = priv;
326
 
 
327
 
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
328
 
        return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
329
 
}
330
 
 
331
 
 
332
 
static int
333
 
wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
334
 
{
335
 
        struct wpa_driver_bsd_data *drv = priv;
336
 
 
337
 
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
338
 
        return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
339
 
}
340
 
 
341
 
static int
342
 
wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
343
 
{
344
 
        struct wpa_driver_bsd_data *drv = priv;
345
 
        struct ieee80211req_mlme mlme;
346
 
 
347
 
        wpa_printf(MSG_DEBUG, "%s", __func__);
348
 
        os_memset(&mlme, 0, sizeof(mlme));
349
 
        mlme.im_op = IEEE80211_MLME_DEAUTH;
350
 
        mlme.im_reason = reason_code;
351
 
        os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
352
 
        return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
353
 
}
354
 
 
355
 
static int
356
 
wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
357
 
{
358
 
        struct wpa_driver_bsd_data *drv = priv;
359
 
        struct ieee80211req_mlme mlme;
360
 
 
361
 
        wpa_printf(MSG_DEBUG, "%s", __func__);
362
 
        os_memset(&mlme, 0, sizeof(mlme));
363
 
        mlme.im_op = IEEE80211_MLME_DISASSOC;
364
 
        mlme.im_reason = reason_code;
365
 
        os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
366
 
        return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
367
 
}
368
 
 
369
 
static int
370
 
wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
371
 
{
372
 
        struct wpa_driver_bsd_data *drv = priv;
373
 
        struct ieee80211req_mlme mlme;
374
 
        int privacy;
375
 
 
376
 
        wpa_printf(MSG_DEBUG,
377
 
                "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
378
 
                , __func__
379
 
                , params->ssid_len, params->ssid
380
 
                , params->wpa_ie_len
381
 
                , params->pairwise_suite
382
 
                , params->group_suite
383
 
                , params->key_mgmt_suite
384
 
        );
385
 
 
386
 
        /* XXX error handling is wrong but unclear what to do... */
387
 
        if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
388
 
                return -1;
389
 
 
390
 
        privacy = !(params->pairwise_suite == CIPHER_NONE &&
391
 
            params->group_suite == CIPHER_NONE &&
392
 
            params->key_mgmt_suite == KEY_MGMT_NONE &&
393
 
            params->wpa_ie_len == 0);
394
 
        wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
395
 
 
396
 
        if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
397
 
                return -1;
398
 
 
399
 
        if (params->wpa_ie_len &&
400
 
            set80211param(drv, IEEE80211_IOC_WPA,
401
 
                          params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
402
 
                return -1;
403
 
 
404
 
        os_memset(&mlme, 0, sizeof(mlme));
405
 
        mlme.im_op = IEEE80211_MLME_ASSOC;
406
 
        if (params->ssid != NULL)
407
 
                os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
408
 
        mlme.im_ssid_len = params->ssid_len;
409
 
        if (params->bssid != NULL)
410
 
                os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
411
 
        if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
412
 
                return -1;
413
 
        return 0;
414
 
}
415
 
 
416
 
static int
417
 
wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
418
 
{
419
 
        struct wpa_driver_bsd_data *drv = priv;
420
 
        int authmode;
421
 
 
422
 
        if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
423
 
            (auth_alg & AUTH_ALG_SHARED_KEY))
424
 
                authmode = IEEE80211_AUTH_AUTO;
425
 
        else if (auth_alg & AUTH_ALG_SHARED_KEY)
426
 
                authmode = IEEE80211_AUTH_SHARED;
427
 
        else
428
 
                authmode = IEEE80211_AUTH_OPEN;
429
 
 
430
 
        return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
431
 
}
432
 
 
433
 
static int
434
 
wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
435
 
{
436
 
        struct wpa_driver_bsd_data *drv = priv;
437
 
        int flags;
438
 
 
439
 
        /* NB: interface must be marked UP to do a scan */
440
 
        if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
441
 
                return -1;
442
 
 
443
 
        /* set desired ssid before scan */
444
 
        if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
445
 
                return -1;
446
 
 
447
 
        /* NB: net80211 delivers a scan complete event so no need to poll */
448
 
        return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
449
 
}
450
 
 
451
 
#include <net/route.h>
452
 
#if __FreeBSD__
453
 
#include <net80211/ieee80211_freebsd.h>
454
 
#endif
455
 
#if __NetBSD__
456
 
#include <net80211/ieee80211_netbsd.h>
457
 
#endif
458
 
 
459
 
static void
460
 
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
461
 
{
462
 
        struct wpa_driver_bsd_data *drv = sock_ctx;
463
 
        char buf[2048];
464
 
        struct if_announcemsghdr *ifan;
465
 
        struct if_msghdr *ifm;
466
 
        struct rt_msghdr *rtm;
467
 
        union wpa_event_data event;
468
 
        struct ieee80211_michael_event *mic;
469
 
        int n;
470
 
 
471
 
        n = read(sock, buf, sizeof(buf));
472
 
        if (n < 0) {
473
 
                if (errno != EINTR && errno != EAGAIN)
474
 
                        perror("read(PF_ROUTE)");
475
 
                return;
476
 
        }
477
 
 
478
 
        rtm = (struct rt_msghdr *) buf;
479
 
        if (rtm->rtm_version != RTM_VERSION) {
480
 
                wpa_printf(MSG_DEBUG, "Routing message version %d not "
481
 
                        "understood\n", rtm->rtm_version);
482
 
                return;
483
 
        }
484
 
        os_memset(&event, 0, sizeof(event));
485
 
        switch (rtm->rtm_type) {
486
 
        case RTM_IFANNOUNCE:
487
 
                ifan = (struct if_announcemsghdr *) rtm;
488
 
                if (ifan->ifan_index != drv->ifindex)
489
 
                        break;
490
 
                strlcpy(event.interface_status.ifname, drv->ifname,
491
 
                        sizeof(event.interface_status.ifname));
492
 
                switch (ifan->ifan_what) {
493
 
                case IFAN_DEPARTURE:
494
 
                        event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
495
 
                default:
496
 
                        return;
497
 
                }
498
 
                wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
499
 
                           event.interface_status.ifname,
500
 
                           ifan->ifan_what == IFAN_DEPARTURE ?
501
 
                                "removed" : "added");
502
 
                wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
503
 
                break;
504
 
        case RTM_IEEE80211:
505
 
                ifan = (struct if_announcemsghdr *) rtm;
506
 
                if (ifan->ifan_index != drv->ifindex)
507
 
                        break;
508
 
                switch (ifan->ifan_what) {
509
 
                case RTM_IEEE80211_ASSOC:
510
 
                case RTM_IEEE80211_REASSOC:
511
 
                        wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
512
 
                        break;
513
 
                case RTM_IEEE80211_DISASSOC:
514
 
                        wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
515
 
                        break;
516
 
                case RTM_IEEE80211_SCAN:
517
 
                        wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
518
 
                        break;
519
 
                case RTM_IEEE80211_REPLAY:
520
 
                        /* ignore */
521
 
                        break;
522
 
                case RTM_IEEE80211_MICHAEL:
523
 
                        mic = (struct ieee80211_michael_event *) &ifan[1];
524
 
                        wpa_printf(MSG_DEBUG,
525
 
                                "Michael MIC failure wireless event: "
526
 
                                "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
527
 
                                MAC2STR(mic->iev_src));
528
 
 
529
 
                        os_memset(&event, 0, sizeof(event));
530
 
                        event.michael_mic_failure.unicast =
531
 
                                !IEEE80211_IS_MULTICAST(mic->iev_dst);
532
 
                        wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
533
 
                                &event);
534
 
                        break;
535
 
                }
536
 
                break;
537
 
        case RTM_IFINFO:
538
 
                ifm = (struct if_msghdr *) rtm;
539
 
                if (ifm->ifm_index != drv->ifindex)
540
 
                        break;
541
 
                if ((rtm->rtm_flags & RTF_UP) == 0) {
542
 
                        strlcpy(event.interface_status.ifname, drv->ifname,
543
 
                                sizeof(event.interface_status.ifname));
544
 
                        event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
545
 
                        wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
546
 
                                   event.interface_status.ifname);
547
 
                        wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
548
 
                }
549
 
                break;
550
 
        }
551
 
}
552
 
 
553
 
/* Compare function for sorting scan results. Return >0 if @b is consider
554
 
 * better. */
555
 
static int
556
 
wpa_scan_result_compar(const void *a, const void *b)
557
 
{
558
 
        const struct wpa_scan_result *wa = a;
559
 
        const struct wpa_scan_result *wb = b;
560
 
 
561
 
        /* WPA/WPA2 support preferred */
562
 
        if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
563
 
            !(wa->wpa_ie_len || wa->rsn_ie_len))
564
 
                return 1;
565
 
        if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
566
 
            (wa->wpa_ie_len || wa->rsn_ie_len))
567
 
                return -1;
568
 
 
569
 
        /* privacy support preferred */
570
 
        if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
571
 
            (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
572
 
                return 1;
573
 
        if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
574
 
            (wb->caps & IEEE80211_CAPINFO_PRIVACY))
575
 
                return -1;
576
 
 
577
 
        /* best/max rate preferred if signal level close enough XXX */
578
 
        if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
579
 
                return wb->maxrate - wa->maxrate;
580
 
 
581
 
        /* use freq for channel preference */
582
 
 
583
 
        /* all things being equal, use signal level */
584
 
        return wb->level - wa->level;
585
 
}
586
 
 
587
 
static int
588
 
getmaxrate(uint8_t rates[15], uint8_t nrates)
589
 
{
590
 
        int i, maxrate = -1;
591
 
 
592
 
        for (i = 0; i < nrates; i++) {
593
 
                int rate = rates[i] & IEEE80211_RATE_VAL;
594
 
                if (rate > maxrate)
595
 
                        rate = maxrate;
596
 
        }
597
 
        return maxrate;
598
 
}
599
 
 
600
 
/* unalligned little endian access */     
601
 
#define LE_READ_4(p)                                    \
602
 
        ((u_int32_t)                                    \
603
 
         ((((const u_int8_t *)(p))[0]      ) |          \
604
 
          (((const u_int8_t *)(p))[1] <<  8) |          \
605
 
          (((const u_int8_t *)(p))[2] << 16) |          \
606
 
          (((const u_int8_t *)(p))[3] << 24)))
607
 
 
608
 
static int __inline
609
 
iswpaoui(const u_int8_t *frm)
610
 
{
611
 
        return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
612
 
}
613
 
 
614
 
static int
615
 
wpa_driver_bsd_get_scan_results(void *priv,
616
 
                                     struct wpa_scan_result *results,
617
 
                                     size_t max_size)
618
 
{
619
 
#define min(a,b)        ((a)>(b)?(b):(a))
620
 
        struct wpa_driver_bsd_data *drv = priv;
621
 
        uint8_t buf[24*1024];
622
 
        uint8_t *cp, *vp;
623
 
        struct ieee80211req_scan_result *sr;
624
 
        struct wpa_scan_result *wsr;
625
 
        int len, ielen;
626
 
 
627
 
        os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
628
 
 
629
 
        len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
630
 
        if (len < 0)
631
 
                return -1;
632
 
        cp = buf;
633
 
        wsr = results;
634
 
        while (len >= sizeof(struct ieee80211req_scan_result)) {
635
 
                sr = (struct ieee80211req_scan_result *) cp;
636
 
                os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
637
 
                wsr->ssid_len = sr->isr_ssid_len;
638
 
                wsr->freq = sr->isr_freq;
639
 
                wsr->noise = sr->isr_noise;
640
 
                wsr->qual = sr->isr_rssi;
641
 
                wsr->level = 0;         /* XXX? */
642
 
                wsr->caps = sr->isr_capinfo;
643
 
                wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
644
 
                vp = (u_int8_t *)(sr+1);
645
 
                os_memcpy(wsr->ssid, vp, sr->isr_ssid_len);
646
 
                if (sr->isr_ie_len > 0) {
647
 
                        vp += sr->isr_ssid_len;
648
 
                        ielen = sr->isr_ie_len;
649
 
                        while (ielen > 0) {
650
 
                                switch (vp[0]) {
651
 
                                case IEEE80211_ELEMID_VENDOR:
652
 
                                        if (!iswpaoui(vp))
653
 
                                                break;
654
 
                                        wsr->wpa_ie_len =
655
 
                                            min(2+vp[1], SSID_MAX_WPA_IE_LEN);
656
 
                                        os_memcpy(wsr->wpa_ie, vp,
657
 
                                                  wsr->wpa_ie_len);
658
 
                                        break;
659
 
                                case IEEE80211_ELEMID_RSN:
660
 
                                        wsr->rsn_ie_len =
661
 
                                            min(2+vp[1], SSID_MAX_WPA_IE_LEN);
662
 
                                        os_memcpy(wsr->rsn_ie, vp,
663
 
                                                  wsr->rsn_ie_len);
664
 
                                        break;
665
 
                                }
666
 
                                ielen -= 2+vp[1];
667
 
                                vp += 2+vp[1];
668
 
                        }
669
 
                }
670
 
 
671
 
                cp += sr->isr_len, len -= sr->isr_len;
672
 
                wsr++;
673
 
        }
674
 
        qsort(results, wsr - results, sizeof(struct wpa_scan_result),
675
 
              wpa_scan_result_compar);
676
 
 
677
 
        wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
678
 
                   len, wsr - results);
679
 
 
680
 
        return wsr - results;
681
 
#undef min
682
 
}
683
 
 
684
 
static void *
685
 
wpa_driver_bsd_init(void *ctx, const char *ifname)
686
 
{
687
 
#define GETPARAM(drv, param, v) \
688
 
        (((v) = get80211param(drv, param)) != -1)
689
 
        struct wpa_driver_bsd_data *drv;
690
 
 
691
 
        drv = os_zalloc(sizeof(*drv));
692
 
        if (drv == NULL)
693
 
                return NULL;
694
 
        /*
695
 
         * NB: We require the interface name be mappable to an index.
696
 
         *     This implies we do not support having wpa_supplicant
697
 
         *     wait for an interface to appear.  This seems ok; that
698
 
         *     doesn't belong here; it's really the job of devd.
699
 
         */
700
 
        drv->ifindex = if_nametoindex(ifname);
701
 
        if (drv->ifindex == 0) {
702
 
                wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
703
 
                           __func__, ifname);
704
 
                goto fail1;
705
 
        }
706
 
        drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
707
 
        if (drv->sock < 0)
708
 
                goto fail1;
709
 
        drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
710
 
        if (drv->route < 0)
711
 
                goto fail;
712
 
        eloop_register_read_sock(drv->route,
713
 
                wpa_driver_bsd_event_receive, ctx, drv);
714
 
 
715
 
        drv->ctx = ctx;
716
 
        os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
717
 
 
718
 
        if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
719
 
                wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
720
 
                        __func__, strerror(errno));
721
 
                goto fail;
722
 
        }
723
 
        if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
724
 
                wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
725
 
                        __func__, strerror(errno));
726
 
                goto fail;
727
 
        }
728
 
        if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
729
 
                wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
730
 
                        __func__, strerror(errno));
731
 
                goto fail;
732
 
        }
733
 
        if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
734
 
                wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
735
 
                           "roaming: %s", __func__, strerror(errno));
736
 
                goto fail;
737
 
        }
738
 
 
739
 
        if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
740
 
                wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
741
 
                           __func__, strerror(errno));
742
 
                goto fail;
743
 
        }
744
 
 
745
 
        return drv;
746
 
fail:
747
 
        close(drv->sock);
748
 
fail1:
749
 
        os_free(drv);
750
 
        return NULL;
751
 
#undef GETPARAM
752
 
}
753
 
 
754
 
static void
755
 
wpa_driver_bsd_deinit(void *priv)
756
 
{
757
 
        struct wpa_driver_bsd_data *drv = priv;
758
 
        int flags;
759
 
 
760
 
        eloop_unregister_read_sock(drv->route);
761
 
 
762
 
        /* NB: mark interface down */
763
 
        if (getifflags(drv, &flags) == 0)
764
 
                (void) setifflags(drv, flags &~ IFF_UP);
765
 
 
766
 
        wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
767
 
        if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
768
 
                wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
769
 
                        __func__);
770
 
 
771
 
        (void) close(drv->route);               /* ioctl socket */
772
 
        (void) close(drv->sock);                /* event socket */
773
 
        os_free(drv);
774
 
}
775
 
 
776
 
 
777
 
const struct wpa_driver_ops wpa_driver_bsd_ops = {
778
 
        .name                   = "bsd",
779
 
        .desc                   = "BSD 802.11 support (Atheros, etc.)",
780
 
        .init                   = wpa_driver_bsd_init,
781
 
        .deinit                 = wpa_driver_bsd_deinit,
782
 
        .get_bssid              = wpa_driver_bsd_get_bssid,
783
 
        .get_ssid               = wpa_driver_bsd_get_ssid,
784
 
        .set_wpa                = wpa_driver_bsd_set_wpa,
785
 
        .set_key                = wpa_driver_bsd_set_key,
786
 
        .set_countermeasures    = wpa_driver_bsd_set_countermeasures,
787
 
        .set_drop_unencrypted   = wpa_driver_bsd_set_drop_unencrypted,
788
 
        .scan                   = wpa_driver_bsd_scan,
789
 
        .get_scan_results       = wpa_driver_bsd_get_scan_results,
790
 
        .deauthenticate         = wpa_driver_bsd_deauthenticate,
791
 
        .disassociate           = wpa_driver_bsd_disassociate,
792
 
        .associate              = wpa_driver_bsd_associate,
793
 
        .set_auth_alg           = wpa_driver_bsd_set_auth_alg,
794
 
};