- Add usr.sbin/802_11 to hold wpa_supplicant and other 802.11 related
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 24 Jun 2006 07:29:44 +0000 (07:29 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 24 Jun 2006 07:29:44 +0000 (07:29 +0000)
  programs' building infrastructures
- Add build infrastructure for wpa_supplicant-0.4.9 under newly added
  usr.sbin/802_11
- Hook 802_11/wpa_supplicant building

Obtained-from: FreeBSD (mainly sam@freebsd.org)

12 files changed:
usr.sbin/802_11/Makefile [new file with mode: 0644]
usr.sbin/802_11/Makefile.inc [new file with mode: 0644]
usr.sbin/802_11/l2_packet.c [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/Makefile [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/Packet32.c [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/Packet32.h [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/common.h [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/driver_dragonfly.c [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/ntddndis.h [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8 [new file with mode: 0644]
usr.sbin/802_11/wpa_supplicant/wpa_supplicant.conf.5 [new file with mode: 0644]
usr.sbin/Makefile

diff --git a/usr.sbin/802_11/Makefile b/usr.sbin/802_11/Makefile
new file mode 100644 (file)
index 0000000..15445d4
--- /dev/null
@@ -0,0 +1,5 @@
+# $DragonFly: src/usr.sbin/802_11/Makefile,v 1.1 2006/06/24 07:29:44 sephe Exp $
+
+SUBDIR= wpa_supplicant
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/802_11/Makefile.inc b/usr.sbin/802_11/Makefile.inc
new file mode 100644 (file)
index 0000000..e7b8609
--- /dev/null
@@ -0,0 +1,3 @@
+# $DragonFly: src/usr.sbin/802_11/Makefile.inc,v 1.1 2006/06/24 07:29:44 sephe Exp $
+
+.include "../Makefile.inc"
diff --git a/usr.sbin/802_11/l2_packet.c b/usr.sbin/802_11/l2_packet.c
new file mode 100644 (file)
index 0000000..8b2147f
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * 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: src/usr.sbin/wpa/l2_packet.c,v 1.1.2.2 2006/03/24 01:43:17 sam Exp $
+ * $DragonFly: src/usr.sbin/802_11/l2_packet.c,v 1.1 2006/06/24 07:29:44 sephe Exp $
+ */
+
+/*
+ * FreeBSD-specific implementation.
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <net/bpf.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <pcap.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, const u8 *src_addr,
+                           const u8 *buf, size_t len);
+       void *rx_callback_ctx;
+       int l2_hdr; /* whether to include layer 2 (Ethernet) header data
+                    * buffers */
+};
+
+int
+l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
+{
+       memcpy(addr, l2->own_addr, ETH_ALEN);
+       return 0;
+}
+
+int
+l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
+{
+       pcap_if_t *devs, *dev;
+       struct pcap_addr *addr;
+       struct sockaddr_in *saddr;
+       int found = 0;
+       char err[PCAP_ERRBUF_SIZE + 1];
+
+       if (pcap_findalldevs(&devs, err) < 0) {
+               wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err);
+               return -1;
+       }
+
+       for (dev = devs; dev && !found; dev = dev->next) {
+               if (strcmp(dev->name, l2->ifname) != 0)
+                       continue;
+
+               addr = dev->addresses;
+               while (addr) {
+                       saddr = (struct sockaddr_in *) addr->addr;
+                       if (saddr && saddr->sin_family == AF_INET) {
+                               snprintf(buf, len, "%s",
+                                        inet_ntoa(saddr->sin_addr));
+                               found = 1;
+                               break;
+                       }
+                       addr = addr->next;
+               }
+       }
+
+       pcap_freealldevs(devs);
+
+       return found ? 0 : -1;
+}
+
+void
+l2_packet_notify_auth_start(struct l2_packet_data *l2)
+{
+}
+
+int
+l2_packet_send(struct l2_packet_data *l2,
+       const u8 *dst_addr, u16 proto, const u8 *buf, size_t len)
+{
+       if (!l2->l2_hdr) {
+               int ret;
+               struct l2_ethhdr *eth = malloc(sizeof(*eth) + len);
+               if (eth == NULL)
+                       return -1;
+               memcpy(eth->h_dest, dst_addr, ETH_ALEN);
+               memcpy(eth->h_source, l2->own_addr, ETH_ALEN);
+               eth->h_proto = htons(proto);
+               memcpy(eth + 1, buf, len);
+               ret = pcap_inject(l2->pcap, (u8 *) eth, len + sizeof(*eth));
+               free(eth);
+               return ret;
+       } else
+               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->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 void
+l2_packet_deinit_libpcap(struct l2_packet_data *l2)
+{
+       if (l2->pcap != NULL) {
+               eloop_unregister_read_sock(pcap_get_selectable_fd(l2->pcap));
+               pcap_close(l2->pcap);
+               l2->pcap = NULL;
+       }
+}
+
+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, const u8 *src_addr,
+                           const u8 *buf, size_t len),
+       void *rx_callback_ctx, int l2_hdr)
+{
+       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;
+       l2->l2_hdr = l2_hdr;
+
+       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) {
+               l2_packet_deinit_libpcap(l2);
+               free(l2);
+       }
+}
diff --git a/usr.sbin/802_11/wpa_supplicant/Makefile b/usr.sbin/802_11/wpa_supplicant/Makefile
new file mode 100644 (file)
index 0000000..019f1a5
--- /dev/null
@@ -0,0 +1,54 @@
+# $FreeBSD: src/usr.sbin/wpa/wpa_supplicant/Makefile,v 1.3.2.3 2006/03/24 01:43:18 sam Exp $
+# $DragonFly: src/usr.sbin/802_11/wpa_supplicant/Makefile,v 1.1 2006/06/24 07:29:44 sephe Exp $
+
+SRCDIR= ${.CURDIR}/../../../contrib/wpa_supplicant-0.4.9
+
+.PATH: ${.CURDIR}/.. ${SRCDIR}
+
+PROG=  wpa_supplicant
+SRCS=  config.c eloop.c common.c md5.c rc4.c sha1.c aes_wrap.c \
+       wpa_supplicant.c events.c wpa.c preauth.c \
+       ctrl_iface.c l2_packet.c main.c drivers.c driver_dragonfly.c \
+       driver_ndis.c driver_ndis_.c Packet32.c
+
+MAN=   wpa_supplicant.8 wpa_supplicant.conf.5
+
+CFLAGS+= -I${.CURDIR} -I${SRCDIR}
+CFLAGS+= -DCONFIG_DRIVER_BSD
+CFLAGS+= -DCONFIG_DRIVER_NDIS
+CFLAGS+= -DCONFIG_CTRL_IFACE
+CFLAGS+= -g
+DPADD+=        ${LIBPCAP}
+LDADD+=        -lpcap
+
+# NB: we only support wpa_supplicant.conf file
+SRCS+= config_file.c base64.c
+CFLAGS+=-DCONFIG_BACKEND_FILE
+
+.if !defined(NO_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_psk_common.c \
+       eap_tlv.c eap_tls_common.c tls_openssl.c ms_funcs.c crypto.c
+
+CFLAGS+=-DEAP_TTLS -DEAP_MD5
+SRCS+= eap_ttls.c eap_md5.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/802_11/wpa_supplicant/Packet32.c b/usr.sbin/802_11/wpa_supplicant/Packet32.c
new file mode 100644 (file)
index 0000000..6ec865d
--- /dev/null
@@ -0,0 +1,397 @@
+/*-
+ * Copyright (c) 2005
+ *      Bill Paul <wpaul@windriver.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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
+ * 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: src/usr.sbin/wpa/wpa_supplicant/Packet32.c,v 1.2.2.2 2006/04/12 17:21:08 sam Exp $
+ * $DragonFly: src/usr.sbin/802_11/wpa_supplicant/Packet32.c,v 1.1 2006/06/24 07:29:44 sephe Exp $
+ */
+
+/*
+ * This file implements a small portion of the Winpcap API for the
+ * Windows NDIS interface in wpa_supplicant. It provides just enough
+ * routines to fool wpa_supplicant into thinking it's really running
+ * in a Windows environment.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/sysctl.h>
+#include <sys/fcntl.h>
+#include <sys/time.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_var.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/route.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pcap.h>
+
+#include "Packet32.h"
+
+#define OID_802_11_ADD_KEY      0x0d01011D
+
+typedef ULONGLONG NDIS_802_11_KEY_RSC;
+typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
+
+typedef struct NDIS_802_11_KEY {
+       ULONG Length;
+       ULONG KeyIndex;
+       ULONG KeyLength;
+       NDIS_802_11_MAC_ADDRESS BSSID;
+       NDIS_802_11_KEY_RSC KeyRSC;
+       UCHAR KeyMaterial[1];
+} NDIS_802_11_KEY;
+
+typedef struct NDIS_802_11_KEY_COMPAT {
+       ULONG Length;
+       ULONG KeyIndex;
+       ULONG KeyLength;
+       NDIS_802_11_MAC_ADDRESS BSSID;
+       UCHAR Pad[6]; /* Make struct layout match Windows. */
+       NDIS_802_11_KEY_RSC KeyRSC;
+#ifdef notdef
+       UCHAR KeyMaterial[1];
+#endif
+} NDIS_802_11_KEY_COMPAT;
+
+#define TRUE 1
+#define FALSE 0
+
+struct adapter {
+       int                     socket;
+       char                    name[IFNAMSIZ];
+};
+
+PCHAR
+PacketGetVersion(void)
+{
+       return("FreeBSD WinPcap compatibility shim v1.0");
+}
+
+void *
+PacketOpenAdapter(iface)
+       CHAR                    *iface;
+{
+       struct adapter          *a;
+       int                     s;
+       int                     ifflags;
+       struct ifreq            ifr;
+
+       s = socket(PF_INET, SOCK_DGRAM, 0);
+
+       if (s == -1)
+               return(NULL);
+
+       a = malloc(sizeof(struct adapter));
+       if (a == NULL)
+               return(NULL);
+
+       a->socket = s;
+       snprintf(a->name, IFNAMSIZ, "%s", iface);
+
+       bzero((char *)&ifr, sizeof(ifr));
+        strncpy(ifr.ifr_name, iface, sizeof (ifr.ifr_name));
+        if (ioctl(a->socket, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+               free(a);
+               close(s);
+               return(NULL);
+        }
+        ifr.ifr_flags |= IFF_UP;
+        if (ioctl(a->socket, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
+               free(a);
+               close(s);
+               return(NULL);
+        }
+
+       return(a);
+}
+
+int
+PacketRequest(iface, set, oid)
+       void                    *iface;
+       BOOLEAN                 set;
+       PACKET_OID_DATA         *oid;
+{
+       struct adapter          *a;
+       uint32_t                retval;
+       struct ifreq            ifr;
+       NDIS_802_11_KEY         *old;
+       NDIS_802_11_KEY_COMPAT  *new;
+       PACKET_OID_DATA         *o = NULL;
+
+       if (iface == NULL)
+               return(-1);
+
+       a = iface;
+       bzero((char *)&ifr, sizeof(ifr));
+
+       /*
+        * This hack is necessary to work around a difference
+        * betwee the GNU C and Microsoft C compilers. The NDIS_802_11_KEY
+        * structure has a uint64_t in it, right after an array of
+        * chars. The Microsoft compiler inserts padding right before
+        * the 64-bit value to align it on a 64-bit boundary, but
+        * GCC only aligns it on a 32-bit boundary. Trying to pass
+        * the GCC-formatted structure to an NDIS binary driver
+        * fails because some of the fields appear to be at the
+        * wrong offsets.
+        *
+        * To get around this, if we detect someone is trying to do
+        * a set operation on OID_802_11_ADD_KEY, we shuffle the data
+        * into a properly padded structure and pass that into the
+        * driver instead. This allows the driver_ndis.c code supplied
+        * with wpa_supplicant to work unmodified.
+        */
+
+       if (set == TRUE && oid->Oid == OID_802_11_ADD_KEY) {
+               old = (NDIS_802_11_KEY *)&oid->Data;
+               o = malloc(sizeof(PACKET_OID_DATA) +
+                   sizeof(NDIS_802_11_KEY_COMPAT) + old->KeyLength);
+               if (o == NULL)
+                       return(0);
+               bzero((char *)o, sizeof(PACKET_OID_DATA) +
+                   sizeof(NDIS_802_11_KEY_COMPAT) + old->KeyLength);
+               o->Oid = oid->Oid;
+               o->Length = sizeof(NDIS_802_11_KEY_COMPAT) + old->KeyLength;
+               new = (NDIS_802_11_KEY_COMPAT *)&o->Data;
+               new->KeyRSC = old->KeyRSC;
+               new->Length = o->Length;
+               new->KeyIndex = old->KeyIndex;
+               new->KeyLength = old->KeyLength;
+               bcopy(old->BSSID, new->BSSID, sizeof(NDIS_802_11_MAC_ADDRESS));
+               bcopy(old->KeyMaterial, (char *)new +
+                   sizeof(NDIS_802_11_KEY_COMPAT), new->KeyLength);
+               ifr.ifr_data = (caddr_t)o;
+       } else
+               ifr.ifr_data = (caddr_t)oid;
+
+        strlcpy(ifr.ifr_name, a->name, sizeof(ifr.ifr_name));
+
+       if (set == TRUE)
+               retval = ioctl(a->socket, SIOCSDRVSPEC, &ifr);
+       else
+               retval = ioctl(a->socket, SIOCGDRVSPEC, &ifr);
+
+       if (o != NULL)
+               free(o);
+
+       if (retval)
+               return(0);
+
+       return(1);
+}
+
+int
+PacketGetAdapterNames(namelist, len)
+       CHAR                    *namelist;
+       ULONG                   *len;
+{
+       int                     mib[6];
+       size_t                  needed;
+       struct if_msghdr        *ifm;
+       struct sockaddr_dl      *sdl;
+       char                    *buf, *lim, *next;
+       char                    *plist;
+       int                     spc;
+       int                     i, ifcnt = 0;
+
+       plist = namelist;
+       spc = 0;
+
+       bzero(plist, *len);
+
+       needed = 0;
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;             /* protocol */
+       mib[3] = 0;             /* wildcard address family */
+       mib[4] = NET_RT_IFLIST;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
+               return(FALSE);
+
+       buf = malloc (needed);
+       if (buf == NULL)
+               return(FALSE);
+
+       if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0) {
+               free(buf);
+               return(FALSE);
+       }
+
+       lim = buf + needed;
+
+       /* Generate interface name list. */
+
+       next = buf;
+       while (next < lim) {
+               ifm = (struct if_msghdr *)next;
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       sdl = (struct sockaddr_dl *)(ifm + 1);
+                       if (strnstr(sdl->sdl_data, "ndis", sdl->sdl_nlen)) {
+                               if ((spc + sdl->sdl_nlen) > *len) {
+                                       free(buf);
+                                       return(FALSE);
+                               }
+                               strncpy(plist, sdl->sdl_data, sdl->sdl_nlen);
+                               plist += (sdl->sdl_nlen + 1);
+                               spc += (sdl->sdl_nlen + 1);
+                               ifcnt++;
+                       }
+               }
+               next += ifm->ifm_msglen;
+       }
+
+
+       /* Insert an extra "" as a spacer */
+
+       plist++;
+       spc++;
+
+       /*
+        * Now generate the interface description list. There
+        * must be a unique description for each interface, and
+        * they have to match what the ndis_events program will
+        * feed in later. To keep this simple, we just repeat
+        * the interface list over again.
+        */
+
+       next = buf;
+       while (next < lim) {
+               ifm = (struct if_msghdr *)next;
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       sdl = (struct sockaddr_dl *)(ifm + 1);
+                       if (strnstr(sdl->sdl_data, "ndis", sdl->sdl_nlen)) {
+                               if ((spc + sdl->sdl_nlen) > *len) {
+                                       free(buf);
+                                       return(FALSE);
+                               }
+                               strncpy(plist, sdl->sdl_data, sdl->sdl_nlen);
+                               plist += (sdl->sdl_nlen + 1);
+                               spc += (sdl->sdl_nlen + 1);
+                               ifcnt++;
+                       }
+               }
+               next += ifm->ifm_msglen;
+       }
+
+       free (buf);
+
+       *len = spc + 1;
+
+       return(TRUE);
+}
+
+void
+PacketCloseAdapter(iface)
+       void                    *iface;
+{      
+       struct adapter          *a;
+       struct ifreq            ifr;
+
+       if (iface == NULL)
+               return;
+
+       a = iface;
+
+       bzero((char *)&ifr, sizeof(ifr));
+        strncpy(ifr.ifr_name, a->name, sizeof (ifr.ifr_name));
+        ioctl(a->socket, SIOCGIFFLAGS, (caddr_t)&ifr);
+        ifr.ifr_flags &= ~IFF_UP;
+        ioctl(a->socket, SIOCSIFFLAGS, (caddr_t)&ifr);
+       close(a->socket);
+       free(a);
+
+       return;
+}
+
+#if __FreeBSD_version < 600000
+
+/*
+ * The version of libpcap in FreeBSD 5.2.1 doesn't have these routines.
+ * Call me insane if you will, but I still run 5.2.1 on my laptop, and
+ * I'd like to use WPA there.
+ */
+
+int
+pcap_get_selectable_fd(pcap_t *p)
+{
+       return(pcap_fileno(p));
+}
+
+/*
+ * The old version of libpcap opens its BPF descriptor in read-only
+ * mode. We need to temporarily create a new one we can write to.
+ */
+
+int
+pcap_inject(pcap_t *p, const void *buf, size_t len)
+{
+       int                     fd;
+       int                     res, n = 0;
+       char                    device[sizeof "/dev/bpf0000000000"];
+       struct ifreq            ifr;
+
+        /*
+         * Go through all the minors and find one that isn't in use.
+         */
+       do {
+               (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+               fd = open(device, O_RDWR);
+       } while (fd < 0 && errno == EBUSY);
+
+       if (fd == -1)
+               return(-1);
+
+       bzero((char *)&ifr, sizeof(ifr));
+       ioctl(pcap_fileno(p), BIOCGETIF, (caddr_t)&ifr);
+       ioctl(fd, BIOCSETIF, (caddr_t)&ifr);
+
+       res = write(fd, buf, len);
+
+       close(fd);
+
+       return(res);
+}
+#endif
diff --git a/usr.sbin/802_11/wpa_supplicant/Packet32.h b/usr.sbin/802_11/wpa_supplicant/Packet32.h
new file mode 100644 (file)
index 0000000..9b57c30
--- /dev/null
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2005
+ *      Bill Paul <wpaul@windriver.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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
+ * 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: src/usr.sbin/wpa/wpa_supplicant/Packet32.h,v 1.2.2.1 2005/10/27 17:06:47 wpaul Exp $
+ * $DragonFly: src/usr.sbin/802_11/wpa_supplicant/Packet32.h,v 1.1 2006/06/24 07:29:44 sephe Exp $
+ */
+
+#ifndef _PACKET32_H_
+#define _PACKET32_H_
+
+#include <sys/types.h>
+#include <ntddndis.h>
+
+struct PACKET_OID_DATA {
+       uint32_t                Oid;
+       uint32_t                Length;
+       uint8_t                 Data[1];
+};
+
+
+typedef struct PACKET_OID_DATA PACKET_OID_DATA;
+
+extern PCHAR PacketGetVersion(void);
+extern void *PacketOpenAdapter(CHAR *);
+extern int PacketRequest(void *, BOOLEAN, PACKET_OID_DATA *);
+extern int PacketGetAdapterNames(CHAR *, ULONG *);
+extern void PacketCloseAdapter(void *);
+
+/*
+ * This is for backwards compatibility on FreeBSD 5.
+ */
+
+#ifndef SIOCGDRVSPEC
+#define SIOCSDRVSPEC   _IOW('i', 123, struct ifreq)    /* set driver-specific
+                                                               parameters */
+#define SIOCGDRVSPEC   _IOWR('i', 123, struct ifreq)   /* get driver-specific
+                                                               parameters */
+#endif
+
+#endif /* _PACKET32_H_ */
diff --git a/usr.sbin/802_11/wpa_supplicant/common.h b/usr.sbin/802_11/wpa_supplicant/common.h
new file mode 100644 (file)
index 0000000..3bae3dd
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * 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.
+ *
+ * $DragonFly: src/usr.sbin/802_11/wpa_supplicant/Attic/common.h,v 1.1 2006/06/24 07:29:44 sephe Exp $
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifdef __linux__
+#include <endian.h>
+#include <byteswap.h>
+#endif /* __linux__ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+#include <sys/types.h>
+#include <sys/endian.h>
+#define __BYTE_ORDER   _BYTE_ORDER
+#define        __LITTLE_ENDIAN _LITTLE_ENDIAN
+#define        __BIG_ENDIAN    _BIG_ENDIAN
+#define bswap_16 bswap16
+#define bswap_32 bswap32
+#define bswap_64 bswap64
+#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) */
+
+#ifdef CONFIG_NATIVE_WINDOWS
+#include <winsock2.h>
+
+static inline int daemon(int nochdir, int noclose)
+{
+       printf("Windows - daemon() not supported yet\n");
+       return -1;
+}
+
+static inline void sleep(int seconds)
+{
+       Sleep(seconds * 1000);
+}
+
+static inline void usleep(unsigned long usec)
+{
+       Sleep(usec / 1000);
+}
+
+#ifndef timersub
+#define timersub(a, b, res) do { \
+       (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+       (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+       if ((res)->tv_usec < 0) { \
+               (res)->tv_sec--; \
+               (res)->tv_usec += 1000000; \
+       } \
+} while (0)
+#endif
+
+struct timezone {
+       int  tz_minuteswest;
+       int  tz_dsttime;
+};
+
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+
+static inline long int random(void)
+{
+       return rand();
+}
+
+typedef int gid_t;
+typedef int socklen_t;
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0 /* not supported */
+#endif
+
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
+
+static inline unsigned short wpa_swap_16(unsigned short v)
+{
+       return ((v & 0xff) << 8) | (v >> 8);
+}
+
+static inline unsigned int wpa_swap_32(unsigned int v)
+{
+       return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
+               ((v & 0xff0000) >> 8) | (v >> 24);
+}
+
+#define le_to_host16(n) (n)
+#define host_to_le16(n) (n)
+#define be_to_host16(n) wpa_swap_16(n)
+#define host_to_be16(n) wpa_swap_16(n)
+#define le_to_host32(n) (n)
+#define be_to_host32(n) wpa_swap_32(n)
+#define host_to_be32(n) wpa_swap_32(n)
+
+#else /* __CYGWIN__ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define le_to_host16(n) (n)
+#define host_to_le16(n) (n)
+#define be_to_host16(n) bswap_16(n)
+#define host_to_be16(n) bswap_16(n)
+#define le_to_host32(n) (n)
+#define be_to_host32(n) bswap_32(n)
+#define host_to_be32(n) bswap_32(n)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define le_to_host16(n) bswap_16(n)
+#define host_to_le16(n) bswap_16(n)
+#define be_to_host16(n) (n)
+#define host_to_be16(n) (n)
+#define le_to_host32(n) bswap_32(n)
+#define be_to_host32(n) (n)
+#define host_to_be32(n) (n)
+#ifndef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN
+#endif
+#else
+#error Could not determine CPU byte order
+#endif
+
+#endif /* __CYGWIN__ */
+
+/* Macros for handling unaligned 16-bit variables */
+#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define WPA_PUT_BE16(a, val)                   \
+       do {                                    \
+               (a)[0] = ((u16) (val)) >> 8;    \
+               (a)[1] = ((u16) (val)) & 0xff;  \
+       } while (0)
+
+#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
+#define WPA_PUT_LE16(a, val)                   \
+       do {                                    \
+               (a)[1] = ((u16) (val)) >> 8;    \
+               (a)[0] = ((u16) (val)) & 0xff;  \
+       } while (0)
+
+#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
+                        (((u32) (a)[2]) << 8) | ((u32) (a)[3]))
+
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#include <stdint.h>
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+int hostapd_get_rand(u8 *buf, size_t len);
+void hostapd_hexdump(const char *title, const u8 *buf, size_t len);
+int hwaddr_aton(const char *txt, u8 *addr);
+int hexstr2bin(const char *hex, u8 *buf, size_t len);
+char * rel2abs_path(const char *rel_path);
+void inc_byte_array(u8 *counter, size_t len);
+void print_char(char c);
+void fprint_char(FILE *f, char c);
+
+
+/* Debugging function - conditional printf and hex dump. Driver wrappers can
+ *  use these for debugging purposes. */
+
+enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
+
+#ifdef CONFIG_NO_STDOUT_DEBUG
+
+#define wpa_debug_print_timestamp() do { } while (0)
+#define wpa_printf(args...) do { } while (0)
+#define wpa_hexdump(args...) do { } while (0)
+#define wpa_hexdump_key(args...) do { } while (0)
+#define wpa_hexdump_ascii(args...) do { } while (0)
+#define wpa_hexdump_ascii_key(args...) do { } while (0)
+
+#else /* CONFIG_NO_STDOUT_DEBUG */
+
+/**
+ * wpa_debug_printf_timestamp - Print timestamp for debug output
+ *
+ * This function prints a timestamp in <seconds from 1970>.<microsoconds>
+ * format if debug output has been configured to include timestamps in debug
+ * messages.
+ */
+void wpa_debug_print_timestamp(void);
+
+/**
+ * wpa_printf - conditional printf
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration.
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+void wpa_printf(int level, char *fmt, ...)
+__attribute__ ((format (printf, 2, 3)));
+
+/**
+ * wpa_hexdump - conditional hex dump
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump.
+ */
+void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
+
+/**
+ * wpa_hexdump_key - conditional hex dump, hide keys
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump. This works
+ * like wpa_hexdump(), but by default, does not include secret keys (passwords,
+ * etc.) in debug output.
+ */
+void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
+
+/**
+ * wpa_hexdump_ascii - conditional hex dump
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump with both
+ * the hex numbers and ASCII characters (for printable range) are shown. 16
+ * bytes per line will be shown.
+ */
+void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
+                      size_t len);
+
+/**
+ * wpa_hexdump_ascii_key - conditional hex dump, hide keys
+ * @level: priority level (MSG_*) of the message
+ * @title: title of for the message
+ * @buf: data buffer to be dumped
+ * @len: length of the buf
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump with both
+ * the hex numbers and ASCII characters (for printable range) are shown. 16
+ * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
+ * default, does not include secret keys (passwords, etc.) in debug output.
+ */
+void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
+                          size_t len);
+
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+
+#ifdef EAPOL_TEST
+#define WPA_ASSERT(a)                                                 \
+       do {                                                           \
+               if (!(a)) {                                            \
+                       printf("WPA_ASSERT FAILED '" #a "' "           \
+                              "%s %s:%d\n",                           \
+                              __FUNCTION__, __FILE__, __LINE__);      \
+                       exit(1);                                       \
+               }                                                      \
+       } while (0)
+#else
+#define WPA_ASSERT(a) do { } while (0)
+#endif
+
+#endif /* COMMON_H */
diff --git a/usr.sbin/802_11/wpa_supplicant/driver_dragonfly.c b/usr.sbin/802_11/wpa_supplicant/driver_dragonfly.c
new file mode 100644 (file)
index 0000000..b84c2ca
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+ * 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: src/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c,v 1.5.2.4 2006/03/24 01:43:18 sam Exp $
+ * $DragonFly: src/usr.sbin/802_11/wpa_supplicant/driver_dragonfly.c,v 1.1 2006/06/24 07:29:44 sephe Exp $
+ */
+
+#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 "wpa.h"                       /* XXX for RSN_INFO_ELEM */
+
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+
+#include <netproto/802_11/ieee80211.h>
+#include <netproto/802_11/ieee80211_crypto.h>
+#include <netproto/802_11/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 */
+       unsigned int ifindex;           /* interface index */
+       void    *ctx;
+       int     prev_roaming;           /* roaming state to restore on deinit */
+       int     prev_privacy;           /* privacy state to restore on deinit */
+       int     prev_wpa;               /* wpa state to restore on deinit */
+};
+
+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) {
+               fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
+                       op, arg_len, strerror(errno));
+               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) {
+               fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
+                       op, arg_len, strerror(errno));
+               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]");
+               fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
+                       op, arg, strerror(errno));
+               return -1;
+       }
+       return 0;
+}
+
+static int
+get80211param(struct wpa_driver_bsd_data *drv, int op)
+{
+       struct ieee80211req ireq;
+
+       memset(&ireq, 0, sizeof(ireq));
+       strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
+       ireq.i_type = op;
+
+       if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
+               perror("ioctl[SIOCG80211]");
+               fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
+                       op, strerror(errno));
+               return -1;
+       }
+       return ireq.i_val;
+}
+
+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_internal(void *priv, int wpa, int privacy)
+{
+       struct wpa_driver_bsd_data *drv = priv;
+       int ret = 0;
+
+       wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
+               __FUNCTION__, wpa, privacy);
+
+       if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
+               ret = -1;
+       if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
+               ret = -1;
+       if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
+               ret = -1;
+
+       return ret;
+}
+
+static int
+wpa_driver_bsd_set_wpa(void *priv, int enabled)
+{
+       wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
+
+       return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
+}
+
+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;
+
+       memset(&wk, 0, sizeof(wk));
+       if (addr != NULL &&
+           bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) {
+               struct ether_addr ea;
+
+               memcpy(&ea, addr, IEEE80211_ADDR_LEN);
+               wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d",
+                       __func__, ether_ntoa(&ea), key_idx);
+               memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
+               wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE;
+       } else {
+               wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx);
+               wk.idk_keyix = key_idx;
+       }
+       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;
+       struct ether_addr ea;
+       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",
+                       __func__, alg);
+               return -1;
+       }
+
+       memcpy(&ea, addr, IEEE80211_ADDR_LEN);
+       wpa_printf(MSG_DEBUG,
+               "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
+               __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
+               seq_len, key_len);
+
+       if (seq_len > sizeof(u_int64_t)) {
+               wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
+                       __func__, seq_len);
+               return -2;
+       }
+       if (key_len > sizeof(wk.ik_keydata)) {
+               wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
+                       __func__, 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;
+       memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+       /*
+        * Deduce whether group/global or unicast key by checking
+        * the address (yech).  Note also that we can only mark global
+        * keys default; doing this for a unicast key is an error.
+        */
+       if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
+               wk.ik_flags |= IEEE80211_KEY_GROUP;
+               wk.ik_keyix = key_idx;
+       } else {
+               wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
+       }
+       if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
+               wk.ik_flags |= IEEE80211_KEY_DEFAULT;
+       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", __func__, 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", __func__, 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", __func__);
+       memset(&mlme, 0, sizeof(mlme));
+       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", __func__);
+       memset(&mlme, 0, sizeof(mlme));
+       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 privacy;
+
+       wpa_printf(MSG_DEBUG,
+               "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
+               , __func__
+               , params->ssid_len, params->ssid
+               , params->wpa_ie_len
+               , params->pairwise_suite
+               , params->group_suite
+               , params->key_mgmt_suite
+       );
+
+       /* 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)
+               return -1;
+
+       privacy = !(params->pairwise_suite == CIPHER_NONE &&
+           params->group_suite == CIPHER_NONE &&
+           params->key_mgmt_suite == KEY_MGMT_NONE &&
+           params->wpa_ie_len == 0);
+       wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
+
+       if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
+               return -1;
+
+       if (params->wpa_ie_len &&
+           set80211param(drv, IEEE80211_IOC_WPA,
+                         params->wpa_ie[0] == RSN_INFO_ELEM ? 2 : 1) < 0)
+               return -1;
+
+       memset(&mlme, 0, sizeof(mlme));
+       mlme.im_op = IEEE80211_MLME_ASSOC;
+       if (params->ssid != NULL)
+               memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
+       mlme.im_ssid_len = params->ssid_len;
+       if (params->bssid != NULL)
+               memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
+       if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
+               return -1;
+       return 0;
+}
+
+static int
+wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
+{
+       struct wpa_driver_bsd_data *drv = priv;
+       int authmode;
+
+       if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
+           (auth_alg & AUTH_ALG_SHARED_KEY))
+               authmode = IEEE80211_AUTH_AUTO;
+       else if (auth_alg & AUTH_ALG_SHARED_KEY)
+               authmode = IEEE80211_AUTH_SHARED;
+       else
+               authmode = IEEE80211_AUTH_OPEN;
+
+       return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
+}
+
+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 <netproto/802_11/ieee80211_dragonfly.h>
+
+static void
+wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
+{
+       struct wpa_driver_bsd_data *drv = sock_ctx;
+       char buf[2048];
+       struct if_announcemsghdr *ifan;
+       struct if_msghdr *ifm;
+       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;
+       }
+       memset(&event, 0, sizeof(event));
+       switch (rtm->rtm_type) {
+       case RTM_IFANNOUNCE:
+               ifan = (struct if_announcemsghdr *) rtm;
+               if (ifan->ifan_index != drv->ifindex)
+                       break;
+               strlcpy(event.interface_status.ifname, drv->ifname,
+                       sizeof(event.interface_status.ifname));
+               switch (ifan->ifan_what) {
+               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:
+               ifan = (struct if_announcemsghdr *) rtm;
+               if (ifan->ifan_index != drv->ifindex)
+                       break;
+               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;
+       case RTM_IFINFO:
+               ifm = (struct if_msghdr *) rtm;
+               if (ifm->ifm_index != drv->ifindex)
+                       break;
+               if ((rtm->rtm_flags & RTF_UP) == 0) {
+                       strlcpy(event.interface_status.ifname, drv->ifname,
+                               sizeof(event.interface_status.ifname));
+                       event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+                       wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
+                                  event.interface_status.ifname);
+                       wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+               }
+               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)
+{
+#define        GETPARAM(drv, param, v) \
+       (((v) = get80211param(drv, param)) != -1)
+       struct wpa_driver_bsd_data *drv;
+
+       drv = malloc(sizeof(*drv));
+       if (drv == NULL)
+               return NULL;
+       memset(drv, 0, sizeof(*drv));
+       /*
+        * NB: We require the interface name be mappable to an index.
+        *     This implies we do not support having wpa_supplicant
+        *     wait for an interface to appear.  This seems ok; that
+        *     doesn't belong here; it's really the job of devd.
+        */
+       drv->ifindex = if_nametoindex(ifname);
+       if (drv->ifindex == 0) {
+               wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
+                          __func__, ifname);
+               goto fail1;
+       }
+       drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
+       if (drv->sock < 0)
+               goto fail1;
+       drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
+       if (drv->route < 0)
+               goto fail;
+       eloop_register_read_sock(drv->route,
+               wpa_driver_bsd_event_receive, ctx, drv);
+
+       drv->ctx = ctx;
+       strncpy(drv->ifname, ifname, sizeof(drv->ifname));
+
+       if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
+               wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
+                       __func__, strerror(errno));
+               goto fail;
+       }
+       if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
+               wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
+                       __func__, strerror(errno));
+               goto fail;
+       }
+       if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
+               wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
+                       __func__, strerror(errno));
+               goto fail;
+       }
+       if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
+               wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
+                          "roaming: %s", __func__, strerror(errno));
+               goto fail;
+       }
+
+       if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
+               wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
+                          __func__, strerror(errno));
+               goto fail;
+       }
+
+       return drv;
+fail:
+       close(drv->sock);
+fail1:
+       free(drv);
+       return NULL;
+#undef GETPARAM
+}
+
+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);
+
+       wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
+       if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
+               wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
+                       __func__);
+
+       (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,
+       .set_auth_alg           = wpa_driver_bsd_set_auth_alg,
+};
diff --git a/usr.sbin/802_11/wpa_supplicant/ntddndis.h b/usr.sbin/802_11/wpa_supplicant/ntddndis.h
new file mode 100644 (file)
index 0000000..1cfb201
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _NTDDNDIS_H_
+#define _NTDDNDIS_H_
+
+/*
+ * $FreeBSD: src/usr.sbin/wpa/wpa_supplicant/ntddndis.h,v 1.2.2.1 2005/10/27 17:06:47 wpaul Exp $
+ * $DragonFly: src/usr.sbin/802_11/wpa_supplicant/ntddndis.h,v 1.1 2006/06/24 07:29:44 sephe Exp $
+ */
+
+/*
+ * Fake up some of the Windows type definitions so that the NDIS
+ * interface module in wpa_supplicant will build.
+ */
+
+#define ULONG uint32_t
+#define USHORT uint16_t
+#define UCHAR uint8_t
+#define LONG int32_t
+#define SHORT int16_t
+#define CHAR int8_t
+#define ULONGLONG uint64_t
+#define LONGLONG int64_t
+#define BOOLEAN uint8_t
+typedef void * LPADAPTER;
+typedef char * PTSTR;
+typedef char * PCHAR;
+
+#define TRUE 1
+#define FALSE 0
+
+#define OID_802_3_CURRENT_ADDRESS               0x01010102
+
+#endif /* _NTDDNDIS_H_ */
diff --git a/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8 b/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8
new file mode 100644 (file)
index 0000000..b578434
--- /dev/null
@@ -0,0 +1,150 @@
+.\" 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: src/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.8,v 1.2 2005/06/27 06:40:43 ru Exp $
+.\" $DragonFly: src/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8,v 1.1 2006/06/24 07:29:44 sephe Exp $
+.\"
+.Dd June 24, 2006
+.Dt WPA_SUPPLICANT 8
+.Os
+.Sh NAME
+.Nm wpa_supplicant
+.Nd "WPA/802.11i Supplicant for wireless network devices"
+.Sh SYNOPSIS
+.Nm
+.Op Fl BdehLqvw
+.Fl i Ar ifname
+.Fl c Ar config-file
+.Op Fl N i Ar ifname Fl c Ar config-file ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+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 an Authentication Server.
+In addition,
+.Nm
+controls the roaming and IEEE 802.11
+authentication/association support of the
+.Xr wlan 4
+module and can be used to configure static WEP keys
+based on identified networks.
+.Pp
+The
+.Nm
+utility
+is designed to be a
+.Dq daemon
+program that runs in the
+background and acts as the backend component controlling
+the wireless connection.
+It supports separate frontend programs such as the
+text-based
+.Xr wpa_cli 8
+program.
+.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 wireless interface.
+See
+.Xr wpa_supplicant.conf 5
+for a description of the configuration file syntax and contents.
+.Pp
+Changes to the configuration file can be reloaded by sending a
+.Dv SIGHUP
+to the
+.Nm
+process or with the
+.Xr wpa_cli 8
+utility, using
+.Dq Li "wpa_cli reconfigure" .
+.El
+.Sh OPTIONS
+The following options are available:
+.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.
+This option is not normally used; instead,
+.Xr devd 8
+should be configured to launch
+.Nm
+when a device is created.
+.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 i Ar ifname Fl c 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 ipw 4 ,
+.Xr iwi 4 ,
+.Xr ral 4 ,
+.Xr wi 4 ,
+.Xr wlan 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
+.Pa README
+file included in the
+.Nm
+distribution.
diff --git a/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.conf.5 b/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.conf.5
new file mode 100644 (file)
index 0000000..2fe9fa0
--- /dev/null
@@ -0,0 +1,530 @@
+.\" 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: src/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5,v 1.3.2.4 2006/02/21 17:19:54 sam Exp $
+.\" $DragonFly: src/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.conf.5,v 1.1 2006/06/24 07:29:44 sephe Exp $
+.\"
+.Dd June 24, 2006
+.Dt WPA_SUPPLICANT.CONF 5
+.Os
+.Sh NAME
+.Nm wpa_supplicant.conf
+.Nd configuration file for
+.Xr wpa_supplicant 8
+.Sh DESCRIPTION
+The
+.Xr wpa_supplicant 8
+utility 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 using
+configuration information stored in a text file.
+.Pp
+The configuration file consists of optional global parameter
+settings and one or more network blocks, e.g.\&
+one for each used SSID.
+The
+.Xr wpa_supplicant 8
+utility
+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.
+Comments are indicated with the
+.Ql #
+character; all text to the
+end of the line will be ignored.
+.Sh GLOBAL PARAMETERS
+Default parameters used by
+.Xr wpa_supplicant 8
+may be overridden by specifying
+.Pp
+.Dl parameter=value
+.Pp
+in the configuration file (note no spaces are allowed).
+Values with embedded spaces must be enclosed in quote marks.
+.Pp
+The following parameters are recognized:
+.Bl -tag -width indent
+.It Va ctrl_interface
+The pathname of the directory in which
+.Xr wpa_supplicant 8
+creates
+.Ux
+domain socket files for communication
+with frontend programs such as
+.Xr wpa_cli 8 .
+.It Va ctrl_interface_group
+A group name or group ID to use in setting protection on the
+control interface file.
+This can be set to allow non-root users to access the
+control interface files.
+If no group is specified, the group ID of the control interface
+is not modified and will, typically, be the
+group ID of the directory in which the socket is created.
+.It Va eapol_version
+The IEEE 802.1x/EAPOL protocol version to use; either 1 (default) or 2.
+The
+.Xr wpa_supplicant 8
+utility
+is implemented according to IEEE 802-1X-REV-d8 which defines
+EAPOL version to be 2.
+However, some access points do not work when presented with
+this version so by default
+.Xr wpa_supplicant 8
+will announce that it is using EAPOL version 1.
+If version 2 must be announced for correct operation with an
+access point, this value may be set to 2.
+.It Va ap_scan
+Access point scanning and selection control; one of 0, 1 (default), or 2.
+Only setting 1 should be used with the
+.Xr wlan 4
+module; the other settings are for use on other operating systems.
+.It Va fast_reauth
+EAP fast re-authentication; either 1 (default) or 0.
+Control fast re-authentication support in EAP methods that support it.
+.El
+.Sh NETWORK BLOCKS
+Each potential network/access point should have a
+.Dq "network block"
+that describes how to identify it and how to set up security.
+When multiple network blocks are listed in a configuration file,
+the highest priority one is selected for use or, if multiple networks
+with the same priority are identified, the first one listed in the
+configuration file is used.
+.Pp
+A network block description is of the form:
+.Bd -literal -offset indent
+network={
+       parameter=value
+       ...
+}
+.Ed
+.Pp
+(note the leading
+.Qq Li "network={"
+may have no spaces).
+The block specification contains one or more parameters
+from the following list:
+.Bl -tag -width indent
+.It Va ssid No (required)
+Network name (as announced by the access point).
+An
+.Tn ASCII
+or hex string enclosed in quotation marks.
+.It Va scan_ssid
+SSID scan technique; 0 (default) or 1.
+Technique 0 scans for the SSID using a broadcast Probe Request
+frame while 1 uses a directed Probe Request frame.
+Access points that cloak themselves by not broadcasting their SSID
+require technique 1, but beware that this scheme can cause scanning
+to take longer to complete.
+.It Va bssid
+Network BSSID (typically the MAC address of the access point).
+.It Va priority
+The priority of a network when selecting among multiple networks;
+a higher value means a network is more desirable.
+By default networks have priority 0.
+When multiple networks with the same priority are considered
+for selection, other information such as security policy and
+signal strength are used to select one.
+.It Va mode
+IEEE 802.11 operation mode; either 0 (infrastructure, default) or 1 (IBSS).
+Note that IBSS (adhoc) mode can only be used with
+.Va key_mgmt
+set to
+.Li NONE
+(plaintext and static WEP).
+.It Va proto
+List of acceptable protocols; one or more of:
+.Li WPA
+(IEEE 802.11i/D3.0)
+and
+.Li RSN
+(IEEE 802.11i).
+.Li WPA2
+is another name for
+.Li RSN .
+If not set this defaults to
+.Qq Li "WPA RSN" .
+.It Va key_mgmt
+List of acceptable key management protocols; one or more of:
+.Li WPA-PSK
+(WPA pre-shared key),
+.Li WPA-EAP
+(WPA using EAP authentication),
+.Li IEEE8021X
+(IEEE 802.1x using EAP authentication and,
+optionally, dynamically generated WEP keys),
+.Li NONE
+(plaintext or static WEP keys).
+If not set this defaults to
+.Qq Li "WPA-PSK WPA-EAP" .
+.It Va auth_alg
+List of allowed IEEE 802.11 authentication algorithms; one or more of:
+.Li OPEN
+(Open System authentication, required for WPA/WPA2),
+.Li SHARED
+(Shared Key authentication),
+.Li LEAP
+(LEAP/Network EAP).
+If not set automatic selection is used (Open System with LEAP
+enabled if LEAP is allowed as one of the EAP methods).
+.It Va pairwise
+List of acceptable pairwise (unicast) ciphers for WPA; one or more of:
+.Li CCMP
+(AES in Counter mode with CBC-MAC, RFC 3610, IEEE 802.11i/D7.0),
+.Li TKIP
+(Temporal Key Integrity Protocol, IEEE 802.11i/D7.0),
+.Li NONE
+(deprecated).
+If not set this defaults to
+.Qq Li "CCMP TKIP" .
+.It Va group
+List of acceptable group (multicast) ciphers for WPA; one or more of:
+.Li CCMP
+(AES in Counter mode with CBC-MAC, RFC 3610, IEEE 802.11i/D7.0),
+.Li TKIP
+(Temporal Key Integrity Protocol, IEEE 802.11i/D7.0),
+.Li WEP104
+(WEP with 104-bit key),
+.Li WEP40
+(WEP with 40-bit key).
+If not set this defaults to
+.Qq Li "CCMP TKIP WEP104 WEP40" .
+.It Va psk
+WPA preshared key used in WPA-PSK mode.
+The key is specified as 64 hex digits or as
+an 8-63 character
+.Tn ASCII
+passphrase.
+.Tn ASCII
+passphrases are converted to a 256-bit key using the network SSID.
+.It Va eapol_flags
+Dynamic WEP key usage for non-WPA mode, specified as a bit field.
+Bit 0 (1) forces dynamically generated unicast WEP keys to be used.
+Bit 1 (2) forces dynamically generated broadcast WEP keys to be used.
+By default this is set to 3 (use both).
+.It Va eap
+List of acceptable EAP methods; one or more of:
+.Li MD5
+(EAP-MD5, cannot be used with WPA,
+used only as a Phase 2 method with EAP-PEAP or EAP-TTLS),
+.Li MSCHAPV2
+(EAP-MSCHAPV2, cannot be used with WPA;
+used only as a Phase 2 method with EAP-PEAP or EAP-TTLS),
+.Li OTP
+(EAP-OTP, cannot be used with WPA;
+used only as a Phase 2 metod with EAP-PEAP or EAP-TTLS),
+.Li GTC
+(EAP-GTC, cannot be used with WPA;
+used only as a Phase 2 metod with EAP-PEAP or EAP-TTLS),
+.Li TLS
+(EAP-TLS, client and server certificate),
+.Li PEAP
+(EAP-PEAP, with tunneled EAP authentication),
+.Li TTLS
+(EAP-TTLS, with tunneled EAP or PAP/CHAP/MSCHAP/MSCHAPV2 authentication).
+If not set this defaults to all available methods compiled in to
+.Xr wpa_supplicant 8 .
+Note that by default
+.Xr wpa_supplicant 8
+is compiled with EAP support; see
+.Xr make.conf 5
+for the
+.Va NO_WPA_SUPPLICANT_EAPOL
+configuration variable that can be used to disable EAP support.
+.It Va identity
+Identity string for EAP.
+.It Va anonymous_identity
+Anonymous identity string for EAP (to be used as the unencrypted identity
+with EAP types that support different tunneled identities; e.g.\& EAP-TTLS).
+.It Va password
+Password string for EAP.
+.It Va ca_cert
+Pathname to CA certificate file.
+This file can have one or more trusted CA certificates.
+If
+.Va ca_cert
+is not included, server certificates will not be verified (not recommended).
+.It Va client_cert
+Pathname to client certificate file (PEM/DER).
+.It Va private_key
+Pathname to a client private key file (PEM/DER/PFX).
+When a PKCS#12/PFX file is used, then
+.Va client_cert
+should not be specified as both the private key and certificate will be
+read from PKCS#12 file.
+.It Va private_key_passwd
+Password for any private key file.
+.It Va dh_file
+Pathname to a file holding DH/DSA parameters (in PEM format).
+This file holds parameters for an ephemeral DH key exchange.
+In most cases, the default RSA authentication does not use this configuration.
+However, it is possible to set up RSA to use an ephemeral DH key exchange.
+In addition, ciphers with
+DSA keys always use ephemeral DH keys.
+This can be used to achieve forward secrecy.
+If the
+.Va dh_file
+is in DSA parameters format, it will be automatically converted
+into DH params.
+.It Va subject_match
+Substring to be matched against the subject of the
+authentication server certificate.
+If this string is set, the server
+certificate is only accepted if it contains this string in the subject.
+The subject string is in following format:
+.Pp
+.Dl "/C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@example.com"
+.It Va phase1
+Phase1 (outer authentication, i.e., TLS tunnel) parameters
+(string with field-value pairs, e.g.,
+.Qq Li peapver=0
+or
+.Qq Li "peapver=1 peaplabel=1" ) .
+.Bl -inset
+.It Li peapver
+can be used to force which PEAP version (0 or 1) is used.
+.It Li peaplabel=1
+can be used to force new label,
+.Dq "client PEAP encryption" ,
+to be used during key derivation when PEAPv1 or newer.
+Most existing PEAPv1 implementations seem to be using the old label,
+.Dq Li "client EAP encryption" ,
+and
+.Xr wpa_supplicant 8
+is now using that as the
+default value.
+Some servers, e.g.,
+.Tn Radiator ,
+may require
+.Li peaplabel=1
+configuration to interoperate with PEAPv1; see
+.Pa eap_testing.txt
+for more details.
+.It Li peap_outer_success=0
+can be used to terminate PEAP authentication on
+tunneled EAP-Success.
+This is required with some RADIUS servers that
+implement
+.Pa draft-josefsson-pppext-eap-tls-eap-05.txt
+(e.g.,
+.Tn Lucent NavisRadius v4.4.0
+with PEAP in
+.Dq "IETF Draft 5"
+mode).
+.It Li include_tls_length=1
+can be used to force
+.Xr wpa_supplicant 8
+to include
+TLS Message Length field in all TLS messages even if they are not
+fragmented.
+.It Li sim_min_num_chal=3
+can be used to configure EAP-SIM to require three
+challenges (by default, it accepts 2 or 3)
+.It Li fast_provisioning=1
+option enables in-line provisioning of EAP-FAST
+credentials (PAC).
+.El
+.It Va phase2
+phase2: Phase2 (inner authentication with TLS tunnel) parameters
+(string with field-value pairs, e.g.,
+.Qq Li "auth=MSCHAPV2"
+for EAP-PEAP or
+.Qq Li "autheap=MSCHAPV2 autheap=MD5"
+for EAP-TTLS).
+.It Va ca_cert2
+Like
+.Va ca_cert
+but for EAP inner Phase 2.
+.It Va client_cert2
+Like
+.Va client_cert
+but for EAP inner Phase 2.
+.It Va private_key2
+Like
+.Va private_key
+but for EAP inner Phase 2.
+.It Va private_key2_passwd
+Like
+.Va private_key_passwd
+but for EAP inner Phase 2.
+.It Va dh_file2
+Like
+.Va dh_file
+but for EAP inner Phase 2.
+.It Va subject_match2
+Like
+.Va subject_match
+but for EAP inner Phase 2.
+.It Va eappsk
+16-byte pre-shared key in hex format for use with EAP-PSK.
+.It Va nai
+User NAI for use with EAP-PSK.
+.It Va server_nai
+Authentication Server NAI for use with EAP-PSK.
+.It Va pac_file
+Pathname to the file to use for PAC entries with EAP-FAST.
+The
+.Xr wpa_supplicant 8
+utility
+must be able to create this file and write updates to it when
+PAC is being provisioned or refreshed.
+.It Va eap_workaround
+Enable/disable EAP workarounds for various interoperability issues
+with misbehaving authentication servers.
+By default these workarounds are enabled.
+String EAP conformance can be configured by setting this to 0.
+.El
+.Sh CERTIFICATES
+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
+.Nm
+file as
+.Va private_key_passwd .
+.Pp
+The
+.Xr wpa_supplicant 8
+utility
+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 a suitable PEM/DER format for
+use by
+.Xr wpa_supplicant 8 .
+This can be done using the
+.Xr openssl 1
+program, e.g.\& with the 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
+.Ed
+.Sh EXAMPLES
+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
+.Pp
+Traditional WEP configuration with 104 bit key specified in hexadecimal.
+Note the WEP key is not quoted.
+.Bd -literal
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+        ssid="example"
+        scan_ssid=1
+        key_mgmt=NONE
+        wep_tx_keyidx=0
+        wep_key0=42FEEDDEAFBABEDEAFBEEFAA55
+}
+.Ed
+.Sh SEE ALSO
+.Xr wpa_supplicant 8
+.Sh HISTORY
+The
+.Nm
+manual page and
+.Xr wpa_supplicant 8
+functionality first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+This manual page is derived from the
+.Pa README
+and
+.Pa wpa_supplicant.conf
+files in the
+.Nm wpa_supplicant
+distribution provided by
+.An Jouni Malinen Aq jkmaline@cc.hut.fi .
index 2fc3b99..58738a3 100644 (file)
@@ -1,9 +1,10 @@
 #      From: @(#)Makefile      5.20 (Berkeley) 6/12/93
 # $FreeBSD: src/usr.sbin/Makefile,v 1.183.2.14 2003/04/16 11:01:51 ru Exp $
-# $DragonFly: src/usr.sbin/Makefile,v 1.28 2006/04/01 02:55:36 sephe Exp $
+# $DragonFly: src/usr.sbin/Makefile,v 1.29 2006/06/24 07:29:44 sephe Exp $
 
 # XXX MISSING:         mkproto
-SUBDIR=        IPXrouted \
+SUBDIR= 802_11 \
+       IPXrouted \
        ac \
        accton \
        acpi \