Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / wpa / src / drivers / driver_bsd.c
bloba711ce672dcf75be807dab71a528d05cfb6dc643
1 /*
2 * WPA Supplicant - driver interaction with BSD net80211 layer
3 * Copyright (c) 2004, Sam Leffler <sam@errno.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
16 #include <sys/ioctl.h>
18 #include "common.h"
19 #include "driver.h"
20 #include "eloop.h"
21 #include "ieee802_11_defs.h"
23 #include <net/if.h>
24 #ifdef __FreeBSD__
25 #include <net/ethernet.h>
26 #endif
27 #ifdef __NetBSD__
28 #include <net/if_ether.h>
29 #endif
31 #include <net80211/ieee80211.h>
32 #include <net80211/ieee80211_crypto.h>
33 #include <net80211/ieee80211_ioctl.h>
35 struct wpa_driver_bsd_data {
36 int sock; /* open socket for 802.11 ioctls */
37 int route; /* routing socket for events */
38 char ifname[IFNAMSIZ+1]; /* interface name */
39 unsigned int ifindex; /* interface index */
40 int flags; /* interface flags */
41 void *ctx;
42 int prev_roaming; /* roaming state to restore on deinit */
43 int prev_privacy; /* privacy state to restore on deinit */
44 int prev_wpa; /* wpa state to restore on deinit */
47 static int
48 set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
50 struct ieee80211req ireq;
52 os_memset(&ireq, 0, sizeof(ireq));
53 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
54 ireq.i_type = op;
55 ireq.i_len = arg_len;
56 ireq.i_data = (void *) arg;
58 if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
59 fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
60 op, arg_len, strerror(errno));
61 return -1;
63 return 0;
66 static int
67 get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
69 struct ieee80211req ireq;
71 os_memset(&ireq, 0, sizeof(ireq));
72 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
73 ireq.i_type = op;
74 ireq.i_len = arg_len;
75 ireq.i_data = arg;
77 if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
78 fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
79 op, arg_len, strerror(errno));
80 return -1;
82 return ireq.i_len;
85 static int
86 set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
88 struct ieee80211req ireq;
90 os_memset(&ireq, 0, sizeof(ireq));
91 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
92 ireq.i_type = op;
93 ireq.i_val = arg;
95 if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
96 fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
97 op, arg, strerror(errno));
98 return -1;
100 return 0;
103 static int
104 get80211param(struct wpa_driver_bsd_data *drv, int op)
106 struct ieee80211req ireq;
108 os_memset(&ireq, 0, sizeof(ireq));
109 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
110 ireq.i_type = op;
112 if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
113 fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
114 op, strerror(errno));
115 return -1;
117 return ireq.i_val;
120 static int
121 getifflags(struct wpa_driver_bsd_data *drv, int *flags)
123 struct ifreq ifr;
125 os_memset(&ifr, 0, sizeof(ifr));
126 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
127 if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
128 perror("SIOCGIFFLAGS");
129 return errno;
131 *flags = ifr.ifr_flags & 0xffff;
132 return 0;
135 static int
136 setifflags(struct wpa_driver_bsd_data *drv, int flags)
138 struct ifreq ifr;
140 os_memset(&ifr, 0, sizeof(ifr));
141 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
142 ifr.ifr_flags = flags & 0xffff;
143 if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
144 perror("SIOCSIFFLAGS");
145 return errno;
147 return 0;
150 static int
151 wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
153 struct wpa_driver_bsd_data *drv = priv;
154 #ifdef SIOCG80211BSSID
155 struct ieee80211_bssid bs;
157 strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
158 if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
159 return -1;
160 os_memcpy(bssid, bs.i_bssid, IEEE80211_ADDR_LEN);
161 return 0;
162 #else
163 return get80211var(drv, IEEE80211_IOC_BSSID,
164 bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
165 #endif
168 #if 0
169 static int
170 wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
172 struct wpa_driver_bsd_data *drv = priv;
173 #ifdef SIOCS80211BSSID
174 struct ieee80211_bssid bs;
176 strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name);
177 os_memcpy(bs.i_bssid, bssid, sizeof(bs.i_bssid));
178 return ioctl(drv->sock, SIOCS80211BSSID, &bs);
179 #else
180 return set80211var(drv, IEEE80211_IOC_BSSID,
181 bssid, IEEE80211_ADDR_LEN);
182 #endif
184 #endif
186 static int
187 wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
189 struct wpa_driver_bsd_data *drv = priv;
190 #ifdef SIOCG80211NWID
191 struct ieee80211_nwid nwid;
192 struct ifreq ifr;
194 os_memset(&ifr, 0, sizeof(ifr));
195 strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
196 ifr.ifr_data = (void *)&nwid;
197 if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
198 nwid.i_len > IEEE80211_NWID_LEN)
199 return -1;
200 os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
201 return nwid.i_len;
202 #else
203 return get80211var(drv, IEEE80211_IOC_SSID,
204 ssid, IEEE80211_NWID_LEN);
205 #endif
208 static int
209 wpa_driver_bsd_set_ssid(void *priv, const char *ssid,
210 size_t ssid_len)
212 struct wpa_driver_bsd_data *drv = priv;
213 #ifdef SIOCS80211NWID
214 struct ieee80211_nwid nwid;
215 struct ifreq ifr;
217 os_memcpy(nwid.i_nwid, ssid, ssid_len);
218 nwid.i_len = ssid_len;
219 os_memset(&ifr, 0, sizeof(ifr));
220 strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
221 ifr.ifr_data = (void *)&nwid;
222 return ioctl(drv->sock, SIOCS80211NWID, &ifr);
223 #else
224 return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
225 #endif
228 static int
229 wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
230 const char *wpa_ie, size_t wpa_ie_len)
232 return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
235 static int
236 wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
238 struct wpa_driver_bsd_data *drv = priv;
239 int ret = 0;
241 wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
242 __func__, wpa, privacy);
244 if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
245 ret = -1;
246 if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
247 ret = -1;
248 if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
249 ret = -1;
251 return ret;
254 static int
255 wpa_driver_bsd_set_wpa(void *priv, int enabled)
257 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
259 return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
262 static int
263 wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
264 const unsigned char *addr)
266 struct ieee80211req_del_key wk;
268 os_memset(&wk, 0, sizeof(wk));
269 if (addr != NULL &&
270 bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) {
271 struct ether_addr ea;
273 os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
274 wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d",
275 __func__, ether_ntoa(&ea), key_idx);
276 os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
277 wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE;
278 } else {
279 wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx);
280 wk.idk_keyix = key_idx;
282 return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
285 static int
286 wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
287 const unsigned char *addr, int key_idx, int set_tx,
288 const u8 *seq, size_t seq_len,
289 const u8 *key, size_t key_len)
291 struct wpa_driver_bsd_data *drv = priv;
292 struct ieee80211req_key wk;
293 struct ether_addr ea;
294 char *alg_name;
295 u_int8_t cipher;
297 if (alg == WPA_ALG_NONE)
298 return wpa_driver_bsd_del_key(drv, key_idx, addr);
300 switch (alg) {
301 case WPA_ALG_WEP:
302 alg_name = "WEP";
303 cipher = IEEE80211_CIPHER_WEP;
304 break;
305 case WPA_ALG_TKIP:
306 alg_name = "TKIP";
307 cipher = IEEE80211_CIPHER_TKIP;
308 break;
309 case WPA_ALG_CCMP:
310 alg_name = "CCMP";
311 cipher = IEEE80211_CIPHER_AES_CCM;
312 break;
313 default:
314 wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
315 __func__, alg);
316 return -1;
319 os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
320 wpa_printf(MSG_DEBUG,
321 "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
322 __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
323 seq_len, key_len);
325 if (seq_len > sizeof(u_int64_t)) {
326 wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
327 __func__, seq_len);
328 return -2;
330 if (key_len > sizeof(wk.ik_keydata)) {
331 wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
332 __func__, key_len);
333 return -3;
336 os_memset(&wk, 0, sizeof(wk));
337 wk.ik_type = cipher;
338 wk.ik_flags = IEEE80211_KEY_RECV;
339 if (set_tx)
340 wk.ik_flags |= IEEE80211_KEY_XMIT;
341 os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
343 * Deduce whether group/global or unicast key by checking
344 * the address (yech). Note also that we can only mark global
345 * keys default; doing this for a unicast key is an error.
347 if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
348 wk.ik_flags |= IEEE80211_KEY_GROUP;
349 wk.ik_keyix = key_idx;
350 } else {
351 wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
353 if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
354 wk.ik_flags |= IEEE80211_KEY_DEFAULT;
355 wk.ik_keylen = key_len;
356 os_memcpy(&wk.ik_keyrsc, seq, seq_len);
357 #ifdef notdef
358 /* Is this needed? */
359 wk.ik_keyrsc = le64toh(wk.ik_keyrsc);
360 #endif
361 os_memcpy(wk.ik_keydata, key, key_len);
363 return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
366 static int
367 wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
369 struct wpa_driver_bsd_data *drv = priv;
371 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
372 return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
376 static int
377 wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
379 struct wpa_driver_bsd_data *drv = priv;
381 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
382 return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
385 static int
386 wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
388 struct wpa_driver_bsd_data *drv = priv;
389 struct ieee80211req_mlme mlme;
391 wpa_printf(MSG_DEBUG, "%s", __func__);
392 os_memset(&mlme, 0, sizeof(mlme));
393 mlme.im_op = IEEE80211_MLME_DEAUTH;
394 mlme.im_reason = reason_code;
395 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
396 return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
399 static int
400 wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
402 struct wpa_driver_bsd_data *drv = priv;
403 struct ieee80211req_mlme mlme;
405 wpa_printf(MSG_DEBUG, "%s", __func__);
406 os_memset(&mlme, 0, sizeof(mlme));
407 mlme.im_op = IEEE80211_MLME_DISASSOC;
408 mlme.im_reason = reason_code;
409 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
410 return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
413 static int
414 wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
416 struct wpa_driver_bsd_data *drv = priv;
417 struct ieee80211req_mlme mlme;
418 int privacy;
420 wpa_printf(MSG_DEBUG,
421 "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
422 , __func__
423 , params->ssid_len, params->ssid
424 , params->wpa_ie_len
425 , params->pairwise_suite
426 , params->group_suite
427 , params->key_mgmt_suite
430 /* XXX error handling is wrong but unclear what to do... */
431 if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
432 return -1;
434 privacy = !(params->pairwise_suite == CIPHER_NONE &&
435 params->group_suite == CIPHER_NONE &&
436 params->key_mgmt_suite == KEY_MGMT_NONE &&
437 params->wpa_ie_len == 0);
438 wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
440 if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
441 return -1;
443 if (params->wpa_ie_len &&
444 set80211param(drv, IEEE80211_IOC_WPA,
445 params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
446 return -1;
448 os_memset(&mlme, 0, sizeof(mlme));
449 mlme.im_op = IEEE80211_MLME_ASSOC;
450 if (params->ssid != NULL)
451 os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
452 mlme.im_ssid_len = params->ssid_len;
453 if (params->bssid != NULL)
454 os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
455 if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
456 return -1;
457 return 0;
460 static int
461 wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
463 struct wpa_driver_bsd_data *drv = priv;
464 int authmode;
466 if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
467 (auth_alg & AUTH_ALG_SHARED_KEY))
468 authmode = IEEE80211_AUTH_AUTO;
469 else if (auth_alg & AUTH_ALG_SHARED_KEY)
470 authmode = IEEE80211_AUTH_SHARED;
471 else
472 authmode = IEEE80211_AUTH_OPEN;
474 return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
477 static int
478 wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
480 struct wpa_driver_bsd_data *drv = priv;
481 int flags;
483 /* NB: interface must be marked UP to do a scan */
484 if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
485 return -1;
487 /* set desired ssid before scan */
488 if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
489 return -1;
491 /* NB: net80211 delivers a scan complete event so no need to poll */
492 return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
495 #include <net/route.h>
496 #if defined(__FreeBSD__)
497 #include <net80211/ieee80211_freebsd.h>
498 #elif defined(__NetBSD__)
499 #include <net80211/ieee80211_netbsd.h>
500 #endif
502 static void
503 wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
505 struct wpa_driver_bsd_data *drv = sock_ctx;
506 char buf[2048];
507 struct if_announcemsghdr *ifan;
508 struct if_msghdr *ifm;
509 struct rt_msghdr *rtm;
510 union wpa_event_data event;
511 struct ieee80211_michael_event *mic;
512 int n;
514 n = read(sock, buf, sizeof(buf));
515 if (n < 0) {
516 if (errno != EINTR && errno != EAGAIN)
517 perror("read(PF_ROUTE)");
518 return;
521 rtm = (struct rt_msghdr *) buf;
522 if (rtm->rtm_version != RTM_VERSION) {
523 wpa_printf(MSG_DEBUG, "Routing message version %d not "
524 "understood\n", rtm->rtm_version);
525 return;
527 os_memset(&event, 0, sizeof(event));
528 switch (rtm->rtm_type) {
529 case RTM_IFANNOUNCE:
530 ifan = (struct if_announcemsghdr *) rtm;
531 if (ifan->ifan_index != drv->ifindex)
532 break;
533 strlcpy(event.interface_status.ifname, drv->ifname,
534 sizeof(event.interface_status.ifname));
535 switch (ifan->ifan_what) {
536 case IFAN_DEPARTURE:
537 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
538 break;
539 default:
540 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
541 break;
543 wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s (%d)",
544 event.interface_status.ifname,
545 ifan->ifan_what == IFAN_DEPARTURE ?
546 "removed" : "added", ifan->ifan_what);
547 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
548 return;
549 case RTM_IEEE80211:
550 ifan = (struct if_announcemsghdr *) rtm;
551 if (ifan->ifan_index != drv->ifindex)
552 break;
553 switch (ifan->ifan_what) {
554 case RTM_IEEE80211_ASSOC:
555 case RTM_IEEE80211_REASSOC:
556 wpa_printf(MSG_DEBUG, "RTM_IEEE80211: (re)assoc (%d)",
557 ifan->ifan_what);
558 wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
559 break;
560 case RTM_IEEE80211_DISASSOC:
561 wpa_printf(MSG_DEBUG, "RTM_IEEE80211: disassoc (%d)",
562 ifan->ifan_what);
563 wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
564 break;
565 case RTM_IEEE80211_SCAN:
566 wpa_printf(MSG_DEBUG, "RTM_IEEE80211: scan result (%d)",
567 ifan->ifan_what);
568 wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
569 break;
570 case RTM_IEEE80211_REPLAY:
571 wpa_printf(MSG_DEBUG, "RTM_IEEE80211: replay (%d)",
572 ifan->ifan_what);
573 /* ignore */
574 break;
575 case RTM_IEEE80211_MICHAEL:
576 mic = (struct ieee80211_michael_event *) &ifan[1];
577 wpa_printf(MSG_DEBUG,
578 "Michael MIC failure wireless event: "
579 "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
580 MAC2STR(mic->iev_src));
582 os_memset(&event, 0, sizeof(event));
583 event.michael_mic_failure.unicast =
584 !IEEE80211_IS_MULTICAST(mic->iev_dst);
585 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
586 &event);
587 break;
588 default:
589 wpa_printf(MSG_DEBUG, "RTM_IEEE80211: ??? (%d)",
590 ifan->ifan_what);
591 break;
593 break;
594 case RTM_IFINFO:
595 ifm = (struct if_msghdr *) rtm;
596 if (ifm->ifm_index != drv->ifindex)
597 break;
598 if ((ifm->ifm_flags & IFF_UP) == 0 &&
599 (drv->flags & IFF_UP) != 0) {
600 strlcpy(event.interface_status.ifname, drv->ifname,
601 sizeof(event.interface_status.ifname));
602 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
603 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
604 event.interface_status.ifname);
605 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
606 } else if ((ifm->ifm_flags & IFF_UP) != 0 &&
607 (drv->flags & IFF_UP) == 0) {
608 strlcpy(event.interface_status.ifname, drv->ifname,
609 sizeof(event.interface_status.ifname));
610 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
611 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
612 event.interface_status.ifname);
613 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
614 } else {
615 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' "
616 "if=%x drv=%x", event.interface_status.ifname,
617 ifm->ifm_flags, drv->flags);
619 drv->flags = ifm->ifm_flags;
620 break;
621 case RTM_LOSING:
622 wpa_printf(MSG_DEBUG, "RTM_LOSING: %d", rtm->rtm_type);
623 break;
624 default:
625 wpa_printf(MSG_DEBUG, "RTM_???: %d", rtm->rtm_type);
626 break;
630 /* Compare function for sorting scan results. Return >0 if @b is consider
631 * better. */
632 static int
633 wpa_scan_result_compar(const void *a, const void *b)
635 const struct wpa_scan_result *wa = a;
636 const struct wpa_scan_result *wb = b;
638 /* WPA/WPA2 support preferred */
639 if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
640 !(wa->wpa_ie_len || wa->rsn_ie_len))
641 return 1;
642 if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
643 (wa->wpa_ie_len || wa->rsn_ie_len))
644 return -1;
646 /* privacy support preferred */
647 if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
648 (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
649 return 1;
650 if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
651 (wb->caps & IEEE80211_CAPINFO_PRIVACY))
652 return -1;
654 /* best/max rate preferred if signal level close enough XXX */
655 if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
656 return wb->maxrate - wa->maxrate;
658 /* use freq for channel preference */
660 /* all things being equal, use signal level */
661 return wb->level - wa->level;
664 static int
665 getmaxrate(uint8_t rates[15], uint8_t nrates)
667 int i, maxrate = -1;
669 for (i = 0; i < nrates; i++) {
670 int rate = rates[i] & IEEE80211_RATE_VAL;
671 if (rate > maxrate)
672 rate = maxrate;
674 return maxrate;
677 /* unalligned little endian access */
678 #define LE_READ_4(p) \
679 ((u_int32_t) \
680 ((((const u_int8_t *)(p))[0] ) | \
681 (((const u_int8_t *)(p))[1] << 8) | \
682 (((const u_int8_t *)(p))[2] << 16) | \
683 (((const u_int8_t *)(p))[3] << 24)))
685 static int __inline
686 iswpaoui(const u_int8_t *frm)
688 return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
691 static int
692 wpa_driver_bsd_get_scan_results(void *priv,
693 struct wpa_scan_result *results,
694 size_t max_size)
696 #define min(a,b) ((a)>(b)?(b):(a))
697 struct wpa_driver_bsd_data *drv = priv;
698 uint8_t buf[24*1024];
699 uint8_t *cp, *vp;
700 struct ieee80211req_scan_result *sr;
701 struct wpa_scan_result *wsr;
702 int len, ielen, olen;
704 os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
706 len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
707 if (len < 0)
708 return -1;
709 olen = len;
710 cp = buf;
711 wsr = results;
712 while (len >= sizeof(struct ieee80211req_scan_result)) {
713 sr = (struct ieee80211req_scan_result *) cp;
714 os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
715 wsr->ssid_len = sr->isr_ssid_len;
716 wsr->freq = sr->isr_freq;
717 wsr->noise = sr->isr_noise;
718 wsr->qual = 0;
719 wsr->level = sr->isr_rssi;
720 wsr->caps = sr->isr_capinfo;
721 wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
722 vp = (u_int8_t *)(sr+1);
723 os_memcpy(wsr->ssid, vp, sr->isr_ssid_len);
724 if (sr->isr_ie_len > 0) {
725 vp += sr->isr_ssid_len;
726 ielen = sr->isr_ie_len;
727 while (ielen > 0) {
728 switch (vp[0]) {
729 case IEEE80211_ELEMID_VENDOR:
730 if (!iswpaoui(vp))
731 break;
732 wsr->wpa_ie_len =
733 min(2+vp[1], SSID_MAX_WPA_IE_LEN);
734 os_memcpy(wsr->wpa_ie, vp,
735 wsr->wpa_ie_len);
736 break;
737 case IEEE80211_ELEMID_RSN:
738 wsr->rsn_ie_len =
739 min(2+vp[1], SSID_MAX_WPA_IE_LEN);
740 os_memcpy(wsr->rsn_ie, vp,
741 wsr->rsn_ie_len);
742 break;
744 ielen -= 2+vp[1];
745 vp += 2+vp[1];
749 cp += sr->isr_len, len -= sr->isr_len;
750 wsr++;
752 qsort(results, wsr - results, sizeof(struct wpa_scan_result),
753 wpa_scan_result_compar);
755 wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
756 olen, wsr - results);
758 return wsr - results;
759 #undef min
762 static void *
763 wpa_driver_bsd_init(void *ctx, const char *ifname)
765 #define GETPARAM(drv, param, v) \
766 (((v) = get80211param(drv, param)) != -1)
767 struct wpa_driver_bsd_data *drv;
769 drv = os_zalloc(sizeof(*drv));
770 if (drv == NULL)
771 return NULL;
773 * NB: We require the interface name be mappable to an index.
774 * This implies we do not support having wpa_supplicant
775 * wait for an interface to appear. This seems ok; that
776 * doesn't belong here; it's really the job of devd.
778 drv->ifindex = if_nametoindex(ifname);
779 if (drv->ifindex == 0) {
780 wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
781 __func__, ifname);
782 goto fail1;
784 drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
785 if (drv->sock < 0)
786 goto fail1;
787 drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
788 if (drv->route < 0)
789 goto fail;
790 eloop_register_read_sock(drv->route,
791 wpa_driver_bsd_event_receive, ctx, drv);
793 drv->ctx = ctx;
794 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
796 if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
797 wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
798 __func__, strerror(errno));
799 goto fail;
801 if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
802 wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
803 __func__, strerror(errno));
804 goto fail;
806 if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
807 wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
808 __func__, strerror(errno));
809 goto fail;
811 if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
812 wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
813 "roaming: %s", __func__, strerror(errno));
814 goto fail;
817 if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
818 wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
819 __func__, strerror(errno));
820 goto fail;
823 return drv;
824 fail:
825 close(drv->sock);
826 fail1:
827 os_free(drv);
828 return NULL;
829 #undef GETPARAM
832 static void
833 wpa_driver_bsd_deinit(void *priv)
835 struct wpa_driver_bsd_data *drv = priv;
836 int flags;
838 eloop_unregister_read_sock(drv->route);
840 /* NB: mark interface down */
841 if (getifflags(drv, &flags) == 0)
842 (void) setifflags(drv, flags &~ IFF_UP);
844 wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
845 if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
846 wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
847 __func__);
849 (void) close(drv->route); /* ioctl socket */
850 (void) close(drv->sock); /* event socket */
851 os_free(drv);
855 const struct wpa_driver_ops wpa_driver_bsd_ops = {
856 .name = "bsd",
857 .desc = "BSD 802.11 support (Atheros, etc.)",
858 .init = wpa_driver_bsd_init,
859 .deinit = wpa_driver_bsd_deinit,
860 .get_bssid = wpa_driver_bsd_get_bssid,
861 .get_ssid = wpa_driver_bsd_get_ssid,
862 .set_wpa = wpa_driver_bsd_set_wpa,
863 .set_key = wpa_driver_bsd_set_key,
864 .set_countermeasures = wpa_driver_bsd_set_countermeasures,
865 .set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted,
866 .scan = wpa_driver_bsd_scan,
867 .get_scan_results = wpa_driver_bsd_get_scan_results,
868 .deauthenticate = wpa_driver_bsd_deauthenticate,
869 .disassociate = wpa_driver_bsd_disassociate,
870 .associate = wpa_driver_bsd_associate,
871 .set_auth_alg = wpa_driver_bsd_set_auth_alg,