1 /*
2  * WPA Supplicant - driver interaction with BSD net80211 layer
3  * Copyright (c) 2004, Sam Leffler <sam@errno.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 #include <sys/ioctl.h>
17 
18 #include "common.h"
19 #include "driver.h"
20 #include "eloop.h"
21 #include "ieee802_11_defs.h"
22 
23 #include <net/if.h>
24 
25 #ifdef __NetBSD__
26 #include <net/if_ether.h>
27 #define COMPAT_FREEBSD_NET80211
28 #else
29 #include <net/ethernet.h>
30 #endif
31 
32 #include <net80211/ieee80211.h>
33 #include <net80211/ieee80211_crypto.h>
34 #include <net80211/ieee80211_ioctl.h>
35 
36 struct wpa_driver_bsd_data {
37 	int	sock;			/* open socket for 802.11 ioctls */
38 	int	route;			/* routing socket for events */
39 	char	ifname[IFNAMSIZ+1];	/* interface name */
40 	unsigned int ifindex;		/* interface index */
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 */
45 };
46 
47 static int
48 set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
49 {
50 	struct ieee80211req ireq;
51 
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;
57 
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;
62 	}
63 	return 0;
64 }
65 
66 static int
67 get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
68 {
69 	struct ieee80211req ireq;
70 
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;
76 
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;
81 	}
82 	return ireq.i_len;
83 }
84 
85 static int
86 set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
87 {
88 	struct ieee80211req ireq;
89 
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;
94 
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;
99 	}
100 	return 0;
101 }
102 
103 static int
104 get80211param(struct wpa_driver_bsd_data *drv, int op)
105 {
106 	struct ieee80211req ireq;
107 
108 	os_memset(&ireq, 0, sizeof(ireq));
109 	os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
110 	ireq.i_type = op;
111 
112 	if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
113 		fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
114 			op, strerror(errno));
115 		return -1;
116 	}
117 	return ireq.i_val;
118 }
119 
120 static int
121 getifflags(struct wpa_driver_bsd_data *drv, int *flags)
122 {
123 	struct ifreq ifr;
124 
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;
130 	}
131 	*flags = ifr.ifr_flags & 0xffff;
132 	return 0;
133 }
134 
135 static int
136 setifflags(struct wpa_driver_bsd_data *drv, int flags)
137 {
138 	struct ifreq ifr;
139 
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;
146 	}
147 	return 0;
148 }
149 
150 static int
151 wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
152 {
153 	struct wpa_driver_bsd_data *drv = priv;
154 
155 	return get80211var(drv, IEEE80211_IOC_BSSID,
156 		bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
157 }
158 
159 #if 0
160 static int
161 wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
162 {
163 	struct wpa_driver_bsd_data *drv = priv;
164 
165 	return set80211var(drv, IEEE80211_IOC_BSSID,
166 		bssid, IEEE80211_ADDR_LEN);
167 }
168 #endif
169 
170 static int
171 wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
172 {
173 	struct wpa_driver_bsd_data *drv = priv;
174 
175 	return get80211var(drv, IEEE80211_IOC_SSID,
176 		ssid, IEEE80211_NWID_LEN);
177 }
178 
179 static int
180 wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid,
181 			     size_t ssid_len)
182 {
183 	struct wpa_driver_bsd_data *drv = priv;
184 
185 	return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
186 }
187 
188 static int
189 wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
190 	const u8 *wpa_ie, size_t wpa_ie_len)
191 {
192 	return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
193 }
194 
195 static int
196 wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
197 {
198 	struct wpa_driver_bsd_data *drv = priv;
199 	int ret = 0;
200 
201 	wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
202 		__FUNCTION__, wpa, privacy);
203 
204 	if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
205 		ret = -1;
206 	if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
207 		ret = -1;
208 	if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
209 		ret = -1;
210 
211 	return ret;
212 }
213 
214 static int
215 wpa_driver_bsd_set_wpa(void *priv, int enabled)
216 {
217 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
218 
219 	return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
220 }
221 
222 static int
223 wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
224 		       const unsigned char *addr)
225 {
226 	struct ieee80211req_del_key wk;
227 
228 	os_memset(&wk, 0, sizeof(wk));
229 	if (addr != NULL &&
230 	    bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) {
231 		struct ether_addr ea;
232 
233 		os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
234 		wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d",
235 			__func__, ether_ntoa(&ea), key_idx);
236 		os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
237 		wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE;
238 	} else {
239 		wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx);
240 		wk.idk_keyix = key_idx;
241 	}
242 	return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
243 }
244 
245 static int
246 wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
247 		       const unsigned char *addr, int key_idx, int set_tx,
248 		       const u8 *seq, size_t seq_len,
249 		       const u8 *key, size_t key_len)
250 {
251 	struct wpa_driver_bsd_data *drv = priv;
252 	struct ieee80211req_key wk;
253 	struct ether_addr ea;
254 	char *alg_name;
255 	u_int8_t cipher;
256 
257 	if (alg == WPA_ALG_NONE)
258 		return wpa_driver_bsd_del_key(drv, key_idx, addr);
259 
260 	switch (alg) {
261 	case WPA_ALG_WEP:
262 		alg_name = "WEP";
263 		cipher = IEEE80211_CIPHER_WEP;
264 		break;
265 	case WPA_ALG_TKIP:
266 		alg_name = "TKIP";
267 		cipher = IEEE80211_CIPHER_TKIP;
268 		break;
269 	case WPA_ALG_CCMP:
270 		alg_name = "CCMP";
271 		cipher = IEEE80211_CIPHER_AES_CCM;
272 		break;
273 	default:
274 		wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
275 			__func__, alg);
276 		return -1;
277 	}
278 
279 	os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
280 	wpa_printf(MSG_DEBUG,
281 		"%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
282 		__func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
283 		seq_len, key_len);
284 
285 	if (seq_len > sizeof(u_int64_t)) {
286 		wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
287 			__func__, seq_len);
288 		return -2;
289 	}
290 	if (key_len > sizeof(wk.ik_keydata)) {
291 		wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
292 			__func__, key_len);
293 		return -3;
294 	}
295 
296 	os_memset(&wk, 0, sizeof(wk));
297 	wk.ik_type = cipher;
298 	wk.ik_flags = IEEE80211_KEY_RECV;
299 	if (set_tx)
300 		wk.ik_flags |= IEEE80211_KEY_XMIT;
301 	os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
302 	/*
303 	 * Deduce whether group/global or unicast key by checking
304 	 * the address (yech).  Note also that we can only mark global
305 	 * keys default; doing this for a unicast key is an error.
306 	 */
307 	if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
308 		wk.ik_flags |= IEEE80211_KEY_GROUP;
309 		wk.ik_keyix = key_idx;
310 	} else {
311 		wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
312 	}
313 	if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
314 		wk.ik_flags |= IEEE80211_KEY_DEFAULT;
315 	wk.ik_keylen = key_len;
316 	os_memcpy(&wk.ik_keyrsc, seq, seq_len);
317 	os_memcpy(wk.ik_keydata, key, key_len);
318 
319 	return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
320 }
321 
322 static int
323 wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
324 {
325 	struct wpa_driver_bsd_data *drv = priv;
326 
327 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
328 	return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
329 }
330 
331 
332 static int
333 wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
334 {
335 	struct wpa_driver_bsd_data *drv = priv;
336 
337 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
338 	return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
339 }
340 
341 static int
342 wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
343 {
344 	struct wpa_driver_bsd_data *drv = priv;
345 	struct ieee80211req_mlme mlme;
346 
347 	wpa_printf(MSG_DEBUG, "%s", __func__);
348 	os_memset(&mlme, 0, sizeof(mlme));
349 	mlme.im_op = IEEE80211_MLME_DEAUTH;
350 	mlme.im_reason = reason_code;
351 	os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
352 	return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
353 }
354 
355 static int
356 wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
357 {
358 	struct wpa_driver_bsd_data *drv = priv;
359 	struct ieee80211req_mlme mlme;
360 
361 	wpa_printf(MSG_DEBUG, "%s", __func__);
362 	os_memset(&mlme, 0, sizeof(mlme));
363 	mlme.im_op = IEEE80211_MLME_DISASSOC;
364 	mlme.im_reason = reason_code;
365 	os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
366 	return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
367 }
368 
369 static int
370 wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
371 {
372 	struct wpa_driver_bsd_data *drv = priv;
373 	struct ieee80211req_mlme mlme;
374 	int privacy;
375 
376 	wpa_printf(MSG_DEBUG,
377 		"%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
378 		, __func__
379 		, params->ssid_len, params->ssid
380 		, params->wpa_ie_len
381 		, params->pairwise_suite
382 		, params->group_suite
383 		, params->key_mgmt_suite
384 	);
385 
386 	/* XXX error handling is wrong but unclear what to do... */
387 	if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
388 		return -1;
389 
390 	privacy = !(params->pairwise_suite == CIPHER_NONE &&
391 	    params->group_suite == CIPHER_NONE &&
392 	    params->key_mgmt_suite == KEY_MGMT_NONE &&
393 	    params->wpa_ie_len == 0);
394 	wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
395 
396 	if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
397 		return -1;
398 
399 	if (params->wpa_ie_len &&
400 	    set80211param(drv, IEEE80211_IOC_WPA,
401 			  params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
402 		return -1;
403 
404 	os_memset(&mlme, 0, sizeof(mlme));
405 	mlme.im_op = IEEE80211_MLME_ASSOC;
406 	if (params->ssid != NULL)
407 		os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
408 	mlme.im_ssid_len = params->ssid_len;
409 	if (params->bssid != NULL)
410 		os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
411 	if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
412 		return -1;
413 	return 0;
414 }
415 
416 static int
417 wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
418 {
419 	struct wpa_driver_bsd_data *drv = priv;
420 	int authmode;
421 
422 	if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
423 	    (auth_alg & AUTH_ALG_SHARED_KEY))
424 		authmode = IEEE80211_AUTH_AUTO;
425 	else if (auth_alg & AUTH_ALG_SHARED_KEY)
426 		authmode = IEEE80211_AUTH_SHARED;
427 	else
428 		authmode = IEEE80211_AUTH_OPEN;
429 
430 	return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
431 }
432 
433 static int
434 wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
435 {
436 	struct wpa_driver_bsd_data *drv = priv;
437 	int flags;
438 
439 	/* NB: interface must be marked UP to do a scan */
440 	if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
441 		return -1;
442 
443 	/* set desired ssid before scan */
444 	if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
445 		return -1;
446 
447 	/* NB: net80211 delivers a scan complete event so no need to poll */
448 	return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
449 }
450 
451 #include <net/route.h>
452 #if __FreeBSD__
453 #include <net80211/ieee80211_freebsd.h>
454 #endif
455 #if __NetBSD__
456 #include <net80211/ieee80211_netbsd.h>
457 #endif
458 
459 static void
460 wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
461 {
462 	struct wpa_driver_bsd_data *drv = sock_ctx;
463 	char buf[2048];
464 	struct if_announcemsghdr *ifan;
465 	struct if_msghdr *ifm;
466 	struct rt_msghdr *rtm;
467 	union wpa_event_data event;
468 	struct ieee80211_michael_event *mic;
469 	int n;
470 
471 	n = read(sock, buf, sizeof(buf));
472 	if (n < 0) {
473 		if (errno != EINTR && errno != EAGAIN)
474 			perror("read(PF_ROUTE)");
475 		return;
476 	}
477 
478 	rtm = (struct rt_msghdr *) buf;
479 	if (rtm->rtm_version != RTM_VERSION) {
480 		wpa_printf(MSG_DEBUG, "Routing message version %d not "
481 			"understood\n", rtm->rtm_version);
482 		return;
483 	}
484 	os_memset(&event, 0, sizeof(event));
485 	switch (rtm->rtm_type) {
486 	case RTM_IFANNOUNCE:
487 		ifan = (struct if_announcemsghdr *) rtm;
488 		if (ifan->ifan_index != drv->ifindex)
489 			break;
490 		strlcpy(event.interface_status.ifname, drv->ifname,
491 			sizeof(event.interface_status.ifname));
492 		switch (ifan->ifan_what) {
493 		case IFAN_DEPARTURE:
494 			event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
495 		default:
496 			return;
497 		}
498 		wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
499 			   event.interface_status.ifname,
500 			   ifan->ifan_what == IFAN_DEPARTURE ?
501 				"removed" : "added");
502 		wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
503 		break;
504 	case RTM_IEEE80211:
505 		ifan = (struct if_announcemsghdr *) rtm;
506 		if (ifan->ifan_index != drv->ifindex)
507 			break;
508 		switch (ifan->ifan_what) {
509 		case RTM_IEEE80211_ASSOC:
510 		case RTM_IEEE80211_REASSOC:
511 			wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
512 			break;
513 		case RTM_IEEE80211_DISASSOC:
514 			wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
515 			break;
516 		case RTM_IEEE80211_SCAN:
517 			wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
518 			break;
519 		case RTM_IEEE80211_REPLAY:
520 			/* ignore */
521 			break;
522 		case RTM_IEEE80211_MICHAEL:
523 			mic = (struct ieee80211_michael_event *) &ifan[1];
524 			wpa_printf(MSG_DEBUG,
525 				"Michael MIC failure wireless event: "
526 				"keyix=%u src_addr=" MACSTR, mic->iev_keyix,
527 				MAC2STR(mic->iev_src));
528 
529 			os_memset(&event, 0, sizeof(event));
530 			event.michael_mic_failure.unicast =
531 				!IEEE80211_IS_MULTICAST(mic->iev_dst);
532 			wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
533 				&event);
534 			break;
535 		}
536 		break;
537 	case RTM_IFINFO:
538 		ifm = (struct if_msghdr *) rtm;
539 		if (ifm->ifm_index != drv->ifindex)
540 			break;
541 		if ((rtm->rtm_flags & RTF_UP) == 0) {
542 			strlcpy(event.interface_status.ifname, drv->ifname,
543 				sizeof(event.interface_status.ifname));
544 			event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
545 			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
546 				   event.interface_status.ifname);
547 			wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
548 		}
549 		break;
550 	}
551 }
552 
553 /* Compare function for sorting scan results. Return >0 if @b is consider
554  * better. */
555 static int
556 wpa_scan_result_compar(const void *a, const void *b)
557 {
558 	const struct wpa_scan_result *wa = a;
559 	const struct wpa_scan_result *wb = b;
560 
561 	/* WPA/WPA2 support preferred */
562 	if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
563 	    !(wa->wpa_ie_len || wa->rsn_ie_len))
564 		return 1;
565 	if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
566 	    (wa->wpa_ie_len || wa->rsn_ie_len))
567 		return -1;
568 
569 	/* privacy support preferred */
570 	if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
571 	    (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
572 		return 1;
573 	if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
574 	    (wb->caps & IEEE80211_CAPINFO_PRIVACY))
575 		return -1;
576 
577 	/* best/max rate preferred if signal level close enough XXX */
578 	if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
579 		return wb->maxrate - wa->maxrate;
580 
581 	/* use freq for channel preference */
582 
583 	/* all things being equal, use signal level */
584 	return wb->level - wa->level;
585 }
586 
587 static int
588 getmaxrate(uint8_t rates[15], uint8_t nrates)
589 {
590 	int i, maxrate = -1;
591 
592 	for (i = 0; i < nrates; i++) {
593 		int rate = rates[i] & IEEE80211_RATE_VAL;
594 		if (rate > maxrate)
595 			rate = maxrate;
596 	}
597 	return maxrate;
598 }
599 
600 /* unalligned little endian access */
601 #define LE_READ_4(p)					\
602 	((u_int32_t)					\
603 	 ((((const u_int8_t *)(p))[0]      ) |		\
604 	  (((const u_int8_t *)(p))[1] <<  8) |		\
605 	  (((const u_int8_t *)(p))[2] << 16) |		\
606 	  (((const u_int8_t *)(p))[3] << 24)))
607 
608 static int __inline
609 iswpaoui(const u_int8_t *frm)
610 {
611 	return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
612 }
613 
614 static int
615 wpa_driver_bsd_get_scan_results(void *priv,
616 				     struct wpa_scan_result *results,
617 				     size_t max_size)
618 {
619 #define	min(a,b)	((a)>(b)?(b):(a))
620 	struct wpa_driver_bsd_data *drv = priv;
621 	uint8_t buf[24*1024];
622 	uint8_t *cp, *vp;
623 	struct ieee80211req_scan_result *sr;
624 	struct wpa_scan_result *wsr;
625 	int len, ielen;
626 
627 	os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
628 
629 	len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
630 	if (len < 0)
631 		return -1;
632 	cp = buf;
633 	wsr = results;
634 	while (len >= sizeof(struct ieee80211req_scan_result)) {
635 		sr = (struct ieee80211req_scan_result *) cp;
636 		os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
637 		wsr->ssid_len = sr->isr_ssid_len;
638 		wsr->freq = sr->isr_freq;
639 		wsr->noise = sr->isr_noise;
640 		wsr->qual = sr->isr_rssi;
641 		wsr->level = 0;		/* XXX? */
642 		wsr->caps = sr->isr_capinfo;
643 		wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
644 		vp = (u_int8_t *)(sr+1);
645 		os_memcpy(wsr->ssid, vp, sr->isr_ssid_len);
646 		if (sr->isr_ie_len > 0) {
647 			vp += sr->isr_ssid_len;
648 			ielen = sr->isr_ie_len;
649 			while (ielen > 0) {
650 				switch (vp[0]) {
651 				case IEEE80211_ELEMID_VENDOR:
652 					if (!iswpaoui(vp))
653 						break;
654 					wsr->wpa_ie_len =
655 					    min(2+vp[1], SSID_MAX_WPA_IE_LEN);
656 					os_memcpy(wsr->wpa_ie, vp,
657 						  wsr->wpa_ie_len);
658 					break;
659 				case IEEE80211_ELEMID_RSN:
660 					wsr->rsn_ie_len =
661 					    min(2+vp[1], SSID_MAX_WPA_IE_LEN);
662 					os_memcpy(wsr->rsn_ie, vp,
663 						  wsr->rsn_ie_len);
664 					break;
665 				}
666 				ielen -= 2+vp[1];
667 				vp += 2+vp[1];
668 			}
669 		}
670 
671 		cp += sr->isr_len, len -= sr->isr_len;
672 		wsr++;
673 	}
674 	qsort(results, wsr - results, sizeof(struct wpa_scan_result),
675 	      wpa_scan_result_compar);
676 
677 	wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
678 		   len, wsr - results);
679 
680 	return wsr - results;
681 #undef min
682 }
683 
684 static void *
685 wpa_driver_bsd_init(void *ctx, const char *ifname)
686 {
687 #define	GETPARAM(drv, param, v) \
688 	(((v) = get80211param(drv, param)) != -1)
689 	struct wpa_driver_bsd_data *drv;
690 
691 	drv = os_zalloc(sizeof(*drv));
692 	if (drv == NULL)
693 		return NULL;
694 	/*
695 	 * NB: We require the interface name be mappable to an index.
696 	 *     This implies we do not support having wpa_supplicant
697 	 *     wait for an interface to appear.  This seems ok; that
698 	 *     doesn't belong here; it's really the job of devd.
699 	 */
700 	drv->ifindex = if_nametoindex(ifname);
701 	if (drv->ifindex == 0) {
702 		wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
703 			   __func__, ifname);
704 		goto fail1;
705 	}
706 	drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
707 	if (drv->sock < 0)
708 		goto fail1;
709 	drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
710 	if (drv->route < 0)
711 		goto fail;
712 	eloop_register_read_sock(drv->route,
713 		wpa_driver_bsd_event_receive, ctx, drv);
714 
715 	drv->ctx = ctx;
716 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
717 
718 	if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
719 		wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
720 			__func__, strerror(errno));
721 		goto fail;
722 	}
723 	if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
724 		wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
725 			__func__, strerror(errno));
726 		goto fail;
727 	}
728 	if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
729 		wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
730 			__func__, strerror(errno));
731 		goto fail;
732 	}
733 	if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
734 		wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
735 			   "roaming: %s", __func__, strerror(errno));
736 		goto fail;
737 	}
738 
739 	if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
740 		wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
741 			   __func__, strerror(errno));
742 		goto fail;
743 	}
744 
745 	return drv;
746 fail:
747 	close(drv->sock);
748 fail1:
749 	os_free(drv);
750 	return NULL;
751 #undef GETPARAM
752 }
753 
754 static void
755 wpa_driver_bsd_deinit(void *priv)
756 {
757 	struct wpa_driver_bsd_data *drv = priv;
758 	int flags;
759 
760 	eloop_unregister_read_sock(drv->route);
761 
762 	/* NB: mark interface down */
763 	if (getifflags(drv, &flags) == 0)
764 		(void) setifflags(drv, flags &~ IFF_UP);
765 
766 	wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
767 	if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
768 		wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
769 			__func__);
770 
771 	(void) close(drv->route);		/* ioctl socket */
772 	(void) close(drv->sock);		/* event socket */
773 	os_free(drv);
774 }
775 
776 
777 const struct wpa_driver_ops wpa_driver_bsd_ops = {
778 	.name			= "bsd",
779 	.desc			= "BSD 802.11 support (Atheros, etc.)",
780 	.init			= wpa_driver_bsd_init,
781 	.deinit			= wpa_driver_bsd_deinit,
782 	.get_bssid		= wpa_driver_bsd_get_bssid,
783 	.get_ssid		= wpa_driver_bsd_get_ssid,
784 	.set_wpa		= wpa_driver_bsd_set_wpa,
785 	.set_key		= wpa_driver_bsd_set_key,
786 	.set_countermeasures	= wpa_driver_bsd_set_countermeasures,
787 	.set_drop_unencrypted	= wpa_driver_bsd_set_drop_unencrypted,
788 	.scan			= wpa_driver_bsd_scan,
789 	.get_scan_results	= wpa_driver_bsd_get_scan_results,
790 	.deauthenticate		= wpa_driver_bsd_deauthenticate,
791 	.disassociate		= wpa_driver_bsd_disassociate,
792 	.associate		= wpa_driver_bsd_associate,
793 	.set_auth_alg		= wpa_driver_bsd_set_auth_alg,
794 };
795