Add a new mgmt subtype "ACTION NO ACK" defined in 802.11n-2009, while here

clean up parts of the *_recv_mgmt() functions.
- make sure appropriate counters are bumped and debug messages are printed
- order the unhandled subtypes by value and add a few missing ones
- fix some whitespace nits
- remove duplicate code in adhoc_recv_mgmt()
- remove a useless comment, probably left in while c&p
This commit is contained in:
Bernhard Schmidt 2011-02-21 19:59:43 +00:00
parent 199ba798b3
commit 96283082bb
8 changed files with 123 additions and 99 deletions

View File

@ -131,6 +131,7 @@ struct ieee80211_qosframe_addr4 {
#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 #define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 #define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
#define IEEE80211_FC0_SUBTYPE_ACTION 0xd0 #define IEEE80211_FC0_SUBTYPE_ACTION 0xd0
#define IEEE80211_FC0_SUBTYPE_ACTION_NOACK 0xe0
/* for TYPE_CTL */ /* for TYPE_CTL */
#define IEEE80211_FC0_SUBTYPE_BAR 0x80 #define IEEE80211_FC0_SUBTYPE_BAR 0x80
#define IEEE80211_FC0_SUBTYPE_BA 0x90 #define IEEE80211_FC0_SUBTYPE_BA 0x90

View File

@ -823,80 +823,35 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0); is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0);
break; break;
case IEEE80211_FC0_SUBTYPE_ACTION: { case IEEE80211_FC0_SUBTYPE_ACTION:
const struct ieee80211_action *ia; case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
if (vap->iv_state == IEEE80211_S_RUN) {
if (vap->iv_state != IEEE80211_S_RUN) { if (ieee80211_parse_action(ni, m0) == 0)
(void)ic->ic_recv_action(ni, wh, frm, efrm);
} else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "wrong state %s", wh, NULL, "wrong state %s",
ieee80211_state_name[vap->iv_state]); ieee80211_state_name[vap->iv_state]);
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
return;
} }
/*
* action frame format:
* [1] category
* [1] action
* [tlv] parameters
*/
IEEE80211_VERIFY_LENGTH(efrm - frm,
sizeof(struct ieee80211_action), return);
ia = (const struct ieee80211_action *) frm;
vap->iv_stats.is_rx_action++;
IEEE80211_NODE_STAT(ni, rx_action);
/* verify frame payloads but defer processing */
/* XXX maybe push this to method */
switch (ia->ia_category) {
case IEEE80211_ACTION_CAT_BA:
switch (ia->ia_action) {
case IEEE80211_ACTION_BA_ADDBA_REQUEST:
IEEE80211_VERIFY_LENGTH(efrm - frm,
sizeof(struct ieee80211_action_ba_addbarequest),
return);
break;
case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
IEEE80211_VERIFY_LENGTH(efrm - frm,
sizeof(struct ieee80211_action_ba_addbaresponse),
return);
break;
case IEEE80211_ACTION_BA_DELBA:
IEEE80211_VERIFY_LENGTH(efrm - frm,
sizeof(struct ieee80211_action_ba_delba),
return);
break;
}
break;
case IEEE80211_ACTION_CAT_HT:
switch (ia->ia_action) {
case IEEE80211_ACTION_HT_TXCHWIDTH:
IEEE80211_VERIFY_LENGTH(efrm - frm,
sizeof(struct ieee80211_action_ht_txchwidth),
return);
break;
}
break;
}
ic->ic_recv_action(ni, wh, frm, efrm);
break; break;
}
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_DEAUTH: case IEEE80211_FC0_SUBTYPE_ATIM:
case IEEE80211_FC0_SUBTYPE_DISASSOC: case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "%s", "not handled"); wh, NULL, "%s", "not handled");
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
return; break;
default: default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "mgt", "subtype 0x%x not handled", subtype); wh, "mgt", "subtype 0x%x not handled", subtype);
vap->iv_stats.is_rx_badsubtype++; vap->iv_stats.is_rx_badsubtype++;
break; break;
} }
@ -910,6 +865,7 @@ ahdemo_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
{ {
struct ieee80211vap *vap = ni->ni_vap; struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic; struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_frame *wh;
/* /*
* Process management frames when scanning; useful for doing * Process management frames when scanning; useful for doing
@ -917,8 +873,33 @@ ahdemo_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
*/ */
if (ic->ic_flags & IEEE80211_F_SCAN) if (ic->ic_flags & IEEE80211_F_SCAN)
adhoc_recv_mgmt(ni, m0, subtype, rssi, nf); adhoc_recv_mgmt(ni, m0, subtype, rssi, nf);
else else {
vap->iv_stats.is_rx_mgtdiscard++; wh = mtod(m0, struct ieee80211_frame *);
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
case IEEE80211_FC0_SUBTYPE_BEACON:
case IEEE80211_FC0_SUBTYPE_ATIM:
case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
case IEEE80211_FC0_SUBTYPE_ACTION:
case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "%s", "not handled");
vap->iv_stats.is_rx_mgtdiscard++;
break;
default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "mgt", "subtype 0x%x not handled", subtype);
vap->iv_stats.is_rx_badsubtype++;
break;
}
}
} }
static void static void

View File

@ -2194,18 +2194,29 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
} }
case IEEE80211_FC0_SUBTYPE_ACTION: case IEEE80211_FC0_SUBTYPE_ACTION:
case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
if (vap->iv_state == IEEE80211_S_RUN) { if (vap->iv_state == IEEE80211_S_RUN) {
if (ieee80211_parse_action(ni, m0) == 0) if (ieee80211_parse_action(ni, m0) == 0)
ic->ic_recv_action(ni, wh, frm, efrm); (void)ic->ic_recv_action(ni, wh, frm, efrm);
} else } else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "wrong state %s",
ieee80211_state_name[vap->iv_state]);
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
}
break; break;
case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_ATIM:
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "%s", "not handled");
vap->iv_stats.is_rx_mgtdiscard++;
break;
default: default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "mgt", "subtype 0x%x not handled", subtype); wh, "mgt", "subtype 0x%x not handled", subtype);
vap->iv_stats.is_rx_badsubtype++; vap->iv_stats.is_rx_badsubtype++;
break; break;
} }

View File

@ -677,7 +677,6 @@ ieee80211_parse_action(struct ieee80211_node *ni, struct mbuf *m)
IEEE80211_NODE_STAT(ni, rx_action); IEEE80211_NODE_STAT(ni, rx_action);
/* verify frame payloads but defer processing */ /* verify frame payloads but defer processing */
/* XXX maybe push this to method */
switch (ia->ia_category) { switch (ia->ia_category) {
case IEEE80211_ACTION_CAT_BA: case IEEE80211_ACTION_CAT_BA:
switch (ia->ia_action) { switch (ia->ia_action) {

View File

@ -1489,11 +1489,9 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
ieee80211_send_proberesp(vap, wh->i_addr2, 0); ieee80211_send_proberesp(vap, wh->i_addr2, 0);
break; break;
} }
case IEEE80211_FC0_SUBTYPE_ACTION: case IEEE80211_FC0_SUBTYPE_ACTION:
if (vap->iv_state != IEEE80211_S_RUN) { case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
vap->iv_stats.is_rx_mgtdiscard++;
break;
}
/* /*
* We received an action for an unknown neighbor. * We received an action for an unknown neighbor.
* XXX: wait for it to beacon or create ieee80211_node? * XXX: wait for it to beacon or create ieee80211_node?
@ -1506,6 +1504,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
} }
/* /*
* Discard if not for us. * Discard if not for us.
* XXX: if from us too?
*/ */
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) && if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) &&
!IEEE80211_IS_MULTICAST(wh->i_addr1)) { !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
@ -1514,21 +1513,30 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
break; break;
} }
/* XXX parse_action is a bit useless now */ if (vap->iv_state == IEEE80211_S_RUN) {
if (ieee80211_parse_action(ni, m0) == 0) if (ieee80211_parse_action(ni, m0) == 0)
ic->ic_recv_action(ni, wh, frm, efrm); (void)ic->ic_recv_action(ni, wh, frm, efrm);
} else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "wrong state %s",
ieee80211_state_name[vap->iv_state]);
vap->iv_stats.is_rx_mgtdiscard++;
}
break; break;
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_DEAUTH: case IEEE80211_FC0_SUBTYPE_ATIM:
case IEEE80211_FC0_SUBTYPE_DISASSOC: case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "%s", "not handled"); wh, NULL, "%s", "not handled");
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
return; break;
default: default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "mgt", "subtype 0x%x not handled", subtype); wh, "mgt", "subtype 0x%x not handled", subtype);

View File

@ -64,7 +64,7 @@ const char *ieee80211_mgt_subtype_name[] = {
"assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
"probe_req", "probe_resp", "reserved#6", "reserved#7", "probe_req", "probe_resp", "reserved#6", "reserved#7",
"beacon", "atim", "disassoc", "auth", "beacon", "atim", "disassoc", "auth",
"deauth", "action", "reserved#14", "reserved#15" "deauth", "action", "action_noack", "reserved#15"
}; };
const char *ieee80211_ctl_subtype_name[] = { const char *ieee80211_ctl_subtype_name[] = {
"reserved#0", "reserved#1", "reserved#2", "reserved#3", "reserved#0", "reserved#1", "reserved#2", "reserved#3",

View File

@ -1718,21 +1718,30 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
} }
case IEEE80211_FC0_SUBTYPE_ACTION: case IEEE80211_FC0_SUBTYPE_ACTION:
case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
if (vap->iv_state == IEEE80211_S_RUN) { if (vap->iv_state == IEEE80211_S_RUN) {
if (ieee80211_parse_action(ni, m0) == 0) if (ieee80211_parse_action(ni, m0) == 0)
ic->ic_recv_action(ni, wh, frm, efrm); (void)ic->ic_recv_action(ni, wh, frm, efrm);
} else } else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "wrong state %s",
ieee80211_state_name[vap->iv_state]);
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
}
break; break;
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
case IEEE80211_FC0_SUBTYPE_ATIM:
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "%s", "not handled");
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
return; break;
default: default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "mgt", "subtype 0x%x not handled", subtype); wh, "mgt", "subtype 0x%x not handled", subtype);
vap->iv_stats.is_rx_badsubtype++; vap->iv_stats.is_rx_badsubtype++;
break; break;
} }

View File

@ -756,31 +756,46 @@ wds_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
frm = (u_int8_t *)&wh[1]; frm = (u_int8_t *)&wh[1];
efrm = mtod(m0, u_int8_t *) + m0->m_len; efrm = mtod(m0, u_int8_t *) + m0->m_len;
switch (subtype) { switch (subtype) {
case IEEE80211_FC0_SUBTYPE_DEAUTH:
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
case IEEE80211_FC0_SUBTYPE_BEACON:
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_DISASSOC:
vap->iv_stats.is_rx_mgtdiscard++;
break;
case IEEE80211_FC0_SUBTYPE_ACTION: case IEEE80211_FC0_SUBTYPE_ACTION:
if (vap->iv_state != IEEE80211_S_RUN || case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
IEEE80211_IS_MULTICAST(wh->i_addr1)) { if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
IEEE80211_DISCARD(vap, IEEE80211_MSG_MESH,
wh, NULL, "%s", "not directed to us");
vap->iv_stats.is_rx_mgtdiscard++; vap->iv_stats.is_rx_mgtdiscard++;
break; break;
} else
ni->ni_inact = ni->ni_inact_reload;
if (vap->iv_state == IEEE80211_S_RUN) {
if (ieee80211_parse_action(ni, m0) == 0)
(void)ic->ic_recv_action(ni, wh, frm, efrm);
} else {
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "wrong state %s",
ieee80211_state_name[vap->iv_state]);
vap->iv_stats.is_rx_mgtdiscard++;
} }
ni->ni_inact = ni->ni_inact_reload;
if (ieee80211_parse_action(ni, m0) == 0)
ic->ic_recv_action(ni, wh, frm, efrm);
break; break;
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
case IEEE80211_FC0_SUBTYPE_BEACON:
case IEEE80211_FC0_SUBTYPE_ATIM:
case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_AUTH:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
wh, NULL, "%s", "not handled");
vap->iv_stats.is_rx_mgtdiscard++;
break;
default: default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "mgt", "subtype 0x%x not handled", subtype); wh, "mgt", "subtype 0x%x not handled", subtype);
vap->iv_stats.is_rx_badsubtype++; vap->iv_stats.is_rx_badsubtype++;
break; break;
} }