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 majord...@freebsd.org
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to