summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_gif.c229
-rw-r--r--sys/netinet/in_gif.c38
-rw-r--r--sys/netinet/in_gif.h4
-rw-r--r--sys/netinet/in_proto.c23
-rw-r--r--sys/netinet/ip_ether.c362
-rw-r--r--sys/netinet/ip_ether.h7
-rw-r--r--sys/netinet/ip_ipip.c87
-rw-r--r--sys/netinet/ip_ipsp.h9
-rw-r--r--sys/netinet6/in6_gif.c72
-rw-r--r--sys/netinet6/in6_gif.h4
10 files changed, 536 insertions, 299 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index e6a28b87d5f..cb9ccba73e0 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_gif.c,v 1.53 2009/11/22 12:33:25 deraadt Exp $ */
+/* $OpenBSD: if_gif.c,v 1.54 2010/05/11 09:36:07 claudio Exp $ */
/* $KAME: if_gif.c,v 1.43 2001/02/20 08:51:07 itojun Exp $ */
/*
@@ -49,6 +49,7 @@
#include <netinet/in_var.h>
#include <netinet/in_gif.h>
#include <netinet/ip.h>
+#include <netinet/ip_var.h>
#endif /* INET */
#ifdef INET6
@@ -56,6 +57,7 @@
#include <netinet/in.h>
#endif
#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
#include <netinet6/in6_gif.h>
#endif /* INET6 */
@@ -67,6 +69,7 @@
void gifattach(int);
int gif_clone_create(struct if_clone *, int);
int gif_clone_destroy(struct ifnet *);
+int gif_checkloop(struct ifnet *, struct mbuf *);
/*
* gif global variable definitions
@@ -145,24 +148,8 @@ gif_start(struct ifnet *ifp)
{
struct gif_softc *sc = (struct gif_softc*)ifp;
struct mbuf *m;
- struct m_tag *mtag;
- int family;
int s;
- u_int8_t tp;
-
- /* is interface up and running? */
- if ((ifp->if_flags & (IFF_OACTIVE | IFF_UP)) != IFF_UP ||
- sc->gif_psrc == NULL || sc->gif_pdst == NULL)
- return;
-
- /* are the tunnel endpoints valid? */
-#ifdef INET
- if (sc->gif_psrc->sa_family != AF_INET)
-#endif
-#ifdef INET6
- if (sc->gif_psrc->sa_family != AF_INET6)
-#endif
- return;
+ sa_family_t family;
while (1) {
s = splnet();
@@ -172,77 +159,124 @@ gif_start(struct ifnet *ifp)
if (m == NULL)
break;
- /*
- * gif may cause infinite recursion calls when misconfigured.
- * We'll prevent this by detecting loops.
- */
- for (mtag = m_tag_find(m, PACKET_TAG_GIF, NULL); mtag;
- mtag = m_tag_find(m, PACKET_TAG_GIF, mtag)) {
- if (!bcmp((caddr_t)(mtag + 1), &ifp,
- sizeof(struct ifnet *))) {
- IF_DROP(&ifp->if_snd);
- log(LOG_NOTICE, "gif_output: "
- "recursively called too many times\n");
- m_freem(m);
- break;
- }
- }
- if (mtag)
- continue;
-
- mtag = m_tag_get(PACKET_TAG_GIF, sizeof(caddr_t), M_NOWAIT);
- if (mtag == NULL) {
+ /* is interface up and usable? */
+ if ((ifp->if_flags & (IFF_OACTIVE | IFF_UP)) != IFF_UP ||
+ sc->gif_psrc == NULL || sc->gif_pdst == NULL ||
+ sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) {
m_freem(m);
- break;
+ continue;
}
- bcopy(&ifp, mtag + 1, sizeof(caddr_t));
- m_tag_prepend(m, mtag);
+
+ /* get tunnel address family */
+ family = sc->gif_psrc->sa_family;
/*
- * Remove multicast and broadcast flags or encapsulated packet
- * ends up as multicast or broadcast packet.
+ * Check if the packet is comming via bridge and needs
+ * etherip encapsulation or not. bridge(4) directly calls
+ * the start function and bypasses the if_output function
+ * so we need to do the encap here.
*/
- m->m_flags &= ~(M_BCAST|M_MCAST);
-
- /* extract address family */
- family = AF_UNSPEC;
- tp = *mtod(m, u_int8_t *);
- tp = (tp >> 4) & 0xff; /* Get the IP version number. */
+ if (ifp->if_bridge && (m->m_flags & M_PROTO1)) {
+ int error = 0;
+ /*
+ * Remove multicast and broadcast flags or encapsulated
+ * packet ends up as multicast or broadcast packet.
+ */
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+ switch (sc->gif_psrc->sa_family) {
#ifdef INET
- if (tp == IPVERSION)
- family = AF_INET;
+ case AF_INET:
+ error = in_gif_output(ifp, AF_LINK, &m);
+ break;
#endif
#ifdef INET6
- if (tp == (IPV6_VERSION >> 4))
- family = AF_INET6;
+ case AF_INET6:
+ error = in6_gif_output(ifp, AF_LINK, &m);
+ break;
#endif
-
-#if NBRIDGE > 0
- /*
- * Check if the packet is comming via bridge and needs
- * etherip encapsulation or not.
- */
- if (ifp->if_bridge && (m->m_flags & M_PROTO1)) {
- m->m_flags &= ~M_PROTO1;
- family = AF_LINK;
+ default:
+ error = EAFNOSUPPORT;
+ m_freem(m);
+ break;
+ }
+ if (error)
+ continue;
+ if (gif_checkloop(ifp, m))
+ continue;
}
-#endif
#if NBPFILTER > 0
- if (ifp->if_bpf)
+ if (ifp->if_bpf) {
+ int offset;
+ sa_family_t family;
+ u_int8_t proto;
+
+ /* must decapsulate outer header for bpf */
+ switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+ case AF_INET:
+ offset = sizeof(struct ip);
+ proto = mtod(m, struct ip *)->ip_p;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ offset = sizeof(struct ip6_hdr);
+ proto = mtod(m, struct ip6_hdr *)->ip6_nxt;
+ break;
+#endif
+ default:
+ proto = 0;
+ break;
+ }
+ switch (proto) {
+ case IPPROTO_IPV4:
+ family = AF_INET;
+ break;
+ case IPPROTO_IPV6:
+ family = AF_INET6;
+ break;
+ case IPPROTO_ETHERIP:
+ family = AF_LINK;
+ break;
+ case IPPROTO_MPLS:
+ family = AF_MPLS;
+ break;
+ default:
+ offset = 0;
+ family = sc->gif_psrc->sa_family;
+ break;
+ }
+ m->m_data += offset;
+ m->m_len -= offset;
+ m->m_pkthdr.len -= offset;
bpf_mtap_af(ifp->if_bpf, family, m, BPF_DIRECTION_OUT);
+ m->m_data -= offset;
+ m->m_len += offset;
+ m->m_pkthdr.len += offset;
+ }
#endif
ifp->if_opackets++;
+ /* XXX we should cache the outgoing route */
+
switch (sc->gif_psrc->sa_family) {
#ifdef INET
case AF_INET:
- in_gif_output(ifp, family, m);
+ ip_output(m, (void *)NULL, (void *)NULL, 0,
+ (void *)NULL, (void *)NULL);
break;
#endif
#ifdef INET6
case AF_INET6:
- in6_gif_output(ifp, family, m);
+ /*
+ * 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.
+ */
+ ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL,
+ NULL);
break;
#endif
default:
@@ -259,44 +293,61 @@ gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct gif_softc *sc = (struct gif_softc*)ifp;
int error = 0;
int s;
+ sa_family_t family = dst->sa_family;
if (!(ifp->if_flags & IFF_UP) ||
- sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+ sc->gif_psrc == NULL || sc->gif_pdst == NULL ||
+ sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) {
m_freem(m);
error = ENETDOWN;
goto end;
}
+ /*
+ * Remove multicast and broadcast flags or encapsulated packet
+ * ends up as multicast or broadcast packet.
+ */
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+
+ /*
+ * Encapsulate packet. Add IP or IP6 header depending on tunnel AF.
+ */
switch (sc->gif_psrc->sa_family) {
#ifdef INET
case AF_INET:
+ error = in_gif_output(ifp, family, &m);
break;
#endif
#ifdef INET6
case AF_INET6:
+ error = in6_gif_output(ifp, family, &m);
break;
#endif
default:
m_freem(m);
- error = ENETDOWN;
- goto end;
+ error = EAFNOSUPPORT;
+ break;
}
- s = splnet();
+ if (error)
+ goto end;
+
+ if ((error = gif_checkloop(ifp, m)))
+ goto end;
+
/*
- * Queue message on interface, and start output if interface
- * not yet active.
+ * Queue message on interface, and start output.
*/
+ s = splnet();
IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
if (error) {
/* mbuf is already freed */
splx(s);
- return (error);
+ goto end;
}
ifp->if_obytes += m->m_pkthdr.len;
if_start(ifp);
splx(s);
- return (error);
end:
if (error)
@@ -617,3 +668,33 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
bad:
return (error);
}
+
+int
+gif_checkloop(struct ifnet *ifp, struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ /*
+ * gif may cause infinite recursion calls when misconfigured.
+ * We'll prevent this by detecting loops.
+ */
+ for (mtag = m_tag_find(m, PACKET_TAG_GIF, NULL); mtag;
+ mtag = m_tag_find(m, PACKET_TAG_GIF, mtag)) {
+ if (!bcmp((caddr_t)(mtag + 1), &ifp,
+ sizeof(struct ifnet *))) {
+ log(LOG_NOTICE, "gif_output: "
+ "recursively called too many times\n");
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ }
+
+ mtag = m_tag_get(PACKET_TAG_GIF, sizeof(caddr_t), M_NOWAIT);
+ if (mtag == NULL) {
+ m_freem(m);
+ return ENOMEM;
+ }
+ bcopy(&ifp, mtag + 1, sizeof(caddr_t));
+ m_tag_prepend(m, mtag);
+ return 0;
+}
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index e2a92c0c57c..3cf02f75490 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_gif.c,v 1.37 2009/11/21 14:08:14 claudio Exp $ */
+/* $OpenBSD: in_gif.c,v 1.38 2010/05/11 09:36:07 claudio Exp $ */
/* $KAME: in_gif.c,v 1.50 2001/01/22 07:27:16 itojun Exp $ */
/*
@@ -54,13 +54,16 @@
#include "gif.h"
#include "bridge.h"
+#if NBRIDGE > 0
+#include <netinet/ip_ether.h>
+#endif
#if NPF > 0
#include <net/pfvar.h>
#endif
int
-in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
+in_gif_output(struct ifnet *ifp, int family, struct mbuf **m0)
{
struct gif_softc *sc = (struct gif_softc*)ifp;
struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
@@ -68,7 +71,7 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
struct tdb tdb;
struct xformsw xfs;
int error;
- struct mbuf *mp;
+ struct mbuf *m = *m0;
if (sin_src == NULL || sin_dst == NULL ||
sin_src->sin_family != AF_INET ||
@@ -85,7 +88,7 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
}
#endif
- /* setup dummy tdb. it highly depends on ipipoutput() code. */
+ /* setup dummy tdb. it highly depends on ipip_output() code. */
bzero(&tdb, sizeof(tdb));
bzero(&xfs, sizeof(xfs));
tdb.tdb_src.sin.sin_family = AF_INET;
@@ -107,7 +110,11 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
#if NBRIDGE > 0
case AF_LINK:
break;
-#endif /* NBRIDGE */
+#endif
+#if MPLS
+ case AF_MPLS:
+ break;
+#endif
default:
#ifdef DEBUG
printf("in_gif_output: warning: unknown family %d passed\n",
@@ -118,26 +125,30 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
}
/* encapsulate into IPv4 packet */
- mp = NULL;
+ *m0 = NULL;
#if NBRIDGE > 0
if (family == AF_LINK)
- error = etherip_output(m, &tdb, &mp, 0, 0);
+ error = etherip_output(m, &tdb, m0, IPPROTO_ETHERIP);
else
#endif /* NBRIDGE */
- error = ipip_output(m, &tdb, &mp, 0, 0);
+#ifdef MPLS
+ if (family == AF_MPLS)
+ error = etherip_output(m, &tdb, m0, IPPROTO_MPLS);
+ else
+#endif
+ error = ipip_output(m, &tdb, m0, 0, 0);
if (error)
return error;
- else if (mp == NULL)
+ else if (*m0 == NULL)
return EFAULT;
- m = mp;
+ m = *m0;
m->m_pkthdr.rdomain = sc->gif_rtableid;
#if NPF > 0
pf_pkt_addr_changed(m);
#endif
- return ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
- (void *)NULL);
+ return 0;
}
void
@@ -186,7 +197,8 @@ in_gif_input(struct mbuf *m, ...)
m->m_pkthdr.rdomain = gifp->if_rdomain;
gifp->if_ipackets++;
gifp->if_ibytes += m->m_pkthdr.len;
- ipip_input(m, off, gifp); /* We have a configured GIF */
+ /* We have a configured GIF */
+ ipip_input(m, off, gifp, ip->ip_p);
return;
}
diff --git a/sys/netinet/in_gif.h b/sys/netinet/in_gif.h
index 3a12d06dd91..aa4b660a2b6 100644
--- a/sys/netinet/in_gif.h
+++ b/sys/netinet/in_gif.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_gif.h,v 1.5 2007/02/10 15:34:22 claudio Exp $ */
+/* $OpenBSD: in_gif.h,v 1.6 2010/05/11 09:36:07 claudio Exp $ */
/* $KAME: in_gif.h,v 1.5 2000/04/14 08:36:02 itojun Exp $ */
/*
@@ -34,6 +34,6 @@
#define _NETINET_IN_GIF_H_
void in_gif_input(struct mbuf *, ...);
-int in_gif_output(struct ifnet *, int, struct mbuf *);
+int in_gif_output(struct ifnet *, int, struct mbuf **);
#endif /*_NETINET_IN_GIF_H_*/
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index f30b585dc4a..0ecac5bd043 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_proto.c,v 1.52 2010/01/12 23:33:24 yasuoka Exp $ */
+/* $OpenBSD: in_proto.c,v 1.53 2010/05/11 09:36:07 claudio Exp $ */
/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */
/*
@@ -210,13 +210,25 @@ struct protosw inetsw[] = {
rip_usrreq,
0, 0, 0, 0, ipip_sysctl
},
+{ SOCK_RAW, &inetdomain, IPPROTO_ETHERIP, PR_ATOMIC|PR_ADDR,
+ etherip_input, rip_output, 0, rip_ctloutput,
+ rip_usrreq,
+ 0, 0, 0, 0, etherip_sysctl
+},
#ifdef INET6
{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
in_gif_input, rip_output, 0, 0,
rip_usrreq, /*XXX*/
0, 0, 0, 0,
},
-#endif /* INET6 */
+#endif
+#ifdef MPLS
+{ SOCK_RAW, &inetdomain, IPPROTO_MPLS, PR_ATOMIC|PR_ADDR,
+ etherip_input, rip_output, 0, 0,
+ rip_usrreq,
+ 0, 0, 0, 0,
+},
+#endif
#else /* NGIF */
{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
ip4_input, rip_output, 0, rip_ctloutput,
@@ -229,7 +241,7 @@ struct protosw inetsw[] = {
rip_usrreq, /*XXX*/
0, 0, 0, 0,
},
-#endif /* INET6 */
+#endif
#endif /*NGIF*/
{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR,
igmp_input, rip_output, 0, rip_ctloutput,
@@ -254,11 +266,6 @@ struct protosw inetsw[] = {
rip_usrreq,
0, 0, 0, 0, esp_sysctl
},
-{ SOCK_RAW, &inetdomain, IPPROTO_ETHERIP, PR_ATOMIC|PR_ADDR,
- etherip_input, rip_output, 0, rip_ctloutput,
- rip_usrreq,
- 0, 0, 0, 0, etherip_sysctl
-},
{ SOCK_RAW, &inetdomain, IPPROTO_IPCOMP, PR_ATOMIC|PR_ADDR,
ipcomp4_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
diff --git a/sys/netinet/ip_ether.c b/sys/netinet/ip_ether.c
index d337aee1bac..1a40db89819 100644
--- a/sys/netinet/ip_ether.c
+++ b/sys/netinet/ip_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ether.c,v 1.53 2010/04/20 22:05:43 tedu Exp $ */
+/* $OpenBSD: ip_ether.c,v 1.54 2010/05/11 09:36:07 claudio Exp $ */
/*
* The author of this code is Angelos D. Keromytis (kermit@adk.gr)
*
@@ -35,9 +35,10 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
+#include <net/bpf.h>
#include <net/if.h>
+#include <net/netisr.h>
#include <net/route.h>
-#include <net/bpf.h>
#ifdef INET
#include <netinet/in.h>
@@ -49,10 +50,16 @@
#include <netinet/ip_ether.h>
#include <netinet/if_ether.h>
-#include <net/if_bridge.h>
+
#include <net/if_gif.h>
-#include "gif.h"
+#if NBRIDGE > 0
+#include <net/if_bridge.h>
+#endif
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#endif
+
#include "bpfilter.h"
#ifdef ENCDEBUG
@@ -61,6 +68,14 @@
#define DPRINTF(x)
#endif
+#if NBRIDGE > 0
+void etherip_decap(struct mbuf *, int);
+#endif
+#ifdef MPLS
+void mplsip_decap(struct mbuf *, int);
+#endif
+struct gif_softc *etherip_getgif(struct mbuf *);
+
/*
* We can control the acceptance of EtherIP packets by altering the sysctl
* net.inet.etherip.allow value. Zero means drop them, all else is acceptance.
@@ -69,43 +84,93 @@ int etherip_allow = 0;
struct etheripstat etheripstat;
+#ifdef INET
/*
- * etherip_input gets called when we receive an encapsulated packet,
- * either because we got it at a real interface, or because AH or ESP
- * were being used in tunnel mode (in which case the rcvif element will
- * contain the address of the encX interface associated with the tunnel.
+ * etherip_input gets called when we receive an encapsulated packet.
+ * Only a wrapper for the IPv4 case.
*/
-
void
etherip_input(struct mbuf *m, ...)
{
- union sockaddr_union ssrc, sdst;
- struct ether_header eh;
- int iphlen;
- struct etherip_header eip;
- u_int8_t v;
+ struct ip *ip;
va_list ap;
+ int iphlen;
-#if NGIF > 0
- struct gif_softc *sc;
-#if NBRIDGE > 0
- int s;
-#endif /* NBRIDGE */
-#endif /* NGIF */
+ ip = mtod(m, struct ip *);
va_start(ap, m);
iphlen = va_arg(ap, int);
va_end(ap);
- etheripstat.etherip_ipackets++;
-
- /* If we do not accept EtherIP explicitly, drop. */
- if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
- DPRINTF(("etherip_input(): dropped due to policy\n"));
+ switch (ip->ip_p) {
+#if NBRIDGE > 0
+ case IPPROTO_ETHERIP:
+ /* If we do not accept EtherIP explicitly, drop. */
+ if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
+ DPRINTF(("etherip_input(): dropped due to policy\n"));
+ etheripstat.etherip_pdrops++;
+ m_freem(m);
+ return;
+ }
+ etherip_decap(m, iphlen);
+ return;
+#endif
+#ifdef MPLS
+ case IPPROTO_MPLS:
+ mplsip_decap(m, iphlen);
+ return;
+#endif
+ default:
+ DPRINTF(("etherip_input(): dropped, unhandled protcol \n"));
etheripstat.etherip_pdrops++;
m_freem(m);
return;
}
+}
+#endif
+
+#ifdef INET6
+int
+etherip_input6(struct mbuf **m, int *offp, int proto)
+{
+ switch (proto) {
+#if NBRIDGE > 0
+ case IPPROTO_ETHERIP:
+ /* If we do not accept EtherIP explicitly, drop. */
+ if (proto == IPPROTO_ETHERIP && !etherip_allow &&
+ ((*m)->m_flags & (M_AUTH|M_CONF)) == 0) {
+ DPRINTF(("etherip_input6(): dropped due to policy\n"));
+ etheripstat.etherip_pdrops++;
+ m_freem(*m);
+ return IPPROTO_DONE;
+ }
+ etherip_decap(*m, *offp);
+ return IPPROTO_DONE;
+#endif
+#ifdef MPLS
+ case IPPROTO_MPLS:
+ mplsip_decap(*m, *offp);
+ return IPPROTO_DONE;
+#endif
+ default:
+ DPRINTF(("etherip_input6(): dropped, unhandled protcol \n"));
+ etheripstat.etherip_pdrops++;
+ m_freem(*m);
+ return IPPROTO_DONE;
+ }
+}
+#endif
+
+#if NBRIDGE > 0
+void
+etherip_decap(struct mbuf *m, int iphlen)
+{
+ struct ether_header eh;
+ struct etherip_header eip;
+ struct gif_softc *sc;
+ int s;
+
+ etheripstat.etherip_ipackets++;
/*
* Make sure there's at least an ethernet header's and an EtherIP
@@ -123,7 +188,7 @@ etherip_input(struct mbuf *m, ...)
m_copydata(m, iphlen, sizeof(struct etherip_header), (caddr_t)&eip);
if ((eip.eip_ver & ETHERIP_VER_VERS_MASK) != ETHERIP_VERSION) {
DPRINTF(("etherip_input(): received EtherIP version number "
- "%d not suppoorted\n", (v >> 4) & 0xff));
+ "%d not suppoorted\n", eip.eip_ver));
etheripstat.etherip_adrops++;
m_freem(m);
return;
@@ -162,6 +227,149 @@ etherip_input(struct mbuf *m, ...)
}
}
+ sc = etherip_getgif(m);
+ if (sc == NULL)
+ return;
+ if (sc->gif_if.if_bridge == NULL) {
+ DPRINTF(("etherip_input(): interface not part of bridge\n"));
+ etheripstat.etherip_noifdrops++;
+ m_freem(m);
+ return;
+ }
+
+ /* Chop off the `outer' IP and EtherIP headers and reschedule. */
+ m_adj(m, iphlen + sizeof(struct etherip_header));
+
+ /* Statistics */
+ etheripstat.etherip_ibytes += m->m_pkthdr.len;
+
+ /* Copy ethernet header */
+ m_copydata(m, 0, sizeof(eh), (void *) &eh);
+
+ /* Reset the flags based on the inner packet */
+ m->m_flags &= ~(M_BCAST|M_MCAST|M_AUTH|M_CONF|M_AUTH_AH);
+ 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;
+ }
+
+#if NBPFILTER > 0
+ if (sc->gif_if.if_bpf)
+ bpf_mtap_af(sc->gif_if.if_bpf, AF_LINK, m, BPF_DIRECTION_IN);
+#endif
+
+ /* Trim the beginning of the mbuf, to remove the ethernet header. */
+ m_adj(m, sizeof(struct ether_header));
+
+ /*
+ * Tap the packet off here for a bridge. bridge_input() returns
+ * NULL if it has consumed the packet. In the case of gif's,
+ * bridge_input() returns non-NULL when an error occurs.
+ */
+#if NPF > 0
+ pf_pkt_addr_changed(m);
+#endif
+ m->m_pkthdr.rcvif = &sc->gif_if;
+ m->m_pkthdr.rdomain = sc->gif_if.if_rdomain;
+ if (m->m_flags & (M_BCAST|M_MCAST))
+ sc->gif_if.if_imcasts++;
+
+ s = splnet();
+ m = bridge_input(&sc->gif_if, &eh, m);
+ splx(s);
+ if (m == NULL)
+ return;
+
+ etheripstat.etherip_noifdrops++;
+ m_freem(m);
+ return;
+}
+#endif
+
+#ifdef MPLS
+void
+mplsip_decap(struct mbuf *m, int iphlen)
+{
+ struct gif_softc *sc;
+ struct ifqueue *ifq;
+ int s;
+
+ etheripstat.etherip_ipackets++;
+
+ /*
+ * Make sure there's at least one MPLS label worth of data after
+ * the outer IP header.
+ */
+ if (m->m_pkthdr.len < iphlen + sizeof(struct shim_hdr)) {
+ DPRINTF(("mplsip_input(): encapsulated packet too short\n"));
+ etheripstat.etherip_hdrops++;
+ m_freem(m);
+ return;
+ }
+
+ /* Make sure the mpls label at least is in the first mbuf. */
+ if (m->m_len < iphlen + sizeof(struct shim_hdr)) {
+ if ((m = m_pullup(m, iphlen + sizeof(struct shim_hdr))) ==
+ NULL) {
+ DPRINTF(("mplsip_input(): m_pullup() failed\n"));
+ etheripstat.etherip_adrops++;
+ return;
+ }
+ }
+
+ sc = etherip_getgif(m);
+ if (sc == NULL)
+ return;
+
+ /* Chop off the `outer' IP header and reschedule. */
+ m_adj(m, iphlen);
+
+ /* Statistics */
+ etheripstat.etherip_ibytes += m->m_pkthdr.len;
+
+ /* Reset the flags based */
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+
+#if NBPFILTER > 0
+ if (sc->gif_if.if_bpf)
+ bpf_mtap_af(sc->gif_if.if_bpf, AF_MPLS, m, BPF_DIRECTION_IN);
+#endif
+
+ m->m_pkthdr.rcvif = &sc->gif_if;
+ m->m_pkthdr.rdomain = sc->gif_if.if_rdomain;
+#if NPF > 0
+ pf_pkt_addr_changed(m);
+#endif
+
+ ifq = &mplsintrq;
+ s = splnet();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ etheripstat.etherip_qfull++;
+ splx(s);
+
+ DPRINTF(("mplsip_input(): packet dropped because of full "
+ "queue\n"));
+ return;
+ }
+ IF_ENQUEUE(ifq, m);
+ schednetisr(NETISR_MPLS);
+ splx(s);
+ return;
+}
+#endif
+
+struct gif_softc *
+etherip_getgif(struct mbuf *m)
+{
+ union sockaddr_union ssrc, sdst;
+ struct gif_softc *sc;
+ u_int8_t v;
+
/* Copy the addresses for use later. */
bzero(&ssrc, sizeof(ssrc));
bzero(&sdst, sizeof(sdst));
@@ -196,29 +404,9 @@ etherip_input(struct mbuf *m, ...)
DPRINTF(("etherip_input(): invalid protocol %d\n", v));
m_freem(m);
etheripstat.etherip_hdrops++;
- return /* EAFNOSUPPORT */;
+ return NULL;
}
- /* Chop off the `outer' IP and EtherIP headers and reschedule. */
- m_adj(m, iphlen + sizeof(struct etherip_header));
-
- /* Statistics */
- etheripstat.etherip_ibytes += m->m_pkthdr.len;
-
- /* Copy ethernet header */
- m_copydata(m, 0, sizeof(eh), (void *) &eh);
-
- /* Reset the flags based on the inner packet */
- m->m_flags &= ~(M_BCAST|M_MCAST|M_AUTH|M_CONF|M_AUTH_AH);
- 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;
- }
-
-#if NGIF > 0
/* Find appropriate gif(4) interface */
LIST_FOREACH(sc, &gif_softc_list, gif_list) {
if ((sc->gif_psrc == NULL) ||
@@ -227,8 +415,7 @@ etherip_input(struct mbuf *m, ...)
continue;
if (!bcmp(sc->gif_psrc, &sdst, sc->gif_psrc->sa_len) &&
- !bcmp(sc->gif_pdst, &ssrc, sc->gif_pdst->sa_len) &&
- sc->gif_if.if_bridge != NULL)
+ !bcmp(sc->gif_pdst, &ssrc, sc->gif_pdst->sa_len))
break;
}
@@ -237,54 +424,22 @@ etherip_input(struct mbuf *m, ...)
DPRINTF(("etherip_input(): no interface found\n"));
etheripstat.etherip_noifdrops++;
m_freem(m);
- return;
+ return NULL;
}
-#if NBPFILTER > 0
- if (sc->gif_if.if_bpf)
- bpf_mtap_af(sc->gif_if.if_bpf, AF_LINK, m, BPF_DIRECTION_IN);
-#endif
-
- /* Trim the beginning of the mbuf, to remove the ethernet header. */
- m_adj(m, sizeof(struct ether_header));
-#if NBRIDGE > 0
- /*
- * Tap the packet off here for a bridge. bridge_input() returns
- * NULL if it has consumed the packet. In the case of gif's,
- * bridge_input() returns non-NULL when an error occurs.
- */
- m->m_pkthdr.rcvif = &sc->gif_if;
- m->m_pkthdr.rdomain = sc->gif_if.if_rdomain;
- if (m->m_flags & (M_BCAST|M_MCAST))
- sc->gif_if.if_imcasts++;
-
- s = splnet();
- m = bridge_input(&sc->gif_if, &eh, m);
- splx(s);
- if (m == NULL)
- return;
-#endif /* NBRIDGE */
-#endif /* NGIF */
-
- etheripstat.etherip_noifdrops++;
- m_freem(m);
- return;
+ return sc;
}
int
-etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
- int protoff)
+etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int proto)
{
#ifdef INET
struct ip *ipo;
#endif /* INET */
-
#ifdef INET6
struct ip6_hdr *ip6;
#endif /* INET6 */
-
struct etherip_header eip;
- struct mbuf *m0;
ushort hlen;
/* Some address family sanity checks. */
@@ -335,27 +490,16 @@ etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
return EINVAL;
}
- /* Don't forget the EtherIP header. */
- hlen += sizeof(struct etherip_header);
-
- if (!(m->m_flags & M_PKTHDR)) {
- DPRINTF(("etherip_output(): mbuf is not a header\n"));
- m_freem(m);
- return (ENOBUFS);
- }
+ if (proto == IPPROTO_ETHERIP)
+ /* Don't forget the EtherIP header. */
+ hlen += sizeof(struct etherip_header);
- MGETHDR(m0, M_DONTWAIT, MT_DATA);
- if (m0 == NULL) {
- DPRINTF(("etherip_output(): M_GETHDR failed\n"));
+ M_PREPEND(m, hlen, M_DONTWAIT);
+ if (m == NULL) {
+ DPRINTF(("etherip_output(): M_PREPEND failed\n"));
etheripstat.etherip_adrops++;
- m_freem(m);
return ENOBUFS;
}
- M_MOVE_PKTHDR(m0, m);
- m0->m_next = m;
- m0->m_len = hlen;
- m0->m_pkthdr.len += hlen;
- m = m0;
/* Statistics */
etheripstat.etherip_opackets++;
@@ -370,7 +514,7 @@ etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
ipo->ip_hl = 5;
ipo->ip_len = htons(m->m_pkthdr.len);
ipo->ip_ttl = ip_defttl;
- ipo->ip_p = IPPROTO_ETHERIP;
+ ipo->ip_p = proto;
ipo->ip_tos = 0;
ipo->ip_off = 0;
ipo->ip_sum = 0;
@@ -390,7 +534,7 @@ etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_flow = 0;
- ip6->ip6_nxt = IPPROTO_ETHERIP;
+ ip6->ip6_nxt = proto;
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
@@ -401,11 +545,13 @@ etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
#endif /* INET6 */
}
- /* Set the version number */
- eip.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
- eip.eip_pad = 0;
- m_copyback(m, hlen - sizeof(struct etherip_header),
- sizeof(struct etherip_header), &eip);
+ if (proto == IPPROTO_ETHERIP) {
+ /* Set the version number */
+ eip.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
+ eip.eip_pad = 0;
+ m_copyback(m, hlen - sizeof(struct etherip_header),
+ sizeof(struct etherip_header), &eip);
+ }
*mp = m;
diff --git a/sys/netinet/ip_ether.h b/sys/netinet/ip_ether.h
index c2372557bd6..3eca19bf521 100644
--- a/sys/netinet/ip_ether.h
+++ b/sys/netinet/ip_ether.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ether.h,v 1.14 2007/12/14 18:33:41 deraadt Exp $ */
+/* $OpenBSD: ip_ether.h,v 1.15 2010/05/11 09:36:07 claudio Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@adk.gr)
*
@@ -64,6 +64,11 @@ struct etherip_header {
}
#ifdef _KERNEL
+int etherip_output(struct mbuf *, struct tdb *, struct mbuf **, int);
+void etherip_input(struct mbuf *, ...);
+#ifdef INET6
+int etherip_input6(struct mbuf **, int *, int);
+#endif
int etherip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
extern int etherip_allow;
diff --git a/sys/netinet/ip_ipip.c b/sys/netinet/ip_ipip.c
index b67f20a566a..6a48e52bb0b 100644
--- a/sys/netinet/ip_ipip.c
+++ b/sys/netinet/ip_ipip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipip.c,v 1.46 2010/04/20 22:05:43 tedu Exp $ */
+/* $OpenBSD: ip_ipip.c,v 1.47 2010/05/11 09:36:07 claudio Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -103,7 +103,7 @@ ip4_input6(struct mbuf **m, int *offp, int proto)
return IPPROTO_DONE;
}
- ipip_input(*m, *offp, NULL);
+ ipip_input(*m, *offp, NULL, proto);
return IPPROTO_DONE;
}
#endif /* INET6 */
@@ -115,6 +115,7 @@ ip4_input6(struct mbuf **m, int *offp, int proto)
void
ip4_input(struct mbuf *m, ...)
{
+ struct ip *ip;
va_list ap;
int iphlen;
@@ -130,7 +131,9 @@ ip4_input(struct mbuf *m, ...)
iphlen = va_arg(ap, int);
va_end(ap);
- ipip_input(m, iphlen, NULL);
+ ip = mtod(m, struct ip *);
+
+ ipip_input(m, iphlen, NULL, ip->ip_p);
}
#endif /* INET */
@@ -142,7 +145,7 @@ ip4_input(struct mbuf *m, ...)
*/
void
-ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
+ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp, int proto)
{
struct sockaddr_in *sin;
struct ifnet *ifp;
@@ -152,13 +155,14 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
u_int rdomain;
#ifdef INET6
struct sockaddr_in6 *sin6;
- struct ip6_hdr *ip6 = NULL;
+ struct ip6_hdr *ip6;
u_int8_t itos;
#endif
int isr;
+ int hlen, s;
u_int8_t otos;
u_int8_t v;
- int hlen, s;
+ sa_family_t af;
ipipstat.ipips_ipackets++;
@@ -166,16 +170,16 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
switch (v >> 4) {
#ifdef INET
- case 4:
+ case 4:
hlen = sizeof(struct ip);
break;
#endif /* INET */
#ifdef INET6
- case 6:
+ case 6:
hlen = sizeof(struct ip6_hdr);
break;
#endif
- default:
+ default:
ipipstat.ipips_family++;
m_freem(m);
return /* EAFNOSUPPORT */;
@@ -190,18 +194,19 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
}
}
- ipo = mtod(m, struct ip *);
/* Keep outer ecn field. */
switch (v >> 4) {
#ifdef INET
case 4:
+ ipo = mtod(m, struct ip *);
otos = ipo->ip_tos;
break;
#endif /* INET */
#ifdef INET6
case 6:
- otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
+ ip6 = mtod(m, struct ip6_hdr *);
+ otos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
break;
#endif
default:
@@ -218,17 +223,15 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
return;
}
- m_copydata(m, 0, 1, &v);
-
- switch (v >> 4) {
+ switch (proto) {
#ifdef INET
- case 4:
+ case IPPROTO_IPV4:
hlen = sizeof(struct ip);
break;
#endif /* INET */
#ifdef INET6
- case 6:
+ case IPPROTO_IPV6:
hlen = sizeof(struct ip6_hdr);
break;
#endif
@@ -239,7 +242,7 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
}
/*
- * Bring the inner IP header in the first mbuf, if not there already.
+ * Bring the inner header into the first mbuf, if not there already.
*/
if (m->m_len < hlen) {
if ((m = m_pullup(m, hlen)) == NULL) {
@@ -256,19 +259,25 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
*/
/* Some sanity checks in the inner IP header */
- switch (v >> 4) {
+ switch (proto) {
#ifdef INET
- case 4:
- ipo = mtod(m, struct ip *);
+ case IPPROTO_IPV4:
+ ipo = mtod(m, struct ip *);
+#ifdef INET6
+ ip6 = NULL;
+#endif
if (!ip_ecn_egress(ECN_ALLOWED, &otos, &ipo->ip_tos)) {
m_freem(m);
return;
}
- break;
+ break;
#endif /* INET */
#ifdef INET6
- case 6:
- ip6 = (struct ip6_hdr *) ipo;
+ case IPPROTO_IPV6:
+#ifdef INET
+ ipo = NULL;
+#endif
+ ip6 = mtod(m, struct ip6_hdr *);
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) {
m_freem(m);
@@ -276,10 +285,15 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
}
ip6->ip6_flow &= ~htonl(0xff << 20);
ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
- break;
+ break;
#endif
default:
- panic("ipip_input: should never reach here");
+#ifdef INET
+ ipo = NULL;
+#endif
+#ifdef INET6
+ ip6 = NULL;
+#endif
}
/* Check for local address spoofing. */
@@ -297,8 +311,8 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
AF_INET)
continue;
- sin = (struct sockaddr_in *) ifa->ifa_addr;
-
+ sin = (struct sockaddr_in *)
+ ifa->ifa_addr;
if (sin->sin_addr.s_addr ==
ipo->ip_src.s_addr) {
ipipstat.ipips_spoof++;
@@ -307,16 +321,16 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
}
}
#endif /* INET */
-
#ifdef INET6
if (ip6) {
if (ifa->ifa_addr->sa_family !=
AF_INET6)
continue;
- sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
-
- if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
+ sin6 = (struct sockaddr_in6 *)
+ ifa->ifa_addr;
+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
+ &ip6->ip6_src)) {
ipipstat.ipips_spoof++;
m_freem(m);
return;
@@ -339,17 +353,19 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
* untrusted packets.
*/
- switch (v >> 4) {
+ switch (proto) {
#ifdef INET
- case 4:
+ case IPPROTO_IPV4:
ifq = &ipintrq;
isr = NETISR_IP;
+ af = AF_INET;
break;
#endif
#ifdef INET6
- case 6:
+ case IPPROTO_IPV6:
ifq = &ip6intrq;
isr = NETISR_IPV6;
+ af = AF_INET6;
break;
#endif
default:
@@ -358,8 +374,7 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
#if NBPFILTER > 0
if (gifp && gifp->if_bpf)
- bpf_mtap_af(gifp->if_bpf, ifq == &ipintrq ? AF_INET : AF_INET6,
- m, BPF_DIRECTION_IN);
+ bpf_mtap_af(gifp->if_bpf, af, m, BPF_DIRECTION_IN);
#endif
#if NPF > 0
pf_pkt_addr_changed(m);
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 01eb0282ffe..8d8f14323d0 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.141 2010/05/07 13:33:17 claudio Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.142 2010/05/11 09:36:07 claudio Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -534,7 +534,7 @@ extern int ipe4_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int ipe4_zeroize(struct tdb *);
extern int ipip_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
extern void ipe4_input(struct mbuf *, ...);
-extern void ipip_input(struct mbuf *, int, struct ifnet *);
+extern void ipip_input(struct mbuf *, int, struct ifnet *, int);
#ifdef INET
extern void ip4_input(struct mbuf *, ...);
@@ -544,11 +544,6 @@ extern void ip4_input(struct mbuf *, ...);
extern int ip4_input6(struct mbuf **, int *, int);
#endif /* INET */
-/* XF_ETHERIP */
-extern int etherip_output(struct mbuf *, struct tdb *, struct mbuf **,
- int, int);
-extern void etherip_input(struct mbuf *, ...);
-
/* XF_AH */
extern int ah_attach(void);
extern int ah_init(struct tdb *, struct xformsw *, struct ipsecinit *);
diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c
index f5ed9e3595d..2e37eb823b6 100644
--- a/sys/netinet6/in6_gif.c
+++ b/sys/netinet6/in6_gif.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_gif.c,v 1.28 2010/05/07 13:33:17 claudio Exp $ */
+/* $OpenBSD: in6_gif.c,v 1.29 2010/05/11 09:36:07 claudio Exp $ */
/* $KAME: in6_gif.c,v 1.43 2001/01/22 07:27:17 itojun Exp $ */
/*
@@ -60,15 +60,14 @@
#include <netinet6/ip6_var.h>
#include <netinet6/in6_gif.h>
-#ifdef INET6
-#include <netinet/ip6.h>
-#endif
-
#include <netinet/ip_ecn.h>
#include <net/if_gif.h>
#include "bridge.h"
+#if NBRIDGE > 0
+#include <netinet/ip_ether.h>
+#endif
#ifndef offsetof
#define offsetof(s, e) ((int)&((s *)0)->e)
@@ -78,16 +77,15 @@
* family - family of the packet to be encapsulate.
*/
int
-in6_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
+in6_gif_output(struct ifnet *ifp, int family, struct mbuf **m0)
{
struct gif_softc *sc = (struct gif_softc*)ifp;
- struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc;
struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst;
struct tdb tdb;
struct xformsw xfs;
int error;
- struct mbuf *mp;
+ struct mbuf *m = *m0;
if (sin6_src == NULL || sin6_dst == NULL ||
sin6_src->sin6_family != AF_INET6 ||
@@ -120,7 +118,11 @@ in6_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
#if NBRIDGE > 0
case AF_LINK:
break;
-#endif /* NBRIDGE */
+#endif
+#ifdef MPLS
+ case AF_MPLS:
+ break;
+#endif
default:
#ifdef DEBUG
printf("in6_gif_output: warning: unknown family %d passed\n",
@@ -131,55 +133,29 @@ in6_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
}
/* encapsulate into IPv6 packet */
- mp = NULL;
+ *m0 = NULL;
#if NBRIDGE > 0
if (family == AF_LINK)
- error = etherip_output(m, &tdb, &mp, 0, 0);
+ error = etherip_output(m, &tdb, m0, IPPROTO_ETHERIP);
else
#endif /* NBRIDGE */
- error = ipip_output(m, &tdb, &mp, 0, 0);
+#if MPLS
+ if (family == AF_MPLS)
+ error = etherip_output(m, &tdb, m0, IPPROTO_MPLS);
+ else
+#endif
+ error = ipip_output(m, &tdb, m0, 0, 0);
if (error)
return error;
- else if (mp == NULL)
+ else if (*m0 == NULL)
return EFAULT;
- m = mp;
-
- /* See if out cached route remains the same */
- if (dst->sin6_family != sin6_dst->sin6_family ||
- !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) {
- /* cache route doesn't match */
- bzero(dst, sizeof(*dst));
- dst->sin6_family = sin6_dst->sin6_family;
- dst->sin6_len = sizeof(struct sockaddr_in6);
- dst->sin6_addr = sin6_dst->sin6_addr;
- /* XXX rdomain */
- sc->gif_ro6.ro_tableid = 0;
- if (sc->gif_ro6.ro_rt) {
- RTFREE(sc->gif_ro6.ro_rt);
- sc->gif_ro6.ro_rt = NULL;
- }
- }
+ m = *m0;
- if (sc->gif_ro6.ro_rt == NULL) {
- rtalloc((struct route *)&sc->gif_ro6);
- if (sc->gif_ro6.ro_rt == NULL) {
- m_freem(m);
- return ENETUNREACH;
- }
- }
-
- /*
- * 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.
- */
#if NPF > 0
pf_pkt_addr_changed(m);
#endif
- error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL, NULL);
-
- return error;
+ return 0;
}
int in6_gif_input(struct mbuf **mp, int *offp, int proto)
@@ -217,12 +193,12 @@ int in6_gif_input(struct mbuf **mp, int *offp, int proto)
m->m_pkthdr.rcvif = gifp;
gifp->if_ipackets++;
gifp->if_ibytes += m->m_pkthdr.len;
- ipip_input(m, *offp, gifp);
+ ipip_input(m, *offp, gifp, proto);
return IPPROTO_DONE;
}
inject:
/* No GIF tunnel configured */
- ip4_input6(&m, offp, 0); /* XXX last argument ignored */
+ ip4_input6(&m, offp, proto);
return IPPROTO_DONE;
}
diff --git a/sys/netinet6/in6_gif.h b/sys/netinet6/in6_gif.h
index 209db1471b7..62713f69120 100644
--- a/sys/netinet6/in6_gif.h
+++ b/sys/netinet6/in6_gif.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_gif.h,v 1.5 2007/02/10 15:34:22 claudio Exp $ */
+/* $OpenBSD: in6_gif.h,v 1.6 2010/05/11 09:36:07 claudio Exp $ */
/* $KAME: in6_gif.h,v 1.5 2000/04/14 08:36:03 itojun Exp $ */
/*
@@ -33,7 +33,7 @@
#ifndef _NETINET6_IN6_GIF_H_
#define _NETINET6_IN6_GIF_H_
+int in6_gif_output(struct ifnet *, int, struct mbuf **);
int in6_gif_input(struct mbuf **, int *, int);
-int in6_gif_output(struct ifnet *, int, struct mbuf *);
#endif /*_NETINET6_IN6_GIF_H_*/