Home | History | Annotate | Download | only in drivers
      1 /*
      2  * WPA Supplicant - driver interaction with MADWIFI 802.11 driver
      3  * Copyright (c) 2004, Sam Leffler <sam (at) errno.com>
      4  * Copyright (c) 2004-2005, Jouni Malinen <j (at) w1.fi>
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License version 2 as
      8  * published by the Free Software Foundation.
      9  *
     10  * Alternatively, this software may be distributed under the terms of BSD
     11  * license.
     12  *
     13  * See README and COPYING for more details.
     14  *
     15  * Please note that madwifi supports WPA configuration via Linux wireless
     16  * extensions and if the kernel includes support for this, driver_wext.c should
     17  * be used instead of this driver wrapper.
     18  */
     19 
     20 #include "includes.h"
     21 #include <sys/ioctl.h>
     22 
     23 #include "common.h"
     24 #include "driver.h"
     25 #include "driver_wext.h"
     26 #include "eloop.h"
     27 #include "ieee802_11_defs.h"
     28 #include "wireless_copy.h"
     29 
     30 /*
     31  * Avoid conflicts with wpa_supplicant definitions by undefining a definition.
     32  */
     33 #undef WME_OUI_TYPE
     34 
     35 #include <include/compat.h>
     36 #include <net80211/ieee80211.h>
     37 #ifdef WME_NUM_AC
     38 /* Assume this is built against BSD branch of madwifi driver. */
     39 #define MADWIFI_BSD
     40 #include <net80211/_ieee80211.h>
     41 #endif /* WME_NUM_AC */
     42 #include <net80211/ieee80211_crypto.h>
     43 #include <net80211/ieee80211_ioctl.h>
     44 
     45 
     46 #ifdef IEEE80211_IOCTL_SETWMMPARAMS
     47 /* Assume this is built against madwifi-ng */
     48 #define MADWIFI_NG
     49 #endif /* IEEE80211_IOCTL_SETWMMPARAMS */
     50 
     51 struct wpa_driver_madwifi_data {
     52 	void *wext; /* private data for driver_wext */
     53 	void *ctx;
     54 	char ifname[IFNAMSIZ + 1];
     55 	int sock;
     56 };
     57 
     58 static int
     59 set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len,
     60 	     int show_err)
     61 {
     62 	struct iwreq iwr;
     63 
     64 	os_memset(&iwr, 0, sizeof(iwr));
     65 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
     66 	if (len < IFNAMSIZ &&
     67 	    op != IEEE80211_IOCTL_SET_APPIEBUF) {
     68 		/*
     69 		 * Argument data fits inline; put it there.
     70 		 */
     71 		os_memcpy(iwr.u.name, data, len);
     72 	} else {
     73 		/*
     74 		 * Argument data too big for inline transfer; setup a
     75 		 * parameter block instead; the kernel will transfer
     76 		 * the data for the driver.
     77 		 */
     78 		iwr.u.data.pointer = data;
     79 		iwr.u.data.length = len;
     80 	}
     81 
     82 	if (ioctl(drv->sock, op, &iwr) < 0) {
     83 		if (show_err) {
     84 #ifdef MADWIFI_NG
     85 			int first = IEEE80211_IOCTL_SETPARAM;
     86 			int last = IEEE80211_IOCTL_KICKMAC;
     87 			static const char *opnames[] = {
     88 				"ioctl[IEEE80211_IOCTL_SETPARAM]",
     89 				"ioctl[IEEE80211_IOCTL_GETPARAM]",
     90 				"ioctl[IEEE80211_IOCTL_SETMODE]",
     91 				"ioctl[IEEE80211_IOCTL_GETMODE]",
     92 				"ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
     93 				"ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
     94 				"ioctl[IEEE80211_IOCTL_SETCHANLIST]",
     95 				"ioctl[IEEE80211_IOCTL_GETCHANLIST]",
     96 				"ioctl[IEEE80211_IOCTL_CHANSWITCH]",
     97 				NULL,
     98 				"ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
     99 				"ioctl[IEEE80211_IOCTL_GETSCANRESULTS]",
    100 				NULL,
    101 				"ioctl[IEEE80211_IOCTL_GETCHANINFO]",
    102 				"ioctl[IEEE80211_IOCTL_SETOPTIE]",
    103 				"ioctl[IEEE80211_IOCTL_GETOPTIE]",
    104 				"ioctl[IEEE80211_IOCTL_SETMLME]",
    105 				NULL,
    106 				"ioctl[IEEE80211_IOCTL_SETKEY]",
    107 				NULL,
    108 				"ioctl[IEEE80211_IOCTL_DELKEY]",
    109 				NULL,
    110 				"ioctl[IEEE80211_IOCTL_ADDMAC]",
    111 				NULL,
    112 				"ioctl[IEEE80211_IOCTL_DELMAC]",
    113 				NULL,
    114 				"ioctl[IEEE80211_IOCTL_WDSMAC]",
    115 				NULL,
    116 				"ioctl[IEEE80211_IOCTL_WDSDELMAC]",
    117 				NULL,
    118 				"ioctl[IEEE80211_IOCTL_KICKMAC]",
    119 			};
    120 #else /* MADWIFI_NG */
    121 			int first = IEEE80211_IOCTL_SETPARAM;
    122 			int last = IEEE80211_IOCTL_CHANLIST;
    123 			static const char *opnames[] = {
    124 				"ioctl[IEEE80211_IOCTL_SETPARAM]",
    125 				"ioctl[IEEE80211_IOCTL_GETPARAM]",
    126 				"ioctl[IEEE80211_IOCTL_SETKEY]",
    127 				"ioctl[IEEE80211_IOCTL_GETKEY]",
    128 				"ioctl[IEEE80211_IOCTL_DELKEY]",
    129 				NULL,
    130 				"ioctl[IEEE80211_IOCTL_SETMLME]",
    131 				NULL,
    132 				"ioctl[IEEE80211_IOCTL_SETOPTIE]",
    133 				"ioctl[IEEE80211_IOCTL_GETOPTIE]",
    134 				"ioctl[IEEE80211_IOCTL_ADDMAC]",
    135 				NULL,
    136 				"ioctl[IEEE80211_IOCTL_DELMAC]",
    137 				NULL,
    138 				"ioctl[IEEE80211_IOCTL_CHANLIST]",
    139 			};
    140 #endif /* MADWIFI_NG */
    141 			int idx = op - first;
    142 			if (first <= op && op <= last &&
    143 			    idx < (int) (sizeof(opnames) / sizeof(opnames[0]))
    144 			    && opnames[idx])
    145 				perror(opnames[idx]);
    146 			else
    147 				perror("ioctl[unknown???]");
    148 		}
    149 		return -1;
    150 	}
    151 	return 0;
    152 }
    153 
    154 static int
    155 set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg,
    156 	      int show_err)
    157 {
    158 	struct iwreq iwr;
    159 
    160 	os_memset(&iwr, 0, sizeof(iwr));
    161 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
    162 	iwr.u.mode = op;
    163 	os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg));
    164 
    165 	if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
    166 		if (show_err)
    167 			perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
    168 		return -1;
    169 	}
    170 	return 0;
    171 }
    172 
    173 static int
    174 wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv,
    175 			      const u8 *wpa_ie, size_t wpa_ie_len)
    176 {
    177 	struct iwreq iwr;
    178 
    179 	os_memset(&iwr, 0, sizeof(iwr));
    180 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
    181 	/* NB: SETOPTIE is not fixed-size so must not be inlined */
    182 	iwr.u.data.pointer = (void *) wpa_ie;
    183 	iwr.u.data.length = wpa_ie_len;
    184 
    185 	if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) {
    186 		perror("ioctl[IEEE80211_IOCTL_SETOPTIE]");
    187 		return -1;
    188 	}
    189 	return 0;
    190 }
    191 
    192 static int
    193 wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx,
    194 			   const u8 *addr)
    195 {
    196 	struct ieee80211req_del_key wk;
    197 
    198 	wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
    199 	os_memset(&wk, 0, sizeof(wk));
    200 	wk.idk_keyix = key_idx;
    201 	if (addr != NULL)
    202 		os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
    203 
    204 	return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1);
    205 }
    206 
    207 static int
    208 wpa_driver_madwifi_set_key(void *priv, wpa_alg alg,
    209 			   const u8 *addr, int key_idx, int set_tx,
    210 			   const u8 *seq, size_t seq_len,
    211 			   const u8 *key, size_t key_len)
    212 {
    213 	struct wpa_driver_madwifi_data *drv = priv;
    214 	struct ieee80211req_key wk;
    215 	char *alg_name;
    216 	u_int8_t cipher;
    217 
    218 	if (alg == WPA_ALG_NONE)
    219 		return wpa_driver_madwifi_del_key(drv, key_idx, addr);
    220 
    221 	switch (alg) {
    222 	case WPA_ALG_WEP:
    223 		if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
    224 					      ETH_ALEN) == 0) {
    225 			/*
    226 			 * madwifi did not seem to like static WEP key
    227 			 * configuration with IEEE80211_IOCTL_SETKEY, so use
    228 			 * Linux wireless extensions ioctl for this.
    229 			 */
    230 			return wpa_driver_wext_set_key(drv->wext, alg, addr,
    231 						       key_idx, set_tx,
    232 						       seq, seq_len,
    233 						       key, key_len);
    234 		}
    235 		alg_name = "WEP";
    236 		cipher = IEEE80211_CIPHER_WEP;
    237 		break;
    238 	case WPA_ALG_TKIP:
    239 		alg_name = "TKIP";
    240 		cipher = IEEE80211_CIPHER_TKIP;
    241 		break;
    242 	case WPA_ALG_CCMP:
    243 		alg_name = "CCMP";
    244 		cipher = IEEE80211_CIPHER_AES_CCM;
    245 		break;
    246 	default:
    247 		wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
    248 			__FUNCTION__, alg);
    249 		return -1;
    250 	}
    251 
    252 	wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
    253 		   "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
    254 		   (unsigned long) seq_len, (unsigned long) key_len);
    255 
    256 	if (seq_len > sizeof(u_int64_t)) {
    257 		wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big",
    258 			   __FUNCTION__, (unsigned long) seq_len);
    259 		return -2;
    260 	}
    261 	if (key_len > sizeof(wk.ik_keydata)) {
    262 		wpa_printf(MSG_DEBUG, "%s: key length %lu too big",
    263 			   __FUNCTION__, (unsigned long) key_len);
    264 		return -3;
    265 	}
    266 
    267 	os_memset(&wk, 0, sizeof(wk));
    268 	wk.ik_type = cipher;
    269 	wk.ik_flags = IEEE80211_KEY_RECV;
    270 	if (addr == NULL ||
    271 	    os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
    272 		wk.ik_flags |= IEEE80211_KEY_GROUP;
    273 	if (set_tx) {
    274 		wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
    275 		os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
    276 	} else
    277 		os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
    278 	wk.ik_keyix = key_idx;
    279 	wk.ik_keylen = key_len;
    280 #ifdef WORDS_BIGENDIAN
    281 #define WPA_KEY_RSC_LEN 8
    282 	{
    283 		size_t i;
    284 		u8 tmp[WPA_KEY_RSC_LEN];
    285 		os_memset(tmp, 0, sizeof(tmp));
    286 		for (i = 0; i < seq_len; i++)
    287 			tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
    288 		os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
    289 	}
    290 #else /* WORDS_BIGENDIAN */
    291 	os_memcpy(&wk.ik_keyrsc, seq, seq_len);
    292 #endif /* WORDS_BIGENDIAN */
    293 	os_memcpy(wk.ik_keydata, key, key_len);
    294 
    295 	return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1);
    296 }
    297 
    298 static int
    299 wpa_driver_madwifi_set_countermeasures(void *priv, int enabled)
    300 {
    301 	struct wpa_driver_madwifi_data *drv = priv;
    302 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
    303 	return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1);
    304 }
    305 
    306 
    307 static int
    308 wpa_driver_madwifi_set_drop_unencrypted(void *priv, int enabled)
    309 {
    310 	struct wpa_driver_madwifi_data *drv = priv;
    311 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
    312 	return set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, enabled, 1);
    313 }
    314 
    315 static int
    316 wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code)
    317 {
    318 	struct wpa_driver_madwifi_data *drv = priv;
    319 	struct ieee80211req_mlme mlme;
    320 
    321 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
    322 	mlme.im_op = IEEE80211_MLME_DEAUTH;
    323 	mlme.im_reason = reason_code;
    324 	os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
    325 	return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
    326 }
    327 
    328 static int
    329 wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code)
    330 {
    331 	struct wpa_driver_madwifi_data *drv = priv;
    332 	struct ieee80211req_mlme mlme;
    333 
    334 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
    335 	mlme.im_op = IEEE80211_MLME_DISASSOC;
    336 	mlme.im_reason = reason_code;
    337 	os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
    338 	return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
    339 }
    340 
    341 static int
    342 wpa_driver_madwifi_associate(void *priv,
    343 			     struct wpa_driver_associate_params *params)
    344 {
    345 	struct wpa_driver_madwifi_data *drv = priv;
    346 	struct ieee80211req_mlme mlme;
    347 	int ret = 0, privacy = 1;
    348 
    349 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
    350 
    351 	/*
    352 	 * NB: Don't need to set the freq or cipher-related state as
    353 	 *     this is implied by the bssid which is used to locate
    354 	 *     the scanned node state which holds it.  The ssid is
    355 	 *     needed to disambiguate an AP that broadcasts multiple
    356 	 *     ssid's but uses the same bssid.
    357 	 */
    358 	/* XXX error handling is wrong but unclear what to do... */
    359 	if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie,
    360 					  params->wpa_ie_len) < 0)
    361 		ret = -1;
    362 
    363 	if (params->pairwise_suite == CIPHER_NONE &&
    364 	    params->group_suite == CIPHER_NONE &&
    365 	    params->key_mgmt_suite == KEY_MGMT_NONE &&
    366 	    params->wpa_ie_len == 0)
    367 		privacy = 0;
    368 
    369 	if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0)
    370 		ret = -1;
    371 
    372 	if (params->wpa_ie_len &&
    373 	    set80211param(drv, IEEE80211_PARAM_WPA,
    374 			  params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0)
    375 		ret = -1;
    376 
    377 	if (params->bssid == NULL) {
    378 		/* ap_scan=2 mode - driver takes care of AP selection and
    379 		 * roaming */
    380 		/* FIX: this does not seem to work; would probably need to
    381 		 * change something in the driver */
    382 		if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0)
    383 			ret = -1;
    384 
    385 		if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
    386 					     params->ssid_len) < 0)
    387 			ret = -1;
    388 	} else {
    389 		if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0)
    390 			ret = -1;
    391 		if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
    392 					     params->ssid_len) < 0)
    393 			ret = -1;
    394 		os_memset(&mlme, 0, sizeof(mlme));
    395 		mlme.im_op = IEEE80211_MLME_ASSOC;
    396 		os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
    397 		if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
    398 				 sizeof(mlme), 1) < 0) {
    399 			wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed",
    400 				   __func__);
    401 			ret = -1;
    402 		}
    403 	}
    404 
    405 	return ret;
    406 }
    407 
    408 static int
    409 wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg)
    410 {
    411 	struct wpa_driver_madwifi_data *drv = priv;
    412 	int authmode;
    413 
    414 	if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
    415 	    (auth_alg & AUTH_ALG_SHARED_KEY))
    416 		authmode = IEEE80211_AUTH_AUTO;
    417 	else if (auth_alg & AUTH_ALG_SHARED_KEY)
    418 		authmode = IEEE80211_AUTH_SHARED;
    419 	else
    420 		authmode = IEEE80211_AUTH_OPEN;
    421 
    422 	return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1);
    423 }
    424 
    425 static int
    426 wpa_driver_madwifi_scan(void *priv, const u8 *ssid, size_t ssid_len)
    427 {
    428 	struct wpa_driver_madwifi_data *drv = priv;
    429 	struct iwreq iwr;
    430 	int ret = 0;
    431 
    432 	os_memset(&iwr, 0, sizeof(iwr));
    433 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
    434 
    435 	/* set desired ssid before scan */
    436 	/* FIX: scan should not break the current association, so using
    437 	 * set_ssid may not be the best way of doing this.. */
    438 	if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0)
    439 		ret = -1;
    440 
    441 	if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) {
    442 		perror("ioctl[SIOCSIWSCAN]");
    443 		ret = -1;
    444 	}
    445 
    446 	/*
    447 	 * madwifi delivers a scan complete event so no need to poll, but
    448 	 * register a backup timeout anyway to make sure that we recover even
    449 	 * if the driver does not send this event for any reason. This timeout
    450 	 * will only be used if the event is not delivered (event handler will
    451 	 * cancel the timeout).
    452 	 */
    453 	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
    454 			     drv->ctx);
    455 	eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext,
    456 			       drv->ctx);
    457 
    458 	return ret;
    459 }
    460 
    461 static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid)
    462 {
    463 	struct wpa_driver_madwifi_data *drv = priv;
    464 	return wpa_driver_wext_get_bssid(drv->wext, bssid);
    465 }
    466 
    467 
    468 static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid)
    469 {
    470 	struct wpa_driver_madwifi_data *drv = priv;
    471 	return wpa_driver_wext_get_ssid(drv->wext, ssid);
    472 }
    473 
    474 
    475 static struct wpa_scan_results *
    476 wpa_driver_madwifi_get_scan_results(void *priv)
    477 {
    478 	struct wpa_driver_madwifi_data *drv = priv;
    479 	return wpa_driver_wext_get_scan_results(drv->wext);
    480 }
    481 
    482 
    483 static int wpa_driver_madwifi_set_operstate(void *priv, int state)
    484 {
    485 	struct wpa_driver_madwifi_data *drv = priv;
    486 	return wpa_driver_wext_set_operstate(drv->wext, state);
    487 }
    488 
    489 
    490 static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies,
    491 					       size_t ies_len)
    492 {
    493 	struct ieee80211req_getset_appiebuf *probe_req_ie;
    494 	int ret;
    495 
    496 	probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len);
    497 	if (probe_req_ie == NULL)
    498 		return -1;
    499 
    500 	probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ;
    501 	probe_req_ie->app_buflen = ies_len;
    502 	os_memcpy(probe_req_ie->app_buf, ies, ies_len);
    503 
    504 	ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie,
    505 			   sizeof(struct ieee80211req_getset_appiebuf) +
    506 			   ies_len, 1);
    507 
    508 	os_free(probe_req_ie);
    509 
    510 	return ret;
    511 }
    512 
    513 
    514 static void * wpa_driver_madwifi_init(void *ctx, const char *ifname)
    515 {
    516 	struct wpa_driver_madwifi_data *drv;
    517 
    518 	drv = os_zalloc(sizeof(*drv));
    519 	if (drv == NULL)
    520 		return NULL;
    521 	drv->wext = wpa_driver_wext_init(ctx, ifname);
    522 	if (drv->wext == NULL)
    523 		goto fail;
    524 
    525 	drv->ctx = ctx;
    526 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
    527 	drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
    528 	if (drv->sock < 0)
    529 		goto fail2;
    530 
    531 	if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) {
    532 		wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
    533 			   "roaming", __FUNCTION__);
    534 		goto fail3;
    535 	}
    536 
    537 	if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) {
    538 		wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support",
    539 			   __FUNCTION__);
    540 		goto fail3;
    541 	}
    542 
    543 	return drv;
    544 
    545 fail3:
    546 	close(drv->sock);
    547 fail2:
    548 	wpa_driver_wext_deinit(drv->wext);
    549 fail:
    550 	os_free(drv);
    551 	return NULL;
    552 }
    553 
    554 
    555 static void wpa_driver_madwifi_deinit(void *priv)
    556 {
    557 	struct wpa_driver_madwifi_data *drv = priv;
    558 
    559 	if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) {
    560 		wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE",
    561 			   __FUNCTION__);
    562 	}
    563 	if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) {
    564 		wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based "
    565 			   "roaming", __FUNCTION__);
    566 	}
    567 	if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) {
    568 		wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy "
    569 			   "flag", __FUNCTION__);
    570 	}
    571 	if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) {
    572 		wpa_printf(MSG_DEBUG, "%s: failed to disable WPA",
    573 			   __FUNCTION__);
    574 	}
    575 
    576 	wpa_driver_wext_deinit(drv->wext);
    577 
    578 	close(drv->sock);
    579 	os_free(drv);
    580 }
    581 
    582 
    583 const struct wpa_driver_ops wpa_driver_madwifi_ops = {
    584 	.name			= "madwifi",
    585 	.desc			= "MADWIFI 802.11 support (Atheros, etc.)",
    586 	.get_bssid		= wpa_driver_madwifi_get_bssid,
    587 	.get_ssid		= wpa_driver_madwifi_get_ssid,
    588 	.set_key		= wpa_driver_madwifi_set_key,
    589 	.init			= wpa_driver_madwifi_init,
    590 	.deinit			= wpa_driver_madwifi_deinit,
    591 	.set_countermeasures	= wpa_driver_madwifi_set_countermeasures,
    592 	.set_drop_unencrypted	= wpa_driver_madwifi_set_drop_unencrypted,
    593 	.scan			= wpa_driver_madwifi_scan,
    594 	.get_scan_results2	= wpa_driver_madwifi_get_scan_results,
    595 	.deauthenticate		= wpa_driver_madwifi_deauthenticate,
    596 	.disassociate		= wpa_driver_madwifi_disassociate,
    597 	.associate		= wpa_driver_madwifi_associate,
    598 	.set_auth_alg		= wpa_driver_madwifi_set_auth_alg,
    599 	.set_operstate		= wpa_driver_madwifi_set_operstate,
    600 	.set_probe_req_ie	= wpa_driver_madwifi_set_probe_req_ie,
    601 };
    602