Merge branch 'vendor/LDNS'
[dragonfly.git] / contrib / hostapd / src / drivers / driver_ralink.c
1 /*
2  * WPA Supplicant - driver interaction with Ralink Wireless Client
3  * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2007, Snowpin Lee <snowpin_lee@ralinktech.com.tw>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Alternatively, this software may be distributed under the terms of BSD
11  * license.
12  *
13  * See README and COPYING for more details.
14  *
15  */
16
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 "l2_packet/l2_packet.h"
24 #include "eloop.h"
25 #include "ieee802_11_defs.h"
26 #include "priv_netlink.h"
27 #include "driver_ralink.h"
28
29 static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx);
30
31 #define MAX_SSID_LEN 32
32
33 struct wpa_driver_ralink_data {
34         void *ctx;
35         int ioctl_sock;
36         int event_sock;
37         char ifname[IFNAMSIZ + 1];
38         u8 *assoc_req_ies;
39         size_t assoc_req_ies_len;
40         u8 *assoc_resp_ies;
41         size_t assoc_resp_ies_len;
42         int no_of_pmkid;
43         struct ndis_pmkid_entry *pmkid;
44         int we_version_compiled;
45         int ap_scan;
46         int scanning_done;
47         u8 g_driver_down;
48 };
49
50 static int ralink_set_oid(struct wpa_driver_ralink_data *drv,
51                           unsigned short oid, char *data, int len)
52 {
53         char *buf;
54         struct iwreq iwr;
55
56         buf = os_zalloc(len);
57         if (buf == NULL)
58                 return -1;
59         os_memset(&iwr, 0, sizeof(iwr));
60         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
61         iwr.u.data.flags = oid;
62         iwr.u.data.flags |= OID_GET_SET_TOGGLE;
63
64         if (data)
65                 os_memcpy(buf, data, len);
66
67         iwr.u.data.pointer = (caddr_t) buf;
68         iwr.u.data.length = len;
69
70         if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
71                 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
72                            __func__, oid, len);
73                 os_free(buf);
74                 return -1;
75         }
76         os_free(buf);
77         return 0;
78 }
79
80 static int
81 ralink_get_new_driver_flag(struct wpa_driver_ralink_data *drv)
82 {
83         struct iwreq iwr;
84         UCHAR enabled = 0;
85
86         os_memset(&iwr, 0, sizeof(iwr));
87         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
88         iwr.u.data.pointer = (UCHAR*) &enabled;
89         iwr.u.data.flags = RT_OID_NEW_DRIVER;
90
91         if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
92                 wpa_printf(MSG_DEBUG, "%s: failed", __func__);
93                 return 0;
94         }
95
96         return (enabled == 1) ? 1 : 0;
97 }
98
99 static int wpa_driver_ralink_get_bssid(void *priv, u8 *bssid)
100 {
101         struct wpa_driver_ralink_data *drv = priv;
102         struct iwreq iwr;
103         int ret = 0;
104
105         if (drv->g_driver_down == 1)
106                 return -1;
107
108         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
109
110         os_memset(&iwr, 0, sizeof(iwr));
111         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
112
113         if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
114                 perror("ioctl[SIOCGIWAP]");
115                 ret = -1;
116         }
117         os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
118
119         return ret;
120 }
121
122 static int wpa_driver_ralink_get_ssid(void *priv, u8 *ssid)
123 {
124         struct wpa_driver_ralink_data *drv = priv;
125 #if 0
126         struct wpa_supplicant *wpa_s = drv->ctx;
127         struct wpa_ssid *entry;
128 #endif
129         int ssid_len;
130         u8 bssid[ETH_ALEN];
131         u8 ssid_str[MAX_SSID_LEN];
132         struct iwreq iwr;
133 #if 0
134         int result = 0;
135 #endif
136         int ret = 0;
137 #if 0
138         BOOLEAN ieee8021x_mode = FALSE;
139         BOOLEAN ieee8021x_required_key = FALSE;
140 #endif
141
142         if (drv->g_driver_down == 1)
143                 return -1;
144
145         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
146
147         os_memset(&iwr, 0, sizeof(iwr));
148         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
149         iwr.u.essid.pointer = (caddr_t) ssid;
150         iwr.u.essid.length = 32;
151
152         if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
153                 perror("ioctl[SIOCGIWESSID]");
154                 ret = -1;
155         } else
156                 ret = iwr.u.essid.length;
157
158         if (ret <= 0)
159                 return ret;
160
161         ssid_len = ret;
162         os_memset(ssid_str, 0, MAX_SSID_LEN);
163         os_memcpy(ssid_str, ssid, ssid_len);
164
165         if (drv->ap_scan == 0) {
166                 /* Read BSSID form driver */
167                 if (wpa_driver_ralink_get_bssid(priv, bssid) < 0) {
168                         wpa_printf(MSG_WARNING, "Could not read BSSID from "
169                                    "driver.");
170                         return ret;
171                 }
172
173 #if 0
174                 entry = wpa_s->conf->ssid;
175                 while (entry) {
176                         if (!entry->disabled && ssid_len == entry->ssid_len &&
177                             os_memcmp(ssid_str, entry->ssid, ssid_len) == 0 &&
178                             (!entry->bssid_set ||
179                              os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) {
180                                 /* match the config of driver */
181                                 result = 1;
182                                 break;
183                         }
184                         entry = entry->next;
185                 }
186
187                 if (result) {
188                         wpa_printf(MSG_DEBUG, "Ready to set 802.1x mode and "
189                                    "ieee_required_keys parameters to driver");
190
191                         /* set 802.1x mode and ieee_required_keys parameter */
192                         if (entry->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
193                                 if ((entry->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST)))
194                                                 ieee8021x_required_key = TRUE;
195                                 ieee8021x_mode = TRUE;
196                         }
197
198                         if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, (char *) &ieee8021x_mode, sizeof(BOOLEAN)) < 0)
199                         {
200                                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set OID_802_11_SET_IEEE8021X(%d)", (int) ieee8021x_mode);
201                         }
202                         else
203                         {
204                                 wpa_printf(MSG_DEBUG, "ieee8021x_mode is %s", ieee8021x_mode ? "TRUE" : "FALSE");
205                         }
206
207                         if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0)
208                         {
209                                 wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", (int) ieee8021x_required_key);
210                         }
211                         else
212                         {
213                                 wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d)", ieee8021x_required_key ? "TRUE" : "FALSE",
214                                                                                                                                                                                                 entry->eapol_flags);
215                         }
216                 }
217 #endif
218         }
219
220         return ret;
221 }
222
223 static int wpa_driver_ralink_set_ssid(struct wpa_driver_ralink_data *drv,
224                                       const u8 *ssid, size_t ssid_len)
225 {
226         NDIS_802_11_SSID *buf;
227         int ret = 0;
228         struct iwreq iwr;
229
230         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
231
232         buf = os_zalloc(sizeof(NDIS_802_11_SSID));
233         if (buf == NULL)
234                 return -1;
235         os_memset(buf, 0, sizeof(*buf));
236         buf->SsidLength = ssid_len;
237         os_memcpy(buf->Ssid, ssid, ssid_len);
238         os_memset(&iwr, 0, sizeof(iwr));
239         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
240
241         iwr.u.data.flags = OID_802_11_SSID;
242         iwr.u.data.flags |= OID_GET_SET_TOGGLE;
243         iwr.u.data.pointer = (caddr_t) buf;
244         iwr.u.data.length = sizeof(NDIS_802_11_SSID);
245
246         if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
247                 perror("ioctl[RT_PRIV_IOCTL] -- OID_802_11_SSID");
248                 ret = -1;
249         }
250         os_free(buf);
251         return ret;
252 }
253
254 static void wpa_driver_ralink_event_pmkid(struct wpa_driver_ralink_data *drv,
255                                           const u8 *data, size_t data_len)
256 {
257         NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
258         size_t i;
259         union wpa_event_data event;
260
261         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
262
263         if (data_len < 8) {
264                 wpa_printf(MSG_DEBUG, "RALINK: Too short PMKID Candidate List "
265                            "Event (len=%lu)", (unsigned long) data_len);
266                 return;
267         }
268         pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
269         wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List Event - Version %d"
270                    " NumCandidates %d",
271                    (int) pmkid->Version, (int) pmkid->NumCandidates);
272
273         if (pmkid->Version != 1) {
274                 wpa_printf(MSG_DEBUG, "RALINK: Unsupported PMKID Candidate "
275                            "List Version %d", (int) pmkid->Version);
276                 return;
277         }
278
279         if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
280                 wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List "
281                            "underflow");
282
283                 return;
284         }
285
286
287
288         os_memset(&event, 0, sizeof(event));
289         for (i = 0; i < pmkid->NumCandidates; i++) {
290                 PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
291                 wpa_printf(MSG_DEBUG, "RALINK: %lu: " MACSTR " Flags 0x%x",
292                            (unsigned long) i, MAC2STR(p->BSSID),
293                            (int) p->Flags);
294                 os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
295                 event.pmkid_candidate.index = i;
296                 event.pmkid_candidate.preauth =
297                         p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
298                 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
299                                      &event);
300         }
301 }
302
303 static int wpa_driver_ralink_set_pmkid(struct wpa_driver_ralink_data *drv)
304 {
305         int len, count, i, ret;
306         struct ndis_pmkid_entry *entry;
307         NDIS_802_11_PMKID *p;
308
309         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
310
311         count = 0;
312         entry = drv->pmkid;
313         while (entry) {
314                 count++;
315                 if (count >= drv->no_of_pmkid)
316                         break;
317                 entry = entry->next;
318         }
319         len = 8 + count * sizeof(BSSID_INFO);
320         p = os_zalloc(len);
321         if (p == NULL)
322                 return -1;
323         p->Length = len;
324         p->BSSIDInfoCount = count;
325         entry = drv->pmkid;
326         for (i = 0; i < count; i++) {
327                 os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
328                 os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
329                 entry = entry->next;
330         }
331         wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID",
332                     (const u8 *) p, len);
333         ret = ralink_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
334         os_free(p);
335         return ret;
336 }
337
338 static int wpa_driver_ralink_add_pmkid(void *priv, const u8 *bssid,
339                                        const u8 *pmkid)
340 {
341         struct wpa_driver_ralink_data *drv = priv;
342         struct ndis_pmkid_entry *entry, *prev;
343
344         if (drv->g_driver_down == 1)
345                 return -1;
346
347         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
348
349         if (drv->no_of_pmkid == 0)
350                 return 0;
351
352         prev = NULL;
353         entry = drv->pmkid;
354         while (entry) {
355                 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
356                         break;
357                 prev = entry;
358                 entry = entry->next;
359         }
360
361         if (entry) {
362                 /* Replace existing entry for this BSSID and move it into the
363                  * beginning of the list. */
364                 os_memcpy(entry->pmkid, pmkid, 16);
365                 if (prev) {
366                         prev->next = entry->next;
367                         entry->next = drv->pmkid;
368                         drv->pmkid = entry;
369                 }
370         } else {
371                 entry = os_malloc(sizeof(*entry));
372                 if (entry) {
373                         os_memcpy(entry->bssid, bssid, ETH_ALEN);
374                         os_memcpy(entry->pmkid, pmkid, 16);
375                         entry->next = drv->pmkid;
376                         drv->pmkid = entry;
377                 }
378         }
379
380         return wpa_driver_ralink_set_pmkid(drv);
381 }
382
383
384 static int wpa_driver_ralink_remove_pmkid(void *priv, const u8 *bssid,
385                                           const u8 *pmkid)
386 {
387         struct wpa_driver_ralink_data *drv = priv;
388         struct ndis_pmkid_entry *entry, *prev;
389
390         if (drv->g_driver_down == 1)
391                 return -1;
392
393         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
394
395         if (drv->no_of_pmkid == 0)
396                 return 0;
397
398         entry = drv->pmkid;
399         prev = NULL;
400         drv->pmkid = NULL;
401         while (entry) {
402                 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
403                     os_memcmp(entry->pmkid, pmkid, 16) == 0) {
404                         if (prev)
405                                 prev->next = entry->next;
406                         else
407                                 drv->pmkid = entry->next;
408                         os_free(entry);
409                         break;
410                 }
411                 prev = entry;
412                 entry = entry->next;
413         }
414         return wpa_driver_ralink_set_pmkid(drv);
415 }
416
417
418 static int wpa_driver_ralink_flush_pmkid(void *priv)
419 {
420         struct wpa_driver_ralink_data *drv = priv;
421         NDIS_802_11_PMKID p;
422         struct ndis_pmkid_entry *pmkid, *prev;
423
424         if (drv->g_driver_down == 1)
425                 return -1;
426
427         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
428
429         if (drv->no_of_pmkid == 0)
430                 return 0;
431
432         pmkid = drv->pmkid;
433         drv->pmkid = NULL;
434         while (pmkid) {
435                 prev = pmkid;
436                 pmkid = pmkid->next;
437                 os_free(prev);
438         }
439
440         os_memset(&p, 0, sizeof(p));
441         p.Length = 8;
442         p.BSSIDInfoCount = 0;
443         wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
444                     (const u8 *) &p, 8);
445         return ralink_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
446 }
447
448 static void
449 wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv,
450                                         void *ctx, char *custom)
451 {
452         union wpa_event_data data;
453
454         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
455
456         wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
457
458         os_memset(&data, 0, sizeof(data));
459         /* Host AP driver */
460         if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
461                 /* receive a MICFAILURE report */
462                 data.michael_mic_failure.unicast =
463                         os_strstr(custom, " unicast") != NULL;
464                 /* TODO: parse parameters(?) */
465                 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
466         } else if (os_strncmp(custom, "ASSOCINFO_ReqIEs=", 17) == 0) {
467                 /* receive assoc. req. IEs */
468                 char *spos;
469                 int bytes;
470
471                 spos = custom + 17;
472                 /*get IE's length */
473                 /*
474                  * bytes = strlen(spos); ==> bug, bytes may less than original
475                  * size by using this way to get size. snowpin 20070312
476                  * if (!bytes)
477                  *      return;
478                  */
479                 bytes = drv->assoc_req_ies_len;
480
481                 data.assoc_info.req_ies = os_malloc(bytes);
482                 if (data.assoc_info.req_ies == NULL)
483                         return;
484
485                 data.assoc_info.req_ies_len = bytes;
486                 os_memcpy(data.assoc_info.req_ies, spos, bytes);
487
488                 /* skip the '\0' byte */
489                 spos += bytes + 1;
490
491                 data.assoc_info.resp_ies = NULL;
492                 data.assoc_info.resp_ies_len = 0;
493
494                 if (os_strncmp(spos, " RespIEs=", 9) == 0) {
495                         /* receive assoc. resp. IEs */
496                         spos += 9;
497                         /* get IE's length */
498                         bytes = os_strlen(spos);
499                         if (!bytes)
500                                 goto done;
501
502
503                         data.assoc_info.resp_ies = os_malloc(bytes);
504                         if (data.assoc_info.resp_ies == NULL)
505                                 goto done;
506
507                         data.assoc_info.resp_ies_len = bytes;
508                         os_memcpy(data.assoc_info.resp_ies, spos, bytes);
509                 }
510
511                 wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
512
513                 /* free allocated memory */
514         done:
515                 os_free(data.assoc_info.resp_ies);
516                 os_free(data.assoc_info.req_ies);
517         }
518 }
519
520 static void
521 wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv,
522                                  void *ctx, char *data, int len)
523 {
524         struct iw_event iwe_buf, *iwe = &iwe_buf;
525         char *pos, *end, *custom, *buf, *assoc_info_buf, *info_pos;
526 #if 0
527         BOOLEAN ieee8021x_required_key = FALSE;
528 #endif
529
530         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
531
532         assoc_info_buf = info_pos = NULL;
533         pos = data;
534         end = data + len;
535
536         while (pos + IW_EV_LCP_LEN <= end) {
537                 /* Event data may be unaligned, so make a local, aligned copy
538                  * before processing. */
539                 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
540                 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
541                            iwe->cmd, iwe->len);
542                 if (iwe->len <= IW_EV_LCP_LEN)
543                         return;
544
545                 custom = pos + IW_EV_POINT_LEN;
546
547                 if (drv->we_version_compiled > 18 && iwe->cmd == IWEVCUSTOM) {
548                         /* WE-19 removed the pointer from struct iw_point */
549                         char *dpos = (char *) &iwe_buf.u.data.length;
550                         int dlen = dpos - (char *) &iwe_buf;
551                         os_memcpy(dpos, pos + IW_EV_LCP_LEN,
552                                   sizeof(struct iw_event) - dlen);
553                 } else {
554                         os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
555                         custom += IW_EV_POINT_OFF;
556                 }
557
558                 switch (iwe->cmd) {
559                 case IWEVCUSTOM:
560                         if (custom + iwe->u.data.length > end)
561                                 return;
562                         buf = os_malloc(iwe->u.data.length + 1);
563                         if (buf == NULL)
564                                 return;
565                         os_memcpy(buf, custom, iwe->u.data.length);
566                         buf[iwe->u.data.length] = '\0';
567
568                         if (drv->ap_scan == 1) {
569                                 if ((iwe->u.data.flags == RT_ASSOC_EVENT_FLAG)
570                                     || (iwe->u.data.flags ==
571                                         RT_REQIE_EVENT_FLAG) ||
572                                     (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG)
573                                     || (iwe->u.data.flags ==
574                                         RT_ASSOCINFO_EVENT_FLAG)) {
575                                         if (drv->scanning_done == 0) {
576                                                 os_free(buf);
577                                                 return;
578                                         }
579                                 }
580                         }
581
582                         if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) {
583                                 wpa_printf(MSG_DEBUG, "Custom wireless event: "
584                                            "receive ASSOCIATED_EVENT !!!");
585                                 /* determine whether the dynamic-WEP is used or
586                                  * not */
587 #if 0
588                                 if (wpa_s && wpa_s->current_ssid &&
589                                     wpa_s->current_ssid->key_mgmt ==
590                                     WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
591                                         if ((wpa_s->current_ssid->eapol_flags &
592                                              (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) {
593                                                 //wpa_printf(MSG_DEBUG, "The current ssid - (%s), eapol_flag = %d.\n",
594                                                 //       wpa_ssid_txt(wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid_len),wpa_s->current_ssid->eapol_flags);
595                                                 ieee8021x_required_key = TRUE;
596                                         }
597
598                                         if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0)
599                                         {
600                                                 wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)",
601                                                            (int) ieee8021x_required_key);
602                                         }
603
604                                         wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d).\n", ieee8021x_required_key ? "TRUE" : "FALSE",
605                                                                                                                                                                                                 wpa_s->current_ssid->eapol_flags);
606                                 }
607 #endif
608
609                                 wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
610                         } else if (iwe->u.data.flags == RT_REQIE_EVENT_FLAG) {
611                                 wpa_printf(MSG_DEBUG, "Custom wireless event: "
612                                            "receive ReqIEs !!!");
613                                 drv->assoc_req_ies =
614                                         os_malloc(iwe->u.data.length);
615                                 if (drv->assoc_req_ies == NULL) {
616                                         os_free(buf);
617                                         return;
618                                 }
619
620                                 drv->assoc_req_ies_len = iwe->u.data.length;
621                                 os_memcpy(drv->assoc_req_ies, custom,
622                                           iwe->u.data.length);
623                         } else if (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) {
624                                 wpa_printf(MSG_DEBUG, "Custom wireless event: "
625                                            "receive RespIEs !!!");
626                                 drv->assoc_resp_ies =
627                                         os_malloc(iwe->u.data.length);
628                                 if (drv->assoc_resp_ies == NULL) {
629                                         os_free(drv->assoc_req_ies);
630                                         drv->assoc_req_ies = NULL;
631                                         os_free(buf);
632                                         return;
633                                 }
634
635                                 drv->assoc_resp_ies_len = iwe->u.data.length;
636                                 os_memcpy(drv->assoc_resp_ies, custom,
637                                           iwe->u.data.length);
638                         } else if (iwe->u.data.flags ==
639                                    RT_ASSOCINFO_EVENT_FLAG) {
640                                 wpa_printf(MSG_DEBUG, "Custom wireless event: "
641                                            "receive ASSOCINFO_EVENT !!!");
642
643                                 assoc_info_buf =
644                                         os_zalloc(drv->assoc_req_ies_len +
645                                                   drv->assoc_resp_ies_len + 1);
646
647                                 if (assoc_info_buf == NULL) {
648                                         os_free(drv->assoc_req_ies);
649                                         drv->assoc_req_ies = NULL;
650                                         os_free(drv->assoc_resp_ies);
651                                         drv->assoc_resp_ies = NULL;
652                                         os_free(buf);
653                                         return;
654                                 }
655
656                                 if (drv->assoc_req_ies) {
657                                         os_memcpy(assoc_info_buf,
658                                                   drv->assoc_req_ies,
659                                                   drv->assoc_req_ies_len);
660                                 }
661                                 info_pos = assoc_info_buf +
662                                         drv->assoc_req_ies_len;
663                                 if (drv->assoc_resp_ies) {
664                                         os_memcpy(info_pos,
665                                                   drv->assoc_resp_ies,
666                                                   drv->assoc_resp_ies_len);
667                                 }
668                                 assoc_info_buf[drv->assoc_req_ies_len +
669                                                drv->assoc_resp_ies_len] = '\0';
670                                 wpa_driver_ralink_event_wireless_custom(
671                                         drv, ctx, assoc_info_buf);
672                                 os_free(drv->assoc_req_ies);
673                                 drv->assoc_req_ies = NULL;
674                                 os_free(drv->assoc_resp_ies);
675                                 drv->assoc_resp_ies = NULL;
676                                 os_free(assoc_info_buf);
677                         } else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG)
678                         {
679                                 wpa_printf(MSG_DEBUG, "Custom wireless event: "
680                                            "receive DISASSOCIATED_EVENT !!!");
681                                 wpa_supplicant_event(ctx, EVENT_DISASSOC,
682                                                      NULL);
683                         } else if (iwe->u.data.flags == RT_PMKIDCAND_FLAG) {
684                                 wpa_printf(MSG_DEBUG, "Custom wireless event: "
685                                            "receive PMKIDCAND_EVENT !!!");
686                                 wpa_driver_ralink_event_pmkid(
687                                         drv, (const u8 *) custom,
688                                         iwe->u.data.length);
689                         } else if (iwe->u.data.flags == RT_INTERFACE_DOWN) {
690                                 drv->g_driver_down = 1;
691                                 eloop_terminate();
692                         } else if (iwe->u.data.flags == RT_REPORT_AP_INFO) {
693                                 if (drv->ap_scan != 1) {
694                                         typedef struct PACKED {
695                                                 UCHAR bssid[MAC_ADDR_LEN];
696                                                 UCHAR ssid[MAX_LEN_OF_SSID];
697                                                 INT ssid_len;
698                                                 UCHAR wpa_ie[40];
699                                                 INT wpa_ie_len;
700                                                 UCHAR rsn_ie[40];
701                                                 INT rsn_ie_len;
702                                                 INT freq;
703                                                 USHORT caps;
704                                         } *PAPINFO;
705
706                                         wpa_printf(MSG_DEBUG, "Custom wireless"
707                                                    " event: receive "
708                                                    "RT_REPORT_AP_INFO !!!");
709                                         //printf("iwe->u.data.length = %d\n", iwe->u.data.length);
710                                         //wpa_hexdump(MSG_DEBUG, "AP_Info: ", buf, iwe->u.data.length);
711 #if 0
712                                         wpa_s->num_scan_results = 1;
713                                         if (wpa_s->scan_results)
714                                                 os_free(wpa_s->scan_results);
715                                         wpa_s->scan_results = os_malloc(sizeof(struct wpa_scan_result) + 1);
716                                         if (wpa_s->scan_results) {
717                                                 PAPINFO pApInfo = (PAPINFO)buf;
718                                                 os_memcpy(wpa_s->scan_results[0].bssid, pApInfo->bssid, ETH_ALEN);
719                                                 os_memcpy(wpa_s->scan_results[0].ssid, pApInfo->ssid, pApInfo->ssid_len);
720                                                 wpa_s->scan_results[0].ssid_len = pApInfo->ssid_len;
721                                                 if (pApInfo->wpa_ie_len > 0) {
722                                                         os_memcpy(wpa_s->scan_results[0].wpa_ie, pApInfo->wpa_ie, pApInfo->wpa_ie_len);
723                                                         wpa_s->scan_results[0].wpa_ie_len = pApInfo->wpa_ie_len;
724                                                 } else if (pApInfo->rsn_ie_len > 0) {
725                                                         os_memcpy(wpa_s->scan_results[0].rsn_ie, pApInfo->rsn_ie, pApInfo->rsn_ie_len);
726                                                         wpa_s->scan_results[0].rsn_ie_len = pApInfo->rsn_ie_len;
727                                                 }
728                                                 wpa_s->scan_results[0].caps = pApInfo->caps;
729                                                 wpa_s->scan_results[0].freq = pApInfo->freq;
730                                         } else {
731                                                 wpa_printf("wpa_s->scan_"
732                                                            "results fail to "
733                                                            "os_malloc!!\n");
734                                         }
735 #endif
736                                 }
737                         } else {
738                                 wpa_driver_ralink_event_wireless_custom(
739                                         drv, ctx, buf);
740                         }
741                         os_free(buf);
742                         break;
743                 }
744
745                 pos += iwe->len;
746         }
747 }
748
749 static void
750 wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv,
751                                     void *ctx, struct nlmsghdr *h, int len)
752 {
753         struct ifinfomsg *ifi;
754         int attrlen, nlmsg_len, rta_len;
755         struct rtattr * attr;
756
757         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
758
759         if (len < (int) sizeof(*ifi))
760                 return;
761
762         ifi = NLMSG_DATA(h);
763         wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg));
764
765         nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
766
767         attrlen = h->nlmsg_len - nlmsg_len;
768         wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen);
769         if (attrlen < 0)
770                 return;
771
772         attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
773         wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr));
774         rta_len = RTA_ALIGN(sizeof(struct rtattr));
775         wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len);
776         while (RTA_OK(attr, attrlen)) {
777                 wpa_printf(MSG_DEBUG, "rta_type=%02x\n", attr->rta_type);
778                 if (attr->rta_type == IFLA_WIRELESS) {
779                         wpa_driver_ralink_event_wireless(
780                                 drv, ctx,
781                                 ((char *) attr) + rta_len,
782                                 attr->rta_len - rta_len);
783                 }
784                 attr = RTA_NEXT(attr, attrlen);
785                 wpa_hexdump(MSG_DEBUG, "attr3: ",
786                             (u8 *) attr, sizeof(struct rtattr));
787         }
788 }
789
790 static void wpa_driver_ralink_event_receive(int sock, void *ctx,
791                                             void *sock_ctx)
792 {
793         char buf[8192];
794         int left;
795         struct sockaddr_nl from;
796         socklen_t fromlen;
797         struct nlmsghdr *h;
798
799         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
800
801         fromlen = sizeof(from);
802         left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
803                         (struct sockaddr *) &from, &fromlen);
804
805         if (left < 0) {
806                 if (errno != EINTR && errno != EAGAIN)
807                         perror("recvfrom(netlink)");
808                 return;
809         }
810
811         h = (struct nlmsghdr *) buf;
812         wpa_hexdump(MSG_DEBUG, "h: ", (u8 *)h, h->nlmsg_len);
813
814         while (left >= (int) sizeof(*h)) {
815                 int len, plen;
816
817                 len = h->nlmsg_len;
818                 plen = len - sizeof(*h);
819                 if (len > left || plen < 0) {
820                         wpa_printf(MSG_DEBUG, "Malformed netlink message: "
821                                    "len=%d left=%d plen=%d", len, left, plen);
822                         break;
823                 }
824
825                 switch (h->nlmsg_type) {
826                 case RTM_NEWLINK:
827                         wpa_driver_ralink_event_rtm_newlink(ctx, sock_ctx, h,
828                                                             plen);
829                         break;
830                 }
831
832                 len = NLMSG_ALIGN(len);
833                 left -= len;
834                 h = (struct nlmsghdr *) ((char *) h + len);
835         }
836
837         if (left > 0) {
838                 wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink "
839                            "message", left);
840         }
841
842 }
843
844 static int
845 ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv)
846 {
847         struct iwreq iwr;
848         UINT we_version_compiled = 0;
849
850         os_memset(&iwr, 0, sizeof(iwr));
851         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
852         iwr.u.data.pointer = (caddr_t) &we_version_compiled;
853         iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED;
854
855         if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
856                 wpa_printf(MSG_DEBUG, "%s: failed", __func__);
857                 return -1;
858         }
859
860         drv->we_version_compiled = we_version_compiled;
861
862         return 0;
863 }
864
865 static int
866 ralink_set_iface_flags(void *priv, int dev_up)
867 {
868         struct wpa_driver_ralink_data *drv = priv;
869         struct ifreq ifr;
870
871         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
872
873         if (drv->ioctl_sock < 0)
874                 return -1;
875
876         os_memset(&ifr, 0, sizeof(ifr));
877         os_snprintf(ifr.ifr_name, IFNAMSIZ, "%s", drv->ifname);
878
879         if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
880                 perror("ioctl[SIOCGIFFLAGS]");
881                 return -1;
882         }
883
884         if (dev_up)
885                 ifr.ifr_flags |= IFF_UP;
886         else
887                 ifr.ifr_flags &= ~IFF_UP;
888
889         if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
890                 perror("ioctl[SIOCSIFFLAGS]");
891                 return -1;
892         }
893
894         return 0;
895 }
896
897 static void * wpa_driver_ralink_init(void *ctx, const char *ifname)
898 {
899         int s;
900         struct wpa_driver_ralink_data *drv;
901         struct ifreq ifr;
902         struct sockaddr_nl local;
903         UCHAR enable_wpa_supplicant = 0;
904
905         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
906
907         /* open socket to kernel */
908         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
909                 perror("socket");
910                 return NULL;
911         }
912         /* do it */
913         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
914
915         if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
916                 perror(ifr.ifr_name);
917                 return NULL;
918         }
919
920         drv = os_zalloc(sizeof(*drv));
921         if (drv == NULL)
922                 return NULL;
923
924         drv->scanning_done = 1;
925         drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */
926         drv->ctx = ctx;
927         os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
928         drv->ioctl_sock = s;
929         drv->g_driver_down = 0;
930
931         s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
932         if (s < 0) {
933                 perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
934                 close(drv->ioctl_sock);
935                 os_free(drv);
936                 return NULL;
937         }
938
939         os_memset(&local, 0, sizeof(local));
940         local.nl_family = AF_NETLINK;
941         local.nl_groups = RTMGRP_LINK;
942
943         if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
944                 perror("bind(netlink)");
945                 close(s);
946                 close(drv->ioctl_sock);
947                 os_free(drv);
948                 return NULL;
949         }
950
951         eloop_register_read_sock(s, wpa_driver_ralink_event_receive, drv, ctx);
952         drv->event_sock = s;
953         drv->no_of_pmkid = 4; /* Number of PMKID saved supported */
954
955         ralink_set_iface_flags(drv, 1); /* mark up during setup */
956         ralink_get_we_version_compiled(drv);
957         wpa_driver_ralink_flush_pmkid(drv);
958
959         if (drv->ap_scan == 1)
960                 enable_wpa_supplicant = 1;
961         else
962                 enable_wpa_supplicant = 2;
963         /* trigger driver support wpa_supplicant */
964         if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
965                            (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0)
966         {
967                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
968                            "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)",
969                            (int) enable_wpa_supplicant);
970                 wpa_printf(MSG_ERROR, "RALINK: Driver does not support "
971                            "wpa_supplicant");
972                 close(s);
973                 close(drv->ioctl_sock);
974                 os_free(drv);
975                 return NULL;
976         }
977
978         if (drv->ap_scan == 1)
979                 drv->scanning_done = 0;
980
981         return drv;
982 }
983
984 static void wpa_driver_ralink_deinit(void *priv)
985 {
986         struct wpa_driver_ralink_data *drv = priv;
987         UCHAR enable_wpa_supplicant;
988
989         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
990
991         enable_wpa_supplicant = 0;
992
993         if (drv->g_driver_down == 0) {
994                 /* trigger driver disable wpa_supplicant support */
995                 if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
996                                    (char *) &enable_wpa_supplicant,
997                                    sizeof(BOOLEAN)) < 0) {
998                         wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
999                                    "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)",
1000                                    (int) enable_wpa_supplicant);
1001                 }
1002
1003                 wpa_driver_ralink_flush_pmkid(drv);
1004
1005                 sleep(1);
1006                 ralink_set_iface_flags(drv, 0);
1007         }
1008
1009         eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
1010         eloop_unregister_read_sock(drv->event_sock);
1011         close(drv->event_sock);
1012         close(drv->ioctl_sock);
1013         os_free(drv);
1014 }
1015
1016 static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx)
1017 {
1018         struct wpa_driver_ralink_data *drv = eloop_ctx;
1019
1020         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1021
1022         wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
1023         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
1024
1025         drv->scanning_done = 1;
1026
1027 }
1028
1029 static int wpa_driver_ralink_scan(void *priv, const u8 *ssid, size_t ssid_len)
1030 {
1031         struct wpa_driver_ralink_data *drv = priv;
1032         struct iwreq iwr;
1033         int ret = 0;
1034
1035         if (drv->g_driver_down == 1)
1036                 return -1;
1037
1038         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1039
1040         if (ssid_len > IW_ESSID_MAX_SIZE) {
1041                 wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
1042                            __FUNCTION__, (unsigned long) ssid_len);
1043                 return -1;
1044         }
1045
1046         /* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */
1047
1048         os_memset(&iwr, 0, sizeof(iwr));
1049         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1050
1051         if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
1052                 perror("ioctl[SIOCSIWSCAN]");
1053                 ret = -1;
1054         }
1055
1056         /* Not all drivers generate "scan completed" wireless event, so try to
1057          * read results after a timeout. */
1058         eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
1059         eloop_register_timeout(4, 0, wpa_driver_ralink_scan_timeout, drv,
1060                                drv->ctx);
1061
1062         drv->scanning_done = 0;
1063
1064         return ret;
1065 }
1066
1067 static int
1068 wpa_driver_ralink_get_scan_results(void *priv,
1069                                    struct wpa_scan_result *results,
1070                                    size_t max_size)
1071 {
1072         struct wpa_driver_ralink_data *drv = priv;
1073         UCHAR *buf = NULL;
1074         NDIS_802_11_BSSID_LIST_EX *wsr;
1075         NDIS_WLAN_BSSID_EX *wbi;
1076         struct iwreq iwr;
1077         int rv = 0;
1078         size_t ap_num;
1079         u8 *pos, *end;
1080
1081         if (drv->g_driver_down == 1)
1082                 return -1;
1083         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1084
1085         if (drv->we_version_compiled >= 17) {
1086                 buf = os_zalloc(8192);
1087                 iwr.u.data.length = 8192;
1088         } else {
1089                 buf = os_zalloc(4096);
1090                 iwr.u.data.length = 4096;
1091         }
1092         if (buf == NULL)
1093                 return -1;
1094
1095         wsr = (NDIS_802_11_BSSID_LIST_EX *) buf;
1096
1097         wsr->NumberOfItems = 0;
1098         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1099         iwr.u.data.pointer = (void *) buf;
1100         iwr.u.data.flags = OID_802_11_BSSID_LIST;
1101
1102         if ((rv = ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr)) < 0) {
1103                 wpa_printf(MSG_DEBUG, "ioctl fail: rv = %d", rv);
1104                 os_free(buf);
1105                 return -1;
1106         }
1107
1108         os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
1109
1110         for (ap_num = 0, wbi = wsr->Bssid; ap_num < wsr->NumberOfItems;
1111              ++ap_num) {
1112                 os_memcpy(results[ap_num].bssid, &wbi->MacAddress, ETH_ALEN);
1113                 os_memcpy(results[ap_num].ssid, wbi->Ssid.Ssid,
1114                           wbi->Ssid.SsidLength);
1115                 results[ap_num].ssid_len = wbi->Ssid.SsidLength;
1116                 results[ap_num].freq = (wbi->Configuration.DSConfig / 1000);
1117
1118                 /* get ie's */
1119                 wpa_hexdump(MSG_DEBUG, "RALINK: AP IEs",
1120                             (u8 *) wbi + sizeof(*wbi) - 1, wbi->IELength);
1121
1122                 pos = (u8 *) wbi + sizeof(*wbi) - 1;
1123                 end = (u8 *) wbi + sizeof(*wbi) + wbi->IELength;
1124
1125                 if (wbi->IELength < sizeof(NDIS_802_11_FIXED_IEs))
1126                         break;
1127
1128                 pos += sizeof(NDIS_802_11_FIXED_IEs) - 2;
1129                 os_memcpy(&results[ap_num].caps, pos, 2);
1130                 pos += 2;
1131
1132                 while (pos + 1 < end && pos + 2 + pos[1] <= end) {
1133                         u8 ielen = 2 + pos[1];
1134
1135                         if (ielen > SSID_MAX_WPA_IE_LEN) {
1136                                 pos += ielen;
1137                                 continue;
1138                         }
1139
1140                         if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
1141                             pos[1] >= 4 &&
1142                             os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
1143                                 os_memcpy(results[ap_num].wpa_ie, pos, ielen);
1144                                 results[ap_num].wpa_ie_len = ielen;
1145                         } else if (pos[0] == WLAN_EID_RSN) {
1146                                 os_memcpy(results[ap_num].rsn_ie, pos, ielen);
1147                                 results[ap_num].rsn_ie_len = ielen;
1148                         }
1149                         pos += ielen;
1150                 }
1151
1152                 wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length);
1153         }
1154
1155         os_free(buf);
1156         return ap_num;
1157 }
1158
1159 static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv,
1160                                 NDIS_802_11_AUTHENTICATION_MODE mode)
1161 {
1162         NDIS_802_11_AUTHENTICATION_MODE auth_mode = mode;
1163
1164         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1165
1166         if (ralink_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
1167                            (char *) &auth_mode, sizeof(auth_mode)) < 0) {
1168                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
1169                            "OID_802_11_AUTHENTICATION_MODE (%d)",
1170                            (int) auth_mode);
1171                 return -1;
1172         }
1173         return 0;
1174 }
1175
1176 static int wpa_driver_ralink_remove_key(struct wpa_driver_ralink_data *drv,
1177                                         int key_idx, const u8 *addr,
1178                                         const u8 *bssid, int pairwise)
1179 {
1180         NDIS_802_11_REMOVE_KEY rkey;
1181         NDIS_802_11_KEY_INDEX _index;
1182         int res, res2;
1183
1184         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1185
1186         os_memset(&rkey, 0, sizeof(rkey));
1187
1188         rkey.Length = sizeof(rkey);
1189         rkey.KeyIndex = key_idx;
1190
1191         if (pairwise)
1192                 rkey.KeyIndex |= 1 << 30;
1193
1194         os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
1195
1196         res = ralink_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
1197                              sizeof(rkey));
1198
1199         /* AlbertY@20060210 removed it */
1200         if (0 /* !pairwise */) {
1201                 res2 = ralink_set_oid(drv, OID_802_11_REMOVE_WEP,
1202                                       (char *) &_index, sizeof(_index));
1203         } else
1204                 res2 = 0;
1205
1206         if (res < 0 && res2 < 0)
1207                 return res;
1208         return 0;
1209 }
1210
1211 static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv,
1212                                      int pairwise, int key_idx, int set_tx,
1213                                      const u8 *key, size_t key_len)
1214 {
1215         NDIS_802_11_WEP *wep;
1216         size_t len;
1217         int res;
1218
1219         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1220
1221         len = 12 + key_len;
1222         wep = os_zalloc(len);
1223         if (wep == NULL)
1224                 return -1;
1225
1226         wep->Length = len;
1227         wep->KeyIndex = key_idx;
1228
1229         if (set_tx)
1230                 wep->KeyIndex |= 0x80000000;
1231
1232         wep->KeyLength = key_len;
1233         os_memcpy(wep->KeyMaterial, key, key_len);
1234
1235         wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_WEP",
1236                         (const u8 *) wep, len);
1237         res = ralink_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
1238
1239         os_free(wep);
1240
1241         return res;
1242 }
1243
1244 static int wpa_driver_ralink_set_key(void *priv, wpa_alg alg, const u8 *addr,
1245                                      int key_idx, int set_tx,
1246                                      const u8 *seq, size_t seq_len,
1247                                      const u8 *key, size_t key_len)
1248 {
1249         struct wpa_driver_ralink_data *drv = priv;
1250         size_t len, i;
1251         NDIS_802_11_KEY *nkey;
1252         int res, pairwise;
1253         u8 bssid[ETH_ALEN];
1254
1255         if (drv->g_driver_down == 1)
1256                 return -1;
1257
1258         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1259
1260         if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
1261                                       ETH_ALEN) == 0) {
1262                 /* Group Key */
1263                 pairwise = 0;
1264                 wpa_driver_ralink_get_bssid(drv, bssid);
1265         } else {
1266                 /* Pairwise Key */
1267                 pairwise = 1;
1268                 os_memcpy(bssid, addr, ETH_ALEN);
1269         }
1270
1271         if (alg == WPA_ALG_NONE || key_len == 0) {
1272                 return wpa_driver_ralink_remove_key(drv, key_idx, addr, bssid,
1273                                                     pairwise);
1274         }
1275
1276         if (alg == WPA_ALG_WEP) {
1277                 return wpa_driver_ralink_add_wep(drv, pairwise, key_idx,
1278                                                  set_tx, key, key_len);
1279         }
1280
1281         len = 12 + 6 + 6 + 8 + key_len;
1282
1283         nkey = os_zalloc(len);
1284         if (nkey == NULL)
1285                 return -1;
1286
1287         nkey->Length = len;
1288         nkey->KeyIndex = key_idx;
1289
1290         if (set_tx)
1291                 nkey->KeyIndex |= 1 << 31;
1292
1293         if (pairwise)
1294                 nkey->KeyIndex |= 1 << 30;
1295
1296         if (seq && seq_len)
1297                 nkey->KeyIndex |= 1 << 29;
1298
1299         nkey->KeyLength = key_len;
1300         os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
1301
1302         if (seq && seq_len) {
1303                 for (i = 0; i < seq_len; i++)
1304                         nkey->KeyRSC |= seq[i] << (i * 8);
1305         }
1306         if (alg == WPA_ALG_TKIP && key_len == 32) {
1307                 os_memcpy(nkey->KeyMaterial, key, 16);
1308                 os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
1309                 os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
1310         } else {
1311                 os_memcpy(nkey->KeyMaterial, key, key_len);
1312         }
1313
1314         wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1315                    "key_len=%lu", __FUNCTION__, alg, key_idx, set_tx,
1316                    (unsigned long) seq_len, (unsigned long) key_len);
1317
1318         wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_KEY",
1319                         (const u8 *) nkey, len);
1320         res = ralink_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
1321         os_free(nkey);
1322
1323         return res;
1324 }
1325
1326 static int wpa_driver_ralink_disassociate(void *priv, const u8 *addr,
1327                                         int reason_code)
1328 {
1329         struct wpa_driver_ralink_data *drv = priv;
1330
1331         if (drv->g_driver_down == 1)
1332                 return -1;
1333         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1334         if (ralink_set_oid(drv, OID_802_11_DISASSOCIATE, "    ", 4) < 0) {
1335                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
1336                            "OID_802_11_DISASSOCIATE");
1337         }
1338
1339         return 0;
1340 }
1341
1342 static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr,
1343                                           int reason_code)
1344 {
1345         struct wpa_driver_ralink_data *drv = priv;
1346
1347         wpa_printf(MSG_DEBUG, "g_driver_down = %d", drv->g_driver_down);
1348
1349         if (drv->g_driver_down == 1)
1350                 return -1;
1351
1352         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1353         if (ralink_get_new_driver_flag(drv) == 0) {
1354                 return wpa_driver_ralink_disassociate(priv, addr, reason_code);
1355         } else {
1356                 MLME_DEAUTH_REQ_STRUCT mlme;
1357                 os_memset(&mlme, 0, sizeof(MLME_DEAUTH_REQ_STRUCT));
1358                 mlme.Reason = reason_code;
1359                 os_memcpy(mlme.Addr, addr, MAC_ADDR_LEN);
1360                 return ralink_set_oid(drv, OID_802_11_DEAUTHENTICATION,
1361                                       (char *) &mlme,
1362                                       sizeof(MLME_DEAUTH_REQ_STRUCT));
1363         }
1364 }
1365
1366 static int
1367 wpa_driver_ralink_associate(void *priv,
1368                             struct wpa_driver_associate_params *params)
1369 {
1370         struct wpa_driver_ralink_data *drv = priv;
1371
1372         NDIS_802_11_NETWORK_INFRASTRUCTURE mode;
1373         NDIS_802_11_AUTHENTICATION_MODE auth_mode;
1374         NDIS_802_11_WEP_STATUS encr;
1375         BOOLEAN         ieee8021xMode;
1376
1377         if (drv->g_driver_down == 1)
1378                 return -1;
1379         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1380
1381         if (params->mode == IEEE80211_MODE_IBSS)
1382                 mode = Ndis802_11IBSS;
1383         else
1384                 mode = Ndis802_11Infrastructure;
1385
1386         if (ralink_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
1387                          (char *) &mode, sizeof(mode)) < 0) {
1388                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
1389                            "OID_802_11_INFRASTRUCTURE_MODE (%d)",
1390                            (int) mode);
1391                 /* Try to continue anyway */
1392         }
1393
1394         if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
1395                 if (params->auth_alg & AUTH_ALG_SHARED_KEY) {
1396                         if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
1397                                 auth_mode = Ndis802_11AuthModeAutoSwitch;
1398                         else
1399                                 auth_mode = Ndis802_11AuthModeShared;
1400                 } else
1401                         auth_mode = Ndis802_11AuthModeOpen;
1402         } else if (params->wpa_ie[0] == WLAN_EID_RSN) {
1403                 if (params->key_mgmt_suite == KEY_MGMT_PSK)
1404                         auth_mode = Ndis802_11AuthModeWPA2PSK;
1405                 else
1406                         auth_mode = Ndis802_11AuthModeWPA2;
1407         } else {
1408                 if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
1409                         auth_mode = Ndis802_11AuthModeWPANone;
1410                 else if (params->key_mgmt_suite == KEY_MGMT_PSK)
1411                         auth_mode = Ndis802_11AuthModeWPAPSK;
1412                 else
1413                         auth_mode = Ndis802_11AuthModeWPA;
1414         }
1415
1416         switch (params->pairwise_suite) {
1417         case CIPHER_CCMP:
1418                 encr = Ndis802_11Encryption3Enabled;
1419                 break;
1420         case CIPHER_TKIP:
1421                 encr = Ndis802_11Encryption2Enabled;
1422                 break;
1423         case CIPHER_WEP40:
1424         case CIPHER_WEP104:
1425                 encr = Ndis802_11Encryption1Enabled;
1426                 break;
1427         case CIPHER_NONE:
1428                 if (params->group_suite == CIPHER_CCMP)
1429                         encr = Ndis802_11Encryption3Enabled;
1430                 else if (params->group_suite == CIPHER_TKIP)
1431                         encr = Ndis802_11Encryption2Enabled;
1432                 else
1433                         encr = Ndis802_11EncryptionDisabled;
1434                 break;
1435         default:
1436                 encr = Ndis802_11EncryptionDisabled;
1437                 break;
1438         }
1439
1440         ralink_set_auth_mode(drv, auth_mode);
1441
1442         /* notify driver that IEEE8021x mode is enabled */
1443         if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA)
1444                 ieee8021xMode = TRUE;
1445         else
1446                 ieee8021xMode = FALSE;
1447
1448         if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X,
1449                            (char *) &ieee8021xMode, sizeof(BOOLEAN)) < 0) {
1450                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
1451                            "OID_802_11_SET_IEEE8021X(%d)",
1452                            (int) ieee8021xMode);
1453         }
1454
1455         if (ralink_set_oid(drv, OID_802_11_WEP_STATUS,
1456                          (char *) &encr, sizeof(encr)) < 0) {
1457                 wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
1458                            "OID_802_11_WEP_STATUS(%d)",
1459                            (int) encr);
1460         }
1461
1462         if ((ieee8021xMode == FALSE) &&
1463             (encr == Ndis802_11Encryption1Enabled)) {
1464                 /* static WEP */
1465                 int enabled = 0;
1466                 if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED,
1467                                    (char *) &enabled, sizeof(enabled)) < 0) {
1468                         wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
1469                                    "OID_802_11_DROP_UNENCRYPTED(%d)",
1470                                    (int) encr);
1471                 }
1472         }
1473
1474         return wpa_driver_ralink_set_ssid(drv, params->ssid, params->ssid_len);
1475 }
1476
1477 static int
1478 wpa_driver_ralink_set_countermeasures(void *priv, int enabled)
1479 {
1480         struct wpa_driver_ralink_data *drv = priv;
1481         if (drv->g_driver_down == 1)
1482                 return -1;
1483         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
1484         return ralink_set_oid(drv, OID_SET_COUNTERMEASURES, (char *) &enabled,
1485                               sizeof(int));
1486 }
1487
1488 const struct wpa_driver_ops wpa_driver_ralink_ops = {
1489         .name = "ralink",
1490         .desc = "Ralink Wireless Client driver",
1491         .get_bssid = wpa_driver_ralink_get_bssid,
1492         .get_ssid = wpa_driver_ralink_get_ssid,
1493         .set_key = wpa_driver_ralink_set_key,
1494         .init = wpa_driver_ralink_init,
1495         .deinit = wpa_driver_ralink_deinit,
1496         .set_countermeasures    = wpa_driver_ralink_set_countermeasures,
1497         .scan = wpa_driver_ralink_scan,
1498         .get_scan_results = wpa_driver_ralink_get_scan_results,
1499         .deauthenticate = wpa_driver_ralink_deauthenticate,
1500         .disassociate = wpa_driver_ralink_disassociate,
1501         .associate = wpa_driver_ralink_associate,
1502         .add_pmkid = wpa_driver_ralink_add_pmkid,
1503         .remove_pmkid = wpa_driver_ralink_remove_pmkid,
1504         .flush_pmkid = wpa_driver_ralink_flush_pmkid,
1505 };