--- ./sys/net/if_bridge.c.orig	2004-10-08 05:11:13.000000000 +0200
+++ ./sys/net/if_bridge.c	2004-12-29 16:30:16.000000000 +0100
@@ -86,6 +86,7 @@
 #include "opt_inet.h"
 #include "opt_pfil_hooks.h"
 #include "bpfilter.h"
+#include "gif.h"
 
 #include <sys/param.h> 
 #include <sys/kernel.h>
@@ -575,6 +576,9 @@
 		 * Take the interface out of promiscuous mode.
 		 */
 		(void) ifpromisc(ifs, 0);
+#if NGIF > 0
+	case IFT_GIF:
+#endif
 		break;
 
 	default:
@@ -628,6 +632,9 @@
 		error = ifpromisc(ifs, 1);
 		if (error)
 			goto out;
+#if NGIF > 0
+	case IFT_GIF:
+#endif
 		break;
 
 	default:
@@ -1153,6 +1160,7 @@
 #endif /* ALTQ */
 
 	len = m->m_pkthdr.len;
+	m->m_flags |= M_PROTO1;
 	mflags = m->m_flags;
 	IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error);
 	if (error) {
@@ -1476,6 +1484,20 @@
 			return (m);
 
 		/* Perform the bridge forwarding function with the copy. */
+#if NGIF > 0
+		if (ifp->if_type == IFT_GIF) {
+			LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
+				if (bif->bif_ifp->if_type == IFT_ETHER)
+				break;
+			}
+			if (bif != NULL) {
+				m->m_flags |= M_PROTO1;
+				m->m_pkthdr.rcvif = bif->bif_ifp;
+				(bif->bif_ifp->if_input)(bif->bif_ifp, m);
+				m = NULL;
+			}
+		}
+#endif
 		bridge_forward(sc, mc);
 
 		/* Return the original packet for local processing. */
@@ -1495,6 +1517,8 @@
 	 * Unicast.  Make sure it's not for us.
 	 */
 	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
+		if(bif->bif_ifp->if_type != IFT_ETHER)
+			continue;
 		/* It is destined for us. */
 		if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
 		    ETHER_ADDR_LEN) == 0) {
@@ -1502,6 +1526,14 @@
 				(void) bridge_rtupdate(sc,
 				    eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
 			m->m_pkthdr.rcvif = bif->bif_ifp;
+#if NGIF > 0
+			if (ifp->if_type == IFT_GIF) {
+				m->m_flags |= M_PROTO1;
+				m->m_pkthdr.rcvif = bif->bif_ifp;
+				(bif->bif_ifp->if_input)(bif->bif_ifp, m);
+				m = NULL;
+			}
+#endif
 			return (m);
 		}
 
--- ./sys/net/if_ethersubr.c.orig	2004-12-29 16:23:26.000000000 +0100
+++ ./sys/net/if_ethersubr.c	2004-12-29 16:27:01.000000000 +0100
@@ -725,18 +725,22 @@
 	 * process it locally.
 	 */
 	if (ifp->if_bridge) {
-		/* clear M_PROMISC, in case the packets comes from a vlan */
-		m->m_flags &= ~M_PROMISC;
-		m = bridge_input(ifp, m);
-		if (m == NULL)
-			return;
+		if(m->m_flags & M_PROTO1) {
+			m->m_flags &= ~M_PROTO1;
+		} else {
+			/* clear M_PROMISC, in case the packets comes from a vlan */
+			m->m_flags &= ~M_PROMISC;
+			m = bridge_input(ifp, m);
+			if (m == NULL)
+				return;
 
-		/*
-		 * Bridge has determined that the packet is for us.
-		 * Update our interface pointer -- we may have had
-		 * to "bridge" the packet locally.
-		 */
-		ifp = m->m_pkthdr.rcvif;
+			/*
+			 * Bridge has determined that the packet is for us.
+			 * Update our interface pointer -- we may have had
+			 * to "bridge" the packet locally.
+			 */
+			ifp = m->m_pkthdr.rcvif;
+		}
 	} else 
 #endif /* NBRIDGE > 0 */
 	{
--- ./sys/net/if_gif.c.orig	2004-12-29 16:23:13.000000000 +0100
+++ ./sys/net/if_gif.c	2004-12-29 16:35:40.000000000 +0100
@@ -82,9 +82,12 @@
 #endif
 
 #include <netinet/ip_encap.h>
+#include <net/if_ether.h>
+#include <net/if_bridgevar.h>
 #include <net/if_gif.h>
 
 #include "bpfilter.h"
+#include "bridge.h"
 
 #include <net/net_osdep.h>
 
@@ -93,6 +96,7 @@
 void gifnetisr __P((void));
 #endif
 void gifintr __P((void *));
+void gif_start __P((struct ifnet *));
 #ifdef ISO
 static struct mbuf *gif_eon_encap __P((struct mbuf *));
 static struct mbuf *gif_eon_decap __P((struct ifnet *, struct mbuf *));
@@ -162,6 +166,7 @@
 	sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
 	sc->gif_if.if_ioctl  = gif_ioctl;
 	sc->gif_if.if_output = gif_output;
+	sc->gif_if.if_start  = gif_start;
 	sc->gif_if.if_type   = IFT_GIF;
 	sc->gif_if.if_dlt    = DLT_NULL;
 	IFQ_SET_READY(&sc->gif_if.if_snd);
@@ -195,6 +200,18 @@
 	free(sc, M_DEVBUF);
 }
 
+void
+gif_start(ifp)
+	struct ifnet *ifp;
+{
+#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
+	softintr_schedule(((struct gif_softc*)ifp)->gif_si);
+#else
+	/* XXX bad spl level? */
+	gifnetisr();
+#endif
+}
+
 #ifdef GIF_ENCAPCHECK
 int
 gif_encapcheck(m, off, proto, arg)
@@ -230,6 +247,10 @@
 	case IPPROTO_EON:
 		break;
 #endif
+#if NBRIDGE > 0
+	case IPPROTO_ETHERIP:
+		break;
+#endif
 	default:
 		return 0;
 	}
@@ -388,6 +409,17 @@
 		if (m == NULL)
 			break;
 
+#if NBRIDGE > 0
+		if(m->m_flags & M_PROTO1) {
+			M_PREPEND(m, sizeof(int), M_DONTWAIT);
+			if (!m) {
+				ifp->if_oerrors++;				
+				continue;
+			}
+			*mtod(m, int *) = AF_LINK;
+		}
+			
+#endif
 		/* grab and chop off inner af type */
 		if (sizeof(int) > m->m_len) {
 			m = m_pullup(m, sizeof(int));
@@ -445,6 +477,7 @@
 {
 	int s, isr;
 	struct ifqueue *ifq = NULL;
+	struct ether_header *eh;
 
 	if (ifp == NULL) {
 		/* just in case */
@@ -511,6 +544,37 @@
 		isr = NETISR_ISO;
 		break;
 #endif
+#if NBRIDGE > 0
+	case AF_LINK:
+		m_adj(m, sizeof(struct etherip_header));
+		if (sizeof(struct ether_header) > m->m_len) {
+			m = m_pullup(m, sizeof(struct ether_header));
+			if (!m) {
+				ifp->if_ierrors++;
+				return;
+			}
+		}
+		eh = mtod(m, struct ether_header *); 	
+		m->m_flags &= ~(M_BCAST|M_MCAST);
+		if (eh->ether_dhost[0] & 1) {
+			if (bcmp((caddr_t) etherbroadcastaddr,
+			    (caddr_t)eh->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
+				m->m_flags |= M_BCAST;
+			else
+				m->m_flags |= M_MCAST;
+		}
+		m->m_pkthdr.rcvif = ifp;
+		if(ifp->if_bridge) {
+			if (m->m_flags & (M_BCAST|M_MCAST))
+				ifp->if_imcasts++;
+
+			s = splnet();
+			m = bridge_input(ifp, m);
+			splx(s);
+			if (m == NULL)
+				return;
+		}
+#endif
 	default:
 		m_freem(m);
 		return;
--- ./sys/netinet/in.h.orig	2004-05-10 17:00:59.000000000 +0200
+++ ./sys/netinet/in.h	2004-12-29 16:38:20.000000000 +0100
@@ -97,6 +97,7 @@
 #define	IPPROTO_NONE		59		/* IP6 no next header */
 #define	IPPROTO_DSTOPTS		60		/* IP6 destination option */
 #define	IPPROTO_EON		80		/* ISO cnlp */
+#define	IPPROTO_ETHERIP		97		/* Ethernet-in-IP */
 #define	IPPROTO_ENCAP		98		/* encapsulation header */
 #define	IPPROTO_PIM		103		/* Protocol indep. multicast */
 #define	IPPROTO_IPCOMP		108		/* IP Payload Comp. Protocol */
--- ./sys/netinet/in_gif.c.orig	2003-11-11 21:25:26.000000000 +0100
+++ ./sys/netinet/in_gif.c	2004-12-29 16:38:28.000000000 +0100
@@ -65,6 +65,8 @@
 #include <net/if_gif.h>
 
 #include "gif.h"
+#include "bridge.h"
+#include <net/if_ether.h>
 
 #include <machine/stdarg.h>
 
@@ -98,6 +100,7 @@
 	struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
 	struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst;
 	struct ip iphdr;	/* capsule IP header, host byte ordered */
+	struct etherip_header eiphdr;
 	int proto, error;
 	u_int8_t tos;
 
@@ -146,6 +149,20 @@
 		tos = 0;
 		break;
 #endif
+#if NBRIDGE > 0
+	case AF_LINK:
+		proto = IPPROTO_ETHERIP;
+		eiphdr.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
+		eiphdr.eip_pad = 0;
+		/* prepend Ethernet-in-IP header */
+		M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
+		if (m && m->m_len < sizeof(struct etherip_header))
+			m = m_pullup(m, sizeof(struct etherip_header));
+		if (m == NULL)
+			return ENOBUFS;
+		bcopy(&eiphdr, mtod(m, struct etherip_header *), sizeof(struct etherip_header));
+		break;
+#endif
 	default:
 #ifdef DEBUG
 		printf("in_gif_output: warning: unknown family %d passed\n",
@@ -299,6 +316,11 @@
 		af = AF_ISO;
 		break;
 #endif
+#if NBRIDGE > 0
+	case IPPROTO_ETHERIP:
+		af = AF_LINK;
+		break;	
+#endif
 	default:
 		ipstat.ips_nogif++;
 		m_freem(m);
--- ./sys/netinet/in_gif.h.orig	2002-11-11 19:35:28.000000000 +0100
+++ ./sys/netinet/in_gif.h	2004-12-29 16:38:36.000000000 +0100
@@ -46,4 +46,13 @@
 int in_gif_attach __P((struct gif_softc *));
 int in_gif_detach __P((struct gif_softc *));
 
+struct etherip_header {
+        u_int8_t eip_ver;        /* version/reserved */
+        u_int8_t eip_pad;        /* required padding byte */
+};
+#define ETHERIP_VER_VERS_MASK   0x0f
+#define ETHERIP_VER_RSVD_MASK   0xf0
+#define ETHERIP_VERSION         0x03
+
+
 #endif /*_NETINET_IN_GIF_H_*/
--- ./sys/netinet/in_proto.c.orig	2003-12-04 20:38:24.000000000 +0100
+++ ./sys/netinet/in_proto.c	2004-12-29 16:38:51.000000000 +0100
@@ -142,6 +142,8 @@
 #include <netinet/ip_gre.h>
 #endif
 
+#include "bridge.h"
+
 extern	struct domain inetdomain;
 
 struct protosw inetsw[] = {
@@ -220,6 +222,13 @@
   encap_init,	0,		0,		0,
 },
 #endif /* INET6 */
+#if NBRIDGE > 0
+{ SOCK_RAW,	&inetdomain,	IPPROTO_ETHERIP,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
+  encap4_input,	rip_output,	rip_ctlinput,	rip_ctloutput,
+  rip_usrreq,
+  encap_init,		0,		0,		0,
+},
+#endif
 #if NGRE > 0
 { SOCK_RAW,	&inetdomain,	IPPROTO_GRE,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
   gre_input,	rip_output,	rip_ctlinput,	rip_ctloutput,
--- ./sys/sys/mbuf.h.orig	2004-09-11 20:08:57.000000000 +0200
+++ ./sys/sys/mbuf.h	2004-12-29 17:16:34.000000000 +0100
@@ -272,6 +272,7 @@
 #define	M_EXT		0x0001	/* has associated external storage */
 #define	M_PKTHDR	0x0002	/* start of record */
 #define	M_EOR		0x0004	/* end of record */
+#define	M_PROTO1	0x0008	/* protocol-specific */
 
 /* mbuf pkthdr flags, also in m_flags */
 #define M_AUTHIPHDR	0x0010	/* data origin authentication for IP header */
