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