PERFORCE change 135978 for review
Sam Leffler
sam at FreeBSD.org
Fri Feb 22 17:48:40 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=135978
Change 135978 by sam at 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 *);
More information about the p4-projects
mailing list