Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Dec 2016 14:17:31 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r310410 - projects/ipsec/sys/netipsec
Message-ID:  <201612221417.uBMEHV2J073461@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Thu Dec 22 14:17:30 2016
New Revision: 310410
URL: https://svnweb.freebsd.org/changeset/base/310410

Log:
  Add IPSEC_INPUT() method implementation for IPv4 and IPv6.

Modified:
  projects/ipsec/sys/netipsec/ipsec_input.c

Modified: projects/ipsec/sys/netipsec/ipsec_input.c
==============================================================================
--- projects/ipsec/sys/netipsec/ipsec_input.c	Thu Dec 22 14:15:27 2016	(r310409)
+++ projects/ipsec/sys/netipsec/ipsec_input.c	Thu Dec 22 14:17:30 2016	(r310410)
@@ -1,4 +1,3 @@
-/*	$FreeBSD$	*/
 /*	$OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $	*/
 /*-
  * The authors of this code are John Ioannidis (ji@tla.org),
@@ -19,6 +18,7 @@
  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
  * Angelos D. Keromytis and Niels Provos.
  * Copyright (c) 2001, Angelos D. Keromytis.
+ * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
  *
  * Permission to use, copy, and modify this software with or without fee
  * is hereby granted, provided that this entire notice is included in
@@ -40,6 +40,9 @@
  * IPsec input processing.
  */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipsec.h"
@@ -225,18 +228,44 @@ ipsec_common_input(struct mbuf *m, int s
 }
 
 #ifdef INET
+extern struct protosw inetsw[];
+
+/*
+ * IPSEC_INPUT() method implementation for IPv4.
+ *  0 - Permitted by inbound security policy for further processing.
+ *  EACCES - Forbidden by inbound security policy.
+ *  EINPROGRESS - consumed by IPsec.
+ */
 int
-ipsec4_common_input(struct mbuf **mp, int *offp, int proto)
+ipsec4_input(struct mbuf *m, int offset, int proto)
 {
-	struct mbuf *m;
-	int off;
 
-	m = *mp;
-	off = *offp;
-	*mp = NULL;
-
-	ipsec_common_input(m, off, offsetof(struct ip, ip_p), AF_INET, proto);
-	return (IPPROTO_DONE);
+	switch (proto) {
+	case IPPROTO_AH:
+	case IPPROTO_ESP:
+	case IPPROTO_IPCOMP:
+		/* Do inbound IPsec processing for AH/ESP/IPCOMP */
+		ipsec_common_input(m, offset,
+		    offsetof(struct ip, ip_p), AF_INET, proto);
+		return (EINPROGRESS); /* mbuf consumed by IPsec */
+	default:
+		/*
+		 * Protocols with further headers get their IPsec treatment
+		 * within the protocol specific processing.
+		 */
+		if ((inetsw[ip_protox[proto]].pr_flags & PR_LASTHDR) == 0)
+			return (0);
+		/* FALLTHROUGH */
+	};
+	/*
+	 * Enforce IPsec policy checking if we are seeing last header.
+	 */
+	if (ipsec4_in_reject(m, NULL) != 0) {
+		/* Forbidden by inbound security policy */
+		m_freem(m);
+		return (EACCES);
+	}
+	return (0);
 }
 
 /*
@@ -414,48 +443,44 @@ bad:
 #endif /* INET */
 
 #ifdef INET6
-/* IPv6 AH wrapper. */
+extern struct protosw inet6sw[];
+
+/*
+ * IPSEC_INPUT() method implementation for IPv6.
+ *  0 - Permitted by inbound security policy for further processing.
+ *  EACCES - Forbidden by inbound security policy.
+ *  EINPROGRESS - consumed by IPsec.
+ */
 int
-ipsec6_common_input(struct mbuf **mp, int *offp, int proto)
+ipsec6_input(struct mbuf *m, int offset, int proto)
 {
-	int l = 0;
-	int protoff;
-	struct ip6_ext ip6e;
-
-	if (*offp < sizeof(struct ip6_hdr)) {
-		DPRINTF(("%s: bad offset %u\n", __func__, *offp));
-		return IPPROTO_DONE;
-	} else if (*offp == sizeof(struct ip6_hdr)) {
-		protoff = offsetof(struct ip6_hdr, ip6_nxt);
-	} else {
-		/* Chase down the header chain... */
-		protoff = sizeof(struct ip6_hdr);
 
-		do {
-			protoff += l;
-			m_copydata(*mp, protoff, sizeof(ip6e),
-			    (caddr_t) &ip6e);
-
-			if (ip6e.ip6e_nxt == IPPROTO_AH)
-				l = (ip6e.ip6e_len + 2) << 2;
-			else
-				l = (ip6e.ip6e_len + 1) << 3;
-			IPSEC_ASSERT(l > 0, ("l went zero or negative"));
-		} while (protoff + l < *offp);
-
-		/* Malformed packet check */
-		if (protoff + l != *offp) {
-			DPRINTF(("%s: bad packet header chain, protoff %u, "
-				"l %u, off %u\n", __func__, protoff, l, *offp));
-			IPSEC_ISTAT(proto, hdrops);
-			m_freem(*mp);
-			*mp = NULL;
-			return IPPROTO_DONE;
-		}
-		protoff += offsetof(struct ip6_ext, ip6e_nxt);
+	switch (proto) {
+	case IPPROTO_AH:
+	case IPPROTO_ESP:
+	case IPPROTO_IPCOMP:
+		/* Do inbound IPsec processing for AH/ESP/IPCOMP */
+		ipsec_common_input(m, offset,
+		    offsetof(struct ip6_hdr, ip6_nxt), AF_INET6, proto);
+		return (EINPROGRESS); /* mbuf consumed by IPsec */
+	default:
+		/*
+		 * Protocols with further headers get their IPsec treatment
+		 * within the protocol specific processing.
+		 */
+		if ((inet6sw[ip6_protox[proto]].pr_flags & PR_LASTHDR) == 0)
+			return (0);
+		/* FALLTHROUGH */
+	};
+	/*
+	 * Enforce IPsec policy checking if we are seeing last header.
+	 */
+	if (ipsec4_in_reject(m, NULL) != 0) {
+		/* Forbidden by inbound security policy */
+		m_freem(m);
+		return (EACCES);
 	}
-	(void) ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto);
-	return IPPROTO_DONE;
+	return (0);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612221417.uBMEHV2J073461>