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