1/* 2 * WPA Supplicant - testing driver interface 3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16#include <sys/un.h> 17#include <dirent.h> 18#include <sys/stat.h> 19 20#include "common.h" 21#include "driver.h" 22#include "wpa_supplicant.h" 23#include "l2_packet.h" 24#include "eloop.h" 25#include "sha1.h" 26#include "wpa.h" 27#include "mlme.h" 28 29 30struct wpa_driver_test_data { 31 void *ctx; 32 u8 own_addr[ETH_ALEN]; 33 int test_socket; 34 struct sockaddr_un hostapd_addr; 35 int hostapd_addr_set; 36 char *own_socket_path; 37 char *test_dir; 38 u8 bssid[ETH_ALEN]; 39 u8 ssid[32]; 40 size_t ssid_len; 41#define MAX_SCAN_RESULTS 30 42 struct wpa_scan_result scanres[MAX_SCAN_RESULTS]; 43 size_t num_scanres; 44 int use_associnfo; 45 u8 assoc_wpa_ie[80]; 46 size_t assoc_wpa_ie_len; 47 int use_mlme; 48}; 49 50 51static int wpa_driver_test_set_wpa(void *priv, int enabled) 52{ 53 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 54 return 0; 55} 56 57 58static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx) 59{ 60 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 61 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 62} 63 64 65static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv, 66 const char *path) 67{ 68 struct dirent *dent; 69 DIR *dir; 70 struct sockaddr_un addr; 71 72 dir = opendir(path); 73 if (dir == NULL) 74 return; 75 76 while ((dent = readdir(dir))) { 77 if (os_strncmp(dent->d_name, "AP-", 3) != 0) 78 continue; 79 wpa_printf(MSG_DEBUG, "%s: SCAN %s", __func__, dent->d_name); 80 81 os_memset(&addr, 0, sizeof(addr)); 82 addr.sun_family = AF_UNIX; 83 os_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", 84 path, dent->d_name); 85 86 if (sendto(drv->test_socket, "SCAN", 4, 0, 87 (struct sockaddr *) &addr, sizeof(addr)) < 0) { 88 perror("sendto(test_socket)"); 89 } 90 } 91 closedir(dir); 92} 93 94 95static int wpa_driver_test_scan(void *priv, const u8 *ssid, size_t ssid_len) 96{ 97 struct wpa_driver_test_data *drv = priv; 98 wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); 99 100 drv->num_scanres = 0; 101 102 if (drv->test_socket >= 0 && drv->test_dir) 103 wpa_driver_scan_dir(drv, drv->test_dir); 104 105 if (drv->test_socket >= 0 && drv->hostapd_addr_set && 106 sendto(drv->test_socket, "SCAN", 4, 0, 107 (struct sockaddr *) &drv->hostapd_addr, 108 sizeof(drv->hostapd_addr)) < 0) { 109 perror("sendto(test_socket)"); 110 } 111 112 eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); 113 eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv, 114 drv->ctx); 115 return 0; 116} 117 118 119static int wpa_driver_test_get_scan_results(void *priv, 120 struct wpa_scan_result *results, 121 size_t max_size) 122{ 123 struct wpa_driver_test_data *drv = priv; 124 size_t num = drv->num_scanres; 125 if (num > max_size) 126 num = max_size; 127 os_memcpy(results, &drv->scanres, 128 num * sizeof(struct wpa_scan_result)); 129 return num; 130} 131 132 133static int wpa_driver_test_set_key(void *priv, wpa_alg alg, const u8 *addr, 134 int key_idx, int set_tx, 135 const u8 *seq, size_t seq_len, 136 const u8 *key, size_t key_len) 137{ 138 wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d", 139 __func__, priv, alg, key_idx, set_tx); 140 if (addr) { 141 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); 142 } 143 if (seq) { 144 wpa_hexdump(MSG_DEBUG, " seq", seq, seq_len); 145 } 146 if (key) { 147 wpa_hexdump(MSG_DEBUG, " key", key, key_len); 148 } 149 return 0; 150} 151 152 153static int wpa_driver_test_associate( 154 void *priv, struct wpa_driver_associate_params *params) 155{ 156 struct wpa_driver_test_data *drv = priv; 157 wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " 158 "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", 159 __func__, priv, params->freq, params->pairwise_suite, 160 params->group_suite, params->key_mgmt_suite, 161 params->auth_alg, params->mode); 162 if (params->bssid) { 163 wpa_printf(MSG_DEBUG, " bssid=" MACSTR, 164 MAC2STR(params->bssid)); 165 } 166 if (params->ssid) { 167 wpa_hexdump_ascii(MSG_DEBUG, " ssid", 168 params->ssid, params->ssid_len); 169 } 170 if (params->wpa_ie) { 171 wpa_hexdump(MSG_DEBUG, " wpa_ie", 172 params->wpa_ie, params->wpa_ie_len); 173 drv->assoc_wpa_ie_len = params->wpa_ie_len; 174 if (drv->assoc_wpa_ie_len > sizeof(drv->assoc_wpa_ie)) 175 drv->assoc_wpa_ie_len = sizeof(drv->assoc_wpa_ie); 176 os_memcpy(drv->assoc_wpa_ie, params->wpa_ie, 177 drv->assoc_wpa_ie_len); 178 } else 179 drv->assoc_wpa_ie_len = 0; 180 181 if (drv->test_dir && params->bssid) { 182 os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr)); 183 drv->hostapd_addr.sun_family = AF_UNIX; 184 os_snprintf(drv->hostapd_addr.sun_path, 185 sizeof(drv->hostapd_addr.sun_path), 186 "%s/AP-" MACSTR, 187 drv->test_dir, MAC2STR(params->bssid)); 188 drv->hostapd_addr_set = 1; 189 } 190 191 if (drv->test_socket >= 0 && drv->hostapd_addr_set) { 192 char cmd[200], *pos, *end; 193 int ret; 194 end = cmd + sizeof(cmd); 195 pos = cmd; 196 ret = os_snprintf(pos, end - pos, "ASSOC " MACSTR " ", 197 MAC2STR(drv->own_addr)); 198 if (ret >= 0 && ret < end - pos) 199 pos += ret; 200 pos += wpa_snprintf_hex(pos, end - pos, params->ssid, 201 params->ssid_len); 202 ret = os_snprintf(pos, end - pos, " "); 203 if (ret >= 0 && ret < end - pos) 204 pos += ret; 205 pos += wpa_snprintf_hex(pos, end - pos, params->wpa_ie, 206 params->wpa_ie_len); 207 end[-1] = '\0'; 208 if (sendto(drv->test_socket, cmd, os_strlen(cmd), 0, 209 (struct sockaddr *) &drv->hostapd_addr, 210 sizeof(drv->hostapd_addr)) < 0) { 211 perror("sendto(test_socket)"); 212 return -1; 213 } 214 215 os_memcpy(drv->ssid, params->ssid, params->ssid_len); 216 drv->ssid_len = params->ssid_len; 217 } else 218 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 219 220 return 0; 221} 222 223 224static int wpa_driver_test_get_bssid(void *priv, u8 *bssid) 225{ 226 struct wpa_driver_test_data *drv = priv; 227 os_memcpy(bssid, drv->bssid, ETH_ALEN); 228 return 0; 229} 230 231 232static int wpa_driver_test_get_ssid(void *priv, u8 *ssid) 233{ 234 struct wpa_driver_test_data *drv = priv; 235 os_memcpy(ssid, drv->ssid, 32); 236 return drv->ssid_len; 237} 238 239 240static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv) 241{ 242 if (drv->test_socket >= 0 && 243 sendto(drv->test_socket, "DISASSOC", 8, 0, 244 (struct sockaddr *) &drv->hostapd_addr, 245 sizeof(drv->hostapd_addr)) < 0) { 246 perror("sendto(test_socket)"); 247 return -1; 248 } 249 return 0; 250} 251 252 253static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr, 254 int reason_code) 255{ 256 struct wpa_driver_test_data *drv = priv; 257 wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", 258 __func__, MAC2STR(addr), reason_code); 259 os_memset(drv->bssid, 0, ETH_ALEN); 260 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 261 return wpa_driver_test_send_disassoc(drv); 262} 263 264 265static int wpa_driver_test_disassociate(void *priv, const u8 *addr, 266 int reason_code) 267{ 268 struct wpa_driver_test_data *drv = priv; 269 wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", 270 __func__, MAC2STR(addr), reason_code); 271 os_memset(drv->bssid, 0, ETH_ALEN); 272 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 273 return wpa_driver_test_send_disassoc(drv); 274} 275 276 277static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv, 278 struct sockaddr_un *from, 279 socklen_t fromlen, 280 const char *data) 281{ 282 struct wpa_scan_result *res; 283 const char *pos, *pos2; 284 size_t len; 285 u8 ie[200], *ipos, *end; 286 287 wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data); 288 if (drv->num_scanres >= MAX_SCAN_RESULTS) { 289 wpa_printf(MSG_DEBUG, "test_driver: No room for the new scan " 290 "result"); 291 return; 292 } 293 294 /* SCANRESP BSSID SSID IEs */ 295 res = &drv->scanres[drv->num_scanres]; 296 297 os_memset(res, 0, sizeof(*res)); 298 if (hwaddr_aton(data, res->bssid)) { 299 wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in scanres"); 300 return; 301 } 302 303 pos = data + 17; 304 while (*pos == ' ') 305 pos++; 306 pos2 = os_strchr(pos, ' '); 307 if (pos2 == NULL) { 308 wpa_printf(MSG_DEBUG, "test_driver: invalid SSID termination " 309 "in scanres"); 310 return; 311 } 312 len = (pos2 - pos) / 2; 313 if (len > sizeof(res->ssid)) 314 len = sizeof(res->ssid); 315 if (hexstr2bin(pos, res->ssid, len) < 0) { 316 wpa_printf(MSG_DEBUG, "test_driver: invalid SSID in scanres"); 317 return; 318 } 319 res->ssid_len = len; 320 321 pos = pos2 + 1; 322 pos2 = os_strchr(pos, ' '); 323 if (pos2 == NULL) 324 len = os_strlen(pos) / 2; 325 else 326 len = (pos2 - pos) / 2; 327 if (len > sizeof(ie)) 328 len = sizeof(ie); 329 if (hexstr2bin(pos, ie, len) < 0) { 330 wpa_printf(MSG_DEBUG, "test_driver: invalid IEs in scanres"); 331 return; 332 } 333 334 ipos = ie; 335 end = ipos + len; 336 while (ipos + 1 < end && ipos + 2 + ipos[1] <= end) { 337 len = 2 + ipos[1]; 338 if (len > SSID_MAX_WPA_IE_LEN) 339 len = SSID_MAX_WPA_IE_LEN; 340 if (ipos[0] == RSN_INFO_ELEM) { 341 os_memcpy(res->rsn_ie, ipos, len); 342 res->rsn_ie_len = len; 343 } else if (ipos[0] == GENERIC_INFO_ELEM) { 344 os_memcpy(res->wpa_ie, ipos, len); 345 res->wpa_ie_len = len; 346 } 347 348 ipos += 2 + ipos[1]; 349 } 350 351 if (pos2) { 352 pos = pos2 + 1; 353 while (*pos == ' ') 354 pos++; 355 if (os_strncmp(pos, "PRIVACY", 7) == 0) 356 res->caps |= IEEE80211_CAP_PRIVACY; 357 } 358 359 drv->num_scanres++; 360} 361 362 363static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv, 364 struct sockaddr_un *from, 365 socklen_t fromlen, 366 const char *data) 367{ 368 /* ASSOCRESP BSSID <res> */ 369 if (hwaddr_aton(data, drv->bssid)) { 370 wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in " 371 "assocresp"); 372 } 373 if (drv->use_associnfo) { 374 union wpa_event_data event; 375 os_memset(&event, 0, sizeof(event)); 376 event.assoc_info.req_ies = drv->assoc_wpa_ie; 377 event.assoc_info.req_ies_len = drv->assoc_wpa_ie_len; 378 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &event); 379 } 380 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 381} 382 383 384static void wpa_driver_test_disassoc(struct wpa_driver_test_data *drv, 385 struct sockaddr_un *from, 386 socklen_t fromlen) 387{ 388 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 389} 390 391 392static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv, 393 struct sockaddr_un *from, 394 socklen_t fromlen, 395 const u8 *data, size_t data_len) 396{ 397 const u8 *src = drv->bssid; 398 399 if (data_len > 14) { 400 /* Skip Ethernet header */ 401 src = data + ETH_ALEN; 402 data += 14; 403 data_len -= 14; 404 } 405 wpa_supplicant_rx_eapol(drv->ctx, src, data, data_len); 406} 407 408 409static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv, 410 struct sockaddr_un *from, 411 socklen_t fromlen, 412 const u8 *data, size_t data_len) 413{ 414 struct ieee80211_rx_status rx_status; 415 os_memset(&rx_status, 0, sizeof(rx_status)); 416 ieee80211_sta_rx(drv->ctx, data, data_len, &rx_status); 417} 418 419 420static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx, 421 void *sock_ctx) 422{ 423 struct wpa_driver_test_data *drv = eloop_ctx; 424 char *buf; 425 int res; 426 struct sockaddr_un from; 427 socklen_t fromlen = sizeof(from); 428 const size_t buflen = 2000; 429 430 buf = os_malloc(buflen); 431 if (buf == NULL) 432 return; 433 res = recvfrom(sock, buf, buflen - 1, 0, 434 (struct sockaddr *) &from, &fromlen); 435 if (res < 0) { 436 perror("recvfrom(test_socket)"); 437 os_free(buf); 438 return; 439 } 440 buf[res] = '\0'; 441 442 wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res); 443 444 if (os_strncmp(buf, "SCANRESP ", 9) == 0) { 445 wpa_driver_test_scanresp(drv, &from, fromlen, buf + 9); 446 } else if (os_strncmp(buf, "ASSOCRESP ", 10) == 0) { 447 wpa_driver_test_assocresp(drv, &from, fromlen, buf + 10); 448 } else if (os_strcmp(buf, "DISASSOC") == 0) { 449 wpa_driver_test_disassoc(drv, &from, fromlen); 450 } else if (os_strcmp(buf, "DEAUTH") == 0) { 451 wpa_driver_test_disassoc(drv, &from, fromlen); 452 } else if (os_strncmp(buf, "EAPOL ", 6) == 0) { 453 wpa_driver_test_eapol(drv, &from, fromlen, 454 (const u8 *) buf + 6, res - 6); 455 } else if (os_strncmp(buf, "MLME ", 5) == 0) { 456 wpa_driver_test_mlme(drv, &from, fromlen, 457 (const u8 *) buf + 5, res - 5); 458 } else { 459 wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command", 460 (u8 *) buf, res); 461 } 462 os_free(buf); 463} 464 465 466static void * wpa_driver_test_init(void *ctx, const char *ifname) 467{ 468 struct wpa_driver_test_data *drv; 469 470 drv = os_zalloc(sizeof(*drv)); 471 if (drv == NULL) 472 return NULL; 473 drv->ctx = ctx; 474 drv->test_socket = -1; 475 476 /* Set dummy BSSID and SSID for testing. */ 477 drv->bssid[0] = 0x02; 478 drv->bssid[1] = 0x00; 479 drv->bssid[2] = 0x00; 480 drv->bssid[3] = 0x00; 481 drv->bssid[4] = 0x00; 482 drv->bssid[5] = 0x01; 483 os_memcpy(drv->ssid, "test", 5); 484 drv->ssid_len = 4; 485 486 /* Generate a MAC address to help testing with multiple STAs */ 487 drv->own_addr[0] = 0x02; /* locally administered */ 488 sha1_prf((const u8 *) ifname, os_strlen(ifname), 489 "wpa_supplicant test mac addr generation", 490 NULL, 0, drv->own_addr + 1, ETH_ALEN - 1); 491 492 return drv; 493} 494 495 496static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv) 497{ 498 if (drv->test_socket >= 0) { 499 eloop_unregister_read_sock(drv->test_socket); 500 close(drv->test_socket); 501 drv->test_socket = -1; 502 } 503 504 if (drv->own_socket_path) { 505 unlink(drv->own_socket_path); 506 os_free(drv->own_socket_path); 507 drv->own_socket_path = NULL; 508 } 509} 510 511 512static void wpa_driver_test_deinit(void *priv) 513{ 514 struct wpa_driver_test_data *drv = priv; 515 wpa_driver_test_close_test_socket(drv); 516 eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); 517 os_free(drv->test_dir); 518 os_free(drv); 519} 520 521 522static int wpa_driver_test_attach(struct wpa_driver_test_data *drv, 523 const char *dir) 524{ 525 static unsigned int counter = 0; 526 struct sockaddr_un addr; 527 size_t len; 528 529 os_free(drv->own_socket_path); 530 if (dir) { 531 len = os_strlen(dir) + 30; 532 drv->own_socket_path = os_malloc(len); 533 if (drv->own_socket_path == NULL) 534 return -1; 535 os_snprintf(drv->own_socket_path, len, "%s/STA-" MACSTR, 536 dir, MAC2STR(drv->own_addr)); 537 } else { 538 drv->own_socket_path = os_malloc(100); 539 if (drv->own_socket_path == NULL) 540 return -1; 541 os_snprintf(drv->own_socket_path, 100, 542 "/tmp/wpa_supplicant_test-%d-%d", 543 getpid(), counter++); 544 } 545 546 drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0); 547 if (drv->test_socket < 0) { 548 perror("socket(PF_UNIX)"); 549 os_free(drv->own_socket_path); 550 drv->own_socket_path = NULL; 551 return -1; 552 } 553 554 os_memset(&addr, 0, sizeof(addr)); 555 addr.sun_family = AF_UNIX; 556 os_strncpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); 557 if (bind(drv->test_socket, (struct sockaddr *) &addr, 558 sizeof(addr)) < 0) { 559 perror("bind(PF_UNIX)"); 560 close(drv->test_socket); 561 unlink(drv->own_socket_path); 562 os_free(drv->own_socket_path); 563 drv->own_socket_path = NULL; 564 return -1; 565 } 566 567 eloop_register_read_sock(drv->test_socket, 568 wpa_driver_test_receive_unix, drv, NULL); 569 570 return 0; 571} 572 573 574static int wpa_driver_test_set_param(void *priv, const char *param) 575{ 576 struct wpa_driver_test_data *drv = priv; 577 const char *pos, *pos2; 578 size_t len; 579 580 wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); 581 if (param == NULL) 582 return 0; 583 584 wpa_driver_test_close_test_socket(drv); 585 pos = os_strstr(param, "test_socket="); 586 if (pos) { 587 pos += 12; 588 pos2 = os_strchr(pos, ' '); 589 if (pos2) 590 len = pos2 - pos; 591 else 592 len = os_strlen(pos); 593 if (len > sizeof(drv->hostapd_addr.sun_path)) 594 return -1; 595 os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr)); 596 drv->hostapd_addr.sun_family = AF_UNIX; 597 os_memcpy(drv->hostapd_addr.sun_path, pos, len); 598 drv->hostapd_addr_set = 1; 599 } 600 601 pos = os_strstr(param, "test_dir="); 602 if (pos) { 603 char *end; 604 os_free(drv->test_dir); 605 drv->test_dir = os_strdup(pos + 9); 606 if (drv->test_dir == NULL) 607 return -1; 608 end = os_strchr(drv->test_dir, ' '); 609 if (end) 610 *end = '\0'; 611 wpa_driver_test_attach(drv, drv->test_dir); 612 } else 613 wpa_driver_test_attach(drv, NULL); 614 615 if (os_strstr(param, "use_associnfo=1")) { 616 wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events"); 617 drv->use_associnfo = 1; 618 } 619 620#ifdef CONFIG_CLIENT_MLME 621 if (os_strstr(param, "use_mlme=1")) { 622 wpa_printf(MSG_DEBUG, "test_driver: Use internal MLME"); 623 drv->use_mlme = 1; 624 } 625#endif /* CONFIG_CLIENT_MLME */ 626 627 return 0; 628} 629 630 631static const u8 * wpa_driver_test_get_mac_addr(void *priv) 632{ 633 struct wpa_driver_test_data *drv = priv; 634 wpa_printf(MSG_DEBUG, "%s", __func__); 635 return drv->own_addr; 636} 637 638 639static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, 640 const u8 *data, size_t data_len) 641{ 642 struct wpa_driver_test_data *drv = priv; 643 struct msghdr msg; 644 struct iovec io[3]; 645 struct l2_ethhdr eth; 646 struct sockaddr_un addr; 647 648 wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len); 649 650 os_memset(ð, 0, sizeof(eth)); 651 os_memcpy(eth.h_dest, dest, ETH_ALEN); 652 os_memcpy(eth.h_source, drv->own_addr, ETH_ALEN); 653 eth.h_proto = host_to_be16(proto); 654 655 io[0].iov_base = "EAPOL "; 656 io[0].iov_len = 6; 657 io[1].iov_base = (u8 *) ð 658 io[1].iov_len = sizeof(eth); 659 io[2].iov_base = (u8 *) data; 660 io[2].iov_len = data_len; 661 662 os_memset(&msg, 0, sizeof(msg)); 663 msg.msg_iov = io; 664 msg.msg_iovlen = 3; 665 if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || 666 drv->test_dir == NULL) { 667 msg.msg_name = &drv->hostapd_addr; 668 msg.msg_namelen = sizeof(drv->hostapd_addr); 669 } else { 670 struct stat st; 671 os_memset(&addr, 0, sizeof(addr)); 672 addr.sun_family = AF_UNIX; 673 os_snprintf(addr.sun_path, sizeof(addr.sun_path), 674 "%s/STA-" MACSTR, drv->test_dir, MAC2STR(dest)); 675 if (stat(addr.sun_path, &st) < 0) { 676 os_snprintf(addr.sun_path, sizeof(addr.sun_path), 677 "%s/AP-" MACSTR, 678 drv->test_dir, MAC2STR(dest)); 679 } 680 msg.msg_name = &addr; 681 msg.msg_namelen = sizeof(addr); 682 } 683 684 if (sendmsg(drv->test_socket, &msg, 0) < 0) { 685 perror("sendmsg(test_socket)"); 686 return -1; 687 } 688 689 return 0; 690} 691 692 693static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa) 694{ 695 struct wpa_driver_test_data *drv = priv; 696 os_memset(capa, 0, sizeof(*capa)); 697 capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 698 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 699 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 700 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | 701 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; 702 capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | 703 WPA_DRIVER_CAPA_ENC_WEP104 | 704 WPA_DRIVER_CAPA_ENC_TKIP | 705 WPA_DRIVER_CAPA_ENC_CCMP; 706 capa->auth = WPA_DRIVER_AUTH_OPEN | 707 WPA_DRIVER_AUTH_SHARED | 708 WPA_DRIVER_AUTH_LEAP; 709 if (drv->use_mlme) 710 capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME; 711 712 return 0; 713} 714 715 716static int wpa_driver_test_mlme_setprotection(void *priv, const u8 *addr, 717 int protect_type, 718 int key_type) 719{ 720 wpa_printf(MSG_DEBUG, "%s: protect_type=%d key_type=%d", 721 __func__, protect_type, key_type); 722 723 if (addr) { 724 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, 725 __func__, MAC2STR(addr)); 726 } 727 728 return 0; 729} 730 731 732#ifdef CONFIG_CLIENT_MLME 733static struct wpa_hw_modes * 734wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) 735{ 736 struct wpa_hw_modes *modes; 737 738 *num_modes = 1; 739 *flags = 0; 740 modes = os_zalloc(*num_modes * sizeof(struct wpa_hw_modes)); 741 if (modes == NULL) 742 return NULL; 743 modes[0].mode = WPA_MODE_IEEE80211G; 744 modes[0].num_channels = 1; 745 modes[0].num_rates = 1; 746 modes[0].channels = os_zalloc(sizeof(struct wpa_channel_data)); 747 modes[0].rates = os_zalloc(sizeof(struct wpa_rate_data)); 748 if (modes[0].channels == NULL || modes[0].rates == NULL) { 749 ieee80211_sta_free_hw_features(modes, *num_modes); 750 return NULL; 751 } 752 modes[0].channels[0].chan = 1; 753 modes[0].channels[0].freq = 2412; 754 modes[0].channels[0].flag = WPA_CHAN_W_SCAN | WPA_CHAN_W_ACTIVE_SCAN; 755 modes[0].rates[0].rate = 10; 756 modes[0].rates[0].flags = WPA_RATE_BASIC | WPA_RATE_SUPPORTED | 757 WPA_RATE_CCK | WPA_RATE_MANDATORY; 758 759 return modes; 760} 761 762 763int wpa_driver_test_set_channel(void *priv, wpa_hw_mode phymode, int chan, 764 int freq) 765{ 766 wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d", 767 __func__, phymode, chan, freq); 768 return 0; 769} 770 771 772static int wpa_driver_test_send_mlme(void *priv, const u8 *data, 773 size_t data_len) 774{ 775 struct wpa_driver_test_data *drv = priv; 776 struct msghdr msg; 777 struct iovec io[2]; 778 struct sockaddr_un addr; 779 const u8 *dest; 780 struct dirent *dent; 781 DIR *dir; 782 783 wpa_hexdump(MSG_MSGDUMP, "test_send_mlme", data, data_len); 784 if (data_len < 10) 785 return -1; 786 dest = data + 4; 787 788 io[0].iov_base = "MLME "; 789 io[0].iov_len = 5; 790 io[1].iov_base = (u8 *) data; 791 io[1].iov_len = data_len; 792 793 os_memset(&msg, 0, sizeof(msg)); 794 msg.msg_iov = io; 795 msg.msg_iovlen = 2; 796 if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || 797 drv->test_dir == NULL) { 798 msg.msg_name = &drv->hostapd_addr; 799 msg.msg_namelen = sizeof(drv->hostapd_addr); 800 } else if (os_memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) 801 { 802 dir = opendir(drv->test_dir); 803 if (dir == NULL) 804 return -1; 805 while ((dent = readdir(dir))) { 806#ifdef _DIRENT_HAVE_D_TYPE 807 /* Skip the file if it is not a socket. 808 * Also accept DT_UNKNOWN (0) in case 809 * the C library or underlying file 810 * system does not support d_type. */ 811 if (dent->d_type != DT_SOCK && 812 dent->d_type != DT_UNKNOWN) 813 continue; 814#endif /* _DIRENT_HAVE_D_TYPE */ 815 if (os_strcmp(dent->d_name, ".") == 0 || 816 os_strcmp(dent->d_name, "..") == 0) 817 continue; 818 wpa_printf(MSG_DEBUG, "%s: Send broadcast MLME to %s", 819 __func__, dent->d_name); 820 os_memset(&addr, 0, sizeof(addr)); 821 addr.sun_family = AF_UNIX; 822 os_snprintf(addr.sun_path, sizeof(addr.sun_path), 823 "%s/%s", drv->test_dir, dent->d_name); 824 825 msg.msg_name = &addr; 826 msg.msg_namelen = sizeof(addr); 827 828 if (sendmsg(drv->test_socket, &msg, 0) < 0) 829 perror("sendmsg(test_socket)"); 830 } 831 closedir(dir); 832 return 0; 833 } else { 834 struct stat st; 835 os_memset(&addr, 0, sizeof(addr)); 836 addr.sun_family = AF_UNIX; 837 os_snprintf(addr.sun_path, sizeof(addr.sun_path), 838 "%s/AP-" MACSTR, drv->test_dir, MAC2STR(dest)); 839 if (stat(addr.sun_path, &st) < 0) { 840 os_snprintf(addr.sun_path, sizeof(addr.sun_path), 841 "%s/STA-" MACSTR, 842 drv->test_dir, MAC2STR(dest)); 843 } 844 msg.msg_name = &addr; 845 msg.msg_namelen = sizeof(addr); 846 } 847 848 if (sendmsg(drv->test_socket, &msg, 0) < 0) { 849 perror("sendmsg(test_socket)"); 850 return -1; 851 } 852 853 return 0; 854} 855 856 857static int wpa_driver_test_mlme_add_sta(void *priv, const u8 *addr, 858 const u8 *supp_rates, 859 size_t supp_rates_len) 860{ 861 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); 862 return 0; 863} 864 865 866static int wpa_driver_test_mlme_remove_sta(void *priv, const u8 *addr) 867{ 868 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); 869 return 0; 870} 871 872 873int wpa_driver_test_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) 874{ 875 wpa_printf(MSG_DEBUG, "%s", __func__); 876 return 0; 877} 878 879 880int wpa_driver_test_set_bssid(void *priv, const u8 *bssid) 881{ 882 wpa_printf(MSG_DEBUG, "%s: bssid=" MACSTR, __func__, MAC2STR(bssid)); 883 return 0; 884} 885#endif /* CONFIG_CLIENT_MLME */ 886 887int wpa_driver_test_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len ) 888{ 889 struct wpa_driver_test_data *drv = (struct wpa_driver_test_data *)priv; 890 int ret = -1; 891 892 wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd); 893 if( os_strncasecmp(cmd, "start", 5) == 0 ) { 894 wpa_printf(MSG_DEBUG,"Start command"); 895 ret = 0; 896 } 897 else if( os_strncasecmp(cmd, "stop", 4) == 0 ) { 898 wpa_printf(MSG_DEBUG,"Stop command"); 899 ret = 0; 900 } 901 else if( os_strncasecmp(cmd, "macaddr", 7) == 0 ) { 902 u8 *macaddr = (u8 *)wpa_driver_test_get_mac_addr(priv); 903 wpa_printf(MSG_DEBUG,"Macaddr command"); 904 wpa_printf(MSG_DEBUG, " Macaddr = " MACSTR, MAC2STR(macaddr)); 905 ret = os_snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); 906 } 907 else if( os_strncasecmp(cmd, "rssi", 4) == 0 ) { 908 wpa_printf(MSG_DEBUG,"RSSI command"); 909 ret = os_snprintf(buf, buf_len, MACSTR " Rssi %d\n", MAC2STR(drv->bssid), -10); 910 } else if (os_strncasecmp(cmd, "linkspeed", 9) == 0) { 911 wpa_printf(MSG_DEBUG, "LinkSpeed command"); 912 ret = os_snprintf(buf, buf_len, "LinkSpeed %u\n", 11); 913 } 914 return ret; 915} 916 917const struct wpa_driver_ops wpa_driver_test_ops = { 918 "test", 919 "wpa_supplicant test driver", 920 wpa_driver_test_get_bssid, 921 wpa_driver_test_get_ssid, 922 wpa_driver_test_set_wpa, 923 wpa_driver_test_set_key, 924 wpa_driver_test_init, 925 wpa_driver_test_deinit, 926 wpa_driver_test_set_param, 927 NULL /* set_countermeasures */, 928 NULL /* set_drop_unencrypted */, 929 wpa_driver_test_scan, 930 wpa_driver_test_get_scan_results, 931 wpa_driver_test_deauthenticate, 932 wpa_driver_test_disassociate, 933 wpa_driver_test_associate, 934 NULL /* set_auth_alg */, 935 NULL /* add_pmkid */, 936 NULL /* remove_pmkid */, 937 NULL /* flush_pmkid */, 938 wpa_driver_test_get_capa, 939 NULL /* poll */, 940 NULL /* get_ifname */, 941 wpa_driver_test_get_mac_addr, 942 wpa_driver_test_send_eapol, 943 NULL /* set_operstate */, 944 wpa_driver_test_mlme_setprotection, 945#ifdef CONFIG_CLIENT_MLME 946 wpa_driver_test_get_hw_feature_data, 947 wpa_driver_test_set_channel, 948 wpa_driver_test_set_ssid, 949 wpa_driver_test_set_bssid, 950 wpa_driver_test_send_mlme, 951 wpa_driver_test_mlme_add_sta, 952 wpa_driver_test_mlme_remove_sta, 953#else /* CONFIG_CLIENT_MLME */ 954 NULL /* get_hw_feature_data */, 955 NULL /* set_channel */, 956 NULL /* set_ssid */, 957 NULL /* set_bssid */, 958 NULL /* send_mlme */, 959 NULL /* mlme_add_sta */, 960 NULL /* mlme_remove_sta */, 961#endif /* CONFIG_CLIENT_MLME */ 962 wpa_driver_test_driver_cmd 963}; 964