~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to src/drivers/driver_hostap.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
1
/*
2
 
 * WPA Supplicant - driver interaction with Linux Host AP driver
 
2
 * Driver interaction with Linux Host AP driver
3
3
 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
23
23
#include "driver_hostap.h"
24
24
 
25
25
 
 
26
#ifdef HOSTAPD
 
27
 
 
28
#include <net/if_arp.h>
 
29
#include <netpacket/packet.h>
 
30
 
 
31
#include "priv_netlink.h"
 
32
#include "netlink.h"
 
33
#include "linux_ioctl.h"
 
34
#include "common/ieee802_11_defs.h"
 
35
 
 
36
 
 
37
/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
 
38
 * frames that might be longer than normal default MTU and they are not
 
39
 * fragmented */
 
40
#define HOSTAPD_MTU 2290
 
41
 
 
42
static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
43
 
 
44
struct hostap_driver_data {
 
45
        struct hostapd_data *hapd;
 
46
 
 
47
        char iface[IFNAMSIZ + 1];
 
48
        int sock; /* raw packet socket for driver access */
 
49
        int ioctl_sock; /* socket for ioctl() use */
 
50
        struct netlink_data *netlink;
 
51
 
 
52
        int we_version;
 
53
 
 
54
        u8 *generic_ie;
 
55
        size_t generic_ie_len;
 
56
        u8 *wps_ie;
 
57
        size_t wps_ie_len;
 
58
};
 
59
 
 
60
 
 
61
static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
 
62
                         int len);
 
63
static int hostap_set_iface_flags(void *priv, int dev_up);
 
64
 
 
65
static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len,
 
66
                        u16 stype)
 
67
{
 
68
        struct ieee80211_hdr *hdr;
 
69
        u16 fc, ethertype;
 
70
        u8 *pos, *sa;
 
71
        size_t left;
 
72
        union wpa_event_data event;
 
73
 
 
74
        if (len < sizeof(struct ieee80211_hdr))
 
75
                return;
 
76
 
 
77
        hdr = (struct ieee80211_hdr *) buf;
 
78
        fc = le_to_host16(hdr->frame_control);
 
79
 
 
80
        if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) {
 
81
                printf("Not ToDS data frame (fc=0x%04x)\n", fc);
 
82
                return;
 
83
        }
 
84
 
 
85
        sa = hdr->addr2;
 
86
        os_memset(&event, 0, sizeof(event));
 
87
        event.rx_from_unknown.frame = buf;
 
88
        event.rx_from_unknown.len = len;
 
89
        wpa_supplicant_event(drv->hapd, EVENT_RX_FROM_UNKNOWN, &event);
 
90
 
 
91
        pos = (u8 *) (hdr + 1);
 
92
        left = len - sizeof(*hdr);
 
93
 
 
94
        if (left < sizeof(rfc1042_header)) {
 
95
                printf("Too short data frame\n");
 
96
                return;
 
97
        }
 
98
 
 
99
        if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) {
 
100
                printf("Data frame with no RFC1042 header\n");
 
101
                return;
 
102
        }
 
103
        pos += sizeof(rfc1042_header);
 
104
        left -= sizeof(rfc1042_header);
 
105
 
 
106
        if (left < 2) {
 
107
                printf("No ethertype in data frame\n");
 
108
                return;
 
109
        }
 
110
 
 
111
        ethertype = WPA_GET_BE16(pos);
 
112
        pos += 2;
 
113
        left -= 2;
 
114
        switch (ethertype) {
 
115
        case ETH_P_PAE:
 
116
                drv_event_eapol_rx(drv->hapd, sa, pos, left);
 
117
                break;
 
118
 
 
119
        default:
 
120
                printf("Unknown ethertype 0x%04x in data frame\n", ethertype);
 
121
                break;
 
122
        }
 
123
}
 
124
 
 
125
 
 
126
static void handle_tx_callback(struct hostap_driver_data *drv, u8 *buf,
 
127
                               size_t len, int ok)
 
128
{
 
129
        struct ieee80211_hdr *hdr;
 
130
        u16 fc;
 
131
        union wpa_event_data event;
 
132
 
 
133
        hdr = (struct ieee80211_hdr *) buf;
 
134
        fc = le_to_host16(hdr->frame_control);
 
135
 
 
136
        os_memset(&event, 0, sizeof(event));
 
137
        event.tx_status.type = WLAN_FC_GET_TYPE(fc);
 
138
        event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
 
139
        event.tx_status.dst = hdr->addr1;
 
140
        event.tx_status.data = buf;
 
141
        event.tx_status.data_len = len;
 
142
        event.tx_status.ack = ok;
 
143
        wpa_supplicant_event(drv->hapd, EVENT_TX_STATUS, &event);
 
144
}
 
145
 
 
146
 
 
147
static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
 
148
{
 
149
        struct ieee80211_hdr *hdr;
 
150
        u16 fc, extra_len, type, stype;
 
151
        unsigned char *extra = NULL;
 
152
        size_t data_len = len;
 
153
        int ver;
 
154
        union wpa_event_data event;
 
155
 
 
156
        /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
 
157
         * these to user space */
 
158
        if (len < 24) {
 
159
                wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)",
 
160
                           (unsigned long) len);
 
161
                return;
 
162
        }
 
163
 
 
164
        hdr = (struct ieee80211_hdr *) buf;
 
165
        fc = le_to_host16(hdr->frame_control);
 
166
        type = WLAN_FC_GET_TYPE(fc);
 
167
        stype = WLAN_FC_GET_STYPE(fc);
 
168
 
 
169
        if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) {
 
170
                wpa_hexdump(MSG_MSGDUMP, "Received management frame",
 
171
                            buf, len);
 
172
        }
 
173
 
 
174
        ver = fc & WLAN_FC_PVER;
 
175
 
 
176
        /* protocol version 3 is reserved for indicating extra data after the
 
177
         * payload, version 2 for indicating ACKed frame (TX callbacks), and
 
178
         * version 1 for indicating failed frame (no ACK, TX callbacks) */
 
179
        if (ver == 3) {
 
180
                u8 *pos = buf + len - 2;
 
181
                extra_len = WPA_GET_LE16(pos);
 
182
                printf("extra data in frame (elen=%d)\n", extra_len);
 
183
                if ((size_t) extra_len + 2 > len) {
 
184
                        printf("  extra data overflow\n");
 
185
                        return;
 
186
                }
 
187
                len -= extra_len + 2;
 
188
                extra = buf + len;
 
189
        } else if (ver == 1 || ver == 2) {
 
190
                handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0);
 
191
                return;
 
192
        } else if (ver != 0) {
 
193
                printf("unknown protocol version %d\n", ver);
 
194
                return;
 
195
        }
 
196
 
 
197
        switch (type) {
 
198
        case WLAN_FC_TYPE_MGMT:
 
199
                os_memset(&event, 0, sizeof(event));
 
200
                event.rx_mgmt.frame = buf;
 
201
                event.rx_mgmt.frame_len = data_len;
 
202
                wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
 
203
                break;
 
204
        case WLAN_FC_TYPE_CTRL:
 
205
                wpa_printf(MSG_DEBUG, "CTRL");
 
206
                break;
 
207
        case WLAN_FC_TYPE_DATA:
 
208
                wpa_printf(MSG_DEBUG, "DATA");
 
209
                handle_data(drv, buf, data_len, stype);
 
210
                break;
 
211
        default:
 
212
                wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
 
213
                break;
 
214
        }
 
215
}
 
216
 
 
217
 
 
218
static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
 
219
{
 
220
        struct hostap_driver_data *drv = eloop_ctx;
 
221
        int len;
 
222
        unsigned char buf[3000];
 
223
 
 
224
        len = recv(sock, buf, sizeof(buf), 0);
 
225
        if (len < 0) {
 
226
                perror("recv");
 
227
                return;
 
228
        }
 
229
 
 
230
        handle_frame(drv, buf, len);
 
231
}
 
232
 
 
233
 
 
234
static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr)
 
235
{
 
236
        struct ifreq ifr;
 
237
        struct sockaddr_ll addr;
 
238
 
 
239
        drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 
240
        if (drv->sock < 0) {
 
241
                perror("socket[PF_PACKET,SOCK_RAW]");
 
242
                return -1;
 
243
        }
 
244
 
 
245
        if (eloop_register_read_sock(drv->sock, handle_read, drv, NULL)) {
 
246
                printf("Could not register read socket\n");
 
247
                return -1;
 
248
        }
 
249
 
 
250
        memset(&ifr, 0, sizeof(ifr));
 
251
        snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
 
252
        if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
 
253
                perror("ioctl(SIOCGIFINDEX)");
 
254
                return -1;
 
255
        }
 
256
 
 
257
        if (hostap_set_iface_flags(drv, 1)) {
 
258
                return -1;
 
259
        }
 
260
 
 
261
        memset(&addr, 0, sizeof(addr));
 
262
        addr.sll_family = AF_PACKET;
 
263
        addr.sll_ifindex = ifr.ifr_ifindex;
 
264
        wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
 
265
                   addr.sll_ifindex);
 
266
 
 
267
        if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
 
268
                perror("bind");
 
269
                return -1;
 
270
        }
 
271
 
 
272
        return linux_get_ifhwaddr(drv->sock, drv->iface, own_addr);
 
273
}
 
274
 
 
275
 
 
276
static int hostap_send_mlme(void *priv, const u8 *msg, size_t len)
 
277
{
 
278
        struct hostap_driver_data *drv = priv;
 
279
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
 
280
        int res;
 
281
 
 
282
        /* Request TX callback */
 
283
        hdr->frame_control |= host_to_le16(BIT(1));
 
284
        res = send(drv->sock, msg, len, 0);
 
285
        hdr->frame_control &= ~host_to_le16(BIT(1));
 
286
 
 
287
        return res;
 
288
}
 
289
 
 
290
 
 
291
static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
 
292
                             size_t data_len, int encrypt, const u8 *own_addr)
 
293
{
 
294
        struct hostap_driver_data *drv = priv;
 
295
        struct ieee80211_hdr *hdr;
 
296
        size_t len;
 
297
        u8 *pos;
 
298
        int res;
 
299
 
 
300
        len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len;
 
301
        hdr = os_zalloc(len);
 
302
        if (hdr == NULL) {
 
303
                printf("malloc() failed for hostapd_send_data(len=%lu)\n",
 
304
                       (unsigned long) len);
 
305
                return -1;
 
306
        }
 
307
 
 
308
        hdr->frame_control =
 
309
                IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
 
310
        hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
 
311
        if (encrypt)
 
312
                hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
 
313
        memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
 
314
        memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
 
315
        memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
 
316
 
 
317
        pos = (u8 *) (hdr + 1);
 
318
        memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
 
319
        pos += sizeof(rfc1042_header);
 
320
        *((u16 *) pos) = htons(ETH_P_PAE);
 
321
        pos += 2;
 
322
        memcpy(pos, data, data_len);
 
323
 
 
324
        res = hostap_send_mlme(drv, (u8 *) hdr, len);
 
325
        if (res < 0) {
 
326
                wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - "
 
327
                           "failed: %d (%s)",
 
328
                           (unsigned long) len, errno, strerror(errno));
 
329
        }
 
330
        free(hdr);
 
331
 
 
332
        return res;
 
333
}
 
334
 
 
335
 
 
336
static int hostap_sta_set_flags(void *priv, const u8 *addr,
 
337
                                int total_flags, int flags_or, int flags_and)
 
338
{
 
339
        struct hostap_driver_data *drv = priv;
 
340
        struct prism2_hostapd_param param;
 
341
 
 
342
        if (flags_or & WPA_STA_AUTHORIZED)
 
343
                flags_or = BIT(5); /* WLAN_STA_AUTHORIZED */
 
344
        if (!(flags_and & WPA_STA_AUTHORIZED))
 
345
                flags_and = ~BIT(5);
 
346
        else
 
347
                flags_and = ~0;
 
348
        memset(&param, 0, sizeof(param));
 
349
        param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
 
350
        memcpy(param.sta_addr, addr, ETH_ALEN);
 
351
        param.u.set_flags_sta.flags_or = flags_or;
 
352
        param.u.set_flags_sta.flags_and = flags_and;
 
353
        return hostapd_ioctl(drv, &param, sizeof(param));
 
354
}
 
355
 
 
356
 
 
357
static int hostap_set_iface_flags(void *priv, int dev_up)
 
358
{
 
359
        struct hostap_driver_data *drv = priv;
 
360
        struct ifreq ifr;
 
361
        char ifname[IFNAMSIZ];
 
362
 
 
363
        os_snprintf(ifname, IFNAMSIZ, "%sap", drv->iface);
 
364
        if (linux_set_iface_flags(drv->ioctl_sock, ifname, dev_up) < 0)
 
365
                return -1;
 
366
 
 
367
        if (dev_up) {
 
368
                memset(&ifr, 0, sizeof(ifr));
 
369
                os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
370
                ifr.ifr_mtu = HOSTAPD_MTU;
 
371
                if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
 
372
                        perror("ioctl[SIOCSIFMTU]");
 
373
                        printf("Setting MTU failed - trying to survive with "
 
374
                               "current value\n");
 
375
                }
 
376
        }
 
377
 
 
378
        return 0;
 
379
}
 
380
 
 
381
 
 
382
static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
 
383
                         int len)
 
384
{
 
385
        struct hostap_driver_data *drv = priv;
 
386
        struct iwreq iwr;
 
387
 
 
388
        memset(&iwr, 0, sizeof(iwr));
 
389
        os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
 
390
        iwr.u.data.pointer = (caddr_t) param;
 
391
        iwr.u.data.length = len;
 
392
 
 
393
        if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
 
394
                perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
 
395
                return -1;
 
396
        }
 
397
 
 
398
        return 0;
 
399
}
 
400
 
 
401
 
 
402
static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
 
403
                                     enum wpa_alg alg, const u8 *addr,
 
404
                                     int key_idx, int set_tx,
 
405
                                     const u8 *seq, size_t seq_len,
 
406
                                     const u8 *key, size_t key_len)
 
407
{
 
408
        struct hostap_driver_data *drv = priv;
 
409
        struct prism2_hostapd_param *param;
 
410
        u8 *buf;
 
411
        size_t blen;
 
412
        int ret = 0;
 
413
 
 
414
        blen = sizeof(*param) + key_len;
 
415
        buf = os_zalloc(blen);
 
416
        if (buf == NULL)
 
417
                return -1;
 
418
 
 
419
        param = (struct prism2_hostapd_param *) buf;
 
420
        param->cmd = PRISM2_SET_ENCRYPTION;
 
421
        if (addr == NULL)
 
422
                memset(param->sta_addr, 0xff, ETH_ALEN);
 
423
        else
 
424
                memcpy(param->sta_addr, addr, ETH_ALEN);
 
425
        switch (alg) {
 
426
        case WPA_ALG_NONE:
 
427
                os_strlcpy((char *) param->u.crypt.alg, "NONE",
 
428
                           HOSTAP_CRYPT_ALG_NAME_LEN);
 
429
                break;
 
430
        case WPA_ALG_WEP:
 
431
                os_strlcpy((char *) param->u.crypt.alg, "WEP",
 
432
                           HOSTAP_CRYPT_ALG_NAME_LEN);
 
433
                break;
 
434
        case WPA_ALG_TKIP:
 
435
                os_strlcpy((char *) param->u.crypt.alg, "TKIP",
 
436
                           HOSTAP_CRYPT_ALG_NAME_LEN);
 
437
                break;
 
438
        case WPA_ALG_CCMP:
 
439
                os_strlcpy((char *) param->u.crypt.alg, "CCMP",
 
440
                           HOSTAP_CRYPT_ALG_NAME_LEN);
 
441
                break;
 
442
        default:
 
443
                os_free(buf);
 
444
                return -1;
 
445
        }
 
446
        param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
 
447
        param->u.crypt.idx = key_idx;
 
448
        param->u.crypt.key_len = key_len;
 
449
        memcpy((u8 *) (param + 1), key, key_len);
 
450
 
 
451
        if (hostapd_ioctl(drv, param, blen)) {
 
452
                printf("Failed to set encryption.\n");
 
453
                ret = -1;
 
454
        }
 
455
        free(buf);
 
456
 
 
457
        return ret;
 
458
}
 
459
 
 
460
 
 
461
static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr,
 
462
                             int idx, u8 *seq)
 
463
{
 
464
        struct hostap_driver_data *drv = priv;
 
465
        struct prism2_hostapd_param *param;
 
466
        u8 *buf;
 
467
        size_t blen;
 
468
        int ret = 0;
 
469
 
 
470
        blen = sizeof(*param) + 32;
 
471
        buf = os_zalloc(blen);
 
472
        if (buf == NULL)
 
473
                return -1;
 
474
 
 
475
        param = (struct prism2_hostapd_param *) buf;
 
476
        param->cmd = PRISM2_GET_ENCRYPTION;
 
477
        if (addr == NULL)
 
478
                memset(param->sta_addr, 0xff, ETH_ALEN);
 
479
        else
 
480
                memcpy(param->sta_addr, addr, ETH_ALEN);
 
481
        param->u.crypt.idx = idx;
 
482
 
 
483
        if (hostapd_ioctl(drv, param, blen)) {
 
484
                printf("Failed to get encryption.\n");
 
485
                ret = -1;
 
486
        } else {
 
487
                memcpy(seq, param->u.crypt.seq, 8);
 
488
        }
 
489
        free(buf);
 
490
 
 
491
        return ret;
 
492
}
 
493
 
 
494
 
 
495
static int hostap_ioctl_prism2param(void *priv, int param, int value)
 
496
{
 
497
        struct hostap_driver_data *drv = priv;
 
498
        struct iwreq iwr;
 
499
        int *i;
 
500
 
 
501
        memset(&iwr, 0, sizeof(iwr));
 
502
        os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
 
503
        i = (int *) iwr.u.name;
 
504
        *i++ = param;
 
505
        *i++ = value;
 
506
 
 
507
        if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
 
508
                perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
 
509
                return -1;
 
510
        }
 
511
 
 
512
        return 0;
 
513
}
 
514
 
 
515
 
 
516
static int hostap_set_ieee8021x(void *priv, struct wpa_bss_params *params)
 
517
{
 
518
        struct hostap_driver_data *drv = priv;
 
519
        int enabled = params->enabled;
 
520
 
 
521
        /* enable kernel driver support for IEEE 802.1X */
 
522
        if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) {
 
523
                printf("Could not setup IEEE 802.1X support in kernel driver."
 
524
                       "\n");
 
525
                return -1;
 
526
        }
 
527
 
 
528
        if (!enabled)
 
529
                return 0;
 
530
 
 
531
        /* use host driver implementation of encryption to allow
 
532
         * individual keys and passing plaintext EAPOL frames */
 
533
        if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) ||
 
534
            hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) {
 
535
                printf("Could not setup host-based encryption in kernel "
 
536
                       "driver.\n");
 
537
                return -1;
 
538
        }
 
539
 
 
540
        return 0;
 
541
}
 
542
 
 
543
 
 
544
static int hostap_set_privacy(void *priv, int enabled)
 
545
{
 
546
        struct hostap_drvier_data *drv = priv;
 
547
 
 
548
        return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
 
549
                                        enabled);
 
550
}
 
551
 
 
552
 
 
553
static int hostap_set_ssid(void *priv, const u8 *buf, int len)
 
554
{
 
555
        struct hostap_driver_data *drv = priv;
 
556
        struct iwreq iwr;
 
557
 
 
558
        memset(&iwr, 0, sizeof(iwr));
 
559
        os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
 
560
        iwr.u.essid.flags = 1; /* SSID active */
 
561
        iwr.u.essid.pointer = (caddr_t) buf;
 
562
        iwr.u.essid.length = len + 1;
 
563
 
 
564
        if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
 
565
                perror("ioctl[SIOCSIWESSID]");
 
566
                printf("len=%d\n", len);
 
567
                return -1;
 
568
        }
 
569
 
 
570
        return 0;
 
571
}
 
572
 
 
573
 
 
574
static int hostap_flush(void *priv)
 
575
{
 
576
        struct hostap_driver_data *drv = priv;
 
577
        struct prism2_hostapd_param param;
 
578
 
 
579
        memset(&param, 0, sizeof(param));
 
580
        param.cmd = PRISM2_HOSTAPD_FLUSH;
 
581
        return hostapd_ioctl(drv, &param, sizeof(param));
 
582
}
 
583
 
 
584
 
 
585
static int hostap_read_sta_data(void *priv,
 
586
                                struct hostap_sta_driver_data *data,
 
587
                                const u8 *addr)
 
588
{
 
589
        struct hostap_driver_data *drv = priv;
 
590
        char buf[1024], line[128], *pos;
 
591
        FILE *f;
 
592
        unsigned long val;
 
593
 
 
594
        memset(data, 0, sizeof(*data));
 
595
        snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR,
 
596
                 drv->iface, MAC2STR(addr));
 
597
 
 
598
        f = fopen(buf, "r");
 
599
        if (!f)
 
600
                return -1;
 
601
        /* Need to read proc file with in one piece, so use large enough
 
602
         * buffer. */
 
603
        setbuffer(f, buf, sizeof(buf));
 
604
 
 
605
        while (fgets(line, sizeof(line), f)) {
 
606
                pos = strchr(line, '=');
 
607
                if (!pos)
 
608
                        continue;
 
609
                *pos++ = '\0';
 
610
                val = strtoul(pos, NULL, 10);
 
611
                if (strcmp(line, "rx_packets") == 0)
 
612
                        data->rx_packets = val;
 
613
                else if (strcmp(line, "tx_packets") == 0)
 
614
                        data->tx_packets = val;
 
615
                else if (strcmp(line, "rx_bytes") == 0)
 
616
                        data->rx_bytes = val;
 
617
                else if (strcmp(line, "tx_bytes") == 0)
 
618
                        data->tx_bytes = val;
 
619
        }
 
620
 
 
621
        fclose(f);
 
622
 
 
623
        return 0;
 
624
}
 
625
 
 
626
 
 
627
static int hostap_sta_add(void *priv, struct hostapd_sta_add_params *params)
 
628
{
 
629
        struct hostap_driver_data *drv = priv;
 
630
        struct prism2_hostapd_param param;
 
631
        int tx_supp_rates = 0;
 
632
        size_t i;
 
633
 
 
634
#define WLAN_RATE_1M BIT(0)
 
635
#define WLAN_RATE_2M BIT(1)
 
636
#define WLAN_RATE_5M5 BIT(2)
 
637
#define WLAN_RATE_11M BIT(3)
 
638
 
 
639
        for (i = 0; i < params->supp_rates_len; i++) {
 
640
                if ((params->supp_rates[i] & 0x7f) == 2)
 
641
                        tx_supp_rates |= WLAN_RATE_1M;
 
642
                if ((params->supp_rates[i] & 0x7f) == 4)
 
643
                        tx_supp_rates |= WLAN_RATE_2M;
 
644
                if ((params->supp_rates[i] & 0x7f) == 11)
 
645
                        tx_supp_rates |= WLAN_RATE_5M5;
 
646
                if ((params->supp_rates[i] & 0x7f) == 22)
 
647
                        tx_supp_rates |= WLAN_RATE_11M;
 
648
        }
 
649
 
 
650
        memset(&param, 0, sizeof(param));
 
651
        param.cmd = PRISM2_HOSTAPD_ADD_STA;
 
652
        memcpy(param.sta_addr, params->addr, ETH_ALEN);
 
653
        param.u.add_sta.aid = params->aid;
 
654
        param.u.add_sta.capability = params->capability;
 
655
        param.u.add_sta.tx_supp_rates = tx_supp_rates;
 
656
        return hostapd_ioctl(drv, &param, sizeof(param));
 
657
}
 
658
 
 
659
 
 
660
static int hostap_sta_remove(void *priv, const u8 *addr)
 
661
{
 
662
        struct hostap_driver_data *drv = priv;
 
663
        struct prism2_hostapd_param param;
 
664
 
 
665
        hostap_sta_set_flags(drv, addr, 0, 0, ~WPA_STA_AUTHORIZED);
 
666
 
 
667
        memset(&param, 0, sizeof(param));
 
668
        param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
 
669
        memcpy(param.sta_addr, addr, ETH_ALEN);
 
670
        if (hostapd_ioctl(drv, &param, sizeof(param))) {
 
671
                printf("Could not remove station from kernel driver.\n");
 
672
                return -1;
 
673
        }
 
674
        return 0;
 
675
}
 
676
 
 
677
 
 
678
static int hostap_get_inact_sec(void *priv, const u8 *addr)
 
679
{
 
680
        struct hostap_driver_data *drv = priv;
 
681
        struct prism2_hostapd_param param;
 
682
 
 
683
        memset(&param, 0, sizeof(param));
 
684
        param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
 
685
        memcpy(param.sta_addr, addr, ETH_ALEN);
 
686
        if (hostapd_ioctl(drv, &param, sizeof(param))) {
 
687
                return -1;
 
688
        }
 
689
 
 
690
        return param.u.get_info_sta.inactive_sec;
 
691
}
 
692
 
 
693
 
 
694
static int hostap_sta_clear_stats(void *priv, const u8 *addr)
 
695
{
 
696
        struct hostap_driver_data *drv = priv;
 
697
        struct prism2_hostapd_param param;
 
698
 
 
699
        memset(&param, 0, sizeof(param));
 
700
        param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS;
 
701
        memcpy(param.sta_addr, addr, ETH_ALEN);
 
702
        if (hostapd_ioctl(drv, &param, sizeof(param))) {
 
703
                return -1;
 
704
        }
 
705
 
 
706
        return 0;
 
707
}
 
708
 
 
709
 
 
710
static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
 
711
{
 
712
        struct prism2_hostapd_param *param;
 
713
        int res;
 
714
        size_t blen, elem_len;
 
715
 
 
716
        elem_len = drv->generic_ie_len + drv->wps_ie_len;
 
717
        blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
 
718
        if (blen < sizeof(*param))
 
719
                blen = sizeof(*param);
 
720
 
 
721
        param = os_zalloc(blen);
 
722
        if (param == NULL)
 
723
                return -1;
 
724
 
 
725
        param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
 
726
        param->u.generic_elem.len = elem_len;
 
727
        if (drv->generic_ie) {
 
728
                os_memcpy(param->u.generic_elem.data, drv->generic_ie,
 
729
                          drv->generic_ie_len);
 
730
        }
 
731
        if (drv->wps_ie) {
 
732
                os_memcpy(&param->u.generic_elem.data[drv->generic_ie_len],
 
733
                          drv->wps_ie, drv->wps_ie_len);
 
734
        }
 
735
        wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
 
736
                    param->u.generic_elem.data, elem_len);
 
737
        res = hostapd_ioctl(drv, param, blen);
 
738
 
 
739
        os_free(param);
 
740
 
 
741
        return res;
 
742
}
 
743
 
 
744
 
 
745
static int hostap_set_generic_elem(void *priv,
 
746
                                   const u8 *elem, size_t elem_len)
 
747
{
 
748
        struct hostap_driver_data *drv = priv;
 
749
 
 
750
        os_free(drv->generic_ie);
 
751
        drv->generic_ie = NULL;
 
752
        drv->generic_ie_len = 0;
 
753
        if (elem) {
 
754
                drv->generic_ie = os_malloc(elem_len);
 
755
                if (drv->generic_ie == NULL)
 
756
                        return -1;
 
757
                os_memcpy(drv->generic_ie, elem, elem_len);
 
758
                drv->generic_ie_len = elem_len;
 
759
        }
 
760
 
 
761
        return hostapd_ioctl_set_generic_elem(drv);
 
762
}
 
763
 
 
764
 
 
765
static int hostap_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
 
766
                                const struct wpabuf *proberesp)
 
767
{
 
768
        struct hostap_driver_data *drv = priv;
 
769
 
 
770
        /*
 
771
         * Host AP driver supports only one set of extra IEs, so we need to
 
772
         * use the Probe Response IEs also for Beacon frames since they include
 
773
         * more information.
 
774
         */
 
775
 
 
776
        os_free(drv->wps_ie);
 
777
        drv->wps_ie = NULL;
 
778
        drv->wps_ie_len = 0;
 
779
        if (proberesp) {
 
780
                drv->wps_ie = os_malloc(wpabuf_len(proberesp));
 
781
                if (drv->wps_ie == NULL)
 
782
                        return -1;
 
783
                os_memcpy(drv->wps_ie, wpabuf_head(proberesp),
 
784
                          wpabuf_len(proberesp));
 
785
                drv->wps_ie_len = wpabuf_len(proberesp);
 
786
        }
 
787
 
 
788
        return hostapd_ioctl_set_generic_elem(drv);
 
789
}
 
790
 
 
791
 
 
792
static void
 
793
hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv,
 
794
                                       char *custom)
 
795
{
 
796
        wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
 
797
 
 
798
        if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
 
799
                char *pos;
 
800
                u8 addr[ETH_ALEN];
 
801
                pos = strstr(custom, "addr=");
 
802
                if (pos == NULL) {
 
803
                        wpa_printf(MSG_DEBUG,
 
804
                                   "MLME-MICHAELMICFAILURE.indication "
 
805
                                   "without sender address ignored");
 
806
                        return;
 
807
                }
 
808
                pos += 5;
 
809
                if (hwaddr_aton(pos, addr) == 0) {
 
810
                        union wpa_event_data data;
 
811
                        os_memset(&data, 0, sizeof(data));
 
812
                        data.michael_mic_failure.unicast = 1;
 
813
                        data.michael_mic_failure.src = addr;
 
814
                        wpa_supplicant_event(drv->hapd,
 
815
                                             EVENT_MICHAEL_MIC_FAILURE, &data);
 
816
                } else {
 
817
                        wpa_printf(MSG_DEBUG,
 
818
                                   "MLME-MICHAELMICFAILURE.indication "
 
819
                                   "with invalid MAC address");
 
820
                }
 
821
        }
 
822
}
 
823
 
 
824
 
 
825
static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv,
 
826
                                            char *data, int len)
 
827
{
 
828
        struct iw_event iwe_buf, *iwe = &iwe_buf;
 
829
        char *pos, *end, *custom, *buf;
 
830
 
 
831
        pos = data;
 
832
        end = data + len;
 
833
 
 
834
        while (pos + IW_EV_LCP_LEN <= end) {
 
835
                /* Event data may be unaligned, so make a local, aligned copy
 
836
                 * before processing. */
 
837
                memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
 
838
                wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
 
839
                           iwe->cmd, iwe->len);
 
840
                if (iwe->len <= IW_EV_LCP_LEN)
 
841
                        return;
 
842
 
 
843
                custom = pos + IW_EV_POINT_LEN;
 
844
                if (drv->we_version > 18 &&
 
845
                    (iwe->cmd == IWEVMICHAELMICFAILURE ||
 
846
                     iwe->cmd == IWEVCUSTOM)) {
 
847
                        /* WE-19 removed the pointer from struct iw_point */
 
848
                        char *dpos = (char *) &iwe_buf.u.data.length;
 
849
                        int dlen = dpos - (char *) &iwe_buf;
 
850
                        memcpy(dpos, pos + IW_EV_LCP_LEN,
 
851
                               sizeof(struct iw_event) - dlen);
 
852
                } else {
 
853
                        memcpy(&iwe_buf, pos, sizeof(struct iw_event));
 
854
                        custom += IW_EV_POINT_OFF;
 
855
                }
 
856
 
 
857
                switch (iwe->cmd) {
 
858
                case IWEVCUSTOM:
 
859
                        if (custom + iwe->u.data.length > end)
 
860
                                return;
 
861
                        buf = malloc(iwe->u.data.length + 1);
 
862
                        if (buf == NULL)
 
863
                                return;
 
864
                        memcpy(buf, custom, iwe->u.data.length);
 
865
                        buf[iwe->u.data.length] = '\0';
 
866
                        hostapd_wireless_event_wireless_custom(drv, buf);
 
867
                        free(buf);
 
868
                        break;
 
869
                }
 
870
 
 
871
                pos += iwe->len;
 
872
        }
 
873
}
 
874
 
 
875
 
 
876
static void hostapd_wireless_event_rtm_newlink(void *ctx,
 
877
                                               struct ifinfomsg *ifi,
 
878
                                               u8 *buf, size_t len)
 
879
{
 
880
        struct hostap_driver_data *drv = ctx;
 
881
        int attrlen, rta_len;
 
882
        struct rtattr *attr;
 
883
 
 
884
        /* TODO: use ifi->ifi_index to filter out wireless events from other
 
885
         * interfaces */
 
886
 
 
887
        attrlen = len;
 
888
        attr = (struct rtattr *) buf;
 
889
 
 
890
        rta_len = RTA_ALIGN(sizeof(struct rtattr));
 
891
        while (RTA_OK(attr, attrlen)) {
 
892
                if (attr->rta_type == IFLA_WIRELESS) {
 
893
                        hostapd_wireless_event_wireless(
 
894
                                drv, ((char *) attr) + rta_len,
 
895
                                attr->rta_len - rta_len);
 
896
                }
 
897
                attr = RTA_NEXT(attr, attrlen);
 
898
        }
 
899
}
 
900
 
 
901
 
 
902
static int hostap_get_we_version(struct hostap_driver_data *drv)
 
903
{
 
904
        struct iw_range *range;
 
905
        struct iwreq iwr;
 
906
        int minlen;
 
907
        size_t buflen;
 
908
 
 
909
        drv->we_version = 0;
 
910
 
 
911
        /*
 
912
         * Use larger buffer than struct iw_range in order to allow the
 
913
         * structure to grow in the future.
 
914
         */
 
915
        buflen = sizeof(struct iw_range) + 500;
 
916
        range = os_zalloc(buflen);
 
917
        if (range == NULL)
 
918
                return -1;
 
919
 
 
920
        memset(&iwr, 0, sizeof(iwr));
 
921
        os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
 
922
        iwr.u.data.pointer = (caddr_t) range;
 
923
        iwr.u.data.length = buflen;
 
924
 
 
925
        minlen = ((char *) &range->enc_capa) - (char *) range +
 
926
                sizeof(range->enc_capa);
 
927
 
 
928
        if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
 
929
                perror("ioctl[SIOCGIWRANGE]");
 
930
                free(range);
 
931
                return -1;
 
932
        } else if (iwr.u.data.length >= minlen &&
 
933
                   range->we_version_compiled >= 18) {
 
934
                wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
 
935
                           "WE(source)=%d enc_capa=0x%x",
 
936
                           range->we_version_compiled,
 
937
                           range->we_version_source,
 
938
                           range->enc_capa);
 
939
                drv->we_version = range->we_version_compiled;
 
940
        }
 
941
 
 
942
        free(range);
 
943
        return 0;
 
944
}
 
945
 
 
946
 
 
947
static int hostap_wireless_event_init(struct hostap_driver_data *drv)
 
948
{
 
949
        struct netlink_config *cfg;
 
950
 
 
951
        hostap_get_we_version(drv);
 
952
 
 
953
        cfg = os_zalloc(sizeof(*cfg));
 
954
        if (cfg == NULL)
 
955
                return -1;
 
956
        cfg->ctx = drv;
 
957
        cfg->newlink_cb = hostapd_wireless_event_rtm_newlink;
 
958
        drv->netlink = netlink_init(cfg);
 
959
        if (drv->netlink == NULL) {
 
960
                os_free(cfg);
 
961
                return -1;
 
962
        }
 
963
 
 
964
        return 0;
 
965
}
 
966
 
 
967
 
 
968
static void * hostap_init(struct hostapd_data *hapd,
 
969
                          struct wpa_init_params *params)
 
970
{
 
971
        struct hostap_driver_data *drv;
 
972
 
 
973
        drv = os_zalloc(sizeof(struct hostap_driver_data));
 
974
        if (drv == NULL) {
 
975
                printf("Could not allocate memory for hostapd driver data\n");
 
976
                return NULL;
 
977
        }
 
978
 
 
979
        drv->hapd = hapd;
 
980
        drv->ioctl_sock = drv->sock = -1;
 
981
        memcpy(drv->iface, params->ifname, sizeof(drv->iface));
 
982
 
 
983
        drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
 
984
        if (drv->ioctl_sock < 0) {
 
985
                perror("socket[PF_INET,SOCK_DGRAM]");
 
986
                free(drv);
 
987
                return NULL;
 
988
        }
 
989
 
 
990
        if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) {
 
991
                printf("Could not enable hostapd mode for interface %s\n",
 
992
                       drv->iface);
 
993
                close(drv->ioctl_sock);
 
994
                free(drv);
 
995
                return NULL;
 
996
        }
 
997
 
 
998
        if (hostap_init_sockets(drv, params->own_addr) ||
 
999
            hostap_wireless_event_init(drv)) {
 
1000
                close(drv->ioctl_sock);
 
1001
                free(drv);
 
1002
                return NULL;
 
1003
        }
 
1004
 
 
1005
        return drv;
 
1006
}
 
1007
 
 
1008
 
 
1009
static void hostap_driver_deinit(void *priv)
 
1010
{
 
1011
        struct hostap_driver_data *drv = priv;
 
1012
 
 
1013
        netlink_deinit(drv->netlink);
 
1014
        (void) hostap_set_iface_flags(drv, 0);
 
1015
        (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
 
1016
        (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);
 
1017
 
 
1018
        if (drv->ioctl_sock >= 0)
 
1019
                close(drv->ioctl_sock);
 
1020
 
 
1021
        if (drv->sock >= 0)
 
1022
                close(drv->sock);
 
1023
 
 
1024
        os_free(drv->generic_ie);
 
1025
        os_free(drv->wps_ie);
 
1026
 
 
1027
        free(drv);
 
1028
}
 
1029
 
 
1030
 
 
1031
static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
 
1032
                             int reason)
 
1033
{
 
1034
        struct hostap_driver_data *drv = priv;
 
1035
        struct ieee80211_mgmt mgmt;
 
1036
 
 
1037
        memset(&mgmt, 0, sizeof(mgmt));
 
1038
        mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 
1039
                                          WLAN_FC_STYPE_DEAUTH);
 
1040
        memcpy(mgmt.da, addr, ETH_ALEN);
 
1041
        memcpy(mgmt.sa, own_addr, ETH_ALEN);
 
1042
        memcpy(mgmt.bssid, own_addr, ETH_ALEN);
 
1043
        mgmt.u.deauth.reason_code = host_to_le16(reason);
 
1044
        return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
 
1045
                                sizeof(mgmt.u.deauth));
 
1046
}
 
1047
 
 
1048
 
 
1049
static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
 
1050
                               int reason)
 
1051
{
 
1052
        struct hostap_driver_data *drv = priv;
 
1053
        struct ieee80211_mgmt mgmt;
 
1054
 
 
1055
        memset(&mgmt, 0, sizeof(mgmt));
 
1056
        mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 
1057
                                          WLAN_FC_STYPE_DISASSOC);
 
1058
        memcpy(mgmt.da, addr, ETH_ALEN);
 
1059
        memcpy(mgmt.sa, own_addr, ETH_ALEN);
 
1060
        memcpy(mgmt.bssid, own_addr, ETH_ALEN);
 
1061
        mgmt.u.disassoc.reason_code = host_to_le16(reason);
 
1062
        return  hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
 
1063
                                 sizeof(mgmt.u.disassoc));
 
1064
}
 
1065
 
 
1066
 
 
1067
static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
 
1068
                                                            u16 *num_modes,
 
1069
                                                            u16 *flags)
 
1070
{
 
1071
        struct hostapd_hw_modes *mode;
 
1072
        int i, clen, rlen;
 
1073
        const short chan2freq[14] = {
 
1074
                2412, 2417, 2422, 2427, 2432, 2437, 2442,
 
1075
                2447, 2452, 2457, 2462, 2467, 2472, 2484
 
1076
        };
 
1077
 
 
1078
        mode = os_zalloc(sizeof(struct hostapd_hw_modes));
 
1079
        if (mode == NULL)
 
1080
                return NULL;
 
1081
 
 
1082
        *num_modes = 1;
 
1083
        *flags = 0;
 
1084
 
 
1085
        mode->mode = HOSTAPD_MODE_IEEE80211B;
 
1086
        mode->num_channels = 14;
 
1087
        mode->num_rates = 4;
 
1088
 
 
1089
        clen = mode->num_channels * sizeof(struct hostapd_channel_data);
 
1090
        rlen = mode->num_rates * sizeof(int);
 
1091
 
 
1092
        mode->channels = os_zalloc(clen);
 
1093
        mode->rates = os_zalloc(rlen);
 
1094
        if (mode->channels == NULL || mode->rates == NULL) {
 
1095
                os_free(mode->channels);
 
1096
                os_free(mode->rates);
 
1097
                os_free(mode);
 
1098
                return NULL;
 
1099
        }
 
1100
 
 
1101
        for (i = 0; i < 14; i++) {
 
1102
                mode->channels[i].chan = i + 1;
 
1103
                mode->channels[i].freq = chan2freq[i];
 
1104
                /* TODO: Get allowed channel list from the driver */
 
1105
                if (i >= 11)
 
1106
                        mode->channels[i].flag = HOSTAPD_CHAN_DISABLED;
 
1107
        }
 
1108
 
 
1109
        mode->rates[0] = 10;
 
1110
        mode->rates[1] = 20;
 
1111
        mode->rates[2] = 55;
 
1112
        mode->rates[3] = 110;
 
1113
 
 
1114
        return mode;
 
1115
}
 
1116
 
 
1117
#else /* HOSTAPD */
 
1118
 
26
1119
struct wpa_driver_hostap_data {
27
1120
        void *wext; /* private data for driver_wext */
28
1121
        void *ctx;
32
1125
};
33
1126
 
34
1127
 
 
1128
static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg);
 
1129
 
 
1130
 
35
1131
static int hostapd_ioctl(struct wpa_driver_hostap_data *drv,
36
1132
                         struct prism2_hostapd_param *param,
37
1133
                         int len, int show_err)
45
1141
 
46
1142
        if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
47
1143
                int ret = errno;
48
 
                if (show_err) 
 
1144
                if (show_err)
49
1145
                        perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
50
1146
                return ret;
51
1147
        }
147
1243
}
148
1244
 
149
1245
 
150
 
static int wpa_driver_hostap_set_key(void *priv, wpa_alg alg,
151
 
                                     const u8 *addr, int key_idx,
152
 
                                     int set_tx, const u8 *seq, size_t seq_len,
 
1246
static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
 
1247
                                     enum wpa_alg alg, const u8 *addr,
 
1248
                                     int key_idx, int set_tx,
 
1249
                                     const u8 *seq, size_t seq_len,
153
1250
                                     const u8 *key, size_t key_len)
154
1251
{
155
1252
        struct wpa_driver_hostap_data *drv = priv;
232
1329
}
233
1330
 
234
1331
 
235
 
static int wpa_driver_hostap_set_drop_unencrypted(void *priv, int enabled)
236
 
{
237
 
        struct wpa_driver_hostap_data *drv = priv;
238
 
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
239
 
        return prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED, enabled);
240
 
}
241
 
 
242
 
 
243
1332
static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv,
244
1333
                                   int type)
245
1334
{
315
1404
 
316
1405
        wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
317
1406
 
 
1407
        if (prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED,
 
1408
                        params->drop_unencrypted) < 0)
 
1409
                ret = -1;
 
1410
        if (wpa_driver_hostap_set_auth_alg(drv, params->auth_alg) < 0)
 
1411
                ret = -1;
318
1412
        if (params->mode != drv->current_mode) {
319
1413
                /* At the moment, Host AP driver requires host_roaming=2 for
320
1414
                 * infrastructure mode and host_roaming=0 for adhoc. */
365
1459
}
366
1460
 
367
1461
 
368
 
static int wpa_driver_hostap_scan(void *priv, const u8 *ssid, size_t ssid_len)
 
1462
static int wpa_driver_hostap_scan(void *priv,
 
1463
                                  struct wpa_driver_scan_params *params)
369
1464
{
370
1465
        struct wpa_driver_hostap_data *drv = priv;
371
1466
        struct prism2_hostapd_param param;
372
1467
        int ret;
 
1468
        const u8 *ssid = params->ssids[0].ssid;
 
1469
        size_t ssid_len = params->ssids[0].ssid_len;
373
1470
 
374
1471
        if (ssid == NULL) {
375
1472
                /* Use standard Linux Wireless Extensions ioctl if possible
376
1473
                 * because some drivers using hostap code in wpa_supplicant
377
1474
                 * might not support Host AP specific scan request (with SSID
378
1475
                 * info). */
379
 
                return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
 
1476
                return wpa_driver_wext_scan(drv->wext, params);
380
1477
        }
381
1478
 
382
1479
        if (ssid_len > 32)
404
1501
        struct wpa_driver_hostap_data *drv = priv;
405
1502
        int algs = 0;
406
1503
 
407
 
        if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
 
1504
        if (auth_alg & WPA_AUTH_ALG_OPEN)
408
1505
                algs |= 1;
409
 
        if (auth_alg & AUTH_ALG_SHARED_KEY)
 
1506
        if (auth_alg & WPA_AUTH_ALG_SHARED)
410
1507
                algs |= 2;
411
 
        if (auth_alg & AUTH_ALG_LEAP)
 
1508
        if (auth_alg & WPA_AUTH_ALG_LEAP)
412
1509
                algs |= 4;
413
1510
        if (algs == 0)
414
1511
                algs = 1; /* at least one algorithm should be set */
479
1576
                wpa_driver_wext_alternative_ifindex(drv->wext, ifname2);
480
1577
        }
481
1578
 
 
1579
        wpa_driver_hostap_set_wpa(drv, 1);
 
1580
 
482
1581
        return drv;
483
1582
}
484
1583
 
486
1585
static void wpa_driver_hostap_deinit(void *priv)
487
1586
{
488
1587
        struct wpa_driver_hostap_data *drv = priv;
 
1588
        wpa_driver_hostap_set_wpa(drv, 0);
489
1589
        wpa_driver_wext_deinit(drv->wext);
490
1590
        close(drv->sock);
491
1591
        os_free(drv);
492
1592
}
493
1593
 
 
1594
#endif /* HOSTAPD */
 
1595
 
494
1596
 
495
1597
const struct wpa_driver_ops wpa_driver_hostap_ops = {
496
1598
        .name = "hostap",
497
1599
        .desc = "Host AP driver (Intersil Prism2/2.5/3)",
 
1600
        .set_key = wpa_driver_hostap_set_key,
 
1601
#ifdef HOSTAPD
 
1602
        .hapd_init = hostap_init,
 
1603
        .hapd_deinit = hostap_driver_deinit,
 
1604
        .set_ieee8021x = hostap_set_ieee8021x,
 
1605
        .set_privacy = hostap_set_privacy,
 
1606
        .get_seqnum = hostap_get_seqnum,
 
1607
        .flush = hostap_flush,
 
1608
        .set_generic_elem = hostap_set_generic_elem,
 
1609
        .read_sta_data = hostap_read_sta_data,
 
1610
        .hapd_send_eapol = hostap_send_eapol,
 
1611
        .sta_set_flags = hostap_sta_set_flags,
 
1612
        .sta_deauth = hostap_sta_deauth,
 
1613
        .sta_disassoc = hostap_sta_disassoc,
 
1614
        .sta_remove = hostap_sta_remove,
 
1615
        .hapd_set_ssid = hostap_set_ssid,
 
1616
        .send_mlme = hostap_send_mlme,
 
1617
        .sta_add = hostap_sta_add,
 
1618
        .get_inact_sec = hostap_get_inact_sec,
 
1619
        .sta_clear_stats = hostap_sta_clear_stats,
 
1620
        .get_hw_feature_data = hostap_get_hw_feature_data,
 
1621
        .set_ap_wps_ie = hostap_set_ap_wps_ie,
 
1622
#else /* HOSTAPD */
498
1623
        .get_bssid = wpa_driver_hostap_get_bssid,
499
1624
        .get_ssid = wpa_driver_hostap_get_ssid,
500
 
        .set_wpa = wpa_driver_hostap_set_wpa,
501
 
        .set_key = wpa_driver_hostap_set_key,
502
1625
        .set_countermeasures = wpa_driver_hostap_set_countermeasures,
503
 
        .set_drop_unencrypted = wpa_driver_hostap_set_drop_unencrypted,
504
 
        .scan = wpa_driver_hostap_scan,
 
1626
        .scan2 = wpa_driver_hostap_scan,
505
1627
        .get_scan_results2 = wpa_driver_hostap_get_scan_results,
506
1628
        .deauthenticate = wpa_driver_hostap_deauthenticate,
507
1629
        .disassociate = wpa_driver_hostap_disassociate,
508
1630
        .associate = wpa_driver_hostap_associate,
509
 
        .set_auth_alg = wpa_driver_hostap_set_auth_alg,
510
1631
        .init = wpa_driver_hostap_init,
511
1632
        .deinit = wpa_driver_hostap_deinit,
512
1633
        .set_operstate = wpa_driver_hostap_set_operstate,
 
1634
#endif /* HOSTAPD */
513
1635
};