Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Mar 2005 01:47:27 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 73944 for review
Message-ID:  <200503280147.j2S1lRR2095549@repoman.freebsd.org>

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

Change 73944 by sam@sam_ebb on 2005/03/28 01:46:29

	o IFC
	o resurrect ff support lost in a previous merge
	o forward merge some stuff from the vap branch to simplify
		ifconfig sharing

Affected files ...

.. //depot/projects/wifi/sys/net80211/_ieee80211.h#5 edit
.. //depot/projects/wifi/sys/net80211/ieee80211.c#22 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_input.c#45 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.h#23 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_output.c#40 edit

Differences ...

==== //depot/projects/wifi/sys/net80211/_ieee80211.h#5 (text+ko) ====

@@ -59,7 +59,8 @@
 	IEEE80211_M_IBSS 	= 0,	/* IBSS (adhoc) station */
 	IEEE80211_M_AHDEMO	= 3,	/* Old lucent compatible adhoc demo */
 	IEEE80211_M_HOSTAP	= 6,	/* Software Access Point */
-	IEEE80211_M_MONITOR	= 8	/* Monitor mode */
+	IEEE80211_M_MONITOR	= 8,	/* Monitor mode */
+	IEEE80211_M_WDS		= 2	/* WDS link */
 };
 
 /*

==== //depot/projects/wifi/sys/net80211/ieee80211.c#22 (text+ko) ====

@@ -625,6 +625,7 @@
 		case IEEE80211_M_HOSTAP:
 		case IEEE80211_M_STA:
 		case IEEE80211_M_MONITOR:
+		case IEEE80211_M_WDS:
 			ic->ic_flags &= ~IEEE80211_F_IBSSON;
 			break;
 		case IEEE80211_M_IBSS:
@@ -696,6 +697,11 @@
 	case IEEE80211_M_MONITOR:
 		imr->ifm_active |= IFM_IEEE80211_MONITOR;
 		break;
+	case IEEE80211_M_WDS:
+#if 0
+		imr->ifm_active |= IFM_IEEE80211_WDS;
+#endif
+		break;
 	}
 	switch (ic->ic_curmode) {
 	case IEEE80211_MODE_11A:

==== //depot/projects/wifi/sys/net80211/ieee80211_input.c#45 (text+ko) ====

@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.33 2005/02/23 04:52:30 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.35 2005/03/16 20:39:05 sam Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -109,7 +109,11 @@
 
 static struct mbuf *ieee80211_defrag(struct ieee80211com *,
 	struct ieee80211_node *, struct mbuf *);
+static void ieee80211_deliver_data(struct ieee80211com *,
+	struct ieee80211_node *, struct mbuf *);
 static struct mbuf *ieee80211_decap(struct ieee80211com *, struct mbuf *);
+static struct mbuf *ieee80211_decap_fastframe(struct ieee80211com *,
+	struct ieee80211_node *, struct mbuf *);
 static void ieee80211_node_pwrsave(struct ieee80211_node *, int enable);
 static void ieee80211_recv_pspoll(struct ieee80211com *,
 	struct ieee80211_node *, struct mbuf *);
@@ -134,7 +138,7 @@
 	struct ieee80211_frame *wh;
 	struct ieee80211_key *key;
 	struct ether_header *eh;
-	int len, hdrsize, off;
+	int hdrsize, off;
 	u_int8_t dir, type, subtype;
 	u_int8_t *bssid;
 	u_int16_t rxseq;
@@ -237,8 +241,7 @@
 				 * discovered member of the IBSS.
 				 */
 				ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
-						type == IEEE80211_FC0_TYPE_CTL ?
-						    wh->i_addr1 : wh->i_addr2);
+						    wh->i_addr2);
 				if (ni == NULL) {
 					/* NB: stat kept for alloc failure */
 					goto err;
@@ -289,9 +292,9 @@
 			hdrsize = roundup(hdrsize, sizeof(u_int32_t));
 		if (m->m_len < hdrsize &&
 		    (m = m_pullup(m, hdrsize)) == NULL) {
-			IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
-			    wh, "data", "too short: len %u, expecting %u",
-			    m->m_pkthdr.len, hdrsize);
+			IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+			    ni->ni_macaddr, NULL,
+			    "data too short: expecting %u", hdrsize);
 			ic->ic_stats.is_rx_tooshort++;
 			goto out;		/* XXX */
 		}
@@ -493,49 +496,32 @@
 		IEEE80211_NODE_STAT(ni, rx_data);
 		IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
 
-		/* perform as a bridge within the AP */
-		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
-		    (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0) {
-			struct mbuf *m1 = NULL;
+#define	FF_LLC_SIZE	(sizeof(struct ether_header) + sizeof(struct llc))
+		if ((ni->ni_flags & IEEE80211_NODE_FF) &&
+		    m->m_pkthdr.len >= 3*FF_LLC_SIZE) {
+			struct llc *llc;
 
-			if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
-				m1 = m_copypacket(m, M_DONTWAIT);
-				if (m1 == NULL)
-					ifp->if_oerrors++;
-				else
-					m1->m_flags |= M_MCAST;
-			} else {
-				/* XXX this dups work done in ieee80211_encap */
-				/* check if destination is associated */
-				struct ieee80211_node *ni1 =
-				    ieee80211_find_node(&ic->ic_sta,
-							eh->ether_dhost);
-				if (ni1 != NULL) {
-					/* XXX check if authorized */
-					if (ni1->ni_associd != 0) {
-						m1 = m;
-						m = NULL;
-					}
-					/* XXX statistic? */
-					ieee80211_free_node(ni1);
-				}
+			/*
+			 * Check for fast-frame tunnel encapsulation.
+			 */
+			if (m->m_len < FF_LLC_SIZE &&
+			    (m = m_pullup(m, FF_LLC_SIZE)) == NULL) {
+				IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+				    ni->ni_macaddr, "fast-frame",
+				    "%s", "m_pullup(llc) failed");
+				ic->ic_stats.is_rx_tooshort++;
 			}
-			if (m1 != NULL) {
-				len = m1->m_pkthdr.len;
-				IF_ENQUEUE(&ifp->if_snd, m1);
-				if (m != NULL)
-					ifp->if_omcasts++;
-				ifp->if_obytes += len;
+			llc = (struct llc *)(mtod(m, u_int8_t *) + 
+				sizeof(struct ether_header));
+			if (llc->llc_snap.ether_type == htons(ATH_FF_ETH_TYPE)) {
+				m_adj(m, FF_LLC_SIZE);
+				m = ieee80211_decap_fastframe(ic, ni, m);
+				if (m == NULL)
+					return;
 			}
 		}
-		if (m != NULL) {
-			if (ni->ni_vlan != 0) {
-				/* attach vlan tag */
-				/* XXX goto err? */
-				VLAN_INPUT_TAG(ifp, m, ni->ni_vlan, goto out);
-			}
-			(*ifp->if_input)(ifp, m);
-		}
+#undef FF_LLC_SIZE
+		ieee80211_deliver_data(ic, ni, m);
 		return;
 
 	case IEEE80211_FC0_TYPE_MGT:
@@ -706,13 +692,72 @@
 		*(u_int16_t *) lwh->i_seq = *(u_int16_t *) wh->i_seq;
 	}
 	if (more_frag) {			/* more to come, save */
-		ni->ni_rxfragstamp = ticks;
 		ni->ni_rxfrag[0] = mfrag;
 		mfrag = NULL;
 	}
 	return mfrag;
 }
 
+static void
+ieee80211_deliver_data(struct ieee80211com *ic,
+	struct ieee80211_node *ni, struct mbuf *m)
+{
+	struct ether_header *eh = mtod(m, struct ether_header *);
+	struct ifnet *ifp = ic->ic_ifp;
+	int len;
+
+	/* perform as a bridge within the AP */
+	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+	    (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0) {
+		struct mbuf *m1 = NULL;
+
+		if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
+			m1 = m_copypacket(m, M_DONTWAIT);
+			if (m1 == NULL)
+				ifp->if_oerrors++;
+			else
+				m1->m_flags |= M_MCAST;
+		} else {
+			/* XXX this dups work done in ieee80211_encap */
+			/* check if destination is associated */
+			struct ieee80211_node *ni1 =
+			    ieee80211_find_node(&ic->ic_sta,
+						eh->ether_dhost);
+			if (ni1 != NULL) {
+				/* XXX check if authorized */
+				if (ni1->ni_associd != 0) {
+					m1 = m;
+					m = NULL;
+				}
+				/* XXX statistic? */
+				ieee80211_free_node(ni1);
+			}
+		}
+		if (m1 != NULL) {
+			len = m1->m_pkthdr.len;
+			IF_ENQUEUE(&ifp->if_snd, m1);
+			if (m != NULL)
+				ifp->if_omcasts++;
+			ifp->if_obytes += len;
+		}
+	}
+	if (m != NULL) {
+		if (ni->ni_vlan != 0) {
+			/* attach vlan tag */
+			/* XXX goto err? */
+			VLAN_INPUT_TAG(ifp, m, ni->ni_vlan, goto out);
+		}
+		(*ifp->if_input)(ifp, m);
+	}
+	return;
+  out:
+	if (m != NULL) {
+		if (ic->ic_rawbpf)
+			bpf_mtap(ic->ic_rawbpf, m);
+		m_freem(m);
+	}
+}
+
 static struct mbuf *
 ieee80211_decap(struct ieee80211com *ic, struct mbuf *m)
 {
@@ -815,6 +860,104 @@
 }
 
 /*
+ * Decap a frame encapsulated in a fast-frame.
+ */
+static struct mbuf *
+ieee80211_decap1(struct mbuf *m, int *framelen)
+{
+#define	FF_LLC_SIZE	(sizeof(struct ether_header) + sizeof(struct llc))
+	struct ether_header *eh;
+	struct llc *llc;
+
+	/*
+	 * The frame has an 802.3 header followed by an 802.2
+	 * LLC header.  The encapsulated frame length is in the
+	 * first header type field; save that and overwrite it 
+	 * with the true type field found in the second.  Then
+	 * copy the 802.3 header up to where it belongs and
+	 * adjust the mbuf contents to remove the void.
+	 */
+	if (m->m_len < FF_LLC_SIZE && (m = m_pullup(m, FF_LLC_SIZE)) == NULL)
+		return NULL;
+	eh = mtod(m, struct ether_header *);	/* 802.3 header is first */
+	llc = (struct llc *)&eh[1];		/* 802.2 header follows */
+	*framelen = ntohs(eh->ether_type)	/* encap'd frame size */
+		  + sizeof(struct ether_header) - sizeof(struct llc);
+	eh->ether_type = llc->llc_un.type_snap.ether_type;
+	ovbcopy(eh, mtod(m, u_int8_t *) + sizeof(struct llc),
+		sizeof(struct ether_header));
+	m_adj(m, sizeof(struct llc));
+	return m;
+#undef FF_LLC_SIZE
+}
+
+/*
+ * Decap the encapsulated frame pair and dispatch the first
+ * for delivery.  The second frame is returned for delivery
+ * via the normal path.
+ */
+static struct mbuf *
+ieee80211_decap_fastframe(struct ieee80211com *ic,
+	struct ieee80211_node *ni, struct mbuf *m)
+{
+#define	MS(x,f)	(((x) & f) >> f##_S)
+	u_int32_t ath;
+	struct mbuf *n;
+	int framelen;
+
+	m_copydata(m, 0, sizeof(u_int32_t), (caddr_t) &ath);
+	if (MS(ath, ATH_FF_PROTO) != ATH_FF_PROTO_L2TUNNEL) {
+		IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+		    ni->ni_macaddr, "fast-frame",
+		    "unsupport tunnel protocol, header 0x%x", ath);
+		ic->ic_stats.is_ff_badhdr++;
+		m_freem(m);
+		return NULL;
+	}
+	/* NB: skip header and alignment padding */
+	m_adj(m, roundup(sizeof(u_int32_t) - 2, 4) + 2);
+
+	ic->ic_stats.is_ff_decap++;
+
+	/*
+	 * Decap the first frame, bust it apart from the
+	 * second and deliver; then decap the second frame
+	 * and return it to the caller for normal delivery.
+	 */
+	m = ieee80211_decap1(m, &framelen);
+	if (m == NULL) {
+		IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+		    ni->ni_macaddr, "fast-frame", "%s", "first decap failed");
+		ic->ic_stats.is_ff_tooshort++;
+		return NULL;
+	}
+	n = m_split(m, framelen, M_NOWAIT);
+	if (n == NULL) {
+		IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+		    ni->ni_macaddr, "fast-frame",
+		    "%s", "unable to split encapsulated frames");
+		ic->ic_stats.is_ff_split++;
+		m_freem(m);			/* NB: must reclaim */
+		return NULL;
+	}
+	ieee80211_deliver_data(ic, ni, m);	/* 1st of pair */
+
+	/*
+	 * Decap second frame.
+	 */
+	m_adj(n, roundup2(framelen, 4) - framelen);	/* padding */
+	n = ieee80211_decap1(n, &framelen);
+	if (n == NULL) {
+		IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+		    ni->ni_macaddr, "fast-frame", "%s", "second decap failed");
+		ic->ic_stats.is_ff_tooshort++;
+	}
+	/* XXX verify framelen against mbuf contents */
+	return n;				/* 2nd delivered by caller */
+#undef MS
+}
+
+/*
  * Install received rate set information in the node's state block.
  */
 static int
@@ -864,6 +1007,7 @@
 		break;
 
 	case IEEE80211_M_AHDEMO:
+	case IEEE80211_M_WDS:
 		/* should not come here */
 		break;
 
@@ -1007,6 +1151,7 @@
 	case IEEE80211_M_MONITOR:
 	case IEEE80211_M_AHDEMO:
 	case IEEE80211_M_IBSS:
+	case IEEE80211_M_WDS:
 		IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 		    ni->ni_macaddr, "shared key auth",
 		    "bad operating mode %u", ic->ic_opmode);
@@ -1613,6 +1758,40 @@
 #undef MS
 }
 
+static int
+ieee80211_parse_athparams(struct ieee80211_node *ni, u_int8_t *frm,
+	const struct ieee80211_frame *wh)
+{
+	struct ieee80211com *ic = ni->ni_ic;
+	const struct ieee80211_ath_ie *ath;
+	u_int len = frm[1];
+	int caps;
+
+	if (len < sizeof(struct ieee80211_ath_ie)-2) {
+		IEEE80211_DISCARD_IE(ic,
+		    IEEE80211_MSG_ELEMID | IEEE80211_MSG_SUPERG,
+		    wh, "Atheros", "too short, len %u", len);
+		return -1;
+	}
+	ath = (const struct ieee80211_ath_ie *)frm;
+	caps = 0;
+	if ((ath->ath_capability & ATHEROS_CAP_TURBO_PRIME) &&
+	    (ic->ic_flags & IEEE80211_F_TURBOP))
+		caps |= IEEE80211_NODE_TURBOP;
+	if ((ath->ath_capability & ATHEROS_CAP_FAST_FRAME) &&
+	    (ic->ic_flags & IEEE80211_F_FF))
+		caps |= IEEE80211_NODE_FF;
+	if ((ni->ni_flags ^ caps) & IEEE80211_NODE_ATH) {
+		IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
+		    "[%s] ath ie: caps 0x%x defkeyix 0x%x, use 0x%x\n",
+		    ether_sprintf(ni->ni_macaddr),
+		    ath->ath_capability, LE_READ_2(ath->ath_defkeyix), caps);
+		ni->ni_flags = (ni->ni_flags &~ IEEE80211_NODE_ATH) | caps;
+		return 1;
+	} else
+		return 0;			/* NB: no change */
+}
+
 static void
 ieee80211_saveie(u_int8_t **iep, const u_int8_t *ie)
 {
@@ -1671,7 +1850,7 @@
 #define	ISREASSOC(_st)	((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
 	struct ieee80211_frame *wh;
 	u_int8_t *frm, *efrm;
-	u_int8_t *ssid, *rates, *xrates, *wpa, *wme;
+	u_int8_t *ssid, *rates, *xrates, *wpa, *wme, *ath;
 	int reassoc, resp, allocbs;
 
 	wh = mtod(m0, struct ieee80211_frame *);
@@ -1712,12 +1891,13 @@
 		 *	[tlv] extended supported rates
 		 *	[tlv] WME
 		 *	[tlv] WPA or RSN
+		 *	[tlv] Atheros capabilities
 		 */
 		IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
 		tstamp  = frm;				frm += 8;
 		bintval = le16toh(*(u_int16_t *)frm);	frm += 2;
 		capinfo = le16toh(*(u_int16_t *)frm);	frm += 2;
-		ssid = rates = xrates = country = wpa = wme = NULL;
+		ssid = rates = xrates = country = wpa = wme = ath = NULL;
 		bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
 		chan = bchan;
 		fhdwell = 0;
@@ -1777,7 +1957,8 @@
 					wpa = frm;
 				else if (iswmeparam(frm) || iswmeinfo(frm))
 					wme = frm;
-				/* XXX Atheros OUI support */
+				else if (isatherosoui(frm))
+					ath = frm;
 				break;
 			default:
 				IEEE80211_DISCARD_IE(ic, IEEE80211_MSG_ELEMID,
@@ -1870,6 +2051,8 @@
 			if (wme != NULL &&
 			    ieee80211_parse_wmeparams(ic, wme, wh) > 0)
 				ieee80211_wme_updateparams(ic);
+			if (ath != NULL)
+				ieee80211_parse_athparams(ni, ath, wh);
 			/* NB: don't need the rest of this */
 			if ((ic->ic_flags & IEEE80211_F_SCAN) == 0)
 				return;
@@ -1945,6 +2128,10 @@
 			ieee80211_saveie(&ni->ni_wme_ie, wme);
 		if (wpa != NULL)
 			ieee80211_saveie(&ni->ni_wpa_ie, wpa);
+		if (ath != NULL) {
+			ieee80211_saveie(&ni->ni_ath_ie, ath);
+			(void) ieee80211_parse_athparams(ni, ath, wh);
+		}
 		/* NB: must be after ni_chan is setup */
 		ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
 		break;
@@ -1969,8 +2156,9 @@
 		 *	[tlv] ssid
 		 *	[tlv] supported rates
 		 *	[tlv] extended supported rates
+		 *	[tlv] Atheros capabilities
 		 */
-		ssid = rates = xrates = NULL;
+		ssid = rates = xrates = ath = NULL;
 		while (frm < efrm) {
 			switch (*frm) {
 			case IEEE80211_ELEMID_SSID:
@@ -1982,20 +2170,16 @@
 			case IEEE80211_ELEMID_XRATES:
 				xrates = frm;
 				break;
+			case IEEE80211_ELEMID_VENDOR:
+				if (isatherosoui(frm))
+					ath = frm;
+				break;
 			}
 			frm += frm[1] + 2;
 		}
 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
 		IEEE80211_VERIFY_SSID(ic->ic_bss, ssid);
-		if ((ic->ic_flags & IEEE80211_F_HIDESSID) && ssid[1] == 0) {
-			IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
-			    wh, ieee80211_mgt_subtype_name[subtype >>
-				IEEE80211_FC0_SUBTYPE_SHIFT],
-			    "%s", "no ssid with ssid suppression enabled");
-			ic->ic_stats.is_rx_ssidmismatch++; /*XXX*/
-			return;
-		}
 
 		if (ni == ic->ic_bss) {
 			if (ic->ic_opmode == IEEE80211_M_IBSS) {
@@ -2018,6 +2202,10 @@
 		    "[%s] recv probe req\n", ether_sprintf(wh->i_addr2));
 		ni->ni_rssi = rssi;
 		ni->ni_rstamp = rstamp;
+		if (ath != NULL) {
+			ieee80211_saveie(&ni->ni_ath_ie, ath);
+			(void) ieee80211_parse_athparams(ni, ath, wh);
+		}
 		rate = ieee80211_setup_rates(ic, ni, rates, xrates,
 			  IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
 			| IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
@@ -2124,6 +2312,7 @@
 		 *	[tlv] supported rates
 		 *	[tlv] extended supported rates
 		 *	[tlv] WPA or RSN
+		 *	[tlv] Atheros capabilities
 		 */
 		IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
 		if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
@@ -2138,7 +2327,7 @@
 		bintval = le16toh(*(u_int16_t *)frm);	frm += 2;
 		if (reassoc)
 			frm += 6;	/* ignore current AP info */
-		ssid = rates = xrates = wpa = wme = NULL;
+		ssid = rates = xrates = wpa = wme = ath = NULL;
 		while (frm < efrm) {
 			switch (*frm) {
 			case IEEE80211_ELEMID_SSID:
@@ -2160,7 +2349,8 @@
 						wpa = frm;
 				} else if (iswmeinfo(frm))
 					wme = frm;
-				/* XXX Atheros OUI support */
+				else if (isatherosoui(frm))
+					ath = frm;
 				break;
 			}
 			frm += frm[1] + 2;
@@ -2184,6 +2374,20 @@
 			ic->ic_stats.is_rx_assoc_notauth++;
 			return;
 		}
+		/* assert right associstion security credentials */
+		if (wpa == NULL && (ic->ic_flags & IEEE80211_F_WPA)) {
+			IEEE80211_DPRINTF(ic,
+			    IEEE80211_MSG_ASSOC | IEEE80211_MSG_WPA,
+			    "[%s] no WPA/RSN IE in association request\n",
+			    ether_sprintf(wh->i_addr2));
+			IEEE80211_SEND_MGMT(ic, ni,
+			    IEEE80211_FC0_SUBTYPE_DEAUTH,
+			    IEEE80211_REASON_RSN_REQUIRED);
+			ieee80211_node_leave(ic, ni);
+			/* XXX distinguish WPA/RSN? */
+			ic->ic_stats.is_rx_assoc_badwpaie++;
+			return;	
+		}
 		if (wpa != NULL) {
 			/*
 			 * Parse WPA information element.  Note that
@@ -2287,6 +2491,23 @@
 			ni->ni_wme_ie = NULL;
 			ni->ni_flags &= ~IEEE80211_NODE_QOS;
 		}
+		if (ath != NULL) {
+			/* 
+			 * Record ATH parameters for station, mark
+			 * node with appropriate capabilities, and
+			 * record the information element for
+			 * applications that require it.
+			 */
+			ieee80211_saveie(&ni->ni_ath_ie, ath);
+			(void) ieee80211_parse_athparams(ni, ath, wh);
+		} else if (ni->ni_ath_ie != NULL) {
+			/*
+			 * Flush any state from a previous association.
+			 */
+			FREE(ni->ni_ath_ie, M_DEVBUF);
+			ni->ni_ath_ie = NULL;
+			ni->ni_flags &= ~IEEE80211_NODE_ATH;
+		}
 		ieee80211_node_join(ic, ni, resp);
 		break;
 	}
@@ -2330,7 +2551,7 @@
 		associd = le16toh(*(u_int16_t *)frm);
 		frm += 2;
 
-		rates = xrates = wpa = wme = NULL;
+		rates = xrates = wme = NULL;
 		while (frm < efrm) {
 			switch (*frm) {
 			case IEEE80211_ELEMID_RATES:
@@ -2398,13 +2619,15 @@
 		else
 			ic->ic_flags &= ~IEEE80211_F_USEPROT;
 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
-		    "[%s] %sassoc success: %s preamble, %s slot time%s%s\n",
+		    "[%s] %sassoc success: %s preamble, %s slot time%s%s%s%s\n",
 		    ether_sprintf(wh->i_addr2),
 		    ISREASSOC(subtype) ? "re" : "",
 		    ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
 		    ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
 		    ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
-		    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : ""
+		    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
+		    ni->ni_flags & IEEE80211_NODE_FF ? ", fast-frames" : "",
+		    ni->ni_flags & IEEE80211_NODE_TURBOP ? ", turbo'" : ""
 		);
 		ieee80211_new_state(ic, IEEE80211_S_RUN, subtype);
 		break;

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.h#23 (text+ko) ====

@@ -360,6 +360,7 @@
 };
 #define	SIOCS80211		 _IOW('i', 234, struct ieee80211req)
 #define	SIOCG80211		_IOWR('i', 235, struct ieee80211req)
+#define	SIOCG80211STATS		_IOWR('i', 236, struct ifreq)
 
 #define IEEE80211_IOC_SSID		1
 #define IEEE80211_IOC_NUMSSIDS		2
@@ -453,7 +454,10 @@
 	/* variable length SSID followed by IE data */
 };
 
-#define	SIOCG80211STATS		_IOWR('i', 236, struct ifreq)
+struct ieee80211_clone_params {
+	char	icp_parent[IFNAMSIZ];		/* parent device */
+	int	icp_opmode;			/* operating mode */
+};
 #endif /* __FreeBSD__ */
 
 #endif /* _NET80211_IEEE80211_IOCTL_H_ */

==== //depot/projects/wifi/sys/net80211/ieee80211_output.c#40 (text+ko) ====

@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.20 2005/02/10 17:00:48 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.21 2005/03/16 20:42:00 sam Exp $");
 
 #include "opt_inet.h"
 
@@ -233,7 +233,7 @@
 	v_wme_ac = 0;
 	if (ni->ni_vlan != 0) {
 		 struct m_tag *mtag = VLAN_OUTPUT_TAG(ic->ic_ifp, m);
-		 if (mtag != NULL) {
+		 if (mtag == NULL) {
 			IEEE80211_NODE_STAT(ni, tx_novlantag);
 			return 1;
 		}
@@ -593,6 +593,7 @@
 		IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
 		break;
 	case IEEE80211_M_MONITOR:
+	case IEEE80211_M_WDS:
 		goto bad;
 	}
 	if (addqos) {



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