Home | History | Annotate | Download | only in drivers
      1 /*
      2  * WPA Supplicant - driver interaction with Linux ndiswrapper
      3  * Copyright (c) 2004-2006, Giridhar Pemmasani <giri (at) lmc.cs.sunysb.edu>
      4  * Copyright (c) 2004-2006, 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 ndiswrapper 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 "wireless_copy.h"
     24 #include "common.h"
     25 #include "driver.h"
     26 #include "driver_wext.h"
     27 
     28 struct wpa_driver_ndiswrapper_data {
     29 	void *wext; /* private data for driver_wext */
     30 	void *ctx;
     31 	char ifname[IFNAMSIZ + 1];
     32 	int sock;
     33 };
     34 
     35 
     36 struct wpa_key
     37 {
     38 	wpa_alg alg;
     39 	const u8 *addr;
     40 	int key_index;
     41 	int set_tx;
     42 	const u8 *seq;
     43 	size_t seq_len;
     44 	const u8 *key;
     45 	size_t key_len;
     46 };
     47 
     48 struct wpa_assoc_info
     49 {
     50 	const u8 *bssid;
     51 	const u8 *ssid;
     52 	size_t ssid_len;
     53 	int freq;
     54 	const u8 *wpa_ie;
     55 	size_t wpa_ie_len;
     56 	wpa_cipher pairwise_suite;
     57 	wpa_cipher group_suite;
     58 	wpa_key_mgmt key_mgmt_suite;
     59 	int auth_alg;
     60 	int mode;
     61 };
     62 
     63 #define PRIV_RESET	 		SIOCIWFIRSTPRIV+0
     64 #define WPA_SET_WPA 			SIOCIWFIRSTPRIV+1
     65 #define WPA_SET_KEY 			SIOCIWFIRSTPRIV+2
     66 #define WPA_ASSOCIATE		 	SIOCIWFIRSTPRIV+3
     67 #define WPA_DISASSOCIATE 		SIOCIWFIRSTPRIV+4
     68 #define WPA_DROP_UNENCRYPTED 		SIOCIWFIRSTPRIV+5
     69 #define WPA_SET_COUNTERMEASURES 	SIOCIWFIRSTPRIV+6
     70 #define WPA_DEAUTHENTICATE	 	SIOCIWFIRSTPRIV+7
     71 #define WPA_SET_AUTH_ALG	 	SIOCIWFIRSTPRIV+8
     72 #define WPA_INIT			SIOCIWFIRSTPRIV+9
     73 #define WPA_DEINIT			SIOCIWFIRSTPRIV+10
     74 #define WPA_GET_CAPA		 	SIOCIWFIRSTPRIV+11
     75 
     76 static int get_socket(void)
     77 {
     78 	static const int families[] = {
     79 		AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
     80 	};
     81 	unsigned int i;
     82 	int sock;
     83 
     84 	for (i = 0; i < sizeof(families) / sizeof(int); ++i) {
     85 		sock = socket(families[i], SOCK_DGRAM, 0);
     86 		if (sock >= 0)
     87 			return sock;
     88 	}
     89 
     90 	return -1;
     91 }
     92 
     93 static int iw_set_ext(struct wpa_driver_ndiswrapper_data *drv, int request,
     94 		      struct iwreq *pwrq)
     95 {
     96 	os_strlcpy(pwrq->ifr_name, drv->ifname, IFNAMSIZ);
     97 	return ioctl(drv->sock, request, pwrq);
     98 }
     99 
    100 static int wpa_ndiswrapper_set_wpa(void *priv, int enabled)
    101 {
    102 	struct wpa_driver_ndiswrapper_data *drv = priv;
    103 	struct iwreq priv_req;
    104 	int ret = 0;
    105 
    106 	os_memset(&priv_req, 0, sizeof(priv_req));
    107 
    108 	priv_req.u.data.flags = enabled;
    109 	if (iw_set_ext(drv, WPA_SET_WPA, &priv_req) < 0)
    110 		ret = -1;
    111 	return ret;
    112 }
    113 
    114 static int wpa_ndiswrapper_set_key(void *priv, wpa_alg alg, const u8 *addr,
    115 				   int key_idx, int set_tx,
    116 				   const u8 *seq, size_t seq_len,
    117 				   const u8 *key, size_t key_len)
    118 {
    119 	struct wpa_driver_ndiswrapper_data *drv = priv;
    120 	struct wpa_key wpa_key;
    121 	int ret = 0;
    122 	struct iwreq priv_req;
    123 
    124 	os_memset(&priv_req, 0, sizeof(priv_req));
    125 
    126 	wpa_key.alg = alg;
    127 	wpa_key.addr = addr;
    128 	wpa_key.key_index = key_idx;
    129 	wpa_key.set_tx = set_tx;
    130 	wpa_key.seq = seq;
    131 	wpa_key.seq_len = seq_len;
    132 	wpa_key.key = key;
    133 	wpa_key.key_len = key_len;
    134 
    135 	priv_req.u.data.pointer = (void *)&wpa_key;
    136 	priv_req.u.data.length = sizeof(wpa_key);
    137 
    138 	if (iw_set_ext(drv, WPA_SET_KEY, &priv_req) < 0)
    139 		ret = -1;
    140 
    141 	if (alg == WPA_ALG_NONE) {
    142 		/*
    143 		 * ndiswrapper did not seem to be clearing keys properly in
    144 		 * some cases with WPA_SET_KEY. For example, roaming from WPA
    145 		 * enabled AP to plaintext one seemed to fail since the driver
    146 		 * did not associate. Try to make sure the keys are cleared so
    147 		 * that plaintext APs can be used in all cases.
    148 		 */
    149 		wpa_driver_wext_set_key(drv->wext, alg, addr, key_idx, set_tx,
    150 					seq, seq_len, key, key_len);
    151 	}
    152 
    153 	return ret;
    154 }
    155 
    156 static int wpa_ndiswrapper_set_countermeasures(void *priv, int enabled)
    157 {
    158 	struct wpa_driver_ndiswrapper_data *drv = priv;
    159 	int ret = 0;
    160 	struct iwreq priv_req;
    161 
    162 	os_memset(&priv_req, 0, sizeof(priv_req));
    163 
    164 	priv_req.u.param.value = enabled;
    165 	if (iw_set_ext(drv, WPA_SET_COUNTERMEASURES, &priv_req) < 0)
    166 		ret = -1;
    167 
    168 	return ret;
    169 }
    170 
    171 static int wpa_ndiswrapper_set_drop_unencrypted(void *priv,
    172 						int enabled)
    173 {
    174 	struct wpa_driver_ndiswrapper_data *drv = priv;
    175 	int ret = 0;
    176 	struct iwreq priv_req;
    177 
    178 	os_memset(&priv_req, 0, sizeof(priv_req));
    179 
    180 	priv_req.u.param.value = enabled;
    181 	if (iw_set_ext(drv, WPA_DROP_UNENCRYPTED, &priv_req) < 0)
    182 		ret = -1;
    183 	return ret;
    184 }
    185 
    186 static int wpa_ndiswrapper_deauthenticate(void *priv, const u8 *addr,
    187 					  int reason_code)
    188 {
    189 	struct wpa_driver_ndiswrapper_data *drv = priv;
    190 	int ret = 0;
    191 	struct iwreq priv_req;
    192 
    193 	os_memset(&priv_req, 0, sizeof(priv_req));
    194 
    195 	priv_req.u.param.value = reason_code;
    196 	os_memcpy(&priv_req.u.ap_addr.sa_data, addr, ETH_ALEN);
    197 	if (iw_set_ext(drv, WPA_DEAUTHENTICATE, &priv_req) < 0)
    198 		ret = -1;
    199 	return ret;
    200 }
    201 
    202 static int wpa_ndiswrapper_disassociate(void *priv, const u8 *addr,
    203 					int reason_code)
    204 {
    205 	struct wpa_driver_ndiswrapper_data *drv = priv;
    206 	int ret = 0;
    207 	struct iwreq priv_req;
    208 
    209 	os_memset(&priv_req, 0, sizeof(priv_req));
    210 
    211 	os_memcpy(&priv_req.u.ap_addr.sa_data, addr, ETH_ALEN);
    212 	if (iw_set_ext(drv, WPA_DISASSOCIATE, &priv_req) < 0)
    213 		ret = -1;
    214 	return ret;
    215 }
    216 
    217 static int
    218 wpa_ndiswrapper_associate(void *priv,
    219 			  struct wpa_driver_associate_params *params)
    220 {
    221 	struct wpa_driver_ndiswrapper_data *drv = priv;
    222 	int ret = 0;
    223 	struct wpa_assoc_info wpa_assoc_info;
    224 	struct iwreq priv_req;
    225 
    226 	os_memset(&priv_req, 0, sizeof(priv_req));
    227 	os_memset(&wpa_assoc_info, 0, sizeof(wpa_assoc_info));
    228 
    229 	wpa_assoc_info.bssid = params->bssid;
    230 	wpa_assoc_info.ssid = params->ssid;
    231 	wpa_assoc_info.ssid_len = params->ssid_len;
    232 	wpa_assoc_info.freq = params->freq;
    233 	wpa_assoc_info.wpa_ie = params->wpa_ie;
    234 	wpa_assoc_info.wpa_ie_len = params->wpa_ie_len;
    235 	wpa_assoc_info.pairwise_suite = params->pairwise_suite;
    236 	wpa_assoc_info.group_suite = params->group_suite;
    237 	wpa_assoc_info.key_mgmt_suite = params->key_mgmt_suite;
    238 	wpa_assoc_info.auth_alg = params->auth_alg;
    239 	wpa_assoc_info.mode = params->mode;
    240 
    241 	priv_req.u.data.pointer = (void *)&wpa_assoc_info;
    242 	priv_req.u.data.length = sizeof(wpa_assoc_info);
    243 
    244 	if (iw_set_ext(drv, WPA_ASSOCIATE, &priv_req) < 0)
    245 		ret = -1;
    246 	return ret;
    247 }
    248 
    249 static int wpa_ndiswrapper_set_auth_alg(void *priv, int auth_alg)
    250 {
    251 	struct wpa_driver_ndiswrapper_data *drv = priv;
    252 	int ret = 0;
    253 	struct iwreq priv_req;
    254 
    255 	os_memset(&priv_req, 0, sizeof(priv_req));
    256 
    257 	priv_req.u.param.value = auth_alg;
    258 	if (iw_set_ext(drv, WPA_SET_AUTH_ALG, &priv_req) < 0)
    259 		ret = -1;
    260 	return ret;
    261 }
    262 
    263 static int wpa_ndiswrapper_get_bssid(void *priv, u8 *bssid)
    264 {
    265 	struct wpa_driver_ndiswrapper_data *drv = priv;
    266 	return wpa_driver_wext_get_bssid(drv->wext, bssid);
    267 }
    268 
    269 
    270 static int wpa_ndiswrapper_get_ssid(void *priv, u8 *ssid)
    271 {
    272 	struct wpa_driver_ndiswrapper_data *drv = priv;
    273 	return wpa_driver_wext_get_ssid(drv->wext, ssid);
    274 }
    275 
    276 
    277 static int wpa_ndiswrapper_scan(void *priv, const u8 *ssid, size_t ssid_len)
    278 {
    279 	struct wpa_driver_ndiswrapper_data *drv = priv;
    280 	return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
    281 }
    282 
    283 
    284 static struct wpa_scan_results * wpa_ndiswrapper_get_scan_results(void *priv)
    285 {
    286 	struct wpa_driver_ndiswrapper_data *drv = priv;
    287 	return wpa_driver_wext_get_scan_results(drv->wext);
    288 }
    289 
    290 
    291 static int wpa_ndiswrapper_get_capa(void *priv, struct wpa_driver_capa *capa)
    292 {
    293 	struct wpa_driver_ndiswrapper_data *drv = priv;
    294 	int ret = 0;
    295 	struct iwreq priv_req;
    296 
    297 	os_memset(&priv_req, 0, sizeof(priv_req));
    298 
    299 	priv_req.u.data.pointer = (void *) capa;
    300 	priv_req.u.data.length = sizeof(*capa);
    301 	if (iw_set_ext(drv, WPA_GET_CAPA, &priv_req) < 0)
    302 		ret = -1;
    303 	return ret;
    304 
    305 }
    306 
    307 
    308 static int wpa_ndiswrapper_set_operstate(void *priv, int state)
    309 {
    310 	struct wpa_driver_ndiswrapper_data *drv = priv;
    311 	return wpa_driver_wext_set_operstate(drv->wext, state);
    312 }
    313 
    314 
    315 static void * wpa_ndiswrapper_init(void *ctx, const char *ifname)
    316 {
    317 	struct wpa_driver_ndiswrapper_data *drv;
    318 
    319 	drv = os_zalloc(sizeof(*drv));
    320 	if (drv == NULL)
    321 		return NULL;
    322 	drv->wext = wpa_driver_wext_init(ctx, ifname);
    323 	if (drv->wext == NULL) {
    324 		os_free(drv);
    325 		return NULL;
    326 	}
    327 
    328 	drv->ctx = ctx;
    329 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
    330 	drv->sock = get_socket();
    331 	if (drv->sock < 0) {
    332 		wpa_driver_wext_deinit(drv->wext);
    333 		os_free(drv);
    334 		return NULL;
    335 	}
    336 
    337 	return drv;
    338 }
    339 
    340 
    341 static void wpa_ndiswrapper_deinit(void *priv)
    342 {
    343 	struct wpa_driver_ndiswrapper_data *drv = priv;
    344 	wpa_driver_wext_deinit(drv->wext);
    345 	close(drv->sock);
    346 	os_free(drv);
    347 }
    348 
    349 
    350 const struct wpa_driver_ops wpa_driver_ndiswrapper_ops = {
    351 	.name = "ndiswrapper",
    352 	.desc = "Linux ndiswrapper (deprecated; use wext)",
    353 	.set_wpa = wpa_ndiswrapper_set_wpa,
    354 	.set_key = wpa_ndiswrapper_set_key,
    355 	.set_countermeasures = wpa_ndiswrapper_set_countermeasures,
    356 	.set_drop_unencrypted = wpa_ndiswrapper_set_drop_unencrypted,
    357 	.deauthenticate = wpa_ndiswrapper_deauthenticate,
    358 	.disassociate = wpa_ndiswrapper_disassociate,
    359 	.associate = wpa_ndiswrapper_associate,
    360 	.set_auth_alg = wpa_ndiswrapper_set_auth_alg,
    361 
    362 	.get_bssid = wpa_ndiswrapper_get_bssid,
    363 	.get_ssid = wpa_ndiswrapper_get_ssid,
    364 	.scan = wpa_ndiswrapper_scan,
    365 	.get_scan_results2 = wpa_ndiswrapper_get_scan_results,
    366 	.init = wpa_ndiswrapper_init,
    367 	.deinit = wpa_ndiswrapper_deinit,
    368 	.get_capa = wpa_ndiswrapper_get_capa,
    369 	.set_operstate = wpa_ndiswrapper_set_operstate,
    370 };
    371