Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Jun 1999 18:53:02 -0700 (PDT)
From:      brooks@one-eyed-alien.net
To:        freebsd-hackers@freebsd.org
Subject:   changes to ether_output()
Message-ID:  <Pine.GSO.4.05.9906161832510.2401-100000@orion.ac.hmc.edu>

next in thread | raw e-mail | index | archive | help
Hi,

I've been doing some work which caused me to want to write a simple
userland bridging/filtering program (don't ask ;-).  The easy way to do it
seemed to be to use BPF to read and write the packets one each side.  I
wrote something up in a few hundred lines of code which worked (mostly) as
long as no one did much broadcast and I threw away multicast packets.  
After some searching I found a refrence in libnet (ports/net/libnet) which
said the problem was that while BPF takes a whole packet and claims to
write it to the wire, it actually ignores the source address and uses the
one assigned to the card.  They had an LKM which fixed the problem, but it
was based on a mid-1997 version of net/if_ethersubr.c from 2.2.x and had a
number of things commented out that probably shouldn't have been.

I've taken the key lines from the LKM and produced a patch which adds
optional support for for spoofing the source address of certain ethernet
packets.  It's a compile time option and is controled by a sysctl which
defaults to off and doesn't work in secure mode.  The patch is included
below.  The diff is against 3.2-STABLE as of a couple weeks ago and it
looks like part of it may have to be applyed by hand on -current.

Please let me know what you think.

-- Brooks

P.S. If someone is willing to commit this, I'll also create the
appropriate LINT entry to go with it.

*** net/if_ethersubr.c.orig	Tue Jun 15 18:46:10 1999
--- net/if_ethersubr.c	Wed Jun 16 18:21:42 1999
***************
*** 38,43 ****
--- 38,44 ----
  #include "opt_inet.h"
  #include "opt_ipx.h"
  #include "opt_bdg.h"
+ #include "opt_ether.h"
  
  #include <sys/param.h>
  #include <sys/systm.h>
***************
*** 111,116 ****
--- 112,125 ----
  #include <net/if_vlan_var.h>
  #endif /* NVLAN > 0 */
  
+ SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
+ 
+ #ifdef ETHER_SPOOF_SRC
+ static int spoof_src = 0; 
+ SYSCTL_INT(_net_link_ether, OID_AUTO, spoof_src, CTLFLAG_RW|CTLFLAG_SECURE,
+             &spoof_src, 0, "Allow Ethernet source addresses to be spoofed");
+ #endif
+ 
  static	int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, 
  				    struct sockaddr *));
  u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
***************
*** 133,138 ****
--- 142,150 ----
  	short type;
  	int s, error = 0;
   	u_char edst[6];
+ #ifdef ETHER_SPOOF_SRC
+ 	u_char esrc[6];
+ #endif
  	register struct mbuf *m = m0;
  	register struct rtentry *rt;
  	register struct ether_header *eh;
***************
*** 167,172 ****
--- 179,187 ----
  			    time_second < rt->rt_rmx.rmx_expire)
  				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  	}
+ #ifdef ETHER_SPOOF_SRC
+ 	(void)memcpy(esrc, ac->ac_enaddr, sizeof (esrc));
+ #endif
  	hlen = ETHER_HDR_LEN;
  	switch (dst->sa_family) {
  #ifdef INET
***************
*** 333,338 ****
--- 348,357 ----
  		loop_copy = -1; /* if this is for us, don't do it */
  		eh = (struct ether_header *)dst->sa_data;
   		(void)memcpy(edst, eh->ether_dhost, sizeof (edst));
+ #ifdef ETHER_SPOOF_SRC
+ 		if (spoof_src != 0)
+  			(void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
+ #endif
  		type = eh->ether_type;
  		break;
  
***************
*** 353,360 ****
--- 372,383 ----
  	(void)memcpy(&eh->ether_type, &type,
  		sizeof(eh->ether_type));
   	(void)memcpy(eh->ether_dhost, edst, sizeof (edst));
+ #ifdef ETHER_SPOOF_SRC
+  	(void)memcpy(eh->ether_shost, esrc, sizeof (esrc));
+ #else
   	(void)memcpy(eh->ether_shost, ac->ac_enaddr,
  	    sizeof(eh->ether_shost));
+ #endif
  
  	/*
  	 * If a simplex interface, and the packet is being sent to our
***************
*** 679,686 ****
  	sdl->sdl_alen = ifp->if_addrlen;
  	bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
  }
- 
- SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
  
  int
  ether_ioctl(ifp, command, data)
--- 702,707 ----
*** conf/options.orig	Fri May 21 15:45:39 1999
--- conf/options	Wed Jun 16 18:19:51 1999
***************
*** 221,226 ****
--- 221,227 ----
  IPFILTER		opt_ipfilter.h
  IPFILTER_LOG		opt_ipfilter.h
  IPFILTER_LKM		opt_ipfilter.h
+ ETHER_SPOOF_SRC		opt_ether.h
  
  # ATM (HARP version)
  ATM_CORE		opt_atm.h



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.05.9906161832510.2401-100000>