Date: Sat, 24 Jun 2006 13:41:11 +0100 From: Andrea Bittau <a.bittau@cs.ucl.ac.uk> To: freebsd-mobile@freebsd.org Subject: if_ath raw 802.11 packet injection patch when in monitor mode Message-ID: <20060624124111.GA26914@shorty.sorbonet.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060624124111.GA26914>