driver_prism54: Use os_zalloc instead of malloc to clear memory
[libeap.git] / src / drivers / driver_prism54.c
1 /*
2  * WPA Supplicant - driver interaction with Linux Prism54.org driver
3  * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2004, Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
5  * Copyright (c) 2004, Bell Kin <bell_kin@pek.com.tw>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * Alternatively, this software may be distributed under the terms of BSD
12  * license.
13  *
14  * See README and COPYING for more details.
15  */
16
17 #include "includes.h"
18 #include <sys/ioctl.h>
19
20 #include "wireless_copy.h"
21 #include "common.h"
22 #include "driver.h"
23 #include "driver_wext.h"
24 #include "driver_hostap.h"
25
26 #ifdef HOSTAPD
27
28 #include <net/if_arp.h>
29 #include <netpacket/packet.h>
30
31 #include "driver.h"
32 #include "eloop.h"
33 #include "prism54.h"
34 #include "radius/radius.h"
35 #include "../../hostapd/hostapd.h"
36 #include "../../hostapd/config.h"
37 #include "../../hostapd/ieee802_1x.h"
38 #include "../../hostapd/ieee802_11.h"
39 #include "../../hostapd/wpa.h"
40 #include "../../hostapd/sta_info.h"
41 #include "../../hostapd/accounting.h"
42
43
44 const int PIM_BUF_SIZE = 4096;
45
46 struct prism54_driver_data {
47         struct hostapd_data *hapd;
48         char iface[IFNAMSIZ + 1];
49         int sock; /* raw packet socket for 802.3 access */
50         int pim_sock; /* socket for pimfor packet */
51         char macs[2007][6];
52 };
53
54
55 static int mac_id_refresh(struct prism54_driver_data *data, int id, char *mac)
56 {
57         if (id < 0 || id > 2006) {
58                 return -1;
59         }
60         memcpy(&data->macs[id][0], mac, ETH_ALEN);
61         return 0;
62 }
63
64
65 static char * mac_id_get(struct prism54_driver_data *data, int id)
66 {
67         if (id < 0 || id > 2006) {
68                 return NULL;
69         }
70         return &data->macs[id][0];
71 }
72
73
74 /* wait for a specific pimfor, timeout in 10ms resolution */
75 /* pim_sock must be non-block to prevent dead lock from no response */
76 /* or same response type in series */
77 static int prism54_waitpim(void *priv, unsigned long oid, void *buf, int len,
78                            int timeout)
79 {
80         struct prism54_driver_data *drv = priv;
81         struct timeval tv, stv, ctv;
82         fd_set pfd;
83         int rlen;
84         pimdev_hdr *pkt;
85
86         pkt = malloc(8192);
87         if (pkt == NULL)
88                 return -1;
89
90         FD_ZERO(&pfd);
91         gettimeofday(&stv, NULL);
92         do {
93                 FD_SET(drv->pim_sock, &pfd);
94                 tv.tv_sec = 0;
95                 tv.tv_usec = 10000;
96                 if (select(drv->pim_sock + 1, &pfd, NULL, NULL, &tv)) {
97                         rlen = recv(drv->pim_sock, pkt, 8192, 0);
98                         if (rlen > 0) {
99                                 if (pkt->oid == htonl(oid)) {
100                                         if (rlen <= len) {
101                                                 if (buf != NULL) {
102                                                         memcpy(buf, pkt, rlen);
103                                                 }
104                                                 free(pkt);
105                                                 return rlen;
106                                         } else {
107                                                 printf("buffer too small\n");
108                                                 free(pkt);
109                                                 return -1;
110                                         }
111                                 } else {
112                                         gettimeofday(&ctv, NULL);
113                                         continue;
114                                 }
115                         }
116                 }
117                 gettimeofday(&ctv, NULL);
118         } while (((ctv.tv_sec - stv.tv_sec) * 100 +
119                   (ctv.tv_usec - stv.tv_usec) / 10000) > timeout);
120         free(pkt);
121         return 0;
122 }
123
124
125 /* send an eapol packet */
126 static int prism54_send_eapol(void *priv, const u8 *addr,
127                               const u8 *data, size_t data_len, int encrypt,
128                               const u8 *own_addr)
129 {
130         struct prism54_driver_data *drv = priv;
131         ieee802_3_hdr *hdr;
132         size_t len;
133         u8 *pos;
134         int res;
135
136         len = sizeof(*hdr) + data_len;
137         hdr = os_zalloc(len);
138         if (hdr == NULL) {
139                 printf("malloc() failed for prism54_send_data(len=%lu)\n",
140                        (unsigned long) len);
141                 return -1;
142         }
143
144         memcpy(&hdr->da[0], addr, ETH_ALEN);
145         memcpy(&hdr->sa[0], own_addr, ETH_ALEN);
146         hdr->type = htons(ETH_P_PAE);
147         pos = (u8 *) (hdr + 1);
148         memcpy(pos, data, data_len);
149
150         res = send(drv->sock, hdr, len, 0);
151         free(hdr);
152
153         if (res < 0) {
154                 perror("hostapd_send_eapol: send");
155                 printf("hostapd_send_eapol - packet len: %lu - failed\n",
156                        (unsigned long) len);
157         }
158
159         return res;
160 }
161
162
163 /* open data channel(auth-1) or eapol only(unauth-0) */
164 static int prism54_set_sta_authorized(void *priv, const u8 *addr,
165                                       int authorized)
166 {
167         struct prism54_driver_data *drv = priv;
168         pimdev_hdr *hdr;
169         char *pos;
170
171         hdr = os_zalloc(sizeof(*hdr) + ETH_ALEN);
172         if (hdr == NULL)
173                 return -1;
174         hdr->op = htonl(PIMOP_SET);
175         if (authorized) {
176                 hdr->oid = htonl(DOT11_OID_EAPAUTHSTA);
177         } else {
178                 hdr->oid = htonl(DOT11_OID_EAPUNAUTHSTA);
179         }
180         pos = (char *) (hdr + 1);
181         memcpy(pos, addr, ETH_ALEN);
182         send(drv->pim_sock, hdr, sizeof(*hdr) + ETH_ALEN, 0);
183         prism54_waitpim(priv, hdr->oid, hdr, sizeof(*hdr) + ETH_ALEN, 10);
184         free(hdr);
185         return 0;
186 }
187
188
189 static int
190 prism54_sta_set_flags(void *priv, const u8 *addr, int total_flags,
191                       int flags_or, int flags_and)
192 {
193         /* For now, only support setting Authorized flag */
194         if (flags_or & WLAN_STA_AUTHORIZED)
195                 return prism54_set_sta_authorized(priv, addr, 1);
196         if (flags_and & WLAN_STA_AUTHORIZED)
197                 return prism54_set_sta_authorized(priv, addr, 0);
198         return 0;
199 }
200
201
202 static int prism54_set_key(const char *ifname, void *priv, wpa_alg alg,
203                            const u8 *addr, int key_idx, int set_tx,
204                            const u8 *seq, size_t seq_len,
205                            const u8 *key, size_t key_len)
206 {
207         struct prism54_driver_data *drv = priv;
208         pimdev_hdr *hdr;
209         struct obj_stakey *keys;
210         u8 *buf;
211         size_t blen;
212         int ret = 0;
213
214         blen = sizeof(struct obj_stakey) + sizeof(pimdev_hdr);
215         hdr = os_zalloc(blen);
216         if (hdr == NULL) {
217                 printf("memory low\n");
218                 return -1;
219         }
220         keys = (struct obj_stakey *) &hdr[1];
221         if (!addr) {
222                 memset(&keys->address[0], 0xff, ETH_ALEN);
223         } else {
224                 memcpy(&keys->address[0], addr, ETH_ALEN);
225         }
226         switch (alg) {
227         case WPA_ALG_WEP:
228                 keys->type = DOT11_PRIV_WEP;
229                 break;
230         case WPA_ALG_TKIP:
231                 keys->type = DOT11_PRIV_TKIP;
232                 break;
233         case WPA_ALG_NONE:
234                 /* the only way to clear the key is to deauth it */
235                 /* and prism54 is capable to receive unencrypted packet */
236                 /* so we do nothing here */
237                 free(hdr);
238                 return 0;
239         default:
240                 printf("bad auth type: %d\n", alg);
241                 free(hdr);
242                 return -1;
243         }
244         buf = (u8 *) &keys->key[0];
245         keys->length = key_len;
246         keys->keyid = key_idx;
247         keys->options = htons(DOT11_STAKEY_OPTION_DEFAULTKEY);
248         keys->reserved = 0;
249
250         hdr->op = htonl(PIMOP_SET);
251         hdr->oid = htonl(DOT11_OID_STAKEY);
252
253         memcpy(buf, key, key_len);
254         
255         ret = send(drv->pim_sock, hdr, blen, 0);
256         if (ret < 0) {
257                 free(hdr);
258                 return ret;
259         }
260         prism54_waitpim(priv, hdr->oid, hdr, blen, 10);
261
262         free(hdr);
263
264         return 0;
265 }
266
267
268 /* get TKIP station sequence counter, prism54 is only 6 bytes */
269 static int prism54_get_seqnum(const char *ifname, void *priv, const u8 *addr,
270                               int idx, u8 *seq)
271 {
272         struct prism54_driver_data *drv = priv;
273         struct obj_stasc *stasc;
274         pimdev_hdr *hdr;
275         size_t blen;
276         int ret = 0;
277
278         blen = sizeof(*stasc) + sizeof(*hdr);
279         hdr = os_zalloc(blen);
280         if (hdr == NULL)
281                 return -1;
282
283         stasc = (struct obj_stasc *) &hdr[1];
284         
285         if (addr == NULL)
286                 memset(&stasc->address[0], 0xff, ETH_ALEN);
287         else
288                 memcpy(&stasc->address[0], addr, ETH_ALEN);
289
290         hdr->oid = htonl(DOT11_OID_STASC);
291         hdr->op = htonl(PIMOP_GET);
292         stasc->keyid = idx;
293         if (send(drv->pim_sock,hdr,blen,0) <= 0) {
294                 free(hdr);
295                 return -1;
296         }
297         if (prism54_waitpim(priv, DOT11_OID_STASC, hdr, blen, 10) <= 0) {
298                 ret = -1;
299         } else {
300                 if (hdr->op == (int) htonl(PIMOP_RESPONSE)) {
301                         memcpy(seq + 2, &stasc->sc_high, ETH_ALEN);
302                         memset(seq, 0, 2);
303                 } else {
304                         ret = -1;
305                 }
306         }
307         free(hdr);
308
309         return ret;
310 }
311
312
313 /* include unencrypted, set mlme autolevel to extended */
314 static int prism54_init_1x(void *priv)
315 {
316         struct prism54_driver_data *drv = priv;
317         pimdev_hdr *hdr;
318         unsigned long *ul;
319         int blen = sizeof(*hdr) + sizeof(*ul);
320
321         hdr = os_zalloc(blen);
322         if (hdr == NULL)
323                 return -1;
324
325         ul = (unsigned long *) &hdr[1];
326         hdr->op = htonl(PIMOP_SET);
327         hdr->oid = htonl(DOT11_OID_EXUNENCRYPTED);
328         *ul = htonl(DOT11_BOOL_TRUE); /* not accept */
329         send(drv->pim_sock, hdr, blen, 0);
330         prism54_waitpim(priv, DOT11_OID_EXUNENCRYPTED, hdr, blen, 10);
331         hdr->op = htonl(PIMOP_SET);
332         hdr->oid = htonl(DOT11_OID_MLMEAUTOLEVEL);
333         *ul = htonl(DOT11_MLME_EXTENDED);
334         send(drv->pim_sock, hdr, blen, 0);
335         prism54_waitpim(priv, DOT11_OID_MLMEAUTOLEVEL, hdr, blen, 10);
336         hdr->op = htonl(PIMOP_SET);
337         hdr->oid = htonl(DOT11_OID_DOT1XENABLE);
338         *ul = htonl(DOT11_BOOL_TRUE);
339         send(drv->pim_sock, hdr, blen, 0);
340         prism54_waitpim(priv, DOT11_OID_DOT1XENABLE, hdr, blen, 10);
341         hdr->op = htonl(PIMOP_SET);
342         hdr->oid = htonl(DOT11_OID_AUTHENABLE);
343         *ul = htonl(DOT11_AUTH_OS); /* OS */
344         send(drv->pim_sock, hdr, blen, 0);
345         prism54_waitpim(priv, DOT11_OID_AUTHENABLE, hdr, blen, 10);
346         free(hdr);
347         return 0;
348 }
349
350
351 static int prism54_set_privacy_invoked(const char *ifname, void *priv,
352                                        int flag)
353 {
354         struct prism54_driver_data *drv = priv;
355         pimdev_hdr *hdr;
356         unsigned long *ul;
357         int ret;
358         int blen = sizeof(*hdr) + sizeof(*ul);
359         hdr = os_zalloc(blen);
360         if (hdr == NULL)
361                 return -1;
362         ul = (unsigned long *) &hdr[1];
363         hdr->op = htonl(PIMOP_SET);
364         hdr->oid = htonl(DOT11_OID_PRIVACYINVOKED);
365         if (flag) {
366                 *ul = htonl(DOT11_BOOL_TRUE); /* has privacy */
367         } else {
368                 *ul = 0;
369         }
370         ret = send(drv->pim_sock, hdr, blen, 0);
371         if (ret >= 0) {
372                 ret = prism54_waitpim(priv, DOT11_OID_PRIVACYINVOKED, hdr,
373                                       blen, 10);
374         }
375         free(hdr);
376         return ret;
377 }
378
379  
380 static int prism54_ioctl_setiwessid(const char *ifname, void *priv,
381                                     const u8 *buf, int len)
382 {
383 #if 0
384         struct prism54_driver_data *drv = priv;
385         struct iwreq iwr;
386
387         memset(&iwr, 0, sizeof(iwr));
388         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
389         iwr.u.essid.flags = 1; /* SSID active */
390         iwr.u.essid.pointer = (caddr_t) buf;
391         iwr.u.essid.length = len + 1;
392
393         if (ioctl(drv->pim_sock, SIOCSIWESSID, &iwr) < 0) {
394                 perror("ioctl[SIOCSIWESSID]");
395                 printf("len=%d\n", len);
396                 return -1;
397         }
398 #endif
399         return 0;
400 }
401
402
403 /* kick all stations */
404 /* does not work during init, but at least it won't crash firmware */
405 static int prism54_flush(void *priv)
406 {
407         struct prism54_driver_data *drv = priv;
408         struct obj_mlmeex *mlme;
409         pimdev_hdr *hdr;
410         int ret;
411         unsigned int i;
412         long *nsta;
413         int blen = sizeof(*hdr) + sizeof(*mlme);
414         char *mac_id;
415
416         hdr = os_zalloc(blen);
417         if (hdr == NULL)
418                 return -1;
419
420         mlme = (struct obj_mlmeex *) &hdr[1];
421         nsta = (long *) &hdr[1];
422         hdr->op = htonl(PIMOP_GET);
423         hdr->oid = htonl(DOT11_OID_CLIENTS);
424         ret = send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(long), 0);
425         ret = prism54_waitpim(priv, DOT11_OID_CLIENTS, hdr, blen, 10);
426         if ((ret < 0) || (hdr->op != (int) htonl(PIMOP_RESPONSE)) ||
427             (le_to_host32(*nsta) > 2007)) {
428                 free(hdr);
429                 return 0;
430         }
431         for (i = 0; i < le_to_host32(*nsta); i++) {
432                 mlme->id = -1;
433                 mac_id = mac_id_get(drv, i);
434                 if (mac_id)
435                         memcpy(&mlme->address[0], mac_id, ETH_ALEN);
436                 mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED);
437                 mlme->state = htons(DOT11_STATE_NONE);
438                 mlme->size = 0;
439                 hdr->op = htonl(PIMOP_SET);
440                 hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
441                 ret = send(drv->pim_sock, hdr, blen, 0);
442                 prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen,
443                                 100);
444         }
445         for (i = 0; i < le_to_host32(*nsta); i++) {
446                 mlme->id = -1;
447                 mac_id = mac_id_get(drv, i);
448                 if (mac_id)
449                         memcpy(&mlme->address[0], mac_id, ETH_ALEN);
450                 mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED);
451                 mlme->state = htons(DOT11_STATE_NONE);
452                 mlme->size = 0;
453                 hdr->op = htonl(PIMOP_SET);
454                 hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
455                 ret = send(drv->pim_sock, hdr, blen, 0);
456                 prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen,
457                                 100);
458         }
459         free(hdr);
460         return 0;
461 }
462
463
464 static int prism54_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
465                               int reason)
466 {
467         struct prism54_driver_data *drv = priv;
468         pimdev_hdr *hdr;
469         struct obj_mlmeex *mlme;
470         int ret;
471         int blen = sizeof(*hdr) + sizeof(*mlme);
472         hdr = os_zalloc(blen);
473         if (hdr == NULL)
474                 return -1;
475         mlme = (struct obj_mlmeex *) &hdr[1];
476         hdr->op = htonl(PIMOP_SET);
477         hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
478         memcpy(&mlme->address[0], addr, ETH_ALEN);
479         mlme->id = -1;
480         mlme->state = htons(DOT11_STATE_NONE);
481         mlme->code = host_to_le16(reason);
482         mlme->size = 0;
483         ret = send(drv->pim_sock, hdr, blen, 0);
484         prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen, 10);
485         free(hdr);
486         return ret;
487 }
488
489
490 static int prism54_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
491                                 int reason)
492 {
493         struct prism54_driver_data *drv = priv;
494         pimdev_hdr *hdr;
495         struct obj_mlmeex *mlme;
496         int ret;
497         int blen = sizeof(*hdr) + sizeof(*mlme);
498         hdr = os_zalloc(blen);
499         if (hdr == NULL)
500                 return -1;
501         mlme = (struct obj_mlmeex *) &hdr[1];
502         hdr->op = htonl(PIMOP_SET);
503         hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
504         memcpy(&mlme->address[0], addr, ETH_ALEN);
505         mlme->id = -1;
506         mlme->state = htons(DOT11_STATE_NONE);
507         mlme->code = host_to_le16(reason);
508         mlme->size = 0;
509         ret = send(drv->pim_sock, hdr, blen, 0);
510         prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen, 10);
511         free(hdr);
512         return ret;
513 }
514
515
516 static int prism54_get_inact_sec(void *priv, const u8 *addr)
517 {
518         struct prism54_driver_data *drv = priv;
519         pimdev_hdr *hdr;
520         struct obj_sta *sta;
521         int blen = sizeof(*hdr) + sizeof(*sta);
522         int ret;
523
524         hdr = os_zalloc(blen);
525         if (hdr == NULL)
526                 return -1;
527         hdr->op = htonl(PIMOP_GET);
528         hdr->oid = htonl(DOT11_OID_CLIENTFIND);
529         sta = (struct obj_sta *) &hdr[1];
530         memcpy(&sta->address[0], addr, ETH_ALEN);
531         ret = send(drv->pim_sock, hdr, blen, 0);
532         ret = prism54_waitpim(priv, DOT11_OID_CLIENTFIND, hdr, blen, 10);
533         if (ret != blen) {
534                 printf("get_inact_sec: bad return %d\n", ret);
535                 free(hdr);
536                 return -1;
537         }
538         if (hdr->op != (int) htonl(PIMOP_RESPONSE)) {
539                 printf("get_inact_sec: bad resp\n");
540                 free(hdr);
541                 return -1;
542         }
543         free(hdr);
544         return le_to_host16(sta->age);
545 }
546
547
548 /* set attachments */
549 static int prism54_set_generic_elem(const char *ifname, void *priv,
550                                     const u8 *elem, size_t elem_len)
551 {
552         struct prism54_driver_data *drv = priv;
553         pimdev_hdr *hdr;
554         char *pos;
555         struct obj_attachment_hdr *attach;
556         size_t blen = sizeof(*hdr) + sizeof(*attach) + elem_len;
557         hdr = os_zalloc(blen);
558         if (hdr == NULL) {
559                 printf("%s: memory low\n", __func__);
560                 return -1;
561         }
562         hdr->op = htonl(PIMOP_SET);
563         hdr->oid = htonl(DOT11_OID_ATTACHMENT);
564         attach = (struct obj_attachment_hdr *)&hdr[1];
565         attach->type = DOT11_PKT_BEACON;
566         attach->id = -1;
567         attach->size = host_to_le16((short)elem_len);
568         pos = ((char*) attach) + sizeof(*attach);
569         if (elem)
570                 memcpy(pos, elem, elem_len);
571         send(drv->pim_sock, hdr, blen, 0);
572         attach->type = DOT11_PKT_PROBE_RESP;
573         send(drv->pim_sock, hdr, blen, 0);
574         free(hdr);
575         return 0;
576 }
577
578
579 /* tell the card to auth the sta */
580 static void prism54_handle_probe(struct prism54_driver_data *drv,
581                                  void *buf, size_t len)
582 {
583         struct obj_mlmeex *mlme;
584         pimdev_hdr *hdr;
585         struct sta_info *sta;
586         hdr = (pimdev_hdr *)buf;
587         mlme = (struct obj_mlmeex *) &hdr[1];
588         sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
589         if (sta != NULL) {
590                 if (sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC))
591                         return;
592         }
593         if (len < sizeof(*mlme)) {
594                 printf("bad probe packet\n");
595                 return;
596         }
597         mlme->state = htons(DOT11_STATE_AUTHING);
598         mlme->code = 0;
599         hdr->op = htonl(PIMOP_SET);
600         hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
601         mlme->size = 0;
602         send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
603 }
604
605
606 static void prism54_handle_deauth(struct prism54_driver_data *drv,
607                                   void *buf, size_t len)
608 {
609         struct obj_mlme *mlme;
610         pimdev_hdr *hdr;
611         struct sta_info *sta;
612         char *mac_id;
613
614         hdr = (pimdev_hdr *) buf;
615         mlme = (struct obj_mlme *) &hdr[1];
616         sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
617         mac_id = mac_id_get(drv, mlme->id);
618         if (sta == NULL || mac_id == NULL)
619                 return;
620         memcpy(&mlme->address[0], mac_id, ETH_ALEN);
621         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
622         wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
623         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
624         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
625         ap_free_sta(drv->hapd, sta);
626 }
627
628
629 static void prism54_handle_disassoc(struct prism54_driver_data *drv,
630                                     void *buf, size_t len)
631 {
632         struct obj_mlme *mlme;
633         pimdev_hdr *hdr;
634         struct sta_info *sta;
635         char *mac_id;
636
637         hdr = (pimdev_hdr *) buf;
638         mlme = (struct obj_mlme *) &hdr[1];
639         mac_id = mac_id_get(drv, mlme->id);
640         if (mac_id == NULL)
641                 return;
642         memcpy(&mlme->address[0], mac_id, ETH_ALEN);
643         sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
644         if (sta == NULL) {
645                 return;
646         }
647         sta->flags &= ~WLAN_STA_ASSOC;
648         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
649         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
650         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
651         accounting_sta_stop(drv->hapd, sta);
652         ieee802_1x_free_station(sta);
653 }
654
655
656 /* to auth it, just allow it now, later for os/sk */
657 static void prism54_handle_auth(struct prism54_driver_data *drv,
658                                 void *buf, size_t len)
659 {
660         struct obj_mlmeex *mlme;
661         pimdev_hdr *hdr;
662         struct sta_info *sta;
663         int resp;
664
665         hdr = (pimdev_hdr *) buf;
666         mlme = (struct obj_mlmeex *) &hdr[1];
667         if (len < sizeof(*mlme)) {
668                 printf("bad auth packet\n");
669                 return;
670         }
671
672         if (mlme->state == htons(DOT11_STATE_AUTHING)) {
673                 sta = ap_sta_add(drv->hapd, (u8 *) &mlme->address[0]);
674                 if (drv->hapd->tkip_countermeasures) {
675                         resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
676                         goto fail;
677                 }
678                 mac_id_refresh(drv, mlme->id, &mlme->address[0]);
679                 if (!sta) {
680                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
681                         goto fail;
682                 }
683                 sta->flags &= ~WLAN_STA_PREAUTH;
684                 
685                 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
686                 sta->flags |= WLAN_STA_AUTH;
687                 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
688                 mlme->code = 0;
689                 mlme->state=htons(DOT11_STATE_AUTH);
690                 hdr->op = htonl(PIMOP_SET);
691                 hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
692                 mlme->size = 0;
693                 sta->timeout_next = STA_NULLFUNC;
694                 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
695         }
696         return;
697
698 fail:
699         printf("auth fail: %x\n", resp);
700         mlme->code = host_to_le16(resp);
701         mlme->size = 0;
702         if (sta)
703                 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
704         hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
705         hdr->op = htonl(PIMOP_SET);
706         send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
707 }
708
709
710 /* do the wpa thing */
711 static void prism54_handle_assoc(struct prism54_driver_data *drv,
712                                  void *buf, size_t len)
713 {
714         pimdev_hdr *hdr;
715         struct obj_mlmeex *mlme;
716         struct ieee802_11_elems elems;
717         struct sta_info *sta;
718         u8 *wpa_ie;
719         u8 *cb;
720         int ieofs = 0;
721         size_t wpa_ie_len;
722         int resp, new_assoc;
723         char *mac_id;
724
725         resp = 0;
726         hdr = (pimdev_hdr *) buf;
727         mlme = (struct obj_mlmeex *) &hdr[1];
728         switch (ntohl(hdr->oid)) {
729                 case DOT11_OID_ASSOCIATE:
730                 case DOT11_OID_REASSOCIATE:
731                         mlme->size = 0;
732                 default:
733                         break;
734         }
735         if ((mlme->state == (int) htonl(DOT11_STATE_ASSOCING)) ||
736             (mlme->state == (int) htonl(DOT11_STATE_REASSOCING))) {
737                 if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) {
738                         printf("bad assoc packet\n");
739                         return;
740                 }
741                 mac_id = mac_id_get(drv, mlme->id);
742                 if (mac_id == NULL)
743                         return;
744                 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
745                 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
746                 if (sta == NULL) {
747                         printf("cannot get sta\n");
748                         return;
749                 }
750                 cb = (u8 *) &mlme->data[0];
751                 if (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) {
752                         ieofs = 4;
753                 } else if (hdr->oid == htonl(DOT11_OID_REASSOCIATEEX)) {
754                         ieofs = 10;
755                 }
756                 if (le_to_host16(mlme->size) <= ieofs) {
757                         printf("attach too small\n");
758                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
759                         goto fail;
760                 }
761                 if (ieee802_11_parse_elems(cb + ieofs,
762                                            le_to_host16(mlme->size) - ieofs,
763                                            &elems, 1) == ParseFailed) {
764                         printf("STA " MACSTR " sent invalid association "
765                                "request\n", MAC2STR(sta->addr));
766                         resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
767                         goto fail;
768                 }
769                 if ((drv->hapd->conf->wpa & WPA_PROTO_RSN) &&
770                     elems.rsn_ie) {
771                         wpa_ie = elems.rsn_ie;
772                         wpa_ie_len = elems.rsn_ie_len;
773                 } else if ((drv->hapd->conf->wpa & WPA_PROTO_WPA) &&
774                            elems.wpa_ie) {
775                         wpa_ie = elems.wpa_ie;
776                         wpa_ie_len = elems.wpa_ie_len;
777                 } else {
778                         wpa_ie = NULL;
779                         wpa_ie_len = 0;
780                 }
781                 if (drv->hapd->conf->wpa && wpa_ie == NULL) {
782                         printf("STA " MACSTR ": No WPA/RSN IE in association "
783                                "request\n", MAC2STR(sta->addr));
784                         resp = WLAN_STATUS_INVALID_IE;
785                         goto fail;
786                 }
787                 if (drv->hapd->conf->wpa) {
788                         int res;
789                         wpa_ie -= 2;
790                         wpa_ie_len += 2;
791                         if (sta->wpa_sm == NULL)
792                                 sta->wpa_sm = wpa_auth_sta_init(
793                                         drv->hapd->wpa_auth, sta->addr);
794                         if (sta->wpa_sm == NULL) {
795                                 printf("Failed to initialize WPA state "
796                                        "machine\n");
797                                 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
798                                 goto fail;
799                         }
800                         res = wpa_validate_wpa_ie(drv->hapd->wpa_auth,
801                                                   sta->wpa_sm,
802                                                   wpa_ie, wpa_ie_len,
803                                                   NULL, 0);
804                         if (res == WPA_INVALID_GROUP)
805                                 resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
806                         else if (res == WPA_INVALID_PAIRWISE)
807                                 resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
808                         else if (res == WPA_INVALID_AKMP)
809                                 resp = WLAN_STATUS_AKMP_NOT_VALID;
810                         else if (res == WPA_ALLOC_FAIL)
811                                 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
812                         else if (res != WPA_IE_OK)
813                                 resp = WLAN_STATUS_INVALID_IE;
814                         if (resp != WLAN_STATUS_SUCCESS)
815                                 goto fail;
816                 }
817                 hdr->oid = (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) ?
818                         htonl(DOT11_OID_ASSOCIATEEX) :
819                         htonl(DOT11_OID_REASSOCIATEEX);
820                 hdr->op = htonl(PIMOP_SET);
821                 mlme->code = 0;
822                 mlme->state = htons(DOT11_STATE_ASSOC);
823                 mlme->size = 0;
824                 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
825                 return;
826         } else if (mlme->state==htons(DOT11_STATE_ASSOC)) {
827                 if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) {
828                         printf("bad assoc packet\n");
829                         return;
830                 }
831                 mac_id = mac_id_get(drv, mlme->id);
832                 if (mac_id == NULL)
833                         return;
834                 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
835                 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
836                 if (sta == NULL) {
837                         printf("cannot get sta\n");
838                         return;
839                 }
840                 new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
841                 sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
842                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
843                 hostapd_new_assoc_sta(drv->hapd, sta, !new_assoc);
844                 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
845                 sta->timeout_next = STA_NULLFUNC;
846                 return;
847         }
848         return;
849
850 fail:
851         printf("Prism54: assoc fail: %x\n", resp);
852         mlme->code = host_to_le16(resp);
853         mlme->size = 0;
854         mlme->state = htons(DOT11_STATE_ASSOCING);
855         hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
856         hdr->op = htonl(PIMOP_SET);
857         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
858         send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
859 }
860
861
862 static void handle_pim(int sock, void *eloop_ctx, void *sock_ctx)
863 {
864         struct prism54_driver_data *drv = eloop_ctx;
865         int len;
866         pimdev_hdr *hdr;
867
868         hdr = malloc(PIM_BUF_SIZE);
869         if (hdr == NULL)
870                 return;
871         len = recv(sock, hdr, PIM_BUF_SIZE, 0);
872         if (len < 0) {
873                 perror("recv");
874                 free(hdr);
875                 return;
876         }
877         if (len < 8) {
878                 printf("handle_pim: too short (%d)\n", len);
879                 free(hdr);
880                 return;
881         }
882
883         if (hdr->op != (int) htonl(PIMOP_TRAP)) {
884                 free(hdr);
885                 return;
886         }
887         switch (ntohl(hdr->oid)) {
888                 case DOT11_OID_PROBE:
889                         prism54_handle_probe(drv, hdr, len);
890                         break;
891                 case DOT11_OID_DEAUTHENTICATEEX:
892                 case DOT11_OID_DEAUTHENTICATE:
893                         prism54_handle_deauth(drv, hdr, len);
894                         break;
895                 case DOT11_OID_DISASSOCIATEEX:
896                 case DOT11_OID_DISASSOCIATE:
897                         prism54_handle_disassoc(drv, hdr, len);
898                         break;
899                 case DOT11_OID_AUTHENTICATEEX:
900                 case DOT11_OID_AUTHENTICATE:
901                         prism54_handle_auth(drv, hdr, len);
902                         break;
903                 case DOT11_OID_ASSOCIATEEX:
904                 case DOT11_OID_REASSOCIATEEX:
905                 case DOT11_OID_ASSOCIATE:
906                 case DOT11_OID_REASSOCIATE:
907                         prism54_handle_assoc(drv, hdr, len);
908                 default:
909                         break;
910         }
911
912         free(hdr);
913 }
914
915
916 static void handle_802_3(int sock, void *eloop_ctx, void *sock_ctx)
917 {
918         struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
919         int len;
920         ieee802_3_hdr *hdr;
921
922         hdr = malloc(PIM_BUF_SIZE);
923         if (hdr == NULL)
924                 return;
925         len = recv(sock, hdr, PIM_BUF_SIZE, 0);
926         if (len < 0) {
927                 perror("recv");
928                 free(hdr);
929                 return;
930         }
931         if (len < 14) {
932                 wpa_printf(MSG_MSGDUMP, "handle_802_3: too short (%d)", len);
933                 free(hdr);
934                 return;
935         }
936         if (hdr->type == htons(ETH_P_PAE)) {
937                 hostapd_eapol_receive(hapd, (u8 *) &hdr->sa[0], (u8 *) &hdr[1],
938                                       len - sizeof(*hdr));
939         }
940         free(hdr);
941 }
942
943
944 static int prism54_init_sockets(struct prism54_driver_data *drv,
945                                 struct wpa_init_params *params)
946 {
947         struct ifreq ifr;
948         struct sockaddr_ll addr;
949
950         drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
951         if (drv->sock < 0) {
952                 perror("socket[PF_PACKET,SOCK_RAW]");
953                 return -1;
954         }
955
956         if (eloop_register_read_sock(drv->sock, handle_802_3, drv->hapd, NULL))
957         {
958                 printf("Could not register read socket\n");
959                 return -1;
960         }
961
962         memset(&ifr, 0, sizeof(ifr));
963         if (params->num_bridge && params->bridge[0]) {
964                 printf("opening bridge: %s\n", params->bridge[0]);
965                 os_strlcpy(ifr.ifr_name, params->bridge[0],
966                            sizeof(ifr.ifr_name));
967         } else {
968                 os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
969         }
970         if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
971                 perror("ioctl(SIOCGIFINDEX)");
972                 return -1;
973         }
974
975         memset(&addr, 0, sizeof(addr));
976         addr.sll_family = AF_PACKET;
977         addr.sll_ifindex = ifr.ifr_ifindex;
978         addr.sll_protocol = htons(ETH_P_PAE);
979         wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
980                    addr.sll_ifindex);
981
982         if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
983                 perror("bind");
984                 return -1;
985         }
986
987         memset(&ifr, 0, sizeof(ifr));
988         os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
989         if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
990                 perror("ioctl(SIOCGIFHWADDR)");
991                 return -1;
992         }
993
994         if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
995                 printf("Invalid HW-addr family 0x%04x\n",
996                        ifr.ifr_hwaddr.sa_family);
997                 return -1;
998         }
999         memcpy(params->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
1000
1001         drv->pim_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1002         if (drv->pim_sock < 0) {
1003                 perror("socket[PF_PACKET,SOCK_RAW]");
1004                 return -1;
1005         }
1006
1007         if (eloop_register_read_sock(drv->pim_sock, handle_pim, drv, NULL)) {
1008                 printf("Could not register read socket\n");
1009                 return -1;
1010         }
1011
1012         memset(&ifr, 0, sizeof(ifr));
1013         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
1014         if (ioctl(drv->pim_sock, SIOCGIFINDEX, &ifr) != 0) {
1015                 perror("ioctl(SIOCGIFINDEX)");
1016                 return -1;
1017         }
1018
1019         memset(&addr, 0, sizeof(addr));
1020         addr.sll_family = AF_PACKET;
1021         addr.sll_ifindex = ifr.ifr_ifindex;
1022         addr.sll_protocol = htons(ETH_P_ALL);
1023         wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
1024                    addr.sll_ifindex);
1025
1026         if (bind(drv->pim_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1027                 perror("bind");
1028                 return -1;
1029         }
1030
1031         return 0;
1032 }
1033
1034
1035 static void * prism54_driver_init(struct hostapd_data *hapd,
1036                                   struct wpa_init_params *params)
1037 {
1038         struct prism54_driver_data *drv;
1039
1040         drv = os_zalloc(sizeof(struct prism54_driver_data));
1041         if (drv == NULL) {
1042                 printf("Could not allocate memory for hostapd Prism54 driver "
1043                        "data\n");
1044                 return NULL;
1045         }
1046
1047         drv->hapd = hapd;
1048         drv->pim_sock = drv->sock = -1;
1049         memcpy(drv->iface, params->ifname, sizeof(drv->iface));
1050
1051         if (prism54_init_sockets(drv, params)) {
1052                 free(drv);
1053                 return NULL;
1054         }
1055         prism54_init_1x(drv);
1056         /* must clean previous elems */
1057         prism54_set_generic_elem(drv->iface, drv, NULL, 0);
1058
1059         return drv;
1060 }
1061
1062
1063 static void prism54_driver_deinit(void *priv)
1064 {
1065         struct prism54_driver_data *drv = priv;
1066
1067         if (drv->pim_sock >= 0)
1068                 close(drv->pim_sock);
1069
1070         if (drv->sock >= 0)
1071                 close(drv->sock);
1072         
1073         free(drv);
1074 }
1075
1076 #else /* HOSTAPD */
1077
1078 struct wpa_driver_prism54_data {
1079         void *wext; /* private data for driver_wext */
1080         void *ctx;
1081         char ifname[IFNAMSIZ + 1];
1082         int sock;
1083 };
1084
1085 #define PRISM54_SET_WPA                 SIOCIWFIRSTPRIV+12
1086 #define PRISM54_HOSTAPD                 SIOCIWFIRSTPRIV+25
1087 #define PRISM54_DROP_UNENCRYPTED        SIOCIWFIRSTPRIV+26
1088
1089 static void show_set_key_error(struct prism2_hostapd_param *);
1090
1091 static int hostapd_ioctl_prism54(struct wpa_driver_prism54_data *drv,
1092                                  struct prism2_hostapd_param *param,
1093                                  int len, int show_err)
1094 {
1095         struct iwreq iwr;
1096
1097         os_memset(&iwr, 0, sizeof(iwr));
1098         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1099         iwr.u.data.pointer = (caddr_t) param;
1100         iwr.u.data.length = len;
1101
1102         if (ioctl(drv->sock, PRISM54_HOSTAPD, &iwr) < 0) {
1103                 int ret = errno;
1104                 if (show_err) 
1105                         perror("ioctl[PRISM54_HOSTAPD]");
1106                 return ret;
1107         }
1108
1109         return 0;
1110 }
1111
1112
1113 static int wpa_driver_prism54_set_wpa_ie(struct wpa_driver_prism54_data *drv,
1114                                          const u8 *wpa_ie,
1115                                          size_t wpa_ie_len)
1116 {
1117         struct prism2_hostapd_param *param;
1118         int res;
1119         size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
1120         if (blen < sizeof(*param))
1121                 blen = sizeof(*param);
1122
1123         param = os_zalloc(blen);
1124         if (param == NULL)
1125                 return -1;
1126         
1127         param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
1128         param->u.generic_elem.len = wpa_ie_len;
1129         os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
1130         res = hostapd_ioctl_prism54(drv, param, blen, 1);
1131
1132         os_free(param);
1133
1134         return res;
1135 }
1136
1137
1138 /* This is called at wpa_supplicant daemon init time */
1139 static int wpa_driver_prism54_set_wpa(void *priv, int enabled)
1140 {
1141         struct wpa_driver_prism54_data *drv = priv;
1142         struct prism2_hostapd_param *param;
1143         int res;
1144         size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
1145         if (blen < sizeof(*param))
1146                 blen = sizeof(*param);
1147
1148         param = os_zalloc(blen);
1149         if (param == NULL)
1150                 return -1;
1151
1152         param->cmd = PRISM54_SET_WPA;
1153         param->u.generic_elem.len = 0;
1154         res = hostapd_ioctl_prism54(drv, param, blen, 1);
1155
1156         os_free(param);
1157
1158         return res;
1159 }
1160
1161
1162 static int wpa_driver_prism54_set_key(void *priv, wpa_alg alg,
1163                                       const u8 *addr, int key_idx, int set_tx,
1164                                       const u8 *seq, size_t seq_len,
1165                                       const u8 *key, size_t key_len)
1166 {
1167         struct wpa_driver_prism54_data *drv = priv;
1168         struct prism2_hostapd_param *param;
1169         u8 *buf;
1170         size_t blen;
1171         int ret = 0;
1172         char *alg_name;
1173
1174         switch (alg) {
1175         case WPA_ALG_NONE:
1176                 alg_name = "none";
1177                 return -1;
1178                 break;
1179         case WPA_ALG_WEP:
1180                 alg_name = "WEP";
1181                 return -1;
1182                 break;
1183         case WPA_ALG_TKIP:
1184                 alg_name = "TKIP";
1185                 break;
1186         case WPA_ALG_CCMP:
1187                 alg_name = "CCMP";
1188                 return -1;
1189                 break;
1190         default:
1191                 return -1;
1192         }
1193
1194         wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
1195                    "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
1196                    (unsigned long) seq_len, (unsigned long) key_len);
1197
1198         if (seq_len > 8)
1199                 return -2;
1200
1201         blen = sizeof(*param) + key_len;
1202         buf = os_zalloc(blen);
1203         if (buf == NULL)
1204                 return -1;
1205
1206         param = (struct prism2_hostapd_param *) buf;
1207         param->cmd = PRISM2_SET_ENCRYPTION;
1208         /* TODO: In theory, STA in client mode can use five keys; four default
1209          * keys for receiving (with keyidx 0..3) and one individual key for
1210          * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
1211          * keyidx 0 is reserved for this unicast use and default keys can only
1212          * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
1213          * This should be fine for more or less all cases, but for completeness
1214          * sake, the driver could be enhanced to support the missing key. */
1215 #if 0
1216         if (addr == NULL)
1217                 os_memset(param->sta_addr, 0xff, ETH_ALEN);
1218         else
1219                 os_memcpy(param->sta_addr, addr, ETH_ALEN);
1220 #else
1221         os_memset(param->sta_addr, 0xff, ETH_ALEN);
1222 #endif
1223         os_strlcpy((char *) param->u.crypt.alg, alg_name,
1224                    HOSTAP_CRYPT_ALG_NAME_LEN);
1225         param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
1226         param->u.crypt.idx = key_idx;
1227         os_memcpy(param->u.crypt.seq, seq, seq_len);
1228         param->u.crypt.key_len = key_len;
1229         os_memcpy((u8 *) (param + 1), key, key_len);
1230
1231         if (hostapd_ioctl_prism54(drv, param, blen, 1)) {
1232                 wpa_printf(MSG_WARNING, "Failed to set encryption.");
1233                 show_set_key_error(param);
1234                 ret = -1;
1235         }
1236         os_free(buf);
1237
1238         return ret;
1239 }
1240
1241
1242 static int wpa_driver_prism54_set_countermeasures(void *priv,
1243                                                  int enabled)
1244 {
1245         /* FIX */
1246         printf("wpa_driver_prism54_set_countermeasures - not yet "
1247                "implemented\n");
1248         return 0;
1249 }
1250
1251
1252 static int wpa_driver_prism54_set_drop_unencrypted(void *priv,
1253                                                   int enabled)
1254 {
1255         struct wpa_driver_prism54_data *drv = priv;
1256         struct prism2_hostapd_param *param;
1257         int res;
1258         size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
1259         if (blen < sizeof(*param))
1260                 blen = sizeof(*param);
1261
1262         param = os_zalloc(blen);
1263         if (param == NULL)
1264                 return -1;
1265
1266         param->cmd = PRISM54_DROP_UNENCRYPTED;
1267         param->u.generic_elem.len = 0;
1268         res = hostapd_ioctl_prism54(drv, param, blen, 1);
1269
1270         os_free(param);
1271
1272         return res;
1273 }
1274
1275
1276 static int wpa_driver_prism54_deauthenticate(void *priv, const u8 *addr,
1277                                              int reason_code)
1278 {
1279         /* FIX */
1280         printf("wpa_driver_prism54_deauthenticate - not yet implemented\n");
1281         return 0;
1282 }
1283
1284
1285 static int wpa_driver_prism54_disassociate(void *priv, const u8 *addr,
1286                                            int reason_code)
1287 {
1288         /* FIX */
1289         printf("wpa_driver_prism54_disassociate - not yet implemented\n");
1290         return 0;
1291 }
1292
1293
1294 static int
1295 wpa_driver_prism54_associate(void *priv,
1296                              struct wpa_driver_associate_params *params)
1297 {
1298         struct wpa_driver_prism54_data *drv = priv;
1299         int ret = 0;
1300
1301         if (wpa_driver_prism54_set_wpa_ie(drv, params->wpa_ie,
1302                                           params->wpa_ie_len) < 0)
1303                 ret = -1;
1304         if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
1305                 ret = -1;
1306         if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
1307                                      params->ssid_len) < 0)
1308                 ret = -1;
1309         if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
1310                 ret = -1;
1311
1312         return ret;
1313 }
1314
1315 static void show_set_key_error(struct prism2_hostapd_param *param)
1316 {
1317         switch (param->u.crypt.err) {
1318         case HOSTAP_CRYPT_ERR_UNKNOWN_ALG:
1319                 wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
1320                            param->u.crypt.alg);
1321                 wpa_printf(MSG_INFO, "You may need to load kernel module to "
1322                            "register that algorithm.");
1323                 wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for "
1324                            "WEP.");
1325                 break;
1326         case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR:
1327                 wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
1328                            MAC2STR(param->sta_addr));
1329                 break;
1330         case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED:
1331                 wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
1332                 break;
1333         case HOSTAP_CRYPT_ERR_KEY_SET_FAILED:
1334                 wpa_printf(MSG_INFO, "Key setting failed.");
1335                 break;
1336         case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED:
1337                 wpa_printf(MSG_INFO, "TX key index setting failed.");
1338                 break;
1339         case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED:
1340                 wpa_printf(MSG_INFO, "Card configuration failed.");
1341                 break;
1342         }
1343 }
1344
1345
1346 static int wpa_driver_prism54_get_bssid(void *priv, u8 *bssid)
1347 {
1348         struct wpa_driver_prism54_data *drv = priv;
1349         return wpa_driver_wext_get_bssid(drv->wext, bssid);
1350 }
1351
1352
1353 static int wpa_driver_prism54_get_ssid(void *priv, u8 *ssid)
1354 {
1355         struct wpa_driver_prism54_data *drv = priv;
1356         return wpa_driver_wext_get_ssid(drv->wext, ssid);
1357 }
1358
1359
1360 static int wpa_driver_prism54_scan(void *priv, const u8 *ssid, size_t ssid_len)
1361 {
1362         struct wpa_driver_prism54_data *drv = priv;
1363         return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
1364 }
1365
1366
1367 static struct wpa_scan_results *
1368 wpa_driver_prism54_get_scan_results(void *priv)
1369 {
1370         struct wpa_driver_prism54_data *drv = priv;
1371         return wpa_driver_wext_get_scan_results(drv->wext);
1372 }
1373
1374
1375 static int wpa_driver_prism54_set_operstate(void *priv, int state)
1376 {
1377         struct wpa_driver_prism54_data *drv = priv;
1378         return wpa_driver_wext_set_operstate(drv->wext, state);
1379 }
1380
1381
1382 static void * wpa_driver_prism54_init(void *ctx, const char *ifname)
1383 {
1384         struct wpa_driver_prism54_data *drv;
1385
1386         drv = os_zalloc(sizeof(*drv));
1387         if (drv == NULL)
1388                 return NULL;
1389         drv->wext = wpa_driver_wext_init(ctx, ifname);
1390         if (drv->wext == NULL) {
1391                 os_free(drv);
1392                 return NULL;
1393         }
1394
1395         drv->ctx = ctx;
1396         os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
1397         drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
1398         if (drv->sock < 0) {
1399                 wpa_driver_wext_deinit(drv->wext);
1400                 os_free(drv);
1401                 return NULL;
1402         }
1403
1404         return drv;
1405 }
1406
1407
1408 static void wpa_driver_prism54_deinit(void *priv)
1409 {
1410         struct wpa_driver_prism54_data *drv = priv;
1411         wpa_driver_wext_deinit(drv->wext);
1412         close(drv->sock);
1413         os_free(drv);
1414 }
1415
1416 #endif /* HOSTAPD */
1417
1418
1419 const struct wpa_driver_ops wpa_driver_prism54_ops = {
1420         .name = "prism54",
1421         .desc = "Prism54.org driver (Intersil Prism GT/Duette/Indigo)",
1422 #ifdef HOSTAPD
1423         .hapd_init = prism54_driver_init,
1424         .hapd_deinit = prism54_driver_deinit,
1425         /* .set_ieee8021x = prism54_init_1x, */
1426         .set_privacy = prism54_set_privacy_invoked,
1427         .hapd_set_key = prism54_set_key,
1428         .get_seqnum = prism54_get_seqnum,
1429         .flush = prism54_flush,
1430         .set_generic_elem = prism54_set_generic_elem,
1431         .hapd_send_eapol = prism54_send_eapol,
1432         .sta_set_flags = prism54_sta_set_flags,
1433         .sta_deauth = prism54_sta_deauth,
1434         .sta_disassoc = prism54_sta_disassoc,
1435         .hapd_set_ssid = prism54_ioctl_setiwessid,
1436         .get_inact_sec = prism54_get_inact_sec,
1437 #else /* HOSTAPD */
1438         .get_bssid = wpa_driver_prism54_get_bssid,
1439         .get_ssid = wpa_driver_prism54_get_ssid,
1440         .set_wpa = wpa_driver_prism54_set_wpa,
1441         .set_key = wpa_driver_prism54_set_key,
1442         .set_countermeasures = wpa_driver_prism54_set_countermeasures,
1443         .set_drop_unencrypted = wpa_driver_prism54_set_drop_unencrypted,
1444         .scan = wpa_driver_prism54_scan,
1445         .get_scan_results2 = wpa_driver_prism54_get_scan_results,
1446         .deauthenticate = wpa_driver_prism54_deauthenticate,
1447         .disassociate = wpa_driver_prism54_disassociate,
1448         .associate = wpa_driver_prism54_associate,
1449         .init = wpa_driver_prism54_init,
1450         .deinit = wpa_driver_prism54_deinit,
1451         .set_operstate = wpa_driver_prism54_set_operstate,
1452 #endif /* HOSTAPD */
1453 };