if_ath raw 802.11 packet injection patch when in monitor mode

Andrea Bittau <[email protected]>
Newsgroups gmane.os.freebsd.devel.mobile
Message-ID <[email protected]>
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 */
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mobile
To unsubscribe, send any mail to "[email protected]"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.