svn commit: r242177 - in user/andre/tcp_workqueue/sys: conf netipsec
Andre Oppermann
andre at FreeBSD.org
Sat Oct 27 12:03:01 UTC 2012
Author: andre
Date: Sat Oct 27 12:03:00 2012
New Revision: 242177
URL: http://svn.freebsd.org/changeset/base/242177
Log:
Convert IPsec packet path processing into a pfil hook that can
be inserted at runtime and loaded as kernel module.
In this first step the functionality of ip_ipsec.c and the IP
input and output path is moved into pfil hooks.
This is a first rudimentary implementation approach and not yet
functional.
Added:
user/andre/tcp_workqueue/sys/netipsec/ipsec_pfil.c
Modified:
user/andre/tcp_workqueue/sys/conf/files
Modified: user/andre/tcp_workqueue/sys/conf/files
==============================================================================
--- user/andre/tcp_workqueue/sys/conf/files Sat Oct 27 10:33:51 2012 (r242176)
+++ user/andre/tcp_workqueue/sys/conf/files Sat Oct 27 12:03:00 2012 (r242177)
@@ -3135,6 +3135,7 @@ netipsec/ipsec.c optional ipsec inet |
netipsec/ipsec_input.c optional ipsec inet | ipsec inet6
netipsec/ipsec_mbuf.c optional ipsec inet | ipsec inet6
netipsec/ipsec_output.c optional ipsec inet | ipsec inet6
+netipsec/ipsec_pfil.c optional ipsec inet | ipsec inet6
netipsec/key.c optional ipsec inet | ipsec inet6
netipsec/key_debug.c optional ipsec inet | ipsec inet6
netipsec/keysock.c optional ipsec inet | ipsec inet6
Added: user/andre/tcp_workqueue/sys/netipsec/ipsec_pfil.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/andre/tcp_workqueue/sys/netipsec/ipsec_pfil.c Sat Oct 27 12:03:00 2012 (r242177)
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2012 Andre Oppermann, Internet Business Solutions AG
+ * All rights reserved.
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ipsec.h"
+#include "opt_sctp.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/pfil.h>
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_options.h>
+#include <netinet/ip_ipsec.h>
+
+#ifdef SCTP
+#include <netinet/sctp_crc32.h>
+#endif
+#include <machine/in_cksum.h>
+
+#include <netipsec/ipsec.h>
+#include <netipsec/xform.h>
+#include <netipsec/key.h>
+
+extern struct protosw inetsw[];
+
+/*
+ * Implement IPSec as pfil hook for host mode.
+ */
+
+static int
+ipsec_pfil_run(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ struct ip *ip = mtod(*m, struct ip *);
+ struct m_tag *mtag;
+ struct tdb_ident *tdbi;
+ struct secpolicy *sp;
+ int error = 0;
+
+ switch (dir) {
+ case PFIL_IN:
+ /*
+ * The input path doesn't do a transform.
+ */
+ if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0)
+ return (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);
+ 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);
+
+ /* Check security policy against packet attributes. */
+ if (sp != NULL) {
+ error = ipsec_in_reject(sp, *m);
+ KEY_FREESP(&sp);
+ } else
+ error = EINVAL;
+ break;
+
+ case PFIL_OUT:
+ /*
+ * 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);
+ if (mtag != NULL) {
+ tdbi = (struct tdb_ident *)(mtag + 1);
+ sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
+ if (sp == NULL) {
+ error = -EINVAL; /* force silent drop */
+ goto drop;
+ }
+ m_tag_delete(*m, mtag);
+ } else
+ sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, 0,
+ &error, inp);
+
+ if (sp == NULL) {
+ 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 drop;
+ }
+ return (0);
+ }
+
+ /* 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);
+ return (0);
+ }
+ }
+
+ /*
+ * 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;
+ }
+#ifdef SCTP
+ if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) {
+ struct ip *ip = mtod(*m, struct ip *);
+
+ sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2));
+ (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+ }
+#endif
+ /* NB: callee frees mbuf */
+ error = ipsec4_process_packet(*m, sp->req, 0, 0);
+ if (error == EJUSTRETURN) {
+ /*
+ * We had a SP with a level of 'use' and no SA. We
+ * will just continue to process the packet without
+ * IPsec processing and return without error.
+ */
+ error = 0;
+ KEY_FREESP(&sp);
+ return (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;
+ goto drop;
+
+ break;
+
+ default:
+ break;
+ }
+
+drop:
+ if (error < 0)
+ error = EACCES;
+ if (sp != NULL)
+ KEY_FREESP(&sp);
+
+ m_freem(*m);
+ return (error);
+}
+
+static int
+ipsec_pfil_hook(int af)
+{
+ struct pfil_head *pfh;
+
+ pfh = pfil_head_get(PFIL_TYPE_AF, af);
+ if (pfh == NULL)
+ return ENOENT;
+
+ pfil_add_hook_order(ipsec_pfil_run, NULL, "ipsec",
+ (PFIL_IN | PFIL_OUT), PFIL_ORDER_FIRST, pfh);
+
+ return (0);
+}
+
+static int
+ipsec_pfil_unhook(int af)
+{
+ struct pfil_head *pfh;
+
+ pfh = pfil_head_get(PFIL_TYPE_AF, af);
+ if (pfh == NULL)
+ return ENOENT;
+
+ pfil_remove_hook(ipsec_pfil_run, NULL, (PFIL_IN | PFIL_OUT), pfh);
+
+ return (0);
+}
+
+static void
+ipsec_pfil_init(void)
+{
+
+ (void)ipsec_pfil_hook(AF_INET);
+ (void)ipsec_pfil_unhook(AF_INET);
+}
+
+SYSINIT(ipsec_pfil_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, ipsec_pfil_init, NULL);
+
More information about the svn-src-user
mailing list