From owner-freebsd-mobile@FreeBSD.ORG Sat Jun 24 12:41:25 2006 Return-Path: X-Original-To: freebsd-mobile@freebsd.org Delivered-To: freebsd-mobile@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BEC9716A492 for ; Sat, 24 Jun 2006 12:41:25 +0000 (UTC) (envelope-from a.bittau@cs.ucl.ac.uk) Received: from darkircop.org (tapir.cs.ucl.ac.uk [128.16.66.93]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3225043D58 for ; Sat, 24 Jun 2006 12:41:24 +0000 (GMT) (envelope-from a.bittau@cs.ucl.ac.uk) Received: by darkircop.org (Postfix, from userid 0) id ACCAB8615C8; Sat, 24 Jun 2006 13:41:11 +0100 (BST) Date: Sat, 24 Jun 2006 13:41:11 +0100 From: Andrea Bittau To: freebsd-mobile@freebsd.org Message-ID: <20060624124111.GA26914@shorty.sorbonet.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.1i X-Echelon: Bush Bomb War KGB Subject: if_ath raw 802.11 packet injection patch when in monitor mode X-BeenThere: freebsd-mobile@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Mobile computing with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Jun 2006 12:41:25 -0000 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 */