diff options
-rw-r--r-- | include/net/mac80211.h | 6 | ||||
-rw-r--r-- | net/mac80211/rx.c | 32 |
2 files changed, 35 insertions, 3 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 947f3c820e42..7d9dc20ee42f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -235,6 +235,10 @@ struct ieee80211_tx_control { | |||
235 | * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. | 235 | * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. |
236 | * If this flag is set, the stack cannot do any replay detection | 236 | * If this flag is set, the stack cannot do any replay detection |
237 | * hence the driver or hardware will have to do that. | 237 | * hence the driver or hardware will have to do that. |
238 | * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on | ||
239 | * the frame. | ||
240 | * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on | ||
241 | * the frame. | ||
238 | */ | 242 | */ |
239 | enum mac80211_rx_flags { | 243 | enum mac80211_rx_flags { |
240 | RX_FLAG_MMIC_ERROR = 1<<0, | 244 | RX_FLAG_MMIC_ERROR = 1<<0, |
@@ -242,6 +246,8 @@ enum mac80211_rx_flags { | |||
242 | RX_FLAG_RADIOTAP = 1<<2, | 246 | RX_FLAG_RADIOTAP = 1<<2, |
243 | RX_FLAG_MMIC_STRIPPED = 1<<3, | 247 | RX_FLAG_MMIC_STRIPPED = 1<<3, |
244 | RX_FLAG_IV_STRIPPED = 1<<4, | 248 | RX_FLAG_IV_STRIPPED = 1<<4, |
249 | RX_FLAG_FAILED_FCS_CRC = 1<<5, | ||
250 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, | ||
245 | }; | 251 | }; |
246 | 252 | ||
247 | /** | 253 | /** |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e9dcc6229c3c..cf2a72f89d68 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -145,6 +145,8 @@ ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb, | |||
145 | __le16 chan_freq; | 145 | __le16 chan_freq; |
146 | __le16 chan_flags; | 146 | __le16 chan_flags; |
147 | u8 antsignal; | 147 | u8 antsignal; |
148 | u8 padding_for_rxflags; | ||
149 | __le16 rx_flags; | ||
148 | } __attribute__ ((packed)) *rthdr; | 150 | } __attribute__ ((packed)) *rthdr; |
149 | 151 | ||
150 | skb->dev = dev; | 152 | skb->dev = dev; |
@@ -167,12 +169,21 @@ ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb, | |||
167 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | 169 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
168 | (1 << IEEE80211_RADIOTAP_RATE) | | 170 | (1 << IEEE80211_RADIOTAP_RATE) | |
169 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 171 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
170 | (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)); | 172 | (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | |
173 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | ||
171 | rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ? | 174 | rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ? |
172 | IEEE80211_RADIOTAP_F_FCS : 0; | 175 | IEEE80211_RADIOTAP_F_FCS : 0; |
176 | |||
177 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ | ||
178 | rthdr->rx_flags = 0; | ||
179 | if (status->flag & | ||
180 | (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | ||
181 | rthdr->rx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); | ||
182 | |||
173 | rate = ieee80211_get_rate(local, status->phymode, status->rate); | 183 | rate = ieee80211_get_rate(local, status->phymode, status->rate); |
174 | if (rate) | 184 | if (rate) |
175 | rthdr->rate = rate->rate / 5; | 185 | rthdr->rate = rate->rate / 5; |
186 | |||
176 | rthdr->chan_freq = cpu_to_le16(status->freq); | 187 | rthdr->chan_freq = cpu_to_le16(status->freq); |
177 | rthdr->chan_flags = | 188 | rthdr->chan_flags = |
178 | status->phymode == MODE_IEEE80211A ? | 189 | status->phymode == MODE_IEEE80211A ? |
@@ -200,6 +211,15 @@ ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx) | |||
200 | return TXRX_QUEUED; | 211 | return TXRX_QUEUED; |
201 | } | 212 | } |
202 | 213 | ||
214 | /* | ||
215 | * Drop frames with failed FCS/PLCP checksums here, they are only | ||
216 | * relevant for monitor mode, the rest of the stack should never | ||
217 | * see them. | ||
218 | */ | ||
219 | if (rx->u.rx.status->flag & | ||
220 | (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | ||
221 | return TXRX_DROP; | ||
222 | |||
203 | if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP) | 223 | if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP) |
204 | skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb->data)); | 224 | skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb->data)); |
205 | 225 | ||
@@ -1360,6 +1380,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1360 | struct ieee80211_sub_if_data *prev = NULL; | 1380 | struct ieee80211_sub_if_data *prev = NULL; |
1361 | struct sk_buff *skb_new; | 1381 | struct sk_buff *skb_new; |
1362 | u8 *bssid; | 1382 | u8 *bssid; |
1383 | int bogon; | ||
1363 | 1384 | ||
1364 | if (status->flag & RX_FLAG_RADIOTAP) { | 1385 | if (status->flag & RX_FLAG_RADIOTAP) { |
1365 | radiotap_len = ieee80211_get_radiotap_len(skb->data); | 1386 | radiotap_len = ieee80211_get_radiotap_len(skb->data); |
@@ -1380,10 +1401,15 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1380 | rx.u.rx.status = status; | 1401 | rx.u.rx.status = status; |
1381 | rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0; | 1402 | rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0; |
1382 | type = rx.fc & IEEE80211_FCTL_FTYPE; | 1403 | type = rx.fc & IEEE80211_FCTL_FTYPE; |
1383 | if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) | 1404 | |
1405 | bogon = status->flag & (RX_FLAG_FAILED_FCS_CRC | | ||
1406 | RX_FLAG_FAILED_PLCP_CRC); | ||
1407 | |||
1408 | if (!bogon && (type == IEEE80211_FTYPE_DATA || | ||
1409 | type == IEEE80211_FTYPE_MGMT)) | ||
1384 | local->dot11ReceivedFragmentCount++; | 1410 | local->dot11ReceivedFragmentCount++; |
1385 | 1411 | ||
1386 | if (skb->len >= 16) { | 1412 | if (!bogon && skb->len >= 16) { |
1387 | sta = rx.sta = sta_info_get(local, hdr->addr2); | 1413 | sta = rx.sta = sta_info_get(local, hdr->addr2); |
1388 | if (sta) { | 1414 | if (sta) { |
1389 | rx.dev = rx.sta->dev; | 1415 | rx.dev = rx.sta->dev; |