summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2006-02-01 13:55:03 +0000
committerandre <andre@FreeBSD.org>2006-02-01 13:55:03 +0000
commit2013a6774517ce67b21d1f06a6d71bc34f75ca7e (patch)
tree592bca82eb249bd3a903c245b8bac5bc8245781d /sys/netinet/ip_output.c
parent2001ac98be09865fc9ee4b5ca1e0b7b79beb14f5 (diff)
downloadFreeBSD-src-2013a6774517ce67b21d1f06a6d71bc34f75ca7e.zip
FreeBSD-src-2013a6774517ce67b21d1f06a6d71bc34f75ca7e.tar.gz
Move the IPSEC related code blocks to their own file to unclutter
and signifincantly improve the readability of ip_input() and ip_output() again. The resulting IPSEC hooks in ip_input() and ip_output() may be used later on for making IPSEC loadable. This move is mostly mechanical and should preserve current IPSEC behaviour as-is. Nothing shall prevent improvements in the way IPSEC interacts with the IPv4 stack. Discussed with: bz, gnn, rwatson; (earlier version)
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c297
1 files changed, 17 insertions, 280 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index ee8ad5f..a3fa63b 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -59,25 +59,19 @@
#include <netinet/ip_var.h>
#include <netinet/ip_options.h>
-#include <machine/in_cksum.h>
-
-static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
-
+#if defined(IPSEC) || defined(FAST_IPSEC)
+#include <netinet/ip_ipsec.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 /*IPSEC*/
-
#ifdef FAST_IPSEC
#include <netipsec/ipsec.h>
-#include <netipsec/xform.h>
-#include <netipsec/key.h>
-#endif /*FAST_IPSEC*/
+#endif
+#endif /*IPSEC*/
+
+#include <machine/in_cksum.h>
+
+static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
x, (ntohl(a.s_addr)>>24)&0xFF,\
@@ -127,16 +121,6 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag = NULL;
#endif
-#ifdef IPSEC
- struct secpolicy *sp = NULL;
-#endif
-#ifdef FAST_IPSEC
- struct secpolicy *sp = NULL;
- struct tdb_ident *tdbi;
- struct m_tag *mtag;
- int s;
-#endif /* FAST_IPSEC */
-
M_ASSERTPKTHDR(m);
if (ro == NULL) {
@@ -405,254 +389,20 @@ again:
}
sendit:
-#ifdef IPSEC
- /* get SP for this packet */
- if (inp == NULL)
- sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
- flags, &error);
- else
- sp = ipsec4_getpolicybypcb(m, IPSEC_DIR_OUTBOUND, inp, &error);
-
- if (sp == NULL) {
- ipsecstat.out_inval++;
- goto bad;
- }
-
- error = 0;
-
- /* check policy */
- switch (sp->policy) {
- case IPSEC_POLICY_DISCARD:
- /*
- * This packet is just discarded.
- */
- ipsecstat.out_polvio++;
+#if defined(IPSEC) || defined(FAST_IPSEC)
+ switch(ip_ipsec_output(&m, inp, &flags, &error, &ro, &iproute, &dst, &ia, &ifp)) {
+ case 1:
goto bad;
-
- case IPSEC_POLICY_BYPASS:
- case IPSEC_POLICY_NONE:
- case IPSEC_POLICY_TCP:
- /* no need to do IPsec. */
- goto skip_ipsec;
-
- case IPSEC_POLICY_IPSEC:
- if (sp->req == NULL) {
- /* acquire a policy */
- error = key_spdacquire(sp);
- goto bad;
- }
- break;
-
- case IPSEC_POLICY_ENTRUST:
+ case -1:
+ goto done;
+ case 0:
default:
- printf("ip_output: Invalid policy found. %d\n", sp->policy);
+ break; /* Continue with packet processing. */
}
- {
- struct ipsec_output_state state;
- bzero(&state, sizeof(state));
- state.m = m;
- if (flags & IP_ROUTETOIF) {
- state.ro = &iproute;
- bzero(&iproute, sizeof(iproute));
- } else
- state.ro = ro;
- state.dst = (struct sockaddr *)dst;
-
- ip->ip_sum = 0;
-
- /*
- * XXX
- * delayed checksums are not currently compatible with IPsec
- */
- 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);
-
- error = ipsec4_output(&state, sp, flags);
-
- m = state.m;
- if (flags & IP_ROUTETOIF) {
- /*
- * if we have tunnel mode SA, we may need to ignore
- * IP_ROUTETOIF.
- */
- if (state.ro != &iproute || state.ro->ro_rt != NULL) {
- flags &= ~IP_ROUTETOIF;
- ro = state.ro;
- }
- } else
- ro = state.ro;
- dst = (struct sockaddr_in *)state.dst;
- if (error) {
- /* mbuf is already reclaimed in ipsec4_output. */
- m = NULL;
- switch (error) {
- case EHOSTUNREACH:
- case ENETUNREACH:
- case EMSGSIZE:
- case ENOBUFS:
- case ENOMEM:
- break;
- default:
- printf("ip4_output (ipsec): error code %d\n", error);
- /*fall through*/
- case ENOENT:
- /* don't show these error codes to the user */
- error = 0;
- break;
- }
- goto bad;
- }
-
- /* be sure to update variables that are affected by ipsec4_output() */
+ /* Update variables that are affected by ipsec4_output(). */
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
- if (ro->ro_rt == NULL) {
- if ((flags & IP_ROUTETOIF) == 0) {
- printf("ip_output: "
- "can't update route after IPsec processing\n");
- error = EHOSTUNREACH; /*XXX*/
- goto bad;
- }
- } else {
- if (state.encap) {
- ia = ifatoia(ro->ro_rt->rt_ifa);
- ifp = ro->ro_rt->rt_ifp;
- }
- }
- }
-
- /* make it flipped, again. */
- ip->ip_len = ntohs(ip->ip_len);
- 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->req->sav->sah->saidx.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);
- /*
- * Preserve KAME behaviour: ENOENT can be returned
- * when an SA acquire is in progress. Don't propagate
- * this to user-level; it confuses applications.
- *
- * XXX this will go away when the SADB is redone.
- */
- if (error == ENOENT)
- error = 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 */
+#endif /* IPSEC */
/* Jump over all PFIL processing if hooks are not active. */
if (inet_pfil_hook.ph_busy_count == -1)
@@ -760,12 +510,10 @@ passout:
ia->ia_ifa.if_opackets++;
ia->ia_ifa.if_obytes += m->m_pkthdr.len;
}
-
#ifdef IPSEC
/* clean ipsec history once it goes out of the node */
ipsec_delaux(m);
#endif
-
#ifdef MBUF_STRESS_TEST
if (mbuf_frag_size && m->m_pkthdr.len > mbuf_frag_size)
m = m_fragment(m, M_DONTWAIT, mbuf_frag_size);
@@ -838,17 +586,6 @@ done:
if (ro == &iproute && ro->ro_rt) {
RTFREE(ro->ro_rt);
}
-#ifdef IPSEC
- if (sp != NULL) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ip_output call free SP:%p\n", sp));
- key_freesp(sp);
- }
-#endif
-#ifdef FAST_IPSEC
- if (sp != NULL)
- KEY_FREESP(&sp);
-#endif
return (error);
bad:
m_freem(m);
OpenPOWER on IntegriCloud