summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files4
-rw-r--r--sys/netinet/in.h4
-rw-r--r--sys/netinet/in_gif.c13
-rw-r--r--sys/netinet/in_proto.c8
-rw-r--r--sys/netinet/ip_ipip.c655
-rw-r--r--sys/netinet/ip_ipip.h (renamed from sys/netinet/ip_ip4.h)44
-rw-r--r--sys/netinet/ip_ipsp.c6
-rw-r--r--sys/netinet/ip_ipsp.h8
-rw-r--r--sys/netinet/ip_mroute.c13
-rw-r--r--sys/netinet/ip_mroute.h4
-rw-r--r--sys/netinet6/in6_gif.c14
-rw-r--r--sys/netinet6/in6_proto.c22
12 files changed, 732 insertions, 63 deletions
diff --git a/sys/conf/files b/sys/conf/files
index ae1fc01194a..b3d6294c202 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.148 2000/01/11 17:58:50 peter Exp $
+# $OpenBSD: files,v 1.149 2000/01/21 03:15:06 angelos Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -496,7 +496,7 @@ file netinet/ip_proxy.c ipfilter
file netinet/ip_auth.c ipfilter
file netinet/ip_log.c ipfilter
file netinet/ip_ipsp.c (inet | inet6) & (ipsec | tcp_signature)
-file netinet/ip_ip4.c inet | inet6
+file netinet/ip_ipip.c inet | inet6
file netinet/ip_ether.c inet & ipsec
file netinet/ipsec_input.c (inet | inet6) & ipsec
file netinet/ip_xform.c inet & ipsec
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 1ea1358fc51..d5562203bed 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.35 2000/01/18 19:06:07 angelos Exp $ */
+/* $OpenBSD: in.h,v 1.36 2000/01/21 03:15:04 angelos Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -318,7 +318,7 @@ struct ip_mreq {
{ "icmp", CTLTYPE_NODE }, \
{ "igmp", CTLTYPE_NODE }, \
{ "ggp", CTLTYPE_NODE }, \
- { "ip4", CTLTYPE_NODE }, \
+ { "ipip", CTLTYPE_NODE }, \
{ 0, 0 }, \
{ "tcp", CTLTYPE_NODE }, \
{ 0, 0 }, \
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 52b50cc4a5a..fb29419712d 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_gif.c,v 1.6 2000/01/11 07:47:09 angelos Exp $ */
+/* $OpenBSD: in_gif.c,v 1.7 2000/01/21 03:15:04 angelos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -110,7 +110,7 @@ in_gif_output(ifp, family, m, rt)
return ENETUNREACH;
}
- /* setup dummy tdb. it highly depends on ipe4_output() code. */
+ /* setup dummy tdb. it highly depends on ipipoutput() code. */
bzero(&tdb, sizeof(tdb));
bzero(&xfs, sizeof(xfs));
tdb.tdb_src.sin.sin_family = AF_INET;
@@ -149,7 +149,7 @@ in_gif_output(ifp, family, m, rt)
/* encapsulate into IPv4 packet */
mp = NULL;
- error = ipe4_output(m, &tdb, &mp, hlen, poff);
+ error = ipip_output(m, &tdb, &mp, hlen, poff);
if (error)
return error;
else if (mp == NULL)
@@ -223,10 +223,13 @@ in_gif_input(m, va_alist)
}
}
- if (gifp && (m->m_flags & (M_AUTH | M_CONF)) == 0)
+ if (gifp) {
m->m_pkthdr.rcvif = gifp;
+ ipip_input(m, off); /* We have a configured GIF */
+ return;
+ }
inject:
- ip4_input(m, off);
+ ip4_input(m, off); /* No GIF interface was configured */
return;
}
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 00b91a4facc..da7125e73fa 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_proto.c,v 1.23 2000/01/17 05:17:24 itojun Exp $ */
+/* $OpenBSD: in_proto.c,v 1.24 2000/01/21 03:15:05 angelos Exp $ */
/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */
/*
@@ -159,7 +159,7 @@ void iplinit __P((void));
#include <netinet/ip_ether.h>
#endif
-#include <netinet/ip_ip4.h>
+#include <netinet/ip_ipip.h>
#include "gre.h"
#if NGRE > 0
@@ -199,7 +199,7 @@ struct protosw inetsw[] = {
{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
in_gif_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
- 0, 0, 0, 0, ip4_sysctl
+ 0, 0, 0, 0, ipip_sysctl
},
#ifdef INET6
{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
@@ -212,7 +212,7 @@ struct protosw inetsw[] = {
{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
ip4_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
- 0, 0, 0, 0, ip4_sysctl
+ 0, 0, 0, 0, ipip_sysctl
},
#ifdef INET6
{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
diff --git a/sys/netinet/ip_ipip.c b/sys/netinet/ip_ipip.c
new file mode 100644
index 00000000000..383b6133977
--- /dev/null
+++ b/sys/netinet/ip_ipip.c
@@ -0,0 +1,655 @@
+/* $OpenBSD: ip_ipip.c,v 1.1 2000/01/21 03:15:05 angelos Exp $ */
+
+/*
+ * The authors of this code are John Ioannidis (ji@tla.org),
+ * Angelos D. Keromytis (kermit@csd.uch.gr) and
+ * Niels Provos (provos@physnet.uni-hamburg.de).
+ *
+ * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
+ * in November 1995.
+ *
+ * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
+ * by Angelos D. Keromytis.
+ *
+ * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
+ * and Niels Provos.
+ *
+ * Additional features in 1999 by Angelos D. Keromytis.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
+ * Angelos D. Keromytis and Niels Provos.
+ *
+ * Permission to use, copy, and modify this software without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software.
+ * You may use this code under the GNU public license if you so wish. Please
+ * contribute changes back to the authors under this freer than GPL license
+ * so that we may further the use of strong encryption without limitations to
+ * all.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+/*
+ * IP-inside-IP processing
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/netisr.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_ecn.h>
+
+#ifdef MROUTING
+#include <netinet/ip_mroute.h>
+#endif
+
+#include <sys/socketvar.h>
+#include <net/raw_cb.h>
+
+#include <netinet/ip_ipsp.h>
+#include <netinet/ip_ipip.h>
+#include <dev/rndvar.h>
+
+#ifdef ENCDEBUG
+#define DPRINTF(x) if (encdebug) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+#ifndef offsetof
+#define offsetof(s, e) ((int)&((s *)0)->e)
+#endif
+
+/*
+ * We can control the acceptance of IP4 packets by altering the sysctl
+ * net.inet.ipip.allow value. Zero means drop them, all else is acceptance.
+ */
+int ipip_allow = 0;
+
+struct ipipstat ipipstat;
+
+#ifdef INET6
+/*
+ * Really only a wrapper for ipip_input(), for use with IPv6.
+ */
+int
+ip4_input6(struct mbuf **m, int *offp, int proto)
+{
+ /* If we do not accept IPv4 explicitly, drop. */
+ if (!ipip_allow && ((*m)->m_flags & (M_AUTH|M_CONF)) == 0)
+ {
+ DPRINTF(("ip4_input6(): dropped due to policy\n"));
+ ipipstat.ipips_pdrops++;
+ m_freem(*m);
+ return IPPROTO_DONE;
+ }
+
+ ipip_input(*m, *offp);
+ return IPPROTO_DONE;
+}
+#endif /* INET6 */
+
+#ifdef INET
+/*
+ * Really only a wrapper for ipip_input(), for use with IPv4.
+ */
+void
+ip4_input(struct mbuf *m, ...)
+{
+ va_list ap;
+ int iphlen;
+
+ /* If we do not accept IPv4 explicitly, drop. */
+ if (!ipip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0)
+ {
+ DPRINTF(("ip4_input(): dropped due to policy\n"));
+ ipipstat.ipips_pdrops++;
+ m_freem(m);
+ return;
+ }
+
+ va_start(ap, m);
+ iphlen = va_arg(ap, int);
+ va_end(ap);
+
+ ipip_input(m, iphlen);
+}
+#endif /* INET */
+
+/*
+ * ipip_input gets called when we receive an IP{46} 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.
+ */
+
+void
+ipip_input(struct mbuf *m, int iphlen)
+{
+ register struct sockaddr_in *sin;
+ register struct ifnet *ifp;
+ register struct ifaddr *ifa;
+ struct ifqueue *ifq = NULL;
+ struct ip *ipo;
+#ifdef INET6
+ register struct sockaddr_in6 *sin6;
+ struct ip6_hdr *ip6 = NULL;
+ u_int8_t itos;
+#endif
+ u_int8_t nxt;
+ int isr;
+ u_int8_t otos;
+ u_int8_t v;
+ int hlen, s;
+
+ ipipstat.ipips_ipackets++;
+
+ m_copydata(m, 0, 1, &v);
+
+ switch (v >> 4)
+ {
+#ifdef INET
+ case 4:
+ hlen = sizeof(struct ip);
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case 6:
+ hlen = sizeof(struct ip6_hdr);
+ break;
+#endif
+ default
+ m_freem(m);
+ return /* EAFNOSUPPORT */;
+ }
+
+ /* Bring the IP header in the first mbuf, if not there already */
+ if (m->m_len < hlen)
+ {
+ if ((m = m_pullup(m, hlen)) == 0)
+ {
+ DPRINTF(("ipip_input(): m_pullup() failed\n"));
+ ipipstat.ipips_hdrops++;
+ m_freem(m);
+ return;
+ }
+ }
+
+ ipo = mtod(m, struct ip *);
+
+#ifdef MROUTING
+ if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4)
+ {
+ if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr))
+ {
+ ipip_mroute_input (m, iphlen);
+ return;
+ }
+ }
+#endif MROUTING
+
+ /* keep outer ecn field */
+
+#ifdef INET
+ if ((v >> 4) == 4)
+ otos = ipo->ip_tos;
+#endif /* INET */
+
+#ifdef INET6
+ if ((v >> 4) == 6)
+ otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
+#endif
+
+ /* Remove outter IP header */
+ m_adj(m, iphlen);
+
+ m_copydata(m, 0, 1, &v);
+
+ switch (v >> 4)
+ {
+#ifdef INET
+ case 4:
+ hlen = sizeof(struct ip);
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case 6:
+ hlen = sizeof(struct ip6_hdr);
+ break;
+#endif
+
+ default:
+ m_freem(m);
+ return /* EAFNOSUPPORT */;
+ }
+
+ /* Bring the inner IP header in the first mbuf, if not there already */
+ if (m->m_len < hlen)
+ {
+ if ((m = m_pullup(m, hlen)) == 0)
+ {
+ DPRINTF(("ipip_input(): m_pullup() failed\n"));
+ ipipstat.ipips_hdrops++;
+ return;
+ }
+ }
+
+ /*
+ * RFC 1853 specifies that the inner TTL should not be touched on
+ * decapsulation. There's no reason this comment should be here, but
+ * this is as good as any a position.
+ */
+
+ /* Some sanity checks in the inner IPv4 header */
+ switch (v >> 4)
+ {
+#ifdef INET
+ case 4:
+ ipo = mtod(m, struct ip *);
+ nxt = ipo->ip_p;
+ ip_ecn_egress(ECN_ALLOWED, &otos, &ipo->ip_tos);
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case 6:
+ ip6 = (struct ip6_hdr *) ipo;
+ nxt = ip6->ip6_nxt;
+ itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+ ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
+ ip6->ip6_flow &= ~htonl(0xff << 20);
+ ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
+ break;
+#endif
+ }
+
+ /* Check for local address spoofing. */
+ if (m->m_pkthdr.rcvif == NULL ||
+ !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK))
+ {
+ for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
+ {
+ for (ifa = ifp->if_addrlist.tqh_first;
+ ifa != 0;
+ ifa = ifa->ifa_list.tqe_next)
+ {
+#ifdef INET
+ if (ipo)
+ {
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+
+ sin = (struct sockaddr_in *) ifa->ifa_addr;
+
+ if (sin->sin_addr.s_addr == ipo->ip_src.s_addr)
+ {
+ DPRINTF(("ipip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst)));
+ ipipstat.ipips_spoof++;
+ m_freem(m);
+ return;
+ }
+ }
+#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))
+ {
+ DPRINTF(("ipip_input(): possible local address spoofing detected on packet\n"));
+ m_freem(m);
+ return;
+ }
+
+ }
+#endif /* INET6 */
+ }
+ }
+ }
+
+ /* Statistics */
+ ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
+
+ /* tdbi is only set in ESP or AH, if the next protocol is UDP or TCP */
+ if (m->m_flags & (M_CONF|M_AUTH))
+ m->m_pkthdr.tdbi = NULL;
+
+ /*
+ * Interface pointer stays the same; if no IPsec processing has
+ * been done (or will be done), this will point to a normal
+ * interface. Otherwise, it'll point to an enc interface, which
+ * will allow a packet filter to distinguish between secure and
+ * untrusted packets.
+ */
+
+#ifdef INET
+ if (ipo)
+ {
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ }
+#endif /* INET */
+
+#ifdef INET6
+ if (ip6)
+ {
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ }
+#endif /* INET6 */
+
+ s = splimp(); /* isn't it already? */
+ if (IF_QFULL(ifq))
+ {
+ IF_DROP(ifq);
+ m_freem(m);
+ ipipstat.ipips_qfull++;
+
+ splx(s);
+
+ DPRINTF(("ipip_input(): packet dropped because of full queue\n"));
+ return;
+ }
+
+ IF_ENQUEUE(ifq, m);
+ schednetisr(isr);
+ splx(s);
+
+ return;
+}
+
+int
+ipip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
+{
+ u_int8_t tp, otos;
+
+#ifdef INET
+ u_int8_t itos;
+ struct ip *ipo;
+#endif /* INET */
+
+#ifdef INET6
+ struct ip6_hdr *ip6o;
+#endif /* INET6 */
+
+ /* Deal with empty TDB source/destination addresses */
+ /* XXX */
+
+ m_copydata(m, 0, 1, &tp);
+ tp = (tp >> 4) & 0xff; /* Get the IP version number */
+
+ switch (tdb->tdb_dst.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ if ((tdb->tdb_src.sa.sa_family != AF_INET) ||
+ (tdb->tdb_src.sin.sin_addr.s_addr == INADDR_ANY) ||
+ (tdb->tdb_dst.sin.sin_addr.s_addr == INADDR_ANY))
+ {
+ DPRINTF(("ipip_output(): unspecified tunnel endpoind address in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ ipipstat.ipips_unspec++;
+ m_freem(m);
+ *mp = NULL;
+ return EINVAL;
+ }
+
+ M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
+ if (m == 0)
+ {
+ DPRINTF(("ipip_output(): M_PREPEND failed\n"));
+ ipipstat.ipips_hdrops++;
+ *mp = NULL;
+ return ENOBUFS;
+ }
+
+ ipo = mtod(m, struct ip *);
+
+ ipo->ip_v = IPVERSION;
+ ipo->ip_hl = 5;
+ ipo->ip_len = htons(m->m_pkthdr.len);
+ ipo->ip_ttl = ip_defttl;
+ ipo->ip_sum = 0;
+ ipo->ip_src = tdb->tdb_src.sin.sin_addr;
+ ipo->ip_dst = tdb->tdb_dst.sin.sin_addr;
+
+ /*
+ * We do the htons() to prevent snoopers from determining our
+ * endianness.
+ */
+ ipo->ip_id = htons(ip_randomid());
+
+ /* If the inner protocol is IP */
+ if (tp == IPVERSION)
+ {
+ /* Save ECN notification */
+ m_copydata(m, sizeof(struct ip) + offsetof(struct ip, ip_tos),
+ sizeof(u_int8_t), (caddr_t) &itos);
+
+ ipo->ip_p = IPPROTO_IPIP;
+
+ /*
+ * We should be keeping tunnel soft-state and send back ICMPs
+ * if needed.
+ */
+ m_copydata(m, sizeof(struct ip) + offsetof(struct ip, ip_off),
+ sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
+ ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
+ }
+#ifdef INET6
+ else if (tp == (IPV6_VERSION >> 4))
+ {
+ u_int32_t itos32;
+ /* Save ECN notification */
+ m_copydata(m, sizeof(struct ip) +
+ offsetof(struct ip6_hdr, ip6_flow),
+ sizeof(u_int32_t), (caddr_t) &itos32);
+ itos = ntohl(itos32) >> 20;
+
+ ipo->ip_p = IPPROTO_IPV6;
+ ipo->ip_off = 0;
+ }
+#endif /* INET6 */
+ else
+ {
+ m_freem(m);
+ *mp = NULL;
+ return EAFNOSUPPORT;
+ }
+
+ otos = 0;
+ ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
+ ipo->ip_tos = otos;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr) ||
+ (tdb->tdb_src.sa.sa_family != AF_INET6) ||
+ IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_src.sin6.sin6_addr))
+ {
+ DPRINTF(("ipip_output(): unspecified tunnel endpoind address in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ ipipstat.ipips_unspec++;
+ m_freem(m);
+ *mp = NULL;
+ return ENOBUFS;
+ }
+
+ M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
+ if (m == 0)
+ {
+ DPRINTF(("ipip_output(): M_PREPEND failed\n"));
+ ipipstat.ipips_hdrops++;
+ *mp = NULL;
+ return ENOBUFS;
+ }
+
+ /* Initialize IPv6 header */
+ ip6o = mtod(m, struct ip6_hdr *);
+ ip6o->ip6_flow = 0;
+ ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
+ ip6o->ip6_vfc |= IPV6_VERSION;
+ ip6o->ip6_plen = htons(m->m_pkthdr.len);
+ ip6o->ip6_hlim = ip_defttl;
+ ip6o->ip6_dst = tdb->tdb_dst.sin6.sin6_addr;
+ ip6o->ip6_src = tdb->tdb_src.sin6.sin6_addr;
+
+#ifdef INET
+ if (tp == IPVERSION)
+ {
+ /* Save ECN notification */
+ m_copydata(m, sizeof(struct ip6_hdr) +
+ offsetof(struct ip, ip_tos), sizeof(u_int8_t),
+ (caddr_t) &itos);
+
+ ip6o->ip6_nxt = IPPROTO_IPIP; /* This is really IPVERSION */
+ }
+ else
+#endif /* INET */
+ if (tp == (IPV6_VERSION >> 4))
+ {
+ u_int32_t itos32;
+ /* Save ECN notification */
+ m_copydata(m, sizeof(struct ip6_hdr) +
+ offsetof(struct ip6_hdr, ip6_flow),
+ sizeof(u_int32_t), (caddr_t) &itos32);
+ itos = ntohl(itos32) >> 20;
+
+ ip6o->ip6_nxt = IPPROTO_IPV6;
+ }
+ else
+ {
+ m_freem(m);
+ *mp = NULL;
+ return EAFNOSUPPORT;
+ }
+
+ otos = 0;
+ ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
+ ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
+ break;
+#endif /* INET6 */
+
+ default:
+ DPRINTF(("ipip_output(): unsupported protocol family %d\n",
+ tdb->tdb_dst.sa.sa_family));
+ m_freem(m);
+ *mp = NULL;
+ ipipstat.ipips_family++;
+ return ENOBUFS;
+ }
+
+ ipipstat.ipips_opackets++;
+
+ *mp = m;
+
+#ifdef INET
+ if (tdb->tdb_dst.sa.sa_family == AF_INET)
+ {
+ if (tdb->tdb_xform->xf_type == XF_IP4)
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - sizeof(struct ip);
+
+ ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip);
+ }
+#endif /* INET */
+
+#ifdef INET6
+ if (tdb->tdb_dst.sa.sa_family == AF_INET6)
+ {
+ if (tdb->tdb_xform->xf_type == XF_IP4)
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - sizeof(struct ip6_hdr);
+
+ ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip6_hdr);
+ }
+#endif /* INET6 */
+
+ return 0;
+}
+
+#ifdef IPSEC
+
+int
+ipe4_attach()
+{
+ return 0;
+}
+
+int
+ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
+{
+ tdbp->tdb_xform = xsp;
+ return 0;
+}
+
+int
+ipe4_zeroize(struct tdb *tdbp)
+{
+ return 0;
+}
+
+void
+ipe4_input(struct mbuf *m, ...)
+{
+ /* This is a rather serious mistake, so no conditional printing */
+ printf("ipe4_input(): should never be called\n");
+ if (m)
+ m_freem(m);
+}
+#endif /* IPSEC */
+
+int
+ipip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+{
+ /* All sysctl names at this level are terminal. */
+ if (namelen != 1)
+ return (ENOTDIR);
+
+ switch (name[0]) {
+ case IPIPCTL_ALLOW:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow));
+ default:
+ return (ENOPROTOOPT);
+ }
+ /* NOTREACHED */
+}
diff --git a/sys/netinet/ip_ip4.h b/sys/netinet/ip_ipip.h
index 5e15d9c4bdd..c413e139ca2 100644
--- a/sys/netinet/ip_ip4.h
+++ b/sys/netinet/ip_ipip.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ip4.h,v 1.17 2000/01/13 05:03:45 angelos Exp $ */
+/* $OpenBSD: ip_ipip.h,v 1.1 2000/01/21 03:15:05 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -35,46 +35,46 @@
* PURPOSE.
*/
-#ifndef _NETINET_IP4_H_
-#define _NETINET_IP4_H_
+#ifndef _NETINET_IPIP_H_
+#define _NETINET_IPIP_H_
/*
* IP-inside-IP processing.
* Not quite all the functionality of RFC-1853, but the main idea is there.
*/
-struct ip4stat
+struct ipipstat
{
- u_int32_t ip4s_ipackets; /* total input packets */
- u_int32_t ip4s_opackets; /* total output packets */
- u_int32_t ip4s_hdrops; /* packet shorter than header shows */
- u_int32_t ip4s_qfull;
- u_int64_t ip4s_ibytes;
- u_int64_t ip4s_obytes;
- u_int32_t ip4s_pdrops; /* packet dropped due to policy */
- u_int32_t ip4s_spoof; /* IP spoofing attempts */
- u_int32_t ip4s_family; /* Protocol family mismatch */
- u_int32_t ip4s_unspec; /* Missing tunnel endpoint address */
+ u_int32_t ipips_ipackets; /* total input packets */
+ u_int32_t ipips_opackets; /* total output packets */
+ u_int32_t ipips_hdrops; /* packet shorter than header shows */
+ u_int32_t ipips_qfull;
+ u_int64_t ipips_ibytes;
+ u_int64_t ipips_obytes;
+ u_int32_t ipips_pdrops; /* packet dropped due to policy */
+ u_int32_t ipips_spoof; /* IP spoofing attempts */
+ u_int32_t ipips_family; /* Protocol family mismatch */
+ u_int32_t ipips_unspec; /* Missing tunnel endpoint address */
};
#define IP4_DEFAULT_TTL 0
#define IP4_SAME_TTL -1
/*
- * Names for IP4 sysctl objects
+ * Names for IPIP sysctl objects
*/
-#define IP4CTL_ALLOW 1 /* accept incoming IP4 packets */
-#define IP4CTL_MAXID 2
+#define IPIPCTL_ALLOW 1 /* accept incoming IP4 packets */
+#define IPIPCTL_MAXID 2
-#define IP4CTL_NAMES { \
+#define IPIPCTL_NAMES { \
{ 0, 0 }, \
{ "allow", CTLTYPE_INT }, \
}
#ifdef _KERNEL
-int ip4_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
+int ipip_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
-extern int ip4_allow;
-extern struct ip4stat ip4stat;
+extern int ipip_allow;
+extern struct ipipstat ipipstat;
#endif /* _KERNEL */
-#endif /* _NETINET_IP4_H_ */
+#endif /* _NETINET_IPIP_H_ */
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index c57f4b8cff8..1cfa5c21bb4 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.75 2000/01/13 05:30:11 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.76 2000/01/21 03:15:05 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -139,7 +139,7 @@ struct xformsw xformsw[] = {
{ XF_IP4, 0, "IPv4 Simple Encapsulation",
ipe4_attach, ipe4_init, ipe4_zeroize,
(struct mbuf * (*)(struct mbuf *, struct tdb *, int, int))ipe4_input,
- ipe4_output, },
+ ipip_output, },
{ XF_OLD_AH, XFT_AUTH, "Keyed Authentication, RFC 1828/1852",
ah_old_attach, ah_old_init, ah_old_zeroize,
ah_old_input, ah_old_output, },
@@ -1822,7 +1822,7 @@ ipsp_process_packet(struct mbuf *m, struct mbuf **mp, struct tdb *tdb, int *af,
#endif /* INET6 */
/* Encapsulate -- the last two arguments are unused */
- error = ipe4_output(m, tdb, mp, 0, 0);
+ error = ipip_output(m, tdb, mp, 0, 0);
if (((*mp) == NULL) && (!error))
error = EFAULT;
if (error)
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 4d240bc2b8b..417b08970ef 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.58 2000/01/13 06:02:31 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.59 2000/01/21 03:15:05 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -547,9 +547,13 @@ extern struct flow *find_global_flow(union sockaddr_union *,
extern int ipe4_attach(void);
extern int ipe4_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int ipe4_zeroize(struct tdb *);
-extern int ipe4_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
+extern int ipip_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
extern void ipe4_input __P((struct mbuf *, ...));
+extern void ipip_input __P((struct mbuf *, int));
+
+#ifdef INET
extern void ip4_input __P((struct mbuf *, ...));
+#endif /* INET */
#ifdef INET6
extern int ip4_input6 __P((struct mbuf **, int *, int));
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 48850137865..b72172ad612 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_mroute.c,v 1.18 1999/08/08 15:04:22 niklas Exp $ */
+/* $OpenBSD: ip_mroute.c,v 1.19 2000/01/21 03:15:05 angelos Exp $ */
/* $NetBSD: ip_mroute.c,v 1.27 1996/05/07 02:40:50 thorpej Exp $ */
/*
@@ -163,7 +163,7 @@ static vifi_t numvifs = 0;
static int have_encap_tunnel = 0;
/*
- * one-back cache used by ipip_input to locate a tunnel's vif
+ * one-back cache used by ipip_mroute_input to locate a tunnel's vif
* given a datagram's src ip address.
*/
static u_int32_t last_encap_src;
@@ -565,7 +565,10 @@ add_vif(m)
/* Prepare cached route entry. */
bzero(&vifp->v_route, sizeof(vifp->v_route));
- /* Tell ipip_input() to start looking at encapsulated packets. */
+ /*
+ * Tell ipip_mroute_input() to start looking at
+ * encapsulated packets.
+ */
have_encap_tunnel = 1;
} else {
/* Use the physical interface associated with the address. */
@@ -1449,9 +1452,9 @@ encap_send(ip, vifp, m)
*/
void
#if __STDC__
-ipip_input(struct mbuf *m, ...)
+ipip_mroute_input(struct mbuf *m, ...)
#else
-ipip_input(m, va_alist)
+ipip_mroute_input(m, va_alist)
struct mbuf *m;
va_dcl
#endif
diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h
index feb51fc1a00..594e1804adc 100644
--- a/sys/netinet/ip_mroute.h
+++ b/sys/netinet/ip_mroute.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_mroute.h,v 1.5 1999/12/08 06:50:20 itojun Exp $ */
+/* $OpenBSD: ip_mroute.h,v 1.6 2000/01/21 03:15:05 angelos Exp $ */
/* $NetBSD: ip_mroute.h,v 1.10 1996/02/13 23:42:55 christos Exp $ */
/*
@@ -230,6 +230,6 @@ void rsvp_input __P((struct mbuf *, int, int));
#else
int ip_mforward __P((struct mbuf *, struct ifnet *));
#endif
-void ipip_input __P((struct mbuf *, ...));
+void ipip_mroute_input __P((struct mbuf *, ...));
#endif /* _KERNEL */
diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c
index 65845c93ad5..dba946b8b42 100644
--- a/sys/netinet6/in6_gif.c
+++ b/sys/netinet6/in6_gif.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_gif.c,v 1.4 2000/01/12 06:35:04 angelos Exp $ */
+/* $OpenBSD: in6_gif.c,v 1.5 2000/01/21 03:15:06 angelos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -101,7 +101,7 @@ in6_gif_output(ifp, family, m, rt)
return ENETUNREACH;
}
- /* setup dummy tdb. it highly depends on ipe4_output() code. */
+ /* setup dummy tdb. it highly depends on ipip_output() code. */
bzero(&tdb, sizeof(tdb));
bzero(&xfs, sizeof(xfs));
tdb.tdb_src.sin6.sin6_family = AF_INET6;
@@ -146,7 +146,7 @@ in6_gif_output(ifp, family, m, rt)
/* encapsulate into IPv6 packet */
mp = NULL;
- error = ipe4_output(m, &tdb, &mp, hlen, poff);
+ error = ipip_output(m, &tdb, &mp, hlen, poff);
if (error)
return error;
else if (mp == NULL)
@@ -224,10 +224,14 @@ int in6_gif_input(mp, offp, proto)
}
}
- if (gifp && (m->m_flags & (M_AUTH | M_CONF)) == 0)
+ if (gifp) {
m->m_pkthdr.rcvif = gifp;
+ ipip_input(m, *offp);
+ return IPPROTO_DONE;
+ }
inject:
- ip4_input(m, *offp);
+ /* No GIF tunnel configured */
+ ip4_input6(&m, offp, 0); /* XXX last argument ignored */
return IPPROTO_DONE;
}
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index b0160854045..1cb08c6c6b3 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_proto.c,v 1.13 2000/01/13 06:01:22 angelos Exp $ */
+/* $OpenBSD: in6_proto.c,v 1.14 2000/01/21 03:15:06 angelos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -93,7 +93,7 @@
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
-#include <netinet/ip_ip4.h>
+#include <netinet/ip_ipip.h>
#include <netinet6/pim6_var.h>
@@ -197,31 +197,31 @@ struct ip6protosw inet6sw[] = {
#endif /* 0 */
#endif /* IPSEC */
#if NGIF > 0
-{ SOCK_RAW, &inet6domain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
in6_gif_input,0, 0, 0,
0,
0, 0, 0, 0,
},
-#ifdef INET6
+#ifdef INET
{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
in6_gif_input,0, 0, 0,
0,
0, 0, 0, 0,
},
-#endif /* INET6 */
+#endif /* INET */
#else /* NFIG */
-{ SOCK_RAW, &inet6domain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
ip4_input6, rip6_output, 0, rip6_ctloutput,
rip6_usrreq, /* XXX */
- 0, 0, 0, 0, ip4_sysctl
+ 0, 0, 0, 0, ipip_sysctl
},
-#ifdef INET6
-{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
- ip4_input6, rip6_output, 0, rip6_ctloutput,
+#ifdef INET
+{ SOCK_RAW, &inet6domain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
+ ip4_input, rip6_output, 0, rip6_ctloutput,
0,
0, 0, 0, 0,
},
-#endif /* INET6 */
+#endif /* INET */
#endif /* GIF */
{ SOCK_RAW, &inet6domain, IPPROTO_PIM, PR_ATOMIC|PR_ADDR,
pim6_input, rip6_output, 0, rip6_ctloutput,