Share a single Linux ioctl helper fo setting interface up/down
[libeap.git] / src / drivers / driver_atheros.c
1 /*
2  * hostapd / Driver interaction with Atheros driver
3  * Copyright (c) 2004, Sam Leffler <sam@errno.com>
4  * Copyright (c) 2004, Video54 Technologies
5  * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
6  * Copyright (c) 2009, Atheros Communications
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * Alternatively, this software may be distributed under the terms of BSD
13  * license.
14  *
15  * See README and COPYING for more details.
16  */
17
18 #include "includes.h"
19 #include <net/if.h>
20 #include <sys/ioctl.h>
21
22 #include "common.h"
23 #ifndef _BYTE_ORDER
24 #ifdef WORDS_BIGENDIAN
25 #define _BYTE_ORDER _BIG_ENDIAN
26 #else
27 #define _BYTE_ORDER _LITTLE_ENDIAN
28 #endif
29 #endif /* _BYTE_ORDER */
30
31 #include <net80211/ieee80211.h>
32 #include <net80211/_ieee80211.h>
33 #include <net80211/ieee80211_crypto.h>
34
35 /*
36  * Note, the ATH_WPS_IE setting must match with the driver build.. If the
37  * driver does not include this, the IEEE80211_IOCTL_GETWPAIE ioctl will fail.
38  */
39 #define ATH_WPS_IE
40 #include <net80211/ieee80211_ioctl.h>
41
42 #ifdef CONFIG_WPS
43 #ifdef IEEE80211_IOCTL_FILTERFRAME
44 #include <netpacket/packet.h>
45
46 #ifndef ETH_P_80211_RAW
47 #define ETH_P_80211_RAW 0x0019
48 #endif
49 #endif /* IEEE80211_IOCTL_FILTERFRAME */
50 #endif /* CONFIG_WPS */
51
52 /*
53  * Avoid conflicts with hostapd definitions by undefining couple of defines
54  * from madwifi header files.
55  */
56 #undef WPA_OUI_TYPE
57 #undef WME_OUI_TYPE
58
59 #include "wireless_copy.h"
60
61 #include "driver.h"
62 #include "eloop.h"
63 #include "priv_netlink.h"
64 #include "l2_packet/l2_packet.h"
65 #include "common/ieee802_11_defs.h"
66 #include "netlink.h"
67 #include "linux_ioctl.h"
68
69
70 struct madwifi_driver_data {
71         struct hostapd_data *hapd;              /* back pointer */
72
73         char    iface[IFNAMSIZ + 1];
74         int     ifindex;
75         struct l2_packet_data *sock_xmit;       /* raw packet xmit socket */
76         struct l2_packet_data *sock_recv;       /* raw packet recv socket */
77         int     ioctl_sock;                     /* socket for ioctl() use */
78         struct netlink_data *netlink;
79         int     we_version;
80         u8      acct_mac[ETH_ALEN];
81         struct hostap_sta_driver_data acct_data;
82
83         struct l2_packet_data *sock_raw; /* raw 802.11 management frames */
84 };
85
86 static int madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
87                               int reason_code);
88
89 static int
90 set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len)
91 {
92         struct iwreq iwr;
93         int do_inline = len < IFNAMSIZ;
94
95         /* Certain ioctls must use the non-inlined method */
96         if (op == IEEE80211_IOCTL_SET_APPIEBUF ||
97             op == IEEE80211_IOCTL_FILTERFRAME)
98                 do_inline = 0;
99
100         memset(&iwr, 0, sizeof(iwr));
101         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
102         if (do_inline) {
103                 /*
104                  * Argument data fits inline; put it there.
105                  */
106                 memcpy(iwr.u.name, data, len);
107         } else {
108                 /*
109                  * Argument data too big for inline transfer; setup a
110                  * parameter block instead; the kernel will transfer
111                  * the data for the driver.
112                  */
113                 iwr.u.data.pointer = data;
114                 iwr.u.data.length = len;
115         }
116
117         if (ioctl(drv->ioctl_sock, op, &iwr) < 0) {
118                 int first = IEEE80211_IOCTL_SETPARAM;
119                 static const char *opnames[] = {
120                         "ioctl[IEEE80211_IOCTL_SETPARAM]",
121                         "ioctl[IEEE80211_IOCTL_GETPARAM]",
122                         "ioctl[IEEE80211_IOCTL_SETKEY]",
123                         "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
124                         "ioctl[IEEE80211_IOCTL_DELKEY]",
125                         "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
126                         "ioctl[IEEE80211_IOCTL_SETMLME]",
127                         "ioctl[IEEE80211_IOCTL_GETCHANINFO]",
128                         "ioctl[IEEE80211_IOCTL_SETOPTIE]",
129                         "ioctl[IEEE80211_IOCTL_GETOPTIE]",
130                         "ioctl[IEEE80211_IOCTL_ADDMAC]",
131                         "ioctl[IEEE80211_IOCTL_DELMAC]",
132                         "ioctl[IEEE80211_IOCTL_GETCHANLIST]",
133                         "ioctl[IEEE80211_IOCTL_SETCHANLIST]",
134                         "ioctl[IEEE80211_IOCTL_KICKMAC]",
135                         "ioctl[IEEE80211_IOCTL_CHANSWITCH]",
136                         "ioctl[IEEE80211_IOCTL_GETMODE]",
137                         "ioctl[IEEE80211_IOCTL_SETMODE]",
138                         "ioctl[IEEE80211_IOCTL_GET_APPIEBUF]",
139                         "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
140                         NULL,
141                         "ioctl[IEEE80211_IOCTL_FILTERFRAME]",
142                 };
143                 int idx = op - first;
144                 if (first <= op &&
145                     idx < (int) (sizeof(opnames) / sizeof(opnames[0])) &&
146                     opnames[idx])
147                         perror(opnames[idx]);
148                 else {
149                         perror("ioctl[unknown???]");
150                         wpa_printf(MSG_DEBUG, "Failed ioctl: 0x%x", op);
151                 }
152                 return -1;
153         }
154         return 0;
155 }
156
157 static int
158 set80211param(struct madwifi_driver_data *drv, int op, int arg)
159 {
160         struct iwreq iwr;
161
162         memset(&iwr, 0, sizeof(iwr));
163         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
164         iwr.u.mode = op;
165         memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg));
166
167         if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
168                 perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
169                 wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d "
170                            "arg %d)", __func__, op, arg);
171                 return -1;
172         }
173         return 0;
174 }
175
176 #ifndef CONFIG_NO_STDOUT_DEBUG
177 static const char *
178 ether_sprintf(const u8 *addr)
179 {
180         static char buf[sizeof(MACSTR)];
181
182         if (addr != NULL)
183                 snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
184         else
185                 snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
186         return buf;
187 }
188 #endif /* CONFIG_NO_STDOUT_DEBUG */
189
190 /*
191  * Configure WPA parameters.
192  */
193 static int
194 madwifi_configure_wpa(struct madwifi_driver_data *drv,
195                       struct wpa_bss_params *params)
196 {
197         int v;
198
199         switch (params->wpa_group) {
200         case WPA_CIPHER_CCMP:
201                 v = IEEE80211_CIPHER_AES_CCM;
202                 break;
203         case WPA_CIPHER_TKIP:
204                 v = IEEE80211_CIPHER_TKIP;
205                 break;
206         case WPA_CIPHER_WEP104:
207                 v = IEEE80211_CIPHER_WEP;
208                 break;
209         case WPA_CIPHER_WEP40:
210                 v = IEEE80211_CIPHER_WEP;
211                 break;
212         case WPA_CIPHER_NONE:
213                 v = IEEE80211_CIPHER_NONE;
214                 break;
215         default:
216                 wpa_printf(MSG_ERROR, "Unknown group key cipher %u",
217                            params->wpa_group);
218                 return -1;
219         }
220         wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v);
221         if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) {
222                 printf("Unable to set group key cipher to %u\n", v);
223                 return -1;
224         }
225         if (v == IEEE80211_CIPHER_WEP) {
226                 /* key length is done only for specific ciphers */
227                 v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
228                 if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) {
229                         printf("Unable to set group key length to %u\n", v);
230                         return -1;
231                 }
232         }
233
234         v = 0;
235         if (params->wpa_pairwise & WPA_CIPHER_CCMP)
236                 v |= 1<<IEEE80211_CIPHER_AES_CCM;
237         if (params->wpa_pairwise & WPA_CIPHER_TKIP)
238                 v |= 1<<IEEE80211_CIPHER_TKIP;
239         if (params->wpa_pairwise & WPA_CIPHER_NONE)
240                 v |= 1<<IEEE80211_CIPHER_NONE;
241         wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
242         if (set80211param(drv, IEEE80211_PARAM_UCASTCIPHERS, v)) {
243                 printf("Unable to set pairwise key ciphers to 0x%x\n", v);
244                 return -1;
245         }
246
247         wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
248                    __func__, params->wpa_key_mgmt);
249         if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS,
250                           params->wpa_key_mgmt)) {
251                 printf("Unable to set key management algorithms to 0x%x\n",
252                         params->wpa_key_mgmt);
253                 return -1;
254         }
255
256         v = 0;
257         if (params->rsn_preauth)
258                 v |= BIT(0);
259         wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
260                    __func__, params->rsn_preauth);
261         if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) {
262                 printf("Unable to set RSN capabilities to 0x%x\n", v);
263                 return -1;
264         }
265
266         wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, params->wpa);
267         if (set80211param(drv, IEEE80211_PARAM_WPA, params->wpa)) {
268                 printf("Unable to set WPA to %u\n", params->wpa);
269                 return -1;
270         }
271         return 0;
272 }
273
274 static int
275 madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
276 {
277         struct madwifi_driver_data *drv = priv;
278
279         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled);
280
281         if (!params->enabled) {
282                 /* XXX restore state */
283                 return set80211param(priv, IEEE80211_PARAM_AUTHMODE,
284                         IEEE80211_AUTH_AUTO);
285         }
286         if (!params->wpa && !params->ieee802_1x) {
287                 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
288                         HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
289                 return -1;
290         }
291         if (params->wpa && madwifi_configure_wpa(drv, params) != 0) {
292                 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
293                         HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
294                 return -1;
295         }
296         if (set80211param(priv, IEEE80211_PARAM_AUTHMODE,
297                 (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
298                 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
299                         HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
300                 return -1;
301         }
302
303         return 0;
304 }
305
306 static int
307 madwifi_set_privacy(const char *ifname, void *priv, int enabled)
308 {
309         struct madwifi_driver_data *drv = priv;
310
311         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
312
313         return set80211param(drv, IEEE80211_PARAM_PRIVACY, enabled);
314 }
315
316 static int
317 madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized)
318 {
319         struct madwifi_driver_data *drv = priv;
320         struct ieee80211req_mlme mlme;
321         int ret;
322
323         wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d",
324                    __func__, ether_sprintf(addr), authorized);
325
326         if (authorized)
327                 mlme.im_op = IEEE80211_MLME_AUTHORIZE;
328         else
329                 mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
330         mlme.im_reason = 0;
331         memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
332         ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
333         if (ret < 0) {
334                 wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR,
335                            __func__, authorized ? "" : "un", MAC2STR(addr));
336         }
337
338         return ret;
339 }
340
341 static int
342 madwifi_sta_set_flags(void *priv, const u8 *addr, int total_flags,
343                       int flags_or, int flags_and)
344 {
345         /* For now, only support setting Authorized flag */
346         if (flags_or & WPA_STA_AUTHORIZED)
347                 return madwifi_set_sta_authorized(priv, addr, 1);
348         if (!(flags_and & WPA_STA_AUTHORIZED))
349                 return madwifi_set_sta_authorized(priv, addr, 0);
350         return 0;
351 }
352
353 static int
354 madwifi_del_key(void *priv, const u8 *addr, int key_idx)
355 {
356         struct madwifi_driver_data *drv = priv;
357         struct ieee80211req_del_key wk;
358         int ret;
359
360         wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d",
361                    __func__, ether_sprintf(addr), key_idx);
362
363         memset(&wk, 0, sizeof(wk));
364         if (addr != NULL) {
365                 memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
366                 wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE;
367         } else {
368                 wk.idk_keyix = key_idx;
369         }
370
371         ret = set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk));
372         if (ret < 0) {
373                 wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s"
374                            " key_idx %d)", __func__, ether_sprintf(addr),
375                            key_idx);
376         }
377
378         return ret;
379 }
380
381 static int
382 madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
383                 const u8 *addr, int key_idx, int set_tx, const u8 *seq,
384                 size_t seq_len, const u8 *key, size_t key_len)
385 {
386         struct madwifi_driver_data *drv = priv;
387         struct ieee80211req_key wk;
388         u_int8_t cipher;
389         int ret;
390
391         if (alg == WPA_ALG_NONE)
392                 return madwifi_del_key(drv, addr, key_idx);
393
394         wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d",
395                    __func__, alg, ether_sprintf(addr), key_idx);
396
397         switch (alg) {
398         case WPA_ALG_WEP:
399                 cipher = IEEE80211_CIPHER_WEP;
400                 break;
401         case WPA_ALG_TKIP:
402                 cipher = IEEE80211_CIPHER_TKIP;
403                 break;
404         case WPA_ALG_CCMP:
405                 cipher = IEEE80211_CIPHER_AES_CCM;
406                 break;
407         default:
408                 printf("%s: unknown/unsupported algorithm %d\n",
409                         __func__, alg);
410                 return -1;
411         }
412
413         if (key_len > sizeof(wk.ik_keydata)) {
414                 printf("%s: key length %lu too big\n", __func__,
415                        (unsigned long) key_len);
416                 return -3;
417         }
418
419         memset(&wk, 0, sizeof(wk));
420         wk.ik_type = cipher;
421         wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
422         if (addr == NULL) {
423                 memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
424                 wk.ik_keyix = key_idx;
425                 wk.ik_flags |= IEEE80211_KEY_DEFAULT;
426         } else {
427                 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
428                 wk.ik_keyix = IEEE80211_KEYIX_NONE;
429         }
430         wk.ik_keylen = key_len;
431         memcpy(wk.ik_keydata, key, key_len);
432
433         ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));
434         if (ret < 0) {
435                 wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s"
436                            " key_idx %d alg %d key_len %lu set_tx %d)",
437                            __func__, ether_sprintf(wk.ik_macaddr), key_idx,
438                            alg, (unsigned long) key_len, set_tx);
439         }
440
441         return ret;
442 }
443
444
445 static int
446 madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
447                    u8 *seq)
448 {
449         struct madwifi_driver_data *drv = priv;
450         struct ieee80211req_key wk;
451
452         wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
453                    __func__, ether_sprintf(addr), idx);
454
455         memset(&wk, 0, sizeof(wk));
456         if (addr == NULL)
457                 memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
458         else
459                 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
460         wk.ik_keyix = idx;
461
462         if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) {
463                 wpa_printf(MSG_DEBUG, "%s: Failed to get encryption data "
464                            "(addr " MACSTR " key_idx %d)",
465                            __func__, MAC2STR(wk.ik_macaddr), idx);
466                 return -1;
467         }
468
469 #ifdef WORDS_BIGENDIAN
470         {
471                 /*
472                  * wk.ik_keytsc is in host byte order (big endian), need to
473                  * swap it to match with the byte order used in WPA.
474                  */
475                 int i;
476                 u8 tmp[WPA_KEY_RSC_LEN];
477                 memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
478                 for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
479                         seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
480                 }
481         }
482 #else /* WORDS_BIGENDIAN */
483         memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
484 #endif /* WORDS_BIGENDIAN */
485         return 0;
486 }
487
488
489 static int
490 madwifi_flush(void *priv)
491 {
492         u8 allsta[IEEE80211_ADDR_LEN];
493         memset(allsta, 0xff, IEEE80211_ADDR_LEN);
494         return madwifi_sta_deauth(priv, NULL, allsta,
495                                   IEEE80211_REASON_AUTH_LEAVE);
496 }
497
498
499 static int
500 madwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
501                              const u8 *addr)
502 {
503         struct madwifi_driver_data *drv = priv;
504         struct ieee80211req_sta_stats stats;
505
506         memset(data, 0, sizeof(*data));
507
508         /*
509          * Fetch statistics for station from the system.
510          */
511         memset(&stats, 0, sizeof(stats));
512         memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
513         if (set80211priv(drv, IEEE80211_IOCTL_STA_STATS,
514                          &stats, sizeof(stats))) {
515                 wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr "
516                            MACSTR ")", __func__, MAC2STR(addr));
517                 if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
518                         memcpy(data, &drv->acct_data, sizeof(*data));
519                         return 0;
520                 }
521
522                 printf("Failed to get station stats information element.\n");
523                 return -1;
524         }
525
526         data->rx_packets = stats.is_stats.ns_rx_data;
527         data->rx_bytes = stats.is_stats.ns_rx_bytes;
528         data->tx_packets = stats.is_stats.ns_tx_data;
529         data->tx_bytes = stats.is_stats.ns_tx_bytes;
530         return 0;
531 }
532
533
534 static int
535 madwifi_sta_clear_stats(void *priv, const u8 *addr)
536 {
537         struct madwifi_driver_data *drv = priv;
538         struct ieee80211req_mlme mlme;
539         int ret;
540
541         wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr));
542
543         mlme.im_op = IEEE80211_MLME_CLEAR_STATS;
544         memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
545         ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
546                            sizeof(mlme));
547         if (ret < 0) {
548                 wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr "
549                            MACSTR ")", __func__, MAC2STR(addr));
550         }
551
552         return ret;
553 }
554
555
556 static int
557 madwifi_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
558 {
559         /*
560          * Do nothing; we setup parameters at startup that define the
561          * contents of the beacon information element.
562          */
563         return 0;
564 }
565
566 static int
567 madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
568                    int reason_code)
569 {
570         struct madwifi_driver_data *drv = priv;
571         struct ieee80211req_mlme mlme;
572         int ret;
573
574         wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
575                    __func__, ether_sprintf(addr), reason_code);
576
577         mlme.im_op = IEEE80211_MLME_DEAUTH;
578         mlme.im_reason = reason_code;
579         memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
580         ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
581         if (ret < 0) {
582                 wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR
583                            " reason %d)",
584                            __func__, MAC2STR(addr), reason_code);
585         }
586
587         return ret;
588 }
589
590 static int
591 madwifi_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
592                      int reason_code)
593 {
594         struct madwifi_driver_data *drv = priv;
595         struct ieee80211req_mlme mlme;
596         int ret;
597
598         wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
599                    __func__, ether_sprintf(addr), reason_code);
600
601         mlme.im_op = IEEE80211_MLME_DISASSOC;
602         mlme.im_reason = reason_code;
603         memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
604         ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
605         if (ret < 0) {
606                 wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr "
607                            MACSTR " reason %d)",
608                            __func__, MAC2STR(addr), reason_code);
609         }
610
611         return ret;
612 }
613
614 #ifdef CONFIG_WPS
615 static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
616                                 size_t len)
617 {
618         struct madwifi_driver_data *drv = ctx;
619         const struct ieee80211_mgmt *mgmt;
620         u16 fc;
621         union wpa_event_data event;
622
623         /* Send Probe Request information to WPS processing */
624
625         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
626                 return;
627         mgmt = (const struct ieee80211_mgmt *) buf;
628
629         fc = le_to_host16(mgmt->frame_control);
630         if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT ||
631             WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ)
632                 return;
633
634         os_memset(&event, 0, sizeof(event));
635         event.rx_probe_req.sa = mgmt->sa;
636         event.rx_probe_req.ie = mgmt->u.probe_req.variable;
637         event.rx_probe_req.ie_len =
638                 len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
639         wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event);
640 }
641 #endif /* CONFIG_WPS */
642
643 static int madwifi_receive_probe_req(struct madwifi_driver_data *drv)
644 {
645         int ret = 0;
646 #ifdef CONFIG_WPS
647         struct ieee80211req_set_filter filt;
648
649         wpa_printf(MSG_DEBUG, "%s Enter", __func__);
650         filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ;
651
652         ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt,
653                            sizeof(struct ieee80211req_set_filter));
654         if (ret)
655                 return ret;
656
657         drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW,
658                                        madwifi_raw_receive, drv, 1);
659         if (drv->sock_raw == NULL)
660                 return -1;
661 #endif /* CONFIG_WPS */
662         return ret;
663 }
664
665 #ifdef CONFIG_WPS
666 static int
667 madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
668 {
669         struct madwifi_driver_data *drv = priv;
670         u8 buf[256];
671         struct ieee80211req_getset_appiebuf *beac_ie;
672
673         wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
674                    (unsigned long) len);
675
676         beac_ie = (struct ieee80211req_getset_appiebuf *) buf;
677         beac_ie->app_frmtype = frametype;
678         beac_ie->app_buflen = len;
679         memcpy(&(beac_ie->app_buf[0]), ie, len);
680
681         return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie,
682                             sizeof(struct ieee80211req_getset_appiebuf) + len);
683 }
684
685 static int
686 madwifi_set_ap_wps_ie(const char *ifname, void *priv,
687                       const struct wpabuf *beacon,
688                       const struct wpabuf *proberesp)
689 {
690         if (madwifi_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
691                                beacon ? wpabuf_len(beacon) : 0,
692                                IEEE80211_APPIE_FRAME_BEACON))
693                 return -1;
694         return madwifi_set_wps_ie(priv,
695                                   proberesp ? wpabuf_head(proberesp) : NULL,
696                                   proberesp ? wpabuf_len(proberesp): 0,
697                                   IEEE80211_APPIE_FRAME_PROBE_RESP);
698 }
699 #else /* CONFIG_WPS */
700 #define madwifi_set_ap_wps_ie NULL
701 #endif /* CONFIG_WPS */
702
703 static void
704 madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
705 {
706         struct hostapd_data *hapd = drv->hapd;
707         struct ieee80211req_wpaie ie;
708         int ielen = 0;
709         u8 *iebuf = NULL;
710
711         /*
712          * Fetch negotiated WPA/RSN parameters from the system.
713          */
714         memset(&ie, 0, sizeof(ie));
715         memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
716         if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) {
717                 /*
718                  * See ATH_WPS_IE comment in the beginning of the file for a
719                  * possible cause for the failure..
720                  */
721                 wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s",
722                            __func__, strerror(errno));
723                 goto no_ie;
724         }
725         wpa_hexdump(MSG_MSGDUMP, "madwifi req WPA IE",
726                     ie.wpa_ie, IEEE80211_MAX_OPT_IE);
727         wpa_hexdump(MSG_MSGDUMP, "madwifi req RSN IE",
728                     ie.rsn_ie, IEEE80211_MAX_OPT_IE);
729         iebuf = ie.wpa_ie;
730         /* madwifi seems to return some random data if WPA/RSN IE is not set.
731          * Assume the IE was not included if the IE type is unknown. */
732         if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC)
733                 iebuf[1] = 0;
734         if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) {
735                 /* madwifi-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not
736                  * set. This is needed for WPA2. */
737                 iebuf = ie.rsn_ie;
738                 if (iebuf[0] != WLAN_EID_RSN)
739                         iebuf[1] = 0;
740         }
741
742         ielen = iebuf[1];
743         if (ielen == 0)
744                 iebuf = NULL;
745         else
746                 ielen += 2;
747
748 no_ie:
749         drv_event_assoc(hapd, addr, iebuf, ielen);
750
751         if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
752                 /* Cached accounting data is not valid anymore. */
753                 memset(drv->acct_mac, 0, ETH_ALEN);
754                 memset(&drv->acct_data, 0, sizeof(drv->acct_data));
755         }
756 }
757
758 static void
759 madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv,
760                                        char *custom, char *end)
761 {
762         wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
763
764         if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
765                 char *pos;
766                 u8 addr[ETH_ALEN];
767                 pos = strstr(custom, "addr=");
768                 if (pos == NULL) {
769                         wpa_printf(MSG_DEBUG,
770                                    "MLME-MICHAELMICFAILURE.indication "
771                                    "without sender address ignored");
772                         return;
773                 }
774                 pos += 5;
775                 if (hwaddr_aton(pos, addr) == 0) {
776                         union wpa_event_data data;
777                         os_memset(&data, 0, sizeof(data));
778                         data.michael_mic_failure.unicast = 1;
779                         data.michael_mic_failure.src = addr;
780                         wpa_supplicant_event(drv->hapd,
781                                              EVENT_MICHAEL_MIC_FAILURE, &data);
782                 } else {
783                         wpa_printf(MSG_DEBUG,
784                                    "MLME-MICHAELMICFAILURE.indication "
785                                    "with invalid MAC address");
786                 }
787         } else if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) {
788                 char *key, *value;
789                 u32 val;
790                 key = custom;
791                 while ((key = strchr(key, '\n')) != NULL) {
792                         key++;
793                         value = strchr(key, '=');
794                         if (value == NULL)
795                                 continue;
796                         *value++ = '\0';
797                         val = strtoul(value, NULL, 10);
798                         if (strcmp(key, "mac") == 0)
799                                 hwaddr_aton(value, drv->acct_mac);
800                         else if (strcmp(key, "rx_packets") == 0)
801                                 drv->acct_data.rx_packets = val;
802                         else if (strcmp(key, "tx_packets") == 0)
803                                 drv->acct_data.tx_packets = val;
804                         else if (strcmp(key, "rx_bytes") == 0)
805                                 drv->acct_data.rx_bytes = val;
806                         else if (strcmp(key, "tx_bytes") == 0)
807                                 drv->acct_data.tx_bytes = val;
808                         key = value;
809                 }
810 #ifdef CONFIG_WPS
811         } else if (strncmp(custom, "PUSH-BUTTON.indication", 22) == 0) {
812                 /* Some atheros kernels send push button as a wireless event */
813                 /* PROBLEM! this event is received for ALL BSSs ...
814                  * so all are enabled for WPS... ugh.
815                  */
816                 wpa_supplicant_event(drv->hapd, EVENT_WPS_BUTTON_PUSHED, NULL);
817         } else if (strncmp(custom, "Manage.prob_req ", 16) == 0) {
818                 /*
819                  * Atheros driver uses a hack to pass Probe Request frames as a
820                  * binary data in the custom wireless event. The old way (using
821                  * packet sniffing) didn't work when bridging.
822                  * Format: "Manage.prob_req <frame len>" | zero padding | frame
823                  */
824 #define WPS_FRAM_TAG_SIZE 30 /* hardcoded in driver */
825                 int len = atoi(custom + 16);
826                 if (len < 0 || custom + WPS_FRAM_TAG_SIZE + len > end) {
827                         wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req event "
828                                    "length %d", len);
829                         return;
830                 }
831                 madwifi_raw_receive(drv, NULL,
832                                     (u8 *) custom + WPS_FRAM_TAG_SIZE, len);
833 #endif /* CONFIG_WPS */
834         }
835 }
836
837 static void
838 madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
839                                 char *data, int len)
840 {
841         struct iw_event iwe_buf, *iwe = &iwe_buf;
842         char *pos, *end, *custom, *buf;
843
844         pos = data;
845         end = data + len;
846
847         while (pos + IW_EV_LCP_LEN <= end) {
848                 /* Event data may be unaligned, so make a local, aligned copy
849                  * before processing. */
850                 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
851                 wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d",
852                            iwe->cmd, iwe->len);
853                 if (iwe->len <= IW_EV_LCP_LEN)
854                         return;
855
856                 custom = pos + IW_EV_POINT_LEN;
857                 if (drv->we_version > 18 &&
858                     (iwe->cmd == IWEVMICHAELMICFAILURE ||
859                      iwe->cmd == IWEVASSOCREQIE ||
860                      iwe->cmd == IWEVCUSTOM)) {
861                         /* WE-19 removed the pointer from struct iw_point */
862                         char *dpos = (char *) &iwe_buf.u.data.length;
863                         int dlen = dpos - (char *) &iwe_buf;
864                         memcpy(dpos, pos + IW_EV_LCP_LEN,
865                                sizeof(struct iw_event) - dlen);
866                 } else {
867                         memcpy(&iwe_buf, pos, sizeof(struct iw_event));
868                         custom += IW_EV_POINT_OFF;
869                 }
870
871                 switch (iwe->cmd) {
872                 case IWEVEXPIRED:
873                         drv_event_disassoc(drv->hapd,
874                                            (u8 *) iwe->u.addr.sa_data);
875                         break;
876                 case IWEVREGISTERED:
877                         madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
878                         break;
879                 case IWEVASSOCREQIE:
880                         /* Driver hack.. Use IWEVASSOCREQIE to bypass
881                          * IWEVCUSTOM size limitations. Need to handle this
882                          * just like IWEVCUSTOM.
883                          */
884                 case IWEVCUSTOM:
885                         if (custom + iwe->u.data.length > end)
886                                 return;
887                         buf = malloc(iwe->u.data.length + 1);
888                         if (buf == NULL)
889                                 return;         /* XXX */
890                         memcpy(buf, custom, iwe->u.data.length);
891                         buf[iwe->u.data.length] = '\0';
892                         madwifi_wireless_event_wireless_custom(
893                                 drv, buf, buf + iwe->u.data.length);
894                         free(buf);
895                         break;
896                 }
897
898                 pos += iwe->len;
899         }
900 }
901
902
903 static void
904 madwifi_wireless_event_rtm_newlink(void *ctx,
905                                    struct ifinfomsg *ifi, u8 *buf, size_t len)
906 {
907         struct madwifi_driver_data *drv = ctx;
908         int attrlen, rta_len;
909         struct rtattr *attr;
910
911         if (ifi->ifi_index != drv->ifindex)
912                 return;
913
914         attrlen = len;
915         attr = (struct rtattr *) buf;
916
917         rta_len = RTA_ALIGN(sizeof(struct rtattr));
918         while (RTA_OK(attr, attrlen)) {
919                 if (attr->rta_type == IFLA_WIRELESS) {
920                         madwifi_wireless_event_wireless(
921                                 drv, ((char *) attr) + rta_len,
922                                 attr->rta_len - rta_len);
923                 }
924                 attr = RTA_NEXT(attr, attrlen);
925         }
926 }
927
928
929 static int
930 madwifi_get_we_version(struct madwifi_driver_data *drv)
931 {
932         struct iw_range *range;
933         struct iwreq iwr;
934         int minlen;
935         size_t buflen;
936
937         drv->we_version = 0;
938
939         /*
940          * Use larger buffer than struct iw_range in order to allow the
941          * structure to grow in the future.
942          */
943         buflen = sizeof(struct iw_range) + 500;
944         range = os_zalloc(buflen);
945         if (range == NULL)
946                 return -1;
947
948         memset(&iwr, 0, sizeof(iwr));
949         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
950         iwr.u.data.pointer = (caddr_t) range;
951         iwr.u.data.length = buflen;
952
953         minlen = ((char *) &range->enc_capa) - (char *) range +
954                 sizeof(range->enc_capa);
955
956         if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
957                 perror("ioctl[SIOCGIWRANGE]");
958                 free(range);
959                 return -1;
960         } else if (iwr.u.data.length >= minlen &&
961                    range->we_version_compiled >= 18) {
962                 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
963                            "WE(source)=%d enc_capa=0x%x",
964                            range->we_version_compiled,
965                            range->we_version_source,
966                            range->enc_capa);
967                 drv->we_version = range->we_version_compiled;
968         }
969
970         free(range);
971         return 0;
972 }
973
974
975 static int
976 madwifi_wireless_event_init(struct madwifi_driver_data *drv)
977 {
978         struct netlink_config *cfg;
979
980         madwifi_get_we_version(drv);
981
982         cfg = os_zalloc(sizeof(*cfg));
983         if (cfg == NULL)
984                 return -1;
985         cfg->ctx = drv;
986         cfg->newlink_cb = madwifi_wireless_event_rtm_newlink;
987         drv->netlink = netlink_init(cfg);
988         if (drv->netlink == NULL) {
989                 os_free(cfg);
990                 return -1;
991         }
992
993         return 0;
994 }
995
996
997 static int
998 madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
999                    int encrypt, const u8 *own_addr)
1000 {
1001         struct madwifi_driver_data *drv = priv;
1002         unsigned char buf[3000];
1003         unsigned char *bp = buf;
1004         struct l2_ethhdr *eth;
1005         size_t len;
1006         int status;
1007
1008         /*
1009          * Prepend the Ethernet header.  If the caller left us
1010          * space at the front we could just insert it but since
1011          * we don't know we copy to a local buffer.  Given the frequency
1012          * and size of frames this probably doesn't matter.
1013          */
1014         len = data_len + sizeof(struct l2_ethhdr);
1015         if (len > sizeof(buf)) {
1016                 bp = malloc(len);
1017                 if (bp == NULL) {
1018                         printf("EAPOL frame discarded, cannot malloc temp "
1019                                "buffer of size %lu!\n", (unsigned long) len);
1020                         return -1;
1021                 }
1022         }
1023         eth = (struct l2_ethhdr *) bp;
1024         memcpy(eth->h_dest, addr, ETH_ALEN);
1025         memcpy(eth->h_source, own_addr, ETH_ALEN);
1026         eth->h_proto = host_to_be16(ETH_P_EAPOL);
1027         memcpy(eth+1, data, data_len);
1028
1029         wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
1030
1031         status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
1032
1033         if (bp != buf)
1034                 free(bp);
1035         return status;
1036 }
1037
1038 static void
1039 handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
1040 {
1041         struct madwifi_driver_data *drv = ctx;
1042         drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
1043                            len - sizeof(struct l2_ethhdr));
1044 }
1045
1046 static void *
1047 madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
1048 {
1049         struct madwifi_driver_data *drv;
1050         struct ifreq ifr;
1051         struct iwreq iwr;
1052
1053         drv = os_zalloc(sizeof(struct madwifi_driver_data));
1054         if (drv == NULL) {
1055                 printf("Could not allocate memory for madwifi driver data\n");
1056                 return NULL;
1057         }
1058
1059         drv->hapd = hapd;
1060         drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
1061         if (drv->ioctl_sock < 0) {
1062                 perror("socket[PF_INET,SOCK_DGRAM]");
1063                 goto bad;
1064         }
1065         memcpy(drv->iface, params->ifname, sizeof(drv->iface));
1066
1067         memset(&ifr, 0, sizeof(ifr));
1068         os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
1069         if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
1070                 perror("ioctl(SIOCGIFINDEX)");
1071                 goto bad;
1072         }
1073         drv->ifindex = ifr.ifr_ifindex;
1074
1075         drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
1076                                         handle_read, drv, 1);
1077         if (drv->sock_xmit == NULL)
1078                 goto bad;
1079         if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr))
1080                 goto bad;
1081         if (params->bridge[0]) {
1082                 wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.",
1083                            params->bridge[0]);
1084                 drv->sock_recv = l2_packet_init(params->bridge[0], NULL,
1085                                                 ETH_P_EAPOL, handle_read, drv,
1086                                                 1);
1087                 if (drv->sock_recv == NULL)
1088                         goto bad;
1089         } else
1090                 drv->sock_recv = drv->sock_xmit;
1091
1092         memset(&iwr, 0, sizeof(iwr));
1093         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
1094
1095         iwr.u.mode = IW_MODE_MASTER;
1096
1097         if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
1098                 perror("ioctl[SIOCSIWMODE]");
1099                 printf("Could not set interface to master mode!\n");
1100                 goto bad;
1101         }
1102
1103         /* mark down during setup */
1104         linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
1105         madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */
1106
1107         madwifi_receive_probe_req(drv);
1108
1109         if (madwifi_wireless_event_init(drv))
1110                 goto bad;
1111
1112         return drv;
1113 bad:
1114         if (drv->sock_xmit != NULL)
1115                 l2_packet_deinit(drv->sock_xmit);
1116         if (drv->ioctl_sock >= 0)
1117                 close(drv->ioctl_sock);
1118         if (drv != NULL)
1119                 free(drv);
1120         return NULL;
1121 }
1122
1123
1124 static void
1125 madwifi_deinit(void *priv)
1126 {
1127         struct madwifi_driver_data *drv = priv;
1128
1129         netlink_deinit(drv->netlink);
1130         (void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
1131         if (drv->ioctl_sock >= 0)
1132                 close(drv->ioctl_sock);
1133         if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit)
1134                 l2_packet_deinit(drv->sock_recv);
1135         if (drv->sock_xmit != NULL)
1136                 l2_packet_deinit(drv->sock_xmit);
1137         if (drv->sock_raw)
1138                 l2_packet_deinit(drv->sock_raw);
1139         free(drv);
1140 }
1141
1142 static int
1143 madwifi_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
1144 {
1145         struct madwifi_driver_data *drv = priv;
1146         struct iwreq iwr;
1147
1148         memset(&iwr, 0, sizeof(iwr));
1149         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
1150         iwr.u.essid.flags = 1; /* SSID active */
1151         iwr.u.essid.pointer = (caddr_t) buf;
1152         iwr.u.essid.length = len + 1;
1153
1154         if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
1155                 perror("ioctl[SIOCSIWESSID]");
1156                 printf("len=%d\n", len);
1157                 return -1;
1158         }
1159         return 0;
1160 }
1161
1162 static int
1163 madwifi_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
1164 {
1165         struct madwifi_driver_data *drv = priv;
1166         struct iwreq iwr;
1167         int ret = 0;
1168
1169         memset(&iwr, 0, sizeof(iwr));
1170         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
1171         iwr.u.essid.pointer = (caddr_t) buf;
1172         iwr.u.essid.length = len;
1173
1174         if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
1175                 perror("ioctl[SIOCGIWESSID]");
1176                 ret = -1;
1177         } else
1178                 ret = iwr.u.essid.length;
1179
1180         return ret;
1181 }
1182
1183 static int
1184 madwifi_set_countermeasures(void *priv, int enabled)
1185 {
1186         struct madwifi_driver_data *drv = priv;
1187         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
1188         return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled);
1189 }
1190
1191 static int
1192 madwifi_commit(void *priv)
1193 {
1194         struct madwifi_driver_data *drv = priv;
1195         return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);
1196 }
1197
1198 const struct wpa_driver_ops wpa_driver_atheros_ops = {
1199         .name                   = "atheros",
1200         .hapd_init              = madwifi_init,
1201         .deinit                 = madwifi_deinit,
1202         .set_ieee8021x          = madwifi_set_ieee8021x,
1203         .set_privacy            = madwifi_set_privacy,
1204         .set_key                = madwifi_set_key,
1205         .get_seqnum             = madwifi_get_seqnum,
1206         .flush                  = madwifi_flush,
1207         .set_generic_elem       = madwifi_set_opt_ie,
1208         .sta_set_flags          = madwifi_sta_set_flags,
1209         .read_sta_data          = madwifi_read_sta_driver_data,
1210         .hapd_send_eapol        = madwifi_send_eapol,
1211         .sta_disassoc           = madwifi_sta_disassoc,
1212         .sta_deauth             = madwifi_sta_deauth,
1213         .hapd_set_ssid          = madwifi_set_ssid,
1214         .hapd_get_ssid          = madwifi_get_ssid,
1215         .set_countermeasures    = madwifi_set_countermeasures,
1216         .sta_clear_stats        = madwifi_sta_clear_stats,
1217         .commit                 = madwifi_commit,
1218         .set_ap_wps_ie          = madwifi_set_ap_wps_ie,
1219 };