Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_sta.c
Show First 20 Lines • Show All 546 Lines • ▼ Show 20 Lines | sta_input(struct ieee80211_node *ni, struct mbuf *m, | ||||
struct ieee80211_key *key; | struct ieee80211_key *key; | ||||
struct ether_header *eh; | struct ether_header *eh; | ||||
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ | int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ | ||||
uint8_t dir, type, subtype, qos; | uint8_t dir, type, subtype, qos; | ||||
uint8_t *bssid; | uint8_t *bssid; | ||||
int is_hw_decrypted = 0; | int is_hw_decrypted = 0; | ||||
int has_decrypted = 0; | int has_decrypted = 0; | ||||
KASSERT(ni != NULL, ("%s: null node, mbuf %p", __func__, m)); | |||||
/* Early init in case of early error case. */ | |||||
type = -1; | |||||
/* | /* | ||||
* Bit of a cheat here, we use a pointer for a 3-address | |||||
* frame format but don't reference fields past outside | |||||
* ieee80211_frame_min (or other shorter frames) w/o first | |||||
* validating the data is present. | |||||
*/ | |||||
wh = mtod(m, struct ieee80211_frame *); | |||||
if (m->m_pkthdr.len < 2 || m->m_pkthdr.len < ieee80211_anyhdrsize(wh)) { | |||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, | |||||
ni->ni_macaddr, NULL, | |||||
"too short (1): len %u", m->m_pkthdr.len); | |||||
vap->iv_stats.is_rx_tooshort++; | |||||
goto err; | |||||
} | |||||
if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != | |||||
IEEE80211_FC0_VERSION_0) { | |||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, | |||||
ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", | |||||
wh->i_fc[0], wh->i_fc[1]); | |||||
vap->iv_stats.is_rx_badversion++; | |||||
goto err; | |||||
} | |||||
/* | |||||
* Some devices do hardware decryption all the way through | * Some devices do hardware decryption all the way through | ||||
* to pretending the frame wasn't encrypted in the first place. | * to pretending the frame wasn't encrypted in the first place. | ||||
* So, tag it appropriately so it isn't discarded inappropriately. | * So, tag it appropriately so it isn't discarded inappropriately. | ||||
*/ | */ | ||||
if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) | if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) | ||||
is_hw_decrypted = 1; | is_hw_decrypted = 1; | ||||
if (m->m_flags & M_AMPDU_MPDU) { | if (m->m_flags & M_AMPDU_MPDU) { | ||||
/* | /* | ||||
* Fastpath for A-MPDU reorder q resubmission. Frames | * Fastpath for A-MPDU reorder q resubmission. Frames | ||||
* w/ M_AMPDU_MPDU marked have already passed through | * w/ M_AMPDU_MPDU marked have already passed through | ||||
* here but were received out of order and been held on | * here but were received out of order and been held on | ||||
* the reorder queue. When resubmitted they are marked | * the reorder queue. When resubmitted they are marked | ||||
* with the M_AMPDU_MPDU flag and we can bypass most of | * with the M_AMPDU_MPDU flag and we can bypass most of | ||||
* the normal processing. | * the normal processing. | ||||
*/ | */ | ||||
wh = mtod(m, struct ieee80211_frame *); | |||||
type = IEEE80211_FC0_TYPE_DATA; | type = IEEE80211_FC0_TYPE_DATA; | ||||
dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; | dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; | ||||
subtype = IEEE80211_FC0_SUBTYPE_QOS; | subtype = IEEE80211_FC0_SUBTYPE_QOS; | ||||
hdrspace = ieee80211_hdrspace(ic, wh); /* XXX optimize? */ | hdrspace = ieee80211_hdrspace(ic, wh); /* XXX optimize? */ | ||||
goto resubmit_ampdu; | goto resubmit_ampdu; | ||||
} | } | ||||
KASSERT(ni != NULL, ("null node")); | |||||
ni->ni_inact = ni->ni_inact_reload; | ni->ni_inact = ni->ni_inact_reload; | ||||
type = -1; /* undefined */ | |||||
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { | |||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, | |||||
ni->ni_macaddr, NULL, | |||||
"too short (1): len %u", m->m_pkthdr.len); | |||||
vap->iv_stats.is_rx_tooshort++; | |||||
goto out; | |||||
} | |||||
/* | |||||
* Bit of a cheat here, we use a pointer for a 3-address | |||||
* frame format but don't reference fields past outside | |||||
* ieee80211_frame_min w/o first validating the data is | |||||
* present. | |||||
*/ | |||||
wh = mtod(m, struct ieee80211_frame *); | |||||
if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != | |||||
IEEE80211_FC0_VERSION_0) { | |||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, | |||||
ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", | |||||
wh->i_fc[0], wh->i_fc[1]); | |||||
vap->iv_stats.is_rx_badversion++; | |||||
goto err; | |||||
} | |||||
dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; | dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; | ||||
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | ||||
subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; | subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; | ||||
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { | /* | ||||
* Control frames are not folowing the header scheme of data and mgmt | |||||
* frames so we do not apply extra checks here. | |||||
* We probably should do checks on RA (+TA) where available for those | |||||
* too, but for now do not drop them. | |||||
*/ | |||||
if (type != IEEE80211_FC0_TYPE_CTL && | |||||
(ic->ic_flags & IEEE80211_F_SCAN) == 0) { | |||||
bssid = wh->i_addr2; | bssid = wh->i_addr2; | ||||
if (!IEEE80211_ADDR_EQ(bssid, ni->ni_bssid)) { | if (!IEEE80211_ADDR_EQ(bssid, ni->ni_bssid)) { | ||||
/* not interested in */ | /* not interested in */ | ||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, | IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, | ||||
bssid, NULL, "%s", "not to bss"); | bssid, NULL, "%s", "not to bss"); | ||||
vap->iv_stats.is_rx_wrongbss++; | vap->iv_stats.is_rx_wrongbss++; | ||||
goto out; | goto out; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,437 Lines • Show Last 20 Lines |