Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Nov 2003 09:02:02 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 42808 for review
Message-ID:  <200311201702.hAKH2247081905@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=42808

Change 42808 by sam@sam_ebb on 2003/11/20 09:01:40

	First pass at integrating netbsd work:
	
	o os portability changes
	o pspoll support
	o shared key authentication support
	o manage assigned aid's to avoid duplicate assignment
	o support for FH phy's
	o change IFM_* constants from values to bitmasks
	o minor (but ABI-changing) mods to radiotap definitions
	
	Still need to go over changes in populating the node table
	that are supposed to fix adhoc mode.

Affected files ...

.. //depot/projects/netperf/sys/net80211/ieee80211.c#6 edit
.. //depot/projects/netperf/sys/net80211/ieee80211.h#3 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_compat.c#1 add
.. //depot/projects/netperf/sys/net80211/ieee80211_compat.h#1 add
.. //depot/projects/netperf/sys/net80211/ieee80211_input.c#14 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.c#16 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.h#11 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_output.c#11 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_proto.c#8 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_radiotap.h#4 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_var.h#10 edit

Differences ...

==== //depot/projects/netperf/sys/net80211/ieee80211.c#6 (text+ko) ====

@@ -84,7 +84,8 @@
 	"11a",		/* IEEE80211_MODE_11A */
 	"11b",		/* IEEE80211_MODE_11B */
 	"11g",		/* IEEE80211_MODE_11G */
-	"turbo",	/* IEEE80211_MODE_TURBO	*/
+	"FH",		/* IEEE80211_MODE_FH */
+	"turbo",	/* IEEE80211_MODE_TURBO */
 };
 
 void
@@ -129,6 +130,8 @@
 				ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
 			if (IEEE80211_IS_CHAN_PUREG(c))
 				ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
+			if (IEEE80211_IS_CHAN_FHSS(c))
+				ic->ic_modecaps |= 1<<IEEE80211_MODE_FH;
 			if (IEEE80211_IS_CHAN_T(c))
 				ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO;
 		}
@@ -266,10 +269,11 @@
 	for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) {
 		static const u_int mopts[] = { 
 			IFM_AUTO,
-			IFM_MAKEMODE(IFM_IEEE80211_11A),
-			IFM_MAKEMODE(IFM_IEEE80211_11B),
-			IFM_MAKEMODE(IFM_IEEE80211_11G),
-			IFM_MAKEMODE(IFM_IEEE80211_11A) | IFM_IEEE80211_TURBO,
+			IFM_IEEE80211_11A,
+			IFM_IEEE80211_11B,
+			IFM_IEEE80211_11G,
+			IFM_IEEE80211_FH,
+			IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
 		};
 		if ((ic->ic_modecaps & (1<<mode)) == 0)
 			continue;
@@ -343,6 +347,9 @@
 
 	if (maxrate)
 		ifp->if_baudrate = IF_Mbps(maxrate);
+
+	if (ic->ic_max_aid == 0)
+		ic->ic_max_aid = IEEE80211_MAX_AID;
 #undef ADD
 }
 
@@ -385,6 +392,9 @@
 	case IFM_IEEE80211_11G:
 		newphymode = IEEE80211_MODE_11G;
 		break;
+	case IFM_IEEE80211_FH:
+		newphymode = IEEE80211_MODE_FH;
+		break;
 	case IFM_AUTO:
 		newphymode = IEEE80211_MODE_AUTO;
 		break;
@@ -555,17 +565,19 @@
 	}
 	switch (ic->ic_curmode) {
 	case IEEE80211_MODE_11A:
-		imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A);
+		imr->ifm_active |= IFM_IEEE80211_11A;
 		break;
 	case IEEE80211_MODE_11B:
-		imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11B);
+		imr->ifm_active |= IFM_IEEE80211_11B;
 		break;
 	case IEEE80211_MODE_11G:
-		imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11G);
+		imr->ifm_active |= IFM_IEEE80211_11G;
+		break;
+	case IEEE80211_MODE_FH:
+		imr->ifm_active |= IFM_IEEE80211_FH;
 		break;
 	case IEEE80211_MODE_TURBO:
-		imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A)
-				|  IFM_IEEE80211_TURBO;
+		imr->ifm_active |= IFM_IEEE80211_11A | IFM_IEEE80211_TURBO;
 		break;
 	}
 }
@@ -598,6 +610,7 @@
 	    { 3, { 12, 24, 48 } },		/* IEEE80211_MODE_11A */
 	    { 4, { 2, 4, 11, 22 } },		/* IEEE80211_MODE_11B */
 	    { 7, { 2, 4, 11, 22, 12, 24, 48 } },/* IEEE80211_MODE_11G */
+	    { 0 },				/* IEEE80211_MODE_FH */
 	    { 0 },				/* IEEE80211_MODE_TURBO	*/
 	};
 	int i, j;
@@ -627,6 +640,7 @@
 		IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
 		IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
 		IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
+		IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
 		IEEE80211_CHAN_T,	/* IEEE80211_MODE_TURBO	*/
 	};
 	struct ieee80211_channel *c;
@@ -691,6 +705,11 @@
 				ic->ic_ibss_chan = &ic->ic_channels[i];
 				break;
 			}
+		KASSERT(ic->ic_ibss_chan != NULL &&
+		    isset(ic->ic_chan_active,
+			ieee80211_chan2ieee(ic, ic->ic_ibss_chan)),
+		    ("Bad IBSS channel %u",
+		     ieee80211_chan2ieee(ic, ic->ic_ibss_chan)));
 	}
 
 	/*
@@ -719,6 +738,8 @@
  * Return the phy mode for with the specified channel so the
  * caller can select a rate set.  This is problematic and the
  * work here assumes how things work elsewhere in this code.
+ *
+ * XXX never returns turbo modes -dcy
  */
 enum ieee80211_phymode
 ieee80211_chan2mode(struct ieee80211com *ic, struct ieee80211_channel *chan)
@@ -736,6 +757,8 @@
 	 */
 	if (IEEE80211_IS_CHAN_5GHZ(chan))
 		return IEEE80211_MODE_11A;
+	else if (IEEE80211_IS_CHAN_FHSS(chan))
+		return IEEE80211_MODE_FH;
 	else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
 		return IEEE80211_MODE_11G;
 	else
@@ -754,31 +777,31 @@
 		u_int	m;	/* rate + mode */
 		u_int	r;	/* if_media rate */
 	} rates[] = {
-		{   2 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS1 },
-		{   4 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS2 },
-		{  11 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS5 },
-		{  22 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS11 },
-		{  44 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS22 },
-		{  12 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM6 },
-		{  18 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM9 },
-		{  24 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM12 },
-		{  36 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM18 },
-		{  48 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM24 },
-		{  72 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM36 },
-		{  96 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM48 },
-		{ 108 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM54 },
-		{   2 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS1 },
-		{   4 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS2 },
-		{  11 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS5 },
-		{  22 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS11 },
-		{  12 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM6 },
-		{  18 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM9 },
-		{  24 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM12 },
-		{  36 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM18 },
-		{  48 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM24 },
-		{  72 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM36 },
-		{  96 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM48 },
-		{ 108 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM54 },
+		{   2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },
+		{   4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },
+		{  11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },
+		{  22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },
+		{  44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },
+		{  12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },
+		{  18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },
+		{  24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },
+		{  36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },
+		{  48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },
+		{  72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },
+		{  96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },
+		{ 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },
+		{   2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },
+		{   4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },
+		{  11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },
+		{  22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },
+		{  12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },
+		{  18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },
+		{  24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },
+		{  36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },
+		{  48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },
+		{  72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
+		{  96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
+		{ 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
 		/* NB: OFDM72 doesn't realy exist so we don't handle it */
 	};
 	u_int mask, i;
@@ -787,10 +810,13 @@
 	switch (mode) {
 	case IEEE80211_MODE_11A:
 	case IEEE80211_MODE_TURBO:
-		mask |= IFM_MAKEMODE(IFM_IEEE80211_11A);
+		mask |= IFM_IEEE80211_11A;
 		break;
 	case IEEE80211_MODE_11B:
-		mask |= IFM_MAKEMODE(IFM_IEEE80211_11B);
+		mask |= IFM_IEEE80211_11B;
+		break;
+	case IEEE80211_MODE_FH:
+		mask |= IFM_IEEE80211_FH;
 		break;
 	case IEEE80211_MODE_AUTO:
 		/* NB: ic may be NULL for some drivers */
@@ -805,7 +831,7 @@
 		/* NB: hack, 11g matches both 11b+11a rates */
 		/* fall thru... */
 	case IEEE80211_MODE_11G:
-		mask |= IFM_MAKEMODE(IFM_IEEE80211_11G);
+		mask |= IFM_IEEE80211_11G;
 		break;
 	}
 	for (i = 0; i < N(rates); i++)
@@ -845,6 +871,7 @@
 #undef N
 }
 
+#ifdef __FreeBSD__
 /*
  * Module glue.
  *
@@ -873,3 +900,4 @@
 DECLARE_MODULE(wlan, ieee80211_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
 MODULE_VERSION(wlan, 1);
 MODULE_DEPEND(wlan, rc4, 1, 1, 1);
+#endif /* __FreeBSD__ */

==== //depot/projects/netperf/sys/net80211/ieee80211.h#3 (text+ko) ====

@@ -51,6 +51,9 @@
 	u_int16_t	i_crc;
 } __attribute__((__packed__));
 
+#define IEEE80211_PLCP_SFD      0xF3A0 
+#define IEEE80211_PLCP_SERVICE  0x00
+
 /*
  * generic definitions for IEEE 802.11 frames
  */
@@ -272,6 +275,8 @@
 	IEEE80211_ELEMID_XRATES			= 50,
 };
 
+#define IEEE80211_CHALLENGE_LEN			128
+
 #define	IEEE80211_RATE_BASIC			0x80
 #define	IEEE80211_RATE_VAL			0x7f
 
@@ -366,6 +371,15 @@
 #define	IEEE80211_MIN_LEN \
 	(sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN)
 
+#define	IEEE80211_MAX_AID			2007
+
+#define	IEEE80211_AID_SET(b, w) \
+	((w)[((b) & ~0xc000) / 32] |= (1 << (((b) & ~0xc000) % 32)))
+#define	IEEE80211_AID_CLR(b, w) \
+	((w)[((b) & ~0xc000) / 32] &= ~(1 << (((b) & ~0xc000) % 32)))
+#define	IEEE80211_AID_ISSET(b, w) \
+	((w)[((b) & ~0xc000) / 32] & (1 << (((b) & ~0xc000) % 32)))
+
 /* 
  * RTS frame length parameters.  The default is specified in
  * the 802.11 spec.  The max may be wrong for jumbo frames.

==== //depot/projects/netperf/sys/net80211/ieee80211_input.c#14 (text+ko) ====

@@ -68,6 +68,8 @@
 
 static	struct mbuf *ieee80211_reass(struct ieee80211com *,
 				     struct ieee80211_node *, struct mbuf *);
+static	void ieee80211_recv_pspoll(struct ieee80211com *,
+				   struct mbuf *, int, u_int32_t);
 
 /*
  * Process a received frame.  The node associated with the sender
@@ -138,10 +140,10 @@
 		switch (ic->ic_opmode) {
 		case IEEE80211_M_STA:
 			if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
-				/* not interested in */
 				IEEE80211_DPRINTF2(("%s: discard frame from "
 					"bss %s\n", __func__,
 					ether_sprintf(wh->i_addr2)));
+				/* not interested in */
 				ic->ic_stats.is_rx_wrongbss++;
 				goto out;
 			}
@@ -184,6 +186,35 @@
 		ni->ni_inact = 0;
 	}
 
+	if (ic->ic_set_tim != NULL &&
+	    (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) &&
+	    ni->ni_pwrsave == 0) {
+		/* turn on power save mode */
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "power save mode on for %s\n",
+			    ether_sprintf(wh->i_addr2));
+		ni->ni_pwrsave = IEEE80211_PS_SLEEP;
+	}
+	if (ic->ic_set_tim != NULL &&
+	    (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) == 0 &&
+	    ni->ni_pwrsave != 0) {
+		/* turn off power save mode, dequeue stored packets */
+		ni->ni_pwrsave = 0;
+		if (ic->ic_set_tim) 
+			ic->ic_set_tim(ic, ni->ni_associd, 0);
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "power save mode off for %s\n",
+			    ether_sprintf(wh->i_addr2));
+		for (;;) {
+			struct mbuf *m;
+			IF_DEQUEUE(&ni->ni_savedq, m);
+			if (!m)
+				break;
+			IF_ENQUEUE(&ic->ic_pwrsaveq, m);
+			(*ifp->if_start)(ifp);
+		}
+	}
+
 	switch (type) {
 	case IEEE80211_FC0_TYPE_DATA:
 		switch (ic->ic_opmode) {
@@ -307,8 +338,15 @@
 				ifp->if_obytes += len;
 			}
 		}
-		if (m != NULL)
+		if (m != NULL) {
+			/*
+			 * If we forward packet into transmitter of the AP,
+			 * we don't need to duplicate for DLT_EN10MB.
+			 */
+			if (ifp->if_bpf && m1 == NULL)
+				bpf_mtap(ifp->if_bpf, m);
 			(*ifp->if_input)(ifp, m);
+		}
 		return;
 
 	case IEEE80211_FC0_TYPE_MGT:
@@ -374,6 +412,17 @@
 
 	case IEEE80211_FC0_TYPE_CTL:
 		ic->ic_stats.is_rx_ctl++;
+		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
+			goto out;
+		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+		if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL) {
+			/* Dump out a single packet from the host */
+			if (ifp->if_flags & IFF_DEBUG)
+				printf("%s: got power save probe from %s\n",
+				    ifp->if_xname,
+				    ether_sprintf(wh->i_addr2));
+			ieee80211_recv_pspoll(ic, m, rssi, rstamp);
+		}
 		goto out;
 	default:
 		IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, type));
@@ -620,6 +669,233 @@
 	}								\
 } while (0)
 
+static void
+ieee80211_auth_open(struct ieee80211com *ic, struct ieee80211_frame *wh,
+    struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq,
+    u_int16_t status)
+{
+	struct ifnet *ifp = &ic->ic_if;
+	int allocbs;
+
+	switch (ic->ic_opmode) {
+	case IEEE80211_M_IBSS:
+		if (ic->ic_state != IEEE80211_S_RUN ||
+		    seq != IEEE80211_AUTH_OPEN_REQUEST) {
+			ic->ic_stats.is_rx_bad_auth++;
+			return;
+		}
+		ieee80211_new_state(ic, IEEE80211_S_AUTH,
+		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+		break;
+
+	case IEEE80211_M_AHDEMO:
+		/* should not come here */
+		break;
+
+	case IEEE80211_M_HOSTAP:
+		if (ic->ic_state != IEEE80211_S_RUN ||
+		    seq != IEEE80211_AUTH_OPEN_REQUEST) {
+			ic->ic_stats.is_rx_bad_auth++;
+			return;
+		}
+		if (ni == ic->ic_bss) {
+			ni = ieee80211_alloc_node(ic, wh->i_addr2);
+			if (ni == NULL)
+				return;
+			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
+			ni->ni_rssi = rssi;
+			ni->ni_rstamp = rstamp;
+			ni->ni_chan = ic->ic_bss->ni_chan;
+			allocbs = 1;
+		} else
+			allocbs = 0;
+		IEEE80211_SEND_MGMT(ic, ni,
+			IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "station %s %s authenticated\n",
+			    ether_sprintf(ni->ni_macaddr),
+			    (allocbs ? "newly" : "already"));
+		break;
+
+	case IEEE80211_M_STA:
+		if (ic->ic_state != IEEE80211_S_AUTH ||
+		    seq != IEEE80211_AUTH_OPEN_RESPONSE) {
+			ic->ic_stats.is_rx_bad_auth++;
+			return;
+		}
+		if (status != 0) {
+			if_printf(&ic->ic_if,
+			    "authentication failed (reason %d) for %s\n",
+			    status,
+			    ether_sprintf(wh->i_addr3));
+			if (ni != ic->ic_bss)
+				ni->ni_fails++;
+			ic->ic_stats.is_rx_auth_fail++;
+			return;
+		}
+		ieee80211_new_state(ic, IEEE80211_S_ASSOC,
+		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+		break;
+	case IEEE80211_M_MONITOR:
+		break;
+	}
+}
+
+/* TBD send appropriate responses on error? */
+static void
+ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh,
+    u_int8_t *frm, u_int8_t *efrm, struct ieee80211_node *ni, int rssi,
+    u_int32_t rstamp, u_int16_t seq, u_int16_t status)
+{
+	struct ifnet *ifp = &ic->ic_if;
+	u_int8_t *challenge = NULL;
+	int allocbs, i;
+
+	if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
+		IEEE80211_DPRINTF(("%s: WEP is off\n", __func__));
+		return;
+	}
+
+	if (frm + 1 < efrm) {
+		if ((frm[1] + 2) > (efrm - frm)) {
+			IEEE80211_DPRINTF(("elt %d %d bytes too long\n",
+			    frm[0], (frm[1] + 2) - (efrm - frm)));
+			return;
+		}
+		if (*frm == IEEE80211_ELEMID_CHALLENGE)
+			challenge = frm;
+		frm += frm[1] + 2;
+	}
+	switch (seq) {
+	case IEEE80211_AUTH_SHARED_CHALLENGE:
+	case IEEE80211_AUTH_SHARED_RESPONSE:
+		if (challenge == NULL) {
+			IEEE80211_DPRINTF(("%s: no challenge sent\n",
+			    __func__));
+			return;
+		}
+		if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
+			IEEE80211_DPRINTF(("%s: bad challenge len %d\n",
+			    __func__, challenge[1]));
+			return;
+		}
+	default:
+		break;
+	}
+	switch (ic->ic_opmode) {
+	case IEEE80211_M_MONITOR:
+	case IEEE80211_M_AHDEMO:
+	case IEEE80211_M_IBSS:
+		IEEE80211_DPRINTF(("%s: unexpected operating mode\n",
+		    __func__));
+		return;
+	case IEEE80211_M_HOSTAP:
+		if (ic->ic_state != IEEE80211_S_RUN) {
+			IEEE80211_DPRINTF(("%s: not running\n", __func__));
+			return;
+		}
+		switch (seq) {
+		case IEEE80211_AUTH_SHARED_REQUEST:
+			if (ni == ic->ic_bss) {
+				ni = ieee80211_alloc_node(ic, wh->i_addr2);
+				if (ni == NULL) {
+					ic->ic_stats.is_rx_nodealloc++;
+					return;
+				}
+				IEEE80211_ADDR_COPY(ni->ni_bssid,
+				    ic->ic_bss->ni_bssid);
+				ni->ni_rssi = rssi;
+				ni->ni_rstamp = rstamp;
+				ni->ni_chan = ic->ic_bss->ni_chan;
+				allocbs = 1;
+			} else
+				allocbs = 0;
+			if (ni->ni_challenge == NULL)
+				ni->ni_challenge = (u_int32_t*)malloc(
+				    IEEE80211_CHALLENGE_LEN, M_DEVBUF,
+				    M_NOWAIT);
+			if (ni->ni_challenge == NULL) {
+				IEEE80211_DPRINTF(("challenge alloc failed\n"));
+				return;
+			}
+			for (i = IEEE80211_CHALLENGE_LEN / sizeof(u_int32_t);
+			     --i >= 0; )
+				ni->ni_challenge[i] = arc4random();
+			break;
+		case IEEE80211_AUTH_SHARED_RESPONSE:
+			if (ni == ic->ic_bss) {
+				IEEE80211_DPRINTF(("%s: unknown STA\n",
+				    __func__));
+				return;
+			}
+			allocbs = 1;
+			if (ni->ni_challenge == NULL) {
+				IEEE80211_DPRINTF((
+				    "%s: no challenge recorded\n", __func__));
+				return;
+			}
+			if (memcmp(ni->ni_challenge, &challenge[2],
+			           challenge[1]) != 0) {
+				IEEE80211_DPRINTF(("%s: challenge mismatch\n",
+				    __func__));
+				return;
+			}
+			break;
+		default:
+			IEEE80211_DPRINTF(("%s: bad seq %d from %s\n",
+			    __func__, seq, ether_sprintf(wh->i_addr2)));
+			return;
+		}
+		IEEE80211_SEND_MGMT(ic, ni,
+			IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "station %s %s authenticated\n",
+			    ether_sprintf(ni->ni_macaddr),
+			    (allocbs ? "newly" : "already"));
+		break;
+
+	case IEEE80211_M_STA:
+		if (ic->ic_state != IEEE80211_S_AUTH)
+			return;
+		switch (seq) {
+		case IEEE80211_AUTH_SHARED_PASS:
+			if (ni->ni_challenge != NULL) {
+				free(ni->ni_challenge, M_DEVBUF);
+				ni->ni_challenge = NULL;
+			}
+			if (status != 0) {
+				if_printf(&ic->ic_if,
+				    "%s: auth failed (reason %d) for %s\n",
+				    __func__, status,
+				    ether_sprintf(wh->i_addr3));
+				if (ni != ic->ic_bss)
+					ni->ni_fails++;
+				ic->ic_stats.is_rx_auth_fail++;
+				return;
+			}
+			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
+			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+			break;
+		case IEEE80211_AUTH_SHARED_CHALLENGE:
+			if (ni->ni_challenge == NULL)
+				ni->ni_challenge = (u_int32_t*)malloc(
+				    challenge[1], M_DEVBUF, M_NOWAIT);
+			if (ni->ni_challenge == NULL) {
+				IEEE80211_DPRINTF((
+				    "%s: challenge alloc failed\n", __func__));
+				return;
+			}
+			memcpy(ni->ni_challenge, &challenge[2], challenge[1]);
+			break;
+		default:
+			IEEE80211_DPRINTF(("%s: bad seq %d from %s\n",
+			    __func__, seq, ether_sprintf(wh->i_addr2)));
+			return;
+		}
+		break;
+	}
+}
+
 void
 ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
 	struct ieee80211_node *ni,
@@ -904,86 +1180,19 @@
 		algo   = le16toh(*(u_int16_t *)frm);
 		seq    = le16toh(*(u_int16_t *)(frm + 2));
 		status = le16toh(*(u_int16_t *)(frm + 4));
-		if (algo != IEEE80211_AUTH_ALG_OPEN) {
-			/* TODO: shared key auth */
+
+		if (algo == IEEE80211_AUTH_ALG_SHARED)
+			ieee80211_auth_shared(ic, wh, frm + 6, efrm, ni, rssi,
+			    rstamp, seq, status);
+		else if (algo == IEEE80211_AUTH_ALG_OPEN)
+			ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq,
+			    status);
+		else {
 			IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
 				__func__, algo, ether_sprintf(wh->i_addr2)));
 			ic->ic_stats.is_rx_auth_unsupported++;
 			return;
-		}
-		switch (ic->ic_opmode) {
-		case IEEE80211_M_IBSS:
-			if (ic->ic_state != IEEE80211_S_RUN || seq != 1) {
-				IEEE80211_DPRINTF(("%s: discard auth from %s; "
-					"state %u, seq %u\n", __func__,
-					ether_sprintf(wh->i_addr2),
-					ic->ic_state, seq));
-				ic->ic_stats.is_rx_bad_auth++;
-				break;
-			}
-			ieee80211_new_state(ic, IEEE80211_S_AUTH,
-			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
-			break;
-
-		case IEEE80211_M_AHDEMO:
-			/* should not come here */
-			break;
-
-		case IEEE80211_M_HOSTAP:
-			if (ic->ic_state != IEEE80211_S_RUN || seq != 1) {
-				IEEE80211_DPRINTF(("%s: discard auth from %s; "
-					"state %u, seq %u\n", __func__,
-					ether_sprintf(wh->i_addr2),
-					ic->ic_state, seq));
-				ic->ic_stats.is_rx_bad_auth++;
-				break;
-			}
-			if (ni == ic->ic_bss) {
-				ni = ieee80211_alloc_node(ic, wh->i_addr2);
-				if (ni == NULL) {
-					ic->ic_stats.is_rx_nodealloc++;
-					return;
-				}
-				IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
-				ni->ni_rssi = rssi;
-				ni->ni_rstamp = rstamp;
-				ni->ni_chan = ic->ic_bss->ni_chan;
-				allocbs = 1;
-			} else
-				allocbs = 0;
-			IEEE80211_SEND_MGMT(ic, ni,
-				IEEE80211_FC0_SUBTYPE_AUTH, 2);
-			if (ifp->if_flags & IFF_DEBUG)
-				if_printf(ifp, "station %s %s authenticated\n",
-				    (allocbs ? "newly" : "already"),
-				    ether_sprintf(ni->ni_macaddr));
-			break;
-
-		case IEEE80211_M_STA:
-			if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) {
-				IEEE80211_DPRINTF(("%s: discard auth from %s; "
-					"state %u, seq %u\n", __func__,
-					ether_sprintf(wh->i_addr2),
-					ic->ic_state, seq));
-				ic->ic_stats.is_rx_bad_auth++;
-				break;
-			}
-			if (status != 0) {
-				if_printf(&ic->ic_if,
-				    "authentication failed (reason %d) for %s\n",
-				    status,
-				    ether_sprintf(wh->i_addr3));
-				if (ni != ic->ic_bss)
-					ni->ni_fails++;
-				ic->ic_stats.is_rx_auth_fail++;
-				return;
-			}
-			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
-			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
-			break;
-		case IEEE80211_M_MONITOR:
-			break;
-		}
+		} 
 		break;
 	}
 
@@ -1064,6 +1273,11 @@
 			ic->ic_stats.is_rx_assoc_notauth++;
 			return;
 		}
+		/* discard challenge after association */
+		if (ni->ni_challenge != NULL) {
+			free(ni->ni_challenge, M_DEVBUF);
+			ni->ni_challenge = NULL;
+		}
 		/* XXX per-node cipher suite */
 		/* XXX some stations use the privacy bit for handling APs
 		       that suport both encrypted and unencrypted traffic */
@@ -1073,6 +1287,7 @@
 		     IEEE80211_CAPINFO_PRIVACY : 0)) {
 			IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n",
 				__func__, capinfo, ether_sprintf(wh->i_addr2)));
+			IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
 			ni->ni_associd = 0;
 			IEEE80211_SEND_MGMT(ic, ni, resp,
 				IEEE80211_STATUS_CAPINFO);
@@ -1099,19 +1314,39 @@
 		ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
 		ni->ni_fhindex = ic->ic_bss->ni_fhindex;
 		if (ni->ni_associd == 0) {
-			/* XXX handle rollover at 2007 */
-			/* XXX guarantee uniqueness */
-			ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++;
-			newassoc = 1;
+			u_int16_t aid;
+
+			/*
+			 * It would be clever to search the bitmap
+			 * more efficiently, but this will do for now.
+			 */
+			for (aid = 1; aid < ic->ic_max_aid; aid++) {
+				if (!IEEE80211_AID_ISSET(aid,
+				    ic->ic_aid_bitmap))
+					break;
+			}
+
+			if (ic->ic_bss->ni_associd >= ic->ic_max_aid) {
+				IEEE80211_SEND_MGMT(ic, ni, resp,
+				    IEEE80211_REASON_ASSOC_TOOMANY);
+				/* XXX statistic */
+				return;
+			} else {
+				ni->ni_associd = aid | 0xc000;
+				IEEE80211_AID_SET(ni->ni_associd,
+				    ic->ic_aid_bitmap);
+				newassoc = 1;
+			}
 		} else
 			newassoc = 0;
 		/* XXX for 11g must turn off short slot time if long
 	           slot time sta associates */
 		IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
 		if (ifp->if_flags & IFF_DEBUG)
-			if_printf(ifp, "station %s %s associated\n",
+			if_printf(ifp, "station %s %s associated at aid %d\n",
 			    (newassoc ? "newly" : "already"),
-			    ether_sprintf(ni->ni_macaddr));
+			    ether_sprintf(ni->ni_macaddr),
+			    ni->ni_associd & ~0xc000);
 		/* give driver a chance to setup state like ni_txrate */
 		if (ic->ic_newassoc)
 			(*ic->ic_newassoc)(ic, ni, newassoc);
@@ -1142,8 +1377,10 @@
 		status = le16toh(*(u_int16_t *)frm);
 		frm += 2;
 		if (status != 0) {
-			if_printf(ifp, "association failed (reason %d) for %s\n",
-			    status, ether_sprintf(wh->i_addr3));
+			if (ifp->if_flags & IFF_DEBUG)
+				if_printf(ifp,
+				    "association failed (reason %d) for %s\n",
+				    status, ether_sprintf(wh->i_addr3));
 			if (ni != ic->ic_bss)
 				ni->ni_fails++;
 			ic->ic_stats.is_rx_auth_fail++;
@@ -1225,6 +1462,8 @@
 					if_printf(ifp, "station %s disassociated"
 					    " by peer (reason %d)\n",
 					    ether_sprintf(ni->ni_macaddr), reason);
+				IEEE80211_AID_CLR(ni->ni_associd,
+				    ic->ic_aid_bitmap);
 				ni->ni_associd = 0;
 				/* XXX node reclaimed how? */
 			}
@@ -1242,5 +1481,76 @@
 	}
 #undef ISPROBE
 }
+
+static void
+ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
+		      u_int32_t rstamp)
+{
+	struct ifnet *ifp = &ic->ic_if;
+	struct ieee80211_frame *wh;
+	struct ieee80211_node *ni;
+	struct mbuf *m;
+	u_int16_t aid;
+
+	if (ic->ic_set_tim == NULL)  /* No powersaving functionality */
+		return;
+
+	wh = mtod(m0, struct ieee80211_frame *);
+
+	if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "unknown station %s sent "
+				"power save poll\n",
+				ether_sprintf(wh->i_addr2));
+		return;
+	}
+
+	memcpy(&aid, wh->i_dur, sizeof(wh->i_dur));
+	if ((aid & 0xc000) != 0xc000) {
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "station %s sent bogus aid %x\n",
+			       ether_sprintf(wh->i_addr2), aid);
+		return;
+	}
+
+	if (aid != ni->ni_associd) {
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "station %s aid %x doesn't match pspoll "
+			       "aid %x\n",
+			       ether_sprintf(wh->i_addr2), ni->ni_associd, aid);
+		return;
+	}
+
+	/* Okay, take the first queued packet and put it out... */
+
+	IF_DEQUEUE(&ni->ni_savedq, m);
+	if (m == NULL) {
+		if (ifp->if_flags & IFF_DEBUG)
+			if_printf(ifp, "station %s sent pspoll, "
+			       "but no packets are saved\n",
+			       ether_sprintf(wh->i_addr2));
+		return;
+	}
+	wh = mtod(m, struct ieee80211_frame *);
+
+	/* 
+	 * If this is the last packet, turn off the TIM fields.
+	 * If there are more packets, set the more packets bit.
+	 */
+
+	if (_IF_QLEN(&ni->ni_savedq) == 0) {
+		if (ic->ic_set_tim) 
+			ic->ic_set_tim(ic, ni->ni_associd, 0);
+	} else {
+		wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
+	}
+
+	if (ifp->if_flags & IFF_DEBUG)
+		if_printf(ifp, "enqueued power saving packet for station %s\n",
+		       ether_sprintf(ni->ni_macaddr));
+
+	IF_ENQUEUE(&ic->ic_pwrsaveq, m);
+	(*ifp->if_start)(ifp);
+}
 #undef IEEE80211_VERIFY_LENGTH
 #undef IEEE80211_VERIFY_ELEMENT

==== //depot/projects/netperf/sys/net80211/ieee80211_node.c#16 (text+ko) ====

@@ -241,6 +241,68 @@
 	ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 }
 
+static int
+ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+        struct ifnet *ifp = &ic->ic_if;
+        u_int8_t rate;
+        int fail;
+
+	fail = 0;
+	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
+		fail |= 0x01;
+	if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
+	    ni->ni_chan != ic->ic_des_chan)
+		fail |= 0x01;
+	if (ic->ic_opmode == IEEE80211_M_IBSS) {
+		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
+			fail |= 0x02;
+	} else {
+		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
+			fail |= 0x02;
+	}
+	if (ic->ic_flags & IEEE80211_F_WEPON) {
+		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
+			fail |= 0x04;
+	} else {
+		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
+			fail |= 0x04;
+	}
+	rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
+	if (rate & IEEE80211_RATE_BASIC)
+		fail |= 0x08;
+	if (ic->ic_des_esslen != 0 &&
+	    (ni->ni_esslen != ic->ic_des_esslen ||
+	     memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
+		fail |= 0x10;
+	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
+	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
+		fail |= 0x20;
+	if (ifp->if_flags & IFF_DEBUG) {
+		printf(" %c %s", fail ? '-' : '+',
+		    ether_sprintf(ni->ni_macaddr));
+		printf(" %s%c", ether_sprintf(ni->ni_bssid),
+		    fail & 0x20 ? '!' : ' ');
+		printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan),
+			fail & 0x01 ? '!' : ' ');
+		printf(" %+4d", ni->ni_rssi);
+		printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
+		    fail & 0x08 ? '!' : ' ');
+		printf(" %4s%c",
+		    (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
+		    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
+		    "????",
+		    fail & 0x02 ? '!' : ' ');
+		printf(" %3s%c ",
+		    (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
+		    "wep" : "no",
+		    fail & 0x04 ? '!' : ' ');
+		ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
+		printf("%s\n", fail & 0x10 ? "!" : "");
+	}
+	return fail;
+}
+
 /*
  * Complete a scan of potential channels.
  */
@@ -249,7 +311,6 @@
 {
 	struct ieee80211com *ic = (void *)ifp;
 	struct ieee80211_node *ni, *nextbs, *selbs;
-	u_int8_t rate;
 	int i, fail;
 
 	ic->ic_flags &= ~IEEE80211_F_ASCAN;
@@ -315,59 +376,7 @@
 				ieee80211_free_node(ic, ni);
 			continue;
 		}
-		fail = 0;
-		if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
-			fail |= 0x01;
-		if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
-		    ni->ni_chan != ic->ic_des_chan)
-			fail |= 0x01;
-		if (ic->ic_opmode == IEEE80211_M_IBSS) {
-			if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
-				fail |= 0x02;
-		} else {
-			if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
-				fail |= 0x02;
-		}
-		if (ic->ic_flags & IEEE80211_F_WEPON) {
-			if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
-				fail |= 0x04;
-		} else {
-			if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
-				fail |= 0x04;
-		}
-		rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
-		if (rate & IEEE80211_RATE_BASIC)
-			fail |= 0x08;
-		if (ic->ic_des_esslen != 0 &&
-		    (ni->ni_esslen != ic->ic_des_esslen ||
-		     memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
-			fail |= 0x10;
-		if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
-		    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
-			fail |= 0x20;
-		if (ifp->if_flags & IFF_DEBUG) {
-			printf(" %c %s", fail ? '-' : '+',
-			    ether_sprintf(ni->ni_macaddr));
-			printf(" %s%c", ether_sprintf(ni->ni_bssid),

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200311201702.hAKH2247081905>