Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_input.c
Show First 20 Lines • Show All 164 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* This function reassembles fragments. | * This function reassembles fragments. | ||||
* | * | ||||
* XXX should handle 3 concurrent reassemblies per-spec. | * XXX should handle 3 concurrent reassemblies per-spec. | ||||
*/ | */ | ||||
struct mbuf * | struct mbuf * | ||||
ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace) | ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace, | ||||
int has_decrypted) | |||||
emaste: `bool has_decrypted` perhaps? | |||||
bzAuthorUnsubmitted Done Inline ActionsI think that's something for an aftermath; I'd rather not start making it all bools (as you'd also want to do the callers)... bz: I think that's something for an aftermath; I'd rather not start making it all bools (as you'd… | |||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); | struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); | ||||
struct ieee80211_frame *lwh; | struct ieee80211_frame *lwh; | ||||
uint16_t rxseq; | uint16_t rxseq; | ||||
uint8_t fragno; | uint8_t fragno; | ||||
uint8_t more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG; | uint8_t more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG; | ||||
struct mbuf *mfrag; | struct mbuf *mfrag; | ||||
KASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1), ("multicast fragm?")); | KASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1), ("multicast fragm?")); | ||||
rxseq = le16toh(*(uint16_t *)wh->i_seq); | rxseq = le16toh(*(uint16_t *)wh->i_seq); | ||||
fragno = rxseq & IEEE80211_SEQ_FRAG_MASK; | fragno = rxseq & IEEE80211_SEQ_FRAG_MASK; | ||||
/* Quick way out, if there's nothing to defragment */ | /* Quick way out, if there's nothing to defragment */ | ||||
if (!more_frag && fragno == 0 && ni->ni_rxfrag[0] == NULL) | if (!more_frag && fragno == 0 && ni->ni_rxfrag[0] == NULL) | ||||
return m; | return m; | ||||
/* Temporarily set flag to remember if fragment was encrypted */ | |||||
if (has_decrypted) | |||||
wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; | |||||
/* | /* | ||||
* Remove frag to insure it doesn't get reaped by timer. | * Remove frag to insure it doesn't get reaped by timer. | ||||
*/ | */ | ||||
if (ni->ni_table == NULL) { | if (ni->ni_table == NULL) { | ||||
/* | /* | ||||
* Should never happen. If the node is orphaned (not in | * Should never happen. If the node is orphaned (not in | ||||
* the table) then input packets should not reach here. | * the table) then input packets should not reach here. | ||||
* Otherwise, a concurrent request that yanks the table | * Otherwise, a concurrent request that yanks the table | ||||
Show All 14 Lines | ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace, | ||||
* Validate new fragment is in order and | * Validate new fragment is in order and | ||||
* related to the previous ones. | * related to the previous ones. | ||||
*/ | */ | ||||
if (mfrag != NULL) { | if (mfrag != NULL) { | ||||
uint16_t last_rxseq; | uint16_t last_rxseq; | ||||
lwh = mtod(mfrag, struct ieee80211_frame *); | lwh = mtod(mfrag, struct ieee80211_frame *); | ||||
last_rxseq = le16toh(*(uint16_t *)lwh->i_seq); | last_rxseq = le16toh(*(uint16_t *)lwh->i_seq); | ||||
/* NB: check seq # and frag together */ | /* | ||||
* NB: check seq # and frag together. Also check that both | |||||
* fragments are plaintext or that both are encrypted. | |||||
* */ | |||||
if (rxseq == last_rxseq+1 && | if (rxseq == last_rxseq+1 && | ||||
IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) && | IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) && | ||||
IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) { | IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2) && | ||||
!((wh->i_fc[1] ^ lwh->i_fc[1]) & IEEE80211_FC1_PROTECTED)) { | |||||
/* XXX clear MORE_FRAG bit? */ | /* XXX clear MORE_FRAG bit? */ | ||||
/* track last seqnum and fragno */ | /* track last seqnum and fragno */ | ||||
*(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq; | *(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq; | ||||
m_adj(m, hdrspace); /* strip header */ | m_adj(m, hdrspace); /* strip header */ | ||||
m_catpkt(mfrag, m); /* concatenate */ | m_catpkt(mfrag, m); /* concatenate */ | ||||
} else { | } else { | ||||
/* | /* | ||||
Show All 13 Lines | if (fragno != 0) { /* !first fragment, discard */ | ||||
return NULL; | return NULL; | ||||
} | } | ||||
mfrag = m; | mfrag = m; | ||||
} | } | ||||
if (more_frag) { /* more to come, save */ | if (more_frag) { /* more to come, save */ | ||||
ni->ni_rxfragstamp = ticks; | ni->ni_rxfragstamp = ticks; | ||||
ni->ni_rxfrag[0] = mfrag; | ni->ni_rxfrag[0] = mfrag; | ||||
mfrag = NULL; | mfrag = NULL; | ||||
} | |||||
/* Remember to clear protected flag that was temporariy set */ | |||||
bzAuthorUnsubmitted Done Inline Actionstemporarily bz: temporarily | |||||
if (mfrag != NULL) { | |||||
wh = mtod(mfrag, struct ieee80211_frame *); | |||||
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; | |||||
} | } | ||||
return mfrag; | return mfrag; | ||||
} | } | ||||
void | void | ||||
ieee80211_deliver_data(struct ieee80211vap *vap, | ieee80211_deliver_data(struct ieee80211vap *vap, | ||||
struct ieee80211_node *ni, struct mbuf *m) | struct ieee80211_node *ni, struct mbuf *m) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 738 Lines • Show Last 20 Lines |
bool has_decrypted perhaps?