if_ath raw 802.11 packet injection patch when in monitor mode
Andrea Bittau
a.bittau at cs.ucl.ac.uk
Sat Jun 24 12:41:25 UTC 2006
I think it would be useful to have 802.11 packet injection support in the
mainstream driver. This would allow people, amongst other things, to run
user-land access points and clients. Below is a crude patch for doing so. The
only problem is that ACKs are not sent in time. I know a fix, but it's a bit of
a hack and a better solution is needed. I've tried contacting Sam but failed
[e-mail bounced]. Hopefully he will see this, and if he's interested, I could
make the patch better.
---
*** /sys/dev/ath/if_ath.c Tue May 2 18:08:34 2006
--- /root/programmi/ath/if_ath.c Sat Jun 24 13:11:10 2006
*************** ath_start(struct ifnet *ifp)
*** 1141,1146 ****
--- 1141,1147 ----
struct mbuf *m;
struct ieee80211_frame *wh;
struct ether_header *eh;
+ int monitor = ic->ic_opmode == IEEE80211_M_MONITOR;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
return;
*************** ath_start(struct ifnet *ifp)
*** 1191,1204 ****
* Find the node for the destination so we can do
* things like power save and fast frames aggregation.
*/
! if (m->m_len < sizeof(struct ether_header) &&
(m = m_pullup(m, sizeof(struct ether_header))) == NULL) {
ic->ic_stats.is_tx_nobuf++; /* XXX */
ni = NULL;
goto bad;
}
eh = mtod(m, struct ether_header *);
! ni = ieee80211_find_txnode(ic, eh->ether_dhost);
if (ni == NULL) {
/* NB: ieee80211_find_txnode does stat+msg */
m_freem(m);
--- 1192,1208 ----
* Find the node for the destination so we can do
* things like power save and fast frames aggregation.
*/
! if (!monitor && m->m_len < sizeof(struct ether_header) &&
(m = m_pullup(m, sizeof(struct ether_header))) == NULL) {
ic->ic_stats.is_tx_nobuf++; /* XXX */
ni = NULL;
goto bad;
}
eh = mtod(m, struct ether_header *);
! if (monitor)
! ni = ieee80211_ref_node(ic->ic_bss);
! else
! ni = ieee80211_find_txnode(ic, eh->ether_dhost);
if (ni == NULL) {
/* NB: ieee80211_find_txnode does stat+msg */
m_freem(m);
*************** ath_start(struct ifnet *ifp)
*** 1227,1239 ****
/*
* Encapsulate the packet in prep for transmission.
*/
! m = ieee80211_encap(ic, m, ni);
! if (m == NULL) {
! DPRINTF(sc, ATH_DEBUG_XMIT,
! "%s: encapsulation failure\n",
! __func__);
! sc->sc_stats.ast_tx_encap++;
! goto bad;
}
} else {
/*
--- 1231,1245 ----
/*
* Encapsulate the packet in prep for transmission.
*/
! if (!monitor) {
! m = ieee80211_encap(ic, m, ni);
! if (m == NULL) {
! DPRINTF(sc, ATH_DEBUG_XMIT,
! "%s: encapsulation failure\n",
! __func__);
! sc->sc_stats.ast_tx_encap++;
! goto bad;
! }
}
} else {
/*
*************** ath_calcrxfilter(struct ath_softc *sc, e
*** 1713,1718 ****
--- 1719,1726 ----
ic->ic_opmode == IEEE80211_M_IBSS ||
state == IEEE80211_S_SCAN)
rfilt |= HAL_RX_FILTER_BEACON;
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ rfilt |= HAL_RX_FILTER_CONTROL;
return rfilt;
#undef RX_FILTER_PRESERVE
}
*************** ath_tx_start(struct ath_softc *sc, struc
*** 3307,3312 ****
--- 3315,3321 ----
struct ath_node *an;
struct mbuf *m;
u_int pri;
+ int monitor = ic->ic_opmode == IEEE80211_M_MONITOR;
wh = mtod(m0, struct ieee80211_frame *);
iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
*************** ath_tx_start(struct ath_softc *sc, struc
*** 3317,3324 ****
* pad bytes; deduct them here.
*/
pktlen = m0->m_pkthdr.len - (hdrlen & 3);
!
! if (iswep) {
const struct ieee80211_cipher *cip;
struct ieee80211_key *k;
--- 3326,3343 ----
* pad bytes; deduct them here.
*/
pktlen = m0->m_pkthdr.len - (hdrlen & 3);
! /* ACK frames are shorter than Ethernet header, so userland needs to pad
! * ACKs with 4 bytes. We get rid of those bytes here.
! */
! if (monitor &&
! (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL &&
! (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
! IEEE80211_FC0_SUBTYPE_ACK) {
! m_adj(m0, -4);
! pktlen = m0->m_pkthdr.len;
! }
!
! if (iswep && !monitor) {
const struct ieee80211_cipher *cip;
struct ieee80211_key *k;
*************** ath_tx_start(struct ath_softc *sc, struc
*** 3522,3527 ****
--- 3541,3550 ----
}
txq = sc->sc_ac2q[pri];
+ /* Set packet type to PSPOLL so fragment & seqnos are not mangled */
+ if (monitor)
+ atype = HAL_PKT_TYPE_PSPOLL;
+
/*
* When servicing one or more stations in power-save mode
* multicast frames must be buffered until after the beacon.
*************** ath_tx_start(struct ath_softc *sc, struc
*** 3535,3541 ****
/*
* Calculate miscellaneous flags.
*/
! if (ismcast) {
flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
} else if (pktlen > ic->ic_rtsthreshold) {
flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */
--- 3558,3564 ----
/*
* Calculate miscellaneous flags.
*/
! if (ismcast || monitor) {
flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
} else if (pktlen > ic->ic_rtsthreshold) {
flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */
More information about the freebsd-mobile
mailing list