experimental OpenBSD support

Brian Fundakowski Feldman bfeldman
Tue Jun 24 10:39:43 PDT 2003


I've completed support for using OpenBSD as a kernel-only HostAP in
conjunction with hostapd as an 802.1x authenticator.  Has anyone else
tried something like this?  Check it out and tell me what you think! 
Not all of the changes are useful only to OpenBSD, so hopefully it's
helpful to some other folks as well.  Here are some miscellaneous notes:

1. Per-station keys could be quite a bit more expensive and not really
any more secure than broadcast keys changing "quickly" so I haven't
implemented them.  I don't think there are many situations where it's
truly useful to have partitioning of individual AP's traffic from
eachother's view.
2. The kernel changes to OpenBSD are not all required, but there are
several important bug fixes/feature additions that the hostapd will
need.  The kernel headers need to be reinstalled after patching.
3. Authorization is implemented differently in that it is divorced from
802.1x and accessed using the "back-channel" mechanisms on the network
interface (bpf + bpf-ioctl(BIOCSTAGGED)).
4. I've simply disabled the parts of hostapd on OpenBSD that should not
be used (/yet).  I believe that it should still work on Linux with the
non-OpenBSD-specific changes made.
5. Thanks for making such a nice hostapd and authenticator!  I'll be
happy to answer any questions about my changes.

-- 
Brian Fundakowski Feldman                    |     
http://www.fla.fujitsu.com/
Software Specialist                          |  Fujitsu Laboratories of
America
-------------- next part --------------
Index: hostapd/Makefile
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/Makefile	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/Makefile	24 Jun 2003 13:06:28 -0000	1.3
@@ -1,8 +1,5 @@
-CC=gcc
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+DEBUG?=	-g
+CFLAGS+= -Wall
 
 # define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
 # a file (undefine it, if you want to save in binary size)
@@ -15,15 +12,17 @@
 # CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
 
 OBJS =	hostapd.o eloop.o ieee802_1x.o eapol_sm.o radius.o md5.o rc4.o \
-	common.o iapp.o ieee802_11.o config.o ieee802_11_auth.o accounting.o \
+	common.o ieee802_11.o config.o accounting.o \
 	sta_info.o driver.o receive.o radius_client.o
+NOTOPENBSD = iapp.o ieee802_11_auth.o 
+LIBS = -lpcap
 
 all: hostapd
 
 hostapd: $(OBJS)
-	$(CC) -o hostapd $(OBJS)
+	$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
 
 clean:
 	rm -f core *~ *.o hostapd *.d
 
--include $(OBJS:%.o=%.d)
+#-include $(OBJS:%.o=%.d)
Index: hostapd/accounting.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/accounting.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/accounting.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/accounting.c	17 Jun 2003 19:04:18 -0000	1.2
@@ -151,7 +151,10 @@
 {
 	struct radius_msg *msg;
 	int cause = sta->acct_terminate_cause;
+#ifndef __OpenBSD__
+	/* XXX OpenBSD has no support for per-host wireless accounting. */
 	struct hostap_sta_driver_data data;
+#endif
 
 	if (!hapd->conf->acct_server)
 		return;
@@ -168,6 +171,7 @@
 		goto fail;
 	}
 
+#ifndef __OpenBSD__
 	if (hostapd_read_sta_driver_data(hapd, &data, sta->addr) == 0) {
 		if (!radius_msg_add_attr_int32(msg,
 					       RADIUS_ATTR_ACCT_INPUT_PACKETS,
@@ -194,6 +198,7 @@
 			goto fail;
 		}
 	}
+#endif
 
 	if (eloop_terminated())
 		cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
Index: hostapd/ap.h
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/ap.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ap.h
--- hostapd/ap.h	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/ap.h	24 Jun 2003 13:15:09 -0000
@@ -73,6 +73,13 @@
 #define STA_HASH(sta) (sta[5])
 
 
+#ifdef __OpenBSD__
+/*
+ * Since we're only polling the kernel for when _it_ has removed a client,
+ * we can check more often on OpenBSD.
+ */
+#define AP_MAX_INACTIVITY 10
+#else
 /* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
  * passed since last received frame from the station, a nullfunc data frame is
  * sent to the station. If this frame is not acknowledged and no other frames
@@ -81,6 +88,7 @@
  * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with
  * max inactivity timer. All these times are in seconds. */
 #define AP_MAX_INACTIVITY (5 * 60)
+#endif
 #define AP_DISASSOC_DELAY (1)
 #define AP_DEAUTH_DELAY (1)
 
Index: hostapd/common.h
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/common.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/common.h	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/common.h	17 Jun 2003 19:04:19 -0000	1.2
@@ -1,6 +1,24 @@
 #ifndef COMMON_H
 #define COMMON_H
 
+#ifdef __OpenBSD__
+#include <sys/types.h>
+#include <machine/endian.h>
+#define le_to_host16(n) letoh16(n)
+#define host_to_le16(n) htole16(n)
+#define be_to_host16(n) betoh16(n)
+#define host_to_be16(n) htobe16(n)
+
+typedef u_int64_t u64;
+typedef u_int32_t u32;
+typedef u_int16_t u16;
+typedef u_int8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+#else
 #include <endian.h>
 #include <byteswap.h>
 #if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -25,6 +43,7 @@
 typedef int32_t s32;
 typedef int16_t s16;
 typedef int8_t s8;
+#endif
 
 int hostapd_get_rand(u8 *buf, size_t len);
 void hostapd_hexdump(const char *title, u8 *buf, size_t len);
Index: hostapd/config.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/config.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- hostapd/config.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/config.c	24 Jun 2003 12:24:34 -0000	1.4
@@ -193,6 +193,7 @@
 		if (pos == NULL) {
 			printf("Line %d: invalid line '%s'\n", line, buf);
 			errors++;
+			continue;
 		}
 		*pos = '\0';
 		pos++;
@@ -252,6 +253,8 @@
 			conf->assoc_ap = 1;
 		} else if (strcmp(buf, "ieee8021x") == 0) {
 			conf->ieee802_1x = atoi(pos);
+		} else if (strcmp(buf, "port_authorization") == 0) {
+			conf->port_authorization = atoi(pos);
 		} else if (strcmp(buf, "minimal_eap") == 0) {
 			conf->minimal_eap = atoi(pos);
 		} else if (strcmp(buf, "eap_message") == 0) {
@@ -284,6 +287,8 @@
 			}
 		} else if (strcmp(buf, "eapol_key_index_workaround") == 0) {
 			conf->eapol_key_index_workaround = atoi(pos);
+		} else if (strcmp(buf, "wep_need_two_keys_immediately") == 0) {
+			conf->wep_need_two_keys = atoi(pos);
 		} else if (strcmp(buf, "iapp_interface") == 0) {
 			conf->ieee802_11f = 1;
 			snprintf(conf->iapp_iface, sizeof(conf->iapp_iface),
Index: hostapd/config.h
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/config.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/config.h	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/config.h	24 Jun 2003 12:24:34 -0000	1.3
@@ -34,6 +34,7 @@
 	int daemonize; /* fork into background */
 
 	int ieee802_1x; /* use IEEE 802.1X */
+	int port_authorization; /* enable/disable 802.11 ports via kernel */
 	int minimal_eap; /* test version of EAP authentication that only
 			  * requires EAP Response-Identity and authorizes any
 			  * station */
@@ -55,6 +56,7 @@
 	size_t default_wep_key_len;
 	int individual_wep_key_len;
 	int wep_rekeying_period;
+	int wep_need_two_keys;
 
 	int ieee802_11f; /* use IEEE 802.11f (IAPP) */
 	char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
Index: hostapd/driver.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/driver.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- hostapd/driver.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/driver.c	24 Jun 2003 11:46:46 -0000	1.4
@@ -13,10 +13,19 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
 #include <sys/ioctl.h>
 #include <netinet/in.h>
 
-#ifdef USE_KERNEL_HEADERS
+#if defined(__OpenBSD__)
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+#include <netinet/if_ether.h>   /* The L2 protocols */
+#include <net/if_ieee80211.h>
+#include <dev/ic/if_wi_hostap.h>
+#elif defined(USE_KERNEL_HEADERS)
 #include <asm/types.h>
 #include <linux/if_packet.h>
 #include <linux/if_ether.h>   /* The L2 protocols */
@@ -31,6 +40,7 @@
 #include "hostapd.h"
 #include "driver.h"
 #include "ieee802_1x.h"
+#include "ieee802_11.h"
 
 
 int hostapd_set_iface_flags(hostapd *hapd, int dev_up)
@@ -41,7 +51,11 @@
 		return -1;
 
 	memset(&ifr, 0, sizeof(ifr));
+#ifdef __OpenBSD__
+	strncpy(ifr.ifr_name, hapd->conf->iface, IFNAMSIZ);
+#else
 	snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", hapd->conf->iface);
+#endif
 
 	if (ioctl(hapd->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
 		perror("ioctl[SIOCGIFFLAGS]");
@@ -59,6 +73,31 @@
 	}
 
 	if (dev_up) {
+#ifdef __OpenBSD__
+		int flags;
+
+		ifr.ifr_media = IFM_MAKEWORD(IFM_TYPE(IFM_IEEE80211),
+			IFM_SUBTYPE(IFM_AUTO),
+			IFM_OPTIONS(IFM_IEEE80211|IFM_IEEE80211_HOSTAP),
+			IFM_INST(0));
+		if (ioctl(hapd->ioctl_sock, SIOCSIFMEDIA, &ifr) != 0) {
+			perror("ioctl[SIOCSIFMEDIA]");
+			return -1;
+		}
+		ifr.ifr_data = (void *)&flags;
+		if (ioctl(hapd->ioctl_sock, SIOCHOSTAP_GFLAGS, &ifr) != 0) {
+			perror("ioctl[SIOCHOSTAP_GFLAGS]");
+			return -1;
+		}
+		if (hapd->conf->port_authorization)
+			flags |= WIHAPFL_AUTHORIZED_FILT;
+		else
+			flags &= ~WIHAPFL_AUTHORIZED_FILT;
+		if (ioctl(hapd->ioctl_sock, SIOCHOSTAP_SFLAGS, &ifr) != 0) {
+			perror("ioctl[SIOCHOSTAP_SFLAGS]");
+			return -1;
+		}
+#else
 		memset(&ifr, 0, sizeof(ifr));
 		snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", hapd->conf->iface);
 		ifr.ifr_mtu = HOSTAPD_MTU;
@@ -67,12 +106,139 @@
 			printf("Setting MTU failed - trying to survive with "
 			       "current value\n");
 		}
+#endif
 	}
 
 	return 0;
 }
 
 
+#ifdef __OpenBSD__
+int hostap_ioctl_setiwessid(hostapd *hapd, char *buf, int len)
+{
+	struct ieee80211_nwid nwid;
+	struct ifreq ifr;
+
+	len--;	/* The NUL byte has been included. */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, hapd->conf->iface, IFNAMSIZ);
+	nwid.i_len = len < sizeof(nwid.i_nwid) ? len : sizeof(nwid.i_nwid);
+	memcpy(nwid.i_nwid, buf, nwid.i_len);
+	ifr.ifr_data = (void *)&nwid;
+	if (ioctl(hapd->ioctl_sock, SIOCS80211NWID, &ifr) != 0) {
+		perror("ioctl[SIOCS80211NWID]");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+void remove_sta(hostapd *hapd, struct sta_info *sta)
+{
+	struct hostap_sta hapsta;
+	struct ifreq ifr;
+	int error;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, hapd->conf->iface, IFNAMSIZ);
+	ifr.ifr_data = (void *)&hapsta;
+	memcpy(hapsta.addr, sta->addr, ETH_ALEN);
+	if (sta->flags & WLAN_STA_ASSOC && sta->flags & WLAN_STA_AUTH) {
+		/* Here, we are called FROM ieee802_1x_set_port_enabled(). */
+		error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_GET, &ifr);
+		if (error == 0) {
+			hapsta.flags &= ~HOSTAP_FLAGS_AUTHORIZED;
+			error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_CHANGE,
+			    &ifr);
+		}
+	} else if (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_AUTH)) {
+		/* Remove just assoc or auth. */
+		error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_GET, &ifr);
+		if (error == 0) {
+			if (sta->flags & WLAN_STA_AUTH)
+				hapsta.flags &= ~HOSTAP_FLAGS_ASSOC;
+			else
+				hapsta.flags &= ~HOSTAP_FLAGS_AUTHEN;
+			error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_CHANGE,
+			    &ifr);
+		}
+	} else {
+		ieee802_1x_set_port_enabled(hapd, sta, 0);
+		error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_DEL, &ifr);
+	}
+	if (error != 0) {
+		perror("ioctl");
+		printf("Could not remove STA " MACSTR " from kernel driver.\n",
+		    MAC2STR(sta->addr));
+	}
+}
+
+
+void hostapd_set_sta_authorized(hostapd *hapd, struct sta_info *sta)
+{
+	struct hostap_sta hapsta;
+	struct ifreq ifr;
+	int error;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, hapd->conf->iface, IFNAMSIZ);
+	ifr.ifr_data = (void *)&hapsta;
+	memcpy(hapsta.addr, sta->addr, ETH_ALEN);
+	error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_GET, &ifr);
+	if (error == 0) {
+		hapsta.flags |= HOSTAP_FLAGS_AUTHORIZED;
+		error = ioctl(hapd->ioctl_sock, SIOCHOSTAP_CHANGE, &ifr);
+	}
+	if (error != 0) {
+		perror("ioctl");
+		printf("Could not authorize STA " MACSTR " in kernel driver.\n",
+		    MAC2STR(sta->addr));
+	}
+}
+
+
+int hostapd_read_sta_driver_flags(hostapd *hapd, u8 *sta)
+{
+	struct hostap_sta hapsta;
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, hapd->conf->iface, IFNAMSIZ);
+	ifr.ifr_data = (void *)&hapsta;
+	memcpy(hapsta.addr, sta, ETH_ALEN);
+	if (ioctl(hapd->ioctl_sock, SIOCHOSTAP_GET, &ifr) != 0)
+		return -1;
+	return (((hapsta.flags & HOSTAP_FLAGS_AUTHEN) ? WLAN_STA_AUTH : 0) |
+		((hapsta.flags & HOSTAP_FLAGS_ASSOC) ? WLAN_STA_ASSOC : 0) |
+		((hapsta.flags & HOSTAP_FLAGS_AUTHORIZED) ?
+		WLAN_STA_AUTHORIZED : 0));
+}
+
+
+int hostapd_set_encryption(hostapd *hapd, const char *alg, u8 *addr,
+			   int idx, u8 *key, size_t key_len)
+{
+	struct ieee80211_nwkey nwkey;
+
+	memset(&nwkey, 0, sizeof(nwkey));
+	if (addr != NULL) {
+		printf("Cannot use per-host WEP on OpenBSD.\n");
+		return -1;
+	}
+	strncpy(nwkey.i_name, hapd->conf->iface, IFNAMSIZ);
+	nwkey.i_wepon = IEEE80211_NWKEY_WEP;
+	nwkey.i_defkid = idx + 1;
+	nwkey.i_key[idx].i_keylen = key_len;
+	nwkey.i_key[idx].i_keydat = key;
+	if (ioctl(hapd->ioctl_sock, SIOCS80211NWKEY, &nwkey) != 0) {
+		printf("Failed to set encryption.\n");
+		return -1;
+	}
+
+	return 0;
+}
+#else
 int hostapd_ioctl(hostapd *hapd, struct prism2_hostapd_param *param, int len)
 {
 	struct iwreq iwr;
@@ -222,12 +388,18 @@
 {
 	struct prism2_hostapd_param param;
 
-	ieee802_1x_set_port_enabled(hapd, sta, 0);
-
 	memset(&param, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
 	memcpy(param.sta_addr, sta->addr, ETH_ALEN);
-	if (hostapd_ioctl(hapd, &param, sizeof(param))) {
-		printf("Could not remove station from kernel driver.\n");
+	if (sta->flags & WLAN_STA_ASSOC && sta->flags & WLAN_STA_AUTH) {
+		/* Removed WLAN_STA_AUTHORIZED */
+		param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
+		param.u.set_flags_sta.flags_and = ~WLAN_STA_AUTHORIZED;
+	} else {
+		/* Removing station completely */
+		ieee802_1x_set_port_enabled(hapd, sta, 0);
+		param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
 	}
+	if (hostapd_ioctl(hapd, &param, sizeof(param)))
+		printf("Could not remove station from kernel driver.\n");
 }
+#endif
Index: hostapd/driver.h
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/driver.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/driver.h	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/driver.h	23 Jun 2003 21:43:25 -0000	1.3
@@ -12,10 +12,14 @@
 int hostap_ioctl_setiwessid(hostapd *hapd, char *buf, int len);
 int hostapd_set_encryption(hostapd *hapd, const char *alg, u8 *addr,
 			   int idx, u8 *key, size_t key_len);
+void hostapd_set_sta_authorized(hostapd *hapd, struct sta_info *sta);
 void remove_sta(hostapd *hapd, struct sta_info *sta);
 int hostapd_flush(hostapd *hapd);
 int hostapd_read_sta_driver_data(hostapd *hapd,
 				 struct hostap_sta_driver_data *data,
 				 u8 *addr);
+#ifdef __OpenBSD__
+int hostapd_read_sta_driver_flags(hostapd *hapd, u8 *sta);
+#endif
 
 #endif /* DRIVER_H */
Index: hostapd/eloop.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/eloop.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/eloop.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/eloop.c	17 Jun 2003 19:04:19 -0000	1.2
@@ -39,6 +39,7 @@
 	int sig;
 	void *user_data;
 	void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
+	int raised;
 };
 
 struct eloop_data {
@@ -170,16 +171,30 @@
 }
 
 
+/* Execute signals in a safe context so non-recursive functions can be used. */
 static void eloop_handle_signal(int sig)
 {
 	int i;
 
 	for (i = 0; i < eloop.signal_count; i++) {
 		if (eloop.signals[i].sig == sig) {
+			eloop.signals[i].raised = 1;
+			break;
+		}
+	}
+}
+
+
+static void eloop_do_signal_handlers(void)
+{
+	int i;
+
+	for (i = 0; i < eloop.signal_count; i++) {
+		if (eloop.signals[i].raised) {
+			eloop.signals[i].raised = 0;
 			eloop.signals[i].handler(eloop.signals[i].sig,
 						 eloop.user_data,
 						 eloop.signals[i].user_data);
-			break;
 		}
 	}
 }
@@ -202,6 +217,7 @@
 	tmp[eloop.signal_count].sig = sig;
 	tmp[eloop.signal_count].user_data = user_data;
 	tmp[eloop.signal_count].handler = handler;
+	tmp[eloop.signal_count].raised = 0;
 	eloop.signal_count++;
 	eloop.signals = tmp;
 	signal(sig, eloop_handle_signal);
@@ -235,9 +251,12 @@
 			FD_SET(eloop.readers[i].sock, &rfds);
 		res = select(eloop.max_sock + 1, &rfds, NULL, NULL,
 			     eloop.timeout ? &tv : NULL);
-		if (res < 0 && errno != EINTR) {
-			perror("select");
-			return;
+		if (res < 0) {
+			if (errno != EINTR) {
+				perror("select");
+				return;
+			}
+			eloop_do_signal_handlers();
 		}
 
 		/* check if some registered timeouts have occurred */
Index: hostapd/hostapd.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/hostapd.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/hostapd.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/hostapd.c	24 Jun 2003 12:24:34 -0000	1.3
@@ -20,6 +20,7 @@
 #include <stdarg.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <pcap.h>
 
 #include "eloop.h"
 #include "hostapd.h"
@@ -27,7 +28,9 @@
 #include "ieee802_11.h"
 #include "accounting.h"
 #include "eapol_sm.h"
+#ifndef __OpenBSD__
 #include "iapp.h"
+#endif
 #include "ap.h"
 #include "ieee802_11_auth.h"
 #include "sta_info.h"
@@ -146,9 +149,11 @@
 /* This function will be called whenever a station associates with the AP */
 void hostapd_new_assoc_sta(hostapd *hapd, struct sta_info *sta)
 {
+#ifndef __OpenBSD__
 	/* IEEE 802.11f (IAPP) */
 	if (hapd->conf->ieee802_11f)
 		iapp_new_station(hapd, sta);
+#endif
 
 	/* Start accounting here, if IEEE 802.1X is not used. IEEE 802.1X code
 	 * will start accounting after the station has been authorized. */
@@ -293,13 +298,21 @@
  * the key index, and direct Key Transmit State Machines of all of the
  * authenticators to send a new key to the authenticated stations.
  */
-static void hostapd_rotate_wep(void *eloop_ctx, void *timeout_ctx)
+static void hostapd_do_rotate_wep(hostapd *hapd)
 {
 	struct sta_info *s;
-	hostapd *hapd = eloop_ctx;
 
-	if (hapd->default_wep_key)
+	if (hapd->conf->wep_need_two_keys) {
+		/*
+		 * Generate two WEP keys here, the minimum for Windows if not
+		 * using any unicast keys.
+		 */
+		free(hapd->default_wep_key_2);
+		hapd->default_wep_key_2 = hapd->default_wep_key;
+		hapd->default_wep_key_idx_2 = hapd->default_wep_key_idx;
+	} else {
 		free(hapd->default_wep_key);
+	}
 
 	if (hapd->default_wep_key_idx >= 3)
 		hapd->default_wep_key_idx =
@@ -327,7 +340,15 @@
 			 	   hapd->conf->default_wep_key_len)) {
 		printf("Could not set WEP encryption.\n");
 	}
+}
+
 
+/* Rotate WEP keys and register for rekeying if necessary. */
+static void hostapd_rotate_wep(void *eloop_ctx, void *timeout_ctx)
+{
+	hostapd *hapd = eloop_ctx;
+
+	hostapd_do_rotate_wep(hapd);
 	if (hapd->conf->wep_rekeying_period > 0)
 		eloop_register_timeout(hapd->conf->wep_rekeying_period, 0,
 				       hostapd_rotate_wep, hapd, NULL);
@@ -336,16 +357,25 @@
 
 static void hostapd_cleanup(hostapd *hapd)
 {
-	if (hapd->sock >= 0)
-		close(hapd->sock);
+	if (hapd->sock >= 0) {
+		if (hapd->pcap != NULL)
+			pcap_close(hapd->pcap);
+		else
+			close(hapd->sock);
+	}
 	if (hapd->ioctl_sock >= 0)
 		close(hapd->ioctl_sock);
 	free(hapd->default_wep_key);
+	free(hapd->default_wep_key_2);
+#ifndef __OpenBSD__
 	if (hapd->conf->ieee802_11f)
 		iapp_deinit(hapd);
+#endif
 	accounting_deinit(hapd);
 	ieee802_1x_deinit(hapd);
+#ifndef __OpenBSD__
 	hostapd_acl_deinit(hapd);
+#endif
 	radius_client_deinit(hapd);
 
 	hostapd_config_free(hapd->conf);
@@ -359,11 +389,13 @@
 {
 	int ret = 0;
 
+#ifndef __OpenBSD__
 	printf("Flushing old station entries\n");
 	if (hostapd_flush(hapd)) {
 		printf("Could not connect to kernel driver.\n");
 		ret = -1;
 	}
+#endif
 	printf("Deauthenticate all stations\n");
 	hostapd_deauth_all_stas(hapd);
 
@@ -376,13 +408,22 @@
 	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL))
 		hostapd_hexdump("Default WEP key", hapd->default_wep_key,
 				hapd->conf->default_wep_key_len);
+	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL) &&
+	    hapd->default_wep_key_2 != NULL)
+		hostapd_hexdump("Default WEP key #2", hapd->default_wep_key_2,
+				hapd->conf->default_wep_key_len);
 
 	hostapd_set_encryption(hapd, "none", NULL, 0, NULL, 0);
 
 	if (hostapd_set_encryption(hapd, "WEP", NULL,
 				   hapd->default_wep_key_idx,
 				   hapd->default_wep_key,
-				   hapd->conf->default_wep_key_len)) {
+				   hapd->conf->default_wep_key_len) ||
+	    (hapd->default_wep_key_2 != NULL &&
+	     hostapd_set_encryption(hapd, "WEP", NULL,
+				    hapd->default_wep_key_idx_2,
+				    hapd->default_wep_key_2,
+				    hapd->conf->default_wep_key_len))) {
 		printf("Could not set WEP encryption.\n");
 		return -1;
 	}
@@ -408,16 +449,18 @@
 		return -1;
 	}
 
+#ifndef __OpenBSD__
 	if (hostap_ioctl_prism2param(hapd, PRISM2_PARAM_HOSTAPD, 1)) {
 		printf("Could not enable hostapd mode for interface %s\n",
 		       hapd->conf->iface);
 		return -1;
 	}
+#endif
 
 	if (hostapd_init_sockets(hapd))
 		return -1;
 
-	printf("Using interface %sap with hwaddr " MACSTR " and ssid '%s'\n",
+	printf("Using interface %s with hwaddr " MACSTR " and ssid '%s'\n",
 	       hapd->conf->iface, MAC2STR(hapd->own_addr), hapd->conf->ssid);
 
 	/* Set SSID for the kernel driver (to be used in beacon and probe
@@ -433,10 +476,12 @@
 		return -1;
 	}
 
+#ifndef __OpenBSD__
 	if (hostapd_acl_init(hapd)) {
 		printf("ACL initialization failed.\n");
 		return -1;
 	}
+#endif
 
 	if (ieee802_1x_init(hapd)) {
 		printf("IEEE 802.1X initialization failed.\n");
@@ -448,10 +493,12 @@
 		return -1;
 	}
 
+#ifndef __OpenBSD__
 	if (hapd->conf->ieee802_11f && iapp_init(hapd)) {
 		printf("IEEE 802.11f (IAPP) initialization failed.\n");
 		return -1;
 	}
+#endif
 
 	if (hapd->default_wep_key && hostapd_setup_encryption(hapd))
 		return -1;
@@ -561,6 +608,7 @@
 	eloop_register_signal(SIGINT, handle_term, NULL);
 	eloop_register_signal(SIGTERM, handle_term, NULL);
 	eloop_register_signal(SIGUSR1, handle_dump_state, NULL);
+	eloop_register_signal(SIGINFO, handle_dump_state, NULL);
 
 	for (i = 0; i < interfaces.count; i++) {
 		printf("Configuration file: %s\n", argv[optind + i]);
@@ -568,6 +616,8 @@
 		if (!interfaces.hapd[i])
 			goto out;
 		hostapd_set_broadcast_wep(interfaces.hapd[i]);
+		if (interfaces.hapd[i]->conf->wep_need_two_keys)
+			hostapd_do_rotate_wep(interfaces.hapd[i]);
 		if (hostapd_setup_interface(interfaces.hapd[i]))
 			goto out;
 	}
@@ -593,8 +643,10 @@
 		if (!interfaces.hapd[i])
 			continue;
 		(void) hostapd_set_iface_flags(interfaces.hapd[i], 0);
+#ifndef __OpenBSD__
 		(void) hostap_ioctl_prism2param(interfaces.hapd[i],
 						PRISM2_PARAM_HOSTAPD, 0);
+#endif
 
 		hostapd_cleanup(interfaces.hapd[i]);
 		free(interfaces.hapd[i]);
Index: hostapd/hostapd.conf
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/hostapd.conf,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/hostapd.conf	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/hostapd.conf	24 Jun 2003 12:44:10 -0000	1.3
@@ -3,7 +3,7 @@
 
 # AP netdevice name (without 'ap' prefix, i.e., wlan0 uses wlan0ap for
 # management frames)
-interface=wlan0
+interface=wi0
 
 # hostapd event logger configuration
 #
@@ -26,22 +26,22 @@
 logger_syslog=-1
 logger_syslog_level=2
 logger_stdout=-1
-logger_stdout_level=2
+logger_stdout_level=4
 
 # Debugging: 0 = no, 1 = minimal, 2 = verbose, 3 = msg dumps
-debug=0
+debug=3
 
-# Dump file for state information (on SIGUSR1)
-dump_file=/tmp/hostapd.dump
+# Dump file for state information (on SIGUSR1/SIGINFO)
+dump_file=/dev/stderr
 
 # Daemonize hostapd process (i.e., fork to background)
-daemonize=1
+daemonize=0
 
 
 ##### IEEE 802.11 related configuration #######################################
 
 # SSID to be used in IEEE 802.11 management frames
-ssid=test
+ssid=something
 
 # Station MAC address -based authentication
 # 0 = accept unless in deny list
@@ -61,7 +61,7 @@
 # Bit fields of allowed authentication algorithms:
 # bit 0 = Open System Authentication
 # bit 1 = Shared Key Authentication (requires WEP)
-auth_algs=3
+auth_algs=0
 
 # Associate as a station to another AP while still acting as an AP on the same
 # channel.
@@ -71,7 +71,10 @@
 ##### IEEE 802.1X (and IEEE 802.1aa/D4) related configuration #################
 
 # Require IEEE 802.1X authorization
-#ieee8021x=1
+ieee8021x=1
+
+# Use OS's 802.11 port authorization
+port_authorization=1
 
 # Use internal minimal EAP Authentication Server for testing IEEE 802.1X.
 # This should only be used for testing since it authorizes all users that
@@ -79,20 +82,26 @@
 minimal_eap=0
 
 # Optional displayable message sent with EAP Request-Identity
-eap_message=hello
+eap_message=Snownet
 
 # WEP rekeying (disabled if key lengths are not set or are set to 0)
 # Key lengths for default/broadcast and individual/unicast keys:
 # 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits)
 # 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits)
-#wep_key_len_broadcast=5
-#wep_key_len_unicast=5
+wep_key_len_broadcast=5
+# Unicast keys aren't supported on OpenBSD
+wep_key_len_unicast=0
 # Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once)
-#wep_rekey_period=300
+wep_rekey_period=300
 
 # EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if
 # only broadcast keys are used)
-eapol_key_index_workaround=0
+eapol_key_index_workaround=1
+
+# WEP keying workaround for Windows supplicants et al which require two
+# keys immediately.  This is necessary only if unicast keys are disabled
+# (wep_key_len_unicast=0).
+wep_need_two_keys_immediately=1
 
 
 ##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################
@@ -106,12 +115,12 @@
 # authentication with external ACL for MAC addresses, and accounting
 
 # The own IP address of the access point (used as NAS-IP-Address)
-own_ip_addr=127.0.0.1
+own_ip_addr=128.8.244.58
 
 # RADIUS authentication server
-#auth_server_addr=127.0.0.1
-#auth_server_port=1812
-#auth_server_shared_secret=secret
+auth_server_addr=128.8.244.14
+auth_server_port=1812
+auth_server_shared_secret=12345678
 
 # RADIUS accounting server
 #acct_server_addr=127.0.0.1
Index: hostapd/hostapd.h
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/hostapd.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/hostapd.h	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/hostapd.h	24 Jun 2003 12:24:34 -0000	1.3
@@ -13,10 +13,14 @@
 #ifndef ETH_P_ALL
 #define ETH_P_ALL 0x0003
 #endif
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888e
+#endif
 
 #include "hostap_wlan.h"
 #include "config.h"
 
+struct pcap;
 
 struct ieee80211_hdr {
 	u16 frame_control;
@@ -49,6 +53,7 @@
 	char *config_fname;
 
 	int sock; /* raw packet socket for driver access */
+	struct pcap *pcap; /* possible pcap associated with sock */
 	int ioctl_sock; /* socket for ioctl() use */
 	u8 own_addr[6];
 
@@ -63,8 +68,8 @@
 	struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
 
 
-	u8 *default_wep_key;
-	u8 default_wep_key_idx;
+	u8 *default_wep_key, *default_wep_key_2;
+	u8 default_wep_key_idx, default_wep_key_idx_2;
 
 	struct radius_client_data *radius;
 
Index: hostapd/ieee802_11.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/ieee802_11.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/ieee802_11.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/ieee802_11.c	23 Jun 2003 21:43:25 -0000	1.3
@@ -12,7 +12,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 #include <net/if.h>
+#include <netinet/in.h>
 #include <arpa/inet.h>
 #include <time.h>
 
@@ -28,6 +31,93 @@
 #include "rc4.h"
 
 
+static struct sta_info * auth_get_sta(hostapd *hapd, u8 *addr, int *isnew)
+{
+	struct sta_info *sta;
+
+	if (isnew != NULL)
+		*isnew = 0;
+	sta = ap_get_sta(hapd, addr);
+	if (sta)
+		return sta;
+
+	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "  New STA\n");
+	if (hapd->num_sta >= MAX_STA_COUNT) {
+		/* FIX: might try to remove some old STAs first? */
+		printf("  no more room for new STAs (%d/%d)\n",
+		       hapd->num_sta, MAX_STA_COUNT);
+		return NULL;
+	}
+
+	sta = (struct sta_info *) malloc(sizeof(struct sta_info));
+	if (sta == NULL) {
+		printf("  malloc failed\n");
+		return NULL;
+	}
+	memset(sta, 0, sizeof(struct sta_info));
+	sta->radius_identifier = -1;
+	sta->acct_session_id_lo = hapd->radius->acct_session_id_lo++;
+
+	/* initialize STA info data */
+	eloop_register_timeout(AP_MAX_INACTIVITY, 0, ap_handle_timer,
+			       hapd, sta);
+	memcpy(sta->addr, addr, ETH_ALEN);
+	sta->next = hapd->sta_list;
+	hapd->sta_list = sta;
+	hapd->num_sta++;
+	ap_sta_hash_add(hapd, sta);
+	if (isnew != NULL)
+		*isnew = 1;
+	return sta;
+}
+
+
+#ifdef __OpenBSD__
+struct sta_info * ieee802_11_locate_sta(hostapd *hapd, u8 *addr)
+{
+	struct sta_info *sta;
+	int isnew;
+
+	sta = auth_get_sta(hapd, addr, &isnew);
+	if (isnew) {
+		sta->flags |= WLAN_STA_ASSOC | WLAN_STA_AUTH;
+		hostapd_new_assoc_sta(hapd, sta);
+	}
+	return sta;
+}
+
+
+void ieee802_11_send_disassoc(hostapd *hapd, u8 *addr, u8 reason)
+{
+
+	/* Cheat for "the" broadcast address. */
+	if (memcmp("\377\377\377\377\377\377", addr, 6) != 0) {
+		struct sta_info *sta;
+
+		sta = ap_get_sta(hapd, addr);
+		if (sta != NULL) {
+			sta->flags &= ~WLAN_STA_ASSOC;
+			remove_sta(hapd, sta);
+		}
+	} else {
+		hostapd_free_stas(hapd);
+	}
+}
+
+
+void ieee802_11_send_deauth(hostapd *hapd, u8 *addr, u8 reason)
+{
+	struct sta_info *sta;
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta != NULL) {
+		sta->flags &= ~WLAN_STA_ASSOC;
+		remove_sta(hapd, sta);
+	}
+}
+
+
+#else
 static u8 * hostapd_eid_supp_rates(hostapd *hapd, u8 *eid)
 {
 	u8 *pos = eid;
@@ -252,43 +342,6 @@
 }
 
 
-static struct sta_info * auth_get_sta(hostapd *hapd, u8 *addr)
-{
-	struct sta_info *sta;
-
-	sta = ap_get_sta(hapd, addr);
-	if (sta)
-		return sta;
-
-	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "  New STA\n");
-	if (hapd->num_sta >= MAX_STA_COUNT) {
-		/* FIX: might try to remove some old STAs first? */
-		printf("  no more room for new STAs (%d/%d)\n",
-		       hapd->num_sta, MAX_STA_COUNT);
-		return NULL;
-	}
-
-	sta = (struct sta_info *) malloc(sizeof(struct sta_info));
-	if (sta == NULL) {
-		printf("  malloc failed\n");
-		return NULL;
-	}
-	memset(sta, 0, sizeof(struct sta_info));
-	sta->radius_identifier = -1;
-	sta->acct_session_id_lo = hapd->radius->acct_session_id_lo++;
-
-	/* initialize STA info data */
-	eloop_register_timeout(AP_MAX_INACTIVITY, 0, ap_handle_timer,
-			       hapd, sta);
-	memcpy(sta->addr, addr, ETH_ALEN);
-	sta->next = hapd->sta_list;
-	hapd->sta_list = sta;
-	hapd->num_sta++;
-	ap_sta_hash_add(hapd, sta);
-	return sta;
-}
-
-
 static u16 auth_shared_key(hostapd *hapd, struct sta_info *sta,
 			   u16 auth_transaction, u8 *challenge, int iswep)
 {
@@ -471,7 +524,7 @@
 		return;
 	}
 
-	sta = auth_get_sta(hapd, mgmt->sa);
+	sta = auth_get_sta(hapd, mgmt->sa, NULL);
 	if (!sta) {
 		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto fail;
@@ -1046,3 +1099,4 @@
 		break;
 	}
 }
+#endif
Index: hostapd/ieee802_11.h
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/ieee802_11.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/ieee802_11.h	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/ieee802_11.h	17 Jun 2003 19:04:19 -0000	1.2
@@ -85,6 +85,9 @@
 			int ok);
 ParseRes ieee802_11_parse_elems(hostapd *hapd, u8 *start, size_t len,
 				struct ieee802_11_elems *elems);
+#ifdef __OpenBSD__
+struct sta_info * ieee802_11_locate_sta(hostapd *hapd, u8 *addr);
+#endif
 
 
 #endif /* IEEE802_11_H */
Index: hostapd/ieee802_11_auth.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/ieee802_11_auth.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/ieee802_11_auth.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/ieee802_11_auth.c	17 Jun 2003 19:04:19 -0000	1.2
@@ -13,9 +13,10 @@
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
-#include <arpa/inet.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "hostapd.h"
 #include "ieee802_11.h"
Index: hostapd/ieee802_1x.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/ieee802_1x.c,v
retrieving revision 1.1.1.1
retrieving revision 1.5
diff -u -r1.1.1.1 -r1.5
--- hostapd/ieee802_1x.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/ieee802_1x.c	24 Jun 2003 13:06:47 -0000	1.5
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/types.h>
 #include <netinet/in.h>
 #include <string.h>
 #include <sys/ioctl.h>
@@ -20,7 +21,12 @@
 #include <time.h>
 #include <sys/time.h>
 #include <sys/socket.h>
-
+#ifdef __OpenBSD__
+#include <net/if.h>
+#include <net/bpf.h>
+#include <netinet/if_ether.h>
+#include <dev/ic/if_wi_ieee.h>
+#endif
 
 #include "hostapd.h"
 #include "ieee802_1x.h"
@@ -35,6 +41,84 @@
 #include "driver.h"
 
 
+#ifdef __OpenBSD__
+void ieee802_1x_set_sta_authorized(hostapd *hapd, struct sta_info *sta,
+				   int authorized)
+{
+	if (authorized) {
+		sta->flags |= WLAN_STA_AUTHORIZED;
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
+			       HOSTAPD_LEVEL_DEBUG, "authorizing port");
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
+			       HOSTAPD_LEVEL_DEBUG, "authorizing port");
+		accounting_sta_start(hapd, sta);
+		hostapd_set_sta_authorized(hapd, sta);
+	} else {
+		sta->flags &= ~WLAN_STA_AUTHORIZED;
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
+			       HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
+		remove_sta(hapd, sta);
+	}
+}
+
+
+static void ieee802_1x_send(hostapd *hapd, struct sta_info *sta, u8 type,
+			    u8 *data, size_t datalen)
+{
+	char *buf;
+	struct ether_header *hdr;
+	struct ieee802_1x_hdr *xhdr;
+	struct bpf_sendtagged bs;
+	struct wi_tag_change_tx_key *tag;
+	size_t len;
+
+	len = sizeof(*hdr) + 2 + sizeof(*xhdr) + datalen;
+	buf = (char *) malloc(len);
+	if (buf == NULL) {
+		printf("malloc() failed for ieee802_1x_send(len=%d)\n", len);
+		return;
+	}
+
+	memset(buf, 0, len);
+
+	hdr = (struct ether_header *) buf;
+#if 0
+	/* TODO:
+	 * According to IEEE 802.1aa/D4 EAPOL-Key should be sent before any
+	 * remaining EAP frames, if possible. This would allow rest of the
+	 * frames to be encrypted. This code could be used to request
+	 * encryption from the kernel driver. */
+	if (sta->eapol_sm &&
+	    sta->eapol_sm->be_auth.state == BE_AUTH_SUCCESS &&
+	    sta->eapol_sm->keyTxEnabled)
+		send using a key;
+#endif
+	memcpy(hdr->ether_dhost, sta->addr, ETH_ALEN);
+	memcpy(hdr->ether_shost, hapd->own_addr, ETH_ALEN);
+	hdr->ether_type = htons(ETH_P_PAE);
+
+	xhdr = (struct ieee802_1x_hdr *)(hdr + 1);
+	xhdr->version = EAPOL_VERSION;
+	xhdr->type = type;
+	xhdr->length = htons(datalen);
+
+	if (datalen > 0 && data != NULL)
+		memcpy(xhdr + 1, data, datalen);
+
+	bs.bs_buf = buf;
+	bs.bs_bufbytes = len;
+	tag = (struct wi_tag_change_tx_key *)bs.bs_tag;
+	bs.bs_tagbytes = sizeof(*tag);
+	tag->type = WI_TAG_CHANGE_TX_KEY;	/* use alternate WEP: */
+	tag->change_tx_key = 255;		/* no key */
+	if (ioctl(hapd->sock, BIOCSTAGGED, &bs) == -1) {
+		perror("ieee802_1x_send: BIOCSTAGGED");
+		printf("ieee802_1x_send - packet len: %d - failed\n", len);
+	}
+
+	free(buf);
+}
+#else
 static void ieee802_1x_send(hostapd *hapd, struct sta_info *sta, u8 type,
 			    u8 *data, size_t datalen)
 {
@@ -102,28 +186,28 @@
 void ieee802_1x_set_sta_authorized(hostapd *hapd, struct sta_info *sta,
 				   int authorized)
 {
-	struct prism2_hostapd_param param;
-
-	memset(&param, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
-	memcpy(param.sta_addr, sta->addr, ETH_ALEN);
 	if (authorized) {
+		struct prism2_hostapd_param param;
+
+		memset(&param, 0, sizeof(param));
+		param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
+		memcpy(param.sta_addr, sta->addr, ETH_ALEN);
 		sta->flags |= WLAN_STA_AUTHORIZED;
 		param.u.set_flags_sta.flags_or = WLAN_STA_AUTHORIZED;
 		param.u.set_flags_sta.flags_and = ~0;
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "authorizing port");
 		accounting_sta_start(hapd, sta);
+		if (hostapd_ioctl(hapd, &param, sizeof(param)))
+			printf("Could not set station flags for kernel driver.\n");
 	} else {
 		sta->flags &= ~WLAN_STA_AUTHORIZED;
-		param.u.set_flags_sta.flags_and = ~WLAN_STA_AUTHORIZED;
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
+		remove_sta(hapd, sta);
 	}
-
-	if (hostapd_ioctl(hapd, &param, sizeof(param)))
-		printf("Could not set station flags for kernel driver.\n");
 }
+#endif
 
 
 void ieee802_1x_request_identity(hostapd *hapd, struct sta_info *sta, u8 id)
@@ -264,6 +348,7 @@
 		key->key_index |= BIT(7);
 	}
 
+	/* XXX iterate over all sta here */
 	/* Key is encrypted using "Key-IV + sta->eapol_key_crypt" as the
 	 * RC4-key */
 	memcpy((u8 *) (key + 1), key_data, key_len);
@@ -307,6 +392,10 @@
 		      "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR
 		      " (identifier %d)\n", MAC2STR(sta->addr), id);
 
+	if (hapd->default_wep_key_2)
+		ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx_2, 1,
+				      hapd->default_wep_key_2,
+				      hapd->conf->default_wep_key_len);
 	if (hapd->default_wep_key)
 		ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1,
 				      hapd->default_wep_key,
@@ -1090,6 +1179,7 @@
 
 static int ieee802_1x_init_kernel_1x(hostapd *hapd)
 {
+#ifndef __OpenBSD__
 	/* enable kernel driver support for IEEE 802.1X */
 	if (hostap_ioctl_prism2param(hapd, PRISM2_PARAM_IEEE_802_1X, 1)) {
 		printf("Could not setup IEEE 802.1X support in kernel driver."
@@ -1105,6 +1195,7 @@
 		       "driver.\n");
 		return -1;
 	}
+#endif
 
 	return 0;
 }
Index: hostapd/md5.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/md5.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/md5.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/md5.c	17 Jun 2003 19:04:19 -0000	1.2
@@ -12,9 +12,11 @@
 #include <assert.h>
 #include <string.h>
 
+#ifndef __OpenBSD__
 #include <endian.h>
 #if __BYTE_ORDER == __BIG_ENDIAN
 #define WORDS_BIGENDIAN
+#endif
 #endif
 
 #include "common.h"
Index: hostapd/receive.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/receive.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- hostapd/receive.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/receive.c	17 Jun 2003 19:04:19 -0000	1.2
@@ -16,7 +16,17 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 
-#ifdef USE_KERNEL_HEADERS
+#if defined(__OpenBSD__)
+#include <pcap.h>
+#include <fcntl.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <ifaddrs.h>
+#include <net/if_dl.h>
+#include <netinet/if_ether.h>
+#include <net/if_types.h>
+#elif defined(USE_KERNEL_HEADERS)
 #include <asm/types.h>
 #include <linux/if_packet.h>
 #include <linux/if_ether.h>   /* The L2 protocols */
@@ -37,6 +47,78 @@
 #include "driver.h"
 
 
+#ifdef __OpenBSD__
+static void handle_read_packet(u_char *hapdp, const struct pcap_pkthdr *hdr,
+			       const u_char *constbuf)
+{
+	hostapd *hapd;
+	struct sta_info *sta;
+	struct ether_header *eh;
+	u8 *sa, buf[/* XXX */ 3000];
+	size_t len;
+
+	hapd = (hostapd *)hapdp;
+	len = hdr->caplen;
+	eh = (struct ether_header *)buf;
+
+	if (len > sizeof(buf)) {
+		printf("Packet size should not be this large!\n");
+		return;
+	}
+	memcpy(buf, constbuf, len);
+	HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE,
+		      "Received %d bytes ethernet frame\n", len);
+	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) {
+		int i;
+		printf("  dump:");
+		for (i = 0; i < len; i++)
+			printf(" %02x", buf[i]);
+		printf("\n");
+	}
+
+	sa = eh->ether_shost;
+	/*
+	 * For OpenBSD, we merely act as an 802.1x authenticator and
+	 * not a full 802.11 AP daemon.  Because of this, there's no
+	 * reason to consider a station as anything but nonexistant
+	 * until its supplicant's authorization begins.
+	 */
+	sta = ieee802_11_locate_sta(hapd, sa);
+	if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+		printf("Data frame from not associated STA " MACSTR "\n",
+		       MAC2STR(sa));
+		return;
+	}
+	switch (ntohs(eh->ether_type)) {
+	case ETH_P_PAE:
+		if (hapd->conf->ieee802_1x)
+			ieee802_1x_receive(hapd, sa, buf + sizeof(*eh),
+					   len - sizeof(*eh));
+		else
+			printf("IEEE 802.1X is not configured to be used - "
+			       "dropping packet\n");
+		break;
+
+	default:
+		printf("Unknown ethertype 0x%04x in data frame\n",
+		       ntohs(eh->ether_type));
+		break;
+	}
+}
+
+void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	hostapd *hapd = (hostapd *) eloop_ctx;
+	
+	HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE,
+		      "Data received on %s.\n", hapd->conf->iface);
+	if (pcap_dispatch(hapd->pcap, -1, handle_read_packet,
+			  (u_char *)hapd) == -1)
+		pcap_perror(hapd->pcap, "reading packet");
+}
+
+#else
+
 static void handle_data(hostapd *hapd, char *buf, size_t len, u16 stype)
 {
 	struct ieee80211_hdr *hdr;
@@ -233,24 +315,106 @@
 
 	handle_frame(hapd, buf, len);
 }
+#endif
 
 
 int hostapd_init_sockets(hostapd *hapd)
 {
+#ifdef __OpenBSD__
+	char pcap_errbuf[PCAP_ERRBUF_SIZE];
+	struct bpf_program program;
+	struct sockaddr_dl *sdl;
+	struct ifaddrs *ifa, *ifalist;
+	char *strprogram;
+#else
         struct ifreq ifr;
 	struct sockaddr_ll addr;
+#endif
 
+#ifdef __OpenBSD__
+	if (getifaddrs(&ifalist) == -1) {
+		perror("getifaddrs");
+		return -1;
+	}
+	for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next) {
+		if (strcmp(ifa->ifa_name, hapd->conf->iface) == 0 &&
+			ifa->ifa_addr->sa_family == AF_LINK)
+			break;
+	}
+	if (ifa == NULL) {
+		freeifaddrs(ifalist);
+		printf("No link-level interfaces found for %s.",
+		       hapd->conf->iface);
+		return -1;
+	}
+	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+	if (sdl->sdl_type != IFT_ETHER || sdl->sdl_alen != ETH_ALEN) {
+		freeifaddrs(ifalist);
+		printf("getifaddrs() returned wrong address type\n");
+		return -1;
+	}
+	memcpy(hapd->own_addr, LLADDR(sdl), ETH_ALEN);
+	freeifaddrs(ifalist);
+	if (hostapd_set_iface_flags(hapd, 1) == -1) {
+		perror("Failed to set interface 'up'.\n");
+		return -1;
+	}
+	hapd->pcap = pcap_open_live(hapd->conf->iface, /* XXX */ 3000, 0, 0,
+				    pcap_errbuf);
+	if (hapd->pcap == NULL) {
+		printf("%s: %s\n", hapd->conf->iface, pcap_errbuf);
+		return -1;
+	}
+	hapd->sock = pcap_fileno(hapd->pcap);
+	if (pcap_datalink(hapd->pcap) != DLT_EN10MB) {
+		printf("pcap_datalink(%s) is not ether\n", hapd->conf->iface);
+		return -1;
+	}
+#if 0
+	if ((fdflags = fcntl(hapd->sock, F_GETFL, 0)) == -1 ||
+		fcntl(hapd->sock, F_SETFL, fdflags | O_NONBLOCK) == -1) {
+		perror("setting non-blocking on pcap descriptor");
+		return -1;
+	}
+#endif
+	if (asprintf(&strprogram, "ether dst " MACSTR " and ether proto %#x",
+		     MAC2STR(hapd->own_addr), ETH_P_PAE) == -1) {
+		perror("asprintf");
+		return -1;
+	}
+	if (pcap_compile(hapd->pcap, &program, strprogram, 1, 0) == -1) {
+		free(strprogram);
+		perror("creating filter");
+		return -1;
+	}
+	HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE,
+		      "Setting bpf program '%s' on %s.\n", strprogram,
+		      hapd->conf->iface);
+	free(strprogram);
+	if (pcap_setfilter(hapd->pcap, &program) == -1) {
+		pcap_freecode(&program);
+		perror("setting filter");
+		return -1;
+	}
+	pcap_freecode(&program);
+#else
 	hapd->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 	if (hapd->sock < 0) {
 		perror("socket[PF_PACKET,SOCK_RAW]");
 		return -1;
 	}
+#endif
 
 	if (eloop_register_read_sock(hapd->sock, handle_read, hapd, NULL)) {
 		printf("Could not register read socket\n");
 		return -1;
 	}
 
+	if (hostapd_set_iface_flags(hapd, 1)) {
+		return -1;
+	}
+
+#ifndef __OpenBSD__
         memset(&ifr, 0, sizeof(ifr));
         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap",
 		 hapd->conf->iface);
@@ -259,10 +423,6 @@
 		return -1;
         }
 
-	if (hostapd_set_iface_flags(hapd, 1)) {
-		return -1;
-	}
-
 	memset(&addr, 0, sizeof(addr));
 	addr.sll_family = AF_PACKET;
 	addr.sll_ifindex = ifr.ifr_ifindex;
@@ -288,6 +448,7 @@
 		return -1;
 	}
 	memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+#endif
 
 	return 0;
 }
Index: hostapd/sta_info.c
===================================================================
RCS file: /u/cvs/SNOWNET/Snownet/hostap/hostapd/sta_info.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- hostapd/sta_info.c	17 Jun 2003 19:01:21 -0000	1.1.1.1
+++ hostapd/sta_info.c	23 Jun 2003 21:43:26 -0000	1.3
@@ -105,16 +105,10 @@
 
 void ap_free_sta(hostapd *hapd, struct sta_info *sta)
 {
-	struct prism2_hostapd_param param;
-
 	accounting_sta_stop(hapd, sta);
 
-	memset(&param, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
-	memcpy(param.sta_addr, sta->addr, ETH_ALEN);
-	if (hostapd_ioctl(hapd, &param, sizeof(param))) {
-		printf("Could not remove station from kernel driver.\n");
-	}
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	remove_sta(hapd, sta);
 
 	ap_sta_hash_del(hapd, sta);
 	ap_sta_list_del(hapd, sta);
@@ -151,6 +145,47 @@
 }
 
 
+#ifdef __OpenBSD__
+/*
+ * Trust kernel's HostAP to do any timeouts.  We'll simply act on those
+ * timeouts when they occur.
+ */
+void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
+{
+	hostapd *hapd = eloop_ctx;
+	struct sta_info *sta = timeout_ctx;
+	int flags;
+
+	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
+		      "Checking STA " MACSTR " inactivity: ",
+		      MAC2STR(sta->addr));
+	flags = hostapd_read_sta_driver_flags(hapd, sta->addr);
+	if (flags != -1 && !(flags & WLAN_STA_ASSOC)) {
+		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
+			      "disassociated due to inactivity\n");
+		if (sta->timeout_next != STA_DEAUTH) {
+			sta->flags &= ~WLAN_STA_ASSOC;
+			ieee802_1x_set_port_enabled(hapd, sta, 0);
+			sta->timeout_next = STA_DEAUTH;
+			eloop_register_timeout(AP_MAX_INACTIVITY, 0,
+					       ap_handle_timer, hapd, sta);
+		}
+	} else if (flags == -1 || !(flags & WLAN_STA_AUTH)) {
+		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
+			      "deauthenticated due to inactivity\n");
+		if (!sta->acct_terminate_cause)
+			sta->acct_terminate_cause =
+				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
+		ap_free_sta(hapd, sta);
+	} else {
+		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
+			      "currently active\n");
+		sta->timeout_next = STA_NULLFUNC;
+		eloop_register_timeout(AP_MAX_INACTIVITY, 0, ap_handle_timer,
+				       hapd, sta);
+	}
+}
+#else
 void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 {
 	hostapd *hapd = eloop_ctx;
@@ -267,6 +302,7 @@
 		break;
 	}
 }
+#endif
 
 
 void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
-------------- next part --------------
Index: sys/sys/mbuf.h
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/sys/mbuf.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- sys/sys/mbuf.h	3 Jul 2002 21:19:08 -0000	1.1.1.1
+++ sys/sys/mbuf.h	24 Jun 2003 13:12:56 -0000	1.3
@@ -597,6 +597,7 @@
 #define PACKET_TAG_PF_GENERATED			11 /* PF generated, pass always */
 #define PACKET_TAG_PF_ROUTED			12 /* PF routed, no route loops */
 #define PACKET_TAG_PF_FRAGCACHE			13 /* PF fragment cached */
+#define PACKET_TAG_DRIVER_SPECIFIC		16 /* NIC specified format */
 
 #ifdef MBTYPES
 int mbtypes[] = {				/* XXX */
Index: sys/net/bpf.c
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/net/bpf.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- sys/net/bpf.c	6 Jun 2002 21:34:16 -0000	1.1.1.1
+++ sys/net/bpf.c	5 Jun 2003 13:17:04 -0000	1.2
@@ -93,6 +93,7 @@
 void	bpf_catchpacket(struct bpf_d *, u_char *, size_t, size_t,
 	    void (*)(const void *, void *, size_t));
 void	bpf_reset_d(struct bpf_d *);
+static int	bpf_write(dev_t, struct uio *, int, struct m_tag *);
 
 void	filt_bpfrdetach(struct knote *);
 int	filt_bpfread(struct knote *, long);
@@ -489,14 +490,28 @@
 	struct uio *uio;
 	int ioflag;
 {
+
+	return (bpf_write(dev, uio, ioflag, NULL));
+}
+
+static int
+bpf_write(dev, uio, ioflag, devtag)
+	dev_t dev;
+	struct uio *uio;
+	int ioflag;
+	struct m_tag *devtag;
+{
 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
 	struct ifnet *ifp;
 	struct mbuf *m;
 	int error, s;
 	struct sockaddr dst;
 
-	if (d->bd_bif == 0)
+	if (d->bd_bif == 0) {
+		if (devtag != NULL)
+			m_tag_free(devtag);
 		return (ENXIO);
+	}
 
 	ifp = d->bd_bif->bif_ifp;
 
@@ -504,8 +519,13 @@
 		return (0);
 
 	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst);
-	if (error)
+	if (error) {
+		if (devtag != NULL)
+			m_tag_free(devtag);
 		return (error);
+	}
+	if (devtag != NULL)
+		m_tag_prepend(m, devtag);
 
 	if (m->m_pkthdr.len > ifp->if_mtu) {
 		m_freem(m);
@@ -559,6 +579,7 @@
  *  BIOCVERSION		Get filter language version.
  *  BIOCGHDRCMPLT	Get "header already complete" flag
  *  BIOCSHDRCMPLT	Set "header already complete" flag
+ *  BIOCSTAGGED		Send a packet with a device-specific m_tag.
  */
 /* ARGSUSED */
 int
@@ -788,6 +809,35 @@
 		}
 	case BIOCGRSIG:
 		*(u_int *)addr = d->bd_sig;
+		break;
+	case BIOCSTAGGED:	/* Send a packet, with a user tag */
+		{
+			struct uio uio;
+			struct iovec iov;
+			struct bpf_sendtagged *bs;
+			struct m_tag *mt;
+
+			bs = (struct bpf_sendtagged *)addr;
+			if (bs->bs_tagbytes > BPF_MAXTAGSIZE)
+				return (EINVAL);
+			if (bs->bs_bufbytes == 0)
+				return (0);
+			mt = m_tag_get(PACKET_TAG_DRIVER_SPECIFIC,
+			    bs->bs_tagbytes, M_WAIT);
+			if (mt == NULL)
+				return (ENOMEM);
+			bcopy(bs->bs_tag, (char *)&mt[1], bs->bs_tagbytes);
+		        iov.iov_base = (char *)bs->bs_buf;
+			iov.iov_len = bs->bs_bufbytes;
+			uio.uio_iov = &iov;
+			uio.uio_iovcnt = 1;
+			uio.uio_resid = iov.iov_len;
+			uio.uio_rw = UIO_WRITE;
+			uio.uio_segflg = UIO_USERSPACE;
+			uio.uio_procp = p;
+
+			return (bpf_write(dev, &uio, 0, mt));
+		}
 		break;
 	}
 	return (error);
Index: sys/net/bpf.h
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/net/bpf.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 bpf.h
--- sys/net/bpf.h	14 Mar 2002 01:27:09 -0000	1.1.1.1
+++ sys/net/bpf.h	24 Jun 2003 13:14:28 -0000
@@ -60,6 +60,18 @@
 #define BPF_MAXBUFSIZE 0x80000
 #define BPF_MINBUFSIZE 32
 
+#define	BPF_MAXTAGSIZE 256
+
+/*
+ *  Structure for BIOCSTAGGED.
+ */
+struct bpf_sendtagged {
+	const void *bs_buf;
+	size_t bs_bufbytes;
+	size_t bs_tagbytes;
+	u_char bs_tag[BPF_MAXTAGSIZE];
+};
+
 /*
  *  Structure for BIOCSETF.
  */
@@ -115,6 +127,7 @@
 #define BIOCGRSIG	_IOR('B',115, u_int)
 #define BIOCGHDRCMPLT	_IOR('B',116, u_int)
 #define BIOCSHDRCMPLT	_IOW('B',117, u_int)
+#define BIOCSTAGGED	_IOW('B',118, struct bpf_sendtagged)
 
 struct bpf_timeval {
 	u_int32_t	tv_sec;
@@ -170,6 +183,8 @@
 #define DLT_SLIP_BSDOS	15	/* BSD/OS Serial Line IP */
 #define DLT_PPP_BSDOS	16	/* BSD/OS Point-to-point Protocol */
 #define DLT_PFLOG	17	/* Packet filter logging */
+#define DLT_IEEE802_11	105	/* IEEE 802.11 wireless */
+#define DLT_PRISM_HEADER 119	/* Prism II monitoring + 802.11 */
 
 /*
  * The instruction encodings.
Index: sys/dev/ic/if_wi.c
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/dev/ic/if_wi.c,v
retrieving revision 1.1.1.1
retrieving revision 1.15
diff -u -r1.1.1.1 -r1.15
--- sys/dev/ic/if_wi.c	30 Aug 2002 08:19:49 -0000	1.1.1.1
+++ sys/dev/ic/if_wi.c	24 Jun 2003 12:25:34 -0000	1.15
@@ -91,6 +91,7 @@
 
 #if NBPFILTER > 0
 #include <net/bpf.h>
+#include <net/bpfdesc.h>
 #endif
 
 #include <machine/bus.h>
@@ -121,6 +122,11 @@
 #else	/* !WIDEBUG */
 #define DPRINTF(mask,args)
 #endif	/* WIDEBUG */
+#define	wi_init_keep_hostap(sc)		do {				\
+	(sc)->wi_flags |= WI_FLAGS_KEEP_HOSTAP_UP;			\
+	wi_init(sc);							\
+	(sc)->wi_flags &= ~WI_FLAGS_KEEP_HOSTAP_UP;			\
+} while (0)
 
 #if !defined(lint) && !defined(__OpenBSD__)
 static const char rcsid[] =
@@ -140,6 +146,9 @@
 STATIC void wi_txeof(struct wi_softc *, int);
 STATIC void wi_update_stats(struct wi_softc *);
 STATIC void wi_setmulti(struct wi_softc *);
+#if NBPFILTER > 0
+STATIC void wi_reset_bpf_linktype(struct wi_softc *);
+#endif
 
 STATIC int wi_cmd(struct wi_softc *, int, int, int, int);
 STATIC int wi_read_record(struct wi_softc *, struct wi_ltv_gen *);
@@ -427,6 +436,7 @@
 	if (status & WI_EV_ALLOC) {
 		int			id;
 		id = CSR_READ_2(sc, WI_ALLOC_FID);
+		
 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
 		if (id == sc->wi_tx_data_id)
 			wi_txeof(sc, status);
@@ -455,24 +465,56 @@
 	return (1);
 }
 
+#if NBPFILTER > 0
+/* Already called at splimp(). */
+STATIC void
+wi_reset_bpf_linktype(struct wi_softc *sc)
+{
+	struct bpf_d *d;
+	struct bpf_if *ifb;
+	extern struct bpf_if *bpf_iflist;
+	struct ifnet *ifp;
+	u_int dlt;
+
+	if (sc->wi_prism2hdr)
+		dlt = DLT_PRISM_HEADER;
+	else if (sc->wi_debug.wi_monitor || sc->wi_procframe)
+		dlt = DLT_IEEE802_11;
+	else
+		dlt = DLT_EN10MB;
+	ifp = &sc->sc_arpcom.ac_if;
+	for (ifb = bpf_iflist; ifb != NULL; ifb = ifb->bif_next)
+		if (ifb->bif_ifp == ifp)
+			break;
+	if (ifb == NULL)
+		return;
+	ifb->bif_dlt = dlt;
+	for (d = ifb->bif_dlist; d != NULL; d = d->bd_next)
+		d->bd_bif->bif_dlt = dlt;
+}
+#endif
+
 STATIC void
 wi_rxeof(sc)
 	struct wi_softc		*sc;
 {
+	struct wi_frame		rx_frame;
 	struct ifnet		*ifp;
 	struct ether_header	*eh;
 	struct mbuf		*m;
 	u_int16_t		msg_type;
-	int			id;
+	int			id, dontbpf = 0, unauth = 0;
 
 	ifp = &sc->sc_arpcom.ac_if;
 
 	id = CSR_READ_2(sc, WI_RX_FID);
 
-	if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
+	if (sc->wi_procframe || sc->wi_debug.wi_monitor ||
+	    sc->wi_prism2hdr) {
 		struct wi_frame	*rx_frame;
-		int		datlen, hdrlen;
+		int		datlen, hdrlen, isdata = 0;
 
+		dontbpf = 1;
 		MGETHDR(m, M_DONTWAIT, MT_DATA);
 		if (m == NULL) {
 			ifp->if_ierrors++;
@@ -484,6 +526,9 @@
 			ifp->if_ierrors++;
 			return;
 		}
+		/* To possibly M_PREPEND() with later. */
+		m->m_data += sizeof(struct prism2_header);
+		m->m_len -= sizeof(struct prism2_header);
 
 		m->m_pkthdr.rcvif = ifp;
 
@@ -510,6 +555,7 @@
 			case WI_FTYPE_DATA:
 				hdrlen = WI_DATA_HDRLEN;
 				datlen = letoh16(rx_frame->wi_dat_len);
+				isdata = 1;
 				break;
 			case WI_FTYPE_MGMT:
 				hdrlen = WI_MGMT_HDRLEN;
@@ -530,6 +576,7 @@
 		case 0:
 			hdrlen = WI_DATA_HDRLEN;
 			datlen = letoh16(rx_frame->wi_dat_len);
+			isdata = 1;
 			break;
 		default:
 			printf(WI_PRT_FMT ": received packet on invalid port "
@@ -540,7 +587,8 @@
 			return;
 		}
 
-		if ((hdrlen + datlen + 2) > MCLBYTES) {
+		if ((hdrlen + datlen + 2 + sizeof(struct prism2_header)) >
+		    MCLBYTES) {
 			m_freem(m);
 			ifp->if_ierrors++;
 			return;
@@ -553,166 +601,251 @@
 			return;
 		}
 
-		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
-	} else {
-		struct wi_frame rx_frame;
+		/*
+		 * Remove the non-802.11 section of the packet that nothing
+		 * really knows how to deal with if we're requested to
+		 * just return the frames.
+		 */
+		if (sc->wi_procframe || sc->wi_debug.wi_monitor ||
+		    sc->wi_prism2hdr) {
+			const size_t begin_80211 =
+			    offsetof(struct wi_frame, wi_frame_ctl);
+			const size_t begin_data =
+#ifdef include_802_3
+			    offsetof(struct wi_frame, wi_dst_addr);
+#else
+			    offsetof(struct wi_frame, wi_dat);
+#endif
+			size_t end_80211;
+			caddr_t data;
 
-		/* First read in the frame header */
-		if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
-		    sizeof(rx_frame))) {
-			ifp->if_ierrors++;
-			return;
+			/* from and to DS both being set means + addr4 */
+			if ((~letoh16(rx_frame->wi_frame_ctl) & 
+			    (WI_FCTL_TODS | WI_FCTL_FROMDS)) == 0)
+				end_80211 = offsetof(struct wi_frame,
+				    wi_dat_len);
+			else
+				end_80211 = offsetof(struct wi_frame,
+				    wi_addr4);
+#ifdef questionable
+			/* Turn off the WEP bit if we know we decoded it. */
+			if (?)
+				rx_frame->wi_frame_ctl &= ~htole16(WI_FCTL_WEP);
+#endif
+			/* chop off everything before the 802.11 header */
+			data = mtod(m, caddr_t);
+			bcopy(data + begin_80211, data,
+			    end_80211 - begin_80211);
+			if (datlen > 0) {
+				/*
+				 * Slide down (ETHER/LLC)+DATA or MGMT+DATA.
+				 */
+				bcopy(data + begin_data,
+				    data + end_80211 - begin_80211, datlen);
+				m->m_pkthdr.len = m->m_len = datlen
+				     - begin_80211 + end_80211;
+			} else {
+				m->m_pkthdr.len = m->m_len =
+				    hdrlen - begin_80211;
+			}
+			if (sc->wi_prism2hdr) {
+				struct prism2_header *p2;
+				struct timeval tv;
+
+				/* We have the space we need already. */
+				M_PREPEND(m, sizeof(*p2), M_DONTWAIT);
+				p2 = mtod(m, struct prism2_header *);
+				p2->version = htonl(PRISM2_HEADER_VERSION);
+				p2->length = htonl(sizeof(*p2));
+				p2->mac_time =
+				    htobe64(letoh32((rx_frame->wi_time0 << 16)
+				    + rx_frame->wi_time1));
+				microtime(&tv);
+				p2->host_time =
+				    htobe64((u_int64_t)tv.tv_sec * 1000000 +
+				    tv.tv_usec);
+				p2->phy_type = htonl(4); /* DSSS 802.11b */
+				p2->channel = htonl(sc->wi_channel);
+				p2->data_rate = htonl(rx_frame->wi_rx_rate);
+				p2->antenna = htonl(0);
+				p2->priority = htonl(0);
+				p2->ssi_type = htonl(3); /* Raw RSSI */
+				p2->ssi_signal =
+				    htonl((letoh16(rx_frame->wi_q_info)
+				    & 0xff00) >> 8);
+				p2->ssi_noise =
+				    htonl(letoh16(rx_frame->wi_q_info) & 0xff);
+				p2->preamble = htonl(0);
+				p2->encoding = htonl(1); /* CCK */
+			}
 		}
-
-		/* Drop undecryptable or packets with receive errors here */
-		if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
-			ifp->if_ierrors++;
+#if NBPFILTER > 0
+		/* Handle BPF listeners. */
+		if (ifp->if_bpf)
+			BPF_MTAP(ifp, m);
+#endif
+		m_freem(m);
+		if (!isdata)
 			return;
-		}
+	}
 
-		/* Stash message type in host byte order for later use */
-		msg_type = letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE;
+	/* First read in the frame header */
+	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
+	    sizeof(rx_frame))) {
+		ifp->if_ierrors++;
+		return;
+	}
 
-		MGETHDR(m, M_DONTWAIT, MT_DATA);
-		if (m == NULL) {
-			ifp->if_ierrors++;
+	/* Drop undecryptable or packets with receive errors here */
+	if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
+		ifp->if_ierrors++;
+		return;
+	}
+
+	/* Stash message type in host byte order for later use */
+	msg_type = letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE;
+
+	MGETHDR(m, M_DONTWAIT, MT_DATA);
+	if (m == NULL) {
+		ifp->if_ierrors++;
+		return;
+	}
+	MCLGET(m, M_DONTWAIT);
+	if (!(m->m_flags & M_EXT)) {
+		m_freem(m);
+		ifp->if_ierrors++;
+		return;
+	}
+
+	/* Align the data after the ethernet header */
+	m->m_data = (caddr_t)ALIGN(m->m_data +
+	    sizeof(struct ether_header)) - sizeof(struct ether_header);
+
+	eh = mtod(m, struct ether_header *);
+	m->m_pkthdr.rcvif = ifp;
+
+	if (msg_type == WI_STAT_MGMT &&
+	    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
+
+		u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
+
+		if ((WI_802_11_OFFSET_RAW + rxlen + 2) > MCLBYTES) {
+			printf("%s: oversized mgmt packet received in "
+			    "hostap mode (wi_dat_len=%d, "
+			    "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
+			    rxlen, letoh16(rx_frame.wi_status));
+			m_freem(m);
+			ifp->if_ierrors++;  
 			return;
 		}
-		MCLGET(m, M_DONTWAIT);
-		if (!(m->m_flags & M_EXT)) {
+
+		/* Put the whole header in there. */
+		bcopy(&rx_frame, mtod(m, void *),
+		    sizeof(struct wi_frame));
+		if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
+		    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
+		    rxlen + 2)) {
 			m_freem(m);
+			if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
+				printf("wihap: failed to copy header\n");
 			ifp->if_ierrors++;
 			return;
 		}
 
-		/* Align the data after the ethernet header */
-		m->m_data = (caddr_t)ALIGN(m->m_data +
-		    sizeof(struct ether_header)) - sizeof(struct ether_header);
-
-		eh = mtod(m, struct ether_header *);
-		m->m_pkthdr.rcvif = ifp;
-
-		if (msg_type == WI_STAT_MGMT &&
-		    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
+		m->m_pkthdr.len = m->m_len =
+		    WI_802_11_OFFSET_RAW + rxlen;
 
-			u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
+		/* XXX: consider giving packet to bhp? */
 
-			if ((WI_802_11_OFFSET_RAW + rxlen + 2) > MCLBYTES) {
-				printf("%s: oversized mgmt packet received in "
-				    "hostap mode (wi_dat_len=%d, "
-				    "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
-				    rxlen, letoh16(rx_frame.wi_status));
-				m_freem(m);
-				ifp->if_ierrors++;  
-				return;
-			}
-
-			/* Put the whole header in there. */
-			bcopy(&rx_frame, mtod(m, void *),
-			    sizeof(struct wi_frame));
-			if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
-			    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
-			    rxlen + 2)) {
-				m_freem(m);
-				if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
-					printf("wihap: failed to copy header\n");
-				ifp->if_ierrors++;
-				return;
-			}
-
-			m->m_pkthdr.len = m->m_len =
-			    WI_802_11_OFFSET_RAW + rxlen;
+		wihap_mgmt_input(sc, &rx_frame, m);
 
-			/* XXX: consider giving packet to bhp? */
-
-			wihap_mgmt_input(sc, &rx_frame, m);
+		return;
+	}
 
+	switch (msg_type) {
+	case WI_STAT_1042:
+	case WI_STAT_TUNNEL:
+	case WI_STAT_WMP_MSG:
+		if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
+		    MCLBYTES) {
+			printf(WI_PRT_FMT ": oversized packet received "
+			    "(wi_dat_len=%d, wi_status=0x%x)\n",
+			    WI_PRT_ARG(sc),
+			    letoh16(rx_frame.wi_dat_len),
+			    letoh16(rx_frame.wi_status));
+			m_freem(m);
+			ifp->if_ierrors++;
 			return;
 		}
+		m->m_pkthdr.len = m->m_len =
+		    letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
 
-		switch (msg_type) {
-		case WI_STAT_1042:
-		case WI_STAT_TUNNEL:
-		case WI_STAT_WMP_MSG:
-			if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
-			    MCLBYTES) {
-				printf(WI_PRT_FMT ": oversized packet received "
-				    "(wi_dat_len=%d, wi_status=0x%x)\n",
-				    WI_PRT_ARG(sc),
-				    letoh16(rx_frame.wi_dat_len),
-				    letoh16(rx_frame.wi_status));
-				m_freem(m);
-				ifp->if_ierrors++;
-				return;
-			}
-			m->m_pkthdr.len = m->m_len =
-			    letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
-
-			bcopy((char *)&rx_frame.wi_dst_addr,
-			    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
-			bcopy((char *)&rx_frame.wi_src_addr,
-			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
-			bcopy((char *)&rx_frame.wi_type,
-			    (char *)&eh->ether_type, ETHER_TYPE_LEN);
-
-			if (wi_read_data(sc, id, WI_802_11_OFFSET,
-			    mtod(m, caddr_t) + sizeof(struct ether_header),
-			    m->m_len + 2)) {
-				ifp->if_ierrors++;
-				m_freem(m);
-				return;
-			}
-			break;
-		default:
-			if ((letoh16(rx_frame.wi_dat_len) +
-			    sizeof(struct ether_header)) > MCLBYTES) {
-				printf(WI_PRT_FMT ": oversized packet received "
-				    "(wi_dat_len=%d, wi_status=0x%x)\n",
-				    WI_PRT_ARG(sc),
-				    letoh16(rx_frame.wi_dat_len),
-				    letoh16(rx_frame.wi_status));
-				m_freem(m);
-				ifp->if_ierrors++;
-				return;
-			}
-			m->m_pkthdr.len = m->m_len =
-			    letoh16(rx_frame.wi_dat_len) +
-			    sizeof(struct ether_header);
+		bcopy((char *)&rx_frame.wi_dst_addr,
+		    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
+		bcopy((char *)&rx_frame.wi_src_addr,
+		    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
+		bcopy((char *)&rx_frame.wi_type,
+		    (char *)&eh->ether_type, ETHER_TYPE_LEN);
+
+		if (wi_read_data(sc, id, WI_802_11_OFFSET,
+		    mtod(m, caddr_t) + sizeof(struct ether_header),
+		    m->m_len + 2)) {
+			ifp->if_ierrors++;
+			m_freem(m);
+			return;
+		}
+		break;
+	default:
+		if ((letoh16(rx_frame.wi_dat_len) +
+		    sizeof(struct ether_header)) > MCLBYTES) {
+			printf(WI_PRT_FMT ": oversized packet received "
+			    "(wi_dat_len=%d, wi_status=0x%x)\n",
+			    WI_PRT_ARG(sc),
+			    letoh16(rx_frame.wi_dat_len),
+			    letoh16(rx_frame.wi_status));
+			m_freem(m);
+			ifp->if_ierrors++;
+			return;
+		}
+		m->m_pkthdr.len = m->m_len =
+		    letoh16(rx_frame.wi_dat_len) +
+		    sizeof(struct ether_header);
 
-			if (wi_read_data(sc, id, WI_802_3_OFFSET,
-			    mtod(m, caddr_t), m->m_len + 2)) {
-				m_freem(m);
-				ifp->if_ierrors++;
-				return;
-			}
-			break;
+		if (wi_read_data(sc, id, WI_802_3_OFFSET,
+		    mtod(m, caddr_t), m->m_len + 2)) {
+			m_freem(m);
+			ifp->if_ierrors++;
+			return;
 		}
+		break;
+	}
 
-		ifp->if_ipackets++;
+	ifp->if_ipackets++;
 
-		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
-			/*
-			 * Give host AP code first crack at data packets.
-			 * If it decides to handle it (or drop it), it will
-			 * return a non-zero.  Otherwise, it is destined for
-			 * this host.
-			 */
-			if (wihap_data_input(sc, &rx_frame, m))
-				return;
-		}
+	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
+		/*
+		 * Give host AP code first crack at data packets.
+		 * If it decides to handle it (or drop it), it will
+		 * return a non-zero.  A -1 is returned for unauthorized
+		 * packets, which should be captured and then dropped.
+		 * Otherwise, it is destined for this host.
+		 */
+		unauth = wihap_data_input(sc, &rx_frame, m);
+		if (unauth && unauth != -1)
+			return;
 	}
 
 #if NBPFILTER > 0
 	/* Handle BPF listeners. */
-	if (ifp->if_bpf)
+	if (!dontbpf && ifp->if_bpf)
 		BPF_MTAP(ifp, m);
 #endif
 
-	/* Receive packet unless in procframe or monitor mode. */
-	if (sc->wi_procframe || sc->wi_debug.wi_monitor)
+	if (unauth == -1) {
 		m_freem(m);
-	else
-		ether_input_mbuf(ifp, m);
+		return;
+	}
+	ether_input_mbuf(ifp, m);
 
 	return;
 }
@@ -733,6 +866,26 @@
 		ifp->if_oerrors++;
 	else
 		ifp->if_opackets++;
+	
+	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP &&
+	    status & (WI_EV_TX | WI_EV_TX_EXC)) {
+		struct wi_frame txframe;
+		u_int16_t fid;
+		int err;
+		
+		fid = CSR_READ_2(sc, WI_TX_CMP_FID);
+		if ((err = wi_read_data(sc, fid, 0, (void *)&txframe,
+		    /* Read only the header portion. */
+		    (char *)&txframe.wi_dat - (char *)&txframe))) {
+			ifp->if_oerrors++;
+			if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
+				printf(WI_PRT_FMT ": wi_txeof: cannot retrieve "
+				    "(err=%d, fid=%u, wi_status=0x%04x)\n",
+				    WI_PRT_ARG(sc), err, fid, status);
+			return;
+		}
+		wihap_tx_intr(sc, status, &txframe);
+	}
 
 	return;
 }
@@ -1446,12 +1599,12 @@
 		switch (ifa->ifa_addr->sa_family) {
 #ifdef INET
 		case AF_INET:
-			wi_init(sc);
+			wi_init_keep_hostap(sc);
 			arp_ifinit(&sc->sc_arpcom, ifa);
 			break;
 #endif	/* INET */
 		default:
-			wi_init(sc);
+			wi_init_keep_hostap(sc);
 			break;
 		}
 		break;
@@ -1477,7 +1630,7 @@
 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
 					WI_SETVAL(WI_RID_PROMISC, 0);
 			} else
-				wi_init(sc);
+				wi_init_keep_hostap(sc);
 		} else if (ifp->if_flags & IFF_RUNNING)
 			wi_stop(sc);
 		sc->wi_if_flags = ifp->if_flags;
@@ -1535,6 +1688,10 @@
 			wreq.wi_val[0] = htole16(sc->sc_firmware_type ==
 			    WI_LUCENT ? 0 : 1);
 			break;
+		case WI_RID_PRISM2HDR:
+			wreq.wi_len = 2;
+			wreq.wi_val[0] = htole16(sc->wi_prism2hdr);
+			break;
 		case WI_RID_SCAN_RES:
 			if (sc->sc_firmware_type == WI_LUCENT) {
 				memcpy((char *)wreq.wi_val,
@@ -1567,6 +1724,16 @@
 			break;
 		case WI_RID_PROCFRAME:
 			sc->wi_procframe = letoh16(wreq.wi_val[0]);
+#if NBPFILTER > 0
+			wi_reset_bpf_linktype(sc);
+#endif
+			error = 0;
+			break;
+		case WI_RID_PRISM2HDR:
+			sc->wi_prism2hdr = letoh16(wreq.wi_val[0]);
+#if NBPFILTER > 0
+			wi_reset_bpf_linktype(sc);
+#endif
 			error = 0;
 			break;
 		case WI_RID_SCAN_REQ:
@@ -1675,6 +1842,7 @@
 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
 		break;
 	case SIOCHOSTAP_ADD:
+	case SIOCHOSTAP_CHANGE:
 	case SIOCHOSTAP_DEL:
 	case SIOCHOSTAP_GET:
 	case SIOCHOSTAP_GETALL:
@@ -1825,7 +1993,8 @@
 	/* enable interrupts */
 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
 
-        wihap_init(sc);
+	if (!(sc->wi_flags & WI_FLAGS_KEEP_HOSTAP_UP))
+		wihap_init(sc);
 
 	splx(s);
 
@@ -1980,7 +2149,8 @@
 	struct mbuf		*m0;
 	struct wi_frame		tx_frame;
 	struct ether_header	*eh;
-	int			id;
+	struct m_tag		*mtag;
+	int			id, oldtxkey, oldusewep;
 
 	sc = ifp->if_softc;
 
@@ -1997,20 +2167,69 @@
 	if (m0 == NULL)
 		return;
 
+	oldtxkey = oldusewep = -1;
+	mtag = NULL;
+	do {
+		mtag = m_tag_find(m0, PACKET_TAG_DRIVER_SPECIFIC, mtag);
+		if (mtag != NULL && mtag->m_tag_len >= 1) {
+			struct wi_tag_change_tx_key *t;
+
+			switch (*(u_char *)&mtag[1]) {
+			case WI_TAG_CHANGE_TX_KEY:
+				/* set a tx key temporarily */
+
+				t = (struct wi_tag_change_tx_key *)&mtag[1];
+				if (mtag->m_tag_len < sizeof(*t))
+					continue;
+				if (t->change_tx_key == 255) {
+					if (oldusewep == -1)
+						oldusewep = sc->wi_use_wep;
+					sc->wi_use_wep = 0;
+					WI_SETVAL(WI_RID_ENCRYPTION,
+					    sc->wi_use_wep);
+					continue;
+				}
+				if (t->change_tx_key > 3)
+					continue;
+				if (oldtxkey == -1)
+					oldtxkey = sc->wi_tx_key;
+				sc->wi_tx_key = t->change_tx_key;
+				WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
+				break;
+			}
+		}
+	} while (mtag != NULL);
 	bzero((char *)&tx_frame, sizeof(tx_frame));
 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
 	id = sc->wi_tx_data_id;
 	eh = mtod(m0, struct ether_header *);
 
 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
-		if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
-		    &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
+		int rej;
+
+		rej = wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
+		    &tx_frame.wi_tx_rate);
+		/*
+		 * Allow sending packets to unauthorized hosts only
+		 * through the BIOCSTAGGED interface.  This is slightly
+		 * less a hack than, say, allowing ethernet type 0x888e...
+		 */
+		if ((rej == -1 && oldusewep == -1 && oldtxkey == -1) ||
+		    (!rej  && !(ifp->if_flags & IFF_PROMISC))) {
 			if (ifp->if_flags & IFF_DEBUG)
 				printf(WI_PRT_FMT
-				    ": wi_start: dropping unassoc dst %s\n",
-				    WI_PRT_ARG(sc),
+				    ": wi_start: dropping un%s dst %s\n",
+				    WI_PRT_ARG(sc), rej ? "author" : "assoc",
 				    ether_sprintf(eh->ether_dhost));
 			m_freem(m0);
+			if (oldtxkey != -1) {
+				sc->wi_tx_key = oldtxkey;
+				WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
+			}
+			if (oldusewep != -1) {
+				sc->wi_use_wep = oldusewep;
+				WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
+			}
 			goto nextpkt;
 		}
 	}
@@ -2022,11 +2241,13 @@
 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
-	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
+	    eh->ether_type == htons(ETHERTYPE_IPV6) ||
+	    eh->ether_type == htons(0x888e) /* EAPOL */) {
 		bcopy((char *)&eh->ether_dhost,
 		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
-			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
+			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT |
+			    WI_TXCNTL_TX_OK); /* XXX */
 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
 			if (sc->wi_use_wep)
 				tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
@@ -2087,11 +2308,14 @@
 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
 
 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
+			static int doprint = 1;
 
-			/* Do host encryption. (XXX - not implemented) */
-			printf(WI_PRT_FMT
-			    ": host encrypt not implemented for 802.3\n",
-			    WI_PRT_ARG(sc));
+			if (doprint) {
+				/* Do host encryption. (XXX not implemented) */
+				printf(WI_PRT_FMT ": host encrypt not "
+				    "implemented for 802.3\n", WI_PRT_ARG(sc));
+				doprint = 0;
+			}
 		} else {
 			m_copydata(m0, 0, m0->m_pkthdr.len,
 			    (caddr_t)&sc->wi_txbuf);
@@ -2108,7 +2332,7 @@
 	 * If there's a BPF listner, bounce a copy of
 	 * this frame to him.
 	 */
-	if (ifp->if_bpf)
+	if (ifp->if_bpf && !sc->wi_procframe && !sc->wi_debug.wi_monitor)
 		BPF_MTAP(ifp, m0);
 #endif
 
@@ -2124,6 +2348,14 @@
 	 */
 	ifp->if_timer = 5;
 
+	if (oldtxkey != -1) {
+		sc->wi_tx_key = oldtxkey;
+		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
+	}
+	if (oldusewep != -1) {
+		sc->wi_use_wep = oldusewep;
+		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
+	}
 	return;
 }
 
@@ -2150,7 +2382,7 @@
 	bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
 	   sizeof(struct wi_80211_hdr));
 
-	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
+	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT | WI_TXCNTL_TX_OK);
 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
 
@@ -2174,7 +2406,8 @@
 {
 	struct ifnet		*ifp;
 
-	wihap_shutdown(sc);
+	if (!(sc->wi_flags & WI_FLAGS_KEEP_HOSTAP_UP))
+		wihap_shutdown(sc);
 
 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
 		return;
@@ -2550,7 +2783,7 @@
 		return (error);
 
 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
-		wi_init(sc);
+		wi_init_keep_hostap(sc);
 	return 0;
 }
 
@@ -2595,7 +2828,7 @@
 	sc->wi_max_sleep = power->i_maxsleep;
 
 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
-		wi_init(sc);
+		wi_init_keep_hostap(sc);
 
 	return (0);
 }
@@ -2713,6 +2946,9 @@
 		break;
 	case WI_DEBUG_MONITOR:
 		sc->wi_debug.wi_monitor = 1;
+#if NBPFILTER > 0
+		wi_reset_bpf_linktype(sc);
+#endif
 		break;
 	case WI_DEBUG_LEDTEST:
 		param0 = letoh16(wreq->wi_val[0]);
@@ -2730,6 +2966,9 @@
 		sc->wi_debug.wi_delaysupp = 0;
 		sc->wi_debug.wi_txsupp = 0;
 		sc->wi_debug.wi_monitor = 0;
+#if NBPFILTER > 0
+		wi_reset_bpf_linktype(sc);
+#endif
 		sc->wi_debug.wi_ledtest = 0;
 		sc->wi_debug.wi_ledtest_param0 = 0;
 		sc->wi_debug.wi_ledtest_param1 = 0;
Index: sys/dev/ic/if_wi_hostap.c
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/dev/ic/if_wi_hostap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- sys/dev/ic/if_wi_hostap.c	13 Aug 2002 03:49:51 -0000	1.1.1.1
+++ sys/dev/ic/if_wi_hostap.c	23 Jun 2003 21:17:49 -0000	1.4
@@ -80,7 +80,6 @@
 struct wihap_sta_info *wihap_sta_alloc(struct wi_softc *sc, u_int8_t *addr);
 void wihap_sta_delete(struct wihap_sta_info *sta);
 struct wihap_sta_info *wihap_sta_find(struct wihap_info *whi, u_int8_t *addr);
-int wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[]);
 void wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
     caddr_t pkt, int len);
 void wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[],
@@ -95,6 +94,18 @@
     caddr_t pkt, int len);
 
 /*
+ * wihap_refresh()
+ *
+ *	Update the timeout for a station and clear the did-ping flag.
+ */
+static __inline void
+wihap_refresh(struct wihap_info *whi, struct wihap_sta_info *sta) {
+
+		sta->flags &= ~WI_SIFLAGS_PING;
+		timeout_add(&sta->tmo, hz * whi->inactivity_time);
+}
+
+/*
  * take_hword()
  *
  *	Used for parsing management frames.  The pkt pointer and length
@@ -288,9 +299,6 @@
 	s = splimp();
 	sta = LIST_FIRST(&whi->sta_list);
 	while (sta) {
-
-		timeout_del(&sta->tmo);
-
 		if (sc->wi_flags & WI_FLAGS_ATTACHED) {
 			/* Disassociate station. */
 			if (sta->flags & WI_SIFLAGS_ASSOC)
@@ -306,7 +314,7 @@
 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
 			printf("wihap_shutdown: FREE(sta=0x%x)\n", sta);
 		next = LIST_NEXT(sta, list);
-		FREE(sta, M_DEVBUF);
+		wihap_sta_delete(sta);
 		sta = next;
 	}
 	splx(s);
@@ -339,7 +347,36 @@
 
 	s = splsoftnet();
 
-	if (sta->flags & WI_SIFLAGS_ASSOC) {
+ 	/*
+	 * If there has been no activity for WIHAP_DFLT_INACTIVITY_TIME
+	 * seconds, send an empty data packet to test for an ACK.
+	 *
+ 	 * The "nullfunc" packet type cannot be used because stations
+	 * may or may not ACK it.
+	 */
+	if (!(sta->flags & WI_SIFLAGS_PING)) {
+		struct wi_80211_hdr *resp_hdr;
+
+		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
+			printf("Sending empty DATA ping to sta %s\n",
+			    ether_sprintf(sta->addr));
+
+		/* Send empty data packet. */
+		resp_hdr = (struct wi_80211_hdr *)sc->wi_txbuf;
+		bzero(resp_hdr, sizeof(struct wi_80211_hdr));
+		resp_hdr->frame_ctl = htole16(WI_FTYPE_DATA);
+
+		bcopy(sta->addr, resp_hdr->addr1, ETHER_ADDR_LEN);
+		bcopy(sc->sc_arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN);
+		bcopy(sc->sc_arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN);
+
+		wi_mgmt_xmit(sc, (caddr_t)&sc->wi_txbuf,
+		    sizeof(struct wi_80211_hdr));
+
+		sta->flags |= WI_SIFLAGS_PING;
+
+		timeout_add(&sta->tmo, hz * whi->inactivity_time);
+	} else if (sta->flags & WI_SIFLAGS_ASSOC) {
 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
 			printf("wihap_timer: disassoc due to inactivity: %s\n",
 			    ether_sprintf(sta->addr));
@@ -349,10 +386,8 @@
 		    IEEE80211_REASON_ASSOC_EXPIRE);
 		sta->flags &= ~WI_SIFLAGS_ASSOC;
 
-		timeout_add(&sta->tmo, hz * whi->inactivity_time);
-
+		timeout_add(&sta->tmo, hz * whi->inactivity_time * 2);
 	} else if (sta->flags & WI_SIFLAGS_AUTHEN) {
-
 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
 			printf("wihap_timer: deauth due to inactivity: %s\n",
 			    ether_sprintf(sta->addr));
@@ -465,6 +500,8 @@
 			sta->rates |= WI_SUPPRATES_2M;
 			if (sta->tx_max_rate < 1)
 				sta->tx_max_rate = 1;
+				sta->tx_max_rate = 1;
+				sta->tx_max_rate = 1;
 			break;
 		case 0x0b:
 			sta->rates |= WI_SUPPRATES_5M;
@@ -549,8 +586,8 @@
 			status = IEEE80211_STATUS_TOO_MANY_STATIONS;
 			goto fail;
 		}
-	}
-	timeout_add(&sta->tmo, hz * whi->inactivity_time);
+	} else
+		wihap_refresh(whi, sta);
 
 	/* Note: it's okay to leave the station info structure around
 	 * if the authen fails.  It'll be timed out eventually.
@@ -771,7 +808,7 @@
 	}
 
 	sta->flags |= WI_SIFLAGS_ASSOC;
-	timeout_add(&sta->tmo, hz * whi->inactivity_time);
+	wihap_refresh(whi, sta);
 	status = IEEE80211_STATUS_SUCCESS;
 
 fail:
@@ -941,9 +978,8 @@
 	pkt = mtod(m, caddr_t) + WI_802_11_OFFSET_RAW;
 	len = m->m_len - WI_802_11_OFFSET_RAW;
 
-	if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) ==
-	    htole16(WI_FTYPE_MGMT)) {
-
+	switch (letoh16(rxfrm->wi_frame_ctl) & WI_FCTL_FTYPE) {
+	case WI_FTYPE_MGMT:
 		/* any of the following will mess w/ the station list */
 		s = splsoftclock();
 		switch (letoh16(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE) {
@@ -976,35 +1012,15 @@
 			break;
 		}
 		splx(s);
+		break;
 	}
 
 	m_freem(m);
 }
 
-/* wihap_sta_is_assoc()
- *
- *	Determine if a station is assoc'ed.  Update its activity
- *	counter as a side-effect.
- */
-int
-wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[])
-{
-	struct wihap_sta_info *sta;
-
-	sta = wihap_sta_find(whi, addr);
-	if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) {
-		/* Keep it active. */
-		timeout_add(&sta->tmo, hz * whi->inactivity_time);
-		return (1);
-	}
-
-	return (0);
-}
-
 /* wihap_check_tx()
  *
- *	Determine if a station is assoc'ed, get its tx rate, and update
- *	its activity.
+ *	Determine if a station is assoc'ed and get its tx rate.
  */
 int
 wihap_check_tx(struct wihap_info *whi, u_int8_t addr[], u_int8_t *txrate)
@@ -1020,12 +1036,14 @@
 
 	s = splsoftclock();
 	sta = wihap_sta_find(whi, addr);
-	if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) {
-		/* Keep it active. */
-		timeout_add(&sta->tmo, hz * whi->inactivity_time);
+	if (sta != NULL && sta->flags & WI_SIFLAGS_ASSOC) {
+		int unauth;
+
 		*txrate = txratetable[sta->tx_curr_rate];
+		unauth = whi->apflags & WIHAPFL_AUTHORIZED_FILT &&
+		    !(sta->flags & HOSTAP_FLAGS_AUTHORIZED);
 		splx(s);
-		return (1);
+		return (unauth ? -1 : 1);
 	}
 	splx(s);
 
@@ -1039,7 +1057,10 @@
  *	Some packets are destined for this machine, others are
  *	repeated to other stations.
  *
- *	If wihap_data_input() returns a non-zero, it has processed
+ *	If wihap_data_input() returns -1, then the packet is
+ *	unauthorized but not freed.
+ *
+ *	If wihap_data_input() returns 1, then it has processed
  *	the packet and will free the mbuf.
  */
 int
@@ -1047,7 +1068,7 @@
 {
 	struct ifnet		*ifp = &sc->sc_arpcom.ac_if;
 	struct wihap_info	*whi = &sc->wi_hostap_info;
-	struct wihap_sta_info	*sta;
+	struct wihap_sta_info	*sta, *dststa;
 	int			mcast, s;
 
 	/* TODS flag must be set. */
@@ -1084,15 +1105,24 @@
 		m_freem(m);
 		return (1);
 	}
+	if (whi->apflags & WIHAPFL_AUTHORIZED_FILT &&
+	    !(sta->flags & HOSTAP_FLAGS_AUTHORIZED)) {
+		if (ifp->if_flags & IFF_DEBUG)
+			printf("wihap_data_input: dropping unauthorized "
+			    "src %s\n", ether_sprintf(rxfrm->wi_addr2));
+		splx(s);
+		return (-1);
+	}
 
-	timeout_add(&sta->tmo, hz * whi->inactivity_time);
+	wihap_refresh(whi, sta);
 	sta->sig_info = letoh16(rxfrm->wi_q_info);
 
 	splx(s);
 
 	/* Repeat this packet to BSS? */
 	mcast = (rxfrm->wi_addr3[0] & 0x01) != 0;
-	if (mcast || wihap_sta_is_assoc(whi, rxfrm->wi_addr3)) {
+	dststa = wihap_sta_find(whi, rxfrm->wi_addr3);;
+	if (mcast || (dststa != NULL && dststa->flags & WI_SIFLAGS_ASSOC)) {
 
 		/* If it's multicast, make a copy.
 		 */
@@ -1101,6 +1131,20 @@
 			if (m == NULL)
 				return (0);
 			m->m_flags |= M_MCAST; /* XXX */
+		} else {
+			/*
+			 * Don't send unicast packets to non-authorized
+			 * hosts when in authorized-only mode.
+			 */
+			if (whi->apflags & WIHAPFL_AUTHORIZED_FILT &&
+			    !(dststa->flags & HOSTAP_FLAGS_AUTHORIZED)) {
+				if (ifp->if_flags & IFF_DEBUG)
+					printf("wihap_data_input: dropping "
+					    "unauthorized dst %s\n",
+					    ether_sprintf(rxfrm->wi_addr3));
+				m_freem(m);
+				return (1);
+			}
 		}
 
 		/* Queue up for repeating.
@@ -1187,6 +1231,30 @@
 		splx(s);
 		break;
 
+	case SIOCHOSTAP_CHANGE:
+		if ((error = suser(p->p_ucred, &p->p_acflag)))
+			break;
+		if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta))))
+			break;
+		s = splimp();
+		sta = wihap_sta_find(whi, reqsta.addr);
+		if (sta == NULL)
+			error = ENOENT;
+		else {
+			if (sta->flags & WI_SIFLAGS_ASSOC &&
+			    !(reqsta.flags & WI_SIFLAGS_ASSOC))
+				wihap_sta_disassoc(sc, sta->addr,
+				    IEEE80211_REASON_ASSOC_LEAVE);
+			if (sta->flags & WI_SIFLAGS_AUTHEN &&
+			    !(reqsta.flags & WI_SIFLAGS_AUTHEN))
+				wihap_sta_deauth(sc, sta->addr,
+				    IEEE80211_REASON_AUTH_LEAVE);
+			sta->flags = (sta->flags & HOSTAP_FLAGS_CANTCHANGE) |
+			    (reqsta.flags & ~HOSTAP_FLAGS_CANTCHANGE);
+		}
+		splx(s);
+		break;
+
 	case SIOCHOSTAP_ADD:
 		if ((error = suser(p->p_ucred, &p->p_acflag)))
 			break;
@@ -1205,8 +1273,7 @@
 			break;
 		}
 		sta = wihap_sta_alloc(sc, reqsta.addr);
-		sta->flags = reqsta.flags;
-		timeout_add(&sta->tmo, hz * whi->inactivity_time);
+		sta->flags = reqsta.flags & ~HOSTAP_FLAGS_CANTCHANGE;
 		splx(s);
 		break;
 
@@ -1262,4 +1329,29 @@
 	}
 
 	return (error);
+}
+
+/* wihap_tx_intr()
+ *
+ *	Complete a TX done interrupt by updating the last-used status
+ *	of a station if transmission (i.e. of a ping) was successful.
+ */
+void
+wihap_tx_intr(struct wi_softc *sc, u_int16_t status, struct wi_frame *tx_frame)
+{
+	/* Update the timeout for ACK packets. */
+	struct wihap_sta_info *sta;
+	int s;
+
+	if (status & WI_EV_TX_EXC)
+		return;
+	s = splsoftclock();
+	sta = wihap_sta_find(&sc->wi_hostap_info, tx_frame->wi_addr1);
+	if (sta != NULL) {
+		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
+			printf("wihap_tx_intr: tx completed to %s\n",
+			    ether_sprintf(tx_frame->wi_addr1));
+		wihap_refresh(&sc->wi_hostap_info, sta);
+	}
+	splx(s);
 }
Index: sys/dev/ic/if_wi_hostap.h
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/dev/ic/if_wi_hostap.h,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- sys/dev/ic/if_wi_hostap.h	8 Jun 2002 22:19:47 -0000	1.1.1.1
+++ sys/dev/ic/if_wi_hostap.h	24 Jun 2003 13:12:22 -0000	1.4
@@ -51,7 +51,9 @@
 #define HOSTAP_FLAGS_AUTHEN	0x0001
 #define HOSTAP_FLAGS_ASSOC	0x0002
 #define HOSTAP_FLAGS_PERM	0x0004
-#define	HOSTAP_FLAGS_BITS	"\20\01ASSOC\02AUTH\03PERM"
+#define HOSTAP_FLAGS_AUTHORIZED	0x0008
+#define HOSTAP_FLAGS_PING	0x0010
+#define HOSTAP_FLAGS_BITS	"\20\01AUTH\02ASSOC\03PERM\04AUTHR\05PING"
 
 #define SIOCHOSTAP_GET		_IOWR('i', 210, struct ifreq)
 #define SIOCHOSTAP_ADD		_IOWR('i', 211, struct ifreq)
@@ -59,13 +61,16 @@
 #define SIOCHOSTAP_GETALL	_IOWR('i', 213, struct ifreq)
 #define SIOCHOSTAP_GFLAGS	_IOWR('i', 214, struct ifreq)
 #define SIOCHOSTAP_SFLAGS	_IOWR('i', 215, struct ifreq)
+#define SIOCHOSTAP_CHANGE	_IOWR('i', 216, struct ifreq)
 
 /* Flags for SIOCHOSTAP_GFLAGS/SFLAGS */
 #define WIHAPFL_ACTIVE		0x0001
 #define WIHAPFL_MAC_FILT	0x0002
+#define WIHAPFL_AUTHORIZED_FILT	0x0004
 
-/* Flags set inernally only: */
+/* Flags set internally only: */
 #define WIHAPFL_CANTCHANGE	(WIHAPFL_ACTIVE)
+#define HOSTAP_FLAGS_CANTCHANGE	(HOSTAP_FLAGS_PING)
 
 struct hostap_getall {
 	int		nstations;
@@ -97,6 +102,8 @@
 #define WI_SIFLAGS_ASSOC	HOSTAP_FLAGS_ASSOC
 #define WI_SIFLAGS_AUTHEN	HOSTAP_FLAGS_AUTHEN
 #define WI_SIFLAGS_PERM		HOSTAP_FLAGS_PERM
+#define WI_SIFLAGS_AUTHORIZED	HOSTAP_FLAGS_AUTHORIZED
+#define WI_SIFLAGS_PING		HOSTAP_FLAGS_PING
 
 #define WI_STA_HASH_SIZE	113
 
@@ -119,7 +126,7 @@
 	int			inactivity_time;
 };
 
-#define WIHAP_DFLT_INACTIVITY_TIME	(120) /* 2 minutes */
+#define WIHAP_DFLT_INACTIVITY_TIME	(60) /* 1 minute */
 
 struct wi_softc;
 struct wi_frame;
@@ -129,6 +136,7 @@
 int	wihap_ioctl(struct wi_softc *, u_long, caddr_t);
 void	wihap_init(struct wi_softc *);
 void	wihap_mgmt_input(struct wi_softc *, struct wi_frame *, struct mbuf *);
+void	wihap_tx_intr(struct wi_softc *, u_int16_t status, struct wi_frame *);
 void	wihap_shutdown(struct wi_softc *);
 
 #endif /* _KERNEL */
Index: sys/dev/ic/if_wi_ieee.h
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/dev/ic/if_wi_ieee.h,v
retrieving revision 1.1.1.1
retrieving revision 1.5
diff -u -r1.1.1.1 -r1.5
--- sys/dev/ic/if_wi_ieee.h	10 Sep 2002 08:21:35 -0000	1.1.1.1
+++ sys/dev/ic/if_wi_ieee.h	24 Jun 2003 13:12:22 -0000	1.5
@@ -82,7 +82,7 @@
  */
 #define WI_RID_IFACE_STATS	0x0100
 #define WI_RID_MGMT_XMIT	0x0200
-#define	WI_RID_MONITOR_MODE	0x0500
+#define WI_RID_MONITOR_MODE	0x0500
 
 struct wi_80211_hdr {
 	u_int16_t		frame_ctl;
@@ -180,39 +180,39 @@
 /*
  * Network parameters, static configuration entities.
  */
-#define	WI_RID_PORTTYPE		0xFC00 /* Connection control characteristics */
-#define	WI_RID_MAC_NODE		0xFC01 /* MAC address of this station */
-#define	WI_RID_DESIRED_SSID	0xFC02 /* Service Set ID for connection */
-#define	WI_RID_OWN_CHNL		0xFC03 /* Comm channel for BSS creation */
-#define	WI_RID_OWN_SSID		0xFC04 /* IBSS creation ID */
-#define	WI_RID_OWN_ATIM_WIN	0xFC05 /* ATIM window time for IBSS creation */
-#define	WI_RID_SYSTEM_SCALE	0xFC06 /* scale that specifies AP density */
-#define	WI_RID_MAX_DATALEN	0xFC07 /* Max len of MAC frame body data */
-#define	WI_RID_MAC_WDS		0xFC08 /* MAC addr of corresponding WDS node */
-#define	WI_RID_PM_ENABLED	0xFC09 /* ESS power management enable */
-#define	WI_RID_PM_EPS		0xFC0A /* PM EPS/PS mode */
-#define	WI_RID_MCAST_RX		0xFC0B /* ESS PM mcast reception */
-#define	WI_RID_MAX_SLEEP	0xFC0C /* max sleep time for ESS PM */
-#define	WI_RID_HOLDOVER		0xFC0D /* holdover time for ESS PM */
-#define	WI_RID_NODENAME		0xFC0E /* ID name of this node for diag */
-#define	WI_RID_DTIM_PERIOD	0xFC10 /* beacon interval between DTIMs */
-#define	WI_RID_WDS_ADDR1	0xFC11 /* port 1 MAC of WDS link node */
-#define	WI_RID_WDS_ADDR2	0xFC12 /* port 1 MAC of WDS link node */
-#define	WI_RID_WDS_ADDR3	0xFC13 /* port 1 MAC of WDS link node */
-#define	WI_RID_WDS_ADDR4	0xFC14 /* port 1 MAC of WDS link node */
-#define	WI_RID_WDS_ADDR5	0xFC15 /* port 1 MAC of WDS link node */
-#define	WI_RID_WDS_ADDR6	0xFC16 /* port 1 MAC of WDS link node */
-#define	WI_RID_MCAST_PM_BUF	0xFC17 /* PM buffering of mcast */
-#define	WI_RID_ENCRYPTION	0xFC20 /* enable/disable WEP */
-#define	WI_RID_AUTHTYPE		0xFC21 /* specify authentication type */
-#define	WI_RID_SYMBOL_MANDATORYBSSID 0xFC21
-#define	WI_RID_P2_TX_CRYPT_KEY	0xFC23
-#define	WI_RID_P2_CRYPT_KEY0	0xFC24
-#define	WI_RID_P2_CRYPT_KEY1	0xFC25
-#define	WI_RID_MICROWAVE_OVEN	0xFC25 /* Microwave oven robustness */
-#define	WI_RID_P2_CRYPT_KEY2	0xFC26
-#define	WI_RID_P2_CRYPT_KEY3	0xFC27
-#define	WI_RID_P2_ENCRYPTION	0xFC28
+#define WI_RID_PORTTYPE		0xFC00 /* Connection control characteristics */
+#define WI_RID_MAC_NODE		0xFC01 /* MAC address of this station */
+#define WI_RID_DESIRED_SSID	0xFC02 /* Service Set ID for connection */
+#define WI_RID_OWN_CHNL		0xFC03 /* Comm channel for BSS creation */
+#define WI_RID_OWN_SSID		0xFC04 /* IBSS creation ID */
+#define WI_RID_OWN_ATIM_WIN	0xFC05 /* ATIM window time for IBSS creation */
+#define WI_RID_SYSTEM_SCALE	0xFC06 /* scale that specifies AP density */
+#define WI_RID_MAX_DATALEN	0xFC07 /* Max len of MAC frame body data */
+#define WI_RID_MAC_WDS		0xFC08 /* MAC addr of corresponding WDS node */
+#define WI_RID_PM_ENABLED	0xFC09 /* ESS power management enable */
+#define WI_RID_PM_EPS		0xFC0A /* PM EPS/PS mode */
+#define WI_RID_MCAST_RX		0xFC0B /* ESS PM mcast reception */
+#define WI_RID_MAX_SLEEP	0xFC0C /* max sleep time for ESS PM */
+#define WI_RID_HOLDOVER		0xFC0D /* holdover time for ESS PM */
+#define WI_RID_NODENAME		0xFC0E /* ID name of this node for diag */
+#define WI_RID_DTIM_PERIOD	0xFC10 /* beacon interval between DTIMs */
+#define WI_RID_WDS_ADDR1	0xFC11 /* port 1 MAC of WDS link node */
+#define WI_RID_WDS_ADDR2	0xFC12 /* port 1 MAC of WDS link node */
+#define WI_RID_WDS_ADDR3	0xFC13 /* port 1 MAC of WDS link node */
+#define WI_RID_WDS_ADDR4	0xFC14 /* port 1 MAC of WDS link node */
+#define WI_RID_WDS_ADDR5	0xFC15 /* port 1 MAC of WDS link node */
+#define WI_RID_WDS_ADDR6	0xFC16 /* port 1 MAC of WDS link node */
+#define WI_RID_MCAST_PM_BUF	0xFC17 /* PM buffering of mcast */
+#define WI_RID_ENCRYPTION	0xFC20 /* enable/disable WEP */
+#define WI_RID_AUTHTYPE		0xFC21 /* specify authentication type */
+#define WI_RID_SYMBOL_MANDATORYBSSID 0xFC21
+#define WI_RID_P2_TX_CRYPT_KEY	0xFC23
+#define WI_RID_P2_CRYPT_KEY0	0xFC24
+#define WI_RID_P2_CRYPT_KEY1	0xFC25
+#define WI_RID_MICROWAVE_OVEN	0xFC25 /* Microwave oven robustness */
+#define WI_RID_P2_CRYPT_KEY2	0xFC26
+#define WI_RID_P2_CRYPT_KEY3	0xFC27
+#define WI_RID_P2_ENCRYPTION	0xFC28
 #define PRIVACY_INVOKED		0x01
 #define EXCLUDE_UNENCRYPTED	0x02
 #define HOST_ENCRYPT		0x10
@@ -221,16 +221,16 @@
 #define IV_EVERY50_FRAME	0x40
 #define IV_EVERY100_FRAME	0x60
 #define HOST_DECRYPT		0x80
-#define	WI_RID_WEP_MAPTABLE	0xFC29
-#define	WI_RID_CNFAUTHMODE	0xFC2A
-#define	WI_RID_SYMBOL_KEYLENGTH	0xFC2B
-#define	WI_RID_ROAMING_MODE	0xFC2D /* Roaming mode (1:firm,3:disable) */
-#define	WI_RID_CNF_DBM_ADJUST	0xFC46 /* Get DBM adjustment factor */
-#define	WI_RID_SYMBOL_PREAMBLE	0xFC8C /* Enable/disable short preamble */
-#define	WI_RID_P2_SHORT_PREAMBLE	0xFCB0 /* Short preamble support */
-#define	WI_RID_P2_EXCLUDE_LONG_PREAMBLE	0xFCB1 /* Don't send long preamble */
-#define	WI_RID_BASIC_RATE	0xFCB3
-#define	WI_RID_SUPPORT_RATE	0xFCB4
+#define WI_RID_WEP_MAPTABLE	0xFC29
+#define WI_RID_CNFAUTHMODE	0xFC2A
+#define WI_RID_SYMBOL_KEYLENGTH	0xFC2B
+#define WI_RID_ROAMING_MODE	0xFC2D /* Roaming mode (1:firm,3:disable) */
+#define WI_RID_CNF_DBM_ADJUST	0xFC46 /* Get DBM adjustment factor */
+#define WI_RID_SYMBOL_PREAMBLE	0xFC8C /* Enable/disable short preamble */
+#define WI_RID_P2_SHORT_PREAMBLE	0xFCB0 /* Short preamble support */
+#define WI_RID_P2_EXCLUDE_LONG_PREAMBLE	0xFCB1 /* Don't send long preamble */
+#define WI_RID_BASIC_RATE	0xFCB3
+#define WI_RID_SUPPORT_RATE	0xFCB4
 #define WI_RID_SYMBOL_DIVERSITY	0xFC87 /* Symbol antenna diversity */
 #define WI_RID_SYMBOL_BASIC_RATE 0xFC90
 
@@ -544,6 +544,7 @@
  */
 #define WI_RID_PROCFRAME	0x3137 /* Return full frame information */
 #define WI_RID_PRISM2		0x3138 /* tell if we're a prism2 card or not */
+#define WI_RID_PRISM2HDR	0x3139 /* provide the PRISM 2 header */
 
 
 /*
@@ -708,4 +709,13 @@
 #define WI_RID_MAC_PROC_DELAY	0xFDC5 /* MAC processing delay time */
 #define WI_RID_DATA_RATES	0xFDC6 /* supported data rates */
 
+/*
+ * Mbuf tag types for sending packets with special conditions utilizing
+ * the BIOCSTAGGED ioctl on bpf devices
+ */
+#define WI_TAG_CHANGE_TX_KEY	0x0	/* switch to a different WEP key */
+struct wi_tag_change_tx_key {
+	u_char	type;
+	u_char	change_tx_key;	/* WEP key #0-N, or 255 to disable */
+};
 #endif
Index: sys/dev/ic/if_wireg.h
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/dev/ic/if_wireg.h,v
retrieving revision 1.1.1.1
retrieving revision 1.6
diff -u -r1.1.1.1 -r1.6
--- sys/dev/ic/if_wireg.h	12 Sep 2002 03:48:31 -0000	1.1.1.1
+++ sys/dev/ic/if_wireg.h	24 Jun 2003 13:12:22 -0000	1.6
@@ -26,7 +26,7 @@
  * 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
+ * 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.
@@ -70,11 +70,11 @@
 
 #define WI_DEFAULT_CHAN		3
 
-#define	WI_DEFAULT_ROAMING	1
+#define WI_DEFAULT_ROAMING	1
 
-#define	WI_DEFAULT_AUTHTYPE	1
+#define WI_DEFAULT_AUTHTYPE	1
 
-#define	WI_DEFAULT_DIVERSITY	0
+#define WI_DEFAULT_DIVERSITY	0
 
 /*
  * register space access macros
@@ -272,6 +272,12 @@
 #define WI_INTRS	\
 	(WI_EV_RX|WI_EV_TX|WI_EV_TX_EXC|WI_EV_ALLOC|WI_EV_INFO|WI_EV_INFO_DROP)
 
+/* async tx failure status */
+#define WI_TX_EXC_RETRYERR	0x0001
+#define WI_TX_EXC_AGEDERR	0x0002
+#define WI_TX_EXC_DISCON	0x0004
+#define WI_TX_EXC_FORMERR	0x0008
+
 /* Host software registers */
 #define WI_SW0			0x28
 #define WI_SW1			0x2A
@@ -301,7 +307,7 @@
 #define WI_PLX_LINT1STAT	0x04	/* Local interrupt 1 status bit */
 #define WI_PLX_COR_OFFSET	0x3E0	/* COR attribute offset of card */
 
-#define	WI_DRVR_MAGIC		0x4A2D	/* Magic number for card detection */
+#define WI_DRVR_MAGIC		0x4A2D	/* Magic number for card detection */
 
 #define WI_TMD_LOCALRES		0x14	/* TMD chip's local registers */
 #define WI_TMD_IORES		0x18	/* Prism I/O space (TMD) */
@@ -402,19 +408,19 @@
 	u_int16_t	wi_len;
 	u_int16_t	wi_type;
 	u_int16_t	wi_ver[4];
-#define	WI_NIC_LUCENT		0x0001
-#define	WI_NIC_SONY		0x0002
-#define	WI_NIC_LUCENT_EM	0x0005
-#define	WI_NIC_EVB2		0x8000
-#define	WI_NIC_HWB3763		0x8001
-#define	WI_NIC_HWB3163		0x8002
-#define	WI_NIC_HWB3163B		0x8003
-#define	WI_NIC_EVB3		0x8004
-#define	WI_NIC_HWB1153		0x8007
-#define	WI_NIC_P2_SST		0x8008  /* Prism2 with SST flush */
-#define	WI_NIC_PRISM2_5		0x800C
-#define	WI_NIC_3874A		0x8013	/* Prism2.5 Mini-PCI */
-#define	WI_NIC_37300P		0x801a
+#define WI_NIC_LUCENT		0x0001
+#define WI_NIC_SONY		0x0002
+#define WI_NIC_LUCENT_EM	0x0005
+#define WI_NIC_EVB2		0x8000
+#define WI_NIC_HWB3763		0x8001
+#define WI_NIC_HWB3163		0x8002
+#define WI_NIC_HWB3163B		0x8003
+#define WI_NIC_EVB3		0x8004
+#define WI_NIC_HWB1153		0x8007
+#define WI_NIC_P2_SST		0x8008  /* Prism2 with SST flush */
+#define WI_NIC_PRISM2_5		0x800C
+#define WI_NIC_3874A		0x8013	/* Prism2.5 Mini-PCI */
+#define WI_NIC_37300P		0x801a
 };
 
 /*
@@ -530,7 +536,7 @@
 #define WI_SUPPRATES_2M		0x0002
 #define WI_SUPPRATES_5M		0x0004
 #define WI_SUPPRATES_11M	0x0008
-#define	WI_RATES_BITS	"\20\0011M\0022M\0035.5M\00411M"
+#define WI_RATES_BITS	"\20\0011M\0022M\0035.5M\00411M"
 
 /*
  * Information frame types.
@@ -546,12 +552,13 @@
  */
 struct wi_frame {
 	u_int16_t		wi_status;	/* 0x00 */
-	u_int16_t		wi_rsvd0;	/* 0x02 */
-	u_int16_t		wi_rsvd1;	/* 0x04 */
+	u_int16_t		wi_time0;	/* 0x02 */
+	u_int16_t		wi_time1;	/* 0x04 */
 	u_int16_t		wi_q_info;	/* 0x06 */
-	u_int16_t		wi_rsvd2;	/* 0x08 */
+	u_int8_t		wi_rx_rate;	/* 0x08 */
+	u_int8_t		wi_rx_flow;	/* 0x09 */
 	u_int8_t		wi_tx_rtry;	/* 0x0A */
-	u_int8_t		wi_tx_rate;	/* 0x0A */
+	u_int8_t		wi_tx_rate;	/* 0x0B */
 	u_int16_t		wi_tx_ctl;	/* 0x0C */
 	u_int16_t		wi_frame_ctl;	/* 0x0E */
 	u_int16_t		wi_id;		/* 0x10 */
@@ -585,7 +592,7 @@
 
 #define WI_ENC_TX_802_3		0x00
 #define WI_ENC_TX_802_11	0x11
-#define	WI_ENC_TX_MGMT		0x08
+#define WI_ENC_TX_MGMT		0x08
 #define WI_ENC_TX_E_II		0x0E
 
 #define WI_ENC_TX_1042		0x00
@@ -612,3 +619,25 @@
 #define WI_SNAPHDR_LEN		0x6
 #define WI_FCS_LEN		0x4
 
+
+/*
+ * Prism2 (?) special informational header.
+ */
+struct prism2_header {
+        u_int32_t	version;
+        u_int32_t	length;
+        u_int64_t	mac_time;
+        u_int64_t	host_time;
+        u_int32_t	phy_type;
+        u_int32_t	channel;
+        u_int32_t	data_rate;
+        u_int32_t	antenna;
+        u_int32_t	priority;
+        u_int32_t	ssi_type;
+        int32_t		ssi_signal;
+        int32_t		ssi_noise;
+        u_int32_t	preamble;
+        u_int32_t	encoding;
+};
+
+#define PRISM2_HEADER_VERSION	0x80211001
Index: sys/dev/ic/if_wivar.h
===================================================================
RCS file: /u/cvs/SNOWNET/Soekris/OpenBSD-src/sys/dev/ic/if_wivar.h,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- sys/dev/ic/if_wivar.h	9 Jul 2002 11:00:27 -0000	1.1.1.1
+++ sys/dev/ic/if_wivar.h	24 Jun 2003 13:12:22 -0000	1.4
@@ -52,6 +52,7 @@
 	int			wi_flags;
 	int			wi_if_flags;
 	u_int16_t		wi_procframe;
+	u_int16_t		wi_prism2hdr;
 	u_int16_t		wi_ptype;
 	u_int16_t		wi_portnum;
 	u_int16_t		wi_max_data_len;
@@ -120,6 +121,7 @@
 #define WI_FLAGS_HAS_DIVERSITY		0x0080
 #define WI_FLAGS_HAS_HOSTAP		0x0100
 #define WI_FLAGS_BUS_PCMCIA		0x0200
+#define WI_FLAGS_KEEP_HOSTAP_UP		0x0400
 
 /* Firmware types */
 #define WI_LUCENT	0



More information about the Hostap mailing list