Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Dec 2002 20:40:09 +0700
From:      pirat <pirat@access.inet.co.th>
To:        Maxim Sobolev <sobomax@FreeBSD.org>
Cc:        FreeBSD-stable@FreeBSD.org
Subject:   Re: options GRE in 4.7-stable
Message-ID:  <20021201134009.GA86354@thai-aec.org>
In-Reply-To: <20021201125900.GC7921@vega.vega.com>
References:  <20021201030950.GC11858@thai-aec.org> <20021201125900.GC7921@vega.vega.com>

next in thread | previous in thread | raw e-mail | index | archive | help
hi sirs,

your kindness is highly appreciated.

with best regards,
psr
On Sun, Dec 01, 2002 at 02:59:00PM +0200, Maxim Sobolev wrote:
> Date: Sun, 1 Dec 2002 14:59:00 +0200
> From: Maxim Sobolev <sobomax@FreeBSD.org>
> To: pirat <pirat@access.inet.co.th>
> Subject: Re: options GRE in 4.7-stable
> 
> See attached. Apply it as follows, and don't forget to recompile
> your kernel after that:
> 
> # cd /usr/src
> # patch -p1 -s < /tmp/if_gre.diff
> 
> -Maxim
> 
> On Sun, Dec 01, 2002 at 10:09:50AM +0700, pirat wrote:
> > hi sirs,
> > 
> > i have heard from Alexandr Kovalenko that you have patch for GRE.
> > may i have that patch for GRE ?
> > my machine is
> > 
> > uname -a
> > FreeBSD firak.thai-aec.org 4.7-STABLE FreeBSD 4.7-STABLE #4: Fri Nov 29 04:28:21
> >  ICT 2002     firak@firak.thai-aec.org:/var/obj/var/src/sys/Firak  i386
> > 
> > thank you very much in advance.
> > 
> > with best regards,
> > pirat sriyotha
> > 
> > On Fri, Nov 29, 2002 at 02:21:40PM +0200, Alexandr Kovalenko wrote:
> > > Date: Fri, 29 Nov 2002 14:21:40 +0200
> > > From: Alexandr Kovalenko <never@nevermind.kiev.ua>
> > > To: pirat sriyotha <makhamus@yahoo.com>
> > > Cc: FreeBSD-stable@FreeBSD.ORG
> > > Subject: Re: options GRE in 4.7-stable
> > > 
> > > Hello, pirat sriyotha!
> > > 
> > > On Wed, Nov 27, 2002 at 07:45:27PM -0800, you wrote:
> > > 
> > > > i would like to ask that if options GRE is now in
> > > > 4.7-stable ?
> > > > 
> > > > if not then what options can be substituted for?
> > > > 
> > > > thanks in advance for any hints and helps.
> > > Maxim Sobolev <sobomax@FreeBSD.org> developed patch for GRE, you can ask
> > > him about that.

> Index: src.gre/sys/netns/ns_if.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/netns/ns_if.h,v
> retrieving revision 1.12
> diff -d -u -r1.12 ns_if.h
> --- src.gre/sys/netns/ns_if.h	29 Dec 1999 04:46:19 -0000	1.12
> +++ src.gre/sys/netns/ns_if.h	1 Dec 2002 12:44:45 -0000
> @@ -80,10 +80,10 @@
>  #endif
>  
>  #ifdef	_KERNEL
> -struct	ns_ifaddr *ns_ifaddr;
> -struct	ns_ifaddr *ns_iaonnetof();
> -void	nsintr __P((void));
> -struct	ifqueue	nsintrq;	/* XNS input packet queue */
> +extern struct ns_ifaddr	*ns_ifaddr;
> +struct ns_ifaddr	*ns_iaonnetof(void);
> +void			nsintr(void);
> +extern struct ifqueue	nsintrq;	/* XNS input packet queue */
>  #endif
>  
>  #endif
> Index: src.gre/sys/netns/ns.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/netns/ns.h,v
> retrieving revision 1.13
> diff -d -u -r1.13 ns.h
> --- src.gre/sys/netns/ns.h	29 Dec 1999 04:46:19 -0000	1.13
> +++ src.gre/sys/netns/ns.h	1 Dec 2002 12:44:45 -0000
> @@ -137,12 +137,12 @@
>  
>  #ifdef _KERNEL
>  extern struct domain nsdomain;
> -union ns_host ns_thishost;
> -union ns_host ns_zerohost;
> -union ns_host ns_broadhost;
> -union ns_net ns_zeronet;
> -union ns_net ns_broadnet;
> -u_short ns_cksum();
> +extern union ns_host ns_thishost;
> +extern union ns_host ns_zerohost;
> +extern union ns_host ns_broadhost;
> +extern union ns_net ns_zeronet;
> +extern union ns_net ns_broadnet;
> +u_short ns_cksum(void);
>  #else
>  
>  #include <sys/cdefs.h>
> Index: src.gre/sys/net/if_gre.c
> ===================================================================
> RCS file: src.gre/sys/net/if_gre.c
> diff -N src.gre/sys/net/if_gre.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ src.gre/sys/net/if_gre.c	1 Dec 2002 12:44:45 -0000
> @@ -0,0 +1,802 @@
> +/*	$NetBSD: if_gre.c,v 1.42 2002/08/14 00:23:27 itojun Exp $ */
> +/*	 $FreeBSD$ */
> +
> +/*
> + * Copyright (c) 1998 The NetBSD Foundation, Inc.
> + * All rights reserved.
> + *
> + * This code is derived from software contributed to The NetBSD Foundation
> + * by Heiko W.Rupp <hwr@pilhuhn.de>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *        This product includes software developed by the NetBSD
> + *        Foundation, Inc. and its contributors.
> + * 4. Neither the name of The NetBSD Foundation nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * Encapsulate L3 protocols into IP
> + * See RFC 1701 and 1702 for more details.
> + * If_gre is compatible with Cisco GRE tunnels, so you can
> + * have a NetBSD box as the other end of a tunnel interface of a Cisco
> + * router. See gre(4) for more details.
> + * Also supported:  IP in IP encaps (proto 55) as of RFC 2004
> + */
> +
> +#include "opt_atalk.h"
> +#include "opt_inet.h"
> +#include "opt_ns.h"
> +
> +#include <sys/param.h>
> +#include <sys/kernel.h>
> +#include <sys/malloc.h>
> +#include <sys/mbuf.h>
> +#include <sys/proc.h>
> +#include <sys/protosw.h>
> +#include <machine/bus.h>
> +#include <sys/rman.h>
> +#include <sys/socket.h>
> +#include <sys/sockio.h>
> +#include <sys/sysctl.h>
> +#include <sys/systm.h>
> +
> +#include <net/ethernet.h>
> +#include <net/if.h>
> +#include <net/if_types.h>
> +#include <net/route.h>
> +
> +#ifdef INET
> +#include <netinet/in.h>
> +#include <netinet/in_systm.h>
> +#include <netinet/in_var.h>
> +#include <netinet/ip.h>
> +#include <netinet/ip_gre.h>
> +#include <netinet/ip_var.h>
> +#include <netinet/ip_encap.h>
> +#else
> +#error "Huh? if_gre without inet?"
> +#endif
> +
> +#include <net/bpf.h>
> +
> +#include <net/net_osdep.h>
> +#include <net/if_gre.h>
> +
> +/*
> + * It is not easy to calculate the right value for a GRE MTU.
> + * We leave this task to the admin and use the same default that
> + * other vendors use.
> + */
> +#define GREMTU	1476
> +
> +#define GRENAME	"gre"
> +#define GRE_MAXUNIT 0x7fff
> +
> +static MALLOC_DEFINE(M_GRE, GRENAME, "Generic Routing Encapsulation");
> +static struct rman greunits[1];
> +
> +struct gre_softc_head gre_softc_list;
> +
> +static int	gre_clone_create(struct if_clone *, int *);
> +static void	gre_clone_destroy(struct ifnet *);
> +static int	gre_ioctl(struct ifnet *, u_long, caddr_t);
> +static int	gre_output(struct ifnet *, struct mbuf *, struct sockaddr *,
> +		    struct rtentry *rt);
> +
> +static struct if_clone gre_cloner =
> +    IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
> +
> +static int gre_compute_route(struct gre_softc *sc);
> +
> +static void	greattach(void);
> +
> +#ifdef INET
> +extern struct domain inetdomain;
> +static const struct protosw in_gre_protosw =
> +{ SOCK_RAW,     &inetdomain,    IPPROTO_GRE,    PR_ATOMIC|PR_ADDR,
> +  gre_input,	rip_output,     rip_ctlinput,   rip_ctloutput,
> +  0,
> +  0,		0,		0,		0,
> +  &rip_usrreqs
> +};
> +static const struct protosw in_mobile_protosw =
> +{ SOCK_RAW,     &inetdomain,    IPPROTO_MOBILE, PR_ATOMIC|PR_ADDR,
> +  gre_mobile_input, rip_output, rip_ctlinput,   rip_ctloutput,
> +  0,
> +  0,		0,		0,		0,
> +  &rip_usrreqs
> +};
> +#endif
> +
> +SYSCTL_DECL(_net_link);
> +SYSCTL_NODE(_net_link, IFT_OTHER, gre, CTLFLAG_RW, 0,
> +    "Generic Routing Encapsulation");
> +#ifndef MAX_GRE_NEST
> +/*
> + * This macro controls the default upper limitation on nesting of gre tunnels.
> + * Since, setting a large value to this macro with a careless configuration
> + * may introduce system crash, we don't allow any nestings by default.
> + * If you need to configure nested gre tunnels, you can define this macro
> + * in your kernel configuration file.  However, if you do so, please be
> + * careful to configure the tunnels so that it won't make a loop.
> + */
> +#define MAX_GRE_NEST 1
> +#endif
> +static int max_gre_nesting = MAX_GRE_NEST;
> +SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
> +    &max_gre_nesting, 0, "Max nested tunnels");
> +
> +/* ARGSUSED */
> +static void
> +greattach(void)
> +{
> +
> +	LIST_INIT(&gre_softc_list);
> +	if_clone_attach(&gre_cloner);
> +}
> +
> +static int
> +gre_clone_create(ifc, unit)
> +	struct if_clone *ifc;
> +	int *unit;
> +{
> +	struct resource *r;
> +	struct gre_softc *sc;
> +
> +	if (*unit > GRE_MAXUNIT)
> +		return (ENXIO);
> +
> +	if (*unit < 0) {
> +		r = rman_reserve_resource(greunits, 0, GRE_MAXUNIT, 1,
> +		    RF_ALLOCATED | RF_ACTIVE, NULL);
> +		if (r == NULL)
> +			return (ENOSPC);
> +		*unit = rman_get_start(r);
> +	} else {
> +		r = rman_reserve_resource(greunits, *unit, *unit, 1,
> +		    RF_ALLOCATED | RF_ACTIVE, NULL);
> +		if (r == NULL)
> +			return (EEXIST);
> +	}
> +
> +	sc = malloc(sizeof(struct gre_softc), M_GRE, M_WAITOK);
> +	memset(sc, 0, sizeof(struct gre_softc));
> +
> +	sc->sc_if.if_name = GRENAME;
> +	sc->sc_if.if_softc = sc;
> +	sc->sc_if.if_unit = *unit;
> +	sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
> +	sc->sc_if.if_type = IFT_OTHER;
> +	sc->sc_if.if_addrlen = 0;
> +	sc->sc_if.if_hdrlen = 24; /* IP + GRE */
> +	sc->sc_if.if_mtu = GREMTU;
> +	sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
> +	sc->sc_if.if_output = gre_output;
> +	sc->sc_if.if_ioctl = gre_ioctl;
> +	sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
> +	sc->g_proto = IPPROTO_GRE;
> +	sc->sc_if.if_flags |= IFF_LINK0;
> +	sc->encap = NULL;
> +	sc->called = 0;
> +	sc->r_unit = r;
> +	if_attach(&sc->sc_if);
> +	bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t));
> +	LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
> +	return (0);
> +}
> +
> +static void
> +gre_clone_destroy(ifp)
> +	struct ifnet *ifp;
> +{
> +	int err;
> +	struct gre_softc *sc = ifp->if_softc;
> +
> +#ifdef INET
> +	if (sc->encap != NULL)
> +		encap_detach(sc->encap);
> +#endif
> +	LIST_REMOVE(sc, sc_list);
> +	bpfdetach(ifp);
> +	if_detach(ifp);
> +
> +	err = rman_release_resource(sc->r_unit);
> +	KASSERT(err == 0, ("Unexpected error freeing resource"));
> +
> +	free(sc, M_GRE);
> +}
> +
> +/*
> + * The output routine. Takes a packet and encapsulates it in the protocol
> + * given by sc->g_proto. See also RFC 1701 and RFC 2004
> + */
> +static int
> +gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
> +	   struct rtentry *rt)
> +{
> +	int error = 0;
> +	struct gre_softc *sc = ifp->if_softc;
> +	struct greip *gh;
> +	struct ip *ip;
> +	u_char osrc;
> +	u_short etype = 0;
> +	struct mobile_h mob_h;
> +
> +	/*
> +	 * gre may cause infinite recursion calls when misconfigured.
> +	 * We'll prevent this by introducing upper limit.
> +	 */
> +	if (++(sc->called) > max_gre_nesting) {
> +		printf("%s: gre_output: recursively called too many "
> +		       "times(%d)\n", if_name(&sc->sc_if), sc->called);
> +		m_freem(m);
> +		error = EIO;    /* is there better errno? */
> +		goto end;
> +	}
> +
> +	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 0 ||
> +	    sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
> +		m_freem(m);
> +		error = ENETDOWN;
> +		goto end;
> +	}
> +
> +	gh = NULL;
> +	ip = NULL;
> +	osrc = 0;
> +
> +	if (ifp->if_bpf) {
> +		/* see comment of other if_foo.c files */
> +		struct mbuf m0;
> +		u_int32_t af = dst->sa_family;
> +
> +		m0.m_next = m;
> +		m0.m_len = 4;
> +		m0.m_data = (char *)&af;
> +
> +		bpf_mtap(ifp, &m0);
> +	}
> +
> +	m->m_flags &= ~(M_BCAST|M_MCAST);
> +
> +	if (sc->g_proto == IPPROTO_MOBILE) {
> +		if (dst->sa_family == AF_INET) {
> +			struct mbuf *m0;
> +			int msiz;
> +
> +			ip = mtod(m, struct ip *);
> +
> +			/*
> +			 * RFC2004 specifies that fragmented diagrams shouldn't
> +			 * be encapsulated.
> +			 */
> +			if ((ip->ip_off & IP_MF) != 0) {
> +				IF_DROP(&ifp->if_snd);
> +				m_freem(m);
> +				error = EINVAL;    /* is there better errno? */
> +				goto end;
> +			}
> +			memset(&mob_h, 0, MOB_H_SIZ_L);
> +			mob_h.proto = (ip->ip_p) << 8;
> +			mob_h.odst = ip->ip_dst.s_addr;
> +			ip->ip_dst.s_addr = sc->g_dst.s_addr;
> +
> +			/*
> +			 * If the packet comes from our host, we only change
> +			 * the destination address in the IP header.
> +			 * Else we also need to save and change the source
> +			 */
> +			if (in_hosteq(ip->ip_src, sc->g_src)) {
> +				msiz = MOB_H_SIZ_S;
> +			} else {
> +				mob_h.proto |= MOB_H_SBIT;
> +				mob_h.osrc = ip->ip_src.s_addr;
> +				ip->ip_src.s_addr = sc->g_src.s_addr;
> +				msiz = MOB_H_SIZ_L;
> +			}
> +			mob_h.proto = htons(mob_h.proto);
> +			mob_h.hcrc = gre_in_cksum((u_short *)&mob_h, msiz);
> +
> +			if ((m->m_data - msiz) < m->m_pktdat) {
> +				/* need new mbuf */
> +				MGETHDR(m0, M_DONTWAIT, MT_HEADER);
> +				if (m0 == NULL) {
> +					IF_DROP(&ifp->if_snd);
> +					m_freem(m);
> +					error = ENOBUFS;
> +					goto end;
> +				}
> +				m0->m_next = m;
> +				m->m_data += sizeof(struct ip);
> +				m->m_len -= sizeof(struct ip);
> +				m0->m_pkthdr.len = m->m_pkthdr.len + msiz;
> +				m0->m_len = msiz + sizeof(struct ip);
> +				m0->m_data += max_linkhdr;
> +				memcpy(mtod(m0, caddr_t), (caddr_t)ip,
> +				       sizeof(struct ip));
> +				m = m0;
> +			} else {  /* we have some space left in the old one */
> +				m->m_data -= msiz;
> +				m->m_len += msiz;
> +				m->m_pkthdr.len += msiz;
> +				bcopy(ip, mtod(m, caddr_t),
> +					sizeof(struct ip));
> +			}
> +			ip = mtod(m, struct ip *);
> +			memcpy((caddr_t)(ip + 1), &mob_h, (unsigned)msiz);
> +			ip->ip_len = ntohs(ip->ip_len) + msiz;
> +		} else {  /* AF_INET */
> +			IF_DROP(&ifp->if_snd);
> +			m_freem(m);
> +			error = EINVAL;
> +			goto end;
> +		}
> +	} else if (sc->g_proto == IPPROTO_GRE) {
> +		switch (dst->sa_family) {
> +		case AF_INET:
> +			ip = mtod(m, struct ip *);
> +			etype = ETHERTYPE_IP;
> +			break;
> +#ifdef NETATALK
> +		case AF_APPLETALK:
> +			etype = ETHERTYPE_ATALK;
> +			break;
> +#endif
> +#ifdef NS
> +		case AF_NS:
> +			etype = ETHERTYPE_NS;
> +			break;
> +#endif
> +		default:
> +			IF_DROP(&ifp->if_snd);
> +			m_freem(m);
> +			error = EAFNOSUPPORT;
> +			goto end;
> +		}
> +		M_PREPEND(m, sizeof(struct greip), M_DONTWAIT);
> +	} else {
> +		IF_DROP(&ifp->if_snd);
> +		m_freem(m);
> +		error = EINVAL;
> +		goto end;
> +	}
> +
> +	if (m == NULL) {	/* impossible */
> +		IF_DROP(&ifp->if_snd);
> +		error = ENOBUFS;
> +		goto end;
> +	}
> +
> +	gh = mtod(m, struct greip *);
> +	if (sc->g_proto == IPPROTO_GRE) {
> +		/* we don't have any GRE flags for now */
> +
> +		memset((void *)&gh->gi_g, 0, sizeof(struct gre_h));
> +		gh->gi_ptype = htons(etype);
> +	}
> +
> +	gh->gi_pr = sc->g_proto;
> +	if (sc->g_proto != IPPROTO_MOBILE) {
> +		gh->gi_src = sc->g_src;
> +		gh->gi_dst = sc->g_dst;
> +		((struct ip*)gh)->ip_hl = (sizeof(struct ip)) >> 2;
> +		((struct ip*)gh)->ip_ttl = GRE_TTL;
> +		((struct ip*)gh)->ip_tos = ip->ip_tos;
> +		((struct ip*)gh)->ip_id = ip->ip_id;
> +		gh->gi_len = m->m_pkthdr.len;
> +	}
> +
> +	ifp->if_opackets++;
> +	ifp->if_obytes += m->m_pkthdr.len;
> +	/* send it off */
> +	error = ip_output(m, NULL, &sc->route, 0, NULL);
> +  end:
> +	sc->called = 0;
> +	if (error)
> +		ifp->if_oerrors++;
> +	return (error);
> +}
> +
> +static int
> +gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
> +{
> +	struct ifreq *ifr = (struct ifreq *)data;
> +	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
> +	struct in_aliasreq *aifr = (struct in_aliasreq *)data;
> +	struct gre_softc *sc = ifp->if_softc;
> +	int s;
> +	struct sockaddr_in si;
> +	struct sockaddr *sa = NULL;
> +	int error;
> +	struct sockaddr_in sp, sm, dp, dm;
> +
> +	error = 0;
> +
> +	s = splnet();
> +	switch (cmd) {
> +	case SIOCSIFADDR:
> +		ifp->if_flags |= IFF_UP;
> +		break;
> +	case SIOCSIFDSTADDR: 
> +		break;
> +	case SIOCSIFFLAGS:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		if ((ifr->ifr_flags & IFF_LINK0) != 0)
> +			sc->g_proto = IPPROTO_GRE;
> +		else
> +			sc->g_proto = IPPROTO_MOBILE;
> +		goto recompute;
> +	case SIOCSIFMTU:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		if (ifr->ifr_mtu < 576) {
> +			error = EINVAL;
> +			break;
> +		}
> +		ifp->if_mtu = ifr->ifr_mtu;
> +		break;
> +	case SIOCGIFMTU:
> +		ifr->ifr_mtu = sc->sc_if.if_mtu;
> +		break;
> +	case SIOCADDMULTI:
> +	case SIOCDELMULTI:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		if (ifr == 0) {
> +			error = EAFNOSUPPORT;
> +			break;
> +		}
> +		switch (ifr->ifr_addr.sa_family) {
> +#ifdef INET
> +		case AF_INET:
> +			break;
> +#endif
> +		default:
> +			error = EAFNOSUPPORT;
> +			break;
> +		}
> +		break;
> +	case GRESPROTO:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		sc->g_proto = ifr->ifr_flags;
> +		switch (sc->g_proto) {
> +		case IPPROTO_GRE:
> +			ifp->if_flags |= IFF_LINK0;
> +			break;
> +		case IPPROTO_MOBILE:
> +			ifp->if_flags &= ~IFF_LINK0;
> +			break;
> +		default:
> +			error = EPROTONOSUPPORT;
> +			break;
> +		}
> +		goto recompute;
> +	case GREGPROTO:
> +		ifr->ifr_flags = sc->g_proto;
> +		break;
> +	case GRESADDRS:
> +	case GRESADDRD:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		/*
> +		 * set tunnel endpoints, compute a less specific route
> +		 * to the remote end and mark if as up
> +		 */
> +		sa = &ifr->ifr_addr;
> +		if (cmd == GRESADDRS)
> +			sc->g_src = (satosin(sa))->sin_addr;
> +		if (cmd == GRESADDRD)
> +			sc->g_dst = (satosin(sa))->sin_addr;
> +	recompute:
> +#ifdef INET
> +		if (sc->encap != NULL) {
> +			encap_detach(sc->encap);
> +			sc->encap = NULL;
> +		}
> +#endif
> +		if ((sc->g_src.s_addr != INADDR_ANY) &&
> +		    (sc->g_dst.s_addr != INADDR_ANY)) {
> +			bzero(&sp, sizeof(sp));
> +			bzero(&sm, sizeof(sm));
> +			bzero(&dp, sizeof(dp));
> +			bzero(&dm, sizeof(dm));
> +			sp.sin_len = sm.sin_len = dp.sin_len = dm.sin_len =
> +			    sizeof(struct sockaddr_in);
> +			sp.sin_family = sm.sin_family = dp.sin_family =
> +			    dm.sin_family = AF_INET;
> +			sp.sin_addr = sc->g_src;
> +			dp.sin_addr = sc->g_dst;
> +			sm.sin_addr.s_addr = dm.sin_addr.s_addr = 
> +			    INADDR_BROADCAST;
> +#ifdef INET
> +			sc->encap = encap_attach(AF_INET, sc->g_proto,
> +			    sintosa(&sp), sintosa(&sm), sintosa(&dp),
> +			    sintosa(&dm), (sc->g_proto == IPPROTO_GRE) ?
> +				&in_gre_protosw : &in_mobile_protosw, sc);
> +			if (sc->encap == NULL)
> +				printf("%s: unable to attach encap\n",
> +				    if_name(&sc->sc_if));
> +#endif
> +			if (sc->route.ro_rt != 0) /* free old route */
> +				RTFREE(sc->route.ro_rt);
> +			if (gre_compute_route(sc) == 0)
> +				ifp->if_flags |= IFF_RUNNING;
> +			else
> +				ifp->if_flags &= ~IFF_RUNNING;
> +		}
> +		break;
> +	case GREGADDRS:
> +		memset(&si, 0, sizeof(si));
> +		si.sin_family = AF_INET;
> +		si.sin_len = sizeof(struct sockaddr_in);
> +		si.sin_addr.s_addr = sc->g_src.s_addr;
> +		sa = sintosa(&si);
> +		ifr->ifr_addr = *sa;
> +		break;
> +	case GREGADDRD:
> +		memset(&si, 0, sizeof(si));
> +		si.sin_family = AF_INET;
> +		si.sin_len = sizeof(struct sockaddr_in);
> +		si.sin_addr.s_addr = sc->g_dst.s_addr;
> +		sa = sintosa(&si);
> +		ifr->ifr_addr = *sa;
> +		break;
> +	case SIOCSIFPHYADDR:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		if (aifr->ifra_addr.sin_family != AF_INET ||
> +		    aifr->ifra_dstaddr.sin_family != AF_INET) {
> +			error = EAFNOSUPPORT;
> +			break;
> +		}
> +		if (aifr->ifra_addr.sin_len != sizeof(si) ||
> +		    aifr->ifra_dstaddr.sin_len != sizeof(si)) {
> +			error = EINVAL;
> +			break;
> +		}
> +		sc->g_src = aifr->ifra_addr.sin_addr;
> +		sc->g_dst = aifr->ifra_dstaddr.sin_addr;
> +		goto recompute;
> +	case SIOCSLIFPHYADDR:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		if (lifr->addr.ss_family != AF_INET ||
> +		    lifr->dstaddr.ss_family != AF_INET) {
> +			error = EAFNOSUPPORT;
> +			break;
> +		}
> +		if (lifr->addr.ss_len != sizeof(si) ||
> +		    lifr->dstaddr.ss_len != sizeof(si)) {
> +			error = EINVAL;
> +			break;
> +		}
> +		sc->g_src = (satosin((struct sockadrr *)&lifr->addr))->sin_addr;
> +		sc->g_dst =
> +		    (satosin((struct sockadrr *)&lifr->dstaddr))->sin_addr;
> +		goto recompute;
> +	case SIOCDIFPHYADDR:
> +		if ((error = suser(curproc)) != 0)
> +			break;
> +		sc->g_src.s_addr = INADDR_ANY;
> +		sc->g_dst.s_addr = INADDR_ANY;
> +		goto recompute;
> +	case SIOCGLIFPHYADDR:
> +		if (sc->g_src.s_addr == INADDR_ANY ||
> +		    sc->g_dst.s_addr == INADDR_ANY) {
> +			error = EADDRNOTAVAIL;
> +			break;
> +		}
> +		memset(&si, 0, sizeof(si));
> +		si.sin_family = AF_INET;
> +		si.sin_len = sizeof(struct sockaddr_in);
> +		si.sin_addr.s_addr = sc->g_src.s_addr;
> +		memcpy(&lifr->addr, &si, sizeof(si));
> +		si.sin_addr.s_addr = sc->g_dst.s_addr;
> +		memcpy(&lifr->dstaddr, &si, sizeof(si));
> +		break;
> +	case SIOCGIFPSRCADDR:
> +		if (sc->g_src.s_addr == INADDR_ANY) {
> +			error = EADDRNOTAVAIL;
> +			break;
> +		}
> +		memset(&si, 0, sizeof(si));
> +		si.sin_family = AF_INET;
> +		si.sin_len = sizeof(struct sockaddr_in);
> +		si.sin_addr.s_addr = sc->g_src.s_addr;
> +		bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
> +		break;
> +	case SIOCGIFPDSTADDR:
> +		if (sc->g_dst.s_addr == INADDR_ANY) {
> +			error = EADDRNOTAVAIL;
> +			break;
> +		}
> +		memset(&si, 0, sizeof(si));
> +		si.sin_family = AF_INET;
> +		si.sin_len = sizeof(struct sockaddr_in);
> +		si.sin_addr.s_addr = sc->g_dst.s_addr;
> +		bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
> +		break;
> +	default:
> +		error = EINVAL;
> +		break;
> +	}
> +
> +	splx(s);
> +	return (error);
> +}
> +
> +/*
> + * computes a route to our destination that is not the one
> + * which would be taken by ip_output(), as this one will loop back to
> + * us. If the interface is p2p as  a--->b, then a routing entry exists
> + * If we now send a packet to b (e.g. ping b), this will come down here
> + * gets src=a, dst=b tacked on and would from ip_ouput() sent back to
> + * if_gre.
> + * Goal here is to compute a route to b that is less specific than
> + * a-->b. We know that this one exists as in normal operation we have
> + * at least a default route which matches.
> + */
> +static int
> +gre_compute_route(struct gre_softc *sc)
> +{
> +	struct route *ro;
> +	u_int32_t a, b, c;
> +
> +	ro = &sc->route;
> +
> +	memset(ro, 0, sizeof(struct route));
> +	((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
> +	ro->ro_dst.sa_family = AF_INET;
> +	ro->ro_dst.sa_len = sizeof(ro->ro_dst);
> +
> +	/*
> +	 * toggle last bit, so our interface is not found, but a less
> +	 * specific route. I'd rather like to specify a shorter mask,
> +	 * but this is not possible. Should work though. XXX
> +	 * there is a simpler way ...
> +	 */
> +	if ((sc->sc_if.if_flags & IFF_LINK1) == 0) {
> +		a = ntohl(sc->g_dst.s_addr);
> +		b = a & 0x01;
> +		c = a & 0xfffffffe;
> +		b = b ^ 0x01;
> +		a = b | c;
> +		((struct sockaddr_in *)&ro->ro_dst)->sin_addr.s_addr
> +		    = htonl(a);
> +	}
> +
> +#ifdef DIAGNOSTIC
> +	printf("%s: searching a route to %s", if_name(&sc->sc_if),
> +	    inet_ntoa(((struct sockaddr_in *)&ro->ro_dst)->sin_addr));
> +#endif
> +
> +	rtalloc(ro);
> +
> +	/*
> +	 * check if this returned a route at all and this route is no
> +	 * recursion to ourself
> +	 */
> +	if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp->if_softc == sc) {
> +#ifdef DIAGNOSTIC
> +		if (ro->ro_rt == NULL)
> +			printf(" - no route found!\n");
> +		else
> +			printf(" - route loops back to ourself!\n");
> +#endif
> +		return EADDRNOTAVAIL;
> +	}
> +
> +	/*
> +	 * now change it back - else ip_output will just drop
> +	 * the route and search one to this interface ...
> +	 */
> +	if ((sc->sc_if.if_flags & IFF_LINK1) == 0)
> +		((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
> +
> +#ifdef DIAGNOSTIC
> +	printf(", choosing %s with gateway %s", if_name(ro->ro_rt->rt_ifp),
> +	    inet_ntoa(((struct sockaddr_in *)(ro->ro_rt->rt_gateway))->sin_addr));
> +	printf("\n");
> +#endif
> +
> +	return 0;
> +}
> +
> +/*
> + * do a checksum of a buffer - much like in_cksum, which operates on
> + * mbufs.
> + */
> +u_short
> +gre_in_cksum(u_short *p, u_int len)
> +{
> +	u_int sum = 0;
> +	int nwords = len >> 1;
> +
> +	while (nwords-- != 0)
> +		sum += *p++;
> +
> +	if (len & 1) {
> +		union {
> +			u_short w;
> +			u_char c[2];
> +		} u;
> +		u.c[0] = *(u_char *)p;
> +		u.c[1] = 0;
> +		sum += u.w;
> +	}
> +
> +	/* end-around-carry */
> +	sum = (sum >> 16) + (sum & 0xffff);
> +	sum += (sum >> 16);
> +	return (~sum);
> +}
> +
> +static int
> +gremodevent(module_t mod, int type, void *data)
> +{
> +	int err;
> +
> +	switch (type) {
> +	case MOD_LOAD:
> +		greunits->rm_type = RMAN_ARRAY;
> +		greunits->rm_descr = "configurable if_gre units";
> +		err = rman_init(greunits);
> +		if (err != 0)
> +			return (err);
> +		err = rman_manage_region(greunits, 0, GRE_MAXUNIT);
> +		if (err != 0) {
> +			printf("%s: greunits: rman_manage_region: Failed %d\n",
> +			    GRENAME, err);
> +			rman_fini(greunits);
> +			return (err);
> +		}
> +		greattach();
> +		break;
> +	case MOD_UNLOAD:
> +		if_clone_detach(&gre_cloner);
> +
> +		while (!LIST_EMPTY(&gre_softc_list))
> +			gre_clone_destroy(&LIST_FIRST(&gre_softc_list)->sc_if);
> +
> +		err = rman_fini(greunits);
> +		if (err != 0)
> +			return (err);
> +
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static moduledata_t gre_mod = {
> +	"if_gre",
> +	gremodevent,
> +	0
> +};
> +
> +DECLARE_MODULE(if_gre, gre_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
> +MODULE_VERSION(if_gre, 1);
> Index: src.gre/sys/net/ethernet.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/ethernet.h,v
> retrieving revision 1.12.2.7
> diff -d -u -r1.12.2.7 ethernet.h
> --- src.gre/sys/net/ethernet.h	4 Apr 2002 05:51:55 -0000	1.12.2.7
> +++ src.gre/sys/net/ethernet.h	1 Dec 2002 12:44:45 -0000
> @@ -60,14 +60,264 @@
>  	u_char octet[ETHER_ADDR_LEN];
>  };
>  
> -#define	ETHERTYPE_PUP		0x0200	/* PUP protocol */
> +/*
> + *  NOTE: 0x0000-0x05DC (0..1500) are generally IEEE 802.3 length fields.
> + *  However, there are some conflicts.
> + */
> +
> +#define	ETHERTYPE_8023		0x0004	/* IEEE 802.3 packet */
> +		   /* 0x0101 .. 0x1FF	   Experimental */
> +#define	ETHERTYPE_PUP		0x0200	/* Xerox PUP protocol - see 0A00 */
> +#define	ETHERTYPE_PUPAT		0x0200	/* PUP Address Translation - see 0A01 */
> +#define	ETHERTYPE_SPRITE	0x0500	/* ??? */
> +			     /* 0x0400	   Nixdorf */
> +#define	ETHERTYPE_NS		0x0600	/* XNS */
> +#define	ETHERTYPE_NSAT		0x0601	/* XNS Address Translation (3Mb only) */
> +#define	ETHERTYPE_DLOG1 	0x0660	/* DLOG (?) */
> +#define	ETHERTYPE_DLOG2 	0x0661	/* DLOG (?) */
>  #define	ETHERTYPE_IP		0x0800	/* IP protocol */
> -#define	ETHERTYPE_ARP		0x0806	/* Addr. resolution protocol */
> -#define	ETHERTYPE_REVARP	0x8035	/* reverse Addr. resolution protocol */
> -#define	ETHERTYPE_VLAN		0x8100	/* IEEE 802.1Q VLAN tagging */
> -#define	ETHERTYPE_IPV6		0x86dd	/* IPv6 */
> -#define	ETHERTYPE_LOOPBACK	0x9000	/* used to test interfaces */
> -/* XXX - add more useful types here */
> +#define	ETHERTYPE_X75		0x0801	/* X.75 Internet */
> +#define	ETHERTYPE_NBS		0x0802	/* NBS Internet */
> +#define	ETHERTYPE_ECMA		0x0803	/* ECMA Internet */
> +#define	ETHERTYPE_CHAOS 	0x0804	/* CHAOSnet */
> +#define	ETHERTYPE_X25		0x0805	/* X.25 Level 3 */
> +#define	ETHERTYPE_ARP		0x0806	/* Address resolution protocol */
> +#define	ETHERTYPE_NSCOMPAT	0x0807	/* XNS Compatibility */
> +#define	ETHERTYPE_FRARP 	0x0808	/* Frame Relay ARP (RFC1701) */
> +			     /* 0x081C	   Symbolics Private */
> +		    /* 0x0888 - 0x088A	   Xyplex */
> +#define	ETHERTYPE_UBDEBUG	0x0900	/* Ungermann-Bass network debugger */
> +#define	ETHERTYPE_IEEEPUP	0x0A00	/* Xerox IEEE802.3 PUP */
> +#define	ETHERTYPE_IEEEPUPAT	0x0A01	/* Xerox IEEE802.3 PUP Address Translation */
> +#define	ETHERTYPE_VINES 	0x0BAD	/* Banyan VINES */
> +#define	ETHERTYPE_VINESLOOP	0x0BAE	/* Banyan VINES Loopback */
> +#define	ETHERTYPE_VINESECHO	0x0BAF	/* Banyan VINES Echo */
> +
> +/*		       0x1000 - 0x100F	   Berkeley Trailer */
> +/*
> + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
> + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
> + * by an ETHER type (as given above) and then the (variable-length) header.
> + */
> +#define	ETHERTYPE_TRAIL		0x1000	/* Trailer packet */
> +#define	ETHERTYPE_NTRAILER	16
> +
> +#define	ETHERTYPE_DCA		0x1234	/* DCA - Multicast */
> +#define	ETHERTYPE_VALID 	0x1600	/* VALID system protocol */
> +#define	ETHERTYPE_DOGFIGHT	0x1989	/* Artificial Horizons ("Aviator" dogfight simulator [on Sun]) */
> +#define	ETHERTYPE_RCL		0x1995	/* Datapoint Corporation (RCL lan protocol) */
> +
> +					/* The following 3C0x types
> +					   are unregistered: */
> +#define	ETHERTYPE_NBPVCD	0x3C00	/* 3Com NBP virtual circuit datagram (like XNS SPP) not registered */
> +#define	ETHERTYPE_NBPSCD	0x3C01	/* 3Com NBP System control datagram not registered */
> +#define	ETHERTYPE_NBPCREQ	0x3C02	/* 3Com NBP Connect request (virtual cct) not registered */
> +#define	ETHERTYPE_NBPCRSP	0x3C03	/* 3Com NBP Connect repsonse not registered */
> +#define	ETHERTYPE_NBPCC		0x3C04	/* 3Com NBP Connect complete not registered */
> +#define	ETHERTYPE_NBPCLREQ	0x3C05	/* 3Com NBP Close request (virtual cct) not registered */
> +#define	ETHERTYPE_NBPCLRSP	0x3C06	/* 3Com NBP Close response not registered */
> +#define	ETHERTYPE_NBPDG		0x3C07	/* 3Com NBP Datagram (like XNS IDP) not registered */
> +#define	ETHERTYPE_NBPDGB	0x3C08	/* 3Com NBP Datagram broadcast not registered */
> +#define	ETHERTYPE_NBPCLAIM	0x3C09	/* 3Com NBP Claim NetBIOS name not registered */
> +#define	ETHERTYPE_NBPDLTE	0x3C0A	/* 3Com NBP Delete Netbios name not registered */
> +#define	ETHERTYPE_NBPRAS	0x3C0B	/* 3Com NBP Remote adaptor status request not registered */
> +#define	ETHERTYPE_NBPRAR	0x3C0C	/* 3Com NBP Remote adaptor response not registered */
> +#define	ETHERTYPE_NBPRST	0x3C0D	/* 3Com NBP Reset not registered */
> +
> +#define	ETHERTYPE_PCS		0x4242	/* PCS Basic Block Protocol */
> +#define	ETHERTYPE_IMLBLDIAG	0x424C	/* Information Modes Little Big LAN diagnostic */
> +#define	ETHERTYPE_DIDDLE	0x4321	/* THD - Diddle */
> +#define	ETHERTYPE_IMLBL		0x4C42	/* Information Modes Little Big LAN */
> +#define	ETHERTYPE_SIMNET	0x5208	/* BBN Simnet Private */
> +#define	ETHERTYPE_DECEXPER	0x6000	/* DEC Unassigned, experimental */
> +#define	ETHERTYPE_MOPDL		0x6001	/* DEC MOP dump/load */
> +#define	ETHERTYPE_MOPRC		0x6002	/* DEC MOP remote console */
> +#define	ETHERTYPE_DECnet	0x6003	/* DEC DECNET Phase IV route */
> +#define	ETHERTYPE_DN		ETHERTYPE_DECnet	/* libpcap, tcpdump */
> +#define	ETHERTYPE_LAT		0x6004	/* DEC LAT */
> +#define	ETHERTYPE_DECDIAG	0x6005	/* DEC diagnostic protocol (at interface initialization?) */
> +#define	ETHERTYPE_DECCUST	0x6006	/* DEC customer protocol */
> +#define	ETHERTYPE_SCA		0x6007	/* DEC LAVC, SCA */
> +#define	ETHERTYPE_AMBER		0x6008	/* DEC AMBER */
> +#define	ETHERTYPE_DECMUMPS	0x6009	/* DEC MUMPS */
> +		    /* 0x6010 - 0x6014	   3Com Corporation */
> +#define	ETHERTYPE_TRANSETHER	0x6558	/* Trans Ether Bridging (RFC1701)*/
> +#define	ETHERTYPE_RAWFR		0x6559	/* Raw Frame Relay (RFC1701) */
> +#define	ETHERTYPE_UBDL		0x7000	/* Ungermann-Bass download */
> +#define	ETHERTYPE_UBNIU		0x7001	/* Ungermann-Bass NIUs */
> +#define	ETHERTYPE_UBDIAGLOOP	0x7002	/* Ungermann-Bass diagnostic/loopback */
> +#define	ETHERTYPE_UBNMC		0x7003	/* Ungermann-Bass ??? (NMC to/from UB Bridge) */
> +#define	ETHERTYPE_UBBST		0x7005	/* Ungermann-Bass Bridge Spanning Tree */
> +#define	ETHERTYPE_OS9		0x7007	/* OS/9 Microware */
> +#define	ETHERTYPE_OS9NET	0x7009	/* OS/9 Net? */
> +		    /* 0x7020 - 0x7029	   LRT (England) (now Sintrom) */
> +#define	ETHERTYPE_RACAL		0x7030	/* Racal-Interlan */
> +#define	ETHERTYPE_PRIMENTS	0x7031	/* Prime NTS (Network Terminal Service) */
> +#define	ETHERTYPE_CABLETRON	0x7034	/* Cabletron */
> +#define	ETHERTYPE_CRONUSVLN	0x8003	/* Cronus VLN */
> +#define	ETHERTYPE_CRONUS	0x8004	/* Cronus Direct */
> +#define	ETHERTYPE_HP		0x8005	/* HP Probe */
> +#define	ETHERTYPE_NESTAR	0x8006	/* Nestar */
> +#define	ETHERTYPE_ATTSTANFORD	0x8008	/* AT&T/Stanford (local use) */
> +#define	ETHERTYPE_EXCELAN	0x8010	/* Excelan */
> +#define	ETHERTYPE_SG_DIAG	0x8013	/* SGI diagnostic type */
> +#define	ETHERTYPE_SG_NETGAMES	0x8014	/* SGI network games */
> +#define	ETHERTYPE_SG_RESV	0x8015	/* SGI reserved type */
> +#define	ETHERTYPE_SG_BOUNCE	0x8016	/* SGI bounce server */
> +#define	ETHERTYPE_APOLLODOMAIN	0x8019	/* Apollo DOMAIN */
> +#define	ETHERTYPE_TYMSHARE	0x802E	/* Tymeshare */
> +#define	ETHERTYPE_TIGAN		0x802F	/* Tigan, Inc. */
> +#define	ETHERTYPE_REVARP	0x8035	/* Reverse addr resolution protocol */
> +#define	ETHERTYPE_AEONIC	0x8036	/* Aeonic Systems */
> +#define	ETHERTYPE_IPXNEW	0x8037	/* IPX (Novell Netware?) */
> +#define	ETHERTYPE_LANBRIDGE	0x8038	/* DEC LANBridge */
> +#define	ETHERTYPE_DSMD	0x8039	/* DEC DSM/DDP */
> +#define	ETHERTYPE_ARGONAUT	0x803A	/* DEC Argonaut Console */
> +#define	ETHERTYPE_VAXELN	0x803B	/* DEC VAXELN */
> +#define	ETHERTYPE_DECDNS	0x803C	/* DEC DNS Naming Service */
> +#define	ETHERTYPE_ENCRYPT	0x803D	/* DEC Ethernet Encryption */
> +#define	ETHERTYPE_DECDTS	0x803E	/* DEC Distributed Time Service */
> +#define	ETHERTYPE_DECLTM	0x803F	/* DEC LAN Traffic Monitor */
> +#define	ETHERTYPE_DECNETBIOS	0x8040	/* DEC PATHWORKS DECnet NETBIOS Emulation */
> +#define	ETHERTYPE_DECLAST	0x8041	/* DEC Local Area System Transport */
> +			     /* 0x8042	   DEC Unassigned */
> +#define	ETHERTYPE_PLANNING	0x8044	/* Planning Research Corp. */
> +		    /* 0x8046 - 0x8047	   AT&T */
> +#define	ETHERTYPE_DECAM		0x8048	/* DEC Availability Manager for Distributed Systems DECamds (but someone at DEC says not) */
> +#define	ETHERTYPE_EXPERDATA	0x8049	/* ExperData */
> +#define	ETHERTYPE_VEXP		0x805B	/* Stanford V Kernel exp. */
> +#define	ETHERTYPE_VPROD		0x805C	/* Stanford V Kernel prod. */
> +#define	ETHERTYPE_ES		0x805D	/* Evans & Sutherland */
> +#define	ETHERTYPE_LITTLE	0x8060	/* Little Machines */
> +#define	ETHERTYPE_COUNTERPOINT	0x8062	/* Counterpoint Computers */
> +		    /* 0x8065 - 0x8066	   Univ. of Mass @ Amherst */
> +#define	ETHERTYPE_VEECO		0x8067	/* Veeco Integrated Auto. */
> +#define	ETHERTYPE_GENDYN	0x8068	/* General Dynamics */
> +#define	ETHERTYPE_ATT		0x8069	/* AT&T */
> +#define	ETHERTYPE_AUTOPHON	0x806A	/* Autophon */
> +#define	ETHERTYPE_COMDESIGN	0x806C	/* ComDesign */
> +#define	ETHERTYPE_COMPUGRAPHIC	0x806D	/* Compugraphic Corporation */
> +		    /* 0x806E - 0x8077	   Landmark Graphics Corp. */
> +#define	ETHERTYPE_MATRA		0x807A	/* Matra */
> +#define	ETHERTYPE_DDE		0x807B	/* Dansk Data Elektronik */
> +#define	ETHERTYPE_MERIT		0x807C	/* Merit Internodal (or Univ of Michigan?) */
> +		    /* 0x807D - 0x807F	   Vitalink Communications */
> +#define	ETHERTYPE_VLTLMAN	0x8080	/* Vitalink TransLAN III Management */
> +		    /* 0x8081 - 0x8083	   Counterpoint Computers */
> +		    /* 0x8088 - 0x808A	   Xyplex */
> +#define	ETHERTYPE_ATALK		0x809B	/* AppleTalk */
> +#define	ETHERTYPE_AT		ETHERTYPE_ATALK		/* old NetBSD */
> +#define	ETHERTYPE_APPLETALK	ETHERTYPE_ATALK		/* HP-UX */
> +		    /* 0x809C - 0x809E	   Datability */
> +#define	ETHERTYPE_SPIDER	0x809F	/* Spider Systems Ltd. */
> +			     /* 0x80A3	   Nixdorf */
> +		    /* 0x80A4 - 0x80B3	   Siemens Gammasonics Inc. */
> +		    /* 0x80C0 - 0x80C3	   DCA (Digital Comm. Assoc.) Data Exchange Cluster */
> +		    /* 0x80C4 - 0x80C5	   Banyan Systems */
> +#define	ETHERTYPE_PACER		0x80C6	/* Pacer Software */
> +#define	ETHERTYPE_APPLITEK	0x80C7	/* Applitek Corporation */
> +		    /* 0x80C8 - 0x80CC	   Intergraph Corporation */
> +		    /* 0x80CD - 0x80CE	   Harris Corporation */
> +		    /* 0x80CF - 0x80D2	   Taylor Instrument */
> +		    /* 0x80D3 - 0x80D4	   Rosemount Corporation */
> +#define	ETHERTYPE_SNA		0x80D5	/* IBM SNA Services over Ethernet */
> +#define	ETHERTYPE_VARIAN	0x80DD	/* Varian Associates */
> +		    /* 0x80DE - 0x80DF	   TRFS (Integrated Solutions Transparent Remote File System) */
> +		    /* 0x80E0 - 0x80E3	   Allen-Bradley */
> +		    /* 0x80E4 - 0x80F0	   Datability */
> +#define	ETHERTYPE_RETIX		0x80F2	/* Retix */
> +#define	ETHERTYPE_AARP		0x80F3	/* AppleTalk AARP */
> +		    /* 0x80F4 - 0x80F5	   Kinetics */
> +#define	ETHERTYPE_APOLLO	0x80F7	/* Apollo Computer */
> +#define ETHERTYPE_VLAN		0x8100	/* IEEE 802.1Q VLAN tagging (XXX conflicts) */
> +		    /* 0x80FF - 0x8101	   Wellfleet Communications (XXX conflicts) */
> +#define	ETHERTYPE_BOFL		0x8102	/* Wellfleet; BOFL (Breath OF Life) pkts [every 5-10 secs.] */
> +#define	ETHERTYPE_WELLFLEET	0x8103	/* Wellfleet Communications */
> +		    /* 0x8107 - 0x8109	   Symbolics Private */
> +#define	ETHERTYPE_TALARIS	0x812B	/* Talaris */
> +#define	ETHERTYPE_WATERLOO	0x8130	/* Waterloo Microsystems Inc. (XXX which?) */
> +#define	ETHERTYPE_HAYES		0x8130	/* Hayes Microcomputers (XXX which?) */
> +#define	ETHERTYPE_VGLAB		0x8131	/* VG Laboratory Systems */
> +		    /* 0x8132 - 0x8137	   Bridge Communications */
> +#define	ETHERTYPE_IPX		0x8137	/* Novell (old) NetWare IPX (ECONFIG E option) */
> +#define	ETHERTYPE_NOVELL	0x8138	/* Novell, Inc. */
> +		    /* 0x8139 - 0x813D	   KTI */
> +#define	ETHERTYPE_MUMPS		0x813F	/* M/MUMPS data sharing */
> +#define	ETHERTYPE_AMOEBA	0x8145	/* Vrije Universiteit (NL) Amoeba 4 RPC (obsolete) */
> +#define	ETHERTYPE_FLIP		0x8146	/* Vrije Universiteit (NL) FLIP (Fast Local Internet Protocol) */
> +#define	ETHERTYPE_VURESERVED	0x8147	/* Vrije Universiteit (NL) [reserved] */
> +#define	ETHERTYPE_LOGICRAFT	0x8148	/* Logicraft */
> +#define	ETHERTYPE_NCD		0x8149	/* Network Computing Devices */
> +#define	ETHERTYPE_ALPHA		0x814A	/* Alpha Micro */
> +#define	ETHERTYPE_SNMP		0x814C	/* SNMP over Ethernet (see RFC1089) */
> +		    /* 0x814D - 0x814E	   BIIN */
> +#define	ETHERTYPE_TEC	0x814F	/* Technically Elite Concepts */
> +#define	ETHERTYPE_RATIONAL	0x8150	/* Rational Corp */
> +		    /* 0x8151 - 0x8153	   Qualcomm */
> +		    /* 0x815C - 0x815E	   Computer Protocol Pty Ltd */
> +		    /* 0x8164 - 0x8166	   Charles River Data Systems */
> +#define	ETHERTYPE_XTP		0x817D	/* Protocol Engines XTP */
> +#define	ETHERTYPE_SGITW		0x817E	/* SGI/Time Warner prop. */
> +#define	ETHERTYPE_HIPPI_FP	0x8180	/* HIPPI-FP encapsulation */
> +#define	ETHERTYPE_STP		0x8181	/* Scheduled Transfer STP, HIPPI-ST */
> +		    /* 0x8182 - 0x8183	   Reserved for HIPPI-6400 */
> +		    /* 0x8184 - 0x818C	   SGI prop. */
> +#define	ETHERTYPE_MOTOROLA	0x818D	/* Motorola */
> +#define	ETHERTYPE_NETBEUI	0x8191	/* PowerLAN NetBIOS/NetBEUI (PC) */
> +		    /* 0x819A - 0x81A3	   RAD Network Devices */
> +		    /* 0x81B7 - 0x81B9	   Xyplex */
> +		    /* 0x81CC - 0x81D5	   Apricot Computers */
> +		    /* 0x81D6 - 0x81DD	   Artisoft Lantastic */
> +		    /* 0x81E6 - 0x81EF	   Polygon */
> +		    /* 0x81F0 - 0x81F2	   Comsat Labs */
> +		    /* 0x81F3 - 0x81F5	   SAIC */
> +		    /* 0x81F6 - 0x81F8	   VG Analytical */
> +		    /* 0x8203 - 0x8205	   QNX Software Systems Ltd. */
> +		    /* 0x8221 - 0x8222	   Ascom Banking Systems */
> +		    /* 0x823E - 0x8240	   Advanced Encryption Systems */
> +		    /* 0x8263 - 0x826A	   Charles River Data Systems */
> +		    /* 0x827F - 0x8282	   Athena Programming */
> +		    /* 0x829A - 0x829B	   Inst Ind Info Tech */
> +		    /* 0x829C - 0x82AB	   Taurus Controls */
> +		    /* 0x82AC - 0x8693	   Walker Richer & Quinn */
> +#define	ETHERTYPE_ACCTON	0x8390	/* Accton Technologies (unregistered) */
> +#define	ETHERTYPE_TALARISMC	0x852B	/* Talaris multicast */
> +#define	ETHERTYPE_KALPANA	0x8582	/* Kalpana */
> +		    /* 0x8694 - 0x869D	   Idea Courier */
> +		    /* 0x869E - 0x86A1	   Computer Network Tech */
> +		    /* 0x86A3 - 0x86AC	   Gateway Communications */
> +#define	ETHERTYPE_SECTRA	0x86DB	/* SECTRA */
> +#define	ETHERTYPE_IPV6		0x86DD	/* IP protocol version 6 */
> +#define	ETHERTYPE_DELTACON	0x86DE	/* Delta Controls */
> +#define	ETHERTYPE_ATOMIC	0x86DF	/* ATOMIC */
> +		    /* 0x86E0 - 0x86EF	   Landis & Gyr Powers */
> +		    /* 0x8700 - 0x8710	   Motorola */
> +#define	ETHERTYPE_RDP		0x8739	/* Control Technology Inc. RDP Without IP */
> +#define	ETHERTYPE_MICP		0x873A	/* Control Technology Inc. Mcast Industrial Ctrl Proto. */
> +		    /* 0x873B - 0x873C	   Control Technology Inc. Proprietary */
> +#define	ETHERTYPE_TCPCOMP	0x876B	/* TCP/IP Compression (RFC1701) */
> +#define	ETHERTYPE_IPAS		0x876C	/* IP Autonomous Systems (RFC1701) */
> +#define	ETHERTYPE_SECUREDATA	0x876D	/* Secure Data (RFC1701) */
> +#define	ETHERTYPE_FLOWCONTROL	0x8808	/* 802.3x flow control packet */
> +#define	ETHERTYPE_PPP		0x880B	/* PPP (obsolete by PPPOE) */
> +#define	ETHERTYPE_HITACHI	0x8820	/* Hitachi Cable (Optoelectronic Systems Laboratory) */
> +#define	ETHERTYPE_MPLS		0x8847	/* MPLS Unicast */
> +#define	ETHERTYPE_MPLS_MCAST	0x8848	/* MPLS Multicast */
> +#define	ETHERTYPE_AXIS		0x8856	/* Axis Communications AB proprietary bootstrap/config */
> +#define	ETHERTYPE_PPPOEDISC	0x8863	/* PPP Over Ethernet Discovery Stage */
> +#define	ETHERTYPE_PPPOE		0x8864	/* PPP Over Ethernet Session Stage */
> +#define	ETHERTYPE_LANPROBE	0x8888	/* HP LanProbe test? */
> +#define	ETHERTYPE_LOOPBACK	0x9000	/* Loopback: used to test interfaces */
> +#define	ETHERTYPE_LBACK		ETHERTYPE_LOOPBACK	/* DEC MOP loopback */
> +#define	ETHERTYPE_XNSSM		0x9001	/* 3Com (Formerly Bridge Communications), XNS Systems Management */
> +#define	ETHERTYPE_TCPSM		0x9002	/* 3Com (Formerly Bridge Communications), TCP/IP Systems Management */
> +#define	ETHERTYPE_BCLOOP	0x9003	/* 3Com (Formerly Bridge Communications), loopback detection */
> +#define	ETHERTYPE_DEBNI		0xAAAA	/* DECNET? Used by VAX 6220 DEBNI */
> +#define	ETHERTYPE_SONIX		0xFAF5	/* Sonix Arpeggio */
> +#define	ETHERTYPE_VITAL		0xFF00	/* BBN VITAL-LanBridge cache wakeups */
> +		    /* 0xFF00 - 0xFFOF	   ISC Bunker Ramo */
> +
> +#define	ETHERTYPE_MAX		0xFFFF	/* Maximum valid ethernet type, reserved */
>  
>  /*
>   * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
> Index: src.gre/sys/net/if_gre.h
> ===================================================================
> RCS file: src.gre/sys/net/if_gre.h
> diff -N src.gre/sys/net/if_gre.h
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ src.gre/sys/net/if_gre.h	1 Dec 2002 12:44:46 -0000
> @@ -0,0 +1,174 @@
> +/*	$NetBSD: if_gre.h,v 1.10 2002/02/24 17:22:20 martin Exp $ */
> +/*	 $FreeBSD$ */
> +
> +/*
> + * Copyright (c) 1998 The NetBSD Foundation, Inc.
> + * All rights reserved
> + *
> + * This code is derived from software contributed to The NetBSD Foundation
> + * by Heiko W.Rupp <hwr@pilhuhn.de>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *        This product includes software developed by the NetBSD
> + *        Foundation, Inc. and its contributors.
> + * 4. Neither the name of The NetBSD Foundation nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *    
> + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef _NET_IF_GRE_H
> +#define _NET_IF_GRE_H
> +
> +#include <sys/ioccom.h>
> +#ifdef _KERNEL
> +#include <sys/queue.h>
> +
> +struct gre_softc {
> +	struct ifnet sc_if;
> +	LIST_ENTRY(gre_softc) sc_list;
> +	int gre_unit;
> +	int gre_flags;
> +	struct in_addr g_src;	/* source address of gre packets */
> +	struct in_addr g_dst;	/* destination address of gre packets */
> +	struct route route;	/* routing entry that determines, where a
> +				   encapsulated packet should go */
> +	u_char g_proto;		/* protocol of encapsulator */
> +
> +	const struct encaptab *encap;	/* encapsulation cookie */
> +
> +	int called;		/* infinite recursion preventer */
> +
> +	struct resource *r_unit;/* resource allocated for this unit */
> +};	
> +
> +
> +struct gre_h {
> +	u_int16_t flags;	/* GRE flags */
> +	u_int16_t ptype;	/* protocol type of payload typically 
> +				   Ether protocol type*/
> +/* 
> + *  from here on: fields are optional, presence indicated by flags 
> + *
> +	u_int_16 checksum	checksum (one-complements of GRE header
> +				and payload
> +				Present if (ck_pres | rt_pres == 1).
> +				Valid if (ck_pres == 1).
> +	u_int_16 offset		offset from start of routing filed to
> +				first octet of active SRE (see below).
> +				Present if (ck_pres | rt_pres == 1).
> +				Valid if (rt_pres == 1).
> +	u_int_32 key		inserted by encapsulator e.g. for
> +				authentication
> +				Present if (key_pres ==1 ).
> +	u_int_32 seq_num	Sequence number to allow for packet order
> +				Present if (seq_pres ==1 ).
> +	struct gre_sre[] routing Routing fileds (see below)
> +				Present if (rt_pres == 1)
> + */
> +} __attribute__((__packed__));
> +
> +struct greip {
> +	struct ip gi_i;
> +	struct gre_h  gi_g;
> +} __attribute__((__packed__));
> +
> +#define gi_pr		gi_i.ip_p
> +#define gi_len		gi_i.ip_len
> +#define gi_src		gi_i.ip_src
> +#define gi_dst		gi_i.ip_dst
> +#define gi_ptype	gi_g.ptype
> +#define gi_flags	gi_g.flags
> +
> +#define GRE_CP		0x8000  /* Checksum Present */
> +#define GRE_RP		0x4000  /* Routing Present */
> +#define GRE_KP		0x2000  /* Key Present */
> +#define GRE_SP		0x1000  /* Sequence Present */
> +#define GRE_SS		0x0800	/* Strict Source Route */
> +
> +/*
> + * CISCO uses special type for GRE tunnel created as part of WCCP
> + * connection, while in fact those packets are just IPv4 encapsulated
> + * into GRE.
> + */
> +#define WCCP_PROTOCOL_TYPE	0x883E
> +
> +/*
> + * gre_sre defines a Source route Entry. These are needed if packets
> + * should be routed over more than one tunnel hop by hop
> + */
> +struct gre_sre {
> +	u_int16_t sre_family;	/* adress family */
> +	u_char	sre_offset;	/* offset to first octet of active entry */
> +	u_char	sre_length;	/* number of octets in the SRE. 
> +				   sre_lengthl==0 -> last entry. */
> +	u_char	*sre_rtinfo;	/* the routing information */
> +};
> +
> +struct greioctl {
> +	int unit;
> +	struct in_addr addr;
> +};
> +
> +/* for mobile encaps */
> +
> +struct mobile_h {
> +	u_int16_t proto;		/* protocol and S-bit */
> +	u_int16_t hcrc;			/* header checksum */
> +	u_int32_t odst;			/* original destination address */
> +	u_int32_t osrc;			/* original source addr, if S-bit set */
> +} __attribute__((__packed__));
> +
> +struct mobip_h {
> +	struct ip	mi;
> +	struct mobile_h	mh;
> +} __attribute__((__packed__));
> +
> +
> +#define MOB_H_SIZ_S		(sizeof(struct mobile_h) - sizeof(u_int32_t))
> +#define MOB_H_SIZ_L		(sizeof(struct mobile_h))
> +#define MOB_H_SBIT	0x0080
> +
> +#define	GRE_TTL	30
> +
> +#endif /* _KERNEL */
> +
> +/* 
> + * ioctls needed to manipulate the interface 
> + */
> +
> +#define GRESADDRS	_IOW('i', 101, struct ifreq)
> +#define GRESADDRD	_IOW('i', 102, struct ifreq)   
> +#define GREGADDRS	_IOWR('i', 103, struct ifreq)
> +#define GREGADDRD	_IOWR('i', 104, struct ifreq)
> +#define GRESPROTO	_IOW('i' , 105, struct ifreq)
> +#define GREGPROTO	_IOWR('i', 106, struct ifreq)
> +
> +#ifdef _KERNEL
> +LIST_HEAD(gre_softc_head, gre_softc);
> +extern struct gre_softc_head gre_softc_list;
> +
> +u_short	gre_in_cksum(u_short *p, u_int len);
> +#endif /* _KERNEL */
> +
> +#endif
> Index: src.gre/sys/netatalk/at.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/netatalk/at.h,v
> retrieving revision 1.5
> diff -d -u -r1.5 at.h
> --- src.gre/sys/netatalk/at.h	3 Feb 1998 21:56:42 -0000	1.5
> +++ src.gre/sys/netatalk/at.h	1 Dec 2002 12:44:46 -0000
> @@ -19,6 +19,8 @@
>   *	Ann Arbor, Michigan
>   *	+1-313-763-0525
>   *	netatalk@itd.umich.edu
> + *
> + * $FreeBSD$
>   */
>  
>  #ifndef __AT_HEADER__
> @@ -28,14 +30,6 @@
>   */
>  #define ATPROTO_DDP	0
>  #define ATPROTO_AARP	254
> -
> -/*
> - * Ethernet types, for DIX.
> - * These should really be in some global header file, but we can't
> - * count on them being there, and it's annoying to patch system files.
> - */
> -#define ETHERTYPE_AT	0x809B		/* AppleTalk protocol */
> -#define ETHERTYPE_AARP	0x80F3		/* AppleTalk ARP */
>  
>  #define DDP_MAXSZ	587
>  
> Index: src.gre/sys/conf/options
> ===================================================================
> RCS file: /home/ncvs/src/sys/conf/options,v
> retrieving revision 1.191.2.44
> diff -d -u -r1.191.2.44 options
> --- src.gre/sys/conf/options	1 Sep 2002 07:18:21 -0000	1.191.2.44
> +++ src.gre/sys/conf/options	1 Dec 2002 12:44:46 -0000
> @@ -284,6 +284,7 @@
>  LIBMCHAIN
>  NCP			opt_ncp.h
>  NETATALK		opt_atalk.h
> +NS			opt_ns.h
>  PPP_BSDCOMP		opt_ppp.h
>  PPP_DEFLATE		opt_ppp.h
>  PPP_FILTER		opt_ppp.h
> Index: src.gre/sys/conf/files
> ===================================================================
> RCS file: /home/ncvs/src/sys/conf/files,v
> retrieving revision 1.340.2.124
> diff -d -u -r1.340.2.124 files
> --- src.gre/sys/conf/files	21 Nov 2002 23:45:37 -0000	1.340.2.124
> +++ src.gre/sys/conf/files	1 Dec 2002 12:44:46 -0000
> @@ -738,6 +738,7 @@
>  net/if_faith.c		optional faith
>  net/if_fddisubr.c	optional fddi
>  net/if_gif.c		optional gif
> +net/if_gre.c		optional gre
>  net/if_loop.c		optional loop
>  net/if_media.c		standard
>  net/if_mib.c		standard
> @@ -894,6 +895,7 @@
>  netinet/igmp.c		optional inet
>  netinet/in.c		optional inet
>  #netinet/in_hostcache.c	optional inet
> +netinet/ip_gre.c	optional gre inet
>  netinet/ip_id.c		optional inet
>  netinet/in_pcb.c	optional inet
>  netinet/in_proto.c	optional inet
> Index: src.gre/sys/netinet/ip_gre.c
> ===================================================================
> RCS file: src.gre/sys/netinet/ip_gre.c
> diff -N src.gre/sys/netinet/ip_gre.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ src.gre/sys/netinet/ip_gre.c	1 Dec 2002 12:44:48 -0000
> @@ -0,0 +1,352 @@
> +/*	$NetBSD: ip_gre.c,v 1.21 2002/08/14 00:23:30 itojun Exp $ */
> +/*	 $FreeBSD$ */
> +
> +/*
> + * Copyright (c) 1998 The NetBSD Foundation, Inc.
> + * All rights reserved.
> + *
> + * This code is derived from software contributed to The NetBSD Foundation
> + * by Heiko W.Rupp <hwr@pilhuhn.de>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *        This product includes software developed by the NetBSD
> + *        Foundation, Inc. and its contributors.
> + * 4. Neither the name of The NetBSD Foundation nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * deencapsulate tunneled packets and send them on
> + * output half is in net/if_gre.[ch]
> + * This currently handles IPPROTO_GRE, IPPROTO_MOBILE
> + */
> +
> +#include "opt_inet.h"
> +#include "opt_ns.h"
> +#include "opt_atalk.h"
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/mbuf.h>
> +#include <sys/socket.h>
> +#include <sys/socketvar.h>
> +#include <sys/protosw.h>
> +#include <sys/errno.h>
> +#include <sys/time.h>
> +#include <sys/kernel.h>
> +#include <sys/syslog.h>
> +#include <net/bpf.h>
> +#include <net/ethernet.h>
> +#include <net/if.h>
> +#include <net/netisr.h>
> +#include <net/route.h>
> +#include <net/raw_cb.h>
> +
> +#ifdef INET
> +#include <netinet/in.h>
> +#include <netinet/in_var.h>
> +#include <netinet/in_systm.h>
> +#include <netinet/ip.h>
> +#include <netinet/ip_var.h>
> +#include <netinet/ip_gre.h>
> +#include <machine/in_cksum.h>
> +#else
> +#error ip_gre input without IP?
> +#endif
> +
> +#ifdef NS
> +#include <netns/ns.h>
> +#include <netns/ns_if.h>
> +#endif
> +
> +#ifdef NETATALK
> +#include <netatalk/at.h>
> +#include <netatalk/at_var.h>
> +#include <netatalk/at_extern.h>
> +#endif
> +
> +/* Needs IP headers. */
> +#include <net/if_gre.h>
> +
> +#include <machine/stdarg.h>
> +
> +#if 1
> +void gre_inet_ntoa(struct in_addr in); 	/* XXX */
> +#endif
> +
> +static struct gre_softc *gre_lookup(struct mbuf *, u_int8_t);
> +
> +static int	gre_input2(struct mbuf *, int, u_char);
> +
> +/*
> + * De-encapsulate a packet and feed it back through ip input (this
> + * routine is called whenever IP gets a packet with proto type
> + * IPPROTO_GRE and a local destination address).
> + * This really is simple
> + */
> +void
> +#if __STDC__
> +gre_input(struct mbuf *m, ...)
> +#else
> +gre_input(m, va_alist)
> +        struct mbuf *m;
> +        va_dcl
> +#endif
> +{
> +	int off, ret, proto;
> +	va_list ap;
> +
> +	va_start(ap, m);
> +	off = va_arg(ap, int);
> +	va_end(ap);
> +	proto = (mtod(m, struct ip *))->ip_p;
> +
> +	ret = gre_input2(m, off, proto);
> +	/*
> +	 * ret == 0 : packet not processed, meaning that 
> +	 * no matching tunnel that is up is found.
> +	 * we inject it to raw ip socket to see if anyone picks it up.
> +	 */
> +	if (ret == 0)
> +		rip_input(m, off, proto);
> +}
> +
> +/*
> + * decapsulate.
> + * Does the real work and is called from gre_input() (above)
> + * returns 0 if packet is not yet processed
> + * and 1 if it needs no further processing
> + * proto is the protocol number of the "calling" foo_input()
> + * routine.
> + */
> +
> +static int
> +gre_input2(struct mbuf *m ,int hlen, u_char proto)
> +{
> +	struct greip *gip = mtod(m, struct greip *);
> +	int s;
> +	struct ifqueue *ifq;
> +	struct gre_softc *sc;
> +	u_short flags;
> +
> +	if ((sc = gre_lookup(m, proto)) == NULL) {
> +		/* No matching tunnel or tunnel is down. */
> +		return (0);
> +	}
> +
> +	sc->sc_if.if_ipackets++;
> +	sc->sc_if.if_ibytes += m->m_pkthdr.len;
> +
> +	switch (proto) {
> +	case IPPROTO_GRE:
> +		hlen += sizeof (struct gre_h);
> +
> +		/* process GRE flags as packet can be of variable len */
> +		flags = ntohs(gip->gi_flags);
> +
> +		/* Checksum & Offset are present */
> +		if ((flags & GRE_CP) | (flags & GRE_RP))
> +			hlen += 4;
> +		/* We don't support routing fields (variable length) */
> +		if (flags & GRE_RP)
> +			return(0);
> +		if (flags & GRE_KP)
> +			hlen += 4;
> +		if (flags & GRE_SP)
> +			hlen +=4;
> +
> +		switch (ntohs(gip->gi_ptype)) { /* ethertypes */
> +		case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
> +		case WCCP_PROTOCOL_TYPE: /* we are in ip_input */
> +			ifq = &ipintrq;
> +			break;
> +#ifdef NS
> +		case ETHERTYPE_NS:
> +			ifq = &nsintrq;
> +			schednetisr(NETISR_NS);
> +			break;
> +#endif
> +#ifdef NETATALK
> +		case ETHERTYPE_ATALK:
> +			ifq = &atintrq1;
> +			schednetisr(NETISR_ATALK);
> +			break;
> +#endif
> +		case ETHERTYPE_IPV6:
> +			/* FALLTHROUGH */
> +		default:	   /* others not yet supported */
> +			return(0);
> +		}
> +		break;
> +	default:
> +		/* others not yet supported */
> +		return(0);
> +	}
> +
> +	m->m_data += hlen;
> +	m->m_len -= hlen;
> +	m->m_pkthdr.len -= hlen;
> +
> +	if (sc->sc_if.if_bpf) {
> +		struct mbuf m0;
> +		u_int32_t af = AF_INET;
> +
> +		m0.m_next = m;
> +		m0.m_len = 4;
> +		m0.m_data = (char *)&af;
> +
> +		bpf_mtap(&(sc->sc_if), &m0);
> +	}
> +
> +	m->m_pkthdr.rcvif = &sc->sc_if;
> +
> +	s = splnet();		/* possible */
> +	if (_IF_QFULL(ifq)) {
> +		IF_DROP(ifq);
> +		m_freem(m);
> +	} else {
> +		IF_ENQUEUE(ifq,m);
> +	}
> +	splx(s);
> +
> +	return(1);	/* packet is done, no further processing needed */
> +}
> +
> +/*
> + * input routine for IPPRPOTO_MOBILE
> + * This is a little bit diffrent from the other modes, as the
> + * encapsulating header was not prepended, but instead inserted
> + * between IP header and payload
> + */
> +
> +void
> +#if __STDC__
> +gre_mobile_input(struct mbuf *m, ...)
> +#else
> +gre_mobile_input(m, va_alist)
> +        struct mbuf *m;
> +        va_dcl
> +#endif
> +{
> +	struct ip *ip = mtod(m, struct ip *);
> +	struct mobip_h *mip = mtod(m, struct mobip_h *);
> +	struct ifqueue *ifq;
> +	struct gre_softc *sc;
> +	int hlen,s;
> +	va_list ap;
> +	u_char osrc = 0;
> +	int msiz;
> +
> +	va_start(ap,m);
> +	hlen = va_arg(ap, int);
> +	va_end(ap);
> +
> +	if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) {
> +		/* No matching tunnel or tunnel is down. */
> +		m_freem(m);
> +		return;
> +	}
> +
> +	sc->sc_if.if_ipackets++;
> +	sc->sc_if.if_ibytes += m->m_pkthdr.len;
> +
> +	if(ntohs(mip->mh.proto) & MOB_H_SBIT) {
> +		osrc = 1;
> +		msiz = MOB_H_SIZ_L;
> +		mip->mi.ip_src.s_addr = mip->mh.osrc;
> +	} else {
> +		msiz = MOB_H_SIZ_S;
> +	}
> +	mip->mi.ip_dst.s_addr = mip->mh.odst;
> +	mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8);
> +
> +	if (gre_in_cksum((u_short*)&mip->mh,msiz) != 0) {
> +		m_freem(m);
> +		return;
> +	}
> +
> +	bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) +
> +	    (ip->ip_hl << 2), m->m_len - msiz - (ip->ip_hl << 2));
> +	m->m_len -= msiz;
> +	m->m_pkthdr.len -= msiz;
> +
> +	/*
> +	 * On FreeBSD, rip_input() supplies us with ip->ip_len
> +	 * already converted into host byteorder and also decreases
> +	 * it by the lengh of IP header, however, ip_input() expects
> +	 * that this field is in the original format (network byteorder
> +	 * and full size of IP packet), so that adjust accordingly.
> +	 */
> +	ip->ip_len = htons(ip->ip_len + sizeof(struct ip) - msiz);
> +	
> +	ip->ip_sum = 0;
> +	ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
> +
> +	if (sc->sc_if.if_bpf) {
> +		struct mbuf m0;
> +		u_int af = AF_INET;
> +
> +		m0.m_next = m;
> +		m0.m_len = 4;
> +		m0.m_data = (char *)&af;
> +
> +		bpf_mtap(&(sc->sc_if), &m0);
> +	}
> +
> +	m->m_pkthdr.rcvif = &sc->sc_if;
> +
> +	ifq = &ipintrq;
> +	s = splnet();       /* possible */
> +	if (_IF_QFULL(ifq)) {
> +		IF_DROP(ifq);
> +		m_freem(m);
> +	} else {
> +		IF_ENQUEUE(ifq,m);
> +	}
> +	splx(s);
> +}
> +
> +/*
> + * Find the gre interface associated with our src/dst/proto set.
> + */
> +static struct gre_softc *
> +gre_lookup(m, proto)
> +	struct mbuf *m;
> +	u_int8_t proto;
> +{
> +	struct ip *ip = mtod(m, struct ip *);
> +	struct gre_softc *sc;
> +
> +	for (sc = LIST_FIRST(&gre_softc_list); sc != NULL;
> +	     sc = LIST_NEXT(sc, sc_list)) {
> +		if ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
> +		    (sc->g_src.s_addr == ip->ip_dst.s_addr) &&
> +		    (sc->g_proto == proto) &&
> +		    ((sc->sc_if.if_flags & IFF_UP) != 0))
> +			return (sc);
> +	}
> +
> +	return (NULL);
> +}
> Index: src.gre/sys/netinet/in_proto.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/in_proto.c,v
> retrieving revision 1.53.2.4
> diff -d -u -r1.53.2.4 in_proto.c
> --- src.gre/sys/netinet/in_proto.c	24 Jul 2001 19:10:18 -0000	1.53.2.4
> +++ src.gre/sys/netinet/in_proto.c	1 Dec 2002 12:44:48 -0000
> @@ -162,6 +162,18 @@
>    encap_init,		0,		0,		0,
>    &rip_usrreqs
>  },
> +{ SOCK_RAW,	&inetdomain,	IPPROTO_MOBILE,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
> +  encap4_input,	0,		0,		rip_ctloutput,
> +  0,
> +  encap_init,	0,		0,		0,
> +  &rip_usrreqs
> +},
> +{ SOCK_RAW,	&inetdomain,	IPPROTO_GRE,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
> +  encap4_input,	0,		0,		rip_ctloutput,
> +  0,
> +  encap_init,	0,		0,		0,
> +  &rip_usrreqs
> +},
>  # ifdef INET6
>  { SOCK_RAW,	&inetdomain,	IPPROTO_IPV6,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
>    encap4_input,	0,	 	0,		rip_ctloutput,
> Index: src.gre/sys/netinet/ip_gre.h
> ===================================================================
> RCS file: src.gre/sys/netinet/ip_gre.h
> diff -N src.gre/sys/netinet/ip_gre.h
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ src.gre/sys/netinet/ip_gre.h	1 Dec 2002 12:44:48 -0000
> @@ -0,0 +1,43 @@
> +/*	$NetBSD: ip_gre.h,v 1.5 2002/06/09 16:33:40 itojun Exp $ */
> +/*	 $FreeBSD$ */
> +
> +/*
> + * Copyright (c) 1998 The NetBSD Foundation, Inc.
> + * All rights reserved.
> + *
> + * This code is derived from software contributed to The NetBSD Foundation
> + * by Heiko W.Rupp <hwr@pilhuhn.de>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *        This product includes software developed by the NetBSD
> + *        Foundation, Inc. and its contributors.
> + * 4. Neither the name of The NetBSD Foundation nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifdef _KERNEL
> +void gre_input(struct mbuf *, ...);
> +void gre_mobile_input(struct mbuf *, ...);
> +#endif /* _KERNEL */
> Index: src.gre/sys/netinet/in.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/in.h,v
> retrieving revision 1.48.2.8
> diff -d -u -r1.48.2.8 in.h
> --- src.gre/sys/netinet/in.h	2 May 2002 02:36:50 -0000	1.48.2.8
> +++ src.gre/sys/netinet/in.h	1 Dec 2002 12:44:48 -0000
> @@ -101,7 +101,9 @@
>  #define	IPPROTO_INLSP		52		/* Integ. Net Layer Security */
>  #define	IPPROTO_SWIPE		53		/* IP with encryption */
>  #define	IPPROTO_NHRP		54		/* Next Hop Resolution */
> -/* 55-57: Unassigned */
> +#define	IPPROTO_MOBILE		55		/* IP Mobility */
> +#define	IPPROTO_TLSP		56		/* Transport Layer Security */
> +#define	IPPROTO_SKIP		57		/* SKIP */
>  #define	IPPROTO_ICMPV6		58		/* ICMP6 */
>  #define	IPPROTO_NONE		59		/* IP6 no next header */
>  #define	IPPROTO_DSTOPTS		60		/* IP6 destination option */
> @@ -477,6 +479,9 @@
>  
>  int	prison_ip __P((struct proc *p, int flag, u_int32_t *ip));
>  void	prison_remote_ip __P((struct proc *p, int flag, u_int32_t *ip));
> +
> +#define in_hosteq(s, t)	((s).s_addr == (t).s_addr)
> +#define in_nullhost(x)	((x).s_addr == INADDR_ANY)
>  
>  #define satosin(sa)	((struct sockaddr_in *)(sa))
>  #define sintosa(sin)	((struct sockaddr *)(sin))
> Index: src.gre/sys/modules/if_gre/Makefile
> ===================================================================
> RCS file: src.gre/sys/modules/if_gre/Makefile
> diff -N src.gre/sys/modules/if_gre/Makefile
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ src.gre/sys/modules/if_gre/Makefile	1 Dec 2002 12:44:48 -0000
> @@ -0,0 +1,17 @@
> +# $FreeBSD$
> +
> +.PATH: ${.CURDIR}/../../net ${.CURDIR}/../../netinet 
> +
> +KMOD=	if_gre
> +SRCS=	if_gre.c ip_gre.c opt_inet.h opt_ns.h opt_atalk.h
> +
> +opt_inet.h:
> +	echo "#define INET 1" > ${.TARGET}
> +
> +opt_ns.h:
> +	echo "#define NS 1" > ${.TARGET}
> +
> +opt_atalk.h:
> +	echo "#define NETATALK 1" > ${.TARGET}
> +
> +.include <bsd.kmod.mk>
> Index: src.gre/sys/modules/Makefile
> ===================================================================
> RCS file: /home/ncvs/src/sys/modules/Makefile,v
> retrieving revision 1.110.2.62
> diff -d -u -r1.110.2.62 Makefile
> --- src.gre/sys/modules/Makefile	21 Nov 2002 23:42:20 -0000	1.110.2.62
> +++ src.gre/sys/modules/Makefile	1 Dec 2002 12:44:48 -0000
> @@ -27,6 +27,7 @@
>  	if_ef \
>  	if_faith \
>  	if_gif \
> +	if_gre \
>  	if_ppp \
>  	if_sl \
>  	if_stf \
> Index: src.gre/sys/i386/conf/LINT
> ===================================================================
> RCS file: /home/ncvs/src/sys/i386/conf/Attic/LINT,v
> retrieving revision 1.749.2.133
> diff -d -u -r1.749.2.133 LINT
> --- src.gre/sys/i386/conf/LINT	22 Nov 2002 01:34:57 -0000	1.749.2.133
> +++ src.gre/sys/i386/conf/LINT	1 Dec 2002 12:44:51 -0000
> @@ -495,6 +495,8 @@
>  #  The `gif' pseudo-device implements IPv6 over IP4 tunneling,
>  #  IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
>  #  IPv6 over IPv6 tunneling.
> +#  The `gre' device implements two types of IP4 over IP4 tunneling:
> +#  GRE and MOBILE, as specified in the RFC1701 and RFC2004.
>  #  The `faith' pseudo-device captures packets sent to it and diverts them
>  #  to the IPv4/IPv6 translation daemon.
>  #  The `stf' device implements 6to4 encapsulation.
> @@ -518,6 +520,7 @@
>  pseudo-device	disc			#Discard device (ds0, ds1, etc)
>  pseudo-device	tun			#Tunnel driver (ppp(8), nos-tun(8))
>  pseudo-device	sl	2		#Serial Line IP
> +pseudo-device	gre			#IP over IP tunneling
>  pseudo-device	ppp	2		#Point-to-point protocol
>  options 	PPP_BSDCOMP		#PPP BSD-compress support
>  options 	PPP_DEFLATE		#PPP zlib/deflate/gzip support
> Index: src.gre/share/man/man4/Makefile
> ===================================================================
> RCS file: /home/ncvs/src/share/man/man4/Makefile,v
> retrieving revision 1.83.2.52
> diff -d -u -r1.83.2.52 Makefile
> --- src.gre/share/man/man4/Makefile	21 Nov 2002 01:28:16 -0000	1.83.2.52
> +++ src.gre/share/man/man4/Makefile	1 Dec 2002 12:44:51 -0000
> @@ -46,6 +46,7 @@
>  	fwohci.4 \
>  	fxp.4 \
>  	gif.4 \
> +	gre.4 \
>  	gusc.4 \
>  	gx.4 \
>  	ichsmb.4 \
> Index: src.gre/share/man/man4/gre.4
> ===================================================================
> RCS file: src.gre/share/man/man4/gre.4
> diff -N src.gre/share/man/man4/gre.4
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ src.gre/share/man/man4/gre.4	1 Dec 2002 12:44:51 -0000
> @@ -0,0 +1,279 @@
> +.\" $NetBSD: gre.4,v 1.28 2002/06/10 02:49:35 itojun Exp $
> +.\"  $FreeBSD$
> +.\"
> +.\" Copyright 1998 (c) The NetBSD Foundation, Inc.
> +.\" All rights reserved.
> +.\"
> +.\" This code is derived from software contributed to The NetBSD Foundation
> +.\" by Heiko W.Rupp <hwr@pilhuhn.de>
> +.\"
> +.\" Redistribution and use in source and binary forms, with or without
> +.\" modification, are permitted provided that the following conditions
> +.\" are met:
> +.\" 1. Redistributions of source code must retain the above copyright
> +.\"    notice, this list of conditions and the following disclaimer.
> +.\" 2. Redistributions in binary form must reproduce the above copyright
> +.\"    notice, this list of conditions and the following disclaimer in the
> +.\"    documentation and/or other materials provided with the distribution.
> +.\" 3. All advertising materials mentioning features or use of this software
> +.\"    must display the following acknowledgement:
> +.\"     This product includes software developed by the NetBSD
> +.\"	Foundation, Inc. and its contributors.
> +.\" 4. Neither the name of the The NetBSD Foundation nor the names of its
> +.\"    contributors may be used to endorse or promote products derived
> +.\"    from this software without specific prior written permission.
> +.\"
> +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
> +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> +.\" TO, THE  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> +.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
> +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +.\" CONTRACT, STRICT  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +.\" ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +.\" POSSIBILITY OF SUCH DAMAGE.
> +.\"
> +.Dd June 9, 2002
> +.Dt GRE 4
> +.Os
> +.Sh NAME
> +.Nm gre
> +.Nd encapsulating network device
> +.Sh SYNOPSIS
> +.Cd pseudo-device gre
> +.Sh DESCRIPTION
> +The
> +.Nm gre
> +network interface pseudo device encapsulates datagrams
> +into IP.  These encapsulated datagrams are routed to a destination host,
> +where they are decapsulated and further routed to their final destination.
> +The
> +.Dq tunnel
> +appears to the inner datagrams as one hop.
> +.Pp
> +.Nm
> +interfaces are dynamically created and destroyed with the
> +.Xr ifconfig 8
> +.Cm create
> +and
> +.Cm destroy
> +subcommands.
> +.Pp
> +This driver currently supports the following modes of operation:
> +.Bl -tag -width abc
> +.It GRE encapsulation (IP protocol number 47)
> +Encapsulated datagrams are
> +prepended an outer datagram and a GRE header.  The GRE header specifies
> +the type of the encapsulated datagram and thus allows for tunneling other
> +protocols than IP like e.g. AppleTalk.  GRE mode is also the default tunnel
> +mode on Cisco routers.  This is also the default mode of operation of the
> +.Sy gre Ns Ar X
> +interfaces.
> +.It MOBILE encapsulation (IP protocol number 55)
> +Datagrams are
> +encapsulated into IP, but with a shorter encapsulation.  The original
> +IP header is modified and the modifications are inserted between the
> +so modified header and the original payload.  Like
> +.Xr gif 4 ,
> +only for IP in IP encapsulation.
> +.El
> +.Pp
> +The
> +.Sy gre Ns Ar X
> +interfaces support a number of
> +.Xr ioctl 2 Ns s ,
> +such as:
> +.Bl -tag -width aaa
> +.It GRESADDRS :
> +Set the IP address of the local tunnel end.  This is the source address
> +set by or displayed by ifconfig for the
> +.Sy gre Ns Ar X
> +interface.
> +.It GRESADDRD :
> +Set the IP address of the remote tunnel end.  This is the destination address
> +set by or displayed by ifconfig for the
> +.Sy gre Ns Ar X
> +interface.
> +.It GREGADDRS :
> +Query the IP address that is set for the local tunnel end.  This is the
> +address the encapsulation header carries as local address (i.e. the real
> +address of the tunnel start point.)
> +.It GREGADDRD :
> +Query the IP address that is set for the remote tunnel end.  This is the
> +address the encapsulated packets are sent to (i.e. the real address of
> +the remote tunnel endpoint.)
> +.It GRESPROTO :
> +Set the operation mode to the specified IP protocol value.  The
> +protocol is passed to the interface in (struct ifreq)-\*[Gt]ifr_flags.
> +The operation mode can also be given as
> +.Bl -tag -width link0xxx
> +.It link0
> +IPPROTO_GRE
> +.It -link0
> +IPPROTO_MOBILE
> +.El
> +.Pp
> +to
> +.Xr ifconfig 8 .
> +.Pp
> +The link1 flag is not used to choose encapsulation, but to modify the
> +internal route search for the remote tunnel endpoint, see the
> +.Sx BUGS
> +section below.
> +.It GREGPROTO :
> +Query operation mode.
> +.El
> +.Pp
> +Note that the IP addresses of the tunnel endpoints may be the same as the
> +ones defined with
> +.Xr ifconfig 8
> +for the interface (as if IP is encapsulated), but need not be, as e.g. when
> +encapsulating AppleTalk.
> +.Sh EXAMPLES
> +Configuration example:
> +.Bd -literal
> +Host X-- Host A  ----------------tunnel---------- cisco D------Host E
> +          \\                                          |
> +           \\                                        /
> +             +------Host B----------Host C----------+
> +.Ed
> +On host A
> +.Ns ( Nx ) :
> +.Bd -literal
> +   # route add default B
> +   # ifconfig greN create
> +   # ifconfig greN A D netmask 0xffffffff linkX up
> +   # ifconfig greN tunnel A D
> +   # route add E D
> +.Ed
> +On Host D (Cisco):
> +.Bd -literal
> +   Interface TunnelX
> +    ip unnumbered D   ! e.g. address from Ethernet interface
> +    tunnel source D   ! e.g. address from Ethernet interface
> +    tunnel destination A
> +   ip route C \*[Lt]some interface and mask\*[Gt]
> +   ip route A mask C
> +   ip route X mask tunnelX
> +.Ed
> +OR
> +On Host D
> +.Ns ( Nx ) :
> +.Bd -literal
> +   # route add default C
> +   # ifconfig greN create
> +   # ifconfig greN D A
> +   # ifconfig tunnel greN D A
> +.Ed
> +.Pp
> +If all goes well, you should see packets flowing ;-)
> +.Pp
> +If you want to reach Host A over the tunnel (from Host D (Cisco)), then
> +you have to have an alias on Host A for e.g. the Ethernet interface like:
> +.Bd -literal
> +     ifconfig \*[Lt]etherif\*[Gt] alias Y
> +.Ed
> +and on the cisco
> +.Bd -literal
> +     ip route Y mask tunnelX
> +.Ed
> +.Pp
> +A similar setup can be used to create a link between two private networks
> +(for example in the 192.168 subnet) over the Internet:
> +.Bd -literal
> +192.168.1.* --- Router A  -------tunnel-------- Router B --- 192.168.2.*
> +                   \\                              /
> +                    \\                            /
> +                      +----- the Internet ------+
> +.Ed
> +Assuming router A has the (external) IP address A and the internal address
> +192.168.1.1, while router B has external address B and internal address
> +192.168.2.1, the following commands will configure the tunnel:
> +.Pp
> +On router A:
> +.Bd -literal
> +   # ifconfig greN create
> +   # ifconfig greN 192.168.1.1 192.168.2.1 link1
> +   # ifconfig greN tunnel A B
> +   # route add -net 192.168.2 -netmask 255.255.255.0 192.168.2.1
> +.Ed
> +.Pp
> +On router B:
> +.Bd -literal
> +   # ifconfig greN create
> +   # ifconfig greN 192.168.2.1 192.168.1.1 link1
> +   # ifconfig greN tunnel B A
> +   # route add -net 192.168.1 -netmask 255.255.255.0 192.168.1.1
> +.Ed
> +.Pp
> +Note that this is a safe situation where the link1 flag (as discussed in the
> +.Sx BUGS
> +section below) may (and probably should) be set.
> +.Sh NOTES
> +The MTU of
> +.Sy gre Ns Ar X
> +interfaces is set to 1476 by default to match the value used by Cisco routers.
> +This may not be an optimal value, depending on the link between the two tunnel
> +endpoints.  It can be adjusted via
> +.Xr ifconfig 8 .
> +.Pp
> +For correct operation, the
> +.Nm
> +device needs a route to the destination that is less specific than the
> +one over the tunnel.
> +(Basically, there needs to be a route to the decapsulating host that
> +does not run over the tunnel, as this would be a loop.)
> +If the addresses are ambiguous, doing the
> +.Xr ifconfig 8
> +.Li tunnel
> +step before the
> +.Xr ifconfig 8
> +call to set the
> +.Sy gre Ns Ar X
> +IP addresses will help to find a route outside the tunnel.
> +.Pp
> +In order to tell
> +.Xr ifconfig 8
> +to actually mark the interface as up, the keyword
> +.Dq up
> +must be given last on its command line.
> +.Pp
> +The kernel must be set to forward datagrams by either option
> +.Em GATEWAY
> +in the kernel config file or by issuing the appropriate option to
> +.Xr sysctl 8 .
> +.Sh SEE ALSO
> +.Xr atalk 4 ,
> +.Xr gif 4 ,
> +.Xr inet 4 ,
> +.Xr ip 4 ,
> +.Xr netintro 4 ,
> +.Xr options 4 ,
> +.Xr protocols 5 ,
> +.Xr ifconfig 8 ,
> +.Xr sysctl 8
> +.Pp
> +A description of GRE encapsulation can be found in RFC 1701 and RFC 1702.
> +.Pp
> +A description of MOBILE encapsulation can be found in RFC 2004.
> +.Sh AUTHORS
> +.An Heiko W.Rupp Aq hwr@pilhuhn.de
> +.Sh BUGS
> +The compute_route() code in if_gre.c toggles the last bit of the
> +IP-address to provoke the search for a less specific route than the
> +one directly over the tunnel to prevent loops.  This is possibly not
> +the best solution.
> +.Pp
> +To avoid the address munging described above, turn on the link1 flag
> +on the
> +.Xr ifconfig 8
> +command line.
> +This implies that the GRE packet destination and the ifconfig remote host
> +are not the same IP addresses, and that the GRE destination does not route
> +over the
> +.Sy gre Ns Ar X
> +interface itself.
> +.Pp
> +The GRE RFCs are not yet fully implemented (no GRE options).


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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021201134009.GA86354>