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