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