Add RFC 3378 EtherIP support, ported from OpenBSD to NetBSD by

Hans Rosenfeld (rosenfeld at grumpf.hope-2000.org)

This change makes it possible to add gif interfaces to bridges, which
will then send and receive IP protocol 97 packets. Packets are Ethernet
frames with an EtherIP header prepended.
This commit is contained in:
kim 2005-01-31 23:49:36 +00:00
parent 36eef77064
commit c9f56c04dc
8 changed files with 167 additions and 26 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bridge.c,v 1.27 2004/12/04 18:31:43 peter Exp $ */
/* $NetBSD: if_bridge.c,v 1.28 2005/01/31 23:49:36 kim Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -80,12 +80,13 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.27 2004/12/04 18:31:43 peter Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.28 2005/01/31 23:49:36 kim 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>
@ -580,7 +581,10 @@ 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");
@ -633,7 +637,10 @@ 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;
@ -1157,6 +1164,7 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
#endif /* ALTQ */
len = m->m_pkthdr.len;
m->m_flags |= M_PROTO1;
mflags = m->m_flags;
IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error);
if (error) {
@ -1480,6 +1488,20 @@ 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. */
@ -1499,6 +1521,8 @@ 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) {
@ -1506,6 +1530,14 @@ 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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ethersubr.c,v 1.118 2005/01/08 03:18:18 yamt Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.119 2005/01/31 23:49:36 kim 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.118 2005/01/08 03:18:18 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.119 2005/01/31 23:49:36 kim Exp $");
#include "opt_inet.h"
#include "opt_atalk.h"
@ -726,18 +726,22 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
* process it locally.
*/
if (ifp->if_bridge) {
/* clear M_PROMISC, in case the packets comes from a vlan */
m->m_flags &= ~M_PROMISC;
m = bridge_input(ifp, m);
if (m == NULL)
return;
if(m->m_flags & M_PROTO1) {
m->m_flags &= ~M_PROTO1;
} else {
/* clear M_PROMISC, in case the packets comes from a vlan */
m->m_flags &= ~M_PROMISC;
m = bridge_input(ifp, m);
if (m == NULL)
return;
/*
* Bridge has determined that the packet is for us.
* Update our interface pointer -- we may have had
* to "bridge" the packet locally.
*/
ifp = m->m_pkthdr.rcvif;
/*
* Bridge has determined that the packet is for us.
* Update our interface pointer -- we may have had
* to "bridge" the packet locally.
*/
ifp = m->m_pkthdr.rcvif;
}
} else
#endif /* NBRIDGE > 0 */
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_gif.c,v 1.47 2004/12/04 18:31:43 peter Exp $ */
/* $NetBSD: if_gif.c,v 1.48 2005/01/31 23:49:36 kim 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.47 2004/12/04 18:31:43 peter Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.48 2005/01/31 23:49:36 kim Exp $");
#include "opt_inet.h"
#include "opt_iso.h"
@ -82,9 +82,12 @@ __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.47 2004/12/04 18:31:43 peter 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>
@ -93,6 +96,7 @@ void gifattach __P((int));
void gifnetisr __P((void));
#endif
void gifintr __P((void *));
void gif_start __P((struct ifnet *));
#ifdef ISO
static struct mbuf *gif_eon_encap __P((struct mbuf *));
static struct mbuf *gif_eon_decap __P((struct ifnet *, struct mbuf *));
@ -163,6 +167,7 @@ gifattach0(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);
@ -198,6 +203,18 @@ gif_clone_destroy(ifp)
return (0);
}
void
gif_start(ifp)
struct ifnet *ifp;
{
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
softintr_schedule(((struct gif_softc*)ifp)->gif_si);
#else
/* XXX bad spl level? */
gifnetisr();
#endif
}
#ifdef GIF_ENCAPCHECK
int
gif_encapcheck(m, off, proto, arg)
@ -232,6 +249,10 @@ gif_encapcheck(m, off, proto, arg)
#ifdef ISO
case IPPROTO_EON:
break;
#endif
#if NBRIDGE > 0
case IPPROTO_ETHERIP:
break;
#endif
default:
return 0;
@ -391,6 +412,17 @@ gifintr(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));
@ -443,6 +475,7 @@ gif_input(m, af, ifp)
{
int s, isr;
struct ifqueue *ifq = NULL;
struct ether_header *eh;
if (ifp == NULL) {
/* just in case */
@ -489,6 +522,37 @@ gif_input(m, af, 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 (bcmp((caddr_t) etherbroadcastaddr,
(caddr_t)eh->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
m->m_flags |= M_BCAST;
else
m->m_flags |= M_MCAST;
}
m->m_pkthdr.rcvif = ifp;
if(ifp->if_bridge) {
if (m->m_flags & (M_BCAST|M_MCAST))
ifp->if_imcasts++;
s = splnet();
m = bridge_input(ifp, m);
splx(s);
if (m == NULL)
return;
}
#endif
default:
m_freem(m);

View File

@ -1,4 +1,4 @@
/* $NetBSD: in.h,v 1.69 2004/12/15 04:25:19 thorpej Exp $ */
/* $NetBSD: in.h,v 1.70 2005/01/31 23:49:36 kim Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993
@ -97,6 +97,7 @@ typedef __sa_family_t sa_family_t;
#define IPPROTO_NONE 59 /* IP6 no next header */
#define IPPROTO_DSTOPTS 60 /* IP6 destination option */
#define IPPROTO_EON 80 /* ISO cnlp */
#define IPPROTO_ETHERIP 97 /* Ethernet-in-IP */
#define IPPROTO_ENCAP 98 /* encapsulation header */
#define IPPROTO_PIM 103 /* Protocol indep. multicast */
#define IPPROTO_IPCOMP 108 /* IP Payload Comp. Protocol */

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_gif.c,v 1.36 2004/04/26 01:31:56 matt Exp $ */
/* $NetBSD: in_gif.c,v 1.37 2005/01/31 23:49:36 kim 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.36 2004/04/26 01:31:56 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.37 2005/01/31 23:49:36 kim Exp $");
#include "opt_inet.h"
#include "opt_iso.h"
@ -65,6 +65,8 @@ __KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.36 2004/04/26 01:31:56 matt Exp $");
#include <net/if_gif.h>
#include "gif.h"
#include "bridge.h"
#include <net/if_ether.h>
#include <machine/stdarg.h>
@ -97,6 +99,7 @@ in_gif_output(ifp, family, 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 */
struct etherip_header eiphdr;
int proto, error;
u_int8_t tos;
@ -144,6 +147,20 @@ in_gif_output(ifp, family, 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 && m->m_len < sizeof(struct etherip_header))
m = m_pullup(m, sizeof(struct etherip_header));
if (m == NULL)
return ENOBUFS;
bcopy(&eiphdr, mtod(m, struct etherip_header *), sizeof(struct etherip_header));
break;
#endif
default:
#ifdef DEBUG
@ -291,6 +308,11 @@ 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.10 2004/04/21 17:49:46 itojun Exp $ */
/* $NetBSD: in_gif.h,v 1.11 2005/01/31 23:49:36 kim Exp $ */
/* $KAME: in_gif.h,v 1.6 2001/07/25 00:55:48 itojun Exp $ */
/*
@ -46,4 +46,12 @@ int gif_encapcheck4(const 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.66 2005/01/23 18:41:57 matt Exp $ */
/* $NetBSD: in_proto.c,v 1.67 2005/01/31 23:49:36 kim 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.66 2005/01/23 18:41:57 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.67 2005/01/31 23:49:36 kim Exp $");
#include "opt_mrouting.h"
#include "opt_eon.h" /* ISO CLNL over IP */
@ -146,6 +146,8 @@ __KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.66 2005/01/23 18:41:57 matt Exp $");
#include <netinet/ip_gre.h>
#endif
#include "bridge.h"
DOMAIN_DEFINE(inetdomain); /* forward declare and add to link set */
const struct protosw inetsw[] = {
@ -224,6 +226,13 @@ const struct protosw inetsw[] = {
encap_init, 0, 0, 0,
},
#endif /* INET6 */
#if NBRIDGE > 0
{ SOCK_RAW, &inetdomain, IPPROTO_ETHERIP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
encap4_input, rip_output, rip_ctlinput, rip_ctloutput,
rip_usrreq,
encap_init, 0, 0, 0,
},
#endif
#if NGRE > 0
{ SOCK_RAW, &inetdomain, IPPROTO_GRE, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
gre_input, rip_output, rip_ctlinput, rip_ctloutput,

View File

@ -1,4 +1,4 @@
/* $NetBSD: mbuf.h,v 1.99 2004/09/21 21:57:30 yamt Exp $ */
/* $NetBSD: mbuf.h,v 1.100 2005/01/31 23:49:36 kim Exp $ */
/*-
* Copyright (c) 1996, 1997, 1999, 2001 The NetBSD Foundation, Inc.
@ -272,6 +272,7 @@ MBUF_DEFINE(mbuf, MHLEN, MLEN);
#define M_EXT 0x0001 /* has associated external storage */
#define M_PKTHDR 0x0002 /* start of record */
#define M_EOR 0x0004 /* end of record */
#define M_PROTO1 0x0008 /* protocol-specific */
/* mbuf pkthdr flags, also in m_flags */
#define M_AUTHIPHDR 0x0010 /* data origin authentication for IP header */