[Madwifi-cvs] revision 1290 committed by jbicket
Status: Beta
Brought to you by:
otaku
From: jbicket <svn...@ma...> - 2005-11-04 20:11:10
|
Project : madwifi Revision : 1290 Author : jbicket Date : 2005-11-04 21:10:56 +0100 (Fri, 04 Nov 2005) Log Message : ticket #20. allow additional monitor mode dev->types, for instance radiotap headers. Also add /proc/sys/net/athX/dev_type so you can change it: jbicket@sled>cat /proc/sys/net/ath0/dev_type 1 Affected Files: * trunk/ath/if_ath.c updated * trunk/net80211/Makefile updated * trunk/net80211/ieee80211_linux.c updated * trunk/net80211/ieee80211_linux.h updated * trunk/net80211/ieee80211_monitor.c added * trunk/net80211/ieee80211_monitor.h added * trunk/net80211/ieee80211_output.c updated Modified: trunk/ath/if_ath.c =================================================================== --- trunk/ath/if_ath.c 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/ath/if_ath.c 2005-11-04 20:10:56 UTC (rev 1290) @@ -66,6 +66,7 @@ #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_monitor.h> #ifdef USE_HEADERLEN_RESV #include <net80211/if_llc.h> @@ -2098,106 +2099,128 @@ sc->sc_devstats.tx_bytes += framelen; } +static int +dot11_to_ratecode(struct ath_softc *sc, const HAL_RATE_TABLE *rt, int dot11) { + int index = sc->sc_rixmap[dot11 & IEEE80211_RATE_VAL]; + if (index >= 0 && index < rt->rateCount) { + return rt->info[index].rateCode; + } + return rt->info[sc->sc_minrateix].rateCode; +} + + int ath_tx_startraw(struct net_device *dev, struct ath_buf *bf, struct sk_buff *skb) { - struct ath_softc *sc = dev->priv; + struct ath_softc *sc = dev->priv; struct ath_hal *ah = sc->sc_ah; - const HAL_RATE_TABLE *rt; - int pktlen; - int hdrlen; - HAL_PKT_TYPE atype; - u_int flags; - int keyix; - int try0; - u_int8_t antenna, txrate; - struct ath_txq *txq=NULL; - struct ath_desc *ds=NULL; - struct ieee80211_frame *wh; - - wh = (struct ieee80211_frame *) skb->data; - try0 = ATH_TXMAXTRY; - rt = sc->sc_currates; - txrate = rt->info[sc->sc_minrateix].rateCode; - hdrlen = ieee80211_anyhdrsize(wh); - pktlen = skb->len + IEEE80211_CRC_LEN; - - keyix = HAL_TXKEYIX_INVALID; - flags = HAL_TXDESC_INTREQ | HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ - - bf->bf_skbaddr = bus_map_single(sc->sc_bdev, - skb->data, pktlen, BUS_DMA_TODEVICE); - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: skb %p [data %p len %u] skbaddr %llx\n", - __func__, skb, skb->data, skb->len, ito64(bf->bf_skbaddr)); - - - bf->bf_skb = skb; - bf->bf_node = NULL; - + struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *) (skb->cb + sizeof(struct ieee80211_cb)); + const HAL_RATE_TABLE *rt; + int pktlen; + int hdrlen; + HAL_PKT_TYPE atype; + u_int flags; + int keyix; + int try0; + int power; + u_int8_t antenna, txrate; + struct ath_txq *txq=NULL; + struct ath_desc *ds=NULL; + struct ieee80211_frame *wh; + + wh = (struct ieee80211_frame *) skb->data; + try0 = ATH_TXMAXTRY; + rt = sc->sc_currates; + txrate = dot11_to_ratecode(sc, rt, ph->rate0); + power = ph->power > 60 ? 60 : ph->power; + hdrlen = ieee80211_anyhdrsize(wh); + pktlen = skb->len + IEEE80211_CRC_LEN; + + keyix = HAL_TXKEYIX_INVALID; + flags = HAL_TXDESC_INTREQ | HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ + + bf->bf_skbaddr = bus_map_single(sc->sc_bdev, + skb->data, pktlen, BUS_DMA_TODEVICE); + DPRINTF(sc, ATH_DEBUG_XMIT, "%s: skb %p [data %p len %u] skbaddr %llx\n", + __func__, skb, skb->data, skb->len, ito64(bf->bf_skbaddr)); + + + bf->bf_skb = skb; + bf->bf_node = NULL; + #ifdef ATH_SUPERG_FF - bf->bf_numdesc = 1; + bf->bf_numdesc = 1; #endif - - /* setup descriptors */ - ds = bf->bf_desc; - rt = sc->sc_currates; - KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); - + + /* setup descriptors */ + ds = bf->bf_desc; + rt = sc->sc_currates; + KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); + + + if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { + flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */ + sc->sc_stats.ast_tx_noack++; + try0 = 1; + } + atype = HAL_PKT_TYPE_NORMAL; /* default */ + txq = sc->sc_ac2q[skb->priority & 0x3]; + + + flags |= HAL_TXDESC_INTREQ; + antenna = sc->sc_txantenna; + + /* XXX check return value? */ + ath_hal_setuptxdesc(ah, ds + , pktlen /* packet length */ + , hdrlen /* header length */ + , atype /* Atheros packet type */ + , power /* txpower */ + , txrate, try0 /* series 0 rate/tries */ + , keyix /* key cache index */ + , antenna /* antenna mode */ + , flags /* flags */ + , 0 /* rts/cts rate */ + , 0 /* rts/cts duration */ + , 0 /* comp icv len */ + , 0 /* comp iv len */ + , ATH_COMP_PROC_NO_COMP_NO_CCS /* comp scheme */ + ); - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */ - sc->sc_stats.ast_tx_noack++; - } - atype = HAL_PKT_TYPE_NORMAL; /* default */ - txq = sc->sc_ac2q[skb->priority & 0x3]; - - flags |= HAL_TXDESC_INTREQ; - antenna = sc->sc_txantenna; - - /* XXX check return value? */ - ath_hal_setuptxdesc(ah, ds - , pktlen /* packet length */ - , hdrlen /* header length */ - , atype /* Atheros packet type */ - , 60 /* txpower */ - , txrate, try0 /* series 0 rate/tries */ - , keyix /* key cache index */ - , antenna /* antenna mode */ - , flags /* flags */ - , 0 /* rts/cts rate */ - , 0 /* rts/cts duration */ - , 0 /* comp icv len */ - , 0 /* comp iv len */ - , ATH_COMP_PROC_NO_COMP_NO_CCS /* comp scheme */ - ); - - bf->bf_flags = flags; /* record for post-processing */ - - - ds->ds_link = 0; - ds->ds_data = bf->bf_skbaddr; - - ath_hal_filltxdesc(ah, ds - , skb->len /* segment length */ - , AH_TRUE /* first segment */ - , AH_TRUE /* last segment */ - , ds /* first descriptor */ - ); - - /* NB: The desc swap function becomes void, - * if descriptor swapping is not enabled - */ - ath_desc_swap(ds); - - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: Q%d: %08x %08x %08x %08x %08x %08x\n", - __func__, M_FLAG_GET(skb, M_UAPSD) ? 0 : txq->axq_qnum, ds->ds_link, ds->ds_data, - ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]); - - - - ath_tx_txqaddbuf(sc, NULL, txq, bf, ds, pktlen); - return 0; + if (ph->try1) { + ath_hal_setupxtxdesc(sc->sc_ah, ds + , dot11_to_ratecode(sc, rt, ph->rate1), ph->try1 /* series 1 */ + , dot11_to_ratecode(sc, rt, ph->rate2), ph->try2 /* series 2 */ + , dot11_to_ratecode(sc, rt, ph->rate3), ph->try3 /* series 3 */ + ); + } + bf->bf_flags = flags; /* record for post-processing */ + + + ds->ds_link = 0; + ds->ds_data = bf->bf_skbaddr; + + ath_hal_filltxdesc(ah, ds + , skb->len /* segment length */ + , AH_TRUE /* first segment */ + , AH_TRUE /* last segment */ + , ds /* first descriptor */ + ); + + /* NB: The desc swap function becomes void, + * if descriptor swapping is not enabled + */ + ath_desc_swap(ds); + + DPRINTF(sc, ATH_DEBUG_XMIT, "%s: Q%d: %08x %08x %08x %08x %08x %08x\n", + __func__, M_FLAG_GET(skb, M_UAPSD) ? 0 : txq->axq_qnum, ds->ds_link, ds->ds_data, + ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]); + + + + ath_tx_txqaddbuf(sc, NULL, txq, bf, ds, pktlen); + return 0; } #ifdef ATH_SUPERG_FF Modified: trunk/net80211/Makefile =================================================================== --- trunk/net80211/Makefile 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/net80211/Makefile 2005-11-04 20:10:56 UTC (rev 1290) @@ -71,7 +71,8 @@ ieee80211.o ieee80211_beacon.o ieee80211_crypto.o \ ieee80211_crypto_none.o ieee80211_input.o ieee80211_node.o \ ieee80211_output.o ieee80211_power.o ieee80211_proto.o \ - ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o + ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o \ + ieee80211_monitor.o wlan_wep-objs := ieee80211_crypto_wep.o wlan_tkip-objs := ieee80211_crypto_tkip.o wlan_ccmp-objs := ieee80211_crypto_ccmp.o @@ -88,7 +89,7 @@ ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o \ ieee80211_crypto_wep.o ieee80211_crypto_tkip.o \ ieee80211_crypto_ccmp.o ieee80211_xauth.o \ - ieee80211_scan_sta.o ieee80211_scan_ap.o + ieee80211_monitor.o ieee80211_scan_sta.o ieee80211_scan_ap.o list-multi := $(MOD_INSTALL) endif Modified: trunk/net80211/ieee80211_linux.c =================================================================== --- trunk/net80211/ieee80211_linux.c 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/net80211/ieee80211_linux.c 2005-11-04 20:10:56 UTC (rev 1290) @@ -52,6 +52,7 @@ #include "if_ethersubr.h" #include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_monitor.h> /* * Print a console message with the device name prepended. @@ -324,6 +325,34 @@ } #endif /* IEEE80211_DEBUG */ +static int +IEEE80211_SYSCTL_DECL(ieee80211_sysctl_dev_type, ctl, write, filp, buffer, + lenp, ppos) +{ + struct ieee80211vap *vap = ctl->extra1; + u_int val; + int ret; + + ctl->data = &val; + ctl->maxlen = sizeof(val); + if (write) { + ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, + lenp, ppos); + if (ret == 0 && vap->iv_opmode == IEEE80211_M_MONITOR) { + if (val == ARPHRD_IEEE80211_RADIOTAP || + val == ARPHRD_IEEE80211 || + val == ARPHRD_IEEE80211_PRISM) { + vap->iv_dev->type = val; + } + } + } else { + val = vap->iv_dev->type; + ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, + lenp, ppos); + } + return ret; +} + #define CTL_AUTO -2 /* cannot be CTL_ANY or CTL_NONE */ static const ctl_table ieee80211_sysctl_template[] = { @@ -334,6 +363,11 @@ .proc_handler = ieee80211_sysctl_debug }, #endif + { .ctl_name = CTL_AUTO, + .procname = "dev_type", + .mode = 0644, + .proc_handler = ieee80211_sysctl_dev_type + }, /* NB: must be last entry before NULL */ { .ctl_name = CTL_AUTO, .procname = "%parent", @@ -416,112 +450,6 @@ } EXPORT_SYMBOL(ether_sprintf); /* XXX */ -enum { - DIDmsg_lnxind_wlansniffrm = 0x00000044, - DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, - DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, - DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, - DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, - DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, - DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, - DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, - DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, - DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, - DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 -}; -enum { - P80211ENUM_msgitem_status_no_value = 0x00 -}; -enum { - P80211ENUM_truth_false = 0x00 -}; - -void -ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb, - u_int32_t mactime, u_int32_t rssi, u_int32_t signal, u_int32_t rate) -{ - static const wlan_ng_prism2_header template = { - .msgcode = DIDmsg_lnxind_wlansniffrm, - .msglen = sizeof(wlan_ng_prism2_header), - - .hosttime = { .did = DIDmsg_lnxind_wlansniffrm_hosttime, - .len = 4}, - - .mactime = { .did = DIDmsg_lnxind_wlansniffrm_mactime, - .len = 4}, - - .istx = { .did = DIDmsg_lnxind_wlansniffrm_istx, - .len = 4, - .data = P80211ENUM_truth_false}, - - .frmlen = { .did = DIDmsg_lnxind_wlansniffrm_frmlen, - .len = 4}, - - .channel = { .did = DIDmsg_lnxind_wlansniffrm_channel, - .len = 4}, - - .rssi = { .did = DIDmsg_lnxind_wlansniffrm_rssi, - .status = P80211ENUM_msgitem_status_no_value, - .len = 4}, - - .signal = { .did = DIDmsg_lnxind_wlansniffrm_signal, - .len = 4}, - - .rate = { .did = DIDmsg_lnxind_wlansniffrm_rate, - .len = 4}, - }; - struct ieee80211vap *vap, *next; - /* XXX locking */ - for (vap = TAILQ_FIRST(&ic->ic_vaps); vap != NULL; vap = next) { - struct sk_buff *skb1; - struct net_device *dev = vap->iv_dev; - wlan_ng_prism2_header *ph; - next = TAILQ_NEXT(vap, iv_next); - if (vap->iv_opmode != IEEE80211_M_MONITOR || - vap->iv_state != IEEE80211_S_RUN) - continue; - - skb1 = skb_copy(skb, GFP_ATOMIC); - if (skb1 == NULL) { - /* XXX stat+msg */ - continue; - } - if (skb_headroom(skb1) < sizeof(wlan_ng_prism2_header)) { - dev_kfree_skb(skb1); - return; - } - - ph = (wlan_ng_prism2_header *) - skb_push(skb1, sizeof(wlan_ng_prism2_header)); - *ph = template; - - ph->hosttime.data = jiffies; - ph->mactime.data = mactime; - ph->frmlen.data = skb->len - sizeof(wlan_ng_prism2_header); - /* XXX no way to pass channel flag state */ - ph->channel.data = ieee80211_chan2ieee(ic, ic->ic_curchan); - ph->rssi.data = rssi; - ph->signal.data = signal; - ph->rate.data = rate; - - - - strncpy(ph->devname, dev->name, sizeof(ph->devname)); - - skb1->dev = dev; /* NB: deliver to wlanX */ - skb1->mac.raw = skb1->data; - skb1->ip_summed = CHECKSUM_NONE; - skb1->pkt_type = PACKET_OTHERHOST; - skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ - - netif_rx(skb1); - - vap->iv_devstats.rx_packets++; - vap->iv_devstats.rx_bytes += skb1->len; - } -} -EXPORT_SYMBOL(ieee80211_input_monitor); - /* * Module glue. */ Modified: trunk/net80211/ieee80211_linux.h =================================================================== --- trunk/net80211/ieee80211_linux.h 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/net80211/ieee80211_linux.h 2005-11-04 20:10:56 UTC (rev 1290) @@ -228,6 +228,7 @@ struct sk_buff *next; /* fast frame sk_buf chain */ }; + #define M_FLAG_SET(_skb, _flag) \ (((struct ieee80211_cb *)(_skb)->cb)->flags |= (_flag)) #define M_FLAG_CLR(_skb, _flag) \ @@ -461,12 +462,4 @@ p80211item_uint32_t frmlen; } wlan_ng_prism2_header; -/* - * Dispatch an skb to monitor-mode vap's. The skb is assumed - * to have space at the front to push a wlan_ng_prims2_header. - */ -void ieee80211_input_monitor(struct ieee80211com *, struct sk_buff *, - u_int32_t mactime, u_int32_t rssi, u_int32_t signal, - u_int32_t rate); - #endif /* _NET80211_IEEE80211_LINUX_H_ */ Added: trunk/net80211/ieee80211_monitor.c =================================================================== --- trunk/net80211/ieee80211_monitor.c 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/net80211/ieee80211_monitor.c 2005-11-04 20:10:56 UTC (rev 1290) @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2005 John Bicket + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif + +/* + * IEEE 802.11 monitor mode + */ +#include <linux/config.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kmod.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/sysctl.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/if_vlan.h> + +#include <net/iw_handler.h> +#include <linux/wireless.h> +#include <linux/if_arp.h> /* XXX for ARPHRD_* */ + +#include <asm/uaccess.h> + +#include "if_media.h" +#include "if_ethersubr.h" + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_monitor.h> +enum { + DIDmsg_lnxind_wlansniffrm = 0x00000044, + DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, + DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, + DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, + DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, + DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, + DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, + DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, + DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, + DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, + DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 +}; +enum { + P80211ENUM_msgitem_status_no_value = 0x00 +}; +enum { + P80211ENUM_truth_false = 0x00 +}; + + +void +ieee80211_monitor_encap(struct ieee80211com *ic, struct sk_buff *skb) +{ + struct ieee80211_cb *cb = (struct ieee80211_cb *) skb->cb; + struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *) (skb->cb + sizeof(struct ieee80211_cb)); + cb = (struct ieee80211_cb *) skb->cb; + cb->flags = M_RAW; + cb->ni = NULL; + cb->next = NULL; + memset(ph, 0, sizeof(struct ieee80211_phy_params)); + + /* defaults */ + ph->rate0 = 2; + ph->try0 = 11; + ph->power = 60; + + switch (skb->dev->type) { + case ARPHRD_IEEE80211: break; + case ARPHRD_IEEE80211_PRISM: { + wlan_ng_prism2_header *wh = NULL; + wh = (wlan_ng_prism2_header *) skb->data; + /* does it look like there is a prism header here? */ + if (skb->len > sizeof (wlan_ng_prism2_header) && + wh->msgcode == DIDmsg_lnxind_wlansniffrm && + wh->rate.did == DIDmsg_lnxind_wlansniffrm_rate) { + ph->rate0 = wh->rate.data; + skb_pull(skb, sizeof(wlan_ng_prism2_header)); + } + break; + } + + default: break; + } + + if (!ph->rate0) { + ph->rate0 = 0; + ph->try0 = 11; + } +} +EXPORT_SYMBOL(ieee80211_monitor_encap); + +void +ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb, + u_int32_t mactime, u_int32_t rssi, u_int32_t signal, u_int32_t rate) +{ + static const wlan_ng_prism2_header template = { + .msgcode = DIDmsg_lnxind_wlansniffrm, + .msglen = sizeof(wlan_ng_prism2_header), + + .hosttime = { .did = DIDmsg_lnxind_wlansniffrm_hosttime, + .len = 4}, + + .mactime = { .did = DIDmsg_lnxind_wlansniffrm_mactime, + .len = 4}, + + .istx = { .did = DIDmsg_lnxind_wlansniffrm_istx, + .len = 4, + .data = P80211ENUM_truth_false}, + + .frmlen = { .did = DIDmsg_lnxind_wlansniffrm_frmlen, + .len = 4}, + + .channel = { .did = DIDmsg_lnxind_wlansniffrm_channel, + .len = 4}, + + .rssi = { .did = DIDmsg_lnxind_wlansniffrm_rssi, + .status = P80211ENUM_msgitem_status_no_value, + .len = 4}, + + .signal = { .did = DIDmsg_lnxind_wlansniffrm_signal, + .len = 4}, + + .rate = { .did = DIDmsg_lnxind_wlansniffrm_rate, + .len = 4}, + }; + struct ieee80211vap *vap, *next; + /* XXX locking */ + for (vap = TAILQ_FIRST(&ic->ic_vaps); vap != NULL; vap = next) { + struct sk_buff *skb1; + struct net_device *dev = vap->iv_dev; + wlan_ng_prism2_header *ph; + next = TAILQ_NEXT(vap, iv_next); + if (vap->iv_opmode != IEEE80211_M_MONITOR || + vap->iv_state != IEEE80211_S_RUN) + continue; + + skb1 = skb_copy(skb, GFP_ATOMIC); + if (skb1 == NULL) { + /* XXX stat+msg */ + continue; + } + if (skb_headroom(skb1) < sizeof(wlan_ng_prism2_header)) { + dev_kfree_skb(skb1); + return; + } + + ph = (wlan_ng_prism2_header *) + skb_push(skb1, sizeof(wlan_ng_prism2_header)); + *ph = template; + + ph->hosttime.data = jiffies; + ph->mactime.data = mactime; + ph->frmlen.data = skb->len - sizeof(wlan_ng_prism2_header); + /* XXX no way to pass channel flag state */ + ph->channel.data = ieee80211_chan2ieee(ic, ic->ic_curchan); + ph->rssi.data = rssi; + ph->signal.data = signal; + ph->rate.data = rate; + + + + strncpy(ph->devname, dev->name, sizeof(ph->devname)); + + skb1->dev = dev; /* NB: deliver to wlanX */ + skb1->mac.raw = skb1->data; + skb1->ip_summed = CHECKSUM_NONE; + skb1->pkt_type = PACKET_OTHERHOST; + skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ + + netif_rx(skb1); + + vap->iv_devstats.rx_packets++; + vap->iv_devstats.rx_bytes += skb1->len; + } +} +EXPORT_SYMBOL(ieee80211_input_monitor); + Added: trunk/net80211/ieee80211_monitor.h =================================================================== --- trunk/net80211/ieee80211_monitor.h 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/net80211/ieee80211_monitor.h 2005-11-04 20:10:56 UTC (rev 1290) @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2005 John Bicket + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _NET80211_IEEE80211_MONITOR_H_ +#define _NET80211_IEEE80211_MONITOR_H_ + + +#ifndef ARPHRD_IEEE80211_RADIOTAP +#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ +#endif /* ARPHRD_IEEE80211_RADIOTAP */ + +struct ieee80211_phy_params { + u_int8_t rate0; + u_int8_t rate1; + u_int8_t rate2; + u_int8_t rate3; + + u_int8_t try0; + u_int8_t try1; + u_int8_t try2; + u_int8_t try3; + + u_int8_t power; + u_int32_t flags; +}; + +/* + * Dispatch an skb to monitor-mode vap's. The skb is assumed + * to have space at the front to push a wlan_ng_prims2_header. + */ +void ieee80211_input_monitor(struct ieee80211com *, struct sk_buff *, + u_int32_t mactime, u_int32_t rssi, u_int32_t signal, + u_int32_t rate); + + +void ieee80211_monitor_encap(struct ieee80211com *ic, struct sk_buff *skb); + + +#endif /* _NET80211_IEEE80211_MONITOR_H_ */ Modified: trunk/net80211/ieee80211_output.c =================================================================== --- trunk/net80211/ieee80211_output.c 2005-11-04 11:39:56 UTC (rev 1289) +++ trunk/net80211/ieee80211_output.c 2005-11-04 20:10:56 UTC (rev 1290) @@ -52,6 +52,7 @@ #include "if_media.h" #include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_monitor.h> #include <net80211/if_athproto.h> #ifdef IEEE80211_DEBUG @@ -221,11 +222,8 @@ } if (vap->iv_opmode == IEEE80211_M_MONITOR) { - cb = (struct ieee80211_cb *) skb->cb; - cb->flags = M_RAW; - cb->ni = ni; - cb->next = NULL; - skb->dev = parent; + ieee80211_monitor_encap(ic, skb); + skb->dev = parent; (void) dev_queue_xmit(skb); return 0; } |