update madwifi
[linux-2.6/zen-sources.git] / drivers / net / wireless / madwifi / net80211 / ieee80211_monitor.c
blob3b3f65a66271dde3ec09f1c5903ff7159dce9f0f
1 /*-
2 * Copyright (c) 2005 John Bicket
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * $Id: ieee80211_monitor.c 3720 2008-06-12 05:22:37Z mentor $
30 #ifndef EXPORT_SYMTAB
31 #define EXPORT_SYMTAB
32 #endif
35 * IEEE 802.11 monitor mode
37 #ifndef AUTOCONF_INCLUDED
38 #include <linux/config.h>
39 #endif
40 #include <linux/version.h>
41 #include <linux/module.h>
42 #include <linux/kmod.h>
43 #include <linux/init.h>
44 #include <linux/skbuff.h>
45 #include <linux/sysctl.h>
46 #include <linux/netdevice.h>
47 #include <linux/etherdevice.h>
48 #include <linux/if_vlan.h>
50 #include <net/iw_handler.h>
51 #include <linux/wireless.h>
52 #include <linux/if_arp.h> /* for ARPHRD_* */
54 #include <asm/uaccess.h>
56 #include "if_media.h"
57 #include "if_ethersubr.h"
59 #include <net80211/ieee80211_var.h>
60 #include <net80211/ieee80211_monitor.h>
61 #include <ath/if_athvar.h>
64 static int
65 ratecode_to_dot11(int ratecode)
67 switch (ratecode) {
68 /* a */
69 case 0x0b: return 12;
70 case 0x0f: return 18;
71 case 0x0a: return 24;
72 case 0x0e: return 36;
73 case 0x09: return 48;
74 case 0x0d: return 72;
75 case 0x08: return 96;
76 case 0x0c: return 108;
78 case 0x1b: return 2;
79 case 0x1a: return 4;
80 case 0x1e: return 4;
81 case 0x19: return 11;
82 case 0x1d: return 11;
83 case 0x18: return 22;
84 case 0x1c: return 22;
86 return 0;
89 struct ar5212_openbsd_desc {
91 * tx_control_0
93 u_int32_t frame_len:12;
94 u_int32_t reserved_12_15:4;
95 u_int32_t xmit_power:6;
96 u_int32_t rts_cts_enable:1;
97 u_int32_t veol:1;
98 u_int32_t clear_dest_mask:1;
99 u_int32_t ant_mode_xmit:4;
100 u_int32_t inter_req:1;
101 u_int32_t encrypt_key_valid:1;
102 u_int32_t cts_enable:1;
104 u_int32_t r1;
107 * tx_control_2
109 u_int32_t rts_duration:15;
110 u_int32_t duration_update_enable:1;
111 u_int32_t xmit_tries0:4;
112 u_int32_t xmit_tries1:4;
113 u_int32_t xmit_tries2:4;
114 u_int32_t xmit_tries3:4;
117 * tx_control_3
119 u_int32_t xmit_rate0:5;
120 u_int32_t xmit_rate1:5;
121 u_int32_t xmit_rate2:5;
122 u_int32_t xmit_rate3:5;
123 u_int32_t rts_cts_rate:5;
124 u_int32_t reserved_25_31:7;
127 void
128 ieee80211_monitor_encap(struct ieee80211vap *vap, struct sk_buff *skb)
130 struct ieee80211_phy_params *ph = &(SKB_CB(skb)->phy);
131 SKB_CB(skb)->flags = M_RAW;
132 SKB_NI(skb) = ieee80211_ref_node(vap->iv_bss);
134 /* send at a static rate if it is configured */
135 ph->rate[0] = vap->iv_fixed_rate > 0 ? vap->iv_fixed_rate : 2;
136 /* don't retry control packets */
137 ph->try[0] = 11;
138 ph->power = 60;
140 switch (skb->dev->type) {
141 case ARPHRD_IEEE80211: {
142 struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
143 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
144 ph->try[0] = 1;
145 break;
147 case ARPHRD_IEEE80211_PRISM: {
148 struct ieee80211_frame *wh = NULL;
149 struct wlan_ng_prism2_header *p2h =
150 (struct wlan_ng_prism2_header *)skb->data;
151 /* does it look like there is a prism header here? */
152 if (skb->len > sizeof(struct wlan_ng_prism2_header) &&
153 p2h->msgcode == DIDmsg_lnxind_wlansniffrm &&
154 p2h->rate.did == DIDmsg_lnxind_wlansniffrm_rate) {
155 ph->rate[0] = p2h->rate.data;
156 skb_pull(skb, sizeof(struct wlan_ng_prism2_header));
158 wh = (struct ieee80211_frame *)skb->data;
159 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
160 ph->try[0] = 1;
161 break;
163 case ARPHRD_IEEE80211_RADIOTAP: {
164 struct ieee80211_frame *wh = NULL;
165 struct ieee80211_radiotap_header *rh =
166 (struct ieee80211_radiotap_header *)skb->data;
167 u_int32_t present, present_ext;
168 u_int16_t len;
169 u_int8_t *start = skb->data + sizeof(struct ieee80211_radiotap_header);
170 u_int8_t *p = start;
171 u_int8_t *end = skb->data + skb->len;
172 u_int8_t bit, flags = 0;
174 if (skb->len < sizeof(*rh) || rh->it_version != 0)
175 break;
177 present_ext = present = le32_to_cpu(rh->it_present);
178 len = le16_to_cpu(rh->it_len);
180 if (skb->len < len)
181 break;
183 /* skip the chain of additional bitmaps following it_present */
184 while (present_ext & (1 << IEEE80211_RADIOTAP_EXT)) {
185 if (p + 4 > end) {
186 /* An extended bitmap would now follow, but there is
187 * no place for it. Stop parsing. */
188 present = 0;
189 break;
191 present_ext = le32_to_cpu(*(__le32 *)p);
192 p += 4;
195 for (bit = 0; present && p < end; present >>= 1, bit++) {
196 if ((present & 1) == 0)
197 continue;
198 switch (bit) {
199 case IEEE80211_RADIOTAP_RATE:
200 ph->rate[0] = *p;
201 p++;
202 break;
204 case IEEE80211_RADIOTAP_DBM_TX_POWER:
205 ph->power = *p;
206 p++;
207 break;
209 case IEEE80211_RADIOTAP_FLAGS:
210 flags = *p;
211 p++;
212 break;
214 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
215 case IEEE80211_RADIOTAP_DB_ANTNOISE:
216 case IEEE80211_RADIOTAP_ANTENNA:
217 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
218 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
219 /* 8-bit */
220 p++;
221 break;
223 case IEEE80211_RADIOTAP_FHSS:
224 /* 2 x 8-bit */
225 p += 2;
226 break;
228 case IEEE80211_RADIOTAP_LOCK_QUALITY:
229 case IEEE80211_RADIOTAP_TX_ATTENUATION:
230 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
231 /* 16-bit */
232 p = start + roundup(p - start, 2) + 2;
233 break;
235 case IEEE80211_RADIOTAP_CHANNEL:
236 /* 2 x 16-bit */
237 p = start + roundup(p - start, 2) + 4;
238 break;
240 case IEEE80211_RADIOTAP_TSFT:
241 /* 64-bit */
242 p = start + roundup(p - start, 8) + 8;
243 break;
245 case IEEE80211_RADIOTAP_DATA_RETRIES:
246 ph->try[0] = *p + 1;
247 p++;
248 break;
250 default:
251 present = 0;
252 break;
255 skb_pull(skb, len);
256 if (flags & IEEE80211_RADIOTAP_F_FCS)
257 /* Remove FCS from the end of frames to transmit */
258 skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
259 wh = (struct ieee80211_frame *)skb->data;
260 if (!ph->try[0] &&
261 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
262 ph->try[0] = 1;
263 break;
265 case ARPHRD_IEEE80211_ATHDESC: {
266 if (skb->len > ATHDESC_HEADER_SIZE) {
267 struct ar5212_openbsd_desc *desc =
268 (struct ar5212_openbsd_desc *)(skb->data + 8);
269 ph->power = desc->xmit_power;
270 ph->rate[0] = ratecode_to_dot11(desc->xmit_rate0);
271 ph->rate[1] = ratecode_to_dot11(desc->xmit_rate1);
272 ph->rate[2] = ratecode_to_dot11(desc->xmit_rate2);
273 ph->rate[3] = ratecode_to_dot11(desc->xmit_rate3);
274 ph->try[0] = desc->xmit_tries0;
275 ph->try[1] = desc->xmit_tries1;
276 ph->try[2] = desc->xmit_tries2;
277 ph->try[3] = desc->xmit_tries3;
278 skb_pull(skb, ATHDESC_HEADER_SIZE);
280 break;
282 default:
283 break;
286 if (!ph->rate[0]) {
287 ph->rate[0] = 0;
288 ph->try[0] = 11;
291 EXPORT_SYMBOL(ieee80211_monitor_encap);
294 * Context: softIRQ (tasklet)
296 void
297 ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb,
298 const struct ath_buf *bf, int tx, u_int64_t mactime, struct ath_softc *sc)
300 struct ieee80211vap *vap, *next;
301 struct ath_desc *ds = bf->bf_desc;
302 int noise = 0, antenna = 0, ieeerate = 0;
303 u_int32_t rssi = 0;
304 u_int8_t pkttype = 0;
306 if (tx) {
307 rssi = bf->bf_dsstatus.ds_txstat.ts_rssi;
308 antenna = bf->bf_dsstatus.ds_txstat.ts_antenna;
309 ieeerate = sc->sc_hwmap[bf->bf_dsstatus.ds_txstat.ts_rate].ieeerate;
310 } else {
311 rssi = bf->bf_dsstatus.ds_rxstat.rs_rssi;
312 antenna = bf->bf_dsstatus.ds_rxstat.rs_antenna;
313 ieeerate = sc->sc_hwmap[bf->bf_dsstatus.ds_rxstat.rs_rate].ieeerate;
316 noise = bf->bf_channoise;
318 /* XXX locking */
319 for (vap = TAILQ_FIRST(&ic->ic_vaps); vap != NULL; vap = next) {
320 struct sk_buff *skb1;
321 struct net_device *dev = vap->iv_dev;
322 struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
323 u_int8_t dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
325 next = TAILQ_NEXT(vap, iv_next);
326 /* If we have rx'd an error frame... */
327 if (!tx && bf->bf_dsstatus.ds_rxstat.rs_status != 0) {
329 /* Discard PHY errors if necessary */
330 if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_PHY) {
331 if (vap->iv_monitor_phy_errors == 0) continue;
334 /* Discard CRC errors if necessary */
335 if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_CRC) {
336 if (vap->iv_monitor_crc_errors == 0) continue;
339 /* Accept PHY, CRC and decrypt errors. Discard the rest. */
340 if (bf->bf_dsstatus.ds_rxstat.rs_status &~
341 (HAL_RXERR_DECRYPT | HAL_RXERR_MIC |
342 HAL_RXERR_PHY | HAL_RXERR_CRC))
343 continue;
345 /* We can't use addr1 to determine direction at this point */
346 pkttype = PACKET_HOST;
347 } else {
349 * The frame passed its CRC, so we can rely
350 * on the contents of the frame to set pkttype.
352 if (tx)
353 pkttype = PACKET_OUTGOING;
354 else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
355 if (IEEE80211_ADDR_EQ(wh->i_addr1, dev->broadcast))
356 pkttype = PACKET_BROADCAST;
357 else
358 pkttype = PACKET_MULTICAST;
359 } else
360 pkttype = PACKET_HOST;
363 if (vap->iv_opmode != IEEE80211_M_MONITOR ||
364 vap->iv_state != IEEE80211_S_RUN)
365 continue;
366 if (vap->iv_monitor_nods_only &&
367 dir != IEEE80211_FC1_DIR_NODS) {
368 /* don't rx fromds, tods, or dstods packets */
369 continue;
372 if (skb_headroom(skb) < IEEE80211_MON_MAXHDROOM)
373 skb1 = skb_copy_expand(skb, IEEE80211_MON_MAXHDROOM,
374 0, GFP_ATOMIC);
375 else
376 skb1 = skb_copy(skb, GFP_ATOMIC);
377 if (skb1 == NULL) {
378 /* XXX stat+msg */
379 continue;
381 ieee80211_skb_copy_noderef(skb, skb1);
383 if (vap->iv_monitor_txf_len && tx) {
384 /* truncate transmit feedback packets */
385 skb_trim(skb1, vap->iv_monitor_txf_len);
386 skb_reset_network_header(skb1);
388 switch (vap->iv_dev->type) {
389 case ARPHRD_IEEE80211:
390 break;
391 case ARPHRD_IEEE80211_PRISM: {
392 struct wlan_ng_prism2_header *ph;
393 if (skb_headroom(skb1) < sizeof(struct wlan_ng_prism2_header)) {
394 ieee80211_dev_kfree_skb(&skb1);
395 break;
398 ph = (struct wlan_ng_prism2_header *)
399 skb_push(skb1, sizeof(struct wlan_ng_prism2_header));
400 memset(ph, 0, sizeof(struct wlan_ng_prism2_header));
402 ph->msgcode = DIDmsg_lnxind_wlansniffrm;
403 ph->msglen = sizeof(struct wlan_ng_prism2_header);
404 strncpy(ph->devname, dev->name, sizeof(ph->devname));
406 ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
407 ph->hosttime.status = 0;
408 ph->hosttime.len = 4;
409 ph->hosttime.data = jiffies;
411 /* Pass up tsf clock in mactime */
412 /* NB: the prism mactime field is 32bit, so we lose TSF precision here */
413 ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
414 ph->mactime.status = 0;
415 ph->mactime.len = 4;
416 ph->mactime.data = mactime;
418 ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
419 ph->istx.status = 0;
420 ph->istx.len = 4;
421 ph->istx.data = tx ? P80211ENUM_truth_true : P80211ENUM_truth_false;
423 ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
424 ph->frmlen.status = 0;
425 ph->frmlen.len = 4;
426 ph->frmlen.data = skb->len;
428 ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
429 ph->channel.status = 0;
430 ph->channel.len = 4;
431 ph->channel.data =
432 ieee80211_mhz2ieee(ic->ic_curchan->ic_freq,
433 ic->ic_curchan->ic_flags);
435 ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
436 ph->rssi.status = 0;
437 ph->rssi.len = 4;
438 ph->rssi.data = rssi;
440 ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
441 ph->noise.status = 0;
442 ph->noise.len = 4;
443 ph->noise.data = noise;
445 ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
446 ph->signal.status = 0;
447 ph->signal.len = 4;
448 ph->signal.data = rssi + noise;
450 ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
451 ph->rate.status = 0;
452 ph->rate.len = 4;
453 ph->rate.data = ieeerate;
454 break;
456 case ARPHRD_IEEE80211_RADIOTAP: {
457 if (tx) {
458 struct ath_tx_radiotap_header *th;
459 if (skb_headroom(skb1) < sizeof(struct ath_tx_radiotap_header)) {
460 printk("%s:%d %s\n", __FILE__, __LINE__, __func__);
461 ieee80211_dev_kfree_skb(&skb1);
462 break;
465 th = (struct ath_tx_radiotap_header *)skb_push(skb1,
466 sizeof(struct ath_tx_radiotap_header));
467 memset(th, 0, sizeof(struct ath_tx_radiotap_header));
468 th->wt_ihdr.it_version = 0;
469 th->wt_ihdr.it_len = cpu_to_le16(sizeof(struct ath_tx_radiotap_header));
470 th->wt_ihdr.it_present = cpu_to_le32(ATH_TX_RADIOTAP_PRESENT);
472 /* radiotap's TSF field is the full 64 bits, so we don't lose
473 * any TSF precision when using radiotap */
474 th->wt_tsft = cpu_to_le64(mactime);
476 th->wt_flags = 0;
477 th->wt_rate = ieeerate;
478 th->wt_antenna = antenna;
479 th->wt_pad = 0;
481 if (bf->bf_dsstatus.ds_txstat.ts_status & HAL_TXERR_XRETRY)
482 th->wt_txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
484 th->wt_dataretries = bf->bf_dsstatus.ds_txstat.ts_shortretry + bf->bf_dsstatus.ds_txstat.ts_longretry;
486 } else {
487 struct ath_rx_radiotap_header *th;
488 if (skb_headroom(skb1) < sizeof(struct ath_rx_radiotap_header)) {
489 printk("%s:%d %s\n", __FILE__, __LINE__, __func__);
490 ieee80211_dev_kfree_skb(&skb1);
491 break;
494 th = (struct ath_rx_radiotap_header *)skb_push(skb1,
495 sizeof(struct ath_rx_radiotap_header));
496 memset(th, 0, sizeof(struct ath_rx_radiotap_header));
497 th->wr_ihdr.it_version = 0;
498 th->wr_ihdr.it_len = cpu_to_le16(sizeof(struct ath_rx_radiotap_header));
499 th->wr_ihdr.it_present = cpu_to_le32(ATH_RX_RADIOTAP_PRESENT);
501 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
502 th->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
503 if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_CRC)
504 th->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
505 if (skb->len >= IEEE80211_CRC_LEN)
506 th->wr_flags |= IEEE80211_RADIOTAP_F_FCS;
508 th->wr_rate = ieeerate;
509 th->wr_chan_freq = cpu_to_le16(ic->ic_curchan->ic_freq);
511 /* Define the channel flags for radiotap */
512 switch (sc->sc_curmode) {
513 case IEEE80211_MODE_11A:
514 th->wr_chan_flags =
515 cpu_to_le16(IEEE80211_CHAN_A);
516 break;
517 case IEEE80211_MODE_TURBO_A:
518 th->wr_chan_flags =
519 cpu_to_le16(IEEE80211_CHAN_TA);
520 break;
521 case IEEE80211_MODE_11B:
522 th->wr_chan_flags =
523 cpu_to_le16(IEEE80211_CHAN_B);
524 break;
525 case IEEE80211_MODE_11G:
526 th->wr_chan_flags =
527 cpu_to_le16(IEEE80211_CHAN_G);
528 break;
529 case IEEE80211_MODE_TURBO_G:
530 th->wr_chan_flags =
531 cpu_to_le16(IEEE80211_CHAN_TG);
532 break;
533 default:
534 th->wr_chan_flags = 0; /* unknown */
535 break;
538 th->wr_dbm_antnoise = (int8_t) noise;
539 th->wr_dbm_antsignal =
540 th->wr_dbm_antnoise + rssi;
541 th->wr_antenna = antenna;
542 th->wr_antsignal = rssi;
544 th->wr_tsft = cpu_to_le64(mactime);
546 break;
548 case ARPHRD_IEEE80211_ATHDESC: {
549 if (skb_headroom(skb1) < ATHDESC_HEADER_SIZE) {
550 printk("%s:%d %s\n", __FILE__,
551 __LINE__, __func__);
552 ieee80211_dev_kfree_skb(&skb1);
553 break;
555 memcpy(skb_push(skb1, ATHDESC_HEADER_SIZE),
556 ds, ATHDESC_HEADER_SIZE);
557 break;
559 default:
560 break;
562 if (skb1 != NULL) {
563 if (!tx && (skb1->len >= IEEE80211_CRC_LEN) &&
564 (vap->iv_dev->type !=
565 ARPHRD_IEEE80211_RADIOTAP)) {
566 /* Remove FCS from end of RX frames when
567 * delivering to non-Radiotap VAPs. */
568 skb_trim(skb1, skb1->len - IEEE80211_CRC_LEN);
570 skb1->dev = dev; /* NB: deliver to wlanX */
571 skb_reset_mac_header(skb1);
573 skb1->ip_summed = CHECKSUM_NONE;
574 skb1->pkt_type = pkttype;
575 skb1->protocol =
576 __constant_htons(0x0019); /* ETH_P_80211_RAW */
578 vap->iv_devstats.rx_packets++;
579 vap->iv_devstats.rx_bytes += skb1->len;
581 if (SKB_NI(skb1) != NULL)
582 ieee80211_unref_node(&SKB_NI(skb1));
583 if (netif_rx(skb1) == NET_RX_DROP)
584 vap->iv_devstats.rx_dropped++;
585 skb1 = NULL;
589 EXPORT_SYMBOL(ieee80211_input_monitor);