net80211: split up ieee80211_probereq()
Factor out ieee80211_probereq_ie() and ieee80211_probereq_ie_len() and make the length dynamic rather than static max. The latter is needed as our current fixed length was longer than some "hw scan", e.g. that of ath10k, will take. This way we can pass what we have. Should this not be sufficient in the future we might have to deal with filtering and much more error handling. This also removes a duplicate calculation for ieee80211_ie_wpa [1]. Repoprted-by: Martin Husemann <martin NetBSD.org> [1] Sponsored-by: Rubicon Communications, LLC ("Netgate") Sponsored-by: The FreeBSD Foundation (update for alloc) Reviewed-by: adrian, martin NetBSD.org (earlier version) Reviewed-by: philip MFC-after: 2 weeks Differential Revision: https://reviews.freebsd.org/D26545
This commit is contained in:
parent
0c7b75f128
commit
c338cf2c6d
@ -2414,80 +2414,76 @@ ieee80211_add_qos(uint8_t *frm, const struct ieee80211_node *ni)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a probe request frame with the specified ssid
|
* ieee80211_send_probereq(): send a probe request frame with the specified ssid
|
||||||
* and any optional information element data.
|
* and any optional information element data; some helper functions as FW based
|
||||||
|
* HW scans need some of that information passed too.
|
||||||
*/
|
*/
|
||||||
int
|
static uint32_t
|
||||||
ieee80211_send_probereq(struct ieee80211_node *ni,
|
ieee80211_probereq_ie_len(struct ieee80211vap *vap, struct ieee80211com *ic)
|
||||||
const uint8_t sa[IEEE80211_ADDR_LEN],
|
|
||||||
const uint8_t da[IEEE80211_ADDR_LEN],
|
|
||||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
|
||||||
const uint8_t *ssid, size_t ssidlen)
|
|
||||||
{
|
{
|
||||||
struct ieee80211vap *vap = ni->ni_vap;
|
|
||||||
struct ieee80211com *ic = ni->ni_ic;
|
|
||||||
struct ieee80211_node *bss;
|
|
||||||
const struct ieee80211_txparam *tp;
|
|
||||||
struct ieee80211_bpf_params params;
|
|
||||||
const struct ieee80211_rateset *rs;
|
const struct ieee80211_rateset *rs;
|
||||||
struct mbuf *m;
|
|
||||||
uint8_t *frm;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
bss = ieee80211_ref_node(vap->iv_bss);
|
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
|
||||||
|
|
||||||
if (vap->iv_state == IEEE80211_S_CAC) {
|
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
|
|
||||||
"block %s frame in CAC state", "probe request");
|
|
||||||
vap->iv_stats.is_tx_badstate++;
|
|
||||||
ieee80211_free_node(bss);
|
|
||||||
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__,
|
|
||||||
ni, ether_sprintf(ni->ni_macaddr),
|
|
||||||
ieee80211_node_refcnt(ni)+1);
|
|
||||||
ieee80211_ref_node(ni);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prreq frame format
|
* prreq frame format
|
||||||
* [tlv] ssid
|
* [tlv] ssid
|
||||||
* [tlv] supported rates
|
* [tlv] supported rates
|
||||||
* [tlv] RSN (optional)
|
* [tlv] RSN (optional)
|
||||||
* [tlv] extended supported rates
|
* [tlv] extended supported rates (if needed)
|
||||||
* [tlv] HT cap (optional)
|
* [tlv] HT cap (optional)
|
||||||
* [tlv] VHT cap (optional)
|
* [tlv] VHT cap (optional)
|
||||||
* [tlv] WPA (optional)
|
* [tlv] WPA (optional)
|
||||||
* [tlv] user-specified ie's
|
* [tlv] user-specified ie's
|
||||||
*/
|
*/
|
||||||
m = ieee80211_getmgtframe(&frm,
|
return ( 2 + IEEE80211_NWID_LEN
|
||||||
ic->ic_headroom + sizeof(struct ieee80211_frame),
|
|
||||||
2 + IEEE80211_NWID_LEN
|
|
||||||
+ 2 + IEEE80211_RATE_SIZE
|
+ 2 + IEEE80211_RATE_SIZE
|
||||||
+ sizeof(struct ieee80211_ie_htcap)
|
+ ((vap->iv_flags & IEEE80211_F_WPA2 && vap->iv_rsn_ie != NULL) ?
|
||||||
+ sizeof(struct ieee80211_ie_vhtcap)
|
vap->iv_rsn_ie[1] : 0)
|
||||||
|
+ ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
|
||||||
|
2 + (rs->rs_nrates - IEEE80211_RATE_SIZE) : 0)
|
||||||
|
+ (((vap->iv_opmode == IEEE80211_M_IBSS) &&
|
||||||
|
(vap->iv_flags_ht & IEEE80211_FHT_HT)) ?
|
||||||
|
sizeof(struct ieee80211_ie_htcap) : 0)
|
||||||
|
#ifdef notyet
|
||||||
+ sizeof(struct ieee80211_ie_htinfo) /* XXX not needed? */
|
+ sizeof(struct ieee80211_ie_htinfo) /* XXX not needed? */
|
||||||
+ sizeof(struct ieee80211_ie_wpa)
|
+ sizeof(struct ieee80211_ie_vhtcap)
|
||||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
|
#endif
|
||||||
+ sizeof(struct ieee80211_ie_wpa)
|
+ ((vap->iv_flags & IEEE80211_F_WPA1 && vap->iv_wpa_ie != NULL) ?
|
||||||
|
vap->iv_wpa_ie[1] : 0)
|
||||||
+ (vap->iv_appie_probereq != NULL ?
|
+ (vap->iv_appie_probereq != NULL ?
|
||||||
vap->iv_appie_probereq->ie_len : 0)
|
vap->iv_appie_probereq->ie_len : 0)
|
||||||
);
|
);
|
||||||
if (m == NULL) {
|
}
|
||||||
vap->iv_stats.is_tx_nobuf++;
|
|
||||||
ieee80211_free_node(ni);
|
|
||||||
ieee80211_free_node(bss);
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
frm = ieee80211_add_ssid(frm, ssid, ssidlen);
|
int
|
||||||
|
ieee80211_probereq_ie(struct ieee80211vap *vap, struct ieee80211com *ic,
|
||||||
|
uint8_t **frmp, uint32_t *frmlen, const uint8_t *ssid, size_t ssidlen,
|
||||||
|
bool alloc)
|
||||||
|
{
|
||||||
|
const struct ieee80211_rateset *rs;
|
||||||
|
uint8_t *frm;
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
|
if (!alloc && (frmp == NULL || frmlen == NULL))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
len = ieee80211_probereq_ie_len(vap, ic);
|
||||||
|
if (!alloc && len > *frmlen)
|
||||||
|
return (ENOBUFS);
|
||||||
|
|
||||||
|
if (alloc) {
|
||||||
|
frm = malloc(len, M_80211_VAP, M_WAITOK | M_ZERO);
|
||||||
|
*frmp = frm;
|
||||||
|
*frmlen = len;
|
||||||
|
} else
|
||||||
|
frm = *frmp;
|
||||||
|
|
||||||
|
/* For HW scans we usually do not pass in the SSID as IE. */
|
||||||
|
if (ssidlen == -1)
|
||||||
|
len -= (2 + IEEE80211_NWID_LEN);
|
||||||
|
else
|
||||||
|
frm = ieee80211_add_ssid(frm, ssid, ssidlen);
|
||||||
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
|
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
|
||||||
frm = ieee80211_add_rates(frm, rs);
|
frm = ieee80211_add_rates(frm, rs);
|
||||||
frm = ieee80211_add_rsn(frm, vap);
|
frm = ieee80211_add_rsn(frm, vap);
|
||||||
@ -2517,8 +2513,8 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
|
|||||||
* XXX TODO: need to figure out what/how to update the
|
* XXX TODO: need to figure out what/how to update the
|
||||||
* VHT channel.
|
* VHT channel.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#ifdef notyet
|
||||||
(vap->iv_flags_vht & IEEE80211_FVHT_VHT) {
|
if (vap->iv_flags_vht & IEEE80211_FVHT_VHT) {
|
||||||
struct ieee80211_channel *c;
|
struct ieee80211_channel *c;
|
||||||
|
|
||||||
c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
|
c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
|
||||||
@ -2531,8 +2527,71 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
|
|||||||
frm = ieee80211_add_wpa(frm, vap);
|
frm = ieee80211_add_wpa(frm, vap);
|
||||||
if (vap->iv_appie_probereq != NULL)
|
if (vap->iv_appie_probereq != NULL)
|
||||||
frm = add_appie(frm, vap->iv_appie_probereq);
|
frm = add_appie(frm, vap->iv_appie_probereq);
|
||||||
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
|
|
||||||
|
|
||||||
|
if (!alloc) {
|
||||||
|
*frmp = frm;
|
||||||
|
*frmlen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||||
|
const uint8_t sa[IEEE80211_ADDR_LEN],
|
||||||
|
const uint8_t da[IEEE80211_ADDR_LEN],
|
||||||
|
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||||
|
const uint8_t *ssid, size_t ssidlen)
|
||||||
|
{
|
||||||
|
struct ieee80211vap *vap = ni->ni_vap;
|
||||||
|
struct ieee80211com *ic = ni->ni_ic;
|
||||||
|
struct ieee80211_node *bss;
|
||||||
|
const struct ieee80211_txparam *tp;
|
||||||
|
struct ieee80211_bpf_params params;
|
||||||
|
struct mbuf *m;
|
||||||
|
uint8_t *frm;
|
||||||
|
uint32_t frmlen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
bss = ieee80211_ref_node(vap->iv_bss);
|
||||||
|
|
||||||
|
if (vap->iv_state == IEEE80211_S_CAC) {
|
||||||
|
IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
|
||||||
|
"block %s frame in CAC state", "probe request");
|
||||||
|
vap->iv_stats.is_tx_badstate++;
|
||||||
|
ieee80211_free_node(bss);
|
||||||
|
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__,
|
||||||
|
ni, ether_sprintf(ni->ni_macaddr),
|
||||||
|
ieee80211_node_refcnt(ni)+1);
|
||||||
|
ieee80211_ref_node(ni);
|
||||||
|
|
||||||
|
/* See comments above for entire frame format. */
|
||||||
|
frmlen = ieee80211_probereq_ie_len(vap, ic);
|
||||||
|
m = ieee80211_getmgtframe(&frm,
|
||||||
|
ic->ic_headroom + sizeof(struct ieee80211_frame), frmlen);
|
||||||
|
if (m == NULL) {
|
||||||
|
vap->iv_stats.is_tx_nobuf++;
|
||||||
|
ieee80211_free_node(ni);
|
||||||
|
ieee80211_free_node(bss);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ieee80211_probereq_ie(vap, ic, &frm, &frmlen, ssid, ssidlen,
|
||||||
|
false);
|
||||||
|
KASSERT(ret == 0,
|
||||||
|
("%s: ieee80211_probereq_ie railed: %d\n", __func__, ret));
|
||||||
|
|
||||||
|
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
|
||||||
KASSERT(M_LEADINGSPACE(m) >= sizeof(struct ieee80211_frame),
|
KASSERT(M_LEADINGSPACE(m) >= sizeof(struct ieee80211_frame),
|
||||||
("leading space %zd", M_LEADINGSPACE(m)));
|
("leading space %zd", M_LEADINGSPACE(m)));
|
||||||
M_PREPEND(m, sizeof(struct ieee80211_frame), M_NOWAIT);
|
M_PREPEND(m, sizeof(struct ieee80211_frame), M_NOWAIT);
|
||||||
|
@ -114,6 +114,8 @@ struct mbuf *ieee80211_encap(struct ieee80211vap *, struct ieee80211_node *,
|
|||||||
void ieee80211_free_mbuf(struct mbuf *);
|
void ieee80211_free_mbuf(struct mbuf *);
|
||||||
int ieee80211_send_mgmt(struct ieee80211_node *, int, int);
|
int ieee80211_send_mgmt(struct ieee80211_node *, int, int);
|
||||||
struct ieee80211_appie;
|
struct ieee80211_appie;
|
||||||
|
int ieee80211_probereq_ie(struct ieee80211vap *, struct ieee80211com *,
|
||||||
|
uint8_t **, uint32_t *, const uint8_t *, size_t, bool);
|
||||||
int ieee80211_send_probereq(struct ieee80211_node *ni,
|
int ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||||
const uint8_t sa[IEEE80211_ADDR_LEN],
|
const uint8_t sa[IEEE80211_ADDR_LEN],
|
||||||
const uint8_t da[IEEE80211_ADDR_LEN],
|
const uint8_t da[IEEE80211_ADDR_LEN],
|
||||||
|
Loading…
Reference in New Issue
Block a user