]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/drivers/driver_bsd.c
driver_bsd.c: Reduce code duplication (MLME)
[thirdparty/hostap.git] / src / drivers / driver_bsd.c
CommitLineData
6fc6879b
JM
1/*
2 * WPA Supplicant - driver interaction with BSD net80211 layer
3 * Copyright (c) 2004, Sam Leffler <sam@errno.com>
c5121837 4 * Copyright (c) 2004, 2Wire, Inc
6fc6879b
JM
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 "eloop.h"
90973fb2 22#include "common/ieee802_11_defs.h"
6fc6879b
JM
23
24#include <net/if.h>
5197244a 25#include <net/if_media.h>
898d6921
JR
26
27#ifdef __NetBSD__
28#include <net/if_ether.h>
898d6921 29#else
6fc6879b 30#include <net/ethernet.h>
898d6921 31#endif
131289d8 32#include <net/route.h>
6fc6879b 33
9b336bce
MH
34#ifdef __DragonFly__
35#include <netproto/802_11/ieee80211_ioctl.h>
36#include <netproto/802_11/ieee80211_dragonfly.h>
37#else /* __DragonFly__ */
6fc6879b 38#include <net80211/ieee80211.h>
6fc6879b 39#include <net80211/ieee80211_ioctl.h>
c610dba1 40#include <net80211/ieee80211_crypto.h>
9b336bce 41#endif /* __DragonFly__ */
131289d8
MH
42#if __FreeBSD__
43#include <net80211/ieee80211_freebsd.h>
44#endif
45#if __NetBSD__
46#include <net80211/ieee80211_netbsd.h>
47#endif
48
66d4085f
RM
49/* Generic functions for hostapd and wpa_supplicant */
50
51static int
52bsd_set80211var(int s, const char *ifname, int op, const void *arg, int arg_len)
53{
54 struct ieee80211req ireq;
55
56 os_memset(&ireq, 0, sizeof(ireq));
57 os_strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
58 ireq.i_type = op;
59 ireq.i_len = arg_len;
60 ireq.i_data = (void *) arg;
61
62 if (ioctl(s, SIOCS80211, &ireq) < 0) {
63 fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
64 op, arg_len, strerror(errno));
65 return -1;
66 }
67 return 0;
68}
69
70static int
71bsd_get80211var(int s, const char *ifname, int op, void *arg, int arg_len)
72{
73 struct ieee80211req ireq;
74
75 os_memset(&ireq, 0, sizeof(ireq));
76 os_strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
77 ireq.i_type = op;
78 ireq.i_len = arg_len;
79 ireq.i_data = arg;
80
81 if (ioctl(s, SIOCG80211, &ireq) < 0) {
82 fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
83 op, arg_len, strerror(errno));
84 return -1;
85 }
86 return ireq.i_len;
87}
88
89static int
90bsd_set80211param(int s, const char *ifname, int op, int arg)
91{
92 struct ieee80211req ireq;
93
94 os_memset(&ireq, 0, sizeof(ireq));
95 os_strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
96 ireq.i_type = op;
97 ireq.i_val = arg;
98
99 if (ioctl(s, SIOCS80211, &ireq) < 0) {
100 fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
101 op, arg, strerror(errno));
102 return -1;
103 }
104 return 0;
105}
106
107static int
108bsd_get_ssid(int s, const char *ifname, u8 *ssid)
109{
110#ifdef SIOCG80211NWID
111 struct ieee80211_nwid nwid;
112 struct ifreq ifr;
113
114 os_memset(&ifr, 0, sizeof(ifr));
115 os_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
116 ifr.ifr_data = (void *)&nwid;
117 if (ioctl(s, SIOCG80211NWID, &ifr) < 0 ||
118 nwid.i_len > IEEE80211_NWID_LEN)
119 return -1;
120 os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
121 return nwid.i_len;
122#else
123 return bsd_get80211var(s, ifname, IEEE80211_IOC_SSID,
124 ssid, IEEE80211_NWID_LEN);
125#endif
126}
127
128static int
129bsd_set_ssid(int s, const char *ifname, const u8 *ssid, size_t ssid_len)
130{
131#ifdef SIOCS80211NWID
132 struct ieee80211_nwid nwid;
133 struct ifreq ifr;
134
135 os_memcpy(nwid.i_nwid, ssid, ssid_len);
136 nwid.i_len = ssid_len;
137 os_memset(&ifr, 0, sizeof(ifr));
138 os_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
139 ifr.ifr_data = (void *)&nwid;
140 return ioctl(s, SIOCS80211NWID, &ifr);
141#else
142 return bsd_set80211var(s, ifname, IEEE80211_IOC_SSID, ssid, ssid_len);
143#endif
144}
145
5197244a
MH
146static int
147bsd_get_if_media(int s, const char *ifname)
148{
149 struct ifmediareq ifmr;
150
151 os_memset(&ifmr, 0, sizeof(ifmr));
152 os_strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
153
154 if (ioctl(s, SIOCGIFMEDIA, &ifmr) < 0) {
155 wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__,
156 strerror(errno));
157 return -1;
158 }
159
160 return ifmr.ifm_current;
161}
162
163static int
164bsd_set_if_media(int s, const char *ifname, int media)
165{
166 struct ifreq ifr;
167
168 os_memset(&ifr, 0, sizeof(ifr));
169 os_strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
170 ifr.ifr_media = media;
171
172 if (ioctl(s, SIOCSIFMEDIA, &ifr) < 0) {
173 wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__,
174 strerror(errno));
175 return -1;
176 }
177
178 return 0;
179}
180
181static int
182bsd_set_mediaopt(int s, const char *ifname, uint32_t mask, uint32_t mode)
183{
184 int media = bsd_get_if_media(s, ifname);
185
186 if (media < 0)
187 return -1;
188 media &= ~mask;
189 media |= mode;
190 if (bsd_set_if_media(s, ifname, media) < 0)
191 return -1;
192 return 0;
193}
194
cbdecd2b
MH
195static int
196bsd_del_key(int s, const char *ifname, const u8 *addr, int key_idx)
197{
198 struct ieee80211req_del_key wk;
199
200 os_memset(&wk, 0, sizeof(wk));
201 if (addr == NULL) {
202 wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx);
203 wk.idk_keyix = key_idx;
204 } else {
205 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__,
206 MAC2STR(addr));
207 os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
208 wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */
209 }
210
211 return bsd_set80211var(s, ifname, IEEE80211_IOC_DELKEY, &wk,
212 sizeof(wk));
213}
214
fa6b8afe
MH
215static int
216bsd_send_mlme_param(int s, const char *ifname, const u8 op, const u16 reason,
217 const u8 *addr)
218{
219 struct ieee80211req_mlme mlme;
220
221 os_memset(&mlme, 0, sizeof(mlme));
222 mlme.im_op = op;
223 mlme.im_reason = reason;
224 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
225 return bsd_set80211var(s, ifname, IEEE80211_IOC_MLME, &mlme,
226 sizeof(mlme));
227}
228
66d4085f 229
131289d8 230#ifdef HOSTAPD
6fc6879b 231
c5121837
JM
232/*
233 * Avoid conflicts with hostapd definitions by undefining couple of defines
234 * from net80211 header files.
235 */
236#undef RSN_VERSION
237#undef WPA_VERSION
238#undef WPA_OUI_TYPE
239
c5121837 240#include "l2_packet/l2_packet.h"
c5121837
JM
241
242struct bsd_driver_data {
243 struct hostapd_data *hapd; /* back pointer */
244
245 char iface[IFNAMSIZ + 1];
246 struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
247 int ioctl_sock; /* socket for ioctl() use */
248 int wext_sock; /* socket for wireless events */
249};
250
731723a5
JM
251static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
252 int reason_code);
c5121837
JM
253
254static int
255set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
256{
66d4085f 257 return bsd_set80211var(drv->ioctl_sock, drv->iface, op, arg, arg_len);
c5121837
JM
258}
259
260static int
261get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
262{
66d4085f 263 return bsd_get80211var(drv->ioctl_sock, drv->iface, op, arg, arg_len);
c5121837
JM
264}
265
266static int
267set80211param(struct bsd_driver_data *drv, int op, int arg)
268{
66d4085f 269 return bsd_set80211param(drv->ioctl_sock, drv->iface, op, arg);
c5121837
JM
270}
271
272static const char *
273ether_sprintf(const u8 *addr)
274{
275 static char buf[sizeof(MACSTR)];
276
277 if (addr != NULL)
278 snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
279 else
280 snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
281 return buf;
282}
283
284/*
285 * Configure WPA parameters.
286 */
287static int
af586419 288bsd_configure_wpa(struct bsd_driver_data *drv, struct wpa_bss_params *params)
c5121837
JM
289{
290 static const char *ciphernames[] =
291 { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
c5121837
JM
292 int v;
293
af586419 294 switch (params->wpa_group) {
c5121837
JM
295 case WPA_CIPHER_CCMP:
296 v = IEEE80211_CIPHER_AES_CCM;
297 break;
298 case WPA_CIPHER_TKIP:
299 v = IEEE80211_CIPHER_TKIP;
300 break;
301 case WPA_CIPHER_WEP104:
302 v = IEEE80211_CIPHER_WEP;
303 break;
304 case WPA_CIPHER_WEP40:
305 v = IEEE80211_CIPHER_WEP;
306 break;
307 case WPA_CIPHER_NONE:
308 v = IEEE80211_CIPHER_NONE;
309 break;
310 default:
311 printf("Unknown group key cipher %u\n",
af586419 312 params->wpa_group);
c5121837
JM
313 return -1;
314 }
315 wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
316 __func__, ciphernames[v], v);
317 if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) {
318 printf("Unable to set group key cipher to %u (%s)\n",
319 v, ciphernames[v]);
320 return -1;
321 }
322 if (v == IEEE80211_CIPHER_WEP) {
323 /* key length is done only for specific ciphers */
af586419 324 v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
c5121837
JM
325 if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) {
326 printf("Unable to set group key length to %u\n", v);
327 return -1;
328 }
329 }
330
331 v = 0;
af586419 332 if (params->wpa_pairwise & WPA_CIPHER_CCMP)
c5121837 333 v |= 1<<IEEE80211_CIPHER_AES_CCM;
af586419 334 if (params->wpa_pairwise & WPA_CIPHER_TKIP)
c5121837 335 v |= 1<<IEEE80211_CIPHER_TKIP;
af586419 336 if (params->wpa_pairwise & WPA_CIPHER_NONE)
c5121837
JM
337 v |= 1<<IEEE80211_CIPHER_NONE;
338 wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
339 if (set80211param(drv, IEEE80211_IOC_UCASTCIPHERS, v)) {
340 printf("Unable to set pairwise key ciphers to 0x%x\n", v);
341 return -1;
342 }
343
344 wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
af586419
JM
345 __func__, params->wpa_key_mgmt);
346 if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, params->wpa_key_mgmt))
347 {
c5121837 348 printf("Unable to set key management algorithms to 0x%x\n",
af586419 349 params->wpa_key_mgmt);
c5121837
JM
350 return -1;
351 }
352
353 v = 0;
af586419 354 if (params->rsn_preauth)
c5121837
JM
355 v |= BIT(0);
356 wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
af586419 357 __func__, params->rsn_preauth);
c5121837
JM
358 if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) {
359 printf("Unable to set RSN capabilities to 0x%x\n", v);
360 return -1;
361 }
362
af586419
JM
363 wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa);
364 if (set80211param(drv, IEEE80211_IOC_WPA, params->wpa)) {
365 printf("Unable to set WPA to %u\n", params->wpa);
c5121837
JM
366 return -1;
367 }
368 return 0;
369}
370
371
372static int
373bsd_set_iface_flags(void *priv, int dev_up)
374{
375 struct bsd_driver_data *drv = priv;
376 struct ifreq ifr;
377
378 wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
379
380 if (drv->ioctl_sock < 0)
381 return -1;
382
383 memset(&ifr, 0, sizeof(ifr));
66d4085f 384 os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
c5121837
JM
385
386 if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
387 perror("ioctl[SIOCGIFFLAGS]");
388 return -1;
389 }
390
391 if (dev_up)
392 ifr.ifr_flags |= IFF_UP;
393 else
394 ifr.ifr_flags &= ~IFF_UP;
395
396 if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
397 perror("ioctl[SIOCSIFFLAGS]");
398 return -1;
399 }
400
c5121837
JM
401 return 0;
402}
403
404static int
e3bd3912 405bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
c5121837
JM
406{
407 struct bsd_driver_data *drv = priv;
c5121837 408
af586419 409 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled);
c5121837 410
af586419 411 if (!params->enabled) {
c5121837
JM
412 /* XXX restore state */
413 return set80211param(priv, IEEE80211_IOC_AUTHMODE,
414 IEEE80211_AUTH_AUTO);
415 }
af586419
JM
416 if (!params->wpa && !params->ieee802_1x) {
417 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
c5121837
JM
418 HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
419 return -1;
420 }
c9b9e494 421 if (params->wpa && bsd_configure_wpa(drv, params) != 0) {
af586419 422 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
c5121837
JM
423 HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
424 return -1;
425 }
426 if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
af586419
JM
427 (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
428 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
c5121837
JM
429 HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
430 return -1;
431 }
432 return bsd_set_iface_flags(priv, 1);
433}
434
435static int
436bsd_set_privacy(const char *ifname, void *priv, int enabled)
437{
438 struct bsd_driver_data *drv = priv;
439
440 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
441
442 return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);
443}
444
445static int
446bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized)
447{
448 struct bsd_driver_data *drv = priv;
c5121837 449
fa6b8afe
MH
450 return bsd_send_mlme_param(drv->ioctl_sock, drv->iface, authorized ?
451 IEEE80211_MLME_AUTHORIZE :
452 IEEE80211_MLME_UNAUTHORIZE, 0, addr);
c5121837
JM
453}
454
455static int
456bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or,
457 int flags_and)
458{
459 /* For now, only support setting Authorized flag */
0de39516 460 if (flags_or & WPA_STA_AUTHORIZED)
c5121837 461 return bsd_set_sta_authorized(priv, addr, 1);
0de39516 462 if (!(flags_and & WPA_STA_AUTHORIZED))
c5121837
JM
463 return bsd_set_sta_authorized(priv, addr, 0);
464 return 0;
465}
466
c5121837 467static int
71934751 468bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
c5121837
JM
469 const u8 *addr, int key_idx, int set_tx, const u8 *seq,
470 size_t seq_len, const u8 *key, size_t key_len)
471{
472 struct bsd_driver_data *drv = priv;
473 struct ieee80211req_key wk;
474 u_int8_t cipher;
475
476 if (alg == WPA_ALG_NONE)
cbdecd2b 477 return bsd_del_key(drv->ioctl_sock, drv->iface, addr, key_idx);
c5121837
JM
478
479 wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d",
480 __func__, alg, ether_sprintf(addr), key_idx);
481
482 if (alg == WPA_ALG_WEP)
483 cipher = IEEE80211_CIPHER_WEP;
484 else if (alg == WPA_ALG_TKIP)
485 cipher = IEEE80211_CIPHER_TKIP;
486 else if (alg == WPA_ALG_CCMP)
487 cipher = IEEE80211_CIPHER_AES_CCM;
488 else {
489 printf("%s: unknown/unsupported algorithm %d\n",
490 __func__, alg);
491 return -1;
492 }
493
494 if (key_len > sizeof(wk.ik_keydata)) {
92e63aaf 495 printf("%s: key length %d too big\n", __func__, (int) key_len);
c5121837
JM
496 return -3;
497 }
498
499 memset(&wk, 0, sizeof(wk));
500 wk.ik_type = cipher;
501 wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
502 if (addr == NULL) {
503 memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
504 wk.ik_keyix = key_idx;
505 wk.ik_flags |= IEEE80211_KEY_DEFAULT;
506 } else {
507 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
508 wk.ik_keyix = IEEE80211_KEYIX_NONE;
509 }
510 wk.ik_keylen = key_len;
511 memcpy(wk.ik_keydata, key, key_len);
512
513 return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
514}
515
516
517static int
518bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
519 u8 *seq)
520{
521 struct bsd_driver_data *drv = priv;
522 struct ieee80211req_key wk;
523
524 wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
525 __func__, ether_sprintf(addr), idx);
526
527 memset(&wk, 0, sizeof(wk));
528 if (addr == NULL)
529 memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
530 else
531 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
532 wk.ik_keyix = idx;
533
534 if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
535 printf("Failed to get encryption.\n");
536 return -1;
537 }
538
539#ifdef WORDS_BIGENDIAN
540 {
541 /*
542 * wk.ik_keytsc is in host byte order (big endian), need to
543 * swap it to match with the byte order used in WPA.
544 */
545 int i;
546 u8 tmp[WPA_KEY_RSC_LEN];
547 memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
548 for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
549 seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
550 }
551 }
552#else /* WORDS_BIGENDIAN */
553 memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
554#endif /* WORDS_BIGENDIAN */
555 return 0;
556}
557
558
559static int
560bsd_flush(void *priv)
561{
562 u8 allsta[IEEE80211_ADDR_LEN];
563
564 memset(allsta, 0xff, IEEE80211_ADDR_LEN);
731723a5 565 return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE);
c5121837
JM
566}
567
568
569static int
570bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
571 const u8 *addr)
572{
573 struct bsd_driver_data *drv = priv;
574 struct ieee80211req_sta_stats stats;
575
576 memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
577 if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) {
578 /* XXX? do packets counts include non-data frames? */
579 data->rx_packets = stats.is_stats.ns_rx_data;
580 data->rx_bytes = stats.is_stats.ns_rx_bytes;
581 data->tx_packets = stats.is_stats.ns_tx_data;
582 data->tx_bytes = stats.is_stats.ns_tx_bytes;
583 }
584 return 0;
585}
586
587static int
588bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
589{
590 /*
591 * Do nothing; we setup parameters at startup that define the
592 * contents of the beacon information element.
593 */
594 return 0;
595}
596
597static int
731723a5 598bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code)
c5121837
JM
599{
600 struct bsd_driver_data *drv = priv;
c5121837 601
fa6b8afe
MH
602 return bsd_send_mlme_param(drv->ioctl_sock, drv->iface,
603 IEEE80211_MLME_DEAUTH, reason_code, addr);
c5121837
JM
604}
605
606static int
731723a5
JM
607bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
608 int reason_code)
c5121837
JM
609{
610 struct bsd_driver_data *drv = priv;
c5121837 611
fa6b8afe
MH
612 return bsd_send_mlme_param(drv->ioctl_sock, drv->iface,
613 IEEE80211_MLME_DISASSOC, reason_code, addr);
c5121837
JM
614}
615
1d041bec 616static void
c5121837
JM
617bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
618{
619 struct hostapd_data *hapd = drv->hapd;
620 struct ieee80211req_wpaie ie;
621 int ielen = 0;
622 u8 *iebuf = NULL;
623
624 /*
625 * Fetch and validate any negotiated WPA/RSN parameters.
626 */
627 memset(&ie, 0, sizeof(ie));
628 memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
629 if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
630 printf("Failed to get WPA/RSN information element.\n");
631 goto no_ie;
632 }
633 iebuf = ie.wpa_ie;
634 ielen = ie.wpa_ie[1];
635 if (ielen == 0)
636 iebuf = NULL;
637 else
638 ielen += 2;
639
640no_ie:
1d041bec 641 drv_event_assoc(hapd, addr, iebuf, ielen);
c5121837
JM
642}
643
c5121837
JM
644static void
645bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
646{
647 struct bsd_driver_data *drv = ctx;
c5121837
JM
648 char buf[2048];
649 struct if_announcemsghdr *ifan;
650 struct rt_msghdr *rtm;
651 struct ieee80211_michael_event *mic;
652 struct ieee80211_join_event *join;
653 struct ieee80211_leave_event *leave;
654 int n;
1cd973d5 655 union wpa_event_data data;
c5121837
JM
656
657 n = read(sock, buf, sizeof(buf));
658 if (n < 0) {
659 if (errno != EINTR && errno != EAGAIN)
660 perror("read(PF_ROUTE)");
661 return;
662 }
663
664 rtm = (struct rt_msghdr *) buf;
665 if (rtm->rtm_version != RTM_VERSION) {
666 wpa_printf(MSG_DEBUG, "Routing message version %d not "
667 "understood\n", rtm->rtm_version);
668 return;
669 }
670 ifan = (struct if_announcemsghdr *) rtm;
671 switch (rtm->rtm_type) {
672 case RTM_IEEE80211:
673 switch (ifan->ifan_what) {
674 case RTM_IEEE80211_ASSOC:
675 case RTM_IEEE80211_REASSOC:
676 case RTM_IEEE80211_DISASSOC:
677 case RTM_IEEE80211_SCAN:
678 break;
679 case RTM_IEEE80211_LEAVE:
680 leave = (struct ieee80211_leave_event *) &ifan[1];
69378b79 681 drv_event_disassoc(drv->hapd, leave->iev_addr);
c5121837
JM
682 break;
683 case RTM_IEEE80211_JOIN:
684#ifdef RTM_IEEE80211_REJOIN
685 case RTM_IEEE80211_REJOIN:
686#endif
687 join = (struct ieee80211_join_event *) &ifan[1];
688 bsd_new_sta(drv, join->iev_addr);
689 break;
690 case RTM_IEEE80211_REPLAY:
691 /* ignore */
692 break;
693 case RTM_IEEE80211_MICHAEL:
694 mic = (struct ieee80211_michael_event *) &ifan[1];
695 wpa_printf(MSG_DEBUG,
696 "Michael MIC failure wireless event: "
697 "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
698 MAC2STR(mic->iev_src));
1cd973d5
JM
699 os_memset(&data, 0, sizeof(data));
700 data.michael_mic_failure.unicast = 1;
701 data.michael_mic_failure.src = mic->iev_src;
702 wpa_supplicant_event(drv->hapd,
703 EVENT_MICHAEL_MIC_FAILURE, &data);
c5121837
JM
704 break;
705 }
706 break;
707 }
708}
709
710static int
711bsd_wireless_event_init(struct bsd_driver_data *drv)
712{
713 int s;
714
715 drv->wext_sock = -1;
716
717 s = socket(PF_ROUTE, SOCK_RAW, 0);
718 if (s < 0) {
719 perror("socket(PF_ROUTE,SOCK_RAW)");
720 return -1;
721 }
722 eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL);
723 drv->wext_sock = s;
724
725 return 0;
726}
727
728static void
729bsd_wireless_event_deinit(struct bsd_driver_data *drv)
730{
731 if (drv->wext_sock < 0)
732 return;
733 eloop_unregister_read_sock(drv->wext_sock);
734 close(drv->wext_sock);
735}
736
737
738static int
739bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
740 int encrypt, const u8 *own_addr)
741{
742 struct bsd_driver_data *drv = priv;
11386396 743 unsigned char *bp;
c5121837
JM
744 struct l2_ethhdr *eth;
745 size_t len;
746 int status;
747
748 /*
11386396 749 * Prepend the Ethernet header. If the caller left us
c5121837
JM
750 * space at the front we could just insert it but since
751 * we don't know we copy to a local buffer. Given the frequency
752 * and size of frames this probably doesn't matter.
753 */
754 len = data_len + sizeof(struct l2_ethhdr);
11386396
MH
755 bp = os_zalloc(len);
756 if (bp == NULL) {
757 wpa_printf(MSG_ERROR, "malloc() failed for bsd_send_eapol"
758 "(len=%lu)", (unsigned long) len);
759 return -1;
c5121837
JM
760 }
761 eth = (struct l2_ethhdr *) bp;
11386396
MH
762 os_memcpy(eth->h_dest, addr, ETH_ALEN);
763 os_memcpy(eth->h_source, own_addr, ETH_ALEN);
c5121837 764 eth->h_proto = htons(ETH_P_EAPOL);
11386396 765 os_memcpy(eth + 1, data, data_len);
c5121837
JM
766
767 wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
768
769 status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
770
11386396 771 os_free(bp);
c5121837
JM
772 return status;
773}
774
775static void
776handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
777{
778 struct bsd_driver_data *drv = ctx;
baac6490
JM
779 drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
780 len - sizeof(struct l2_ethhdr));
c5121837
JM
781}
782
783static int
66d4085f 784hostapd_bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
c5121837
JM
785{
786 struct bsd_driver_data *drv = priv;
66d4085f 787 int ssid_len;
c5121837 788
66d4085f 789 ssid_len = bsd_get_ssid(drv->ioctl_sock, drv->iface, buf);
c5121837
JM
790 wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);
791
792 return ssid_len;
793}
794
795static int
66d4085f 796hostapd_bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
c5121837
JM
797{
798 struct bsd_driver_data *drv = priv;
799
800 wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf);
801
66d4085f 802 return bsd_set_ssid(drv->ioctl_sock, drv->iface, buf, len);
c5121837
JM
803}
804
5197244a
MH
805static int
806bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
807{
808 struct bsd_driver_data *drv = priv;
809 struct ieee80211chanreq creq;
810 uint32_t mode;
811
812 if (freq->channel < 14)
813 mode = IFM_IEEE80211_11G;
814 else if (freq->channel == 14)
815 mode = IFM_IEEE80211_11B;
816 else
817 mode = IFM_IEEE80211_11A;
818 if (bsd_set_mediaopt(drv->ioctl_sock, drv->iface, IFM_MMASK,
819 mode) < 0) {
820 wpa_printf(MSG_ERROR, "%s: failed to set modulation mode",
821 __func__);
822 return -1;
823 }
824
825 os_memset(&creq, 0, sizeof(creq));
826 os_strlcpy(creq.i_name, drv->iface, sizeof(creq.i_name));
827 creq.i_channel = freq->channel;
828 return ioctl(drv->ioctl_sock, SIOCS80211CHANNEL, &creq);
829}
830
c5121837 831static void *
92f475b4 832bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
c5121837
JM
833{
834 struct bsd_driver_data *drv;
835
836 drv = os_zalloc(sizeof(struct bsd_driver_data));
837 if (drv == NULL) {
838 printf("Could not allocate memory for bsd driver data\n");
839 goto bad;
840 }
841
842 drv->hapd = hapd;
843 drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
844 if (drv->ioctl_sock < 0) {
845 perror("socket[PF_INET,SOCK_DGRAM]");
846 goto bad;
847 }
412036f5 848 memcpy(drv->iface, params->ifname, sizeof(drv->iface));
c5121837
JM
849
850 drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
851 handle_read, drv, 1);
852 if (drv->sock_xmit == NULL)
853 goto bad;
412036f5 854 if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr))
c5121837
JM
855 goto bad;
856
857 bsd_set_iface_flags(drv, 0); /* mark down during setup */
858 if (bsd_wireless_event_init(drv))
859 goto bad;
860
5197244a
MH
861 if (bsd_set_mediaopt(drv->ioctl_sock, drv->iface, IFM_OMASK,
862 IFM_IEEE80211_HOSTAP) < 0) {
863 wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
864 __func__);
865 goto bad;
866 }
867
c5121837
JM
868 return drv;
869bad:
870 if (drv->sock_xmit != NULL)
871 l2_packet_deinit(drv->sock_xmit);
872 if (drv->ioctl_sock >= 0)
873 close(drv->ioctl_sock);
874 if (drv != NULL)
82f36163 875 os_free(drv);
c5121837
JM
876 return NULL;
877}
878
879
880static void
881bsd_deinit(void *priv)
882{
883 struct bsd_driver_data *drv = priv;
884
885 bsd_wireless_event_deinit(drv);
886 (void) bsd_set_iface_flags(drv, 0);
887 if (drv->ioctl_sock >= 0)
888 close(drv->ioctl_sock);
889 if (drv->sock_xmit != NULL)
890 l2_packet_deinit(drv->sock_xmit);
82f36163 891 os_free(drv);
c5121837
JM
892}
893
894const struct wpa_driver_ops wpa_driver_bsd_ops = {
895 .name = "bsd",
896 .hapd_init = bsd_init,
897 .hapd_deinit = bsd_deinit,
898 .set_ieee8021x = bsd_set_ieee8021x,
899 .set_privacy = bsd_set_privacy,
642187d6 900 .set_key = bsd_set_key,
c5121837
JM
901 .get_seqnum = bsd_get_seqnum,
902 .flush = bsd_flush,
903 .set_generic_elem = bsd_set_opt_ie,
904 .sta_set_flags = bsd_sta_set_flags,
905 .read_sta_data = bsd_read_sta_driver_data,
906 .hapd_send_eapol = bsd_send_eapol,
907 .sta_disassoc = bsd_sta_disassoc,
908 .sta_deauth = bsd_sta_deauth,
66d4085f
RM
909 .hapd_set_ssid = hostapd_bsd_set_ssid,
910 .hapd_get_ssid = hostapd_bsd_get_ssid,
5197244a 911 .set_freq = bsd_set_freq,
c5121837
JM
912};
913
914#else /* HOSTAPD */
915
6fc6879b
JM
916struct wpa_driver_bsd_data {
917 int sock; /* open socket for 802.11 ioctls */
918 int route; /* routing socket for events */
919 char ifname[IFNAMSIZ+1]; /* interface name */
920 unsigned int ifindex; /* interface index */
921 void *ctx;
922 int prev_roaming; /* roaming state to restore on deinit */
923 int prev_privacy; /* privacy state to restore on deinit */
924 int prev_wpa; /* wpa state to restore on deinit */
925};
926
927static int
928set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
929{
66d4085f 930 return bsd_set80211var(drv->sock, drv->ifname, op, arg, arg_len);
6fc6879b
JM
931}
932
933static int
934get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
935{
66d4085f 936 return bsd_get80211var(drv->sock, drv->ifname, op, arg, arg_len);
6fc6879b
JM
937}
938
939static int
940set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
941{
66d4085f 942 return bsd_set80211param(drv->sock, drv->ifname, op, arg);
6fc6879b
JM
943}
944
945static int
946get80211param(struct wpa_driver_bsd_data *drv, int op)
947{
948 struct ieee80211req ireq;
949
950 os_memset(&ireq, 0, sizeof(ireq));
66d4085f 951 os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
6fc6879b
JM
952 ireq.i_type = op;
953
954 if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
955 fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
956 op, strerror(errno));
957 return -1;
958 }
959 return ireq.i_val;
960}
961
962static int
963getifflags(struct wpa_driver_bsd_data *drv, int *flags)
964{
965 struct ifreq ifr;
966
967 os_memset(&ifr, 0, sizeof(ifr));
968 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
969 if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
970 perror("SIOCGIFFLAGS");
971 return errno;
972 }
973 *flags = ifr.ifr_flags & 0xffff;
974 return 0;
975}
976
977static int
978setifflags(struct wpa_driver_bsd_data *drv, int flags)
979{
980 struct ifreq ifr;
981
982 os_memset(&ifr, 0, sizeof(ifr));
983 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
984 ifr.ifr_flags = flags & 0xffff;
985 if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
986 perror("SIOCSIFFLAGS");
987 return errno;
988 }
989 return 0;
990}
991
992static int
993wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
994{
995 struct wpa_driver_bsd_data *drv = priv;
66d4085f 996#ifdef SIOCG80211BSSID
a65f4a57 997 struct ieee80211_bssid bs;
6fc6879b 998
a65f4a57
MH
999 os_strncpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
1000 if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
1001 return -1;
1002 os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
1003 return 0;
1004#else
6fc6879b
JM
1005 return get80211var(drv, IEEE80211_IOC_BSSID,
1006 bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
a65f4a57 1007#endif
6fc6879b
JM
1008}
1009
1010#if 0
1011static int
1012wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
1013{
1014 struct wpa_driver_bsd_data *drv = priv;
1015
1016 return set80211var(drv, IEEE80211_IOC_BSSID,
1017 bssid, IEEE80211_ADDR_LEN);
1018}
1019#endif
1020
1021static int
1022wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
1023{
1024 struct wpa_driver_bsd_data *drv = priv;
1025
66d4085f 1026 return bsd_get_ssid(drv->sock, drv->ifname, ssid);
6fc6879b
JM
1027}
1028
1029static int
4df91b3f 1030wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid,
6fc6879b
JM
1031 size_t ssid_len)
1032{
1033 struct wpa_driver_bsd_data *drv = priv;
1034
66d4085f 1035 return bsd_set_ssid(drv->sock, drv->ifname, ssid, ssid_len);
6fc6879b
JM
1036}
1037
1038static int
1039wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
4df91b3f 1040 const u8 *wpa_ie, size_t wpa_ie_len)
6fc6879b 1041{
c610dba1
MH
1042#ifdef IEEE80211_IOC_APPIE
1043 return set80211var(drv, IEEE80211_IOC_APPIE, wpa_ie, wpa_ie_len);
1044#else /* IEEE80211_IOC_APPIE */
6fc6879b 1045 return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
c610dba1 1046#endif /* IEEE80211_IOC_APPIE */
6fc6879b
JM
1047}
1048
1049static int
1050wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
1051{
1052 struct wpa_driver_bsd_data *drv = priv;
1053 int ret = 0;
1054
1055 wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
1056 __FUNCTION__, wpa, privacy);
1057
1058 if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
1059 ret = -1;
1060 if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
1061 ret = -1;
1062 if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
1063 ret = -1;
1064
1065 return ret;
1066}
1067
1068static int
1069wpa_driver_bsd_set_wpa(void *priv, int enabled)
1070{
1071 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
1072
1073 return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
1074}
1075
6fc6879b 1076static int
71934751 1077wpa_driver_bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
6fc6879b
JM
1078 const unsigned char *addr, int key_idx, int set_tx,
1079 const u8 *seq, size_t seq_len,
1080 const u8 *key, size_t key_len)
1081{
1082 struct wpa_driver_bsd_data *drv = priv;
1083 struct ieee80211req_key wk;
1084 struct ether_addr ea;
1085 char *alg_name;
1086 u_int8_t cipher;
1087
1088 if (alg == WPA_ALG_NONE)
cbdecd2b
MH
1089 return bsd_del_key(drv->sock, drv->ifname,
1090 os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
1091 IEEE80211_ADDR_LEN) == 0 ? NULL : addr,
1092 key_idx);
6fc6879b
JM
1093
1094 switch (alg) {
1095 case WPA_ALG_WEP:
1096 alg_name = "WEP";
1097 cipher = IEEE80211_CIPHER_WEP;
1098 break;
1099 case WPA_ALG_TKIP:
1100 alg_name = "TKIP";
1101 cipher = IEEE80211_CIPHER_TKIP;
1102 break;
1103 case WPA_ALG_CCMP:
1104 alg_name = "CCMP";
1105 cipher = IEEE80211_CIPHER_AES_CCM;
1106 break;
1107 default:
1108 wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
1109 __func__, alg);
1110 return -1;
1111 }
1112
1113 os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
1114 wpa_printf(MSG_DEBUG,
1115 "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
1116 __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
1117 seq_len, key_len);
1118
1119 if (seq_len > sizeof(u_int64_t)) {
1120 wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
1121 __func__, seq_len);
1122 return -2;
1123 }
1124 if (key_len > sizeof(wk.ik_keydata)) {
1125 wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
1126 __func__, key_len);
1127 return -3;
1128 }
1129
1130 os_memset(&wk, 0, sizeof(wk));
1131 wk.ik_type = cipher;
1132 wk.ik_flags = IEEE80211_KEY_RECV;
1133 if (set_tx)
1134 wk.ik_flags |= IEEE80211_KEY_XMIT;
1135 os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
1136 /*
1137 * Deduce whether group/global or unicast key by checking
1138 * the address (yech). Note also that we can only mark global
1139 * keys default; doing this for a unicast key is an error.
1140 */
1141 if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
1142 wk.ik_flags |= IEEE80211_KEY_GROUP;
1143 wk.ik_keyix = key_idx;
1144 } else {
1145 wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
1146 }
1147 if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
1148 wk.ik_flags |= IEEE80211_KEY_DEFAULT;
1149 wk.ik_keylen = key_len;
1150 os_memcpy(&wk.ik_keyrsc, seq, seq_len);
1151 os_memcpy(wk.ik_keydata, key, key_len);
1152
1153 return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
1154}
1155
1156static int
1157wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
1158{
1159 struct wpa_driver_bsd_data *drv = priv;
1160
1161 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
1162 return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
1163}
1164
1165
1166static int
1167wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
1168{
1169 struct wpa_driver_bsd_data *drv = priv;
1170
1171 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
1172 return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
1173}
1174
1175static int
1176wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
1177{
1178 struct wpa_driver_bsd_data *drv = priv;
6fc6879b 1179
fa6b8afe
MH
1180 return bsd_send_mlme_param(drv->sock, drv->ifname,
1181 IEEE80211_MLME_DEAUTH, reason_code, addr);
6fc6879b
JM
1182}
1183
1184static int
1185wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
1186{
1187 struct wpa_driver_bsd_data *drv = priv;
6fc6879b 1188
fa6b8afe
MH
1189 return bsd_send_mlme_param(drv->sock, drv->ifname,
1190 IEEE80211_MLME_DISASSOC, reason_code, addr);
6fc6879b
JM
1191}
1192
2a91091e
MH
1193static int
1194wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
1195{
1196 struct wpa_driver_bsd_data *drv = priv;
1197 int authmode;
1198
abd9fafa
JM
1199 if ((auth_alg & WPA_AUTH_ALG_OPEN) &&
1200 (auth_alg & WPA_AUTH_ALG_SHARED))
2a91091e 1201 authmode = IEEE80211_AUTH_AUTO;
abd9fafa 1202 else if (auth_alg & WPA_AUTH_ALG_SHARED)
2a91091e
MH
1203 authmode = IEEE80211_AUTH_SHARED;
1204 else
1205 authmode = IEEE80211_AUTH_OPEN;
1206
1207 return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
1208}
1209
6fc6879b
JM
1210static int
1211wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
1212{
1213 struct wpa_driver_bsd_data *drv = priv;
1214 struct ieee80211req_mlme mlme;
1215 int privacy;
4a867032 1216 int ret = 0;
6fc6879b
JM
1217
1218 wpa_printf(MSG_DEBUG,
1219 "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
1220 , __func__
92e63aaf
JM
1221 , (unsigned int) params->ssid_len, params->ssid
1222 , (unsigned int) params->wpa_ie_len
6fc6879b
JM
1223 , params->pairwise_suite
1224 , params->group_suite
1225 , params->key_mgmt_suite
1226 );
1227
4a867032
JM
1228 if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted)
1229 < 0)
1230 ret = -1;
1231 if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0)
1232 ret = -1;
6fc6879b
JM
1233 /* XXX error handling is wrong but unclear what to do... */
1234 if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
1235 return -1;
6fc6879b
JM
1236
1237 privacy = !(params->pairwise_suite == CIPHER_NONE &&
1238 params->group_suite == CIPHER_NONE &&
1239 params->key_mgmt_suite == KEY_MGMT_NONE &&
1240 params->wpa_ie_len == 0);
1241 wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
1242
1243 if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
1244 return -1;
1245
1246 if (params->wpa_ie_len &&
1247 set80211param(drv, IEEE80211_IOC_WPA,
1248 params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
1249 return -1;
1250
1251 os_memset(&mlme, 0, sizeof(mlme));
1252 mlme.im_op = IEEE80211_MLME_ASSOC;
6fc6879b
JM
1253 if (params->ssid != NULL)
1254 os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
1255 mlme.im_ssid_len = params->ssid_len;
6fc6879b
JM
1256 if (params->bssid != NULL)
1257 os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
1258 if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
1259 return -1;
4a867032 1260 return ret;
6fc6879b
JM
1261}
1262
6fc6879b 1263static int
c2e8d0a0 1264wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
6fc6879b
JM
1265{
1266 struct wpa_driver_bsd_data *drv = priv;
1267 int flags;
c2e8d0a0
JM
1268 const u8 *ssid = params->ssids[0].ssid;
1269 size_t ssid_len = params->ssids[0].ssid_len;
6fc6879b
JM
1270
1271 /* NB: interface must be marked UP to do a scan */
1272 if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
1273 return -1;
1274
1275 /* set desired ssid before scan */
1276 if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
1277 return -1;
1278
1279 /* NB: net80211 delivers a scan complete event so no need to poll */
1280 return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
1281}
1282
6fc6879b
JM
1283static void
1284wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
1285{
1286 struct wpa_driver_bsd_data *drv = sock_ctx;
1287 char buf[2048];
1288 struct if_announcemsghdr *ifan;
1289 struct if_msghdr *ifm;
1290 struct rt_msghdr *rtm;
1291 union wpa_event_data event;
1292 struct ieee80211_michael_event *mic;
1293 int n;
1294
1295 n = read(sock, buf, sizeof(buf));
1296 if (n < 0) {
1297 if (errno != EINTR && errno != EAGAIN)
1298 perror("read(PF_ROUTE)");
1299 return;
1300 }
1301
1302 rtm = (struct rt_msghdr *) buf;
1303 if (rtm->rtm_version != RTM_VERSION) {
1304 wpa_printf(MSG_DEBUG, "Routing message version %d not "
1305 "understood\n", rtm->rtm_version);
1306 return;
1307 }
1308 os_memset(&event, 0, sizeof(event));
1309 switch (rtm->rtm_type) {
1310 case RTM_IFANNOUNCE:
1311 ifan = (struct if_announcemsghdr *) rtm;
1312 if (ifan->ifan_index != drv->ifindex)
1313 break;
1314 strlcpy(event.interface_status.ifname, drv->ifname,
1315 sizeof(event.interface_status.ifname));
1316 switch (ifan->ifan_what) {
1317 case IFAN_DEPARTURE:
1318 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
1319 default:
1320 return;
1321 }
1322 wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
1323 event.interface_status.ifname,
1324 ifan->ifan_what == IFAN_DEPARTURE ?
1325 "removed" : "added");
1326 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
1327 break;
1328 case RTM_IEEE80211:
1329 ifan = (struct if_announcemsghdr *) rtm;
1330 if (ifan->ifan_index != drv->ifindex)
1331 break;
1332 switch (ifan->ifan_what) {
1333 case RTM_IEEE80211_ASSOC:
1334 case RTM_IEEE80211_REASSOC:
1335 wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
1336 break;
1337 case RTM_IEEE80211_DISASSOC:
1338 wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
1339 break;
1340 case RTM_IEEE80211_SCAN:
1341 wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
1342 break;
1343 case RTM_IEEE80211_REPLAY:
1344 /* ignore */
1345 break;
1346 case RTM_IEEE80211_MICHAEL:
1347 mic = (struct ieee80211_michael_event *) &ifan[1];
1348 wpa_printf(MSG_DEBUG,
1349 "Michael MIC failure wireless event: "
1350 "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
1351 MAC2STR(mic->iev_src));
1352
1353 os_memset(&event, 0, sizeof(event));
1354 event.michael_mic_failure.unicast =
1355 !IEEE80211_IS_MULTICAST(mic->iev_dst);
1356 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
1357 &event);
1358 break;
1359 }
1360 break;
1361 case RTM_IFINFO:
1362 ifm = (struct if_msghdr *) rtm;
1363 if (ifm->ifm_index != drv->ifindex)
1364 break;
1365 if ((rtm->rtm_flags & RTF_UP) == 0) {
1366 strlcpy(event.interface_status.ifname, drv->ifname,
1367 sizeof(event.interface_status.ifname));
1368 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
1369 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
1370 event.interface_status.ifname);
1371 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
1372 }
1373 break;
1374 }
1375}
1376
a65f4a57
MH
1377static void
1378wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
1379 struct ieee80211req_scan_result *sr)
6fc6879b 1380{
a65f4a57
MH
1381 struct wpa_scan_res *result, **tmp;
1382 size_t extra_len;
1383 u8 *pos;
6fc6879b 1384
a65f4a57
MH
1385 extra_len = 2 + sr->isr_ssid_len;
1386 extra_len += 2 + sr->isr_nrates;
1387 extra_len += 3; /* ERP IE */
1388 extra_len += sr->isr_ie_len;
6fc6879b 1389
a65f4a57
MH
1390 result = os_zalloc(sizeof(*result) + extra_len);
1391 if (result == NULL)
1392 return;
1393 os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN);
1394 result->freq = sr->isr_freq;
1395 result->beacon_int = sr->isr_intval;
1396 result->caps = sr->isr_capinfo;
1397 result->qual = sr->isr_rssi;
1398 result->noise = sr->isr_noise;
6fc6879b 1399
a65f4a57 1400 pos = (u8 *)(result + 1);
6fc6879b 1401
a65f4a57
MH
1402 *pos++ = WLAN_EID_SSID;
1403 *pos++ = sr->isr_ssid_len;
1404 os_memcpy(pos, sr + 1, sr->isr_ssid_len);
1405 pos += sr->isr_ssid_len;
6fc6879b 1406
a65f4a57
MH
1407 /*
1408 * Deal all rates as supported rate.
1409 * Because net80211 doesn't report extended supported rate or not.
1410 */
1411 *pos++ = WLAN_EID_SUPP_RATES;
1412 *pos++ = sr->isr_nrates;
1413 os_memcpy(pos, sr->isr_rates, sr->isr_nrates);
1414 pos += sr->isr_nrates;
6fc6879b 1415
a65f4a57
MH
1416 *pos++ = WLAN_EID_ERP_INFO;
1417 *pos++ = 1;
1418 *pos++ = sr->isr_erp;
6fc6879b 1419
a65f4a57
MH
1420 os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len);
1421 pos += sr->isr_ie_len;
6fc6879b 1422
a65f4a57
MH
1423 result->ie_len = pos - (u8 *)(result + 1);
1424
1425 tmp = os_realloc(res->res,
1426 (res->num + 1) * sizeof(struct wpa_scan_res *));
1427 if (tmp == NULL) {
1428 os_free(result);
1429 return;
1430 }
1431 tmp[res->num++] = result;
1432 res->res = tmp;
6fc6879b
JM
1433}
1434
a65f4a57
MH
1435struct wpa_scan_results *
1436wpa_driver_bsd_get_scan_results2(void *priv)
6fc6879b 1437{
6fc6879b 1438 struct wpa_driver_bsd_data *drv = priv;
6fc6879b 1439 struct ieee80211req_scan_result *sr;
a65f4a57
MH
1440 struct wpa_scan_results *res;
1441 int len, rest;
1442 uint8_t buf[24*1024], *pos;
6fc6879b 1443
a65f4a57 1444 len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024);
6fc6879b 1445 if (len < 0)
a65f4a57
MH
1446 return NULL;
1447
1448 res = os_zalloc(sizeof(*res));
1449 if (res == NULL)
1450 return NULL;
6fc6879b 1451
a65f4a57
MH
1452 pos = buf;
1453 rest = len;
1454 while (rest >= sizeof(struct ieee80211req_scan_result)) {
1455 sr = (struct ieee80211req_scan_result *)pos;
1456 wpa_driver_bsd_add_scan_entry(res, sr);
1457 pos += sr->isr_len;
1458 rest -= sr->isr_len;
6fc6879b 1459 }
6fc6879b 1460
a65f4a57
MH
1461 wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)",
1462 len, (unsigned long)res->num);
6fc6879b 1463
a65f4a57 1464 return res;
6fc6879b
JM
1465}
1466
1467static void *
1468wpa_driver_bsd_init(void *ctx, const char *ifname)
1469{
1470#define GETPARAM(drv, param, v) \
1471 (((v) = get80211param(drv, param)) != -1)
1472 struct wpa_driver_bsd_data *drv;
1473
1474 drv = os_zalloc(sizeof(*drv));
1475 if (drv == NULL)
1476 return NULL;
1477 /*
1478 * NB: We require the interface name be mappable to an index.
1479 * This implies we do not support having wpa_supplicant
1480 * wait for an interface to appear. This seems ok; that
1481 * doesn't belong here; it's really the job of devd.
1482 */
1483 drv->ifindex = if_nametoindex(ifname);
1484 if (drv->ifindex == 0) {
1485 wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
1486 __func__, ifname);
1487 goto fail1;
1488 }
1489 drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
1490 if (drv->sock < 0)
1491 goto fail1;
1492 drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
1493 if (drv->route < 0)
1494 goto fail;
1495 eloop_register_read_sock(drv->route,
1496 wpa_driver_bsd_event_receive, ctx, drv);
1497
1498 drv->ctx = ctx;
1499 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
1500
1501 if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
1502 wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
1503 __func__, strerror(errno));
1504 goto fail;
1505 }
1506 if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
1507 wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
1508 __func__, strerror(errno));
1509 goto fail;
1510 }
1511 if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
1512 wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
1513 __func__, strerror(errno));
1514 goto fail;
1515 }
5197244a
MH
1516
1517 if (bsd_set_mediaopt(drv->sock, drv->ifname, IFM_OMASK,
1518 0 /* STA */) < 0) {
1519 wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
1520 __func__);
1521 goto fail;
1522 }
6fc6879b
JM
1523 if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
1524 wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
1525 "roaming: %s", __func__, strerror(errno));
1526 goto fail;
1527 }
1528
1529 if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
1530 wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
1531 __func__, strerror(errno));
1532 goto fail;
1533 }
1534
4a867032
JM
1535 wpa_driver_bsd_set_wpa(drv, 1);
1536
6fc6879b
JM
1537 return drv;
1538fail:
1539 close(drv->sock);
1540fail1:
1541 os_free(drv);
1542 return NULL;
1543#undef GETPARAM
1544}
1545
1546static void
1547wpa_driver_bsd_deinit(void *priv)
1548{
1549 struct wpa_driver_bsd_data *drv = priv;
1550 int flags;
1551
4a867032 1552 wpa_driver_bsd_set_wpa(drv, 0);
6fc6879b
JM
1553 eloop_unregister_read_sock(drv->route);
1554
1555 /* NB: mark interface down */
1556 if (getifflags(drv, &flags) == 0)
1557 (void) setifflags(drv, flags &~ IFF_UP);
1558
1559 wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
1560 if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
1561 wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
1562 __func__);
1563
1564 (void) close(drv->route); /* ioctl socket */
1565 (void) close(drv->sock); /* event socket */
1566 os_free(drv);
1567}
1568
1569
1570const struct wpa_driver_ops wpa_driver_bsd_ops = {
1571 .name = "bsd",
66d4085f 1572 .desc = "BSD 802.11 support",
6fc6879b
JM
1573 .init = wpa_driver_bsd_init,
1574 .deinit = wpa_driver_bsd_deinit,
1575 .get_bssid = wpa_driver_bsd_get_bssid,
1576 .get_ssid = wpa_driver_bsd_get_ssid,
6fc6879b
JM
1577 .set_key = wpa_driver_bsd_set_key,
1578 .set_countermeasures = wpa_driver_bsd_set_countermeasures,
c2e8d0a0 1579 .scan2 = wpa_driver_bsd_scan,
a65f4a57 1580 .get_scan_results2 = wpa_driver_bsd_get_scan_results2,
6fc6879b
JM
1581 .deauthenticate = wpa_driver_bsd_deauthenticate,
1582 .disassociate = wpa_driver_bsd_disassociate,
1583 .associate = wpa_driver_bsd_associate,
6fc6879b 1584};
c5121837
JM
1585
1586#endif /* HOSTAPD */