From ae456864c832178281744e29512afbd33316a0e1 Mon Sep 17 00:00:00 2001 From: wpaul Date: Mon, 10 Oct 2005 17:51:12 +0000 Subject: Enable -D ndis support in wpa_supplicant and add the ndis_events utility. This allows wpa_supplicant to work with WPA and WPA2 compliant NDIS drivers. --- usr.sbin/wpa/wpa_supplicant/Makefile | 4 +- usr.sbin/wpa/wpa_supplicant/Packet32.c | 388 +++++++++++++++++++++++++++++++++ usr.sbin/wpa/wpa_supplicant/Packet32.h | 66 ++++++ usr.sbin/wpa/wpa_supplicant/ntddndis.h | 30 +++ 4 files changed, 487 insertions(+), 1 deletion(-) create mode 100644 usr.sbin/wpa/wpa_supplicant/Packet32.c create mode 100644 usr.sbin/wpa/wpa_supplicant/Packet32.h create mode 100644 usr.sbin/wpa/wpa_supplicant/ntddndis.h (limited to 'usr.sbin/wpa/wpa_supplicant') diff --git a/usr.sbin/wpa/wpa_supplicant/Makefile b/usr.sbin/wpa/wpa_supplicant/Makefile index 7ab6414..19e0b24 100644 --- a/usr.sbin/wpa/wpa_supplicant/Makefile +++ b/usr.sbin/wpa/wpa_supplicant/Makefile @@ -6,12 +6,14 @@ WPA_SUPPLICANT_DISTDIR?= ${.CURDIR}/../../../contrib/wpa_supplicant 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 + ctrl_iface.c l2_packet.c drivers.c driver_freebsd.c \ + driver_ndis.c driver_ndis_.c Packet32.c MAN= wpa_supplicant.8 wpa_supplicant.conf.5 CFLAGS+= -I${.CURDIR} -I${WPA_SUPPLICANT_DISTDIR} CFLAGS+= -DCONFIG_DRIVER_BSD +CFLAGS+= -DCONFIG_DRIVER_NDIS CFLAGS+= -DCONFIG_CTRL_IFACE CFLAGS+= -g DPADD+= ${LIBPCAP} diff --git a/usr.sbin/wpa/wpa_supplicant/Packet32.c b/usr.sbin/wpa/wpa_supplicant/Packet32.c new file mode 100644 index 0000000..dafa6b9 --- /dev/null +++ b/usr.sbin/wpa/wpa_supplicant/Packet32.c @@ -0,0 +1,388 @@ +/*- + * Copyright (c) 2005 + * Bill Paul . 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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]; +}; + +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(EIO); + + buf = malloc (needed); + if (buf == NULL) + return(ENOMEM); + + if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + return(EIO); + } + + 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(ENOSPC); + } + 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(ENOSPC); + } + 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(0); +} + +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/wpa/wpa_supplicant/Packet32.h b/usr.sbin/wpa/wpa_supplicant/Packet32.h new file mode 100644 index 0000000..a3f715d --- /dev/null +++ b/usr.sbin/wpa/wpa_supplicant/Packet32.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2005 + * Bill Paul . 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$ + */ + +#ifndef _PACKET32_H_ +#define _PACKET32_H_ + +#include +#include + +struct PACKET_OID_DATA { + uint32_t Oid; + uint32_t Length; + uint8_t Data[1]; +}; + + +typedef struct PACKET_OID_DATA PACKET_OID_DATA; + +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/wpa/wpa_supplicant/ntddndis.h b/usr.sbin/wpa/wpa_supplicant/ntddndis.h new file mode 100644 index 0000000..97dd608 --- /dev/null +++ b/usr.sbin/wpa/wpa_supplicant/ntddndis.h @@ -0,0 +1,30 @@ +#ifndef _NTDDNDIS_H_ +#define _NTDDNDIS_H_ + +/* + * $FreeBSD$ + */ + +/* + * 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; + +#define TRUE 1 +#define FALSE 0 + +#define OID_802_3_CURRENT_ADDRESS 0x01010102 + +#endif /* _NTDDNDIS_H_ */ -- cgit v1.1