summaryrefslogtreecommitdiffstats
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
parentd5b041c0d95cfdd0d9f6a4f7029a7352981f15c7 (diff)
downloadFreeBSD-src-c4dae948adfad2a62bfcfdfe4006a7858196db80.zip
FreeBSD-src-c4dae948adfad2a62bfcfdfe4006a7858196db80.tar.gz
freebsd pieces of wpa supplicant support
Reviewed by: brooks
-rw-r--r--usr.sbin/wpa/Makefile5
-rw-r--r--usr.sbin/wpa/Makefile.inc3
-rw-r--r--usr.sbin/wpa/l2_packet.c227
-rw-r--r--usr.sbin/wpa/wpa_cli/Makefile9
-rw-r--r--usr.sbin/wpa/wpa_cli/wpa_cli.1192
-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
9 files changed, 1401 insertions, 0 deletions
diff --git a/usr.sbin/wpa/Makefile b/usr.sbin/wpa/Makefile
new file mode 100644
index 0000000..df3c13b
--- /dev/null
+++ b/usr.sbin/wpa/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= wpa_supplicant wpa_cli
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/wpa/Makefile.inc b/usr.sbin/wpa/Makefile.inc
new file mode 100644
index 0000000..8c6b79e
--- /dev/null
+++ b/usr.sbin/wpa/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+BINDIR?= /usr/sbin
diff --git a/usr.sbin/wpa/l2_packet.c b/usr.sbin/wpa/l2_packet.c
new file mode 100644
index 0000000..dae3eb7
--- /dev/null
+++ b/usr.sbin/wpa/l2_packet.c
@@ -0,0 +1,227 @@
+/*
+ * WPA Supplicant - Layer2 packet handling
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2005, 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$
+ */
+
+/*
+ * FreeBSD-specific implementation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <pcap.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include "common.h"
+#include "eloop.h"
+#include "l2_packet.h"
+
+struct l2_packet_data {
+ pcap_t *pcap;
+ char ifname[100];
+ u8 own_addr[ETH_ALEN];
+ void (*rx_callback)(void *ctx, unsigned char *src_addr,
+ unsigned char *buf, size_t len);
+ void *rx_callback_ctx;
+ int rx_l2_hdr; /* whether to include layer 2 (Ethernet) header in calls
+ * to rx_callback */
+};
+
+int
+l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
+{
+ memcpy(addr, l2->own_addr, ETH_ALEN);
+ return 0;
+}
+
+void
+l2_packet_set_rx_l2_hdr(struct l2_packet_data *l2, int rx_l2_hdr)
+{
+ l2->rx_l2_hdr = rx_l2_hdr;
+}
+
+int
+l2_packet_send(struct l2_packet_data *l2, u8 *buf, size_t len)
+{
+ return pcap_inject(l2->pcap, buf, len);
+}
+
+
+static void
+l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct l2_packet_data *l2 = eloop_ctx;
+ pcap_t *pcap = sock_ctx;
+ struct pcap_pkthdr hdr;
+ const u_char *packet;
+ struct l2_ethhdr *ethhdr;
+ unsigned char *buf;
+ size_t len;
+
+ packet = pcap_next(pcap, &hdr);
+
+ if (packet == NULL || hdr.caplen < sizeof(*ethhdr))
+ return;
+
+ ethhdr = (struct l2_ethhdr *) packet;
+ if (l2->rx_l2_hdr) {
+ buf = (unsigned char *) ethhdr;
+ len = hdr.caplen;
+ } else {
+ buf = (unsigned char *) (ethhdr + 1);
+ len = hdr.caplen - sizeof(*ethhdr);
+ }
+ l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
+}
+
+static int
+l2_packet_init_libpcap(struct l2_packet_data *l2, unsigned short protocol)
+{
+ bpf_u_int32 pcap_maskp, pcap_netp;
+ char pcap_filter[100], pcap_err[PCAP_ERRBUF_SIZE];
+ struct bpf_program pcap_fp;
+
+ pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
+ l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err);
+ if (l2->pcap == NULL) {
+ fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
+ fprintf(stderr, "ifname='%s'\n", l2->ifname);
+ return -1;
+ }
+ if (pcap_datalink(l2->pcap) != DLT_EN10MB &&
+ pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) {
+ fprintf(stderr, "pcap_set_datalinke(DLT_EN10MB): %s\n",
+ pcap_geterr(l2->pcap));
+ return -1;
+ }
+ snprintf(pcap_filter, sizeof(pcap_filter),
+ "ether dst " MACSTR " and ether proto 0x%x",
+ MAC2STR(l2->own_addr), protocol);
+ if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
+ fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
+ return -1;
+ }
+
+ if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
+ fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap));
+ return -1;
+ }
+
+ pcap_freecode(&pcap_fp);
+ /*
+ * When libpcap uses BPF we must enable "immediate mode" to
+ * receive frames right away; otherwise the system may
+ * buffer them for us.
+ */
+ { unsigned int on = 1;
+ if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) {
+ fprintf(stderr, "%s: cannot enable immediate mode on "
+ "interface %s: %s\n",
+ __func__, l2->ifname, strerror(errno));
+ /* XXX should we fail? */
+ }
+ }
+
+ eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap),
+ l2_packet_receive, l2, l2->pcap);
+
+ return 0;
+}
+
+static int
+eth_get(const char *device, u8 ea[ETH_ALEN])
+{
+ struct if_msghdr *ifm;
+ struct sockaddr_dl *sdl;
+ u_char *p, *buf;
+ size_t len;
+ int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+ return -1;
+ if ((buf = malloc(len)) == NULL)
+ return -1;
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return -1;
+ }
+ for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
+ ifm = (struct if_msghdr *)p;
+ sdl = (struct sockaddr_dl *)(ifm + 1);
+ if (ifm->ifm_type != RTM_IFINFO ||
+ (ifm->ifm_addrs & RTA_IFP) == 0)
+ continue;
+ if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
+ memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0)
+ continue;
+ memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
+ break;
+ }
+ free(buf);
+
+ if (p >= buf + len) {
+ errno = ESRCH;
+ return -1;
+ }
+ return 0;
+}
+
+struct l2_packet_data *
+l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol,
+ void (*rx_callback)(void *ctx, unsigned char *src_addr,
+ unsigned char *buf, size_t len),
+ void *rx_callback_ctx)
+{
+ struct l2_packet_data *l2;
+
+ l2 = malloc(sizeof(struct l2_packet_data));
+ if (l2 == NULL)
+ return NULL;
+ memset(l2, 0, sizeof(*l2));
+ strncpy(l2->ifname, ifname, sizeof(l2->ifname));
+ l2->rx_callback = rx_callback;
+ l2->rx_callback_ctx = rx_callback_ctx;
+
+ if (eth_get(l2->ifname, l2->own_addr) < 0) {
+ fprintf(stderr, "Failed to get link-level address for "
+ "interface '%s'.\n", l2->ifname);
+ free(l2);
+ return NULL;
+ }
+
+ if (l2_packet_init_libpcap(l2, protocol) != 0) {
+ free(l2);
+ return NULL;
+ }
+ return l2;
+}
+
+void
+l2_packet_deinit(struct l2_packet_data *l2)
+{
+ if (l2 != NULL) {
+ if (l2->pcap)
+ pcap_close(l2->pcap);
+ free(l2);
+ }
+}
diff --git a/usr.sbin/wpa/wpa_cli/Makefile b/usr.sbin/wpa/wpa_cli/Makefile
new file mode 100644
index 0000000..927a30e
--- /dev/null
+++ b/usr.sbin/wpa/wpa_cli/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+WPA_SUPPLICANT_DISTDIR?= ${.CURDIR}/../../../contrib/wpa_supplicant
+.PATH: ${WPA_SUPPLICANT_DISTDIR}
+
+PROG= wpa_cli
+SRCS= wpa_cli.c wpa_ctrl.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/wpa/wpa_cli/wpa_cli.1 b/usr.sbin/wpa/wpa_cli/wpa_cli.1
new file mode 100644
index 0000000..b28f5b7
--- /dev/null
+++ b/usr.sbin/wpa/wpa_cli/wpa_cli.1
@@ -0,0 +1,192 @@
+.\" 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_CLI 1
+.Os
+.Sh NAME
+.Nm wpa_cli
+.Nd "text-based frontend program for interacting with wpa_supplicant"
+.Sh SYNOPSIS
+.Nm
+.Op commands
+.Sh DESCRIPTION
+.Nm
+is a text-based frontend program for interacting with
+.Xr wpa_supplicant 1.
+.Nm
+is used to query current status,
+change configuration,
+trigger events,
+and
+request interactive user input.
+.Pp
+.Nm
+can show the
+current authentication status,
+selected security
+mode, dot11 and dot1x MIBs, etc.
+In addition,
+.Nm
+can configure EAPOL state machine
+parameters and trigger events like reassociation
+and IEEE 802.1X logoff/logon.
+.Nm
+provides a user interface to request authentication information,
+like username and password, if these are not included in the
+configuration.
+This can be used to implement,
+e.g., one-time-passwords or generic token card
+authentication where the authentication is based on a
+challenge-response that uses an external device for generating the
+response.
+.Pp
+The control interface of
+.Nm wpa_supplicant
+can be configured to allow
+non-root user access (ctrl_interface_group in the configuration file).
+This makes it possible to run
+.Nm
+with a normal user account.
+.Pp
+.Nm
+supports two modes: interactive and command line.
+Both modes share the same command set and the main difference
+is in interactive mode providing access to unsolicited messages
+(event messages, username/password requests).
+.Pp
+Interactive mode is started when
+.Nm
+is executed without with any parameters on the command line.
+Commands are then entered from the controlling terminal in
+response to the
+.Nm
+prompt.
+In command line mode, the same commands are
+entered as command line arguments.
+.Sh AUTHENTICATION PARAMETERS
+.Pp
+When
+.Nm wpa_supplicant
+needs authentication parameters, such as username and password,
+that are not present in the configuration file, it sends a
+request message to all attached frontend programs, e.g.,
+.Nm
+in interactive mode.
+.Nm
+shows these requests with
+"CTRL-REQ-<type>-<id>:<text>" prefix.
+<type> is IDENTITY, PASSWORD, or OTP (one-time-password).
+<id> is a unique identifier for the current network.
+<text> is description of the request.
+In case of OTP request, it includes the challenge from
+the authentication server.
+.Pp
+A user must supply
+.Nm wpa_supplicant
+the needed parameters in response to these requests.
+.Pp
+For example,
+.Bd -literal
+CTRL-REQ-PASSWORD-1:Password needed for SSID foobar
+> password 1 mysecretpassword
+
+Example request for generic token card challenge-response:
+
+CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
+> otp 2 9876
+.Ed
+.Sh COMMANDS
+The following commands may be supplied on the command line
+or at a prompt when operating interactively.
+.Bl -tag -width indent
+.It status
+Report the current WPA/EAPOL/EAP status for the current interface.
+.It mib
+Report MIB variables (dot1x, dot11) for the current interface.
+.It help
+Show usage help.
+.It interface [ Ar ifname ]
+Show available interfaces and/or set the current interface
+when multiple are available.
+.It level <debug level>
+Change the debugging level in
+.Nm wpa_supplicant .
+Larger numbers generate more messages.
+.It license
+Display the full
+.Nm
+license for
+.Nm .
+.It logoff
+Send the IEEE 802.1X EAPOL state machine into the logoff state.
+.It logon
+Send the IEEE 802.1X EAPOL state machine into the logon state.
+.It set [ settings ]
+Set variables.
+When no arguments are supplied the known variables and their settings
+are displayed.
+.It pmksa
+Show the contents of the PMKSA cache.
+.It reassociate
+Force a reassociation to the current access point.
+.It reconfigure
+Force
+.Nm
+to re-read its configuration file.
+.It preauthenticate <BSSID>
+Force preauthentication of the specified BSSID.
+.It identity <network id> <identity>
+Configure an identity for an SSID.
+.It password <network id> <password>
+Configure a password for an SSID.
+.It otp <network id> <password>
+Configure a one-time-password for an SSID.
+.It terminate
+Force
+.Nm wpa_supplicant
+to terminate.
+.It quit
+Exit
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr wpa_supplicant 1 ,
+.Xr wpa_supplicant.conf 5
+.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/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