New EtherIP driver based on tap(4) and gif(4) by Hans Rosenfeld.

Notable changes:
	* Fixes PR 34268.
	* Separates the code from gif(4) (which is more cleaner).
	* Allows the usage of STP (Spanning Tree Protocol).
	* Removed EtherIP implementation from gif(4)/tap(4).

Some input from Christos.
This commit is contained in:
rpaulo 2006-11-23 04:07:07 +00:00
parent dec2eb4c9d
commit 5423539f94
20 changed files with 1665 additions and 174 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.979 2006/11/22 23:38:26 tnozaki Exp $
# $NetBSD: mi,v 1.980 2006/11/23 04:07:07 rpaulo Exp $
./etc/mtree/set.comp comp-sys-root
./usr/bin/addr2line comp-debug-bin bfd
./usr/bin/ar comp-util-bin bfd
@ -1285,6 +1285,7 @@
./usr/include/net/if_bridgevar.h comp-c-include
./usr/include/net/if_dl.h comp-c-include
./usr/include/net/if_ether.h comp-c-include
./usr/include/net/if_etherip.h comp-c-include
./usr/include/net/if_fddi.h comp-c-include
./usr/include/net/if_gif.h comp-c-include
./usr/include/net/if_gre.h comp-c-include

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.952 2006/11/12 03:02:50 christos Exp $
# $NetBSD: mi,v 1.953 2006/11/23 04:07:07 rpaulo Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -820,6 +820,7 @@
./usr/share/man/cat4/eso.0 man-sys-catman .cat
./usr/share/man/cat4/esp.0 man-sys-catman .cat
./usr/share/man/cat4/ess.0 man-sys-catman .cat
./usr/share/man/cat4/etherip.0 man-sys-catman .cat
./usr/share/man/cat4/evbarm/intro.0 man-sys-catman .cat
./usr/share/man/cat4/evbarm/iopaau.0 man-sys-catman .cat
./usr/share/man/cat4/evbarm/iopwdog.0 man-sys-catman .cat
@ -3215,6 +3216,7 @@
./usr/share/man/man4/eso.4 man-sys-man .man
./usr/share/man/man4/esp.4 man-sys-man .man
./usr/share/man/man4/ess.4 man-sys-man .man
./usr/share/man/man4/etherip.4 man-sys-man .man
./usr/share/man/man4/evbarm/intro.4 man-sys-man .man
./usr/share/man/man4/evbarm/iopaau.4 man-sys-man .man
./usr/share/man/man4/evbarm/iopwdog.4 man-sys-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.413 2006/11/09 01:29:34 pooka Exp $
# $NetBSD: Makefile,v 1.414 2006/11/23 04:07:07 rpaulo Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
@ -16,7 +16,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
ddb.4 ddc.4 de.4 dge.4 dk.4 dmoverio.4 \
dmphy.4 dpt.4 dpti.4 drum.4 eap.4 ebus.4 edc.4 \
elmc.4 emuxki.4 en.4 envsys.4 ep.4 esh.4 esis.4 \
esa.4 esiop.4 esl.4 esm.4 eso.4 exphy.4 fast_ipsec.4 fd.4 \
esa.4 esiop.4 esl.4 esm.4 eso.4 etherip.4 exphy.4 fast_ipsec.4 fd.4 \
fpa.4 fms.4 fss.4 fxp.4 gem.4 gentbi.4 \
glxtphy.4 gpib.4 gpio.4 gre.4 gphyter.4 gsip.4 hifn.4 hme.4 \
hptide.4 icmp.4 icp.4 icsphy.4 ieee80211.4 ifmedia.4 \

174
share/man/man4/etherip.4 Normal file
View File

@ -0,0 +1,174 @@
.\" $NetBSD: etherip.4,v 1.1 2006/11/23 04:07:07 rpaulo Exp $
.\"
.\" Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>.
.\" All rights reserved.
.\"
.\" 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. Neither the name of Hans Rosenfeld nor the names of his contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
.\"
.\"
.\" Copyright (c) 2004, 2005 The NetBSD Foundation.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to the NetBSD Foundation
.\" by Quentin Garnier.
.\"
.\" 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.
.\"
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\"
.\" 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. Neither the name of the project 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 PROJECT 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 PROJECT 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 October 29, 2006
.Dt ETHERIP 4
.Os
.Sh NAME
.Nm etherip
.Nd EtherIP tunneling device
.Sh SYNOPSIS
.Cd "pseudo-device etherip"
.Sh DESCRIPTION
The
.Nm
interface is a tunneling pseudo device for ethernet frames.
It can tunnel ethernet traffic over IPv4 and IPv6 using the EtherIP
protocol specified in RFC 3378.
.Pp
The only difference between an
.Nm
interface and a real ethernet interface is that there is an IP tunnel
instead of a wire.
Therefore, to use
.Nm
the administrator must first create the interface
and then configure protocol and addresses used for the outer
header.
This can be done by using
.Xr ifconfig 8
.Cm create
and
.Cm tunnel
subcommands, or
.Dv SIOCIFCREATE
and
.Dv SIOCSLIFPHYADDR
ioctls.
.Ss Packet format
Ethernet frames are prepended with a EtherIP header as described by
RFC 3378. The resulting EtherIP packets will be encapsulated in an
outer packet, which may be either an IPv4 or IPv6 packet, with IP
protocol number 97.
.Ss Ethernet address
When a
.Nm
device is created, it is assigned an Ethernet address
of the form f2:0b:a5:xx:xx:xx.
This address can later be changed through a sysctl node.
.Pp
The sysctl node is net.link.etherip.\*[Lt]iface\*[Gt].
Any string of six colon-separated hexadecimal numbers will be accepted.
Reading that node will provide a string representation of the current
Ethernet address.
.Ss Security
The EtherIP header of incoming packets is not checked for
validity. This is because there seems to be some confusion about how
such a header has to look like. For outgoing packets, the header is
set up the same way as done in OpenBSD, FreeBSD and Linux to be
compatible with those systems.
.Ss Converting from previous implementation
A tunnel configured for the previous (undocumented) implementation
will work with just renaming the device from gif to
.Nm .
.Sh SEE ALSO
.Xr bridge 4 ,
.Xr gif 4,
.Xr tap 4,
.Xr inet 4 ,
.Xr inet6 4 ,
.Xr ifconfig 8
.\"
.Sh HISTORY
The
.Nm
device first appeared in NetBSD 4.0, it is based on
.Xr tap 4 ,
.Xr gif 4
and the former gif-based EtherIP implementation ported from OpenBSD.
.\"
.Sh BUGS
Probably many. There is lots of code duplication between
.Nm ,
.Xr tap 4 ,
.Xr gif 4
and probably other tunnelling drivers which should be cleaned up.

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.817 2006/11/22 02:02:51 elad Exp $
# $NetBSD: files,v 1.818 2006/11/23 04:07:07 rpaulo Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@ -1148,6 +1148,7 @@ defpseudo faith: ifnet
defpseudo stf: ifnet
defpseudo tap { }: ifnet, ether, arp, bpf_filter
defpseudo carp: ifnet, ether, arp, bpf_filter
defpseudo etherip { }: ifnet, ether, arp, bpf_filter
defpseudo sequencer
defpseudo clockctl
@ -1386,6 +1387,7 @@ file net/if_atmsubr.c atm
file net/if_bridge.c bridge needs-flag
file net/bridgestp.c bridge
file net/if_ecosubr.c eco
file net/if_etherip.c etherip needs-flag
file net/if_ethersubr.c ether | fddi | netatalk | token |
wlan
file net/if_faith.c faith & inet & inet6 needs-flag
@ -1422,7 +1424,9 @@ file netinet/in_gif.c gif & inet
file netinet/ip_carp.c carp & (inet | inet6) needs-flag
file netinet/ip_ecn.c ipsec | fast_ipsec | gif | stf
file netinet/ip_encap.c inet | inet6
file netinet/ip_etherip.c etherip & inet
file netinet/ip_gre.c inet & gre
file netinet6/ip6_etherip.c etherip & inet6
file netinet6/in6_gif.c gif & inet6
file netisdn/i4b_ctl.c isdnctl needs-flag

View File

@ -1,9 +1,9 @@
# $NetBSD: Makefile,v 1.19 2006/06/18 21:02:16 uwe Exp $
# $NetBSD: Makefile,v 1.20 2006/11/23 04:07:07 rpaulo Exp $
INCSDIR= /usr/include/net
INCS= bpf.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \
if_atm.h if_bridgevar.h if_dl.h if_ether.h if_fddi.h if_gif.h \
if_atm.h if_bridgevar.h if_dl.h if_ether.h if_etherip.h if_fddi.h if_gif.h \
if_gre.h if_hippi.h if_ieee1394.h if_llc.h if_media.h \
if_ppp.h if_pppoe.h if_sppp.h if_stf.h \
if_tap.h if_token.h if_tun.h if_types.h if_vlanvar.h \

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bridge.c,v 1.45 2006/11/16 01:33:40 christos Exp $ */
/* $NetBSD: if_bridge.c,v 1.46 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -80,13 +80,12 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.45 2006/11/16 01:33:40 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.46 2006/11/23 04:07:07 rpaulo Exp $");
#include "opt_bridge_ipf.h"
#include "opt_inet.h"
#include "opt_pfil_hooks.h"
#include "bpfilter.h"
#include "gif.h"
#include <sys/param.h>
#include <sys/kernel.h>
@ -595,10 +594,6 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
*/
(void) ifpromisc(ifs, 0);
break;
#if NGIF > 0
case IFT_GIF:
break;
#endif
default:
#ifdef DIAGNOSTIC
panic("bridge_delete_member: impossible");
@ -651,10 +646,6 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
if (error)
goto out;
break;
#if NGIF > 0
case IFT_GIF:
break;
#endif
default:
error = EINVAL;
goto out;
@ -1504,20 +1495,6 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
return (m);
/* Perform the bridge forwarding function with the copy. */
#if NGIF > 0
if (ifp->if_type == IFT_GIF) {
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
if (bif->bif_ifp->if_type == IFT_ETHER)
break;
}
if (bif != NULL) {
m->m_flags |= M_PROTO1;
m->m_pkthdr.rcvif = bif->bif_ifp;
(*bif->bif_ifp->if_input)(bif->bif_ifp, m);
m = NULL;
}
}
#endif
bridge_forward(sc, mc);
/* Return the original packet for local processing. */
@ -1537,8 +1514,6 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
* Unicast. Make sure it's not for us.
*/
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
if(bif->bif_ifp->if_type != IFT_ETHER)
continue;
/* It is destined for us. */
if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
ETHER_ADDR_LEN) == 0
@ -1551,14 +1526,6 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
(void) bridge_rtupdate(sc,
eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
m->m_pkthdr.rcvif = bif->bif_ifp;
#if NGIF > 0
if (ifp->if_type == IFT_GIF) {
m->m_flags |= M_PROTO1;
m->m_pkthdr.rcvif = bif->bif_ifp;
(*bif->bif_ifp->if_input)(bif->bif_ifp, m);
m = NULL;
}
#endif
return (m);
}

712
sys/net/if_etherip.c Normal file
View File

@ -0,0 +1,712 @@
/* $NetBSD: if_etherip.c,v 1.1 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* All rights reserved.
*
* 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. Neither the name of Hans Rosenfeld nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
*
* Copyright (c) 2003, 2004 The NetBSD Foundation.
* All rights reserved.
*
* This code is derived from software contributed to the NetBSD Foundation
* by Quentin Garnier
*
* 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.
*
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
#include <sys/cdefs.h>
#include "opt_inet.h"
#include "bpfilter.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/kauth.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_ether.h>
#include <net/if_media.h>
#include <net/route.h>
#include <net/if_etherip.h>
#if NBPFILTER > 0
#include <net/bpf.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifdef INET
#include <netinet/in_var.h>
#endif /* INET */
#include <netinet/ip_etherip.h>
#ifdef INET6
#include <netinet6/ip6_etherip.h>
#ifndef INET
#include <netinet/in.h>
#endif
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_gif.h>
#include <netinet6/ip6protosw.h>
#endif /* INET6 */
static int etherip_node;
static int etherip_sysctl_handler(SYSCTLFN_PROTO);
SYSCTL_SETUP_PROTO(sysctl_etherip_setup);
void etheripattach(int);
static int etherip_match(struct device *, struct cfdata *, void *);
static void etherip_attach(struct device *, struct device *, void *);
static int etherip_detach(struct device *, int);
static int etherip_ether_aton(u_char *, char *);
CFATTACH_DECL(etherip, sizeof(struct etherip_softc),
etherip_match, etherip_attach, etherip_detach, NULL);
extern struct cfdriver etherip_cd;
static void etherip_start(struct ifnet *);
static void etherip_stop(struct ifnet *, int);
static int etherip_init(struct ifnet *);
static int etherip_ioctl(struct ifnet *, u_long, caddr_t);
static int etherip_mediachange(struct ifnet *);
static void etherip_mediastatus(struct ifnet *, struct ifmediareq *);
static int etherip_clone_create(struct if_clone *, int);
static int etherip_clone_destroy(struct ifnet *);
static struct if_clone etherip_cloners = IF_CLONE_INITIALIZER(
"etherip", etherip_clone_create, etherip_clone_destroy);
static int etherip_set_tunnel(struct ifnet *,
struct sockaddr *, struct sockaddr *);
static void etherip_delete_tunnel(struct ifnet *);
static void etheripintr(void *);
void
etheripattach(int count)
{
int error;
error = config_cfattach_attach(etherip_cd.cd_name, &etherip_ca);
if (error) {
aprint_error("%s: unable to register cfattach\n",
etherip_cd.cd_name);
(void)config_cfdriver_detach(&etherip_cd);
return;
}
LIST_INIT(&etherip_softc_list);
if_clone_attach(&etherip_cloners);
}
/* Pretty much useless for a pseudo-device */
static int
etherip_match(struct device *self, struct cfdata *cfdata, void *arg)
{
return 1;
}
static void
etherip_attach(struct device *parent, struct device *self, void *aux)
{
struct etherip_softc *sc = (struct etherip_softc *)self;
struct ifnet *ifp;
const struct sysctlnode *node;
u_int8_t enaddr[ETHER_ADDR_LEN] =
{ 0xf2, 0x0b, 0xa5, 0xff, 0xff, 0xff };
char enaddrstr[3 * ETHER_ADDR_LEN];
struct timeval tv;
uint32_t ui;
int error;
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
sc->sc_si = NULL;
#endif
sc->sc_src = NULL;
sc->sc_dst = NULL;
sc->sc_route_expire = 0;
/*
* In order to obtain unique initial Ethernet address on a host,
* do some randomisation using the current uptime. It's not meant
* for anything but avoiding hard-coding an address.
*/
getmicrouptime(&tv);
ui = (tv.tv_sec ^ tv.tv_usec) & 0xffffff;
memcpy(enaddr+3, (u_int8_t *)&ui, 3);
aprint_verbose("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
ether_snprintf(enaddrstr, sizeof(enaddrstr), enaddr));
/*
* Why 1000baseT? Why not? You can add more.
*
* Note that there are 3 steps: init, one or several additions to
* list of supported media, and in the end, the selection of one
* of them.
*/
ifmedia_init(&sc->sc_im, 0, etherip_mediachange, etherip_mediastatus);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T, 0, NULL);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX, 0, NULL);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T, 0, NULL);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_AUTO, 0, NULL);
ifmedia_set(&sc->sc_im, IFM_ETHER|IFM_AUTO);
/*
* One should note that an interface must do multicast in order
* to support IPv6.
*/
ifp = &sc->sc_ec.ec_if;
strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = etherip_ioctl;
ifp->if_start = etherip_start;
ifp->if_stop = etherip_stop;
ifp->if_init = etherip_init;
IFQ_SET_READY(&ifp->if_snd);
sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
/*
* Those steps are mandatory for an Ethernet driver, the first call
* being common to all network interface drivers.
*/
if_attach(ifp);
ether_ifattach(ifp, enaddr);
/*
* Add a sysctl node for that interface.
*
* The pointer transmitted is not a string, but instead a pointer to
* the softc structure, which we can use to build the string value on
* the fly in the helper function of the node. See the comments for
* etherip_sysctl_handler for details.
*/
error = sysctl_createv(NULL, 0, NULL, &node, CTLFLAG_READWRITE,
CTLTYPE_STRING, sc->sc_dev.dv_xname, NULL,
etherip_sysctl_handler, 0, sc, 18, CTL_NET,
AF_LINK, etherip_node, device_unit(&sc->sc_dev),
CTL_EOL);
if (error)
aprint_error("%s: sysctl_createv returned %d, ignoring\n",
sc->sc_dev.dv_xname, error);
/* insert into etherip_softc_list */
LIST_INSERT_HEAD(&etherip_softc_list, sc, etherip_list);
}
/*
* When detaching, we do the inverse of what is done in the attach
* routine, in reversed order.
*/
static int
etherip_detach(struct device* self, int flags)
{
struct etherip_softc *sc = (struct etherip_softc *)self;
struct ifnet *ifp = &sc->sc_ec.ec_if;
int error, s;
s = splnet();
etherip_stop(ifp, 1);
if_down(ifp);
splx(s);
/*
* Destroying a single leaf is a very straightforward operation using
* sysctl_destroyv. One should be sure to always end the path with
* CTL_EOL.
*/
error = sysctl_destroyv(NULL, CTL_NET, AF_LINK, etherip_node,
device_unit(&sc->sc_dev), CTL_EOL);
if (error)
aprint_error("%s: sysctl_destroyv returned %d, ignoring\n",
sc->sc_dev.dv_xname, error);
LIST_REMOVE(sc, etherip_list);
etherip_delete_tunnel(ifp);
ether_ifdetach(ifp);
if_detach(ifp);
ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY);
return 0;
}
/*
* This function is called by the ifmedia layer to notify the driver
* that the user requested a media change. A real driver would
* reconfigure the hardware.
*/
static int
etherip_mediachange(struct ifnet *ifp)
{
return 0;
}
/*
* Here the user asks for the currently used media.
*/
static void
etherip_mediastatus(struct ifnet *ifp, struct ifmediareq *imr)
{
struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
imr->ifm_active = sc->sc_im.ifm_cur->ifm_media;
}
static void
etherip_start(struct ifnet *ifp)
{
struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
if(sc->sc_si)
softintr_schedule(sc->sc_si);
#else
etheripintr(sc);
#endif
}
static void
etheripintr(void *arg)
{
struct etherip_softc *sc = (struct etherip_softc *)arg;;
struct ifnet *ifp = &sc->sc_ec.ec_if;;
struct mbuf *m;
int s, error;
for (;;) {
s = splnet();
IFQ_DEQUEUE(&ifp->if_snd, m);
splx(s);
if (m == NULL)
return;
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
#endif
ifp->if_opackets++;
if (sc->sc_src && sc->sc_dst) {
ifp->if_flags |= IFF_OACTIVE;
switch (sc->sc_src->sa_family) {
#ifdef INET
case AF_INET:
error = ip_etherip_output(ifp, m);
break;
#endif
#ifdef INET6
case AF_INET6:
error = ip6_etherip_output(ifp, m);
break;
#endif
default:
error = ENETDOWN;
}
ifp->if_flags &= ~IFF_OACTIVE;
} else m_freem(m);
}
}
static int
etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct sockaddr *src, *dst;
int s, error;
switch (cmd) {
case SIOCSLIFPHYADDR:
src = (struct sockaddr *)
&(((struct if_laddrreq *)data)->addr);
dst = (struct sockaddr *)
&(((struct if_laddrreq *)data)->dstaddr);
/* sa_family must be equal */
if (src->sa_family != dst->sa_family)
return EINVAL;
/* validate sa_len */
switch (src->sa_family) {
#ifdef INET
case AF_INET:
if (src->sa_len != sizeof(struct sockaddr_in) ||
dst->sa_len != sizeof(struct sockaddr_in))
return EINVAL;
break;
#endif
#ifdef INET6
case AF_INET6:
if (src->sa_len != sizeof(struct sockaddr_in6) ||
dst->sa_len != sizeof(struct sockaddr_in6))
return EINVAL;
break;
#endif
default:
return EAFNOSUPPORT;
}
error = etherip_set_tunnel(ifp, src, dst);
break;
case SIOCDIFPHYADDR:
etherip_delete_tunnel(ifp);
error = 0;
break;
case SIOCGLIFPHYADDR:
if (sc->sc_src == NULL || sc->sc_dst == NULL)
return EADDRNOTAVAIL;
/* copy src */
src = sc->sc_src;
dst = (struct sockaddr *)
&(((struct if_laddrreq *)data)->addr);
if (src->sa_len > sizeof(((struct if_laddrreq *)data)->addr))
return EINVAL;
memcpy(dst, src, src->sa_len);
/* copy dst */
src = sc->sc_dst;
dst = (struct sockaddr *)
&(((struct if_laddrreq *)data)->dstaddr);
if (src->sa_len > sizeof(((struct if_laddrreq *)data)->dstaddr))
return EINVAL;
memcpy(dst, src, src->sa_len);
error = 0;
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
s = splnet();
error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);
splx(s);
break;
default:
s = splnet();
error = ether_ioctl(ifp, cmd, data);
splx(s);
if (error == ENETRESET)
error = 0;
break;
}
return (error);
}
static int
etherip_set_tunnel(struct ifnet *ifp,
struct sockaddr *src,
struct sockaddr *dst)
{
struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
struct etherip_softc *sc2;
struct sockaddr *osrc, *odst;
int s, error = 0;
s = splsoftnet();
LIST_FOREACH(sc2, &etherip_softc_list, etherip_list) {
if (sc2 == sc)
continue;
if (!sc2->sc_dst || !sc2->sc_src)
continue;
if (sc2->sc_dst->sa_family != dst->sa_family ||
sc2->sc_dst->sa_len != dst->sa_len ||
sc2->sc_src->sa_family != src->sa_family ||
sc2->sc_src->sa_len != src->sa_len)
continue;
/* can't configure same pair of address onto two tunnels */
if (bcmp(sc2->sc_dst, dst, dst->sa_len) == 0 &&
bcmp(sc2->sc_src, src, src->sa_len) == 0) {
error = EADDRNOTAVAIL;
goto out;
}
/* XXX both end must be valid? (I mean, not 0.0.0.0) */
}
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
if (sc->sc_si) {
softintr_disestablish(sc->sc_si);
sc->sc_si = NULL;
}
#endif
ifp->if_flags &= ~IFF_RUNNING;
osrc = sc->sc_src; sc->sc_src = NULL;
odst = sc->sc_dst; sc->sc_dst = NULL;
sc->sc_src = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
memcpy(sc->sc_src, src, src->sa_len);
if (osrc) FREE(osrc, M_IFADDR);
sc->sc_dst = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
memcpy(sc->sc_dst, dst, dst->sa_len);
if (odst) FREE(odst, M_IFADDR);
ifp->if_flags |= IFF_RUNNING;
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
sc->sc_si = softintr_establish(IPL_SOFTNET, etheripintr, sc);
if (sc->sc_si == NULL)
error = ENOMEM;
#endif
out:
splx(s);
return(error);
}
static void
etherip_delete_tunnel(struct ifnet *ifp)
{
struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
int s;
s = splsoftnet();
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
if (sc->sc_si) {
softintr_disestablish(sc->sc_si);
sc->sc_si = NULL;
}
#endif
if (sc->sc_src) {
FREE(sc->sc_src, M_IFADDR);
sc->sc_src = NULL;
}
if (sc->sc_dst) {
FREE(sc->sc_dst, M_IFADDR);
sc->sc_dst = NULL;
}
ifp->if_flags &= ~IFF_RUNNING;
splx(s);
}
static int
etherip_init(struct ifnet *ifp)
{
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
struct etherip_softc *sc = ifp->if_softc;
if (sc->sc_si == NULL)
sc->sc_si = softintr_establish(IPL_SOFTNET, etheripintr, sc);
if (sc->sc_si == NULL)
return(ENOMEM);
#endif
ifp->if_flags |= IFF_RUNNING;
etherip_start(ifp);
return 0;
}
static void
etherip_stop(struct ifnet *ifp, int disable)
{
ifp->if_flags &= ~IFF_RUNNING;
}
static int
etherip_clone_create(struct if_clone *ifc, int unit)
{
struct cfdata *cf;
MALLOC(cf, struct cfdata *, sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
cf->cf_name = etherip_cd.cd_name;
cf->cf_atname = etherip_ca.ca_name;
cf->cf_unit = unit;
cf->cf_fstate = FSTATE_STAR;
if (config_attach_pseudo(cf) == NULL) {
aprint_error("%s%d: unable to attach an instance\n",
etherip_cd.cd_name, unit);
return (ENXIO);
}
return 0;
}
static int
etherip_clone_destroy(struct ifnet *ifp)
{
struct device *dev = (struct device *)ifp->if_softc;
struct cfdata *cf = device_cfdata(dev);
int error;
if ((error = config_detach(dev, 0)) != 0)
aprint_error("%s: unable to detach instance\n",
dev->dv_xname);
FREE(cf, M_DEVBUF);
return error;
}
SYSCTL_SETUP(sysctl_etherip_setup, "sysctl net.link.etherip subtree setup")
{
const struct sysctlnode *node;
int error = 0;
error = sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "net", NULL,
NULL, 0, NULL, 0,
CTL_NET, CTL_EOL);
if (error)
return;
error = sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "link", NULL,
NULL, 0, NULL, 0,
CTL_NET, AF_LINK, CTL_EOL);
if (error)
return;
error = sysctl_createv(clog, 0, NULL, &node,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "etherip", NULL,
NULL, 0, NULL, 0,
CTL_NET, AF_LINK, CTL_CREATE, CTL_EOL);
if (error)
return;
etherip_node = node->sysctl_num;
}
static int
etherip_sysctl_handler(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct etherip_softc *sc;
struct ifnet *ifp;
int error;
size_t len;
char addr[3 * ETHER_ADDR_LEN];
node = *rnode;
sc = node.sysctl_data;
ifp = &sc->sc_ec.ec_if;
(void)ether_snprintf(addr, sizeof(addr), LLADDR(ifp->if_sadl));
node.sysctl_data = addr;
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
len = strlen(addr);
if (len < 11 || len > 17)
return EINVAL;
/* Commit change */
if (ether_snprintf(addr, sizeof(addr), LLADDR(ifp->if_sadl)) != 0)
return EINVAL;
return error;
}

80
sys/net/if_etherip.h Normal file
View File

@ -0,0 +1,80 @@
/* $NetBSD: if_etherip.h,v 1.1 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* All rights reserved.
*
* 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. Neither the name of Hans Rosenfeld nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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_ETHERIP_H_
#define _NET_IF_ETHERIP_H_
#include <sys/queue.h>
#if defined(_KERNEL) && !defined(_LKM)
#include "opt_inet.h"
#endif
#include <netinet/in.h>
LIST_HEAD(, etherip_softc) etherip_softc_list;
struct etherip_softc {
struct device sc_dev;
struct ifmedia sc_im;
struct ethercom sc_ec;
struct sockaddr *sc_src; /* tunnel source address */
struct sockaddr *sc_dst; /* tunnel destination address */
union {
#ifdef INET
struct route scr_ro; /* cached inet route */
#endif
#ifdef INET6
struct route_in6 scr_ro6; /* cached inet6 route */
#endif
} sc_scr;
long sc_route_expire;
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
void *sc_si; /* softintr handle */
#endif
LIST_ENTRY(etherip_softc) etherip_list; /* list of etherip tunnels */
};
#define sc_ro sc_scr.scr_ro
#define sc_ro6 sc_scr.scr_ro6
struct etherip_header {
u_int8_t eip_ver; /* version/reserved */
u_int8_t eip_pad; /* required padding byte */
};
#define ETHERIP_VER_VERS_MASK 0x0f
#define ETHERIP_VER_RSVD_MASK 0xf0
#define ETHERIP_VERSION 0x03
#define ETHERIP_TTL 30
#define ETHERIP_ROUTE_TTL 10
#endif /* !_NET_IF_ETHERIP_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ethersubr.c,v 1.136 2006/09/07 02:40:33 dogcow Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.137 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.136 2006/09/07 02:40:33 dogcow Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.137 2006/11/23 04:07:07 rpaulo Exp $");
#include "opt_inet.h"
#include "opt_atalk.h"
@ -698,22 +698,18 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
* process it locally.
*/
if (ifp->if_bridge) {
if(m->m_flags & M_PROTO1) {
m->m_flags &= ~M_PROTO1;
} else {
/* clear M_PROMISC, in case the packets comes from a vlan */
m->m_flags &= ~M_PROMISC;
m = bridge_input(ifp, m);
if (m == NULL)
return;
/* clear M_PROMISC, in case the packets comes from a vlan */
m->m_flags &= ~M_PROMISC;
m = bridge_input(ifp, m);
if (m == NULL)
return;
/*
* Bridge has determined that the packet is for us.
* Update our interface pointer -- we may have had
* to "bridge" the packet locally.
*/
ifp = m->m_pkthdr.rcvif;
}
/*
* Bridge has determined that the packet is for us.
* Update our interface pointer -- we may have had
* to "bridge" the packet locally.
*/
ifp = m->m_pkthdr.rcvif;
} else
#endif /* NBRIDGE > 0 */
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_gif.c,v 1.63 2006/11/16 01:33:40 christos Exp $ */
/* $NetBSD: if_gif.c,v 1.64 2006/11/23 04:07:07 rpaulo Exp $ */
/* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.63 2006/11/16 01:33:40 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.64 2006/11/23 04:07:07 rpaulo Exp $");
#include "opt_inet.h"
#include "opt_iso.h"
@ -84,12 +84,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.63 2006/11/16 01:33:40 christos Exp $")
#endif
#include <netinet/ip_encap.h>
#include <net/if_ether.h>
#include <net/if_bridgevar.h>
#include <net/if_gif.h>
#include "bpfilter.h"
#include "bridge.h"
#include <net/net_osdep.h>
@ -98,7 +95,6 @@ void gifattach(int);
static void gifnetisr(void);
#endif
static void gifintr(void *);
static void gif_start(struct ifnet *);
#ifdef ISO
static struct mbuf *gif_eon_encap(struct mbuf *);
static struct mbuf *gif_eon_decap(struct ifnet *, struct mbuf *);
@ -165,7 +161,6 @@ gifattach0(struct gif_softc *sc)
sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
sc->gif_if.if_ioctl = gif_ioctl;
sc->gif_if.if_output = gif_output;
sc->gif_if.if_start = gif_start;
sc->gif_if.if_type = IFT_GIF;
sc->gif_if.if_dlt = DLT_NULL;
IFQ_SET_READY(&sc->gif_if.if_snd);
@ -200,17 +195,6 @@ gif_clone_destroy(struct ifnet *ifp)
return (0);
}
static void
gif_start(struct ifnet *ifp)
{
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
softintr_schedule(((struct gif_softc*)ifp)->gif_si);
#else
/* XXX bad spl level? */
gifnetisr();
#endif
}
#ifdef GIF_ENCAPCHECK
int
gif_encapcheck(struct mbuf *m, int off, int proto, void *arg)
@ -241,10 +225,6 @@ gif_encapcheck(struct mbuf *m, int off, int proto, void *arg)
#ifdef ISO
case IPPROTO_EON:
break;
#endif
#if NBRIDGE > 0
case IPPROTO_ETHERIP:
break;
#endif
default:
return 0;
@ -399,17 +379,6 @@ gifintr(void *arg)
if (m == NULL)
break;
#if NBRIDGE > 0
if(m->m_flags & M_PROTO1) {
M_PREPEND(m, sizeof(int), M_DONTWAIT);
if (!m) {
ifp->if_oerrors++;
continue;
}
*mtod(m, int *) = AF_LINK;
}
#endif
/* grab and chop off inner af type */
if (sizeof(int) > m->m_len) {
m = m_pullup(m, sizeof(int));
@ -459,9 +428,6 @@ gif_input(struct mbuf *m, int af, struct ifnet *ifp)
{
int s, isr;
struct ifqueue *ifq = NULL;
#if NBRIDGE > 0
struct ether_header *eh;
#endif
if (ifp == NULL) {
/* just in case */
@ -508,37 +474,6 @@ gif_input(struct mbuf *m, int af, struct ifnet *ifp)
ifq = &clnlintrq;
isr = NETISR_ISO;
break;
#endif
#if NBRIDGE > 0
case AF_LINK:
m_adj(m, sizeof(struct etherip_header));
if (sizeof(struct ether_header) > m->m_len) {
m = m_pullup(m, sizeof(struct ether_header));
if (!m) {
ifp->if_ierrors++;
return;
}
}
eh = mtod(m, struct ether_header *);
m->m_flags &= ~(M_BCAST|M_MCAST);
if (eh->ether_dhost[0] & 1) {
if (memcmp(etherbroadcastaddr,
eh->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
m->m_flags |= M_BCAST;
else
m->m_flags |= M_MCAST;
}
m->m_pkthdr.rcvif = ifp;
if(ifp->if_bridge) {
if (m->m_flags & (M_BCAST|M_MCAST))
ifp->if_imcasts++;
s = splnet();
m = bridge_input(ifp, m);
splx(s);
if (m == NULL)
return;
}
#endif
default:
m_freem(m);

View File

@ -1,4 +1,4 @@
# $NetBSD: files.netinet,v 1.13 2006/11/13 05:13:41 dyoung Exp $
# $NetBSD: files.netinet,v 1.14 2006/11/23 04:07:07 rpaulo Exp $
defflag opt_tcp_debug.h TCP_DEBUG
defparam opt_tcp_debug.h TCP_NDEBUG
@ -38,5 +38,6 @@ file netinet/tcp_subr.c inet | inet6
file netinet/tcp_timer.c inet | inet6
file netinet/tcp_usrreq.c inet | inet6
file netinet/tcp_congctl.c inet | inet6
file netinet/tcp_highspeed.c inet | inet6
file netinet/udp_usrreq.c inet | inet6

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_gif.c,v 1.50 2006/07/28 17:34:13 dyoung Exp $ */
/* $NetBSD: in_gif.c,v 1.51 2006/11/23 04:07:07 rpaulo Exp $ */
/* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.50 2006/07/28 17:34:13 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.51 2006/11/23 04:07:07 rpaulo Exp $");
#include "opt_inet.h"
#include "opt_iso.h"
@ -66,8 +66,6 @@ __KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.50 2006/07/28 17:34:13 dyoung Exp $");
#include <net/if_gif.h>
#include "gif.h"
#include "bridge.h"
#include <net/if_ether.h>
#include <machine/stdarg.h>
@ -97,9 +95,6 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst;
struct ip iphdr; /* capsule IP header, host byte ordered */
#if NBRIDGE > 0
struct etherip_header eiphdr;
#endif
int proto, error;
u_int8_t tos;
@ -147,24 +142,6 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
proto = IPPROTO_EON;
tos = 0;
break;
#endif
#if NBRIDGE > 0
case AF_LINK:
proto = IPPROTO_ETHERIP;
eiphdr.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
eiphdr.eip_pad = 0;
/* prepend Ethernet-in-IP header */
M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
if (m == NULL)
return ENOBUFS;
if (M_UNWRITABLE(m, sizeof(struct etherip_header))) {
m = m_pullup(m, sizeof(struct etherip_header));
if (m == NULL)
return ENOBUFS;
}
bcopy(&eiphdr, mtod(m, struct etherip_header *),
sizeof(struct etherip_header));
break;
#endif
default:
#ifdef DEBUG
@ -314,11 +291,6 @@ in_gif_input(struct mbuf *m, ...)
case IPPROTO_EON:
af = AF_ISO;
break;
#endif
#if NBRIDGE > 0
case IPPROTO_ETHERIP:
af = AF_LINK;
break;
#endif
default:
ipstat.ips_nogif++;

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_gif.h,v 1.13 2005/12/10 23:36:23 elad Exp $ */
/* $NetBSD: in_gif.h,v 1.14 2006/11/23 04:07:07 rpaulo Exp $ */
/* $KAME: in_gif.h,v 1.6 2001/07/25 00:55:48 itojun Exp $ */
/*
@ -46,12 +46,4 @@ int gif_encapcheck4(struct mbuf *, int, int, void *);
int in_gif_attach(struct gif_softc *);
int in_gif_detach(struct gif_softc *);
struct etherip_header {
u_int8_t eip_ver; /* version/reserved */
u_int8_t eip_pad; /* required padding byte */
};
#define ETHERIP_VER_VERS_MASK 0x0f
#define ETHERIP_VER_RSVD_MASK 0xf0
#define ETHERIP_VERSION 0x03
#endif /* !_NETINET_IN_GIF_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_proto.c,v 1.78 2006/11/13 05:13:42 dyoung Exp $ */
/* $NetBSD: in_proto.c,v 1.79 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.78 2006/11/13 05:13:42 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.79 2006/11/23 04:07:07 rpaulo Exp $");
#include "opt_mrouting.h"
#include "opt_eon.h" /* ISO CLNL over IP */
@ -110,6 +110,7 @@ __KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.78 2006/11/13 05:13:42 dyoung Exp $")
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/ip_encap.h>
/*
* TCP/IP protocol family: IP, ICMP, UDP, TCP.
*/
@ -147,7 +148,10 @@ __KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.78 2006/11/13 05:13:42 dyoung Exp $")
#include <netinet/ip_carp.h>
#endif
#include "bridge.h"
#include "etherip.h"
#if NETHERIP > 0
#include <netinet/ip_etherip.h>
#endif
DOMAIN_DEFINE(inetdomain); /* forward declare and add to link set */
@ -226,11 +230,11 @@ const struct protosw inetsw[] = {
encap_init, 0, 0, 0,
},
#endif /* INET6 */
#if NBRIDGE > 0
#if NETHERIP > 0
{ SOCK_RAW, &inetdomain, IPPROTO_ETHERIP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
encap4_input, rip_output, rip_ctlinput, rip_ctloutput,
ip_etherip_input, rip_output, rip_ctlinput, rip_ctloutput,
rip_usrreq,
encap_init, 0, 0, 0,
0, 0, 0, 0,
},
#endif
#if NCARP > 0

277
sys/netinet/ip_etherip.c Normal file
View File

@ -0,0 +1,277 @@
/* $NetBSD: ip_etherip.c,v 1.1 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* All rights reserved.
*
* 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. Neither the name of Hans Rosenfeld nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
#include <sys/cdefs.h>
#include "opt_inet.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/protosw.h>
#include <sys/kernel.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/in_var.h>
#include <netinet/ip_etherip.h>
#include <net/if_ether.h>
#include <net/if_media.h>
#include <net/if_etherip.h>
#include <machine/stdarg.h>
int
ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
{
struct etherip_softc *sc = (struct etherip_softc*)ifp->if_softc;
struct sockaddr_in *dst, *sin_src, *sin_dst;
struct ip iphdr; /* capsule IP header, host byte ordered */
struct etherip_header eiphdr;
int proto, error;
dst = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
sin_src = (struct sockaddr_in *)sc->sc_src;
sin_dst = (struct sockaddr_in *)sc->sc_dst;
if (sin_src == NULL ||
sin_dst == NULL ||
sin_src->sin_family != AF_INET ||
sin_dst->sin_family != AF_INET) {
m_freem(m);
return EAFNOSUPPORT;
}
/* reset broadcast/multicast flags */
m->m_flags &= ~(M_BCAST|M_MCAST);
m->m_flags |= M_PKTHDR;
proto = IPPROTO_ETHERIP;
/* fill and prepend Ethernet-in-IP header */
eiphdr.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
eiphdr.eip_pad = 0;
M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
if (m == NULL)
return ENOBUFS;
if (M_UNWRITABLE(m, sizeof(struct etherip_header))) {
m = m_pullup(m, sizeof(struct etherip_header));
if (m == NULL)
return ENOBUFS;
}
memcpy(mtod(m, struct etherip_header *), &eiphdr,
sizeof(struct etherip_header));
/* fill new IP header */
memset(&iphdr, 0, sizeof(struct ip));
iphdr.ip_src = sin_src->sin_addr;
/* bidirectional configured tunnel mode */
if (sin_dst->sin_addr.s_addr != INADDR_ANY)
iphdr.ip_dst = sin_dst->sin_addr;
else {
m_freem(m);
return ENETUNREACH;
}
iphdr.ip_p = proto;
/* version will be set in ip_output() */
iphdr.ip_ttl = ETHERIP_TTL;
iphdr.ip_len = htons(m->m_pkthdr.len + sizeof(struct ip));
/* prepend new IP header */
M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
if (m == NULL)
return ENOBUFS;
if (M_UNWRITABLE(m, sizeof(struct ip)))
m = m_pullup(m, sizeof(struct ip));
memcpy(mtod(m, struct ip *), &iphdr, sizeof(struct ip));
if (sc->sc_route_expire - time_second <= 0 ||
dst->sin_family != sin_dst->sin_family ||
!in_hosteq(dst->sin_addr, sin_dst->sin_addr)) {
/* cache route doesn't match */
memset(dst, 0, sizeof(struct sockaddr_in));
dst->sin_family = sin_dst->sin_family;
dst->sin_len = sizeof(struct sockaddr_in);
dst->sin_addr = sin_dst->sin_addr;
if (sc->sc_ro.ro_rt) {
RTFREE(sc->sc_ro.ro_rt);
sc->sc_ro.ro_rt = NULL;
}
}
if (sc->sc_ro.ro_rt == NULL) {
rtalloc(&sc->sc_ro);
if (sc->sc_ro.ro_rt == NULL) {
m_freem(m);
return ENETUNREACH ;
}
/* if it constitutes infinite encapsulation, punt. */
if (sc->sc_ro.ro_rt->rt_ifp == ifp) {
m_freem(m);
return ENETUNREACH; /*XXX*/
}
sc->sc_route_expire = time_second + ETHERIP_ROUTE_TTL;
}
error = ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL);
return error;
}
void
ip_etherip_input(struct mbuf *m, ...)
{
struct etherip_softc *sc;
const struct ip *ip;
struct sockaddr_in *src, *dst;
struct ifnet *ifp = NULL;
int off, proto;
va_list ap;
va_start(ap, m);
off = va_arg(ap, int);
proto = va_arg(ap, int);
va_end(ap);
if (proto != IPPROTO_ETHERIP) {
m_freem(m);
ipstat.ips_noproto++;
return;
}
ip = mtod(m, const struct ip *);
/* find device configured for this packets src and dst */
LIST_FOREACH(sc, &etherip_softc_list, etherip_list) {
if (!sc->sc_src || !sc->sc_dst)
continue;
if (sc->sc_src->sa_family != AF_INET ||
sc->sc_dst->sa_family != AF_INET)
continue;
src = (struct sockaddr_in *)sc->sc_src;
dst = (struct sockaddr_in *)sc->sc_dst;
if (src->sin_addr.s_addr != ip->ip_dst.s_addr ||
dst->sin_addr.s_addr != ip->ip_src.s_addr)
continue;
ifp = &sc->sc_ec.ec_if;
break;
}
/* no matching device found */
if (!ifp) {
m_freem(m);
ipstat.ips_odropped++;
return;
}
m_adj(m, off);
/*
* Section 4 of RFC 3378 requires that the EtherIP header of incoming
* packets is verified to contain the correct values in the version and
* reserved fields, and packets with wrong values be dropped.
*
* There is some discussion about what exactly the header should look
* like, the RFC is not very clear there. To be compatible with broken
* implementations, we don't check the header on incoming packets,
* relying on the ethernet code to filter out garbage.
*
* The header we use for sending is compatible with the original
* implementation in OpenBSD, which was used in former NetBSD versions
* and is used in FreeBSD. One Linux implementation is known to use the
* same value.
*/
m_adj(m, sizeof(struct etherip_header));
m = m_pullup(m, sizeof(struct ether_header));
if (m == NULL) {
ifp->if_ierrors++;
return;
}
m->m_pkthdr.rcvif = ifp;
m->m_flags &= ~(M_BCAST|M_MCAST);
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
#endif
ifp->if_ipackets++;
(ifp->if_input)(ifp, m);
return;
}

38
sys/netinet/ip_etherip.h Normal file
View File

@ -0,0 +1,38 @@
/* $NetBSD: ip_etherip.h,v 1.1 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* All rights reserved.
*
* 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. Neither the name of Hans Rosenfeld nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _NETINET_IP_ETHERIP_H_
#define _NETINET_IP_ETHERIP_H_
int ip_etherip_output(struct ifnet *, struct mbuf *);
void ip_etherip_input(struct mbuf *, ...);
#endif /* !_NETINET_IP_ETHERIP_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_proto.c,v 1.67 2006/10/10 21:49:15 dogcow Exp $ */
/* $NetBSD: in6_proto.c,v 1.68 2006/11/23 04:07:07 rpaulo Exp $ */
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
/*
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.67 2006/10/10 21:49:15 dogcow Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.68 2006/11/23 04:07:07 rpaulo Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -120,6 +120,11 @@ __KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.67 2006/10/10 21:49:15 dogcow Exp $"
#include <netinet/ip_carp.h>
#endif
#include "etherip.h"
#if NETHERIP > 1
#include <netinet6/ip6_etherip.h>
#endif
#include <netinet6/ip6protosw.h>
#include <net/net_osdep.h>
@ -210,6 +215,13 @@ const struct ip6protosw inet6sw[] = {
rip6_usrreq,
encap_init, 0, 0, 0,
},
#if NETHERIP > 1
{ SOCK_RAW, &inet6domain, IPPROTO_ETHERIP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
ip6_etherip_input, rip6_output, rip6_ctlinput, rip6_ctloutput,
rip6_usrreq,
0, 0, 0, 0,
},
#endif
#if NCARP > 0
{ SOCK_RAW, &inet6domain, IPPROTO_CARP, PR_ATOMIC|PR_ADDR,
carp6_proto_input, rip6_output, 0, rip6_ctloutput,

286
sys/netinet6/ip6_etherip.c Normal file
View File

@ -0,0 +1,286 @@
/* $NetBSD: ip6_etherip.c,v 1.1 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* All rights reserved.
*
* 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. Neither the name of Hans Rosenfeld nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
#include <sys/cdefs.h>
#include "opt_inet.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/protosw.h>
#include <sys/kernel.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#ifdef INET
#include <netinet/ip.h>
#endif
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6_etherip.h>
#endif
#include <net/if_ether.h>
#include <net/if_media.h>
#include <net/if_etherip.h>
#include <machine/stdarg.h>
int
ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
{
struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
struct sockaddr_in6 *dst, *sin6_src, *sin6_dst;
struct ip6_hdr *ip6; /* capsule IP header, host byte ordered */
struct etherip_header eiphdr;
int proto, error;
dst = (struct sockaddr_in6 *)&sc->sc_ro.ro_dst;
sin6_src = (struct sockaddr_in6 *)sc->sc_src;
sin6_dst = (struct sockaddr_in6 *)sc->sc_dst;
if (sin6_src == NULL ||
sin6_dst == NULL ||
sin6_src->sin6_family != AF_INET6 ||
sin6_dst->sin6_family != AF_INET6) {
m_freem(m);
return EAFNOSUPPORT;
}
/* reset broadcast/multicast flags */
m->m_flags &= ~(M_BCAST|M_MCAST);
m->m_flags |= M_PKTHDR;
proto = IPPROTO_ETHERIP;
/* fill and prepend Ethernet-in-IP header */
eiphdr.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
eiphdr.eip_pad = 0;
M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
if (m == NULL)
return ENOBUFS;
if (M_UNWRITABLE(m, sizeof(struct etherip_header))) {
m = m_pullup(m, sizeof(struct etherip_header));
if (m == NULL)
return ENOBUFS;
}
memcpy(mtod(m, struct etherip_header *), &eiphdr,
sizeof(struct etherip_header));
/* prepend new IP header */
M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
if (m && m->m_len < sizeof(struct ip6_hdr))
m = m_pullup(m, sizeof(struct ip6_hdr));
if (m == NULL)
return ENOBUFS;
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_flow = 0;
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_nxt = proto;
ip6->ip6_hlim = ETHERIP_TTL;
ip6->ip6_src = sin6_src->sin6_addr;
/* bidirectional configured tunnel mode */
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
ip6->ip6_dst = sin6_dst->sin6_addr;
else {
m_freem(m);
return ENETUNREACH;
}
if (sc->sc_route_expire - time_second <= 0 ||
dst->sin6_family != sin6_dst->sin6_family ||
!IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) {
/* cache route doesn't match */
memset(dst, 0, sizeof(*dst));
dst->sin6_family = sin6_dst->sin6_family;
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_addr = sin6_dst->sin6_addr;
if (sc->sc_ro6.ro_rt) {
RTFREE(sc->sc_ro6.ro_rt);
sc->sc_ro6.ro_rt = NULL;
}
}
if (sc->sc_ro6.ro_rt == NULL) {
rtalloc((struct route *)&sc->sc_ro6);
if (sc->sc_ro6.ro_rt == NULL) {
m_freem(m);
return ENETUNREACH;
}
/* if it constitutes infinite encapsulation, punt. */
if (sc->sc_ro.ro_rt->rt_ifp == ifp) {
m_freem(m);
return ENETUNREACH; /* XXX */
}
sc->sc_route_expire = time_second + ETHERIP_ROUTE_TTL;
}
/*
* force fragmentation to minimum MTU, to avoid path MTU discovery.
* it is too painful to ask for resend of inner packet, to achieve
* path MTU discovery for encapsulated packets.
*/
error = ip6_output(m, 0, &sc->sc_ro6, IPV6_MINMTU,
(struct ip6_moptions *)NULL, (struct socket *)NULL, NULL);
return error;
}
int
ip6_etherip_input(struct mbuf *m, ...)
{
struct etherip_softc *sc;
const struct ip6_hdr *ip6;
struct sockaddr_in6 *src6, *dst6;
struct ifnet *ifp = NULL;
int off, proto;
va_list ap;
va_start(ap, m);
off = va_arg(ap, int);
proto = va_arg(ap, int);
va_end(ap);
if (proto != IPPROTO_ETHERIP) {
m_freem(m);
ip6stat.ip6s_nogif++;
return IPPROTO_DONE;
}
ip6 = mtod(m, const struct ip6_hdr *);
/* find device configured for this packets src and dst */
LIST_FOREACH(sc, &etherip_softc_list, etherip_list) {
if( !sc->sc_src || !sc->sc_dst)
continue;
if (sc->sc_src->sa_family != AF_INET6 ||
sc->sc_dst->sa_family != AF_INET6)
continue;
src6 = (struct sockaddr_in6 *)sc->sc_src;
dst6 = (struct sockaddr_in6 *)sc->sc_dst;
if (!IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &ip6->ip6_dst) ||
!IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_src))
continue;
ifp = &sc->sc_ec.ec_if;
break;
}
/* no matching device found */
if (!ifp) {
m_freem(m);
ip6stat.ip6s_odropped++;
return IPPROTO_DONE;
}
m_adj(m, off);
/*
* Section 4 of RFC 3378 requires that the EtherIP header of incoming
* packets is verified to contain the correct values in the version and
* reserved fields, and packets with wrong values be dropped.
*
* There is some discussion about what exactly the header should look
* like, the RFC is not very clear there. To be compatible with broken
* implementations, we don't check the header on incoming packets,
* relying on the ethernet code to filter out garbage.
*
* The header we use for sending is compatible with the original
* implementation in OpenBSD, which was used in former NetBSD versions
* and is used in FreeBSD. One Linux implementation is known to use the
* same value.
*/
m_adj(m, sizeof(struct etherip_header));
m = m_pullup(m, sizeof(struct ether_header));
if (m == NULL) {
ifp->if_ierrors++;
return IPPROTO_DONE;
}
m->m_pkthdr.rcvif = ifp;
m->m_flags &= ~(M_BCAST|M_MCAST);
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
#endif
ifp->if_ipackets++;
(ifp->if_input)(ifp, m);
return IPPROTO_DONE;
}

View File

@ -0,0 +1,38 @@
/* $NetBSD: ip6_etherip.h,v 1.1 2006/11/23 04:07:07 rpaulo Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* All rights reserved.
*
* 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. Neither the name of Hans Rosenfeld nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _NETINET6_IP6_ETHERIP_H_
#define _NETINET6_IP6_ETHERIP_H_
int ip6_etherip_output(struct ifnet *, struct mbuf *);
int ip6_etherip_input(struct mbuf *, ...);
#endif /* !_NETINET6_IP6_ETHERIP_H_ */