Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Feb 2008 17:48:39 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 135978 for review
Message-ID:  <200802221748.m1MHmdJ8034520@repoman.freebsd.org>

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

Change 135978 by sam@sam_ebb on 2008/02/22 17:47:37

	Apply long-overdue overhaul of probe response handling in ap mode:
	o eliminate use of temporary node to send probe response; use the
	  bss node for a reference and pass the destination mac address
	  explicitly (instead of taking it from the node)
	o drop atheros ie processing; not clear it was ever useful (though
	  possibly it was used to propagate the default wep key for shared
	  key auth)
	o don't avg rssi for received probe request frames
	o don't do rate set negotiation; it was unnecessary
	o check for 11b client better (I think); could still be optimized
	  and should probably move to common code so it can be shared between
	  ap and adhoc code
	o add ieee80211_send_proberesp to send a probe response frame; need
	  to think about best way to integrate this into the tx mgt path
	  so drivers can override

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_adhoc.c#7 edit
.. //depot/projects/vap/sys/net80211/ieee80211_hostap.c#17 edit
.. //depot/projects/vap/sys/net80211/ieee80211_output.c#35 edit
.. //depot/projects/vap/sys/net80211/ieee80211_proto.h#14 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_adhoc.c#7 (text+ko) ====

@@ -641,6 +641,23 @@
 #undef SEQ_LEQ
 }
 
+static int
+is11bclient(const uint8_t *rates, const uint8_t *xrates)
+{
+	static const uint32_t brates = (1<<2*1)|(1<<2*2)|(1<<11)|(1<<2*11);
+	int i;
+
+	/* NB: the 11b clients we care about will not have xrates */
+	if (xrates != NULL || rates == NULL)
+		return 0;
+	for (i = 0; i < rates[1]; i++) {
+		int r = rates[2+i] & IEEE80211_RATE_VAL;
+		if (r > 2*11 || ((1<<r) & brates) == 0)
+			return 0;
+	}
+	return 1;
+}
+
 static void
 adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
 	int subtype, int rssi, int noise, uint32_t rstamp)
@@ -649,9 +666,7 @@
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_frame *wh;
 	uint8_t *frm, *efrm, *sfrm;
-	uint8_t *ssid, *rates, *xrates, *ath;
-	int allocbs;
-	uint8_t rate;
+	uint8_t *ssid, *rates, *xrates;
 
 	wh = mtod(m0, struct ieee80211_frame *);
 	frm = (uint8_t *)&wh[1];
@@ -740,7 +755,7 @@
 		 *	[tlv] extended supported rates
 		 *	[tlv] Atheros capabilities
 		 */
-		ssid = rates = xrates = ath = NULL;
+		ssid = rates = xrates = NULL;
 		sfrm = frm;
 		while (efrm - frm > 1) {
 			IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
@@ -754,10 +769,6 @@
 			case IEEE80211_ELEMID_XRATES:
 				xrates = frm;
 				break;
-			case IEEE80211_ELEMID_VENDOR:
-				if (isatherosoui(frm))
-					ath = frm;
-				break;
 			}
 			frm += frm[1] + 2;
 		}
@@ -775,62 +786,17 @@
 			return;
 		}
 
-		if (ni == vap->iv_bss) {
-			if (IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr))
-				;
-			else {
-				/*
-				 * XXX Cannot tell if the sender is operating
-				 * in ibss mode.  But we need a new node to
-				 * send the response so blindly add them to the
-				 * neighbor table.
-				 */
-				ni = ieee80211_fakeup_adhoc_node(vap,
-					wh->i_addr2);
-			}
-			if (ni == NULL)
-				return;
-			allocbs = 1;
-		} else
-			allocbs = 0;
 		/* XXX find a better class or define it's own */
 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
 		    "%s", "recv probe req");
-		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
-		ni->ni_rstamp = rstamp;
-		rate = ieee80211_setup_rates(ni, rates, xrates,
-			  IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
-			| IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
-		if (rate & IEEE80211_RATE_BASIC) {
-			IEEE80211_DISCARD(vap, IEEE80211_MSG_XRATE,
-			    wh, NULL, "%s", "recv'd rate set invalid");
-		} else {
-			/*
-			 * Some legacy 11b clients cannot hack a complete
-			 * probe response frame.  When the request includes
-			 * only a bare-bones rate set, communicate this to
-			 * the transmit side through the "arg parameters".
-			 *
-			 * NB: using the max rate is a bit of a hack.
-			 */
-			IEEE80211_SEND_MGMT(ni,
-			    IEEE80211_FC0_SUBTYPE_PROBE_RESP,
-			    rate < 48 ? IEEE80211_SEND_LEGACY_11B : 0);
-		}
-		if (allocbs) {
-			/*
-			 * Temporary node created just to send a
-			 * response, reclaim immediately.
-			 */
-			ieee80211_free_node(ni);
-		} else if (ath != NULL) {
-			if (ieee80211_ies_init(&ni->ni_ies, sfrm, efrm-sfrm)) {
-				ieee80211_ies_setie(ni->ni_ies, ath_ie,
-				    ath - sfrm);
-				ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
-			} else
-				ni->ni_ath_flags = 0;
-		}
+		/*
+		 * Some legacy 11b clients cannot hack a complete
+		 * probe response frame.  When the request includes
+		 * only a bare-bones rate set, communicate this to
+		 * the transmit side.
+		 */
+		ieee80211_send_proberesp(vap, wh->i_addr2,
+		    is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0);
 		break;
 
 	case IEEE80211_FC0_SUBTYPE_ACTION: {

==== //depot/projects/vap/sys/net80211/ieee80211_hostap.c#17 (text+ko) ====

@@ -1629,6 +1629,23 @@
 	    IEEE80211_HTINFO_OPMODE_MIXED;
 }
 
+static int
+is11bclient(const uint8_t *rates, const uint8_t *xrates)
+{
+	static const uint32_t brates = (1<<2*1)|(1<<2*2)|(1<<11)|(1<<2*11);
+	int i;
+
+	/* NB: the 11b clients we care about will not have xrates */
+	if (xrates != NULL || rates == NULL)
+		return 0;
+	for (i = 0; i < rates[1]; i++) {
+		int r = rates[2+i] & IEEE80211_RATE_VAL;
+		if (r > 2*11 || ((1<<r) & brates) == 0)
+			return 0;
+	}
+	return 1;
+}
+
 static void
 hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
 	int subtype, int rssi, int noise, uint32_t rstamp)
@@ -1638,7 +1655,7 @@
 	struct ieee80211_frame *wh;
 	uint8_t *frm, *efrm, *sfrm;
 	uint8_t *ssid, *rates, *xrates, *wpa, *rsn, *wme, *ath, *htcap;
-	int reassoc, resp, allocbs;
+	int reassoc, resp;
 	uint8_t rate;
 
 	wh = mtod(m0, struct ieee80211_frame *);
@@ -1750,15 +1767,13 @@
 			vap->iv_stats.is_rx_mgtdiscard++;
 			return;
 		}
-
 		/*
 		 * prreq frame format
 		 *	[tlv] ssid
 		 *	[tlv] supported rates
 		 *	[tlv] extended supported rates
-		 *	[tlv] Atheros capabilities
 		 */
-		ssid = rates = xrates = ath = NULL;
+		ssid = rates = xrates = NULL;
 		sfrm = frm;
 		while (efrm - frm > 1) {
 			IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
@@ -1772,10 +1787,6 @@
 			case IEEE80211_ELEMID_XRATES:
 				xrates = frm;
 				break;
-			case IEEE80211_ELEMID_VENDOR:
-				if (isatherosoui(frm))
-					ath = frm;
-				break;
 			}
 			frm += frm[1] + 2;
 		}
@@ -1793,51 +1804,17 @@
 			return;
 		}
 
-		if (ni == vap->iv_bss) {
-			ni = ieee80211_tmp_node(vap, wh->i_addr2);
-			if (ni == NULL)
-				return;
-			allocbs = 1;
-		} else
-			allocbs = 0;
 		/* XXX find a better class or define it's own */
 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
 		    "%s", "recv probe req");
-		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
-		ni->ni_rstamp = rstamp;
-		rate = ieee80211_setup_rates(ni, rates, xrates,
-			  IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
-			| IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
-		if (rate & IEEE80211_RATE_BASIC) {
-			IEEE80211_DISCARD(vap, IEEE80211_MSG_XRATE,
-			    wh, NULL, "%s", "recv'd rate set invalid");
-		} else {
-			/*
-			 * Some legacy 11b clients cannot hack a complete
-			 * probe response frame.  When the request includes
-			 * only a bare-bones rate set, communicate this to
-			 * the transmit side through the "arg parameters".
-			 *
-			 * NB: using the max rate is a bit of a hack.
-			 */
-			IEEE80211_SEND_MGMT(ni,
-			    IEEE80211_FC0_SUBTYPE_PROBE_RESP,
-			    rate < 48 ? IEEE80211_SEND_LEGACY_11B : 0);
-		}
-		if (allocbs) {
-			/*
-			 * Temporary node created just to send a
-			 * response, reclaim immediately.
-			 */
-			ieee80211_free_node(ni);
-		} else if (ath != NULL) {
-			if (ieee80211_ies_init(&ni->ni_ies, sfrm, efrm-sfrm)) {
-				ieee80211_ies_setie(ni->ni_ies, ath_ie,
-				    ath - sfrm);
-				ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
-			} else
-				ni->ni_ath_flags = 0;
-		}
+		/*
+		 * Some legacy 11b clients cannot hack a complete
+		 * probe response frame.  When the request includes
+		 * only a bare-bones rate set, communicate this to
+		 * the transmit side.
+		 */
+		ieee80211_send_proberesp(vap, wh->i_addr2,
+		    is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0);
 		break;
 
 	case IEEE80211_FC0_SUBTYPE_AUTH: {

==== //depot/projects/vap/sys/net80211/ieee80211_output.c#35 (text+ko) ====

@@ -1721,7 +1721,6 @@
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_node *bss = vap->iv_bss;
-	const struct ieee80211_rateset *rs;
 	struct mbuf *m;
 	uint8_t *frm;
 	uint16_t capinfo;
@@ -1742,139 +1741,7 @@
 	ieee80211_ref_node(ni);
 
 	switch (type) {
-	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
-		/*
-		 * probe response frame format
-		 *	[8] time stamp
-		 *	[2] beacon interval
-		 *	[2] cabability information
-		 *	[tlv] ssid
-		 *	[tlv] supported rates
-		 *	[tlv] parameter set (FH/DS)
-		 *	[tlv] parameter set (IBSS)
-		 *	[tlv] country (optional)
-		 *	[tlv] RSN (optional)
-		 *	[3] power control (optional)
-		 *	[5] channel switch announcement (CSA) (optional)
-		 *	[tlv] extended rate phy (ERP)
-		 *	[tlv] extended supported rates
-		 *	[tlv] HT capabilities
-		 *	[tlv] HT information
-		 *	[tlv] WPA (optional)
-		 *	[tlv] WME (optional)
-		 *	[tlv] Vendor OUI HT capabilities (optional)
-		 *	[tlv] Vendor OUI HT information (optional)
-		 *	[tlv] Atheros capabilities
-		 *	[tlv] AppIE's (optional)
-		 */
-		m = ieee80211_getmgtframe(&frm,
-			 ic->ic_headroom + sizeof(struct ieee80211_frame),
-			 8
-		       + sizeof(uint16_t)
-		       + sizeof(uint16_t)
-		       + 2 + IEEE80211_NWID_LEN
-		       + 2 + IEEE80211_RATE_SIZE
-		       + 7	/* max(7,3) */
-		       + sizeof(struct ieee80211_country_ie)
-		       + sizeof(struct ieee80211_ie_wpa)
-		       + 3
-		       + sizeof(struct ieee80211_csa_ie)
-		       + 3
-		       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
-		       + sizeof(struct ieee80211_ie_htcap)
-		       + sizeof(struct ieee80211_ie_htinfo)
-		       + sizeof(struct ieee80211_ie_wpa)
-		       + sizeof(struct ieee80211_wme_param)
-		       + 4 + sizeof(struct ieee80211_ie_htcap)
-		       + 4 + sizeof(struct ieee80211_ie_htinfo)
-		       + sizeof(struct ieee80211_ath_ie)
-		       + (vap->iv_appie_proberesp != NULL ?
-				vap->iv_appie_proberesp->ie_len : 0)
-		);
-		if (m == NULL)
-			senderr(ENOMEM, is_tx_nobuf);
-
-		memset(frm, 0, 8);	/* timestamp should be filled later */
-		frm += 8;
-		*(uint16_t *)frm = htole16(bss->ni_intval);
-		frm += 2;
-		capinfo = getcapinfo(vap, bss->ni_chan);
-		*(uint16_t *)frm = htole16(capinfo);
-		frm += 2;
-
-		frm = ieee80211_add_ssid(frm, bss->ni_essid, bss->ni_esslen);
-		rs = ieee80211_get_suprates(ic, bss->ni_chan);
-		frm = ieee80211_add_rates(frm, rs);
-
-		if (IEEE80211_IS_CHAN_FHSS(bss->ni_chan)) {
-                        *frm++ = IEEE80211_ELEMID_FHPARMS;
-                        *frm++ = 5;
-                        *frm++ = ni->ni_fhdwell & 0x00ff;
-                        *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff;
-                        *frm++ = IEEE80211_FH_CHANSET(
-			    ieee80211_chan2ieee(ic, bss->ni_chan));
-                        *frm++ = IEEE80211_FH_CHANPAT(
-			    ieee80211_chan2ieee(ic, bss->ni_chan));
-                        *frm++ = ni->ni_fhindex;
-		} else {
-			*frm++ = IEEE80211_ELEMID_DSPARMS;
-			*frm++ = 1;
-			*frm++ = ieee80211_chan2ieee(ic, bss->ni_chan);
-		}
 
-		if (vap->iv_opmode == IEEE80211_M_IBSS) {
-			*frm++ = IEEE80211_ELEMID_IBSSPARMS;
-			*frm++ = 2;
-			*frm++ = 0; *frm++ = 0;		/* TODO: ATIM window */
-		}
-		if (vap->iv_flags & IEEE80211_F_DOTH)
-			frm = ieee80211_add_countryie(frm, ic);
-		if (vap->iv_flags & IEEE80211_F_WPA2) {
-			if (vap->iv_rsn_ie != NULL)
-				frm = add_ie(frm, vap->iv_rsn_ie);
-			/* XXX else complain? */
-		}
-		if (vap->iv_flags & IEEE80211_F_DOTH) {
-			if (IEEE80211_IS_CHAN_5GHZ(bss->ni_chan))
-				frm = ieee80211_add_powerconstraint(frm, vap);
-			if (ic->ic_flags & IEEE80211_F_CSAPENDING)
-				frm = ieee80211_add_csa(frm, vap);
-		}
-		if (IEEE80211_IS_CHAN_ANYG(bss->ni_chan))
-			frm = ieee80211_add_erp(frm, ic);
-		frm = ieee80211_add_xrates(frm, rs);
-		/*
-		 * NB: legacy 11b clients do not get certain ie's.
-		 *     The caller identifies such clients by passing
-		 *     a token in arg to us.  Could expand this to be
-		 *     any legacy client for stuff like HT ie's.
-		 */
-		if (IEEE80211_IS_CHAN_HT(bss->ni_chan) &&
-		    arg != IEEE80211_SEND_LEGACY_11B) {
-			frm = ieee80211_add_htcap(frm, bss);
-			frm = ieee80211_add_htinfo(frm, bss);
-		}
-		if (vap->iv_flags & IEEE80211_F_WPA1) {
-			if (vap->iv_wpa_ie != NULL)
-				frm = add_ie(frm, vap->iv_wpa_ie);
-			/* XXX else complain? */
-		}
-		if (vap->iv_flags & IEEE80211_F_WME)
-			frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
-		if (IEEE80211_IS_CHAN_HT(bss->ni_chan) &&
-		    (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) &&
-		    arg != IEEE80211_SEND_LEGACY_11B) {
-			frm = ieee80211_add_htcap_vendor(frm, bss);
-			frm = ieee80211_add_htinfo_vendor(frm, bss);
-		}
-		if (ni->ni_ies.ath_ie != NULL)
-			frm = ieee80211_add_ath(frm, ni->ni_ath_flags,
-				ni->ni_ath_defkeyix);
-		if (vap->iv_appie_proberesp != NULL)
-			frm = add_appie(frm, vap->iv_appie_proberesp);
-		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
-		break;
-
 	case IEEE80211_FC0_SUBTYPE_AUTH:
 		status = arg >> 16;
 		arg &= 0xffff;
@@ -2169,6 +2036,195 @@
 #undef HTFLAGS
 }
 
+/*
+ * Send a probe response frame to the specified mac address.
+ * This does not go through the normal mgt frame api so we
+ * can specify the destination address and re-use the bss node
+ * for the sta reference.
+ */
+int
+ieee80211_send_proberesp(struct ieee80211vap *vap,
+	const uint8_t da[IEEE80211_ADDR_LEN], int legacy)
+{
+	struct ieee80211_node *bss = vap->iv_bss;
+	struct ieee80211com *ic = vap->iv_ic;
+	struct ieee80211_frame *wh;
+	const struct ieee80211_rateset *rs;
+	struct mbuf *m;
+	uint16_t capinfo;
+	uint8_t *frm;
+
+	if (vap->iv_state == IEEE80211_S_CAC) {
+		IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, bss,
+		    "block %s frame in CAC state", "probe response");
+		vap->iv_stats.is_tx_badstate++;
+		return EIO;		/* XXX */
+	}
+
+	/*
+	 * Hold a reference on the node so it doesn't go away until after
+	 * the xmit is complete all the way in the driver.  On error we
+	 * will remove our reference.
+	 */
+	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+		"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
+		__func__, __LINE__,
+		bss, ether_sprintf(bss->ni_macaddr),
+		ieee80211_node_refcnt(bss)+1);
+	ieee80211_ref_node(bss);
+
+	/*
+	 * probe response frame format
+	 *	[8] time stamp
+	 *	[2] beacon interval
+	 *	[2] cabability information
+	 *	[tlv] ssid
+	 *	[tlv] supported rates
+	 *	[tlv] parameter set (FH/DS)
+	 *	[tlv] parameter set (IBSS)
+	 *	[tlv] country (optional)
+	 *	[tlv] RSN (optional)
+	 *	[3] power control (optional)
+	 *	[5] channel switch announcement (CSA) (optional)
+	 *	[tlv] extended rate phy (ERP)
+	 *	[tlv] extended supported rates
+	 *	[tlv] HT capabilities
+	 *	[tlv] HT information
+	 *	[tlv] WPA (optional)
+	 *	[tlv] WME (optional)
+	 *	[tlv] Vendor OUI HT capabilities (optional)
+	 *	[tlv] Vendor OUI HT information (optional)
+	 *	[tlv] Atheros capabilities
+	 *	[tlv] AppIE's (optional)
+	 */
+	m = ieee80211_getmgtframe(&frm,
+		 ic->ic_headroom + sizeof(struct ieee80211_frame),
+		 8
+	       + sizeof(uint16_t)
+	       + sizeof(uint16_t)
+	       + 2 + IEEE80211_NWID_LEN
+	       + 2 + IEEE80211_RATE_SIZE
+	       + 7	/* max(7,3) */
+	       + sizeof(struct ieee80211_country_ie)
+	       + sizeof(struct ieee80211_ie_wpa)
+	       + 3
+	       + sizeof(struct ieee80211_csa_ie)
+	       + 3
+	       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
+	       + sizeof(struct ieee80211_ie_htcap)
+	       + sizeof(struct ieee80211_ie_htinfo)
+	       + sizeof(struct ieee80211_ie_wpa)
+	       + sizeof(struct ieee80211_wme_param)
+	       + 4 + sizeof(struct ieee80211_ie_htcap)
+	       + 4 + sizeof(struct ieee80211_ie_htinfo)
+	       + sizeof(struct ieee80211_ath_ie)
+	       + (vap->iv_appie_proberesp != NULL ?
+			vap->iv_appie_proberesp->ie_len : 0)
+	);
+	if (m == NULL) {
+		vap->iv_stats.is_tx_nobuf++;
+		ieee80211_free_node(bss);
+		return ENOMEM;
+	}
+
+	memset(frm, 0, 8);	/* timestamp should be filled later */
+	frm += 8;
+	*(uint16_t *)frm = htole16(bss->ni_intval);
+	frm += 2;
+	capinfo = getcapinfo(vap, bss->ni_chan);
+	*(uint16_t *)frm = htole16(capinfo);
+	frm += 2;
+
+	frm = ieee80211_add_ssid(frm, bss->ni_essid, bss->ni_esslen);
+	rs = ieee80211_get_suprates(ic, bss->ni_chan);
+	frm = ieee80211_add_rates(frm, rs);
+
+	if (IEEE80211_IS_CHAN_FHSS(bss->ni_chan)) {
+		*frm++ = IEEE80211_ELEMID_FHPARMS;
+		*frm++ = 5;
+		*frm++ = bss->ni_fhdwell & 0x00ff;
+		*frm++ = (bss->ni_fhdwell >> 8) & 0x00ff;
+		*frm++ = IEEE80211_FH_CHANSET(
+		    ieee80211_chan2ieee(ic, bss->ni_chan));
+		*frm++ = IEEE80211_FH_CHANPAT(
+		    ieee80211_chan2ieee(ic, bss->ni_chan));
+		*frm++ = bss->ni_fhindex;
+	} else {
+		*frm++ = IEEE80211_ELEMID_DSPARMS;
+		*frm++ = 1;
+		*frm++ = ieee80211_chan2ieee(ic, bss->ni_chan);
+	}
+
+	if (vap->iv_opmode == IEEE80211_M_IBSS) {
+		*frm++ = IEEE80211_ELEMID_IBSSPARMS;
+		*frm++ = 2;
+		*frm++ = 0; *frm++ = 0;		/* TODO: ATIM window */
+	}
+	if (vap->iv_flags & IEEE80211_F_DOTH)
+		frm = ieee80211_add_countryie(frm, ic);
+	if (vap->iv_flags & IEEE80211_F_WPA2) {
+		if (vap->iv_rsn_ie != NULL)
+			frm = add_ie(frm, vap->iv_rsn_ie);
+		/* XXX else complain? */
+	}
+	if (vap->iv_flags & IEEE80211_F_DOTH) {
+		if (IEEE80211_IS_CHAN_5GHZ(bss->ni_chan))
+			frm = ieee80211_add_powerconstraint(frm, vap);
+		if (ic->ic_flags & IEEE80211_F_CSAPENDING)
+			frm = ieee80211_add_csa(frm, vap);
+	}
+	if (IEEE80211_IS_CHAN_ANYG(bss->ni_chan))
+		frm = ieee80211_add_erp(frm, ic);
+	frm = ieee80211_add_xrates(frm, rs);
+	/*
+	 * NB: legacy 11b clients do not get certain ie's.
+	 *     The caller identifies such clients by passing
+	 *     a token in legacy to us.  Could expand this to be
+	 *     any legacy client for stuff like HT ie's.
+	 */
+	if (IEEE80211_IS_CHAN_HT(bss->ni_chan) &&
+	    legacy != IEEE80211_SEND_LEGACY_11B) {
+		frm = ieee80211_add_htcap(frm, bss);
+		frm = ieee80211_add_htinfo(frm, bss);
+	}
+	if (vap->iv_flags & IEEE80211_F_WPA1) {
+		if (vap->iv_wpa_ie != NULL)
+			frm = add_ie(frm, vap->iv_wpa_ie);
+		/* XXX else complain? */
+	}
+	if (vap->iv_flags & IEEE80211_F_WME)
+		frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
+	if (IEEE80211_IS_CHAN_HT(bss->ni_chan) &&
+	    (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) &&
+	    legacy != IEEE80211_SEND_LEGACY_11B) {
+		frm = ieee80211_add_htcap_vendor(frm, bss);
+		frm = ieee80211_add_htinfo_vendor(frm, bss);
+	}
+	if (bss->ni_ies.ath_ie != NULL && legacy != IEEE80211_SEND_LEGACY_11B)
+		frm = ieee80211_add_ath(frm, bss->ni_ath_flags,
+			bss->ni_ath_defkeyix);
+	if (vap->iv_appie_proberesp != NULL)
+		frm = add_appie(frm, vap->iv_appie_proberesp);
+	m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
+
+	M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
+	KASSERT(m != NULL, ("no room for header"));
+
+	wh = mtod(m, struct ieee80211_frame *);
+	ieee80211_send_setup(bss, wh,
+		IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP,
+		vap->iv_myaddr, da, bss->ni_bssid);
+	/* XXX power management? */
+
+	IEEE80211_NODE_STAT(bss, tx_mgmt);
+
+	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
+	    wh->i_addr1, "send probe resp on channel %u",
+	    ieee80211_chan2ieee(ic, ic->ic_curchan));
+
+	return ic->ic_raw_xmit(bss, m, NULL);
+}
+
 static void
 ieee80211_tx_mgt_timeout(void *arg)
 {

==== //depot/projects/vap/sys/net80211/ieee80211_proto.h#14 (text+ko) ====

@@ -89,6 +89,8 @@
 		const uint8_t da[IEEE80211_ADDR_LEN],
 		const uint8_t bssid[IEEE80211_ADDR_LEN],
 		const uint8_t *ssid, size_t ssidlen);
+int	ieee80211_send_proberesp(struct ieee80211vap *,
+		const uint8_t da[IEEE80211_ADDR_LEN], int);
 struct mbuf *ieee80211_encap(struct ieee80211_node *, struct mbuf *);
 
 void	ieee80211_reset_erp(struct ieee80211com *);



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