xref: /f-stack/freebsd/netipsec/ipsec_input.c (revision 22ce4aff)
1a9643ea8Slogwang /*	$OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $	*/
2a9643ea8Slogwang /*-
3a9643ea8Slogwang  * The authors of this code are John Ioannidis ([email protected]),
4a9643ea8Slogwang  * Angelos D. Keromytis ([email protected]) and
5a9643ea8Slogwang  * Niels Provos ([email protected]).
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
8a9643ea8Slogwang  * in November 1995.
9a9643ea8Slogwang  *
10a9643ea8Slogwang  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
11a9643ea8Slogwang  * by Angelos D. Keromytis.
12a9643ea8Slogwang  *
13a9643ea8Slogwang  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
14a9643ea8Slogwang  * and Niels Provos.
15a9643ea8Slogwang  *
16a9643ea8Slogwang  * Additional features in 1999 by Angelos D. Keromytis.
17a9643ea8Slogwang  *
18a9643ea8Slogwang  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
19a9643ea8Slogwang  * Angelos D. Keromytis and Niels Provos.
20a9643ea8Slogwang  * Copyright (c) 2001, Angelos D. Keromytis.
21*22ce4affSfengbojiang  * Copyright (c) 2016 Andrey V. Elsukov <[email protected]>
22a9643ea8Slogwang  *
23a9643ea8Slogwang  * Permission to use, copy, and modify this software with or without fee
24a9643ea8Slogwang  * is hereby granted, provided that this entire notice is included in
25a9643ea8Slogwang  * all copies of any software which is or includes a copy or
26a9643ea8Slogwang  * modification of this software.
27a9643ea8Slogwang  * You may use this code under the GNU public license if you so wish. Please
28a9643ea8Slogwang  * contribute changes back to the authors under this freer than GPL license
29a9643ea8Slogwang  * so that we may further the use of strong encryption without limitations to
30a9643ea8Slogwang  * all.
31a9643ea8Slogwang  *
32a9643ea8Slogwang  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
33a9643ea8Slogwang  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
34a9643ea8Slogwang  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
35a9643ea8Slogwang  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
36a9643ea8Slogwang  * PURPOSE.
37a9643ea8Slogwang  */
38a9643ea8Slogwang 
39a9643ea8Slogwang /*
40a9643ea8Slogwang  * IPsec input processing.
41a9643ea8Slogwang  */
42a9643ea8Slogwang 
43*22ce4affSfengbojiang #include <sys/cdefs.h>
44*22ce4affSfengbojiang __FBSDID("$FreeBSD$");
45*22ce4affSfengbojiang 
46a9643ea8Slogwang #include "opt_inet.h"
47a9643ea8Slogwang #include "opt_inet6.h"
48a9643ea8Slogwang #include "opt_ipsec.h"
49a9643ea8Slogwang 
50a9643ea8Slogwang #include <sys/param.h>
51a9643ea8Slogwang #include <sys/systm.h>
52a9643ea8Slogwang #include <sys/malloc.h>
53a9643ea8Slogwang #include <sys/mbuf.h>
54a9643ea8Slogwang #include <sys/domain.h>
55a9643ea8Slogwang #include <sys/protosw.h>
56a9643ea8Slogwang #include <sys/socket.h>
57a9643ea8Slogwang #include <sys/errno.h>
58a9643ea8Slogwang #include <sys/hhook.h>
59a9643ea8Slogwang #include <sys/syslog.h>
60a9643ea8Slogwang 
61a9643ea8Slogwang #include <net/if.h>
62a9643ea8Slogwang #include <net/if_var.h>
63a9643ea8Slogwang #include <net/if_enc.h>
64a9643ea8Slogwang #include <net/netisr.h>
65a9643ea8Slogwang #include <net/vnet.h>
66a9643ea8Slogwang 
67a9643ea8Slogwang #include <netinet/in.h>
68a9643ea8Slogwang #include <netinet/in_systm.h>
69a9643ea8Slogwang #include <netinet/ip.h>
70a9643ea8Slogwang #include <netinet/ip_var.h>
71a9643ea8Slogwang #include <netinet/in_var.h>
72a9643ea8Slogwang 
73a9643ea8Slogwang #include <netinet/ip6.h>
74a9643ea8Slogwang #ifdef INET6
75a9643ea8Slogwang #include <netinet6/ip6_var.h>
76a9643ea8Slogwang #endif
77a9643ea8Slogwang #include <netinet/in_pcb.h>
78a9643ea8Slogwang #ifdef INET6
79a9643ea8Slogwang #include <netinet/icmp6.h>
80a9643ea8Slogwang #endif
81a9643ea8Slogwang 
82a9643ea8Slogwang #include <netipsec/ipsec.h>
83a9643ea8Slogwang #ifdef INET6
84a9643ea8Slogwang #include <netipsec/ipsec6.h>
85a9643ea8Slogwang #endif
86a9643ea8Slogwang #include <netipsec/ah_var.h>
87a9643ea8Slogwang #include <netipsec/esp.h>
88a9643ea8Slogwang #include <netipsec/esp_var.h>
89a9643ea8Slogwang #include <netipsec/ipcomp_var.h>
90a9643ea8Slogwang 
91a9643ea8Slogwang #include <netipsec/key.h>
92a9643ea8Slogwang #include <netipsec/keydb.h>
93*22ce4affSfengbojiang #include <netipsec/key_debug.h>
94a9643ea8Slogwang 
95a9643ea8Slogwang #include <netipsec/xform.h>
96a9643ea8Slogwang #include <netinet6/ip6protosw.h>
97a9643ea8Slogwang 
98a9643ea8Slogwang #include <machine/in_cksum.h>
99a9643ea8Slogwang #include <machine/stdarg.h>
100a9643ea8Slogwang 
101a9643ea8Slogwang #define	IPSEC_ISTAT(proto, name)	do {	\
102a9643ea8Slogwang 	if ((proto) == IPPROTO_ESP)		\
103a9643ea8Slogwang 		ESPSTAT_INC(esps_##name);	\
104a9643ea8Slogwang 	else if ((proto) == IPPROTO_AH)		\
105a9643ea8Slogwang 		AHSTAT_INC(ahs_##name);		\
106a9643ea8Slogwang 	else					\
107a9643ea8Slogwang 		IPCOMPSTAT_INC(ipcomps_##name);	\
108a9643ea8Slogwang } while (0)
109a9643ea8Slogwang 
110a9643ea8Slogwang /*
111a9643ea8Slogwang  * ipsec_common_input gets called when an IPsec-protected packet
112a9643ea8Slogwang  * is received by IPv4 or IPv6.  Its job is to find the right SA
113a9643ea8Slogwang  * and call the appropriate transform.  The transform callback
114a9643ea8Slogwang  * takes care of further processing (like ingress filtering).
115a9643ea8Slogwang  */
116*22ce4affSfengbojiang static int
ipsec_common_input(struct mbuf * m,int skip,int protoff,int af,int sproto)117a9643ea8Slogwang ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
118a9643ea8Slogwang {
119*22ce4affSfengbojiang 	IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
120a9643ea8Slogwang 	union sockaddr_union dst_address;
121a9643ea8Slogwang 	struct secasvar *sav;
122*22ce4affSfengbojiang 	uint32_t spi;
123a9643ea8Slogwang 	int error;
124a9643ea8Slogwang 
125a9643ea8Slogwang 	IPSEC_ISTAT(sproto, input);
126a9643ea8Slogwang 
127a9643ea8Slogwang 	IPSEC_ASSERT(m != NULL, ("null packet"));
128a9643ea8Slogwang 
129a9643ea8Slogwang 	IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
130a9643ea8Slogwang 		sproto == IPPROTO_IPCOMP,
131a9643ea8Slogwang 		("unexpected security protocol %u", sproto));
132a9643ea8Slogwang 
133a9643ea8Slogwang 	if ((sproto == IPPROTO_ESP && !V_esp_enable) ||
134a9643ea8Slogwang 	    (sproto == IPPROTO_AH && !V_ah_enable) ||
135a9643ea8Slogwang 	    (sproto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
136a9643ea8Slogwang 		m_freem(m);
137a9643ea8Slogwang 		IPSEC_ISTAT(sproto, pdrops);
138a9643ea8Slogwang 		return EOPNOTSUPP;
139a9643ea8Slogwang 	}
140a9643ea8Slogwang 
141a9643ea8Slogwang 	if (m->m_pkthdr.len - skip < 2 * sizeof (u_int32_t)) {
142a9643ea8Slogwang 		m_freem(m);
143a9643ea8Slogwang 		IPSEC_ISTAT(sproto, hdrops);
144a9643ea8Slogwang 		DPRINTF(("%s: packet too small\n", __func__));
145a9643ea8Slogwang 		return EINVAL;
146a9643ea8Slogwang 	}
147a9643ea8Slogwang 
148a9643ea8Slogwang 	/* Retrieve the SPI from the relevant IPsec header */
149a9643ea8Slogwang 	if (sproto == IPPROTO_ESP)
150a9643ea8Slogwang 		m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
151a9643ea8Slogwang 	else if (sproto == IPPROTO_AH)
152a9643ea8Slogwang 		m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
153a9643ea8Slogwang 		    (caddr_t) &spi);
154a9643ea8Slogwang 	else if (sproto == IPPROTO_IPCOMP) {
155a9643ea8Slogwang 		u_int16_t cpi;
156a9643ea8Slogwang 		m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t),
157a9643ea8Slogwang 		    (caddr_t) &cpi);
158a9643ea8Slogwang 		spi = ntohl(htons(cpi));
159a9643ea8Slogwang 	}
160a9643ea8Slogwang 
161a9643ea8Slogwang 	/*
162a9643ea8Slogwang 	 * Find the SA and (indirectly) call the appropriate
163a9643ea8Slogwang 	 * kernel crypto routine. The resulting mbuf chain is a valid
164a9643ea8Slogwang 	 * IP packet ready to go through input processing.
165a9643ea8Slogwang 	 */
166a9643ea8Slogwang 	bzero(&dst_address, sizeof (dst_address));
167a9643ea8Slogwang 	dst_address.sa.sa_family = af;
168a9643ea8Slogwang 	switch (af) {
169a9643ea8Slogwang #ifdef INET
170a9643ea8Slogwang 	case AF_INET:
171a9643ea8Slogwang 		dst_address.sin.sin_len = sizeof(struct sockaddr_in);
172a9643ea8Slogwang 		m_copydata(m, offsetof(struct ip, ip_dst),
173a9643ea8Slogwang 		    sizeof(struct in_addr),
174a9643ea8Slogwang 		    (caddr_t) &dst_address.sin.sin_addr);
175a9643ea8Slogwang 		break;
176a9643ea8Slogwang #endif /* INET */
177a9643ea8Slogwang #ifdef INET6
178a9643ea8Slogwang 	case AF_INET6:
179a9643ea8Slogwang 		dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
180a9643ea8Slogwang 		m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
181a9643ea8Slogwang 		    sizeof(struct in6_addr),
182a9643ea8Slogwang 		    (caddr_t) &dst_address.sin6.sin6_addr);
183a9643ea8Slogwang 		/* We keep addresses in SADB without embedded scope id */
184a9643ea8Slogwang 		if (IN6_IS_SCOPE_LINKLOCAL(&dst_address.sin6.sin6_addr)) {
185a9643ea8Slogwang 			/* XXX: sa6_recoverscope() */
186a9643ea8Slogwang 			dst_address.sin6.sin6_scope_id =
187a9643ea8Slogwang 			    ntohs(dst_address.sin6.sin6_addr.s6_addr16[1]);
188a9643ea8Slogwang 			dst_address.sin6.sin6_addr.s6_addr16[1] = 0;
189a9643ea8Slogwang 		}
190a9643ea8Slogwang 		break;
191a9643ea8Slogwang #endif /* INET6 */
192a9643ea8Slogwang 	default:
193a9643ea8Slogwang 		DPRINTF(("%s: unsupported protocol family %u\n", __func__, af));
194a9643ea8Slogwang 		m_freem(m);
195a9643ea8Slogwang 		IPSEC_ISTAT(sproto, nopf);
196a9643ea8Slogwang 		return EPFNOSUPPORT;
197a9643ea8Slogwang 	}
198a9643ea8Slogwang 
199a9643ea8Slogwang 	/* NB: only pass dst since key_allocsa follows RFC2401 */
200*22ce4affSfengbojiang 	sav = key_allocsa(&dst_address, sproto, spi);
201a9643ea8Slogwang 	if (sav == NULL) {
202a9643ea8Slogwang 		DPRINTF(("%s: no key association found for SA %s/%08lx/%u\n",
203a9643ea8Slogwang 		    __func__, ipsec_address(&dst_address, buf, sizeof(buf)),
204a9643ea8Slogwang 		    (u_long) ntohl(spi), sproto));
205a9643ea8Slogwang 		IPSEC_ISTAT(sproto, notdb);
206a9643ea8Slogwang 		m_freem(m);
207a9643ea8Slogwang 		return ENOENT;
208a9643ea8Slogwang 	}
209a9643ea8Slogwang 
210a9643ea8Slogwang 	if (sav->tdb_xform == NULL) {
211a9643ea8Slogwang 		DPRINTF(("%s: attempted to use uninitialized SA %s/%08lx/%u\n",
212a9643ea8Slogwang 		    __func__, ipsec_address(&dst_address, buf, sizeof(buf)),
213a9643ea8Slogwang 		    (u_long) ntohl(spi), sproto));
214a9643ea8Slogwang 		IPSEC_ISTAT(sproto, noxform);
215*22ce4affSfengbojiang 		key_freesav(&sav);
216a9643ea8Slogwang 		m_freem(m);
217a9643ea8Slogwang 		return ENXIO;
218a9643ea8Slogwang 	}
219a9643ea8Slogwang 
220a9643ea8Slogwang 	/*
221a9643ea8Slogwang 	 * Call appropriate transform and return -- callback takes care of
222a9643ea8Slogwang 	 * everything else.
223a9643ea8Slogwang 	 */
224a9643ea8Slogwang 	error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff);
225*22ce4affSfengbojiang 	return (error);
226a9643ea8Slogwang }
227a9643ea8Slogwang 
228a9643ea8Slogwang #ifdef INET
229*22ce4affSfengbojiang extern struct protosw inetsw[];
230*22ce4affSfengbojiang 
231*22ce4affSfengbojiang /*
232*22ce4affSfengbojiang  * IPSEC_INPUT() method implementation for IPv4.
233*22ce4affSfengbojiang  *  0 - Permitted by inbound security policy for further processing.
234*22ce4affSfengbojiang  *  EACCES - Forbidden by inbound security policy.
235*22ce4affSfengbojiang  *  EINPROGRESS - consumed by IPsec.
236*22ce4affSfengbojiang  */
237a9643ea8Slogwang int
ipsec4_input(struct mbuf * m,int offset,int proto)238*22ce4affSfengbojiang ipsec4_input(struct mbuf *m, int offset, int proto)
239a9643ea8Slogwang {
240a9643ea8Slogwang 
241*22ce4affSfengbojiang 	switch (proto) {
242*22ce4affSfengbojiang 	case IPPROTO_AH:
243*22ce4affSfengbojiang 	case IPPROTO_ESP:
244*22ce4affSfengbojiang 	case IPPROTO_IPCOMP:
245*22ce4affSfengbojiang 		/* Do inbound IPsec processing for AH/ESP/IPCOMP */
246*22ce4affSfengbojiang 		ipsec_common_input(m, offset,
247*22ce4affSfengbojiang 		    offsetof(struct ip, ip_p), AF_INET, proto);
248*22ce4affSfengbojiang 		return (EINPROGRESS); /* mbuf consumed by IPsec */
249*22ce4affSfengbojiang 	default:
250*22ce4affSfengbojiang 		/*
251*22ce4affSfengbojiang 		 * Protocols with further headers get their IPsec treatment
252*22ce4affSfengbojiang 		 * within the protocol specific processing.
253*22ce4affSfengbojiang 		 */
254*22ce4affSfengbojiang 		if ((inetsw[ip_protox[proto]].pr_flags & PR_LASTHDR) == 0)
255*22ce4affSfengbojiang 			return (0);
256*22ce4affSfengbojiang 		/* FALLTHROUGH */
257*22ce4affSfengbojiang 	};
258*22ce4affSfengbojiang 	/*
259*22ce4affSfengbojiang 	 * Enforce IPsec policy checking if we are seeing last header.
260*22ce4affSfengbojiang 	 */
261*22ce4affSfengbojiang 	if (ipsec4_in_reject(m, NULL) != 0) {
262*22ce4affSfengbojiang 		/* Forbidden by inbound security policy */
263*22ce4affSfengbojiang 		m_freem(m);
264*22ce4affSfengbojiang 		return (EACCES);
265a9643ea8Slogwang 	}
266*22ce4affSfengbojiang 	return (0);
267a9643ea8Slogwang }
268a9643ea8Slogwang 
269a9643ea8Slogwang /*
270a9643ea8Slogwang  * IPsec input callback for INET protocols.
271a9643ea8Slogwang  * This routine is called as the transform callback.
272a9643ea8Slogwang  * Takes care of filtering and other sanity checks on
273a9643ea8Slogwang  * the processed packet.
274a9643ea8Slogwang  */
275a9643ea8Slogwang int
ipsec4_common_input_cb(struct mbuf * m,struct secasvar * sav,int skip,int protoff)276a9643ea8Slogwang ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
277a9643ea8Slogwang     int protoff)
278a9643ea8Slogwang {
279*22ce4affSfengbojiang 	IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
280*22ce4affSfengbojiang 	struct epoch_tracker et;
281a9643ea8Slogwang 	struct ipsec_ctx_data ctx;
282*22ce4affSfengbojiang 	struct xform_history *xh;
283a9643ea8Slogwang 	struct secasindex *saidx;
284*22ce4affSfengbojiang 	struct m_tag *mtag;
285*22ce4affSfengbojiang 	struct ip *ip;
286*22ce4affSfengbojiang 	int error, prot, af, sproto, isr_prot;
287a9643ea8Slogwang 
288a9643ea8Slogwang 	IPSEC_ASSERT(sav != NULL, ("null SA"));
289a9643ea8Slogwang 	IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
290a9643ea8Slogwang 	saidx = &sav->sah->saidx;
291a9643ea8Slogwang 	af = saidx->dst.sa.sa_family;
292a9643ea8Slogwang 	IPSEC_ASSERT(af == AF_INET, ("unexpected af %u", af));
293a9643ea8Slogwang 	sproto = saidx->proto;
294a9643ea8Slogwang 	IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
295a9643ea8Slogwang 		sproto == IPPROTO_IPCOMP,
296a9643ea8Slogwang 		("unexpected security protocol %u", sproto));
297a9643ea8Slogwang 
298a9643ea8Slogwang 	if (skip != 0) {
299a9643ea8Slogwang 		/*
300a9643ea8Slogwang 		 * Fix IPv4 header
301a9643ea8Slogwang 		 */
302a9643ea8Slogwang 		if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) {
303a9643ea8Slogwang 			DPRINTF(("%s: processing failed for SA %s/%08lx\n",
304a9643ea8Slogwang 			    __func__, ipsec_address(&sav->sah->saidx.dst,
305a9643ea8Slogwang 			    buf, sizeof(buf)), (u_long) ntohl(sav->spi)));
306a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
307a9643ea8Slogwang 			error = ENOBUFS;
308a9643ea8Slogwang 			goto bad;
309a9643ea8Slogwang 		}
310a9643ea8Slogwang 
311a9643ea8Slogwang 		ip = mtod(m, struct ip *);
312a9643ea8Slogwang 		ip->ip_len = htons(m->m_pkthdr.len);
313a9643ea8Slogwang 		ip->ip_sum = 0;
314a9643ea8Slogwang 		ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
315a9643ea8Slogwang 	} else {
316a9643ea8Slogwang 		ip = mtod(m, struct ip *);
317a9643ea8Slogwang 	}
318a9643ea8Slogwang 	prot = ip->ip_p;
319*22ce4affSfengbojiang 	/*
320*22ce4affSfengbojiang 	 * Check that we have NAT-T enabled and apply transport mode
321*22ce4affSfengbojiang 	 * decapsulation NAT procedure (RFC3948).
322*22ce4affSfengbojiang 	 * Do this before invoking into the PFIL.
323*22ce4affSfengbojiang 	 */
324*22ce4affSfengbojiang 	if (sav->natt != NULL &&
325*22ce4affSfengbojiang 	    (prot == IPPROTO_UDP || prot == IPPROTO_TCP))
326*22ce4affSfengbojiang 		udp_ipsec_adjust_cksum(m, sav, prot, skip);
327a9643ea8Slogwang 
328*22ce4affSfengbojiang 	IPSEC_INIT_CTX(&ctx, &m, NULL, sav, AF_INET, IPSEC_ENC_BEFORE);
329a9643ea8Slogwang 	if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
330a9643ea8Slogwang 		goto bad;
331*22ce4affSfengbojiang 	ip = mtod(m, struct ip *);	/* update pointer */
332a9643ea8Slogwang 
333a9643ea8Slogwang 	/* IP-in-IP encapsulation */
334a9643ea8Slogwang 	if (prot == IPPROTO_IPIP &&
335a9643ea8Slogwang 	    saidx->mode != IPSEC_MODE_TRANSPORT) {
336a9643ea8Slogwang 		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
337a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
338a9643ea8Slogwang 			error = EINVAL;
339a9643ea8Slogwang 			goto bad;
340a9643ea8Slogwang 		}
341a9643ea8Slogwang 		/* enc0: strip outer IPv4 header */
342a9643ea8Slogwang 		m_striphdr(m, 0, ip->ip_hl << 2);
343a9643ea8Slogwang 	}
344a9643ea8Slogwang #ifdef INET6
345a9643ea8Slogwang 	/* IPv6-in-IP encapsulation. */
346a9643ea8Slogwang 	else if (prot == IPPROTO_IPV6 &&
347a9643ea8Slogwang 	    saidx->mode != IPSEC_MODE_TRANSPORT) {
348a9643ea8Slogwang 		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
349a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
350a9643ea8Slogwang 			error = EINVAL;
351a9643ea8Slogwang 			goto bad;
352a9643ea8Slogwang 		}
353a9643ea8Slogwang 		/* enc0: strip IPv4 header, keep IPv6 header only */
354a9643ea8Slogwang 		m_striphdr(m, 0, ip->ip_hl << 2);
355a9643ea8Slogwang 	}
356a9643ea8Slogwang #endif /* INET6 */
357a9643ea8Slogwang 	else if (prot != IPPROTO_IPV6 && saidx->mode == IPSEC_MODE_ANY) {
358a9643ea8Slogwang 		/*
359a9643ea8Slogwang 		 * When mode is wildcard, inner protocol is IPv6 and
360a9643ea8Slogwang 		 * we have no INET6 support - drop this packet a bit later.
361*22ce4affSfengbojiang 		 * In other cases we assume transport mode. Set prot to
362*22ce4affSfengbojiang 		 * correctly choose netisr.
363a9643ea8Slogwang 		 */
364a9643ea8Slogwang 		prot = IPPROTO_IPIP;
365a9643ea8Slogwang 	}
366a9643ea8Slogwang 
367a9643ea8Slogwang 	/*
368a9643ea8Slogwang 	 * Record what we've done to the packet (under what SA it was
369a9643ea8Slogwang 	 * processed).
370a9643ea8Slogwang 	 */
371a9643ea8Slogwang 	if (sproto != IPPROTO_IPCOMP) {
372a9643ea8Slogwang 		mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
373*22ce4affSfengbojiang 		    sizeof(struct xform_history), M_NOWAIT);
374a9643ea8Slogwang 		if (mtag == NULL) {
375a9643ea8Slogwang 			DPRINTF(("%s: failed to get tag\n", __func__));
376a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
377a9643ea8Slogwang 			error = ENOMEM;
378a9643ea8Slogwang 			goto bad;
379a9643ea8Slogwang 		}
380a9643ea8Slogwang 
381*22ce4affSfengbojiang 		xh = (struct xform_history *)(mtag + 1);
382*22ce4affSfengbojiang 		bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len);
383*22ce4affSfengbojiang 		xh->spi = sav->spi;
384*22ce4affSfengbojiang 		xh->proto = sproto;
385*22ce4affSfengbojiang 		xh->mode = saidx->mode;
386a9643ea8Slogwang 		m_tag_prepend(m, mtag);
387a9643ea8Slogwang 	}
388a9643ea8Slogwang 
389a9643ea8Slogwang 	key_sa_recordxfer(sav, m);		/* record data transfer */
390a9643ea8Slogwang 
391a9643ea8Slogwang 	/*
392a9643ea8Slogwang 	 * In transport mode requeue decrypted mbuf back to IPv4 protocol
393a9643ea8Slogwang 	 * handler. This is necessary to correctly expose rcvif.
394a9643ea8Slogwang 	 */
395a9643ea8Slogwang 	if (saidx->mode == IPSEC_MODE_TRANSPORT)
396a9643ea8Slogwang 		prot = IPPROTO_IPIP;
397a9643ea8Slogwang 	/*
398a9643ea8Slogwang 	 * Re-dispatch via software interrupt.
399a9643ea8Slogwang 	 */
400a9643ea8Slogwang 	switch (prot) {
401a9643ea8Slogwang 	case IPPROTO_IPIP:
402a9643ea8Slogwang 		isr_prot = NETISR_IP;
403a9643ea8Slogwang 		af = AF_INET;
404a9643ea8Slogwang 		break;
405a9643ea8Slogwang #ifdef INET6
406a9643ea8Slogwang 	case IPPROTO_IPV6:
407a9643ea8Slogwang 		isr_prot = NETISR_IPV6;
408a9643ea8Slogwang 		af = AF_INET6;
409a9643ea8Slogwang 		break;
410a9643ea8Slogwang #endif
411a9643ea8Slogwang 	default:
412a9643ea8Slogwang 		DPRINTF(("%s: cannot handle inner ip proto %d\n",
413a9643ea8Slogwang 			    __func__, prot));
414a9643ea8Slogwang 		IPSEC_ISTAT(sproto, nopf);
415a9643ea8Slogwang 		error = EPFNOSUPPORT;
416a9643ea8Slogwang 		goto bad;
417a9643ea8Slogwang 	}
418a9643ea8Slogwang 
419*22ce4affSfengbojiang 	IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER);
420a9643ea8Slogwang 	if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
421a9643ea8Slogwang 		goto bad;
422*22ce4affSfengbojiang 
423*22ce4affSfengbojiang 	/* Handle virtual tunneling interfaces */
424*22ce4affSfengbojiang 	if (saidx->mode == IPSEC_MODE_TUNNEL)
425*22ce4affSfengbojiang 		error = ipsec_if_input(m, sav, af);
426*22ce4affSfengbojiang 	if (error == 0) {
427*22ce4affSfengbojiang 		NET_EPOCH_ENTER(et);
428a9643ea8Slogwang 		error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
429*22ce4affSfengbojiang 		NET_EPOCH_EXIT(et);
430a9643ea8Slogwang 		if (error) {
431a9643ea8Slogwang 			IPSEC_ISTAT(sproto, qfull);
432a9643ea8Slogwang 			DPRINTF(("%s: queue full; proto %u packet dropped\n",
433a9643ea8Slogwang 			    __func__, sproto));
434a9643ea8Slogwang 		}
435*22ce4affSfengbojiang 	}
436*22ce4affSfengbojiang 	key_freesav(&sav);
437*22ce4affSfengbojiang 	return (error);
438a9643ea8Slogwang bad:
439*22ce4affSfengbojiang 	key_freesav(&sav);
440*22ce4affSfengbojiang 	if (m != NULL)
441a9643ea8Slogwang 		m_freem(m);
442*22ce4affSfengbojiang 	return (error);
443a9643ea8Slogwang }
444a9643ea8Slogwang #endif /* INET */
445a9643ea8Slogwang 
446a9643ea8Slogwang #ifdef INET6
447*22ce4affSfengbojiang /*
448*22ce4affSfengbojiang  * IPSEC_INPUT() method implementation for IPv6.
449*22ce4affSfengbojiang  *  0 - Permitted by inbound security policy for further processing.
450*22ce4affSfengbojiang  *  EACCES - Forbidden by inbound security policy.
451*22ce4affSfengbojiang  *  EINPROGRESS - consumed by IPsec.
452*22ce4affSfengbojiang  */
453a9643ea8Slogwang int
ipsec6_input(struct mbuf * m,int offset,int proto)454*22ce4affSfengbojiang ipsec6_input(struct mbuf *m, int offset, int proto)
455a9643ea8Slogwang {
456a9643ea8Slogwang 
457*22ce4affSfengbojiang 	switch (proto) {
458*22ce4affSfengbojiang 	case IPPROTO_AH:
459*22ce4affSfengbojiang 	case IPPROTO_ESP:
460*22ce4affSfengbojiang 	case IPPROTO_IPCOMP:
461*22ce4affSfengbojiang 		/* Do inbound IPsec processing for AH/ESP/IPCOMP */
462*22ce4affSfengbojiang 		ipsec_common_input(m, offset,
463*22ce4affSfengbojiang 		    offsetof(struct ip6_hdr, ip6_nxt), AF_INET6, proto);
464*22ce4affSfengbojiang 		return (EINPROGRESS); /* mbuf consumed by IPsec */
465*22ce4affSfengbojiang 	default:
466*22ce4affSfengbojiang 		/*
467*22ce4affSfengbojiang 		 * Protocols with further headers get their IPsec treatment
468*22ce4affSfengbojiang 		 * within the protocol specific processing.
469*22ce4affSfengbojiang 		 */
470*22ce4affSfengbojiang 		if ((inet6sw[ip6_protox[proto]].pr_flags & PR_LASTHDR) == 0)
471*22ce4affSfengbojiang 			return (0);
472*22ce4affSfengbojiang 		/* FALLTHROUGH */
473*22ce4affSfengbojiang 	};
474*22ce4affSfengbojiang 	/*
475*22ce4affSfengbojiang 	 * Enforce IPsec policy checking if we are seeing last header.
476*22ce4affSfengbojiang 	 */
477*22ce4affSfengbojiang 	if (ipsec6_in_reject(m, NULL) != 0) {
478*22ce4affSfengbojiang 		/* Forbidden by inbound security policy */
479*22ce4affSfengbojiang 		m_freem(m);
480*22ce4affSfengbojiang 		return (EACCES);
481a9643ea8Slogwang 	}
482*22ce4affSfengbojiang 	return (0);
483a9643ea8Slogwang }
484a9643ea8Slogwang 
485a9643ea8Slogwang /*
486a9643ea8Slogwang  * IPsec input callback, called by the transform callback. Takes care of
487a9643ea8Slogwang  * filtering and other sanity checks on the processed packet.
488a9643ea8Slogwang  */
489a9643ea8Slogwang int
ipsec6_common_input_cb(struct mbuf * m,struct secasvar * sav,int skip,int protoff)490a9643ea8Slogwang ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
491a9643ea8Slogwang     int protoff)
492a9643ea8Slogwang {
493*22ce4affSfengbojiang 	IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
494*22ce4affSfengbojiang 	struct epoch_tracker et;
495a9643ea8Slogwang 	struct ipsec_ctx_data ctx;
496*22ce4affSfengbojiang 	struct xform_history *xh;
497*22ce4affSfengbojiang 	struct secasindex *saidx;
498a9643ea8Slogwang 	struct ip6_hdr *ip6;
499a9643ea8Slogwang 	struct m_tag *mtag;
500*22ce4affSfengbojiang 	int prot, af, sproto;
501a9643ea8Slogwang 	int nxt, isr_prot;
502a9643ea8Slogwang 	int error, nest;
503*22ce4affSfengbojiang 	uint8_t nxt8;
504a9643ea8Slogwang 
505a9643ea8Slogwang 	IPSEC_ASSERT(sav != NULL, ("null SA"));
506a9643ea8Slogwang 	IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
507a9643ea8Slogwang 	saidx = &sav->sah->saidx;
508a9643ea8Slogwang 	af = saidx->dst.sa.sa_family;
509a9643ea8Slogwang 	IPSEC_ASSERT(af == AF_INET6, ("unexpected af %u", af));
510a9643ea8Slogwang 	sproto = saidx->proto;
511a9643ea8Slogwang 	IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
512a9643ea8Slogwang 		sproto == IPPROTO_IPCOMP,
513a9643ea8Slogwang 		("unexpected security protocol %u", sproto));
514a9643ea8Slogwang 
515a9643ea8Slogwang 	/* Fix IPv6 header */
516a9643ea8Slogwang 	if (m->m_len < sizeof(struct ip6_hdr) &&
517a9643ea8Slogwang 	    (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
518a9643ea8Slogwang 		DPRINTF(("%s: processing failed for SA %s/%08lx\n",
519a9643ea8Slogwang 		    __func__, ipsec_address(&sav->sah->saidx.dst, buf,
520a9643ea8Slogwang 		    sizeof(buf)), (u_long) ntohl(sav->spi)));
521a9643ea8Slogwang 
522a9643ea8Slogwang 		IPSEC_ISTAT(sproto, hdrops);
523a9643ea8Slogwang 		error = EACCES;
524a9643ea8Slogwang 		goto bad;
525a9643ea8Slogwang 	}
526a9643ea8Slogwang 
527*22ce4affSfengbojiang 	IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_BEFORE);
528*22ce4affSfengbojiang 	if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
529*22ce4affSfengbojiang 		goto bad;
530*22ce4affSfengbojiang 
531a9643ea8Slogwang 	ip6 = mtod(m, struct ip6_hdr *);
532a9643ea8Slogwang 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
533a9643ea8Slogwang 
534a9643ea8Slogwang 	/* Save protocol */
535a9643ea8Slogwang 	m_copydata(m, protoff, 1, &nxt8);
536a9643ea8Slogwang 	prot = nxt8;
537a9643ea8Slogwang 
538a9643ea8Slogwang 	/* IPv6-in-IP encapsulation */
539a9643ea8Slogwang 	if (prot == IPPROTO_IPV6 &&
540a9643ea8Slogwang 	    saidx->mode != IPSEC_MODE_TRANSPORT) {
541a9643ea8Slogwang 		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
542a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
543a9643ea8Slogwang 			error = EINVAL;
544a9643ea8Slogwang 			goto bad;
545a9643ea8Slogwang 		}
546a9643ea8Slogwang 		/* ip6n will now contain the inner IPv6 header. */
547a9643ea8Slogwang 		m_striphdr(m, 0, skip);
548a9643ea8Slogwang 		skip = 0;
549a9643ea8Slogwang 	}
550a9643ea8Slogwang #ifdef INET
551a9643ea8Slogwang 	/* IP-in-IP encapsulation */
552a9643ea8Slogwang 	else if (prot == IPPROTO_IPIP &&
553a9643ea8Slogwang 	    saidx->mode != IPSEC_MODE_TRANSPORT) {
554a9643ea8Slogwang 		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
555a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
556a9643ea8Slogwang 			error = EINVAL;
557a9643ea8Slogwang 			goto bad;
558a9643ea8Slogwang 		}
559a9643ea8Slogwang 		/* ipn will now contain the inner IPv4 header */
560a9643ea8Slogwang 		m_striphdr(m, 0, skip);
561a9643ea8Slogwang 		skip = 0;
562a9643ea8Slogwang 	}
563a9643ea8Slogwang #endif /* INET */
564a9643ea8Slogwang 	else {
565a9643ea8Slogwang 		prot = IPPROTO_IPV6; /* for correct BPF processing */
566a9643ea8Slogwang 	}
567a9643ea8Slogwang 
568a9643ea8Slogwang 	/*
569a9643ea8Slogwang 	 * Record what we've done to the packet (under what SA it was
570a9643ea8Slogwang 	 * processed).
571a9643ea8Slogwang 	 */
572a9643ea8Slogwang 	if (sproto != IPPROTO_IPCOMP) {
573a9643ea8Slogwang 		mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
574*22ce4affSfengbojiang 		    sizeof(struct xform_history), M_NOWAIT);
575a9643ea8Slogwang 		if (mtag == NULL) {
576a9643ea8Slogwang 			DPRINTF(("%s: failed to get tag\n", __func__));
577a9643ea8Slogwang 			IPSEC_ISTAT(sproto, hdrops);
578a9643ea8Slogwang 			error = ENOMEM;
579a9643ea8Slogwang 			goto bad;
580a9643ea8Slogwang 		}
581a9643ea8Slogwang 
582*22ce4affSfengbojiang 		xh = (struct xform_history *)(mtag + 1);
583*22ce4affSfengbojiang 		bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len);
584*22ce4affSfengbojiang 		xh->spi = sav->spi;
585*22ce4affSfengbojiang 		xh->proto = sproto;
586*22ce4affSfengbojiang 		xh->mode = saidx->mode;
587a9643ea8Slogwang 		m_tag_prepend(m, mtag);
588a9643ea8Slogwang 	}
589a9643ea8Slogwang 
590a9643ea8Slogwang 	key_sa_recordxfer(sav, m);
591a9643ea8Slogwang 
592a9643ea8Slogwang #ifdef INET
593a9643ea8Slogwang 	if (prot == IPPROTO_IPIP)
594a9643ea8Slogwang 		af = AF_INET;
595a9643ea8Slogwang 	else
596a9643ea8Slogwang #endif
597a9643ea8Slogwang 		af = AF_INET6;
598*22ce4affSfengbojiang 	IPSEC_INIT_CTX(&ctx, &m, NULL, sav, af, IPSEC_ENC_AFTER);
599a9643ea8Slogwang 	if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
600a9643ea8Slogwang 		goto bad;
601a9643ea8Slogwang 	if (skip == 0) {
602a9643ea8Slogwang 		/*
603a9643ea8Slogwang 		 * We stripped outer IPv6 header.
604a9643ea8Slogwang 		 * Now we should requeue decrypted packet via netisr.
605a9643ea8Slogwang 		 */
606a9643ea8Slogwang 		switch (prot) {
607a9643ea8Slogwang #ifdef INET
608a9643ea8Slogwang 		case IPPROTO_IPIP:
609a9643ea8Slogwang 			isr_prot = NETISR_IP;
610a9643ea8Slogwang 			break;
611a9643ea8Slogwang #endif
612a9643ea8Slogwang 		case IPPROTO_IPV6:
613a9643ea8Slogwang 			isr_prot = NETISR_IPV6;
614a9643ea8Slogwang 			break;
615a9643ea8Slogwang 		default:
616a9643ea8Slogwang 			DPRINTF(("%s: cannot handle inner ip proto %d\n",
617a9643ea8Slogwang 			    __func__, prot));
618a9643ea8Slogwang 			IPSEC_ISTAT(sproto, nopf);
619a9643ea8Slogwang 			error = EPFNOSUPPORT;
620a9643ea8Slogwang 			goto bad;
621a9643ea8Slogwang 		}
622*22ce4affSfengbojiang 		/* Handle virtual tunneling interfaces */
623*22ce4affSfengbojiang 		if (saidx->mode == IPSEC_MODE_TUNNEL)
624*22ce4affSfengbojiang 			error = ipsec_if_input(m, sav, af);
625*22ce4affSfengbojiang 		if (error == 0) {
626*22ce4affSfengbojiang 			NET_EPOCH_ENTER(et);
627*22ce4affSfengbojiang 			error = netisr_queue_src(isr_prot,
628*22ce4affSfengbojiang 			    (uintptr_t)sav->spi, m);
629*22ce4affSfengbojiang 			NET_EPOCH_EXIT(et);
630a9643ea8Slogwang 			if (error) {
631a9643ea8Slogwang 				IPSEC_ISTAT(sproto, qfull);
632*22ce4affSfengbojiang 				DPRINTF(("%s: queue full; proto %u packet"
633*22ce4affSfengbojiang 				    " dropped\n", __func__, sproto));
634a9643ea8Slogwang 			}
635*22ce4affSfengbojiang 		}
636*22ce4affSfengbojiang 		key_freesav(&sav);
637a9643ea8Slogwang 		return (error);
638a9643ea8Slogwang 	}
639a9643ea8Slogwang 	/*
640a9643ea8Slogwang 	 * See the end of ip6_input for this logic.
641a9643ea8Slogwang 	 * IPPROTO_IPV[46] case will be processed just like other ones
642a9643ea8Slogwang 	 */
643a9643ea8Slogwang 	nest = 0;
644a9643ea8Slogwang 	nxt = nxt8;
645*22ce4affSfengbojiang 	NET_EPOCH_ENTER(et);
646a9643ea8Slogwang 	while (nxt != IPPROTO_DONE) {
647a9643ea8Slogwang 		if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
648a9643ea8Slogwang 			IP6STAT_INC(ip6s_toomanyhdr);
649a9643ea8Slogwang 			error = EINVAL;
650*22ce4affSfengbojiang 			goto bad_epoch;
651a9643ea8Slogwang 		}
652a9643ea8Slogwang 
653a9643ea8Slogwang 		/*
654a9643ea8Slogwang 		 * Protection against faulty packet - there should be
655a9643ea8Slogwang 		 * more sanity checks in header chain processing.
656a9643ea8Slogwang 		 */
657a9643ea8Slogwang 		if (m->m_pkthdr.len < skip) {
658a9643ea8Slogwang 			IP6STAT_INC(ip6s_tooshort);
659a9643ea8Slogwang 			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
660a9643ea8Slogwang 			error = EINVAL;
661*22ce4affSfengbojiang 			goto bad_epoch;
662a9643ea8Slogwang 		}
663a9643ea8Slogwang 		/*
664a9643ea8Slogwang 		 * Enforce IPsec policy checking if we are seeing last header.
665a9643ea8Slogwang 		 * note that we do not visit this with protocols with pcb layer
666a9643ea8Slogwang 		 * code - like udp/tcp/raw ip.
667a9643ea8Slogwang 		 */
668a9643ea8Slogwang 		if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
669a9643ea8Slogwang 		    ipsec6_in_reject(m, NULL)) {
670a9643ea8Slogwang 			error = EINVAL;
671*22ce4affSfengbojiang 			goto bad_epoch;
672a9643ea8Slogwang 		}
673a9643ea8Slogwang 		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt);
674a9643ea8Slogwang 	}
675*22ce4affSfengbojiang 	NET_EPOCH_EXIT(et);
676*22ce4affSfengbojiang 	key_freesav(&sav);
677*22ce4affSfengbojiang 	return (0);
678*22ce4affSfengbojiang bad_epoch:
679*22ce4affSfengbojiang 	NET_EPOCH_EXIT(et);
680a9643ea8Slogwang bad:
681*22ce4affSfengbojiang 	key_freesav(&sav);
682a9643ea8Slogwang 	if (m)
683a9643ea8Slogwang 		m_freem(m);
684*22ce4affSfengbojiang 	return (error);
685a9643ea8Slogwang }
686a9643ea8Slogwang #endif /* INET6 */
687