summaryrefslogtreecommitdiffstats
path: root/usr.sbin/wpa/wpa_supplicant
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2005-06-05 21:18:53 +0000
committersam <sam@FreeBSD.org>2005-06-05 21:18:53 +0000
commitc4dae948adfad2a62bfcfdfe4006a7858196db80 (patch)
treef3e1fbca2d982558e49e34bf359913179a794447 /usr.sbin/wpa/wpa_supplicant
parentd5b041c0d95cfdd0d9f6a4f7029a7352981f15c7 (diff)
downloadFreeBSD-src-c4dae948adfad2a62bfcfdfe4006a7858196db80.zip
FreeBSD-src-c4dae948adfad2a62bfcfdfe4006a7858196db80.tar.gz
freebsd pieces of wpa supplicant support
Reviewed by: brooks
Diffstat (limited to 'usr.sbin/wpa/wpa_supplicant')
-rw-r--r--usr.sbin/wpa/wpa_supplicant/Makefile40
-rw-r--r--usr.sbin/wpa/wpa_supplicant/driver_freebsd.c636
-rw-r--r--usr.sbin/wpa/wpa_supplicant/wpa_supplicant.1132
-rw-r--r--usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5157
4 files changed, 965 insertions, 0 deletions
diff --git a/usr.sbin/wpa/wpa_supplicant/Makefile b/usr.sbin/wpa/wpa_supplicant/Makefile
new file mode 100644
index 0000000..e24743a
--- /dev/null
+++ b/usr.sbin/wpa/wpa_supplicant/Makefile
@@ -0,0 +1,40 @@
+# $FreeBSD$
+
+WPA_SUPPLICANT_DISTDIR?= ${.CURDIR}/../../../contrib/wpa_supplicant
+.PATH: ${.CURDIR}/.. ${WPA_SUPPLICANT_DISTDIR}
+
+PROG= wpa_supplicant
+SRCS= config.c eloop.c common.c md5.c rc4.c sha1.c aes_wrap.c \
+ wpa_supplicant.c wpa.c \
+ ctrl_iface.c l2_packet.c drivers.c driver_freebsd.c
+
+CFLAGS+= -I${.CURDIR} -I${WPA_SUPPLICANT_DISTDIR}
+CFLAGS+= -DCONFIG_DRIVER_BSD
+CFLAGS+= -DCONFIG_CTRL_IFACE
+CFLAGS+= -g
+DPADD+= ${LIBPCAP}
+LDADD+= -lpcap
+
+.if defined(ENABLE_WPA_SUPPLICANT_EAPOL)
+SRCS+= eapol_sm.c eap.c
+CFLAGS+= -DIEEE8021X_EAPOL
+
+.if !defined(NO_CRYPT) && !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH)
+CFLAGS+=-DEAP_TLS -DEAP_PEAP -DEAP_MSCHAPv2 -DEAP_LEAP -DEAP_PSK \
+ -DEAP_TLV -DEAP_TLS_FUNCS
+SRCS+= eap_tls.c eap_peap.c eap_mschapv2.c eap_leap.c eap_psk.c \
+ eap_tlv.c eap_tls_common.c tls_openssl.c ms_funcs.c crypto.c
+
+# NB: requires patch to openssl
+#CFLAGS+= -DEAP_FAST
+#SRCS+= eap_fast.c
+
+DPADD+= ${LIBCRYPTO}
+LDADD+= -lssl -lcrypto
+.else
+SRCS+= tls_none.c
+.endif
+
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
new file mode 100644
index 0000000..1a9a0fd
--- /dev/null
+++ b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
@@ -0,0 +1,636 @@
+/*
+ * WPA Supplicant - driver interaction with BSD net80211 layer
+ * Copyright (c) 2004, Sam Leffler <sam@errno.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "common.h"
+#include "driver.h"
+#include "eloop.h"
+#include "wpa_supplicant.h"
+#include "l2_packet.h"
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+#include <net80211/ieee80211_ioctl.h>
+
+struct wpa_driver_bsd_data {
+ int sock; /* open socket for 802.11 ioctls */
+ int route; /* routing socket for events */
+ char ifname[IFNAMSIZ+1]; /* interface name */
+ void *ctx;
+};
+
+static int
+set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
+{
+ struct ieee80211req ireq;
+
+ memset(&ireq, 0, sizeof(ireq));
+ strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
+ ireq.i_type = op;
+ ireq.i_len = arg_len;
+ ireq.i_data = (void *) arg;
+
+ if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
+ perror("ioctl[SIOCS80211]");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
+{
+ struct ieee80211req ireq;
+
+ memset(&ireq, 0, sizeof(ireq));
+ strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
+ ireq.i_type = op;
+ ireq.i_len = arg_len;
+ ireq.i_data = arg;
+
+ if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
+ perror("ioctl[SIOCG80211]");
+ return -1;
+ }
+ return ireq.i_len;
+}
+
+static int
+set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
+{
+ struct ieee80211req ireq;
+
+ memset(&ireq, 0, sizeof(ireq));
+ strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
+ ireq.i_type = op;
+ ireq.i_val = arg;
+
+ if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
+ perror("ioctl[SIOCS80211]");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+getifflags(struct wpa_driver_bsd_data *drv, int *flags)
+{
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, drv->ifname, sizeof (ifr.ifr_name));
+ if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+ perror("SIOCGIFFLAGS");
+ return errno;
+ }
+ *flags = ifr.ifr_flags & 0xffff;
+ return 0;
+}
+
+static int
+setifflags(struct wpa_driver_bsd_data *drv, int flags)
+{
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, drv->ifname, sizeof (ifr.ifr_name));
+ ifr.ifr_flags = flags & 0xffff;
+ if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
+ perror("SIOCSIFFLAGS");
+ return errno;
+ }
+ return 0;
+}
+
+static int
+wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+
+ return get80211var(drv, IEEE80211_IOC_BSSID,
+ bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
+}
+
+#if 0
+static int
+wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+
+ return set80211var(drv, IEEE80211_IOC_BSSID,
+ bssid, IEEE80211_ADDR_LEN);
+}
+#endif
+
+static int
+wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+
+ return get80211var(drv, IEEE80211_IOC_SSID,
+ ssid, IEEE80211_NWID_LEN);
+}
+
+static int
+wpa_driver_bsd_set_ssid(void *priv, const char *ssid,
+ size_t ssid_len)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+
+ return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
+}
+
+static int
+wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
+ const char *wpa_ie, size_t wpa_ie_len)
+{
+ return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
+}
+
+static int
+wpa_driver_bsd_set_wpa(void *priv, int enabled)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ int ret = 0;
+
+ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
+
+ if (!enabled && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
+ ret = -1;
+ if (set80211param(drv, IEEE80211_IOC_ROAMING, enabled ? 2 : 0) < 0)
+ ret = -1;
+ if (set80211param(drv, IEEE80211_IOC_PRIVACY, enabled) < 0)
+ ret = -1;
+ if (set80211param(drv, IEEE80211_IOC_WPA, enabled ? 3 : 0) < 0)
+ ret = -1;
+
+ return ret;
+}
+
+static int
+wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
+ const unsigned char *addr)
+{
+ struct ieee80211req_del_key wk;
+
+ wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
+ memset(&wk, 0, sizeof(wk));
+ wk.idk_keyix = key_idx;
+ if (addr != NULL)
+ memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
+
+ return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
+}
+
+static int
+wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
+ const unsigned char *addr, int key_idx, int set_tx,
+ const u8 *seq, size_t seq_len,
+ const u8 *key, size_t key_len)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ struct ieee80211req_key wk;
+ char *alg_name;
+ u_int8_t cipher;
+
+ if (alg == WPA_ALG_NONE)
+ return wpa_driver_bsd_del_key(drv, key_idx, addr);
+
+ switch (alg) {
+ case WPA_ALG_WEP:
+ alg_name = "WEP";
+ cipher = IEEE80211_CIPHER_WEP;
+ break;
+ case WPA_ALG_TKIP:
+ alg_name = "TKIP";
+ cipher = IEEE80211_CIPHER_TKIP;
+ break;
+ case WPA_ALG_CCMP:
+ alg_name = "CCMP";
+ cipher = IEEE80211_CIPHER_AES_CCM;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
+ __FUNCTION__, alg);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%d "
+ "key_len=%d", __FUNCTION__, alg_name, key_idx, set_tx,
+ seq_len, key_len);
+
+ if (seq_len > sizeof(u_int64_t)) {
+ wpa_printf(MSG_DEBUG, "%s: seq_len %d too big",
+ __FUNCTION__, seq_len);
+ return -2;
+ }
+ if (key_len > sizeof(wk.ik_keydata)) {
+ wpa_printf(MSG_DEBUG, "%s: key length %d too big",
+ __FUNCTION__, key_len);
+ return -3;
+ }
+
+ memset(&wk, 0, sizeof(wk));
+ wk.ik_type = cipher;
+ wk.ik_flags = IEEE80211_KEY_RECV;
+ if (set_tx) {
+ wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
+ memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+ } else
+ memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
+ wk.ik_keyix = key_idx;
+ wk.ik_keylen = key_len;
+ memcpy(&wk.ik_keyrsc, seq, seq_len);
+ memcpy(wk.ik_keydata, key, key_len);
+
+ return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
+}
+
+static int
+wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+
+ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
+ return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
+}
+
+
+static int
+wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+
+ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
+ return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
+}
+
+static int
+wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ struct ieee80211req_mlme mlme;
+
+ wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
+ mlme.im_op = IEEE80211_MLME_DEAUTH;
+ mlme.im_reason = reason_code;
+ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
+}
+
+static int
+wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ struct ieee80211req_mlme mlme;
+
+ wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
+ mlme.im_op = IEEE80211_MLME_DISASSOC;
+ mlme.im_reason = reason_code;
+ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
+}
+
+static int
+wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ struct ieee80211req_mlme mlme;
+
+ int ret = 0;
+
+ wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
+
+ /*
+ * NB: Don't need to set the freq or cipher-related state as
+ * this is implied by the bssid which is used to locate
+ * the scanned node state which holds it. The ssid is
+ * needed to disambiguate an AP that broadcasts multiple
+ * ssid's but uses the same bssid.
+ */
+ /* XXX error handling is wrong but unclear what to do... */
+ if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
+ ret = -1;
+ if (wpa_driver_bsd_set_ssid(drv, params->ssid, params->ssid_len) < 0)
+ ret = -1;
+ memset(&mlme, 0, sizeof(mlme));
+ mlme.im_op = IEEE80211_MLME_ASSOC;
+ memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
+ if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
+ ret = -1;
+
+ return ret;
+}
+
+static int
+wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ int flags;
+
+ /* NB: interface must be marked UP to do a scan */
+ if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
+ return -1;
+
+ /* set desired ssid before scan */
+ if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
+ return -1;
+
+ /* NB: net80211 delivers a scan complete event so no need to poll */
+ return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
+}
+
+#include <net/route.h>
+#include <net80211/ieee80211_freebsd.h>
+
+static void
+wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
+{
+ char buf[2048];
+ struct if_announcemsghdr *ifan;
+ struct rt_msghdr *rtm;
+ union wpa_event_data event;
+ struct ieee80211_michael_event *mic;
+ int n;
+
+ n = read(sock, buf, sizeof(buf));
+ if (n < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ perror("read(PF_ROUTE)");
+ return;
+ }
+
+ rtm = (struct rt_msghdr *) buf;
+ if (rtm->rtm_version != RTM_VERSION) {
+ wpa_printf(MSG_DEBUG, "Routing message version %d not "
+ "understood\n", rtm->rtm_version);
+ return;
+ }
+ ifan = (struct if_announcemsghdr *) rtm;
+ switch (rtm->rtm_type) {
+ case RTM_IFANNOUNCE:
+ memset(&event, 0, sizeof(event));
+ /* XXX name buffer must be >= IFNAMSIZ */
+ /* XXX check return value */
+ if_indextoname(ifan->ifan_index, event.interface_status.ifname);
+ switch (ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+ break;
+ case IFAN_DEPARTURE:
+ event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+ default:
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
+ event.interface_status.ifname,
+ ifan->ifan_what == IFAN_DEPARTURE ?
+ "removed" : "added");
+ wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+ break;
+ case RTM_IEEE80211:
+ switch (ifan->ifan_what) {
+ case RTM_IEEE80211_ASSOC:
+ case RTM_IEEE80211_REASSOC:
+ wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
+ break;
+ case RTM_IEEE80211_DISASSOC:
+ wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
+ break;
+ case RTM_IEEE80211_SCAN:
+ wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
+ break;
+ case RTM_IEEE80211_REPLAY:
+ /* ignore */
+ break;
+ case RTM_IEEE80211_MICHAEL:
+ mic = (struct ieee80211_michael_event *) &ifan[1];
+ wpa_printf(MSG_DEBUG,
+ "Michael MIC failure wireless event: "
+ "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
+ MAC2STR(mic->iev_src));
+
+ memset(&event, 0, sizeof(event));
+ event.michael_mic_failure.unicast =
+ !IEEE80211_IS_MULTICAST(mic->iev_dst);
+ wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
+ &event);
+ break;
+ }
+ break;
+ }
+}
+
+/* Compare function for sorting scan results. Return >0 if @b is consider
+ * better. */
+static int
+wpa_scan_result_compar(const void *a, const void *b)
+{
+ const struct wpa_scan_result *wa = a;
+ const struct wpa_scan_result *wb = b;
+
+ /* WPA/WPA2 support preferred */
+ if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
+ !(wa->wpa_ie_len || wa->rsn_ie_len))
+ return 1;
+ if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
+ (wa->wpa_ie_len || wa->rsn_ie_len))
+ return -1;
+
+ /* privacy support preferred */
+ if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
+ (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
+ return 1;
+ if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
+ (wb->caps & IEEE80211_CAPINFO_PRIVACY))
+ return -1;
+
+ /* best/max rate preferred if signal level close enough XXX */
+ if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
+ return wb->maxrate - wa->maxrate;
+
+ /* use freq for channel preference */
+
+ /* all things being equal, use signal level */
+ return wb->level - wa->level;
+}
+
+static int
+getmaxrate(uint8_t rates[15], uint8_t nrates)
+{
+ int i, maxrate = -1;
+
+ for (i = 0; i < nrates; i++) {
+ int rate = rates[i] & IEEE80211_RATE_VAL;
+ if (rate > maxrate)
+ rate = maxrate;
+ }
+ return maxrate;
+}
+
+/* unalligned little endian access */
+#define LE_READ_4(p) \
+ ((u_int32_t) \
+ ((((const u_int8_t *)(p))[0] ) | \
+ (((const u_int8_t *)(p))[1] << 8) | \
+ (((const u_int8_t *)(p))[2] << 16) | \
+ (((const u_int8_t *)(p))[3] << 24)))
+
+static int __inline
+iswpaoui(const u_int8_t *frm)
+{
+ return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
+}
+
+static int
+wpa_driver_bsd_get_scan_results(void *priv,
+ struct wpa_scan_result *results,
+ size_t max_size)
+{
+#define min(a,b) ((a)>(b)?(b):(a))
+ struct wpa_driver_bsd_data *drv = priv;
+ uint8_t buf[24*1024];
+ uint8_t *cp, *vp;
+ struct ieee80211req_scan_result *sr;
+ struct wpa_scan_result *wsr;
+ int len, ielen;
+
+ memset(results, 0, max_size * sizeof(struct wpa_scan_result));
+
+ len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+ cp = buf;
+ wsr = results;
+ while (len >= sizeof(struct ieee80211req_scan_result)) {
+ sr = (struct ieee80211req_scan_result *) cp;
+ memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
+ wsr->ssid_len = sr->isr_ssid_len;
+ wsr->freq = sr->isr_freq;
+ wsr->noise = sr->isr_noise;
+ wsr->qual = sr->isr_rssi;
+ wsr->level = 0; /* XXX? */
+ wsr->caps = sr->isr_capinfo;
+ wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
+ vp = (u_int8_t *)(sr+1);
+ memcpy(wsr->ssid, vp, sr->isr_ssid_len);
+ if (sr->isr_ie_len > 0) {
+ vp += sr->isr_ssid_len;
+ ielen = sr->isr_ie_len;
+ while (ielen > 0) {
+ switch (vp[0]) {
+ case IEEE80211_ELEMID_VENDOR:
+ if (!iswpaoui(vp))
+ break;
+ wsr->wpa_ie_len =
+ min(2+vp[1], SSID_MAX_WPA_IE_LEN);
+ memcpy(wsr->wpa_ie, vp, wsr->wpa_ie_len);
+ break;
+ case IEEE80211_ELEMID_RSN:
+ wsr->rsn_ie_len =
+ min(2+vp[1], SSID_MAX_WPA_IE_LEN);
+ memcpy(wsr->rsn_ie, vp, wsr->rsn_ie_len);
+ break;
+ }
+ ielen -= 2+vp[1];
+ vp += 2+vp[1];
+ }
+ }
+
+ cp += sr->isr_len, len -= sr->isr_len;
+ wsr++;
+ }
+ qsort(results, wsr - results, sizeof(struct wpa_scan_result),
+ wpa_scan_result_compar);
+
+ wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
+ len, wsr - results);
+
+ return wsr - results;
+#undef min
+}
+
+static void *
+wpa_driver_bsd_init(void *ctx, const char *ifname)
+{
+ struct wpa_driver_bsd_data *drv;
+
+ drv = malloc(sizeof(*drv));
+ if (drv == NULL)
+ return NULL;
+ memset(drv, 0, sizeof(*drv));
+ drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (drv->sock < 0) {
+ free(drv);
+ return NULL;
+ }
+ drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (drv->route < 0) {
+ close(drv->sock);
+ free(drv);
+ return NULL;
+ }
+ eloop_register_read_sock(drv->route,
+ wpa_driver_bsd_event_receive, ctx, NULL);
+
+ drv->ctx = ctx;
+ strncpy(drv->ifname, ifname, sizeof(drv->ifname));
+
+ return drv;
+}
+
+static void
+wpa_driver_bsd_deinit(void *priv)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ int flags;
+
+ /* NB: mark interface down */
+ if (getifflags(drv, &flags) == 0)
+ (void) setifflags(drv, flags &~ IFF_UP);
+
+ (void) close(drv->route); /* ioctl socket */
+ (void) close(drv->sock); /* event socket */
+ free(drv);
+}
+
+
+struct wpa_driver_ops wpa_driver_bsd_ops = {
+ .name = "bsd",
+ .desc = "BSD 802.11 support (Atheros, etc.)",
+ .init = wpa_driver_bsd_init,
+ .deinit = wpa_driver_bsd_deinit,
+ .get_bssid = wpa_driver_bsd_get_bssid,
+ .get_ssid = wpa_driver_bsd_get_ssid,
+ .set_wpa = wpa_driver_bsd_set_wpa,
+ .set_key = wpa_driver_bsd_set_key,
+ .set_countermeasures = wpa_driver_bsd_set_countermeasures,
+ .set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted,
+ .scan = wpa_driver_bsd_scan,
+ .get_scan_results = wpa_driver_bsd_get_scan_results,
+ .deauthenticate = wpa_driver_bsd_deauthenticate,
+ .disassociate = wpa_driver_bsd_disassociate,
+ .associate = wpa_driver_bsd_associate,
+};
diff --git a/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.1 b/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.1
new file mode 100644
index 0000000..70db4d7
--- /dev/null
+++ b/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.1
@@ -0,0 +1,132 @@
+.\" Copyright (c) 2005 Sam Leffler <sam@errno.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 3, 2005
+.Dt WPA_SUPPLICANT 8
+.Os
+.Sh NAME
+.Nm wpa_supplicant
+.Nd "WPA/802.11i Supplicant for wireless network devices"
+.Sh SYNOPSIS
+.Nm
+.Op Fl BddehLqqvw
+.Fl i Ar ifname
+.Fl c Ar config-file
+.Op Fl N i Ar ifname Fl c Ar config-file ....
+.Sh DESCRIPTION
+.Nm
+is an implementation of the WPA Supplicant component,
+i.e., the part that runs in the client stations.
+It implements WPA key negotiation with a WPA Authenticator
+and EAP authentication with Authentication Server.
+In addition, it controls the roaming and IEEE 802.11
+authentication/association of the wlan driver.
+.Pp
+.Nm
+is designed to be a "daemon" program that runs in the
+background and acts as the backend component controlling
+the wireless connection.
+.Nm
+supports separate frontend programs such as the
+text-based frontend,
+.Xr wpa_cli 8
+.Pp
+The following arguments must be specified on the command line:
+.Bl -tag -width indent
+.It Fl i Ar ifname
+Use the specified wireless interface.
+.It Fl c Ar config-file
+Use the settings in the specified configuration file when managing
+the specified wireless interface.
+See
+.Xr wpa_supplicant.conf 5
+for a description of the configuration file syntax.
+.Pp
+Changes to the configuration file can be reloaded by sending a
+.Nm SIGHUP
+to the
+.Nm
+processor or with the
+.Xr wpa_cli
+utility, using ``wpa_cli reconfigure''.
+.El
+.Sh OPTIONS
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d
+Enable debugging messages.
+If this option is supplied twice more verbose messages are displayed.
+.It Fl e
+Use an external IEEE 802.1X Supplicant program and disable the
+internal Supplicant.
+This option is not normally used.
+.It Fl h
+Show help text.
+.It Fl q
+Decrease debugging verbosity (i.e. counteract the use of the
+.Fl d
+flag.
+.It Fl v
+Display version information on the terminal and exit.
+.It Fl w
+If the specified interface is not present, wait for it to be
+added; e.g. a cardbus device to be inserted.
+.It Fl B
+Detach from the controlling terminal and run as a daemon process
+in the background.
+.It Fl K
+Include key information in debugging output.
+.It Fl L
+Display the license for this program on the terminal and exit.
+.It Fl N Fl i Ar iface Fl Ar config-file
+Specify an additional interface and configuration file.
+If multiple interfaces are specified then
+.Nm
+will manage them all with a single process.
+.El
+.Sh SEE ALSO
+.Xr ath 4 ,
+.Xr iwi 4 ,
+.Xr ipw 4 ,
+.Xr ral 4 ,
+.Xr ural 4 ,
+.Xr wi 4 ,
+.Xr wpa_supplicant.conf 5 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Jouni Malinen Aq jkmaline@cc.hut.fi .
+This manual page is derived from the README file included in the
+.Nm
+distribution.
+.Sh BUGS
diff --git a/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5 b/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
new file mode 100644
index 0000000..c320453
--- /dev/null
+++ b/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
@@ -0,0 +1,157 @@
+.\" Copyright (c) 2005 Sam Leffler <sam@errno.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 3, 2005
+.Dt WPA_SUPPLICANT.CONF 5
+.Os
+.Sh NAME
+.Nm wpa_supplicant.conf
+.Nd "configuration file for wpa_supplicant utility"
+.Sh DESCRIPTION
+The
+.Xr wpa_supplicant 1
+program is an implementation of the WPA Supplicant component,
+i.e., the part that runs in the client stations.
+.Nm wpa_supplicant
+implements WPA key negotiation with a WPA Authenticator
+and EAP authentication with Authentication Server using
+configuration information stored in a text file.
+.Pp
+The configuration file consists of one or more network blocks, e.g.
+one for each used SSID.
+.Nm wpa_supplicant
+will automatically select the best network based on the order of
+the network blocks in the configuration file, network security level
+(WPA/WPA2 is preferred), and signal strength.
+.Sh CERTIFICATES
+.Pp
+Some EAP authentication methods require use of certificates.
+EAP-TLS uses both server- and client-side certificates,
+whereas EAP-PEAP and EAP-TTLS only require a server-side certificate.
+When a client certificate is used, a matching private key file must
+also be included in configuration.
+If the private key uses a passphrase, this
+has to be configured in the wpa_supplicant.conf file as "private_key_passwd".
+.Pp
+.Nm wpa_supplicant
+supports X.509 certificates in PEM and DER formats.
+User certificate and private key can be included in the same file.
+.Pp
+If the user certificate and private key is received in PKCS#12/PFX
+format, they need to be converted to suitable PEM/DER format for
+use by
+.Nm wpa_supplicant.
+This can be done using the
+.Xr openssl 1
+program, e.g. with following commands:
+.Bd -literal
+# convert client certificate and private key to PEM format
+openssl pkcs12 -in example.pfx -out user.pem -clcerts
+# convert CA certificate (if included in PFX file) to PEM format
+openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys
+.Be
+.Sh EXAMPLES
+.Pp
+WPA-Personal (PSK) as a home network and WPA-Enterprise with EAP-TLS
+as a work network:
+.Bd -literal
+# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+#
+# home network; allow all valid ciphers
+network={
+ ssid="home"
+ scan_ssid=1
+ key_mgmt=WPA-PSK
+ psk="very secret passphrase"
+}
+#
+# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
+network={
+ ssid="work"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ pairwise=CCMP TKIP
+ group=CCMP TKIP
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+}
+.Ed
+.Pp
+WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that use old peaplabel
+(e.g., Funk Odyssey and SBR, Meetinghouse Aegis, Interlink RAD-Series):
+.Bd -literal
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ eap=PEAP
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase1="peaplabel=0"
+ phase2="auth=MSCHAPV2"
+}
+.Ed
+.Pp
+EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the
+unencrypted use. Real identity is sent only within an encrypted TLS tunnel.
+.Bd -literal
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase2="auth=MD5"
+}
+.Ed
+.Sh SEE ALSO
+.Xr wpa_supplicant 1
+.Sh HISTORY
+The
+.Nm
+manual page and
+.Nm wpa_supplicant
+functionality first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+This manual page is derived from the README file in the
+.Nm wpa_supplicant
+distribution provided by
+.An Jouni Malinen Aq jkmaline@cc.hut.fi .
OpenPOWER on IntegriCloud