diff options
author | sam <sam@FreeBSD.org> | 2002-10-16 02:25:05 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2002-10-16 02:25:05 +0000 |
commit | 0ef6c52bbcc67b0dce67c7ad7a6fc685828a6400 (patch) | |
tree | ae7276b550c8f6a3436b1985ff4cb31e8a826d66 /sys | |
parent | b12d57e66aba52a8bea632c34b458fa9d734aef7 (diff) | |
download | FreeBSD-src-0ef6c52bbcc67b0dce67c7ad7a6fc685828a6400.zip FreeBSD-src-0ef6c52bbcc67b0dce67c7ad7a6fc685828a6400.tar.gz |
Tie new "Fast IPsec" code into the build. This involves the usual
configuration stuff as well as conditional code in the IPv4 and IPv6
areas. Everything is conditional on FAST_IPSEC which is mutually
exclusive with IPSEC (KAME IPsec implmentation).
As noted previously, don't use FAST_IPSEC with INET6 at the moment.
Reviewed by: KAME, rwatson
Approved by: silence
Supported by: Vernier Networks
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/NOTES | 2 | ||||
-rw-r--r-- | sys/conf/files | 11 | ||||
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 10 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 2 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 17 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 133 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 148 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 20 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 19 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 5 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 19 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 8 | ||||
-rw-r--r-- | sys/netinet/tcp_syncache.c | 10 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 8 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 125 | ||||
-rw-r--r-- | sys/netinet6/icmp6.c | 6 | ||||
-rw-r--r-- | sys/netinet6/in6_pcb.c | 7 | ||||
-rw-r--r-- | sys/netinet6/in6_proto.c | 9 | ||||
-rw-r--r-- | sys/netinet6/ip6_forward.c | 9 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 6 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 67 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 24 | ||||
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 29 |
25 files changed, 605 insertions, 96 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 6c4e7c2..c20bf71 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -343,6 +343,8 @@ options IPSEC #IP security options IPSEC_ESP #IP security (crypto; define w/ IPSEC) options IPSEC_DEBUG #debug for IP security +#options FAST_IPSEC #new IPsec (cannot define w/ IPSEC) + options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) diff --git a/sys/conf/files b/sys/conf/files index e520520..e2784d61 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1303,6 +1303,17 @@ netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 +netipsec/ipsec.c optional fast_ipsec +netipsec/ipsec_input.c optional fast_ipsec +netipsec/ipsec_mbuf.c optional fast_ipsec +netipsec/ipsec_output.c optional fast_ipsec +netipsec/key.c optional fast_ipsec +netipsec/key_debug.c optional fast_ipsec +netipsec/keysock.c optional fast_ipsec +netipsec/xform_ah.c optional fast_ipsec +netipsec/xform_esp.c optional fast_ipsec +netipsec/xform_ipcomp.c optional fast_ipsec +netipsec/xform_ipip.c optional fast_ipsec netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_input.c optional ipx diff --git a/sys/conf/options b/sys/conf/options index 8f9c79d..8480b1c 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -312,6 +312,7 @@ INET6 opt_inet6.h IPSEC opt_ipsec.h IPSEC_ESP opt_ipsec.h IPSEC_DEBUG opt_ipsec.h +FAST_IPSEC opt_ipsec.h IPDIVERT DUMMYNET opt_ipdn.h IPFILTER opt_ipfilter.h diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 9ad3607..8411fe8 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -72,6 +72,16 @@ #include <netkey/key.h> #endif /* IPSEC */ +#ifdef FAST_IPSEC +#if defined(IPSEC) || defined(IPSEC_ESP) +#error "Bad idea: don't compile with both IPSEC and FAST_IPSEC!" +#endif + +#include <netipsec/ipsec.h> +#include <netipsec/key.h> +#define IPSEC +#endif /* FAST_IPSEC */ + struct in_addr zeroin_addr; /* diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 4fe626b..f08151b 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -42,10 +42,10 @@ #include <sys/_mutex.h> #include <net/route.h> -#include <netinet6/ipsec.h> /* for IPSEC */ #define in6pcb inpcb /* for KAME src sync over BSD*'s */ #define in6p_sp inp_sp /* for KAME src sync over BSD*'s */ +struct inpcbpolicy; /* * Common structure pcb for internet protocol implementation. diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 876d8b6..5ecbe65 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -76,6 +76,14 @@ #include <netinet6/ipcomp.h> #endif /* IPSEC */ +#ifdef FAST_IPESC +#include <netipsec/ipsec.h> +#define ah4_input ipsec4_common_input +#define esp4_input ipsec4_common_input +#define ipcomp4_input ipsec4_common_input +#define IPSEC +#endif /* FAST_IPSEC */ + #ifdef IPXIP #include <netipx/ipx_ip.h> #endif @@ -232,9 +240,18 @@ SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP"); SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW, 0, "UDP"); SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP"); SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP"); +#ifdef FAST_IPSEC +/* XXX no protocol # to use, pick something "reserved" */ +SYSCTL_NODE(_net_inet, 253, ipsec, CTLFLAG_RW, 0, "IPSEC"); +SYSCTL_NODE(_net_inet, IPPROTO_AH, ah, CTLFLAG_RW, 0, "AH"); +SYSCTL_NODE(_net_inet, IPPROTO_ESP, esp, CTLFLAG_RW, 0, "ESP"); +SYSCTL_NODE(_net_inet, IPPROTO_IPCOMP, ipcomp, CTLFLAG_RW, 0, "IPCOMP"); +SYSCTL_NODE(_net_inet, IPPROTO_IPIP, ipip, CTLFLAG_RW, 0, "IPIP"); +#else #ifdef IPSEC SYSCTL_NODE(_net_inet, IPPROTO_AH, ipsec, CTLFLAG_RW, 0, "IPSEC"); #endif /* IPSEC */ +#endif /* !FAST_IPSEC */ SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw, CTLFLAG_RW, 0, "RAW"); #ifdef IPDIVERT SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, divert, CTLFLAG_RW, 0, "DIVERT"); diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 5dd82ef..c893340 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -65,6 +65,12 @@ #include <netkey/key.h> #endif +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/key.h> +#define IPSEC +#endif + #include <machine/in_cksum.h> /* diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 1feee4a..f22d550 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -88,6 +88,11 @@ #include <netkey/key.h> #endif +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/key.h> +#endif + int rsvp_on = 0; int ipforwarding = 0; @@ -290,6 +295,12 @@ ip_input(struct mbuf *m) struct mbuf *m0; int rv; #endif /* PFIL_HOOKS */ +#ifdef FAST_IPSEC + struct m_tag *mtag; + struct tdb_ident *tdbi; + struct secpolicy *sp; + int s, error; +#endif /* FAST_IPSEC */ args.eh = NULL; args.oif = NULL; @@ -656,6 +667,34 @@ pass: goto bad; } #endif /* IPSEC */ +#ifdef FAST_IPSEC + mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); + s = splnet(); + if (mtag != NULL) { + tdbi = (struct tdb_ident *)(mtag + 1); + sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); + } else { + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, + IP_FORWARDING, &error); + } + if (sp == NULL) { /* NB: can happen if error */ + splx(s); + /*XXX error stat???*/ + DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/ + goto bad; + } + + /* + * Check security policy against packet attributes. + */ + error = ipsec_in_reject(sp, m); + KEY_FREESP(&sp); + splx(s); + if (error) { + ipstat.ips_cantforward++; + goto bad; + } +#endif /* FAST_IPSEC */ ip_forward(m, 0, args.next_hop); } return; @@ -825,6 +864,45 @@ found: goto bad; } #endif +#if FAST_IPSEC + /* + * enforce IPsec policy checking if we are seeing last header. + * note that we do not visit this with protocols with pcb layer + * code - like udp/tcp/raw ip. + */ + if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) { + /* + * Check if the packet has already had IPsec processing + * done. If so, then just pass it along. This tag gets + * set during AH, ESP, etc. input handling, before the + * packet is returned to the ip input queue for delivery. + */ + mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); + s = splnet(); + if (mtag != NULL) { + tdbi = (struct tdb_ident *)(mtag + 1); + sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); + } else { + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, + IP_FORWARDING, &error); + } + if (sp != NULL) { + /* + * Check security policy against packet attributes. + */ + error = ipsec_in_reject(sp, m); + KEY_FREESP(&sp); + } else { + /* XXX error stat??? */ + error = EINVAL; +DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ + goto bad; + } + splx(s); + if (error) + goto bad; + } +#endif /* FAST_IPSEC */ /* * Switch out to protocol's input routine. @@ -1625,7 +1703,7 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop) n_long dest; struct in_addr pkt_dst; struct ifnet *destifp; -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) struct ifnet dummyifp; #endif @@ -1839,7 +1917,58 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop) key_freesp(sp); } } -#else +#elif FAST_IPSEC + /* + * 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 = ipsec_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); + } + } +#else /* !IPSEC && !FAST_IPSEC */ if (ipforward_rt.ro_rt) destifp = ipforward_rt.ro_rt->rt_ifp; #endif /*IPSEC*/ diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index e78ef26..0a9d66a 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -79,6 +79,12 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); #endif #endif /*IPSEC*/ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/xform.h> +#include <netipsec/key.h> +#endif /*FAST_IPSEC*/ + #include <netinet/ip_fw.h> #include <netinet/ip_dummynet.h> @@ -134,6 +140,13 @@ ip_output(m0, opt, ro, flags, imo, inp) struct secpolicy *sp = NULL; struct socket *so = inp ? inp->inp_socket : NULL; #endif +#ifdef FAST_IPSEC + struct route iproute; + struct m_tag *mtag; + struct secpolicy *sp = NULL; + struct tdb_ident *tdbi; + int s; +#endif /* FAST_IPSEC */ struct ip_fw_args args; int src_was_INADDR_ANY = 0; /* as the name says... */ #ifdef PFIL_HOOKS @@ -182,6 +195,10 @@ ip_output(m0, opt, ro, flags, imo, inp) m = m0; KASSERT(!m || (m->m_flags & M_PKTHDR) != 0, ("ip_output: no HDR")); +#ifndef FAST_IPSEC + KASSERT(ro != NULL, ("ip_output: no route, proto %d", + mtod(m, struct ip *)->ip_p)); +#endif if (args.rule != NULL) { /* dummynet already saw us */ ip = mtod(m, struct ip *); @@ -216,6 +233,12 @@ ip_output(m0, opt, ro, flags, imo, inp) hlen = IP_VHL_HL(ip->ip_vhl) << 2; } +#ifdef FAST_IPSEC + if (ro == NULL) { + ro = &iproute; + bzero(ro, sizeof (*ro)); + } +#endif /* FAST_IPSEC */ dst = (struct sockaddr_in *)&ro->ro_dst; /* * If there is a cached route, @@ -569,6 +592,119 @@ sendit: ip->ip_off = ntohs(ip->ip_off); skip_ipsec: #endif /*IPSEC*/ +#ifdef FAST_IPSEC + /* + * Check the security policy (SP) for the packet and, if + * required, do IPsec-related processing. There are two + * cases here; the first time a packet is sent through + * it will be untagged and handled by ipsec4_checkpolicy. + * If the packet is resubmitted to ip_output (e.g. after + * AH, ESP, etc. processing), there will be a tag to bypass + * the lookup and related policy checking. + */ + mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL); + s = splnet(); + if (mtag != NULL) { + tdbi = (struct tdb_ident *)(mtag + 1); + sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND); + if (sp == NULL) + error = -EINVAL; /* force silent drop */ + m_tag_delete(m, mtag); + } else { + sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, + &error, inp); + } + /* + * There are four return cases: + * sp != NULL apply IPsec policy + * sp == NULL, error == 0 no IPsec handling needed + * sp == NULL, error == -EINVAL discard packet w/o error + * sp == NULL, error != 0 discard packet, report error + */ + if (sp != NULL) { + /* Loop detection, check if ipsec processing already done */ + KASSERT(sp->req != NULL, ("ip_output: no ipsec request")); + for (mtag = m_tag_first(m); mtag != NULL; + mtag = m_tag_next(m, mtag)) { + if (mtag->m_tag_cookie != MTAG_ABI_COMPAT) + continue; + if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE && + mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED) + continue; + /* + * Check if policy has an SA associated with it. + * This can happen when an SP has yet to acquire + * an SA; e.g. on first reference. If it occurs, + * then we let ipsec4_process_packet do its thing. + */ + if (sp->req->sav == NULL) + break; + tdbi = (struct tdb_ident *)(mtag + 1); + if (tdbi->spi == sp->req->sav->spi && + tdbi->proto == sp->req->sav->sah->saidx.proto && + bcmp(&tdbi->dst, &sp->spidx.dst, + sizeof (union sockaddr_union)) == 0) { + /* + * No IPsec processing is needed, free + * reference to SP. + * + * NB: null pointer to avoid free at + * done: below. + */ + KEY_FREESP(&sp), sp = NULL; + splx(s); + goto spd_done; + } + } + + /* + * Do delayed checksums now because we send before + * this is done in the normal processing path. + */ + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } + + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + + /* NB: callee frees mbuf */ + error = ipsec4_process_packet(m, sp->req, flags, 0); + splx(s); + goto done; + } else { + splx(s); + + if (error != 0) { + /* + * Hack: -EINVAL is used to signal that a packet + * should be silently discarded. This is typically + * because we asked key management for an SA and + * it was delayed (e.g. kicked up to IKE). + */ + if (error == -EINVAL) + error = 0; + goto bad; + } else { + /* No IPsec processing for this packet. */ + } +#ifdef notyet + /* + * If deferred crypto processing is needed, check that + * the interface supports it. + */ + mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL); + if (mtag != NULL && (ifp->if_capenable & IFCAP_IPSEC) == 0) { + /* notify IPsec to do its own crypto */ + ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1)); + error = EHOSTUNREACH; + goto bad; + } +#endif + } +spd_done: +#endif /* FAST_IPSEC */ /* * IpHack's section. @@ -1078,6 +1214,14 @@ done: key_freesp(sp); } #endif /* IPSEC */ +#ifdef FAST_IPSEC + if (ro == &iproute && ro->ro_rt) { + RTFREE(ro->ro_rt); + ro->ro_rt = NULL; + } + if (sp != NULL) + KEY_FREESP(&sp); +#endif /* FAST_IPSEC */ return (error); bad: m_freem(m); @@ -1340,7 +1484,7 @@ ip_ctloutput(so, sopt) } break; -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) case IP_IPSEC_POLICY: { caddr_t req; @@ -1444,7 +1588,7 @@ ip_ctloutput(so, sopt) error = ip_getmoptions(sopt, inp->inp_moptions); break; -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) case IP_IPSEC_POLICY: { struct mbuf *m = NULL; diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 144554a..de539fa 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -71,6 +71,10 @@ #include <netinet/ip_fw.h> #include <netinet/ip_dummynet.h> +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#endif /*FAST_IPSEC*/ + #ifdef IPSEC #include <netinet6/ipsec.h> #endif /*IPSEC*/ @@ -157,6 +161,13 @@ rip_input(m, off) /* do not inject data to pcb */ } #endif /*IPSEC*/ +#ifdef FAST_IPSEC + /* check AH/ESP integrity. */ + if (ipsec4_in_reject(n, last)) { + policyfail = 1; + /* do not inject data to pcb */ + } +#endif /*FAST_IPSEC*/ #ifdef MAC if (policyfail == 0 && mac_check_socket_deliver(last->inp_socket, @@ -195,6 +206,15 @@ rip_input(m, off) return; } #endif /*IPSEC*/ +#ifdef FAST_IPSEC + /* check AH/ESP integrity. */ + if (ipsec4_in_reject(m, last)) { + m_freem(m); + ipstat.ips_delivered--; + /* do not inject data to pcb */ + return; + } +#endif /*FAST_IPSEC*/ #ifdef MAC if (mac_check_socket_deliver(last->inp_socket, m) != 0) { m_freem(m); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 59cf6ae..7849ea0 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -84,6 +84,13 @@ #include <netinet/tcp_debug.h> #endif /* TCPDEBUG */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#ifdef INET6 +#include <netipsec/ipsec6.h> +#endif +#endif /*FAST_IPSEC*/ + #ifdef IPSEC #include <netinet6/ipsec.h> #include <netinet6/ipsec6.h> @@ -566,6 +573,18 @@ findpcb: } } #endif +#ifdef FAST_IPSEC +#ifdef INET6 + if (isipv6) { + if (inp != NULL && ipsec6_in_reject(m, inp)) { + goto drop; + } + } else +#endif /* INET6 */ + if (inp != NULL && ipsec4_in_reject(m, inp)) { + goto drop; + } +#endif /*FAST_IPSEC*/ /* * If the state is CLOSED (i.e., TCB does not exist) then diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 4128be5..1200282 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -79,6 +79,11 @@ #include <netinet6/ipsec.h> #endif /*IPSEC*/ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#define IPSEC +#endif /*FAST_IPSEC*/ + #include <machine/in_cksum.h> #ifdef notyet diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 59cf6ae..7849ea0 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -84,6 +84,13 @@ #include <netinet/tcp_debug.h> #endif /* TCPDEBUG */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#ifdef INET6 +#include <netipsec/ipsec6.h> +#endif +#endif /*FAST_IPSEC*/ + #ifdef IPSEC #include <netinet6/ipsec.h> #include <netinet6/ipsec6.h> @@ -566,6 +573,18 @@ findpcb: } } #endif +#ifdef FAST_IPSEC +#ifdef INET6 + if (isipv6) { + if (inp != NULL && ipsec6_in_reject(m, inp)) { + goto drop; + } + } else +#endif /* INET6 */ + if (inp != NULL && ipsec4_in_reject(m, inp)) { + goto drop; + } +#endif /*FAST_IPSEC*/ /* * If the state is CLOSED (i.e., TCB does not exist) then diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index d9b3ecf..02da281 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -99,6 +99,14 @@ #endif #endif /*IPSEC*/ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#ifdef INET6 +#include <netipsec/ipsec6.h> +#endif +#define IPSEC +#endif /*FAST_IPSEC*/ + #include <machine/in_cksum.h> #include <sys/md5.h> diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 49197bf..8426a63 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -81,9 +81,17 @@ #ifdef INET6 #include <netinet6/ipsec6.h> #endif -#include <netkey/key.h> #endif /*IPSEC*/ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#ifdef INET6 +#include <netipsec/ipsec6.h> +#endif +#include <netipsec/key.h> +#define IPSEC +#endif /*FAST_IPSEC*/ + #include <machine/in_cksum.h> #include <vm/uma.h> diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index d9b3ecf..02da281 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -99,6 +99,14 @@ #endif #endif /*IPSEC*/ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#ifdef INET6 +#include <netipsec/ipsec6.h> +#endif +#define IPSEC +#endif /*FAST_IPSEC*/ + #include <machine/in_cksum.h> #include <sys/md5.h> diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 1a07cea..cc816d8 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -78,6 +78,10 @@ #include <netinet/udp.h> #include <netinet/udp_var.h> +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#endif /*FAST_IPSEC*/ + #ifdef IPSEC #include <netinet6/ipsec.h> #endif /*IPSEC*/ @@ -167,10 +171,6 @@ udp_input(m, off) struct mbuf *opts = 0; int len; struct ip save_ip; - struct sockaddr *append_sa; -#ifdef MAC - int error; -#endif udpstat.udps_ipackets++; @@ -203,6 +203,16 @@ udp_input(m, off) goto badunlocked; /* + * Construct sockaddr format source address. + * Stuff source address and datagram in user buffer. + */ + udp_in.sin_port = uh->uh_sport; + udp_in.sin_addr = ip->ip_src; +#ifdef INET6 + udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0; +#endif + + /* * Make mbuf data length reflect UDP length. * If not enough data to reflect UDP length, drop. */ @@ -272,18 +282,10 @@ udp_input(m, off) */ /* - * Construct sockaddr format source address. - */ - udp_in.sin_port = uh->uh_sport; - udp_in.sin_addr = ip->ip_src; - /* * Locate pcb(s) for datagram. * (Algorithm copied from raw_intr().) */ last = NULL; -#ifdef INET6 - udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0; -#endif LIST_FOREACH(inp, &udb, inp_list) { INP_LOCK(inp); if (inp->inp_lport != uh->uh_dport) { @@ -308,29 +310,12 @@ udp_input(m, off) if (last != NULL) { struct mbuf *n; - int policyfail; - policyfail = 0; -#ifdef IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject_so(m, last->inp_socket)) { - ipsecstat.in_polvio++; - policyfail = 1; - /* do not inject data to pcb */ - } -#endif /*IPSEC*/ -#ifdef MAC - if (mac_check_socket_deliver(last->inp_socket, - m) != 0) - policyfail = 1; -#endif - if (!policyfail) { - n = m_copy(m, 0, M_COPYALL); - if (n != NULL) - udp_append(last, ip, n, + n = m_copy(m, 0, M_COPYALL); + if (n != NULL) + udp_append(last, ip, n, iphlen + sizeof(struct udphdr)); - } INP_UNLOCK(last); } last = inp; @@ -355,13 +340,6 @@ udp_input(m, off) udpstat.udps_noportbcast++; goto badheadlocked; } -#ifdef IPSEC - /* check AH/ESP integrity. */ - if (ipsec4_in_reject_so(m, last->inp_socket)) { - ipsecstat.in_polvio++; - goto badheadlocked; - } -#endif /*IPSEC*/ INP_UNLOCK(last); INP_INFO_RUNLOCK(&udbinfo); udp_append(last, ip, m, iphlen + sizeof(struct udphdr)); @@ -399,58 +377,12 @@ udp_input(m, off) } INP_LOCK(inp); INP_INFO_RUNLOCK(&udbinfo); -#ifdef IPSEC - if (ipsec4_in_reject_so(m, inp->inp_socket)) { - ipsecstat.in_polvio++; - goto bad; - } -#endif /*IPSEC*/ -#ifdef MAC - error = mac_check_socket_deliver(inp->inp_socket, m); - if (error) - goto bad; -#endif - - /* - * Construct sockaddr format source address. - * Stuff source address and datagram in user buffer. - */ - udp_in.sin_port = uh->uh_sport; - udp_in.sin_addr = ip->ip_src; - if (inp->inp_flags & INP_CONTROLOPTS - || inp->inp_socket->so_options & SO_TIMESTAMP) { -#ifdef INET6 - if (inp->inp_vflag & INP_IPV6) { - int savedflags; - - ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip); - savedflags = inp->inp_flags; - inp->inp_flags &= ~INP_UNMAPPABLEOPTS; - ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m); - inp->inp_flags = savedflags; - } else -#endif - ip_savecontrol(inp, &opts, ip, m); - } - m_adj(m, iphlen + sizeof(struct udphdr)); -#ifdef INET6 - if (inp->inp_vflag & INP_IPV6) { - in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin); - append_sa = (struct sockaddr *)&udp_in6; - } else -#endif - append_sa = (struct sockaddr *)&udp_in; - if (sbappendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts) == 0) { - udpstat.udps_fullsock++; - goto bad; - } - sorwakeup(inp->inp_socket); + udp_append(inp, ip, m, iphlen + sizeof(struct udphdr)); INP_UNLOCK(inp); return; badheadlocked: INP_INFO_RUNLOCK(&udbinfo); -bad: if (inp) INP_UNLOCK(inp); badunlocked: @@ -493,6 +425,27 @@ udp_append(last, ip, n, off) struct sockaddr *append_sa; struct mbuf *opts = 0; +#ifdef IPSEC + /* check AH/ESP integrity. */ + if (ipsec4_in_reject_so(n, last->inp_socket)) { + ipsecstat.in_polvio++; + m_freem(n); + return; + } +#endif /*IPSEC*/ +#ifdef FAST_IPSEC + /* check AH/ESP integrity. */ + if (ipsec4_in_reject(n, last)) { + m_freem(n); + return; + } +#endif /*FAST_IPSEC*/ +#ifdef MAC + if (mac_check_socket_deliver(last->inp_socket, n) != 0) { + m_freem(n); + return; + } +#endif if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & SO_TIMESTAMP) { #ifdef INET6 diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 6c1c1c5..f318d51 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -106,6 +106,12 @@ #include <netkey/key.h> #endif +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/key.h> +#define IPSEC +#endif + #include <net/net_osdep.h> #ifdef HAVE_NRL_INPCB diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 2d7baab..963cd9a 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -113,6 +113,13 @@ #include <netkey/key.h> #endif /* IPSEC */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#include <netipsec/key.h> +#define IPSEC +#endif /* FAST_IPSEC */ + struct in6_addr zeroin6_addr; int diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 98a312e..1e8aeac 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -126,6 +126,15 @@ #endif #endif /* IPSEC */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec6.h> +#define IPSEC +#define IPSEC_ESP +#define ah6_input ipsec6_common_input +#define esp6_input ipsec6_common_input +#define ipcomp6_input ipsec6_common_input +#endif /* FAST_IPSEC */ + #include <netinet6/ip6protosw.h> #include <net/net_osdep.h> diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 97fa8d6..1e6dde8 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -74,6 +74,13 @@ #include <netkey/key.h> #endif /* IPSEC */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#include <netipsec/key.h> +#define IPSEC +#endif /* FAST_IPSEC */ + #include <netinet6/ip6_fw.h> #include <net/net_osdep.h> @@ -124,7 +131,9 @@ ip6_forward(m, srcrt) * before forwarding packet actually. */ if (ipsec6_in_reject(m, NULL)) { +#if !defined(FAST_IPSEC) ipsec6stat.in_polvio++; +#endif m_freem(m); return; } diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 3f5d7d5..82c1036 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -117,6 +117,12 @@ #endif #endif +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#define IPSEC +#endif /* FAST_IPSEC */ + #include <netinet6/ip6_fw.h> #include <netinet6/ip6protosw.h> diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 63d676d..a45727e 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -105,6 +105,12 @@ #include <netkey/key.h> #endif /* IPSEC */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#include <netipsec/key.h> +#endif /* FAST_IPSEC */ + #include <netinet6/ip6_fw.h> #include <net/net_osdep.h> @@ -179,6 +185,12 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp, inp) ip6 = mtod(m, struct ip6_hdr *); #endif /* IPSEC */ +#ifdef FAST_IPSEC + int needipsectun = 0; + struct secpolicy *sp = NULL; + + ip6 = mtod(m, struct ip6_hdr *); +#endif /* FAST_IPSEC */ #define MAKE_EXTHDR(hp, mp) \ do { \ @@ -247,6 +259,49 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp, inp) printf("ip6_output: Invalid policy found. %d\n", sp->policy); } #endif /* IPSEC */ +#ifdef FAST_IPSEC + /* get a security policy for this packet */ + if (inp == NULL) + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); + else + sp = ipsec_getpolicybysock(m, IPSEC_DIR_OUTBOUND, inp, &error); + + if (sp == NULL) { + newipsecstat.ips_out_inval++; + goto freehdrs; + } + + error = 0; + + /* check policy */ + switch (sp->policy) { + case IPSEC_POLICY_DISCARD: + /* + * This packet is just discarded. + */ + newipsecstat.ips_out_polvio++; + goto freehdrs; + + case IPSEC_POLICY_BYPASS: + case IPSEC_POLICY_NONE: + /* no need to do IPsec. */ + needipsec = 0; + break; + + case IPSEC_POLICY_IPSEC: + if (sp->req == NULL) { + /* acquire a policy */ + error = key_spdacquire(sp); + goto freehdrs; + } + needipsec = 1; + break; + + case IPSEC_POLICY_ENTRUST: + default: + printf("ip6_output: Invalid policy found. %d\n", sp->policy); + } +#endif /* FAST_IPSEC */ /* * Calculate the total length of the extension header chain. @@ -354,7 +409,7 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp, inp) MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp, IPPROTO_ROUTING); -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) if (!needipsec) goto skip_ipsec2; @@ -485,7 +540,7 @@ skip_ipsec2:; dst->sin6_scope_id = ntohs(dst->sin6_addr.s6_addr16[1]); #endif } -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) if (needipsec && needipsectun) { struct ipsec_output_state state; @@ -1069,6 +1124,10 @@ done: if (sp != NULL) key_freesp(sp); #endif /* IPSEC */ +#ifdef FAST_IPSEC + if (sp != NULL) + KEY_FREESP(&sp); +#endif /* FAST_IPSEC */ return(error); @@ -1480,7 +1539,7 @@ do { \ } break; -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) case IPV6_IPSEC_POLICY: { caddr_t req = NULL; @@ -1635,7 +1694,7 @@ do { \ } break; -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) case IPV6_IPSEC_POLICY: { caddr_t req = NULL; diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 6d4cc22..540533b 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -105,6 +105,11 @@ #include <netinet6/ipsec6.h> #endif /*IPSEC*/ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#endif /* FAST_IPSEC */ + #include <machine/stdarg.h> #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) @@ -181,6 +186,15 @@ rip6_input(mp, offp, proto) /* do not inject data into pcb */ } else #endif /*IPSEC*/ +#ifdef FAST_IPSEC + /* + * Check AH/ESP integrity. + */ + if (n && ipsec6_in_reject(n, last)) { + m_freem(n); + /* do not inject data into pcb */ + } else +#endif /*FAST_IPSEC*/ if (n) { if (last->in6p_flags & IN6P_CONTROLOPTS || last->in6p_socket->so_options & SO_TIMESTAMP) @@ -212,6 +226,16 @@ rip6_input(mp, offp, proto) /* do not inject data into pcb */ } else #endif /*IPSEC*/ +#ifdef FAST_IPSEC + /* + * Check AH/ESP integrity. + */ + if (last && ipsec6_in_reject(m, last)) { + m_freem(m); + ip6stat.ip6s_delivered--; + /* do not inject data into pcb */ + } else +#endif /*FAST_IPSEC*/ if (last) { if (last->in6p_flags & IN6P_CONTROLOPTS || last->in6p_socket->so_options & SO_TIMESTAMP) diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index a7e46b9..b5a4033 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -109,6 +109,11 @@ #include <netinet6/ipsec6.h> #endif /* IPSEC */ +#ifdef FAST_IPSEC +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#endif /* FAST_IPSEC */ + /* * UDP protocol inplementation. * Per RFC 768, August, 1980. @@ -261,6 +266,14 @@ udp6_input(mp, offp, proto) /* do not inject data into pcb */ else #endif /* IPSEC */ +#ifdef FAST_IPSEC + /* + * Check AH/ESP integrity. + */ + if (ipsec6_in_reject(m, last)) + ; + else +#endif /* FAST_IPSEC */ if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { /* * KAME NOTE: do not @@ -320,6 +333,14 @@ udp6_input(mp, offp, proto) goto bad; } #endif /* IPSEC */ +#ifdef FAST_IPSEC + /* + * Check AH/ESP integrity. + */ + if (ipsec6_in_reject(m, last)) { + goto bad; + } +#endif /* FAST_IPSEC */ if (last->in6p_flags & IN6P_CONTROLOPTS || last->in6p_socket->so_options & SO_TIMESTAMP) ip6_savecontrol(last, &opts, ip6, m); @@ -368,6 +389,14 @@ udp6_input(mp, offp, proto) goto bad; } #endif /* IPSEC */ +#ifdef FAST_IPSEC + /* + * Check AH/ESP integrity. + */ + if (ipsec6_in_reject(m, in6p)) { + goto bad; + } +#endif /* FAST_IPSEC */ /* * Construct sockaddr format source address. |