1/*	$FreeBSD$	*/
2/*	$OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
3/*-
4 * The authors of this code are John Ioannidis (ji@tla.org),
5 * Angelos D. Keromytis (kermit@csd.uch.gr) and
6 * Niels Provos (provos@physnet.uni-hamburg.de).
7 *
8 * The original version of this code was written by John Ioannidis
9 * for BSD/OS in Athens, Greece, in November 1995.
10 *
11 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
12 * by Angelos D. Keromytis.
13 *
14 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
15 * and Niels Provos.
16 *
17 * Additional features in 1999 by Angelos D. Keromytis.
18 *
19 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
20 * Angelos D. Keromytis and Niels Provos.
21 * Copyright (c) 2001, Angelos D. Keromytis.
22 *
23 * Permission to use, copy, and modify this software with or without fee
24 * is hereby granted, provided that this entire notice is included in
25 * all copies of any software which is or includes a copy or
26 * modification of this software.
27 * You may use this code under the GNU public license if you so wish. Please
28 * contribute changes back to the authors under this freer than GPL license
29 * so that we may further the use of strong encryption without limitations to
30 * all.
31 *
32 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
33 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
34 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
35 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
36 * PURPOSE.
37 */
38
39/*
40 * IP-inside-IP processing
41 */
42#include "opt_inet.h"
43#include "opt_inet6.h"
44#include "opt_enc.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/mbuf.h>
49#include <sys/socket.h>
50#include <sys/kernel.h>
51#include <sys/protosw.h>
52#include <sys/sysctl.h>
53
54#include <net/if.h>
55#include <net/pfil.h>
56#include <net/route.h>
57#include <net/netisr.h>
58#include <net/vnet.h>
59
60#include <netinet/in.h>
61#include <netinet/in_systm.h>
62#include <netinet/in_var.h>
63#include <netinet/ip.h>
64#include <netinet/ip_ecn.h>
65#include <netinet/ip_var.h>
66#include <netinet/ip_encap.h>
67#ifdef MROUTING
68#include <netinet/ip_mroute.h>
69#endif
70
71#include <netipsec/ipsec.h>
72#include <netipsec/xform.h>
73
74#include <netipsec/ipip_var.h>
75
76#ifdef INET6
77#include <netinet/ip6.h>
78#include <netipsec/ipsec6.h>
79#include <netinet6/ip6_ecn.h>
80#include <netinet6/in6_var.h>
81#include <netinet6/ip6protosw.h>
82#endif
83
84#include <netipsec/key.h>
85#include <netipsec/key_debug.h>
86
87#include <machine/stdarg.h>
88
89/*
90 * We can control the acceptance of IP4 packets by altering the sysctl
91 * net.inet.ipip.allow value.  Zero means drop them, all else is acceptance.
92 */
93VNET_DEFINE(int, ipip_allow) = 0;
94VNET_PCPUSTAT_DEFINE(struct ipipstat, ipipstat);
95VNET_PCPUSTAT_SYSINIT(ipipstat);
96
97#ifdef VIMAGE
98VNET_PCPUSTAT_SYSUNINIT(ipipstat);
99#endif /* VIMAGE */
100
101SYSCTL_DECL(_net_inet_ipip);
102SYSCTL_VNET_INT(_net_inet_ipip, OID_AUTO,
103	ipip_allow,	CTLFLAG_RW,	&VNET_NAME(ipip_allow),	0, "");
104SYSCTL_VNET_PCPUSTAT(_net_inet_ipip, IPSECCTL_STATS, stats,
105    struct ipipstat, ipipstat,
106    "IPIP statistics (struct ipipstat, netipsec/ipip_var.h)");
107
108/* XXX IPCOMP */
109#define	M_IPSEC	(M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED)
110
111static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp);
112
113#ifdef INET6
114/*
115 * Really only a wrapper for ipip_input(), for use with IPv6.
116 */
117int
118ip4_input6(struct mbuf **m, int *offp, int proto)
119{
120#if 0
121	/* If we do not accept IP-in-IP explicitly, drop.  */
122	if (!V_ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) {
123		DPRINTF(("%s: dropped due to policy\n", __func__));
124		IPIPSTAT_INC(ipips_pdrops);
125		m_freem(*m);
126		return IPPROTO_DONE;
127	}
128#endif
129	_ipip_input(*m, *offp, NULL);
130	return IPPROTO_DONE;
131}
132#endif /* INET6 */
133
134#ifdef INET
135/*
136 * Really only a wrapper for ipip_input(), for use with IPv4.
137 */
138void
139ip4_input(struct mbuf *m, int off)
140{
141#if 0
142	/* If we do not accept IP-in-IP explicitly, drop.  */
143	if (!V_ipip_allow && (m->m_flags & M_IPSEC) == 0) {
144		DPRINTF(("%s: dropped due to policy\n", __func__));
145		IPIPSTAT_INC(ipips_pdrops);
146		m_freem(m);
147		return;
148	}
149#endif
150	_ipip_input(m, off, NULL);
151}
152#endif /* INET */
153
154/*
155 * ipip_input gets called when we receive an IP{46} encapsulated packet,
156 * either because we got it at a real interface, or because AH or ESP
157 * were being used in tunnel mode (in which case the rcvif element will
158 * contain the address of the encX interface associated with the tunnel.
159 */
160
161static void
162_ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
163{
164#ifdef INET
165	register struct sockaddr_in *sin;
166#endif
167	register struct ifnet *ifp;
168	register struct ifaddr *ifa;
169	struct ip *ipo;
170#ifdef INET6
171	register struct sockaddr_in6 *sin6;
172	struct ip6_hdr *ip6 = NULL;
173	u_int8_t itos;
174#endif
175	u_int8_t nxt;
176	int isr;
177	u_int8_t otos;
178	u_int8_t v;
179	int hlen;
180
181	IPIPSTAT_INC(ipips_ipackets);
182
183	m_copydata(m, 0, 1, &v);
184
185	switch (v >> 4) {
186#ifdef INET
187        case 4:
188		hlen = sizeof(struct ip);
189		break;
190#endif /* INET */
191#ifdef INET6
192        case 6:
193		hlen = sizeof(struct ip6_hdr);
194		break;
195#endif
196        default:
197		IPIPSTAT_INC(ipips_family);
198		m_freem(m);
199		return /* EAFNOSUPPORT */;
200	}
201
202	/* Bring the IP header in the first mbuf, if not there already */
203	if (m->m_len < hlen) {
204		if ((m = m_pullup(m, hlen)) == NULL) {
205			DPRINTF(("%s: m_pullup (1) failed\n", __func__));
206			IPIPSTAT_INC(ipips_hdrops);
207			return;
208		}
209	}
210
211	ipo = mtod(m, struct ip *);
212
213#ifdef MROUTING
214	if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) {
215		if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) {
216			ipip_mroute_input (m, iphlen);
217			return;
218		}
219	}
220#endif /* MROUTING */
221
222	/* Keep outer ecn field. */
223	switch (v >> 4) {
224#ifdef INET
225	case 4:
226		otos = ipo->ip_tos;
227		break;
228#endif /* INET */
229#ifdef INET6
230	case 6:
231		otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
232		break;
233#endif
234	default:
235		panic("ipip_input: unknown ip version %u (outer)", v>>4);
236	}
237
238	/* Remove outer IP header */
239	m_adj(m, iphlen);
240
241	/* Sanity check */
242	if (m->m_pkthdr.len < sizeof(struct ip))  {
243		IPIPSTAT_INC(ipips_hdrops);
244		m_freem(m);
245		return;
246	}
247
248	m_copydata(m, 0, 1, &v);
249
250	switch (v >> 4) {
251#ifdef INET
252        case 4:
253		hlen = sizeof(struct ip);
254		break;
255#endif /* INET */
256
257#ifdef INET6
258        case 6:
259		hlen = sizeof(struct ip6_hdr);
260		break;
261#endif
262	default:
263		IPIPSTAT_INC(ipips_family);
264		m_freem(m);
265		return; /* EAFNOSUPPORT */
266	}
267
268	/*
269	 * Bring the inner IP header in the first mbuf, if not there already.
270	 */
271	if (m->m_len < hlen) {
272		if ((m = m_pullup(m, hlen)) == NULL) {
273			DPRINTF(("%s: m_pullup (2) failed\n", __func__));
274			IPIPSTAT_INC(ipips_hdrops);
275			return;
276		}
277	}
278
279	/*
280	 * RFC 1853 specifies that the inner TTL should not be touched on
281	 * decapsulation. There's no reason this comment should be here, but
282	 * this is as good as any a position.
283	 */
284
285	/* Some sanity checks in the inner IP header */
286	switch (v >> 4) {
287#ifdef INET
288    	case 4:
289                ipo = mtod(m, struct ip *);
290                nxt = ipo->ip_p;
291		ip_ecn_egress(V_ip4_ipsec_ecn, &otos, &ipo->ip_tos);
292                break;
293#endif /* INET */
294#ifdef INET6
295    	case 6:
296                ip6 = (struct ip6_hdr *) ipo;
297                nxt = ip6->ip6_nxt;
298		itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
299		ip_ecn_egress(V_ip6_ipsec_ecn, &otos, &itos);
300		ip6->ip6_flow &= ~htonl(0xff << 20);
301		ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
302                break;
303#endif
304	default:
305		panic("ipip_input: unknown ip version %u (inner)", v>>4);
306	}
307
308	/* Check for local address spoofing. */
309	if ((m->m_pkthdr.rcvif == NULL ||
310	    !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
311	    V_ipip_allow != 2) {
312	    	IFNET_RLOCK_NOSLEEP();
313		TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
314			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
315#ifdef INET
316				if (ipo) {
317					if (ifa->ifa_addr->sa_family !=
318					    AF_INET)
319						continue;
320
321					sin = (struct sockaddr_in *) ifa->ifa_addr;
322
323					if (sin->sin_addr.s_addr ==
324					    ipo->ip_src.s_addr)	{
325						IPIPSTAT_INC(ipips_spoof);
326						m_freem(m);
327						IFNET_RUNLOCK_NOSLEEP();
328						return;
329					}
330				}
331#endif /* INET */
332
333#ifdef INET6
334				if (ip6) {
335					if (ifa->ifa_addr->sa_family !=
336					    AF_INET6)
337						continue;
338
339					sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
340
341					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
342						IPIPSTAT_INC(ipips_spoof);
343						m_freem(m);
344						IFNET_RUNLOCK_NOSLEEP();
345						return;
346					}
347
348				}
349#endif /* INET6 */
350			}
351		}
352		IFNET_RUNLOCK_NOSLEEP();
353	}
354
355	/* Statistics */
356	IPIPSTAT_ADD(ipips_ibytes, m->m_pkthdr.len - iphlen);
357
358#ifdef DEV_ENC
359	switch (v >> 4) {
360#ifdef INET
361	case 4:
362		ipsec_bpf(m, NULL, AF_INET, ENC_IN|ENC_AFTER);
363		break;
364#endif
365#ifdef INET6
366	case 6:
367		ipsec_bpf(m, NULL, AF_INET6, ENC_IN|ENC_AFTER);
368		break;
369#endif
370	default:
371		panic("%s: bogus ip version %u", __func__, v>>4);
372	}
373	/* pass the mbuf to enc0 for packet filtering */
374	if (ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER) != 0)
375		return;
376#endif
377
378	/*
379	 * Interface pointer stays the same; if no IPsec processing has
380	 * been done (or will be done), this will point to a normal
381	 * interface. Otherwise, it'll point to an enc interface, which
382	 * will allow a packet filter to distinguish between secure and
383	 * untrusted packets.
384	 */
385
386	switch (v >> 4) {
387#ifdef INET
388	case 4:
389		isr = NETISR_IP;
390		break;
391#endif
392#ifdef INET6
393	case 6:
394		isr = NETISR_IPV6;
395		break;
396#endif
397	default:
398		panic("%s: bogus ip version %u", __func__, v>>4);
399	}
400
401	if (netisr_queue(isr, m)) {	/* (0) on success. */
402		IPIPSTAT_INC(ipips_qfull);
403		DPRINTF(("%s: packet dropped because of full queue\n",
404			__func__));
405	}
406}
407
408int
409ipip_output(
410	struct mbuf *m,
411	struct ipsecrequest *isr,
412	struct mbuf **mp,
413	int skip,
414	int protoff
415)
416{
417	struct secasvar *sav;
418	u_int8_t tp, otos;
419	struct secasindex *saidx;
420	int error;
421#if defined(INET) || defined(INET6)
422	u_int8_t itos;
423#endif
424#ifdef INET
425	struct ip *ipo;
426#endif /* INET */
427#ifdef INET6
428	struct ip6_hdr *ip6, *ip6o;
429#endif /* INET6 */
430
431	sav = isr->sav;
432	IPSEC_ASSERT(sav != NULL, ("null SA"));
433	IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
434
435	/* XXX Deal with empty TDB source/destination addresses. */
436
437	m_copydata(m, 0, 1, &tp);
438	tp = (tp >> 4) & 0xff;  /* Get the IP version number. */
439
440	saidx = &sav->sah->saidx;
441	switch (saidx->dst.sa.sa_family) {
442#ifdef INET
443	case AF_INET:
444		if (saidx->src.sa.sa_family != AF_INET ||
445		    saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
446		    saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) {
447			DPRINTF(("%s: unspecified tunnel endpoint "
448			    "address in SA %s/%08lx\n", __func__,
449			    ipsec_address(&saidx->dst),
450			    (u_long) ntohl(sav->spi)));
451			IPIPSTAT_INC(ipips_unspec);
452			error = EINVAL;
453			goto bad;
454		}
455
456		M_PREPEND(m, sizeof(struct ip), M_NOWAIT);
457		if (m == 0) {
458			DPRINTF(("%s: M_PREPEND failed\n", __func__));
459			IPIPSTAT_INC(ipips_hdrops);
460			error = ENOBUFS;
461			goto bad;
462		}
463
464		ipo = mtod(m, struct ip *);
465
466		ipo->ip_v = IPVERSION;
467		ipo->ip_hl = 5;
468		ipo->ip_len = htons(m->m_pkthdr.len);
469		ipo->ip_ttl = V_ip_defttl;
470		ipo->ip_sum = 0;
471		ipo->ip_src = saidx->src.sin.sin_addr;
472		ipo->ip_dst = saidx->dst.sin.sin_addr;
473
474		ipo->ip_id = ip_newid();
475
476		/* If the inner protocol is IP... */
477		switch (tp) {
478		case IPVERSION:
479			/* Save ECN notification */
480			m_copydata(m, sizeof(struct ip) +
481			    offsetof(struct ip, ip_tos),
482			    sizeof(u_int8_t), (caddr_t) &itos);
483
484			ipo->ip_p = IPPROTO_IPIP;
485
486			/*
487			 * We should be keeping tunnel soft-state and
488			 * send back ICMPs if needed.
489			 */
490			m_copydata(m, sizeof(struct ip) +
491			    offsetof(struct ip, ip_off),
492			    sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
493			ipo->ip_off = ntohs(ipo->ip_off);
494			ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
495			ipo->ip_off = htons(ipo->ip_off);
496			break;
497#ifdef INET6
498		case (IPV6_VERSION >> 4):
499		{
500			u_int32_t itos32;
501
502			/* Save ECN notification. */
503			m_copydata(m, sizeof(struct ip) +
504			    offsetof(struct ip6_hdr, ip6_flow),
505			    sizeof(u_int32_t), (caddr_t) &itos32);
506			itos = ntohl(itos32) >> 20;
507			ipo->ip_p = IPPROTO_IPV6;
508			ipo->ip_off = 0;
509			break;
510		}
511#endif /* INET6 */
512		default:
513			goto nofamily;
514		}
515
516		otos = 0;
517		ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
518		ipo->ip_tos = otos;
519		break;
520#endif /* INET */
521
522#ifdef INET6
523	case AF_INET6:
524		if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) ||
525		    saidx->src.sa.sa_family != AF_INET6 ||
526		    IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) {
527			DPRINTF(("%s: unspecified tunnel endpoint "
528			    "address in SA %s/%08lx\n", __func__,
529			    ipsec_address(&saidx->dst),
530			    (u_long) ntohl(sav->spi)));
531			IPIPSTAT_INC(ipips_unspec);
532			error = ENOBUFS;
533			goto bad;
534		}
535
536		/* scoped address handling */
537		ip6 = mtod(m, struct ip6_hdr *);
538		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
539			ip6->ip6_src.s6_addr16[1] = 0;
540		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
541			ip6->ip6_dst.s6_addr16[1] = 0;
542
543		M_PREPEND(m, sizeof(struct ip6_hdr), M_NOWAIT);
544		if (m == 0) {
545			DPRINTF(("%s: M_PREPEND failed\n", __func__));
546			IPIPSTAT_INC(ipips_hdrops);
547			error = ENOBUFS;
548			goto bad;
549		}
550
551		/* Initialize IPv6 header */
552		ip6o = mtod(m, struct ip6_hdr *);
553		ip6o->ip6_flow = 0;
554		ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
555		ip6o->ip6_vfc |= IPV6_VERSION;
556		ip6o->ip6_plen = htons(m->m_pkthdr.len);
557		ip6o->ip6_hlim = V_ip_defttl;
558		ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
559		ip6o->ip6_src = saidx->src.sin6.sin6_addr;
560
561		switch (tp) {
562#ifdef INET
563		case IPVERSION:
564			/* Save ECN notification */
565			m_copydata(m, sizeof(struct ip6_hdr) +
566			    offsetof(struct ip, ip_tos), sizeof(u_int8_t),
567			    (caddr_t) &itos);
568
569			/* This is really IPVERSION. */
570			ip6o->ip6_nxt = IPPROTO_IPIP;
571			break;
572#endif /* INET */
573		case (IPV6_VERSION >> 4):
574		{
575			u_int32_t itos32;
576
577			/* Save ECN notification. */
578			m_copydata(m, sizeof(struct ip6_hdr) +
579			    offsetof(struct ip6_hdr, ip6_flow),
580			    sizeof(u_int32_t), (caddr_t) &itos32);
581			itos = ntohl(itos32) >> 20;
582
583			ip6o->ip6_nxt = IPPROTO_IPV6;
584			break;
585		}
586		default:
587			goto nofamily;
588		}
589
590		otos = 0;
591		ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
592		ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
593		break;
594#endif /* INET6 */
595
596	default:
597nofamily:
598		DPRINTF(("%s: unsupported protocol family %u\n", __func__,
599		    saidx->dst.sa.sa_family));
600		IPIPSTAT_INC(ipips_family);
601		error = EAFNOSUPPORT;		/* XXX diffs from openbsd */
602		goto bad;
603	}
604
605	IPIPSTAT_INC(ipips_opackets);
606	*mp = m;
607
608#ifdef INET
609	if (saidx->dst.sa.sa_family == AF_INET) {
610#if 0
611		if (sav->tdb_xform->xf_type == XF_IP4)
612			tdb->tdb_cur_bytes +=
613			    m->m_pkthdr.len - sizeof(struct ip);
614#endif
615		IPIPSTAT_ADD(ipips_obytes,
616		    m->m_pkthdr.len - sizeof(struct ip));
617	}
618#endif /* INET */
619
620#ifdef INET6
621	if (saidx->dst.sa.sa_family == AF_INET6) {
622#if 0
623		if (sav->tdb_xform->xf_type == XF_IP4)
624			tdb->tdb_cur_bytes +=
625			    m->m_pkthdr.len - sizeof(struct ip6_hdr);
626#endif
627		IPIPSTAT_ADD(ipips_obytes,
628		    m->m_pkthdr.len - sizeof(struct ip6_hdr));
629	}
630#endif /* INET6 */
631
632	return 0;
633bad:
634	if (m)
635		m_freem(m);
636	*mp = NULL;
637	return (error);
638}
639
640#ifdef IPSEC
641#if defined(INET) || defined(INET6)
642static int
643ipe4_init(struct secasvar *sav, struct xformsw *xsp)
644{
645	sav->tdb_xform = xsp;
646	return 0;
647}
648
649static int
650ipe4_zeroize(struct secasvar *sav)
651{
652	sav->tdb_xform = NULL;
653	return 0;
654}
655
656static int
657ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
658{
659	/* This is a rather serious mistake, so no conditional printing. */
660	printf("%s: should never be called\n", __func__);
661	if (m)
662		m_freem(m);
663	return EOPNOTSUPP;
664}
665
666static struct xformsw ipe4_xformsw = {
667	XF_IP4,		0,		"IPv4 Simple Encapsulation",
668	ipe4_init,	ipe4_zeroize,	ipe4_input,	ipip_output,
669};
670
671extern struct domain inetdomain;
672#endif /* INET || INET6 */
673#ifdef INET
674static struct protosw ipe4_protosw = {
675	.pr_type =	SOCK_RAW,
676	.pr_domain =	&inetdomain,
677	.pr_protocol =	IPPROTO_IPV4,
678	.pr_flags =	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
679	.pr_input =	ip4_input,
680	.pr_ctloutput =	rip_ctloutput,
681	.pr_usrreqs =	&rip_usrreqs
682};
683#endif /* INET */
684#if defined(INET6) && defined(INET)
685static struct ip6protosw ipe6_protosw = {
686	.pr_type =	SOCK_RAW,
687	.pr_domain =	&inetdomain,
688	.pr_protocol =	IPPROTO_IPV6,
689	.pr_flags =	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
690	.pr_input =	ip4_input6,
691	.pr_ctloutput =	rip_ctloutput,
692	.pr_usrreqs =	&rip_usrreqs
693};
694#endif /* INET6 && INET */
695
696#ifdef INET
697/*
698 * Check the encapsulated packet to see if we want it
699 */
700static int
701ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
702{
703	/*
704	 * Only take packets coming from IPSEC tunnels; the rest
705	 * must be handled by the gif tunnel code.  Note that we
706	 * also return a minimum priority when we want the packet
707	 * so any explicit gif tunnels take precedence.
708	 */
709	return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0);
710}
711#endif /* INET */
712
713static void
714ipe4_attach(void)
715{
716
717	xform_register(&ipe4_xformsw);
718	/* attach to encapsulation framework */
719	/* XXX save return cookie for detach on module remove */
720#ifdef INET
721	(void) encap_attach_func(AF_INET, -1,
722		ipe4_encapcheck, &ipe4_protosw, NULL);
723#endif
724#if defined(INET6) && defined(INET)
725	(void) encap_attach_func(AF_INET6, -1,
726		ipe4_encapcheck, (struct protosw *)&ipe6_protosw, NULL);
727#endif
728}
729SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
730#endif	/* IPSEC */
731