OSDN Git Service

am e31782f9: cherry-pick: wpa_supplicant: disable OpenSSL engine.
[android-x86/external-wpa_supplicant.git] / driver_madwifi.c
1 /*
2  * WPA Supplicant - driver interaction with MADWIFI 802.11 driver
3  * Copyright (c) 2004, Sam Leffler <sam@errno.com>
4  * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
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 #include "includes.h"
17 #include <sys/ioctl.h>
18
19 #include "common.h"
20 #include "driver.h"
21 #include "driver_wext.h"
22 #include "eloop.h"
23 #include "wpa_supplicant.h"
24 #include "wpa.h"
25 #include "wireless_copy.h"
26
27 #include <include/compat.h>
28 #include <net80211/ieee80211.h>
29 #ifdef WME_NUM_AC
30 /* Assume this is built against BSD branch of madwifi driver. */
31 #define MADWIFI_BSD
32 #include <net80211/_ieee80211.h>
33 #endif /* WME_NUM_AC */
34 #include <net80211/ieee80211_crypto.h>
35 #include <net80211/ieee80211_ioctl.h>
36
37 #ifdef IEEE80211_IOCTL_SETWMMPARAMS
38 /* Assume this is built against madwifi-ng */
39 #define MADWIFI_NG
40 #endif /* IEEE80211_IOCTL_SETWMMPARAMS */
41
42 struct wpa_driver_madwifi_data {
43         void *wext; /* private data for driver_wext */
44         void *ctx;
45         char ifname[IFNAMSIZ + 1];
46         int sock;
47 };
48
49 static int
50 set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len,
51              int show_err)
52 {
53         struct iwreq iwr;
54
55         os_memset(&iwr, 0, sizeof(iwr));
56         os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
57         if (len < IFNAMSIZ) {
58                 /*
59                  * Argument data fits inline; put it there.
60                  */
61                 os_memcpy(iwr.u.name, data, len);
62         } else {
63                 /*
64                  * Argument data too big for inline transfer; setup a
65                  * parameter block instead; the kernel will transfer
66                  * the data for the driver.
67                  */
68                 iwr.u.data.pointer = data;
69                 iwr.u.data.length = len;
70         }
71
72         if (ioctl(drv->sock, op, &iwr) < 0) {
73                 if (show_err) {
74 #ifdef MADWIFI_NG
75                         int first = IEEE80211_IOCTL_SETPARAM;
76                         int last = IEEE80211_IOCTL_KICKMAC;
77                         static const char *opnames[] = {
78                                 "ioctl[IEEE80211_IOCTL_SETPARAM]",
79                                 "ioctl[IEEE80211_IOCTL_GETPARAM]",
80                                 "ioctl[IEEE80211_IOCTL_SETMODE]",
81                                 "ioctl[IEEE80211_IOCTL_GETMODE]",
82                                 "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
83                                 "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
84                                 "ioctl[IEEE80211_IOCTL_SETCHANLIST]",
85                                 "ioctl[IEEE80211_IOCTL_GETCHANLIST]",
86                                 "ioctl[IEEE80211_IOCTL_CHANSWITCH]",
87                                 NULL,
88                                 NULL,
89                                 "ioctl[IEEE80211_IOCTL_GETSCANRESULTS]",
90                                 NULL,
91                                 "ioctl[IEEE80211_IOCTL_GETCHANINFO]",
92                                 "ioctl[IEEE80211_IOCTL_SETOPTIE]",
93                                 "ioctl[IEEE80211_IOCTL_GETOPTIE]",
94                                 "ioctl[IEEE80211_IOCTL_SETMLME]",
95                                 NULL,
96                                 "ioctl[IEEE80211_IOCTL_SETKEY]",
97                                 NULL,
98                                 "ioctl[IEEE80211_IOCTL_DELKEY]",
99                                 NULL,
100                                 "ioctl[IEEE80211_IOCTL_ADDMAC]",
101                                 NULL,
102                                 "ioctl[IEEE80211_IOCTL_DELMAC]",
103                                 NULL,
104                                 "ioctl[IEEE80211_IOCTL_WDSMAC]",
105                                 NULL,
106                                 "ioctl[IEEE80211_IOCTL_WDSDELMAC]",
107                                 NULL,
108                                 "ioctl[IEEE80211_IOCTL_KICKMAC]",
109                         };
110 #else /* MADWIFI_NG */
111                         int first = IEEE80211_IOCTL_SETPARAM;
112                         int last = IEEE80211_IOCTL_CHANLIST;
113                         static const char *opnames[] = {
114                                 "ioctl[IEEE80211_IOCTL_SETPARAM]",
115                                 "ioctl[IEEE80211_IOCTL_GETPARAM]",
116                                 "ioctl[IEEE80211_IOCTL_SETKEY]",
117                                 "ioctl[IEEE80211_IOCTL_GETKEY]",
118                                 "ioctl[IEEE80211_IOCTL_DELKEY]",
119                                 NULL,
120                                 "ioctl[IEEE80211_IOCTL_SETMLME]",
121                                 NULL,
122                                 "ioctl[IEEE80211_IOCTL_SETOPTIE]",
123                                 "ioctl[IEEE80211_IOCTL_GETOPTIE]",
124                                 "ioctl[IEEE80211_IOCTL_ADDMAC]",
125                                 NULL,
126                                 "ioctl[IEEE80211_IOCTL_DELMAC]",
127                                 NULL,
128                                 "ioctl[IEEE80211_IOCTL_CHANLIST]",
129                         };
130 #endif /* MADWIFI_NG */
131                         int idx = op - first;
132                         if (first <= op && op <= last &&
133                             idx < (int) (sizeof(opnames) / sizeof(opnames[0]))
134                             && opnames[idx])
135                                 perror(opnames[idx]);
136                         else
137                                 perror("ioctl[unknown???]");
138                 }
139                 return -1;
140         }
141         return 0;
142 }
143
144 static int
145 set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg,
146               int show_err)
147 {
148         struct iwreq iwr;
149
150         os_memset(&iwr, 0, sizeof(iwr));
151         os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
152         iwr.u.mode = op;
153         os_memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg));
154
155         if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
156                 if (show_err) 
157                         perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
158                 return -1;
159         }
160         return 0;
161 }
162
163 static int
164 wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv,
165                               const u8 *wpa_ie, size_t wpa_ie_len)
166 {
167         struct iwreq iwr;
168
169         os_memset(&iwr, 0, sizeof(iwr));
170         os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
171         /* NB: SETOPTIE is not fixed-size so must not be inlined */
172         iwr.u.data.pointer = (void *) wpa_ie;
173         iwr.u.data.length = wpa_ie_len;
174
175         if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) {
176                 perror("ioctl[IEEE80211_IOCTL_SETOPTIE]");
177                 return -1;
178         }
179         return 0;
180 }
181
182 static int
183 wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx,
184                            const u8 *addr)
185 {
186         struct ieee80211req_del_key wk;
187
188         wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
189         os_memset(&wk, 0, sizeof(wk));
190         wk.idk_keyix = key_idx;
191         if (addr != NULL)
192                 os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
193
194         return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1);
195 }
196
197 static int
198 wpa_driver_madwifi_set_key(void *priv, wpa_alg alg,
199                            const u8 *addr, int key_idx, int set_tx,
200                            const u8 *seq, size_t seq_len,
201                            const u8 *key, size_t key_len)
202 {
203         struct wpa_driver_madwifi_data *drv = priv;
204         struct ieee80211req_key wk;
205         char *alg_name;
206         u_int8_t cipher;
207
208         if (alg == WPA_ALG_NONE)
209                 return wpa_driver_madwifi_del_key(drv, key_idx, addr);
210
211         switch (alg) {
212         case WPA_ALG_WEP:
213                 if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
214                                               ETH_ALEN) == 0) {
215                         /*
216                          * madwifi did not seem to like static WEP key
217                          * configuration with IEEE80211_IOCTL_SETKEY, so use
218                          * Linux wireless extensions ioctl for this.
219                          */
220                         return wpa_driver_wext_set_key(drv->wext, alg, addr,
221                                                        key_idx, set_tx,
222                                                        seq, seq_len,
223                                                        key, key_len);
224                 }
225                 alg_name = "WEP";
226                 cipher = IEEE80211_CIPHER_WEP;
227                 break;
228         case WPA_ALG_TKIP:
229                 alg_name = "TKIP";
230                 cipher = IEEE80211_CIPHER_TKIP;
231                 break;
232         case WPA_ALG_CCMP:
233                 alg_name = "CCMP";
234                 cipher = IEEE80211_CIPHER_AES_CCM;
235                 break;
236         default:
237                 wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
238                         __FUNCTION__, alg);
239                 return -1;
240         }
241
242         wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
243                    "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
244                    (unsigned long) seq_len, (unsigned long) key_len);
245
246         if (seq_len > sizeof(u_int64_t)) {
247                 wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big",
248                            __FUNCTION__, (unsigned long) seq_len);
249                 return -2;
250         }
251         if (key_len > sizeof(wk.ik_keydata)) {
252                 wpa_printf(MSG_DEBUG, "%s: key length %lu too big",
253                            __FUNCTION__, (unsigned long) key_len);
254                 return -3;
255         }
256
257         os_memset(&wk, 0, sizeof(wk));
258         wk.ik_type = cipher;
259         wk.ik_flags = IEEE80211_KEY_RECV;
260         if (addr == NULL ||
261             os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
262                 wk.ik_flags |= IEEE80211_KEY_GROUP;
263         if (set_tx) {
264                 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
265                 os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
266         } else
267                 os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
268         wk.ik_keyix = key_idx;
269         wk.ik_keylen = key_len;
270 #ifdef WORDS_BIGENDIAN
271 #define WPA_KEY_RSC_LEN 8
272         {
273                 size_t i;
274                 u8 tmp[WPA_KEY_RSC_LEN];
275                 os_memset(tmp, 0, sizeof(tmp));
276                 for (i = 0; i < seq_len; i++)
277                         tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
278                 os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
279         }
280 #else /* WORDS_BIGENDIAN */
281         os_memcpy(&wk.ik_keyrsc, seq, seq_len);
282 #endif /* WORDS_BIGENDIAN */
283         os_memcpy(wk.ik_keydata, key, key_len);
284
285         return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1);
286 }
287
288 static int
289 wpa_driver_madwifi_set_countermeasures(void *priv, int enabled)
290 {
291         struct wpa_driver_madwifi_data *drv = priv;
292         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
293         return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1);
294 }
295
296
297 static int
298 wpa_driver_madwifi_set_drop_unencrypted(void *priv, int enabled)
299 {
300         struct wpa_driver_madwifi_data *drv = priv;
301         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
302         return set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, enabled, 1);
303 }
304
305 static int
306 wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code)
307 {
308         struct wpa_driver_madwifi_data *drv = priv;
309         struct ieee80211req_mlme mlme;
310
311         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
312         mlme.im_op = IEEE80211_MLME_DEAUTH;
313         mlme.im_reason = reason_code;
314         os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
315         return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
316 }
317
318 static int
319 wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code)
320 {
321         struct wpa_driver_madwifi_data *drv = priv;
322         struct ieee80211req_mlme mlme;
323
324         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
325         mlme.im_op = IEEE80211_MLME_DISASSOC;
326         mlme.im_reason = reason_code;
327         os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
328         return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
329 }
330
331 static int
332 wpa_driver_madwifi_associate(void *priv,
333                              struct wpa_driver_associate_params *params)
334 {
335         struct wpa_driver_madwifi_data *drv = priv;
336         struct ieee80211req_mlme mlme;
337         int ret = 0, privacy = 1;
338
339         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
340
341         /*
342          * NB: Don't need to set the freq or cipher-related state as
343          *     this is implied by the bssid which is used to locate
344          *     the scanned node state which holds it.  The ssid is
345          *     needed to disambiguate an AP that broadcasts multiple
346          *     ssid's but uses the same bssid.
347          */
348         /* XXX error handling is wrong but unclear what to do... */
349         if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie,
350                                           params->wpa_ie_len) < 0)
351                 ret = -1;
352
353         if (params->pairwise_suite == CIPHER_NONE &&
354             params->group_suite == CIPHER_NONE &&
355             params->key_mgmt_suite == KEY_MGMT_NONE &&
356             params->wpa_ie_len == 0)
357                 privacy = 0;
358
359         if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0)
360                 ret = -1;
361
362         if (params->wpa_ie_len &&
363             set80211param(drv, IEEE80211_PARAM_WPA,
364                           params->wpa_ie[0] == RSN_INFO_ELEM ? 2 : 1, 1) < 0)
365                 ret = -1;
366
367         if (params->bssid == NULL) {
368                 /* ap_scan=2 mode - driver takes care of AP selection and
369                  * roaming */
370                 /* FIX: this does not seem to work; would probably need to
371                  * change something in the driver */
372                 if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0)
373                         ret = -1;
374
375                 if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
376                                              params->ssid_len) < 0)
377                         ret = -1;
378         } else {
379                 if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0)
380                         ret = -1;
381                 if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
382                                              params->ssid_len) < 0)
383                         ret = -1;
384                 os_memset(&mlme, 0, sizeof(mlme));
385                 mlme.im_op = IEEE80211_MLME_ASSOC;
386                 os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
387                 if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
388                                  sizeof(mlme), 1) < 0) {
389                         wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed",
390                                    __func__);
391                         ret = -1;
392                 }
393         }
394
395         return ret;
396 }
397
398 static int
399 wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg)
400 {
401         struct wpa_driver_madwifi_data *drv = priv;
402         int authmode;
403
404         if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
405             (auth_alg & AUTH_ALG_SHARED_KEY))
406                 authmode = IEEE80211_AUTH_AUTO;
407         else if (auth_alg & AUTH_ALG_SHARED_KEY)
408                 authmode = IEEE80211_AUTH_SHARED;
409         else
410                 authmode = IEEE80211_AUTH_OPEN;
411
412         return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1);
413 }
414
415 static int
416 wpa_driver_madwifi_scan(void *priv, const u8 *ssid, size_t ssid_len)
417 {
418         struct wpa_driver_madwifi_data *drv = priv;
419         struct iwreq iwr;
420         int ret = 0;
421
422         os_memset(&iwr, 0, sizeof(iwr));
423         os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
424
425         /* set desired ssid before scan */
426         /* FIX: scan should not break the current association, so using
427          * set_ssid may not be the best way of doing this.. */
428         if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0)
429                 ret = -1;
430
431         if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) {
432                 perror("ioctl[SIOCSIWSCAN]");
433                 ret = -1;
434         }
435
436         /*
437          * madwifi delivers a scan complete event so no need to poll, but
438          * register a backup timeout anyway to make sure that we recover even
439          * if the driver does not send this event for any reason. This timeout
440          * will only be used if the event is not delivered (event handler will
441          * cancel the timeout).
442          */
443         eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
444                              drv->ctx);
445         eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext,
446                                drv->ctx);
447
448         return ret;
449 }
450
451 static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid)
452 {
453         struct wpa_driver_madwifi_data *drv = priv;
454         return wpa_driver_wext_get_bssid(drv->wext, bssid);
455 }
456
457
458 static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid)
459 {
460         struct wpa_driver_madwifi_data *drv = priv;
461         return wpa_driver_wext_get_ssid(drv->wext, ssid);
462 }
463
464
465 static int wpa_driver_madwifi_get_scan_results(void *priv,
466                                             struct wpa_scan_result *results,
467                                             size_t max_size)
468 {
469         struct wpa_driver_madwifi_data *drv = priv;
470         return wpa_driver_wext_get_scan_results(drv->wext, results, max_size);
471 }
472
473
474 static int wpa_driver_madwifi_set_operstate(void *priv, int state)
475 {
476         struct wpa_driver_madwifi_data *drv = priv;
477         return wpa_driver_wext_set_operstate(drv->wext, state);
478 }
479
480
481 static void * wpa_driver_madwifi_init(void *ctx, const char *ifname)
482 {
483         struct wpa_driver_madwifi_data *drv;
484
485         drv = os_zalloc(sizeof(*drv));
486         if (drv == NULL)
487                 return NULL;
488         drv->wext = wpa_driver_wext_init(ctx, ifname);
489         if (drv->wext == NULL)
490                 goto fail;
491
492         drv->ctx = ctx;
493         os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
494         drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
495         if (drv->sock < 0)
496                 goto fail2;
497
498         if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) {
499                 wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
500                            "roaming", __FUNCTION__);
501                 goto fail3;
502         }
503
504         if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) {
505                 wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support",
506                            __FUNCTION__);
507                 goto fail3;
508         }
509
510         return drv;
511
512 fail3:
513         close(drv->sock);
514 fail2:
515         wpa_driver_wext_deinit(drv->wext);
516 fail:
517         os_free(drv);
518         return NULL;
519 }
520
521
522 static void wpa_driver_madwifi_deinit(void *priv)
523 {
524         struct wpa_driver_madwifi_data *drv = priv;
525
526         if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) {
527                 wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE",
528                            __FUNCTION__);
529         }
530         if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) {
531                 wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based "
532                            "roaming", __FUNCTION__);
533         }
534         if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) {
535                 wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy "
536                            "flag", __FUNCTION__);
537         }
538         if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) {
539                 wpa_printf(MSG_DEBUG, "%s: failed to disable WPA",
540                            __FUNCTION__);
541         }
542
543         wpa_driver_wext_deinit(drv->wext);
544
545         close(drv->sock);
546         os_free(drv);
547 }
548
549
550 const struct wpa_driver_ops wpa_driver_madwifi_ops = {
551         .name                   = "madwifi",
552         .desc                   = "MADWIFI 802.11 support (Atheros, etc.)",
553         .get_bssid              = wpa_driver_madwifi_get_bssid,
554         .get_ssid               = wpa_driver_madwifi_get_ssid,
555         .set_key                = wpa_driver_madwifi_set_key,
556         .init                   = wpa_driver_madwifi_init,
557         .deinit                 = wpa_driver_madwifi_deinit,
558         .set_countermeasures    = wpa_driver_madwifi_set_countermeasures,
559         .set_drop_unencrypted   = wpa_driver_madwifi_set_drop_unencrypted,
560         .scan                   = wpa_driver_madwifi_scan,
561         .get_scan_results       = wpa_driver_madwifi_get_scan_results,
562         .deauthenticate         = wpa_driver_madwifi_deauthenticate,
563         .disassociate           = wpa_driver_madwifi_disassociate,
564         .associate              = wpa_driver_madwifi_associate,
565         .set_auth_alg           = wpa_driver_madwifi_set_auth_alg,
566         .set_operstate          = wpa_driver_madwifi_set_operstate,
567 };