Add a new gre(4) driver, which could be used to create GRE (RFC1701)
and MOBILE (RFC2004) IP tunnels. Obrained from: NetBSD
This commit is contained in:
parent
8ab96fd8d0
commit
8e96e13e6a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=103026
279
share/man/man4/gre.4
Normal file
279
share/man/man4/gre.4
Normal file
@ -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).
|
@ -1054,6 +1054,7 @@ net/if_ethersubr.c optional ether
|
||||
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_iso88025subr.c optional token
|
||||
net/if_loop.c optional loop
|
||||
net/if_media.c standard
|
||||
@ -1216,6 +1217,7 @@ netinet/if_ether.c optional ether
|
||||
netinet/igmp.c optional inet
|
||||
netinet/in.c optional inet
|
||||
netinet/in_gif.c optional gif 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
|
||||
|
@ -327,6 +327,7 @@ IPTUNNEL opt_ipx.h
|
||||
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
|
||||
|
781
sys/net/if_gre.c
Normal file
781
sys/net/if_gre.c
Normal file
@ -0,0 +1,781 @@
|
||||
/* $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 <sys/cdefs.h>
|
||||
__RCSID("@(#) $FreeBSD$");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ns.h"
|
||||
#include "bpf.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 <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/netisr.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
|
||||
|
||||
#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
|
||||
|
||||
#if NBPF > 0
|
||||
#include <sys/time.h>
|
||||
#include <net/bpf.h>
|
||||
#endif
|
||||
|
||||
#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"
|
||||
|
||||
static MALLOC_DEFINE(M_GRE, GRENAME, "Generic Routing Encapsulation");
|
||||
|
||||
struct gre_softc_head gre_softc_list;
|
||||
int ip_gre_ttl = GRE_TTL;
|
||||
|
||||
int gre_clone_create __P((struct if_clone *, int));
|
||||
void gre_clone_destroy __P((struct ifnet *));
|
||||
|
||||
struct if_clone gre_cloner =
|
||||
IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy, 0, IF_MAXUNIT);
|
||||
|
||||
int gre_compute_route(struct gre_softc *sc);
|
||||
|
||||
void greattach __P((void));
|
||||
|
||||
#ifdef INET
|
||||
extern struct domain inetdomain;
|
||||
static const struct protosw in_gre_protosw =
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_GRE, PR_ATOMIC|PR_ADDR,
|
||||
(pr_input_t*)gre_input, (pr_output_t*)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,
|
||||
(pr_input_t*)gre_mobile_input, (pr_output_t*)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 */
|
||||
void
|
||||
greattach(void)
|
||||
{
|
||||
|
||||
LIST_INIT(&gre_softc_list);
|
||||
if_clone_attach(&gre_cloner);
|
||||
}
|
||||
|
||||
int
|
||||
gre_clone_create(ifc, unit)
|
||||
struct if_clone *ifc;
|
||||
int unit;
|
||||
{
|
||||
struct gre_softc *sc;
|
||||
|
||||
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;
|
||||
if_attach(&sc->sc_if);
|
||||
#if NBPF
|
||||
bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t));
|
||||
#endif
|
||||
LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
gre_clone_destroy(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct gre_softc *sc = ifp->if_softc;
|
||||
|
||||
#ifdef INET
|
||||
if (sc->encap != NULL)
|
||||
encap_detach(sc->encap);
|
||||
#endif
|
||||
LIST_REMOVE(sc, sc_list);
|
||||
#if NBPF
|
||||
bpfdetach(ifp);
|
||||
#endif
|
||||
if_detach(ifp);
|
||||
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
|
||||
*/
|
||||
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 NBPF
|
||||
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 *)⁡
|
||||
|
||||
bpf_mtap(ifp, &m0);
|
||||
}
|
||||
#endif
|
||||
|
||||
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 = ip_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);
|
||||
}
|
||||
|
||||
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(curthread)) != 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(curthread)) != 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(curthread)) != 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(curthread)) != 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(curthread)) != 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(curthread)) != 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(curthread)) != 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(curthread)) != 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.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
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);
|
||||
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);
|
166
sys/net/if_gre.h
Normal file
166
sys/net/if_gre.h
Normal file
@ -0,0 +1,166 @@
|
||||
/* $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>
|
||||
#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 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 */
|
||||
|
||||
/*
|
||||
* 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
|
||||
extern int ip_gre_ttl;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
int gre_ioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
int gre_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *rt));
|
||||
u_short gre_in_cksum(u_short *p, u_int len);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif
|
@ -160,6 +160,18 @@ struct protosw inetsw[] = {
|
||||
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,
|
||||
|
360
sys/netinet/ip_gre.c
Normal file
360
sys/netinet/ip_gre.c
Normal file
@ -0,0 +1,360 @@
|
||||
/* $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 <sys/cdefs.h>
|
||||
__RCSID("@(#) $FreeBSD$");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ns.h"
|
||||
#include "opt_atalk.h"
|
||||
#include "bpf.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
|
||||
|
||||
struct gre_softc *gre_lookup __P((struct mbuf *, u_int8_t));
|
||||
|
||||
int gre_input2 __P((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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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 */
|
||||
ifq = &ipintrq; /* we are in ip_input */
|
||||
break;
|
||||
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 NBPF > 0
|
||||
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 *)⁡
|
||||
|
||||
bpf_mtap(&(sc->sc_if), &m0);
|
||||
}
|
||||
#endif /*NBPF > 0*/
|
||||
|
||||
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 NBPF > 0
|
||||
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 *)⁡
|
||||
|
||||
bpf_mtap(&(sc->sc_if), &m0);
|
||||
}
|
||||
#endif /*NBPFILTER > 0*/
|
||||
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
}
|
43
sys/netinet/ip_gre.h
Normal file
43
sys/netinet/ip_gre.h
Normal file
@ -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 __P((struct mbuf *, ...));
|
||||
void gre_mobile_input __P((struct mbuf *, ...));
|
||||
#endif /* _KERNEL */
|
Loading…
Reference in New Issue
Block a user