]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/hostapd/driver_test.c
This commit was generated by cvs2svn to compensate for changes in r174993,
[FreeBSD/FreeBSD.git] / contrib / hostapd / driver_test.c
1 /*
2  * hostapd / Driver interface for development testing
3  * Copyright (c) 2004-2007, 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/ioctl.h>
17 #include <sys/un.h>
18 #include <dirent.h>
19
20 #include "hostapd.h"
21 #include "driver.h"
22 #include "sha1.h"
23 #include "eloop.h"
24 #include "ieee802_1x.h"
25 #include "sta_info.h"
26 #include "eapol_sm.h"
27 #include "wpa.h"
28 #include "accounting.h"
29 #include "radius.h"
30 #include "l2_packet.h"
31 #include "ieee802_11.h"
32 #include "hw_features.h"
33
34
35 struct test_client_socket {
36         struct test_client_socket *next;
37         u8 addr[ETH_ALEN];
38         struct sockaddr_un un;
39         socklen_t unlen;
40         struct test_driver_bss *bss;
41 };
42
43 struct test_driver_bss {
44         struct test_driver_bss *next;
45         char ifname[IFNAMSIZ + 1];
46         u8 bssid[ETH_ALEN];
47         u8 *ie;
48         size_t ielen;
49         u8 ssid[32];
50         size_t ssid_len;
51         int privacy;
52 };
53
54 struct test_driver_data {
55         struct driver_ops ops;
56         struct hostapd_data *hapd;
57         struct test_client_socket *cli;
58         int test_socket;
59         struct test_driver_bss *bss;
60         char *socket_dir;
61         char *own_socket_path;
62 };
63
64 static const struct driver_ops test_driver_ops;
65
66
67 static void test_driver_free_bss(struct test_driver_bss *bss)
68 {
69         free(bss->ie);
70         free(bss);
71 }
72
73
74 static void test_driver_free_priv(struct test_driver_data *drv)
75 {
76         struct test_driver_bss *bss, *prev;
77
78         if (drv == NULL)
79                 return;
80
81         bss = drv->bss;
82         while (bss) {
83                 prev = bss;
84                 bss = bss->next;
85                 test_driver_free_bss(prev);
86         }
87         free(drv->own_socket_path);
88         free(drv->socket_dir);
89         free(drv);
90 }
91
92
93 static struct test_client_socket *
94 test_driver_get_cli(struct test_driver_data *drv, struct sockaddr_un *from,
95                     socklen_t fromlen)
96 {
97         struct test_client_socket *cli = drv->cli;
98
99         while (cli) {
100                 if (cli->unlen == fromlen &&
101                     strncmp(cli->un.sun_path, from->sun_path,
102                             fromlen - sizeof(cli->un.sun_family)) == 0)
103                         return cli;
104                 cli = cli->next;
105         }
106
107         return NULL;
108 }
109
110
111 static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data,
112                                   size_t data_len, int encrypt,
113                                   const u8 *own_addr)
114 {
115         struct test_driver_data *drv = priv;
116         struct test_client_socket *cli;
117         struct msghdr msg;
118         struct iovec io[3];
119         struct l2_ethhdr eth;
120
121         if (drv->test_socket < 0)
122                 return -1;
123
124         cli = drv->cli;
125         while (cli) {
126                 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
127                         break;
128                 cli = cli->next;
129         }
130
131         if (!cli) {
132                 wpa_printf(MSG_DEBUG, "%s: no destination client entry",
133                            __func__);
134                 return -1;
135         }
136
137         memcpy(eth.h_dest, addr, ETH_ALEN);
138         memcpy(eth.h_source, own_addr, ETH_ALEN);
139         eth.h_proto = htons(ETH_P_EAPOL);
140
141         io[0].iov_base = "EAPOL ";
142         io[0].iov_len = 6;
143         io[1].iov_base = &eth;
144         io[1].iov_len = sizeof(eth);
145         io[2].iov_base = (u8 *) data;
146         io[2].iov_len = data_len;
147
148         memset(&msg, 0, sizeof(msg));
149         msg.msg_iov = io;
150         msg.msg_iovlen = 3;
151         msg.msg_name = &cli->un;
152         msg.msg_namelen = cli->unlen;
153         return sendmsg(drv->test_socket, &msg, 0);
154 }
155
156
157 static int test_driver_send_mgmt_frame(void *priv, const void *buf,
158                                        size_t len, int flags)
159 {
160         struct test_driver_data *drv = priv;
161         struct msghdr msg;
162         struct iovec io[2];
163         const u8 *dest;
164         int ret = 0, broadcast = 0;
165         char desttxt[30];
166         struct sockaddr_un addr;
167         struct dirent *dent;
168         DIR *dir;
169         struct ieee80211_hdr *hdr;
170         u16 fc;
171
172         if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) {
173                 wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%d "
174                            "socket_dir=%p)",
175                            __func__, drv->test_socket, len, drv->socket_dir);
176                 return -1;
177         }
178
179         dest = buf;
180         dest += 4;
181         broadcast = memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0;
182         snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest));
183
184         io[0].iov_base = "MLME ";
185         io[0].iov_len = 5;
186         io[1].iov_base = (void *) buf;
187         io[1].iov_len = len;
188
189         memset(&msg, 0, sizeof(msg));
190         msg.msg_iov = io;
191         msg.msg_iovlen = 2;
192
193         dir = opendir(drv->socket_dir);
194         if (dir == NULL) {
195                 perror("test_driver: opendir");
196                 return -1;
197         }
198         while ((dent = readdir(dir))) {
199 #ifdef _DIRENT_HAVE_D_TYPE
200                 /* Skip the file if it is not a socket. Also accept
201                  * DT_UNKNOWN (0) in case the C library or underlying file
202                  * system does not support d_type. */
203                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
204                         continue;
205 #endif /* _DIRENT_HAVE_D_TYPE */
206                 if (strcmp(dent->d_name, ".") == 0 ||
207                     strcmp(dent->d_name, "..") == 0)
208                         continue;
209
210                 memset(&addr, 0, sizeof(addr));
211                 addr.sun_family = AF_UNIX;
212                 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s",
213                          drv->socket_dir, dent->d_name);
214
215                 if (strcmp(addr.sun_path, drv->own_socket_path) == 0)
216                         continue;
217                 if (!broadcast && strstr(dent->d_name, desttxt) == NULL)
218                         continue;
219
220                 wpa_printf(MSG_DEBUG, "%s: Send management frame to %s",
221                            __func__, dent->d_name);
222
223                 msg.msg_name = &addr;
224                 msg.msg_namelen = sizeof(addr);
225                 ret = sendmsg(drv->test_socket, &msg, 0);
226                 if (ret < 0)
227                         perror("driver_test: sendmsg");
228         }
229         closedir(dir);
230
231         hdr = (struct ieee80211_hdr *) buf;
232         fc = le_to_host16(hdr->frame_control);
233         ieee802_11_mgmt_cb(drv->hapd, (u8 *) buf, len, WLAN_FC_GET_STYPE(fc),
234                            ret >= 0);
235
236         return ret;
237 }
238
239
240 static void test_driver_scan(struct test_driver_data *drv,
241                              struct sockaddr_un *from, socklen_t fromlen)
242 {
243         char buf[512], *pos, *end;
244         int ret;
245         struct test_driver_bss *bss;
246
247         wpa_printf(MSG_DEBUG, "test_driver: SCAN");
248
249         for (bss = drv->bss; bss; bss = bss->next) {
250                 pos = buf;
251                 end = buf + sizeof(buf);
252
253                 /* reply: SCANRESP BSSID SSID IEs */
254                 ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
255                                MAC2STR(bss->bssid));
256                 if (ret < 0 || ret >= end - pos)
257                         return;
258                 pos += ret;
259                 pos += wpa_snprintf_hex(pos, end - pos,
260                                         bss->ssid, bss->ssid_len);
261                 ret = snprintf(pos, end - pos, " ");
262                 if (ret < 0 || ret >= end - pos)
263                         return;
264                 pos += ret;
265                 pos += wpa_snprintf_hex(pos, end - pos, bss->ie, bss->ielen);
266
267                 if (bss->privacy) {
268                         ret = snprintf(pos, end - pos, " PRIVACY");
269                         if (ret < 0 || ret >= end - pos)
270                                 return;
271                         pos += ret;
272                 }
273
274                 sendto(drv->test_socket, buf, pos - buf, 0,
275                        (struct sockaddr *) from, fromlen);
276         }
277 }
278
279
280 static struct hostapd_data * test_driver_get_hapd(struct test_driver_data *drv,
281                                                   struct test_driver_bss *bss)
282 {
283         struct hostapd_iface *iface = drv->hapd->iface;
284         struct hostapd_data *hapd = NULL;
285         size_t i;
286
287         if (bss == NULL) {
288                 wpa_printf(MSG_DEBUG, "%s: bss == NULL", __func__);
289                 return NULL;
290         }
291
292         for (i = 0; i < iface->num_bss; i++) {
293                 hapd = iface->bss[i];
294                 if (memcmp(hapd->own_addr, bss->bssid, ETH_ALEN) == 0)
295                         break;
296         }
297         if (i == iface->num_bss) {
298                 wpa_printf(MSG_DEBUG, "%s: no matching interface entry found "
299                            "for BSSID " MACSTR, __func__, MAC2STR(bss->bssid));
300                 return NULL;
301         }
302
303         return hapd;
304 }
305
306
307 static int test_driver_new_sta(struct test_driver_data *drv,
308                                struct test_driver_bss *bss, const u8 *addr,
309                                const u8 *ie, size_t ielen)
310 {
311         struct hostapd_data *hapd;
312         struct sta_info *sta;
313         int new_assoc, res;
314
315         hapd = test_driver_get_hapd(drv, bss);
316         if (hapd == NULL)
317                 return -1;
318
319         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
320                 HOSTAPD_LEVEL_INFO, "associated");
321
322         sta = ap_get_sta(hapd, addr);
323         if (sta) {
324                 accounting_sta_stop(hapd, sta);
325         } else {
326                 sta = ap_sta_add(hapd, addr);
327                 if (sta == NULL)
328                         return -1;
329         }
330         accounting_sta_get_id(hapd, sta);
331
332         if (hapd->conf->wpa) {
333                 if (ie == NULL || ielen == 0) {
334                         printf("test_driver: no IE from STA\n");
335                         return -1;
336                 }
337                 if (sta->wpa_sm == NULL)
338                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
339                                                         sta->addr);
340                 if (sta->wpa_sm == NULL) {
341                         printf("test_driver: Failed to initialize WPA state "
342                                "machine\n");
343                         return -1;
344                 }
345                 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
346                                           ie, ielen);
347                 if (res != WPA_IE_OK) {
348                         printf("WPA/RSN information element rejected? "
349                                "(res %u)\n", res);
350                         return -1;
351                 }
352         }
353
354         new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
355         sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
356         wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
357
358         hostapd_new_assoc_sta(hapd, sta, !new_assoc);
359
360         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
361
362         return 0;
363 }
364
365
366 static void test_driver_assoc(struct test_driver_data *drv,
367                               struct sockaddr_un *from, socklen_t fromlen,
368                               char *data)
369 {
370         struct test_client_socket *cli;
371         u8 ie[256], ssid[32];
372         size_t ielen, ssid_len = 0;
373         char *pos, *pos2, cmd[50];
374         struct test_driver_bss *bss;
375
376         /* data: STA-addr SSID(hex) IEs(hex) */
377
378         cli = wpa_zalloc(sizeof(*cli));
379         if (cli == NULL)
380                 return;
381
382         if (hwaddr_aton(data, cli->addr)) {
383                 printf("test_socket: Invalid MAC address '%s' in ASSOC\n",
384                        data);
385                 free(cli);
386                 return;
387         }
388         pos = data + 17;
389         while (*pos == ' ')
390                 pos++;
391         pos2 = strchr(pos, ' ');
392         ielen = 0;
393         if (pos2) {
394                 ssid_len = (pos2 - pos) / 2;
395                 if (hexstr2bin(pos, ssid, ssid_len) < 0) {
396                         wpa_printf(MSG_DEBUG, "%s: Invalid SSID", __func__);
397                         free(cli);
398                         return;
399                 }
400                 wpa_hexdump_ascii(MSG_DEBUG, "test_driver_assoc: SSID",
401                                   ssid, ssid_len);
402
403                 pos = pos2 + 1;
404                 ielen = strlen(pos) / 2;
405                 if (ielen > sizeof(ie))
406                         ielen = sizeof(ie);
407                 if (hexstr2bin(pos, ie, ielen) < 0)
408                         ielen = 0;
409         }
410
411         for (bss = drv->bss; bss; bss = bss->next) {
412                 if (bss->ssid_len == ssid_len &&
413                     memcmp(bss->ssid, ssid, ssid_len) == 0)
414                         break;
415         }
416         if (bss == NULL) {
417                 wpa_printf(MSG_DEBUG, "%s: No matching SSID found from "
418                            "configured BSSes", __func__);
419                 free(cli);
420                 return;
421         }
422
423         cli->bss = bss;
424         memcpy(&cli->un, from, sizeof(cli->un));
425         cli->unlen = fromlen;
426         cli->next = drv->cli;
427         drv->cli = cli;
428         wpa_hexdump_ascii(MSG_DEBUG, "test_socket: ASSOC sun_path",
429                           (const u8 *) cli->un.sun_path,
430                           cli->unlen - sizeof(cli->un.sun_family));
431
432         snprintf(cmd, sizeof(cmd), "ASSOCRESP " MACSTR " 0",
433                  MAC2STR(bss->bssid));
434         sendto(drv->test_socket, cmd, strlen(cmd), 0,
435                (struct sockaddr *) from, fromlen);
436
437         if (test_driver_new_sta(drv, bss, cli->addr, ie, ielen) < 0) {
438                 wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA");
439         }
440 }
441
442
443 static void test_driver_disassoc(struct test_driver_data *drv,
444                                  struct sockaddr_un *from, socklen_t fromlen)
445 {
446         struct test_client_socket *cli;
447         struct sta_info *sta;
448
449         cli = test_driver_get_cli(drv, from, fromlen);
450         if (!cli)
451                 return;
452
453         hostapd_logger(drv->hapd, cli->addr, HOSTAPD_MODULE_IEEE80211,
454                        HOSTAPD_LEVEL_INFO, "disassociated");
455
456         sta = ap_get_sta(drv->hapd, cli->addr);
457         if (sta != NULL) {
458                 sta->flags &= ~WLAN_STA_ASSOC;
459                 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
460                 sta->acct_terminate_cause =
461                         RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
462                 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
463                 ap_free_sta(drv->hapd, sta);
464         }
465 }
466
467
468 static void test_driver_eapol(struct test_driver_data *drv,
469                               struct sockaddr_un *from, socklen_t fromlen,
470                               u8 *data, size_t datalen)
471 {
472         struct test_client_socket *cli;
473         if (datalen > 14) {
474                 u8 *proto = data + 2 * ETH_ALEN;
475                 /* Skip Ethernet header */
476                 wpa_printf(MSG_DEBUG, "test_driver: dst=" MACSTR " src="
477                            MACSTR " proto=%04x",
478                            MAC2STR(data), MAC2STR(data + ETH_ALEN),
479                            (proto[0] << 8) | proto[1]);
480                 data += 14;
481                 datalen -= 14;
482         }
483         cli = test_driver_get_cli(drv, from, fromlen);
484         if (cli) {
485                 struct hostapd_data *hapd;
486                 hapd = test_driver_get_hapd(drv, cli->bss);
487                 if (hapd == NULL)
488                         return;
489                 ieee802_1x_receive(hapd, cli->addr, data, datalen);
490         } else {
491                 wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown "
492                            "client");
493         }
494 }
495
496
497 static void test_driver_mlme(struct test_driver_data *drv,
498                              struct sockaddr_un *from, socklen_t fromlen,
499                              u8 *data, size_t datalen)
500 {
501         struct ieee80211_hdr *hdr;
502         u16 fc;
503
504         hdr = (struct ieee80211_hdr *) data;
505
506         if (test_driver_get_cli(drv, from, fromlen) == NULL && datalen >= 16) {
507                 struct test_client_socket *cli;
508                 cli = wpa_zalloc(sizeof(*cli));
509                 if (cli == NULL)
510                         return;
511                 wpa_printf(MSG_DEBUG, "Adding client entry for " MACSTR,
512                            MAC2STR(hdr->addr2));
513                 memcpy(cli->addr, hdr->addr2, ETH_ALEN);
514                 memcpy(&cli->un, from, sizeof(cli->un));
515                 cli->unlen = fromlen;
516                 cli->next = drv->cli;
517                 drv->cli = cli;
518         }
519
520         wpa_hexdump(MSG_MSGDUMP, "test_driver_mlme: received frame",
521                     data, datalen);
522         fc = le_to_host16(hdr->frame_control);
523         if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) {
524                 wpa_printf(MSG_ERROR, "%s: received non-mgmt frame",
525                            __func__);
526                 return;
527         }
528         ieee802_11_mgmt(drv->hapd, data, datalen, WLAN_FC_GET_STYPE(fc), NULL);
529 }
530
531
532 static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx)
533 {
534         struct test_driver_data *drv = eloop_ctx;
535         char buf[2000];
536         int res;
537         struct sockaddr_un from;
538         socklen_t fromlen = sizeof(from);
539
540         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
541                        (struct sockaddr *) &from, &fromlen);
542         if (res < 0) {
543                 perror("recvfrom(test_socket)");
544                 return;
545         }
546         buf[res] = '\0';
547
548         wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res);
549
550         if (strcmp(buf, "SCAN") == 0) {
551                 test_driver_scan(drv, &from, fromlen);
552         } else if (strncmp(buf, "ASSOC ", 6) == 0) {
553                 test_driver_assoc(drv, &from, fromlen, buf + 6);
554         } else if (strcmp(buf, "DISASSOC") == 0) {
555                 test_driver_disassoc(drv, &from, fromlen);
556         } else if (strncmp(buf, "EAPOL ", 6) == 0) {
557                 test_driver_eapol(drv, &from, fromlen, (u8 *) buf + 6,
558                                   res - 6);
559         } else if (strncmp(buf, "MLME ", 5) == 0) {
560                 test_driver_mlme(drv, &from, fromlen, (u8 *) buf + 5, res - 5);
561         } else {
562                 wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command",
563                                   (u8 *) buf, res);
564         }
565 }
566
567
568 static int test_driver_set_generic_elem(const char *ifname, void *priv,
569                                         const u8 *elem, size_t elem_len)
570 {
571         struct test_driver_data *drv = priv;
572         struct test_driver_bss *bss;
573
574         for (bss = drv->bss; bss; bss = bss->next) {
575                 if (strcmp(bss->ifname, ifname) != 0)
576                         continue;
577
578                 free(bss->ie);
579
580                 if (elem == NULL) {
581                         bss->ie = NULL;
582                         bss->ielen = 0;
583                         return 0;
584                 }
585
586                 bss->ie = malloc(elem_len);
587                 if (bss->ie) {
588                         memcpy(bss->ie, elem, elem_len);
589                         bss->ielen = elem_len;
590                         return 0;
591                 } else {
592                         bss->ielen = 0;
593                         return -1;
594                 }
595         }
596
597         return -1;
598 }
599
600
601 static int test_driver_sta_deauth(void *priv, const u8 *addr, int reason)
602 {
603         struct test_driver_data *drv = priv;
604         struct test_client_socket *cli;
605
606         if (drv->test_socket < 0)
607                 return -1;
608
609         cli = drv->cli;
610         while (cli) {
611                 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
612                         break;
613                 cli = cli->next;
614         }
615
616         if (!cli)
617                 return -1;
618
619         return sendto(drv->test_socket, "DEAUTH", 6, 0,
620                       (struct sockaddr *) &cli->un, cli->unlen);
621 }
622
623
624 static int test_driver_sta_disassoc(void *priv, const u8 *addr, int reason)
625 {
626         struct test_driver_data *drv = priv;
627         struct test_client_socket *cli;
628
629         if (drv->test_socket < 0)
630                 return -1;
631
632         cli = drv->cli;
633         while (cli) {
634                 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
635                         break;
636                 cli = cli->next;
637         }
638
639         if (!cli)
640                 return -1;
641
642         return sendto(drv->test_socket, "DISASSOC", 8, 0,
643                       (struct sockaddr *) &cli->un, cli->unlen);
644 }
645
646
647 static struct hostapd_hw_modes *
648 test_driver_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
649 {
650         struct hostapd_hw_modes *modes;
651
652         *num_modes = 3;
653         *flags = 0;
654         modes = wpa_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
655         if (modes == NULL)
656                 return NULL;
657         modes[0].mode = HOSTAPD_MODE_IEEE80211G;
658         modes[0].num_channels = 1;
659         modes[0].num_rates = 1;
660         modes[0].channels = wpa_zalloc(sizeof(struct hostapd_channel_data));
661         modes[0].rates = wpa_zalloc(sizeof(struct hostapd_rate_data));
662         if (modes[0].channels == NULL || modes[0].rates == NULL) {
663                 hostapd_free_hw_features(modes, *num_modes);
664                 return NULL;
665         }
666         modes[0].channels[0].chan = 1;
667         modes[0].channels[0].freq = 2412;
668         modes[0].channels[0].flag = HOSTAPD_CHAN_W_SCAN |
669                 HOSTAPD_CHAN_W_ACTIVE_SCAN;
670         modes[0].rates[0].rate = 10;
671         modes[0].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
672                 HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY;
673
674         modes[1].mode = HOSTAPD_MODE_IEEE80211B;
675         modes[1].num_channels = 1;
676         modes[1].num_rates = 1;
677         modes[1].channels = wpa_zalloc(sizeof(struct hostapd_channel_data));
678         modes[1].rates = wpa_zalloc(sizeof(struct hostapd_rate_data));
679         if (modes[1].channels == NULL || modes[1].rates == NULL) {
680                 hostapd_free_hw_features(modes, *num_modes);
681                 return NULL;
682         }
683         modes[1].channels[0].chan = 1;
684         modes[1].channels[0].freq = 2412;
685         modes[1].channels[0].flag = HOSTAPD_CHAN_W_SCAN |
686                 HOSTAPD_CHAN_W_ACTIVE_SCAN;
687         modes[1].rates[0].rate = 10;
688         modes[1].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
689                 HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY;
690
691         modes[2].mode = HOSTAPD_MODE_IEEE80211A;
692         modes[2].num_channels = 1;
693         modes[2].num_rates = 1;
694         modes[2].channels = wpa_zalloc(sizeof(struct hostapd_channel_data));
695         modes[2].rates = wpa_zalloc(sizeof(struct hostapd_rate_data));
696         if (modes[2].channels == NULL || modes[2].rates == NULL) {
697                 hostapd_free_hw_features(modes, *num_modes);
698                 return NULL;
699         }
700         modes[2].channels[0].chan = 60;
701         modes[2].channels[0].freq = 5300;
702         modes[2].channels[0].flag = HOSTAPD_CHAN_W_SCAN |
703                 HOSTAPD_CHAN_W_ACTIVE_SCAN;
704         modes[2].rates[0].rate = 60;
705         modes[2].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
706                 HOSTAPD_RATE_MANDATORY;
707
708         return modes;
709 }
710
711
712 static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid)
713 {
714         struct test_driver_data *drv = priv;
715         struct test_driver_bss *bss;
716
717         wpa_printf(MSG_DEBUG, "%s(ifname=%s bssid=" MACSTR ")",
718                    __func__, ifname, MAC2STR(bssid));
719
720         bss = wpa_zalloc(sizeof(*bss));
721         if (bss == NULL)
722                 return -1;
723
724         strncpy(bss->ifname, ifname, IFNAMSIZ);
725         memcpy(bss->bssid, bssid, ETH_ALEN);
726
727         bss->next = drv->bss;
728         drv->bss = bss;
729
730         return 0;
731 }
732
733
734 static int test_driver_bss_remove(void *priv, const char *ifname)
735 {
736         struct test_driver_data *drv = priv;
737         struct test_driver_bss *bss, *prev;
738         struct test_client_socket *cli, *prev_c;
739
740         wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname);
741
742         for (prev = NULL, bss = drv->bss; bss; prev = bss, bss = bss->next) {
743                 if (strcmp(bss->ifname, ifname) != 0)
744                         continue;
745
746                 if (prev)
747                         prev->next = bss->next;
748                 else
749                         drv->bss = bss->next;
750
751                 for (prev_c = NULL, cli = drv->cli; cli;
752                      prev_c = cli, cli = cli->next) {
753                         if (cli->bss != bss)
754                                 continue;
755                         if (prev_c)
756                                 prev_c->next = cli->next;
757                         else
758                                 drv->cli = cli->next;
759                         free(cli);
760                         break;
761                 }
762
763                 test_driver_free_bss(bss);
764                 return 0;
765         }
766
767         return -1;
768 }
769
770
771 static int test_driver_if_add(const char *iface, void *priv,
772                               enum hostapd_driver_if_type type, char *ifname,
773                               const u8 *addr)
774 {
775         wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)",
776                    __func__, iface, type, ifname);
777         return 0;
778 }
779
780
781 static int test_driver_if_update(void *priv, enum hostapd_driver_if_type type,
782                                  char *ifname, const u8 *addr)
783 {
784         wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname);
785         return 0;
786 }
787
788
789 static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type,
790                                  const char *ifname, const u8 *addr)
791 {
792         wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname);
793         return 0;
794 }
795
796
797 static int test_driver_valid_bss_mask(void *priv, const u8 *addr,
798                                       const u8 *mask)
799 {
800         return 0;
801 }
802
803
804 static int test_driver_set_ssid(const char *ifname, void *priv, const u8 *buf,
805                                 int len)
806 {
807         struct test_driver_data *drv = priv;
808         struct test_driver_bss *bss;
809
810         wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname);
811         wpa_hexdump_ascii(MSG_DEBUG, "test_driver_set_ssid: SSID", buf, len);
812
813         for (bss = drv->bss; bss; bss = bss->next) {
814                 if (strcmp(bss->ifname, ifname) != 0)
815                         continue;
816
817                 if (len < 0 || (size_t) len > sizeof(bss->ssid))
818                         return -1;
819
820                 memcpy(bss->ssid, buf, len);
821                 bss->ssid_len = len;
822
823                 return 0;
824         }
825
826         return -1;
827 }
828
829
830 static int test_driver_set_privacy(const char *ifname, void *priv, int enabled)
831 {
832         struct test_driver_data *drv = priv;
833         struct test_driver_bss *bss;
834
835         wpa_printf(MSG_DEBUG, "%s(ifname=%s enabled=%d)",
836                    __func__, ifname, enabled);
837
838         for (bss = drv->bss; bss; bss = bss->next) {
839                 if (strcmp(bss->ifname, ifname) != 0)
840                         continue;
841
842                 bss->privacy = enabled;
843
844                 return 0;
845         }
846
847         return -1;
848 }
849
850
851 static int test_driver_set_encryption(const char *iface, void *priv,
852                                       const char *alg, const u8 *addr, int idx,
853                                       const u8 *key, size_t key_len, int txkey)
854 {
855         wpa_printf(MSG_DEBUG, "%s(iface=%s alg=%s idx=%d txkey=%d)",
856                    __func__, iface, alg, idx, txkey);
857         if (addr)
858                 wpa_printf(MSG_DEBUG, "   addr=" MACSTR, MAC2STR(addr));
859         if (key)
860                 wpa_hexdump_key(MSG_DEBUG, "   key", key, key_len);
861         return 0;
862 }
863
864
865 static int test_driver_set_sta_vlan(void *priv, const u8 *addr,
866                                     const char *ifname, int vlan_id)
867 {
868         wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " ifname=%s vlan_id=%d)",
869                    __func__, MAC2STR(addr), ifname, vlan_id);
870         return 0;
871 }
872
873
874 static int test_driver_sta_add(const char *ifname, void *priv, const u8 *addr,
875                                u16 aid, u16 capability, u8 *supp_rates,
876                                size_t supp_rates_len, int flags)
877 {
878         struct test_driver_data *drv = priv;
879         struct test_client_socket *cli;
880         struct test_driver_bss *bss;
881
882         wpa_printf(MSG_DEBUG, "%s(ifname=%s addr=" MACSTR " aid=%d "
883                    "capability=0x%x flags=0x%x",
884                    __func__, ifname, MAC2STR(addr), aid, capability, flags);
885         wpa_hexdump(MSG_DEBUG, "test_driver_sta_add - supp_rates",
886                     supp_rates, supp_rates_len);
887
888         cli = drv->cli;
889         while (cli) {
890                 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
891                         break;
892                 cli = cli->next;
893         }
894         if (!cli) {
895                 wpa_printf(MSG_DEBUG, "%s: no matching client entry",
896                            __func__);
897                 return -1;
898         }
899
900         for (bss = drv->bss; bss; bss = bss->next) {
901                 if (strcmp(ifname, bss->ifname) == 0)
902                         break;
903         }
904         if (bss == NULL) {
905                 wpa_printf(MSG_DEBUG, "%s: No matching interface found from "
906                            "configured BSSes", __func__);
907                 return -1;
908         }
909
910         cli->bss = bss;
911
912         return 0;
913 }
914
915
916 static int test_driver_init(struct hostapd_data *hapd)
917 {
918         struct test_driver_data *drv;
919         struct sockaddr_un addr;
920
921         drv = wpa_zalloc(sizeof(struct test_driver_data));
922         if (drv == NULL) {
923                 printf("Could not allocate memory for test driver data\n");
924                 return -1;
925         }
926         drv->bss = wpa_zalloc(sizeof(*drv->bss));
927         if (drv->bss == NULL) {
928                 printf("Could not allocate memory for test driver BSS data\n");
929                 free(drv);
930                 return -1;
931         }
932
933         drv->ops = test_driver_ops;
934         drv->hapd = hapd;
935
936         /* Generate a MAC address to help testing with multiple APs */
937         hapd->own_addr[0] = 0x02; /* locally administered */
938         sha1_prf((const u8 *) hapd->conf->iface, strlen(hapd->conf->iface),
939                  "hostapd test bssid generation",
940                  (const u8 *) hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len,
941                  hapd->own_addr + 1, ETH_ALEN - 1);
942
943         strncpy(drv->bss->ifname, hapd->conf->iface, IFNAMSIZ);
944         memcpy(drv->bss->bssid, hapd->own_addr, ETH_ALEN);
945
946         if (hapd->conf->test_socket) {
947                 if (strlen(hapd->conf->test_socket) >= sizeof(addr.sun_path)) {
948                         printf("Too long test_socket path\n");
949                         test_driver_free_priv(drv);
950                         return -1;
951                 }
952                 if (strncmp(hapd->conf->test_socket, "DIR:", 4) == 0) {
953                         size_t len = strlen(hapd->conf->test_socket) + 30;
954                         drv->socket_dir = strdup(hapd->conf->test_socket + 4);
955                         drv->own_socket_path = malloc(len);
956                         if (drv->own_socket_path) {
957                                 snprintf(drv->own_socket_path, len,
958                                          "%s/AP-" MACSTR,
959                                          hapd->conf->test_socket + 4,
960                                          MAC2STR(hapd->own_addr));
961                         }
962                 } else {
963                         drv->own_socket_path = strdup(hapd->conf->test_socket);
964                 }
965                 if (drv->own_socket_path == NULL) {
966                         test_driver_free_priv(drv);
967                         return -1;
968                 }
969
970                 drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
971                 if (drv->test_socket < 0) {
972                         perror("socket(PF_UNIX)");
973                         test_driver_free_priv(drv);
974                         return -1;
975                 }
976
977                 memset(&addr, 0, sizeof(addr));
978                 addr.sun_family = AF_UNIX;
979                 strncpy(addr.sun_path, drv->own_socket_path,
980                         sizeof(addr.sun_path));
981                 if (bind(drv->test_socket, (struct sockaddr *) &addr,
982                          sizeof(addr)) < 0) {
983                         perror("bind(PF_UNIX)");
984                         close(drv->test_socket);
985                         unlink(drv->own_socket_path);
986                         test_driver_free_priv(drv);
987                         return -1;
988                 }
989                 eloop_register_read_sock(drv->test_socket,
990                                          test_driver_receive_unix, drv, NULL);
991         } else
992                 drv->test_socket = -1;
993
994         hapd->driver = &drv->ops;
995         return 0;
996 }
997
998
999 static void test_driver_deinit(void *priv)
1000 {
1001         struct test_driver_data *drv = priv;
1002         struct test_client_socket *cli, *prev;
1003
1004         cli = drv->cli;
1005         while (cli) {
1006                 prev = cli;
1007                 cli = cli->next;
1008                 free(prev);
1009         }
1010
1011         if (drv->test_socket >= 0) {
1012                 eloop_unregister_read_sock(drv->test_socket);
1013                 close(drv->test_socket);
1014                 unlink(drv->own_socket_path);
1015         }
1016
1017         drv->hapd->driver = NULL;
1018
1019         /* There should be only one BSS remaining at this point. */
1020         if (drv->bss == NULL)
1021                 wpa_printf(MSG_ERROR, "%s: drv->bss == NULL", __func__);
1022         else if (drv->bss->next)
1023                 wpa_printf(MSG_ERROR, "%s: drv->bss->next != NULL", __func__);
1024
1025         test_driver_free_priv(drv);
1026 }
1027
1028
1029 static const struct driver_ops test_driver_ops = {
1030         .name = "test",
1031         .init = test_driver_init,
1032         .deinit = test_driver_deinit,
1033         .send_eapol = test_driver_send_eapol,
1034         .send_mgmt_frame = test_driver_send_mgmt_frame,
1035         .set_generic_elem = test_driver_set_generic_elem,
1036         .sta_deauth = test_driver_sta_deauth,
1037         .sta_disassoc = test_driver_sta_disassoc,
1038         .get_hw_feature_data = test_driver_get_hw_feature_data,
1039         .bss_add = test_driver_bss_add,
1040         .bss_remove = test_driver_bss_remove,
1041         .if_add = test_driver_if_add,
1042         .if_update = test_driver_if_update,
1043         .if_remove = test_driver_if_remove,
1044         .valid_bss_mask = test_driver_valid_bss_mask,
1045         .set_ssid = test_driver_set_ssid,
1046         .set_privacy = test_driver_set_privacy,
1047         .set_encryption = test_driver_set_encryption,
1048         .set_sta_vlan = test_driver_set_sta_vlan,
1049         .sta_add = test_driver_sta_add,
1050 };
1051
1052
1053 void test_driver_register(void)
1054 {
1055         driver_register(test_driver_ops.name, &test_driver_ops);
1056 }