driver_test.c

Go to the documentation of this file.
00001 
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020 #include <sys/socket.h>
00021 #include <sys/un.h>
00022 
00023 #include "common.h"
00024 #include "driver.h"
00025 #include "wpa_supplicant.h"
00026 #include "l2_packet.h"
00027 #include "eloop.h"
00028 #include "sha1.h"
00029 #include "wpa.h"
00030 
00031 
00032 struct wpa_driver_test_data {
00033         void *ctx;
00034         u8 own_addr[ETH_ALEN];
00035         int test_socket;
00036         struct sockaddr_un hostapd_addr;
00037         char *own_socket_path;
00038         u8 bssid[ETH_ALEN];
00039         u8 ssid[32];
00040         size_t ssid_len;
00041         struct wpa_scan_result scanres;
00042         size_t num_scanres;
00043         int use_associnfo;
00044         u8 assoc_wpa_ie[80];
00045         size_t assoc_wpa_ie_len;
00046 };
00047 
00048 
00049 static int wpa_driver_test_set_wpa(void *priv, int enabled)
00050 {
00051         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
00052         return 0;
00053 }
00054 
00055 
00056 static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
00057 {
00058         wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
00059         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
00060 }
00061 
00062 
00063 static int wpa_driver_test_scan(void *priv, const u8 *ssid, size_t ssid_len)
00064 {
00065         struct wpa_driver_test_data *drv = priv;
00066         wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
00067 
00068         if (drv->test_socket >= 0) {
00069                 if (sendto(drv->test_socket, "SCAN", 4, 0,
00070                            (struct sockaddr *) &drv->hostapd_addr,
00071                            sizeof(drv->hostapd_addr)) < 0) {
00072                         perror("sendto(test_socket)");
00073                         return -1;
00074                 }
00075         } else {
00076                 eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv,
00077                                        drv->ctx);
00078         }
00079         return 0;
00080 }
00081 
00082 
00083 static int wpa_driver_test_get_scan_results(void *priv,
00084                                             struct wpa_scan_result *results,
00085                                             size_t max_size)
00086 {
00087         struct wpa_driver_test_data *drv = priv;
00088         memcpy(results, &drv->scanres, sizeof(drv->scanres));
00089         return drv->num_scanres;
00090 }
00091 
00092 
00093 static int wpa_driver_test_set_key(void *priv, wpa_alg alg, const u8 *addr,
00094                                    int key_idx, int set_tx,
00095                                    const u8 *seq, size_t seq_len,
00096                                    const u8 *key, size_t key_len)
00097 {
00098         wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
00099                    __func__, priv, alg, key_idx, set_tx);
00100         if (addr) {
00101                 wpa_printf(MSG_DEBUG, "   addr=" MACSTR, MAC2STR(addr));
00102         }
00103         if (seq) {
00104                 wpa_hexdump(MSG_DEBUG, "   seq", seq, seq_len);
00105         }
00106         if (key) {
00107                 wpa_hexdump(MSG_DEBUG, "   key", key, key_len);
00108         }
00109         return 0;
00110 }
00111 
00112 
00113 static int wpa_driver_test_associate(
00114         void *priv, struct wpa_driver_associate_params *params)
00115 {
00116         struct wpa_driver_test_data *drv = priv;
00117         wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
00118                    "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
00119                    __func__, priv, params->freq, params->pairwise_suite,
00120                    params->group_suite, params->key_mgmt_suite,
00121                    params->auth_alg, params->mode);
00122         if (params->bssid) {
00123                 wpa_printf(MSG_DEBUG, "   bssid=" MACSTR,
00124                            MAC2STR(params->bssid));
00125         }
00126         if (params->ssid) {
00127                 wpa_hexdump_ascii(MSG_DEBUG, "   ssid",
00128                                   params->ssid, params->ssid_len);
00129         }
00130         if (params->wpa_ie) {
00131                 wpa_hexdump(MSG_DEBUG, "   wpa_ie",
00132                             params->wpa_ie, params->wpa_ie_len);
00133                 drv->assoc_wpa_ie_len = params->wpa_ie_len;
00134                 if (drv->assoc_wpa_ie_len > sizeof(drv->assoc_wpa_ie))
00135                         drv->assoc_wpa_ie_len = sizeof(drv->assoc_wpa_ie);
00136                 memcpy(drv->assoc_wpa_ie, params->wpa_ie,
00137                        drv->assoc_wpa_ie_len);
00138         } else
00139                 drv->assoc_wpa_ie_len = 0;
00140 
00141         if (drv->test_socket >= 0) {
00142                 char cmd[200], *pos, *end;
00143                 int i;
00144                 end = cmd + sizeof(cmd);
00145                 pos = cmd;
00146                 pos += snprintf(pos, end - pos, "ASSOC " MACSTR " ",
00147                                 MAC2STR(drv->own_addr));
00148                 for (i = 0; i < params->ssid_len; i++) {
00149                         pos += snprintf(pos, end - pos, "%02x",
00150                                         params->ssid[i]);
00151                 }
00152                 pos += snprintf(pos, end - pos, " ");
00153                 for (i = 0; i < params->wpa_ie_len; i++) {
00154                         pos += snprintf(pos, end - pos, "%02x",
00155                                         params->wpa_ie[i]);
00156                 }
00157                 if (sendto(drv->test_socket, cmd, strlen(cmd), 0,
00158                            (struct sockaddr *) &drv->hostapd_addr,
00159                            sizeof(drv->hostapd_addr)) < 0) {
00160                         perror("sendto(test_socket)");
00161                         return -1;
00162                 }
00163 
00164                 memcpy(drv->ssid, params->ssid, params->ssid_len);
00165                 drv->ssid_len = params->ssid_len;
00166         } else
00167                 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
00168 
00169         return 0;
00170 }
00171 
00172 
00173 static int wpa_driver_test_get_bssid(void *priv, u8 *bssid)
00174 {
00175         struct wpa_driver_test_data *drv = priv;
00176         memcpy(bssid, drv->bssid, ETH_ALEN);
00177         return 0;
00178 }
00179 
00180 
00181 static int wpa_driver_test_get_ssid(void *priv, u8 *ssid)
00182 {
00183         struct wpa_driver_test_data *drv = priv;
00184         memcpy(ssid, drv->ssid, 32);
00185         return drv->ssid_len;
00186 }
00187 
00188 
00189 static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv)
00190 {
00191         if (drv->test_socket >= 0 &&
00192             sendto(drv->test_socket, "DISASSOC", 8, 0,
00193                    (struct sockaddr *) &drv->hostapd_addr,
00194                    sizeof(drv->hostapd_addr)) < 0) {
00195                 perror("sendto(test_socket)");
00196                 return -1;
00197         }
00198         return 0;
00199 }
00200 
00201 
00202 static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr,
00203                                           int reason_code)
00204 {
00205         struct wpa_driver_test_data *drv = priv;
00206         wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
00207                    __func__, MAC2STR(addr), reason_code);
00208         memset(drv->bssid, 0, ETH_ALEN);
00209         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
00210         return wpa_driver_test_send_disassoc(drv);
00211 }
00212 
00213 
00214 static int wpa_driver_test_disassociate(void *priv, const u8 *addr,
00215                                         int reason_code)
00216 {
00217         struct wpa_driver_test_data *drv = priv;
00218         wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
00219                    __func__, MAC2STR(addr), reason_code);
00220         memset(drv->bssid, 0, ETH_ALEN);
00221         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
00222         return wpa_driver_test_send_disassoc(drv);
00223 }
00224 
00225 
00226 static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv,
00227                                      struct sockaddr_un *from,
00228                                      socklen_t fromlen,
00229                                      const char *data)
00230 {
00231         struct wpa_scan_result *res;
00232         const char *pos, *pos2;
00233         size_t len;
00234         u8 ie[200], *ipos, *end;
00235 
00236         wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data);
00237         /* SCANRESP BSSID SSID IEs */
00238         res = &drv->scanres;
00239         drv->num_scanres = 0;
00240 
00241         memset(res, 0, sizeof(*res));
00242         if (hwaddr_aton(data, res->bssid)) {
00243                 wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in scanres");
00244                 return;
00245         }
00246 
00247         pos = data + 17;
00248         while (*pos == ' ')
00249                 pos++;
00250         pos2 = strchr(pos, ' ');
00251         if (pos2 == NULL) {
00252                 wpa_printf(MSG_DEBUG, "test_driver: invalid SSID termination "
00253                            "in scanres");
00254                 return;
00255         }
00256         len = (pos2 - pos) / 2;
00257         if (len > sizeof(res->ssid))
00258                 len = sizeof(res->ssid);
00259         if (hexstr2bin(pos, res->ssid, len) < 0) {
00260                 wpa_printf(MSG_DEBUG, "test_driver: invalid SSID in scanres");
00261                 return;
00262         }
00263         res->ssid_len = len;
00264 
00265         pos = pos2 + 1;
00266         while (*pos == ' ')
00267                 pos++;
00268         pos2 = strchr(pos, ' ');
00269         if (pos2 == NULL)
00270                 len = strlen(pos) / 2;
00271         else
00272                 len = (pos2 - pos) / 2;
00273         if (len > sizeof(ie))
00274                 len = sizeof(ie);
00275         if (hexstr2bin(pos, ie, len) < 0) {
00276                 wpa_printf(MSG_DEBUG, "test_driver: invalid IEs in scanres");
00277                 return;
00278         }
00279 
00280         ipos = ie;
00281         end = ipos + len;
00282         while (ipos + 1 < end && ipos + 2 + ipos[1] <= end) {
00283                 len = 2 + ipos[1];
00284                 if (len > SSID_MAX_WPA_IE_LEN)
00285                         len = SSID_MAX_WPA_IE_LEN;
00286                 if (ipos[0] == RSN_INFO_ELEM) {
00287                         memcpy(res->rsn_ie, ipos, len);
00288                         res->rsn_ie_len = len;
00289                 } else if (ipos[0] == GENERIC_INFO_ELEM) {
00290                         memcpy(res->wpa_ie, ipos, len);
00291                         res->wpa_ie_len = len;
00292                 }
00293 
00294                 ipos += 2 + ipos[1];
00295         }
00296 
00297         drv->num_scanres = 1;
00298         wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
00299 }
00300 
00301 
00302 static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv,
00303                                       struct sockaddr_un *from,
00304                                       socklen_t fromlen,
00305                                       const char *data)
00306 {
00307         /* ASSOCRESP BSSID <res> */
00308         if (hwaddr_aton(data, drv->bssid)) {
00309                 wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in "
00310                            "assocresp");
00311         }
00312         if (drv->use_associnfo) {
00313                 union wpa_event_data event;
00314                 memset(&event, 0, sizeof(event));
00315                 event.assoc_info.req_ies = drv->assoc_wpa_ie;
00316                 event.assoc_info.req_ies_len = drv->assoc_wpa_ie_len;
00317                 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &event);
00318         }
00319         wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
00320 }
00321 
00322 
00323 static void wpa_driver_test_disassoc(struct wpa_driver_test_data *drv,
00324                                      struct sockaddr_un *from,
00325                                      socklen_t fromlen)
00326 {
00327         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
00328 }
00329 
00330 
00331 static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv,
00332                                   struct sockaddr_un *from,
00333                                   socklen_t fromlen,
00334                                   const u8 *data, size_t data_len)
00335 {
00336         if (data_len > 14) {
00337                 /* Skip Ethernet header */
00338                 data += 14;
00339                 data_len -= 14;
00340         }
00341         wpa_supplicant_rx_eapol(drv->ctx, drv->bssid, (u8 *) data, data_len);
00342 }
00343 
00344 
00345 static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx,
00346                                          void *sock_ctx)
00347 {
00348         struct wpa_driver_test_data *drv = eloop_ctx;
00349         char *buf;
00350         int res;
00351         struct sockaddr_un from;
00352         socklen_t fromlen = sizeof(from);
00353         const size_t buflen = 2000;
00354 
00355         buf = malloc(buflen);
00356         if (buf == NULL)
00357                 return;
00358         res = recvfrom(sock, buf, buflen - 1, 0,
00359                        (struct sockaddr *) &from, &fromlen);
00360         if (res < 0) {
00361                 perror("recvfrom(test_socket)");
00362                 free(buf);
00363                 return;
00364         }
00365         buf[res] = '\0';
00366 
00367         wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res);
00368 
00369         if (strncmp(buf, "SCANRESP ", 9) == 0) {
00370                 wpa_driver_test_scanresp(drv, &from, fromlen, buf + 9);
00371         } else if (strncmp(buf, "ASSOCRESP ", 10) == 0) {
00372                 wpa_driver_test_assocresp(drv, &from, fromlen, buf + 10);
00373         } else if (strcmp(buf, "DISASSOC") == 0) {
00374                 wpa_driver_test_disassoc(drv, &from, fromlen);
00375         } else if (strcmp(buf, "DEAUTH") == 0) {
00376                 wpa_driver_test_disassoc(drv, &from, fromlen);
00377         } else if (strncmp(buf, "EAPOL ", 6) == 0) {
00378                 wpa_driver_test_eapol(drv, &from, fromlen,
00379                                       (const u8 *) buf + 6, res - 6);
00380         } else {
00381                 wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command",
00382                                   (u8 *) buf, res);
00383         }
00384         free(buf);
00385 }
00386 
00387 
00388 static void * wpa_driver_test_init(void *ctx, const char *ifname)
00389 {
00390         struct wpa_driver_test_data *drv;
00391 
00392         drv = malloc(sizeof(*drv));
00393         if (drv == NULL)
00394                 return NULL;
00395         memset(drv, 0, sizeof(*drv));
00396         drv->ctx = ctx;
00397         drv->test_socket = -1;
00398 
00399         /* Set dummy BSSID and SSID for testing. */
00400         drv->bssid[0] = 0x02;
00401         drv->bssid[1] = 0x00;
00402         drv->bssid[2] = 0x00;
00403         drv->bssid[3] = 0x00;
00404         drv->bssid[4] = 0x00;
00405         drv->bssid[5] = 0x01;
00406         memcpy(drv->ssid, "test", 5);
00407         drv->ssid_len = 4;
00408 
00409         /* Generate a MAC address to help testing with multiple STAs */
00410         drv->own_addr[0] = 0x02; /* locally administered */
00411         sha1_prf((const u8 *) ifname, strlen(ifname),
00412                  "wpa_supplicant test mac addr generation",
00413                  NULL, 0, drv->own_addr + 1, ETH_ALEN - 1);
00414 
00415         return drv;
00416 }
00417 
00418 
00419 static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv)
00420 {
00421         if (drv->test_socket >= 0) {
00422                 eloop_unregister_read_sock(drv->test_socket);
00423                 close(drv->test_socket);
00424                 drv->test_socket = -1;
00425         }
00426 
00427         if (drv->own_socket_path) {
00428                 unlink(drv->own_socket_path);
00429                 free(drv->own_socket_path);
00430                 drv->own_socket_path = NULL;
00431         }
00432 }
00433 
00434 
00435 static void wpa_driver_test_deinit(void *priv)
00436 {
00437         struct wpa_driver_test_data *drv = priv;
00438         wpa_driver_test_close_test_socket(drv);
00439         free(drv);
00440 }
00441 
00442 
00443 static int wpa_driver_test_attach(struct wpa_driver_test_data *drv)
00444 {
00445         static unsigned int counter = 0;
00446         struct sockaddr_un addr;
00447 
00448         drv->own_socket_path = malloc(100);
00449         if (drv->own_socket_path == NULL)
00450                 return -1;
00451         snprintf(drv->own_socket_path, 100, "/tmp/wpa_supplicant_test-%d-%d",
00452                  getpid(), counter++);
00453 
00454         drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
00455         if (drv->test_socket < 0) {
00456                 perror("socket(PF_UNIX)");
00457                 free(drv->own_socket_path);
00458                 drv->own_socket_path = NULL;
00459                 return -1;
00460         }
00461 
00462         memset(&addr, 0, sizeof(addr));
00463         addr.sun_family = AF_UNIX;
00464         strncpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
00465         if (bind(drv->test_socket, (struct sockaddr *) &addr,
00466                  sizeof(addr)) < 0) {
00467                 perror("bind(PF_UNIX)");
00468                 close(drv->test_socket);
00469                 unlink(drv->own_socket_path);
00470                 free(drv->own_socket_path);
00471                 drv->own_socket_path = NULL;
00472                 return -1;
00473         }
00474 
00475         eloop_register_read_sock(drv->test_socket,
00476                                  wpa_driver_test_receive_unix, drv, NULL);
00477 
00478         return 0;
00479 }
00480 
00481 
00482 static int wpa_driver_test_set_param(void *priv, const char *param)
00483 {
00484         struct wpa_driver_test_data *drv = priv;
00485         const char *pos, *pos2;
00486         size_t len;
00487 
00488         wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
00489         if (param == NULL)
00490                 return 0;
00491 
00492         wpa_driver_test_close_test_socket(drv);
00493         pos = strstr(param, "test_socket=");
00494         if (pos) {
00495                 pos += 12;
00496                 pos2 = strchr(pos, ' ');
00497                 if (pos2)
00498                         len = pos2 - pos;
00499                 else
00500                         len = strlen(pos);
00501                 if (len > sizeof(drv->hostapd_addr.sun_path))
00502                         return -1;
00503                 memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr));
00504                 drv->hostapd_addr.sun_family = AF_UNIX;
00505                 memcpy(drv->hostapd_addr.sun_path, pos, len);
00506                 wpa_driver_test_attach(drv);
00507         }
00508 
00509         if (strstr(param, "use_associnfo=1")) {
00510                 wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events");
00511                 drv->use_associnfo = 1;
00512         }
00513 
00514         return 0;
00515 }
00516 
00517 
00518 static const u8 * wpa_driver_test_get_mac_addr(void *priv)
00519 {
00520         struct wpa_driver_test_data *drv = priv;
00521         wpa_printf(MSG_DEBUG, "%s", __func__);
00522         return drv->own_addr;
00523 }
00524 
00525 
00526 static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto,
00527                                       const u8 *data, size_t data_len)
00528 {
00529         struct wpa_driver_test_data *drv = priv;
00530         struct msghdr msg;
00531         struct iovec io[3];
00532         struct l2_ethhdr eth;
00533 
00534         wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len);
00535 
00536         memset(&eth, 0, sizeof(eth));
00537         memcpy(eth.h_dest, dest, ETH_ALEN);
00538         memcpy(eth.h_source, drv->own_addr, ETH_ALEN);
00539         eth.h_proto = host_to_be16(proto);
00540 
00541         io[0].iov_base = "EAPOL ";
00542         io[0].iov_len = 6;
00543         io[1].iov_base = (u8 *) &eth;
00544         io[1].iov_len = sizeof(eth);
00545         io[2].iov_base = (u8 *) data;
00546         io[2].iov_len = data_len;
00547 
00548         memset(&msg, 0, sizeof(msg));
00549         msg.msg_iov = io;
00550         msg.msg_iovlen = 3;
00551         msg.msg_name = &drv->hostapd_addr;
00552         msg.msg_namelen = sizeof(drv->hostapd_addr);
00553         if (sendmsg(drv->test_socket, &msg, 0) < 0) {
00554                 perror("sendmsg(test_socket)");
00555                 return -1;
00556         }
00557 
00558         return 0;
00559 }
00560 
00561 
00562 static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
00563 {
00564         memset(capa, 0, sizeof(*capa));
00565         capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
00566                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
00567                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
00568                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
00569                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
00570         capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 |
00571                 WPA_DRIVER_CAPA_ENC_WEP104 |
00572                 WPA_DRIVER_CAPA_ENC_TKIP |
00573                 WPA_DRIVER_CAPA_ENC_CCMP;
00574         capa->auth = WPA_DRIVER_AUTH_OPEN |
00575                 WPA_DRIVER_AUTH_SHARED |
00576                 WPA_DRIVER_AUTH_LEAP;
00577 
00578         return 0;
00579 }
00580 
00581 
00582 const struct wpa_driver_ops wpa_driver_test_ops = {
00583         .name = "test",
00584         .desc = "wpa_supplicant test driver",
00585         .init = wpa_driver_test_init,
00586         .deinit = wpa_driver_test_deinit,
00587         .set_param = wpa_driver_test_set_param,
00588         .set_wpa = wpa_driver_test_set_wpa,
00589         .scan = wpa_driver_test_scan,
00590         .get_scan_results = wpa_driver_test_get_scan_results,
00591         .set_key = wpa_driver_test_set_key,
00592         .associate = wpa_driver_test_associate,
00593         .get_bssid = wpa_driver_test_get_bssid,
00594         .get_ssid = wpa_driver_test_get_ssid,
00595         .get_mac_addr = wpa_driver_test_get_mac_addr,
00596         .send_eapol = wpa_driver_test_send_eapol,
00597         .deauthenticate = wpa_driver_test_deauthenticate,
00598         .disassociate = wpa_driver_test_disassociate,
00599         .get_capa = wpa_driver_test_get_capa,
00600 };
00601 

Generated on Sat May 6 21:13:33 2006 for wpa_supplicant by  doxygen 1.4.2