summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c142
1 files changed, 123 insertions, 19 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index a202a8b..be6d25d 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -42,6 +42,7 @@
#include "opt_ipdivert.h"
#include "opt_ipfilter.h"
#include "opt_ipstealth.h"
+#include "opt_ipsec.h"
#include <stddef.h>
@@ -72,10 +73,27 @@
#include <netinet/ip_icmp.h>
#include <machine/in_cksum.h>
+#include <netinet/ipprotosw.h>
+
#include <sys/socketvar.h>
#include <netinet/ip_fw.h>
+#ifdef IPSEC
+#include <netinet6/ipsec.h>
+#include <netkey/key.h>
+#ifdef IPSEC_DEBUG
+#include <netkey/key_debug.h>
+#else
+#define KEYDEBUG(lev,arg)
+#endif
+#endif
+
+#include "faith.h"
+#if defined(NFAITH) && NFAITH > 0
+#include <net/if_types.h>
+#endif
+
#ifdef DUMMYNET
#include <netinet/ip_dummynet.h>
#endif
@@ -104,12 +122,18 @@ static int ip_acceptsourceroute = 0;
SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute,
CTLFLAG_RW, &ip_acceptsourceroute, 0,
"Enable accepting source routed IP packets");
+
+static int ip_keepfaith = 0;
+SYSCTL_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
+ &ip_keepfaith, 0,
+ "Enable packet capture for FAITH IPv4->IPv6 translater daemon");
+
#ifdef DIAGNOSTIC
static int ipprintfs = 0;
#endif
extern struct domain inetdomain;
-extern struct protosw inetsw[];
+extern struct ipprotosw inetsw[];
u_char ip_protox[IPPROTO_MAX];
static int ipqmaxlen = IFQ_MAXLEN;
struct in_ifaddrhead in_ifaddrhead; /* first inet address */
@@ -181,10 +205,10 @@ static int ip_dooptions __P((struct mbuf *));
static void ip_forward __P((struct mbuf *, int));
static void ip_freef __P((struct ipq *));
#ifdef IPDIVERT
-static struct ip *ip_reass __P((struct mbuf *,
+static struct mbuf *ip_reass __P((struct mbuf *,
struct ipq *, struct ipq *, u_int32_t *, u_int16_t *));
#else
-static struct ip *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *));
+static struct mbuf *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *));
#endif
static struct in_ifaddr *ip_rtaddr __P((struct in_addr));
static void ipintr __P((void));
@@ -196,17 +220,17 @@ static void ipintr __P((void));
void
ip_init()
{
- register struct protosw *pr;
+ register struct ipprotosw *pr;
register int i;
TAILQ_INIT(&in_ifaddrhead);
- pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
+ pr = (struct ipprotosw *)pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
if (pr == 0)
panic("ip_init");
for (i = 0; i < IPPROTO_MAX; i++)
ip_protox[i] = pr - inetsw;
- for (pr = inetdomain.dom_protosw;
- pr < inetdomain.dom_protoswNPROTOSW; pr++)
+ for (pr = (struct ipprotosw *)inetdomain.dom_protosw;
+ pr < (struct ipprotosw *)inetdomain.dom_protoswNPROTOSW; pr++)
if (pr->pr_domain->dom_family == PF_INET &&
pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
ip_protox[pr->pr_protocol] = pr - inetsw;
@@ -387,7 +411,8 @@ iphack:
#ifdef DUMMYNET
if ((i & IP_FW_PORT_DYNT_FLAG) != 0) {
/* Send packet to the appropriate pipe */
- dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule);
+ dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule,
+ 0);
return;
}
#endif
@@ -523,6 +548,19 @@ pass:
if (ip->ip_dst.s_addr == INADDR_ANY)
goto ours;
+#if defined(NFAITH) && 0 < NFAITH
+ /*
+ * FAITH(Firewall Aided Internet Translator)
+ */
+ if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
+ if (ip_keepfaith) {
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_ICMP)
+ goto ours;
+ }
+ m_freem(m);
+ return;
+ }
+#endif
/*
* Not for us; forward if possible and desirable.
*/
@@ -546,6 +584,11 @@ ours:
* but it's not worth the time; just let them time out.)
*/
if (ip->ip_off & (IP_MF | IP_OFFMASK | IP_RF)) {
+
+#if 0 /*
+ * Reassembly should be able to treat a mbuf cluster, for later
+ * operation of contiguous protocol headers on the cluster. (KAME)
+ */
if (m->m_flags & M_EXT) { /* XXX */
if ((m = m_pullup(m, hlen)) == 0) {
ipstat.ips_toosmall++;
@@ -556,6 +599,7 @@ ours:
}
ip = mtod(m, struct ip *);
}
+#endif
sum = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
/*
* Look for queue of fragments
@@ -616,12 +660,12 @@ found:
ipstat.ips_fragments++;
m->m_pkthdr.header = ip;
#ifdef IPDIVERT
- ip = ip_reass(m,
+ m = ip_reass(m,
fp, &ipq[sum], &divert_info, &divert_cookie);
#else
- ip = ip_reass(m, fp, &ipq[sum]);
+ m = ip_reass(m, fp, &ipq[sum]);
#endif
- if (ip == 0) {
+ if (m == 0) {
#ifdef IPFIREWALL_FORWARD
ip_fw_fwd_addr = NULL;
#endif
@@ -630,7 +674,7 @@ found:
/* Get the length of the reassembled packets header */
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
ipstat.ips_reassembled++;
- m = dtom(ip);
+ ip = mtod(m, struct ip *);
#ifdef IPDIVERT
/* Restore original checksum before diverting packet */
if (divert_info != 0) {
@@ -689,11 +733,15 @@ found:
* Switch out to protocol's input routine.
*/
ipstat.ips_delivered++;
- (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
+ {
+ int off = hlen, nh = ip->ip_p;
+
+ (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, off, nh);
#ifdef IPFIREWALL_FORWARD
ip_fw_fwd_addr = NULL; /* tcp needed it */
#endif
return;
+ }
bad:
#ifdef IPFIREWALL_FORWARD
ip_fw_fwd_addr = NULL;
@@ -731,7 +779,7 @@ NETISR_SET(NETISR_IP, ipintr);
* tells us if we need to divert or tee the packet we're building.
*/
-static struct ip *
+static struct mbuf *
#ifdef IPDIVERT
ip_reass(m, fp, where, divinfo, divcookie)
#else
@@ -801,7 +849,7 @@ ip_reass(m, fp, where)
if (i > 0) {
if (i >= ip->ip_len)
goto dropfrag;
- m_adj(dtom(ip), i);
+ m_adj(m, i);
ip->ip_off += i;
ip->ip_len -= i;
}
@@ -908,11 +956,11 @@ inserted:
/* some debugging cruft by sklower, below, will go away soon */
if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
register int plen = 0;
- for (t = m; m; m = m->m_next)
- plen += m->m_len;
- t->m_pkthdr.len = plen;
+ for (t = m; t; t = t->m_next)
+ plen += t->m_len;
+ m->m_pkthdr.len = plen;
}
- return (ip);
+ return (m);
dropfrag:
#ifdef IPDIVERT
@@ -1399,6 +1447,9 @@ ip_forward(m, srcrt)
struct mbuf *mcopy;
n_long dest;
struct ifnet *destifp;
+#ifdef IPSEC
+ struct ifnet dummyifp;
+#endif
dest = 0;
#ifdef DIAGNOSTIC
@@ -1523,8 +1574,61 @@ ip_forward(m, srcrt)
case EMSGSIZE:
type = ICMP_UNREACH;
code = ICMP_UNREACH_NEEDFRAG;
+#ifndef IPSEC
if (ipforward_rt.ro_rt)
destifp = ipforward_rt.ro_rt->rt_ifp;
+#else
+ /*
+ * If the packet is routed over IPsec tunnel, tell the
+ * originator the tunnel MTU.
+ * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
+ * XXX quickhack!!!
+ */
+ if (ipforward_rt.ro_rt) {
+ struct secpolicy *sp = NULL;
+ int ipsecerror;
+ int ipsechdr;
+ struct route *ro;
+
+ sp = ipsec4_getpolicybyaddr(mcopy,
+ IPSEC_DIR_OUTBOUND,
+ IP_FORWARDING,
+ &ipsecerror);
+
+ if (sp == NULL)
+ destifp = ipforward_rt.ro_rt->rt_ifp;
+ else {
+ /* count IPsec header size */
+ ipsechdr = ipsec4_hdrsiz(mcopy,
+ IPSEC_DIR_OUTBOUND,
+ NULL);
+
+ /*
+ * find the correct route for outer IPv4
+ * header, compute tunnel MTU.
+ *
+ * XXX BUG ALERT
+ * The "dummyifp" code relies upon the fact
+ * that icmp_error() touches only ifp->if_mtu.
+ */
+ /*XXX*/
+ destifp = NULL;
+ if (sp->req != NULL
+ && sp->req->sav != NULL
+ && sp->req->sav->sah != NULL) {
+ ro = &sp->req->sav->sah->sa_route;
+ if (ro->ro_rt && ro->ro_rt->rt_ifp) {
+ dummyifp.if_mtu =
+ ro->ro_rt->rt_ifp->if_mtu;
+ dummyifp.if_mtu -= ipsechdr;
+ destifp = &dummyifp;
+ }
+ }
+
+ key_freesp(sp);
+ }
+ }
+#endif /*IPSEC*/
ipstat.ips_cantfrag++;
break;
OpenPOWER on IntegriCloud