xref: /netbsd-src/sys/netinet/ip_encap.c (revision 212397c69a103ae7e5eafa8731ddfae671d2dee7)
1 /*	$NetBSD: ip_encap.c,v 1.51 2016/01/26 05:58:05 knakahara Exp $	*/
2 /*	$KAME: ip_encap.c,v 1.73 2001/10/02 08:30:58 itojun Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 /*
33  * My grandfather said that there's a devil inside tunnelling technology...
34  *
35  * We have surprisingly many protocols that want packets with IP protocol
36  * #4 or #41.  Here's a list of protocols that want protocol #41:
37  *	RFC1933 configured tunnel
38  *	RFC1933 automatic tunnel
39  *	RFC2401 IPsec tunnel
40  *	RFC2473 IPv6 generic packet tunnelling
41  *	RFC2529 6over4 tunnel
42  *	RFC3056 6to4 tunnel
43  *	isatap tunnel
44  *	mobile-ip6 (uses RFC2473)
45  * Here's a list of protocol that want protocol #4:
46  *	RFC1853 IPv4-in-IPv4 tunnelling
47  *	RFC2003 IPv4 encapsulation within IPv4
48  *	RFC2344 reverse tunnelling for mobile-ip4
49  *	RFC2401 IPsec tunnel
50  * Well, what can I say.  They impose different en/decapsulation mechanism
51  * from each other, so they need separate protocol handler.  The only one
52  * we can easily determine by protocol # is IPsec, which always has
53  * AH/ESP/IPComp header right after outer IP header.
54  *
55  * So, clearly good old protosw does not work for protocol #4 and #41.
56  * The code will let you match protocol via src/dst address pair.
57  */
58 /* XXX is M_NETADDR correct? */
59 
60 /*
61  * The code will use radix table for tunnel lookup, for
62  * tunnels registered with encap_attach() with a addr/mask pair.
63  * Faster on machines with thousands of tunnel registerations (= interfaces).
64  *
65  * The code assumes that radix table code can handle non-continuous netmask,
66  * as it will pass radix table memory region with (src + dst) sockaddr pair.
67  */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.51 2016/01/26 05:58:05 knakahara Exp $");
71 
72 #ifdef _KERNEL_OPT
73 #include "opt_mrouting.h"
74 #include "opt_inet.h"
75 #endif
76 
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/socket.h>
80 #include <sys/sockio.h>
81 #include <sys/mbuf.h>
82 #include <sys/errno.h>
83 #include <sys/queue.h>
84 #include <sys/kmem.h>
85 
86 #include <net/if.h>
87 #include <net/route.h>
88 
89 #include <netinet/in.h>
90 #include <netinet/in_systm.h>
91 #include <netinet/ip.h>
92 #include <netinet/ip_var.h>
93 #include <netinet/ip_encap.h>
94 #ifdef MROUTING
95 #include <netinet/ip_mroute.h>
96 #endif /* MROUTING */
97 
98 #ifdef INET6
99 #include <netinet/ip6.h>
100 #include <netinet6/ip6_var.h>
101 #include <netinet6/ip6protosw.h> /* for struct ip6ctlparam */
102 #include <netinet6/in6_var.h>
103 #include <netinet6/in6_pcb.h>
104 #include <netinet/icmp6.h>
105 #endif
106 
107 #include <net/net_osdep.h>
108 
109 enum direction { INBOUND, OUTBOUND };
110 
111 #ifdef INET
112 static struct encaptab *encap4_lookup(struct mbuf *, int, int, enum direction);
113 #endif
114 #ifdef INET6
115 static struct encaptab *encap6_lookup(struct mbuf *, int, int, enum direction);
116 #endif
117 static int encap_add(struct encaptab *);
118 static int encap_remove(struct encaptab *);
119 static int encap_afcheck(int, const struct sockaddr *, const struct sockaddr *);
120 static struct radix_node_head *encap_rnh(int);
121 static int mask_matchlen(const struct sockaddr *);
122 static void encap_fillarg(struct mbuf *, const struct encaptab *);
123 
124 LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab);
125 
126 struct radix_node_head *encap_head[2];	/* 0 for AF_INET, 1 for AF_INET6 */
127 
128 void
129 encap_init(void)
130 {
131 	static int initialized = 0;
132 
133 	if (initialized)
134 		return;
135 	initialized++;
136 #if 0
137 	/*
138 	 * we cannot use LIST_INIT() here, since drivers may want to call
139 	 * encap_attach(), on driver attach.  encap_init() will be called
140 	 * on AF_INET{,6} initialization, which happens after driver
141 	 * initialization - using LIST_INIT() here can nuke encap_attach()
142 	 * from drivers.
143 	 */
144 	LIST_INIT(&encaptab);
145 #endif
146 
147 	/*
148 	 * initialize radix lookup table when the radix subsystem is inited.
149 	 */
150 	rn_delayedinit((void *)&encap_head[0],
151 	    sizeof(struct sockaddr_pack) << 3);
152 #ifdef INET6
153 	rn_delayedinit((void *)&encap_head[1],
154 	    sizeof(struct sockaddr_pack) << 3);
155 #endif
156 }
157 
158 #ifdef INET
159 static struct encaptab *
160 encap4_lookup(struct mbuf *m, int off, int proto, enum direction dir)
161 {
162 	struct ip *ip;
163 	struct ip_pack4 pack;
164 	struct encaptab *ep, *match;
165 	int prio, matchprio;
166 	struct radix_node_head *rnh = encap_rnh(AF_INET);
167 	struct radix_node *rn;
168 
169 	KASSERT(m->m_len >= sizeof(*ip));
170 
171 	ip = mtod(m, struct ip *);
172 
173 	memset(&pack, 0, sizeof(pack));
174 	pack.p.sp_len = sizeof(pack);
175 	pack.mine.sin_family = pack.yours.sin_family = AF_INET;
176 	pack.mine.sin_len = pack.yours.sin_len = sizeof(struct sockaddr_in);
177 	if (dir == INBOUND) {
178 		pack.mine.sin_addr = ip->ip_dst;
179 		pack.yours.sin_addr = ip->ip_src;
180 	} else {
181 		pack.mine.sin_addr = ip->ip_src;
182 		pack.yours.sin_addr = ip->ip_dst;
183 	}
184 
185 	match = NULL;
186 	matchprio = 0;
187 
188 	rn = rnh->rnh_matchaddr((void *)&pack, rnh);
189 	if (rn && (rn->rn_flags & RNF_ROOT) == 0) {
190 		match = (struct encaptab *)rn;
191 		matchprio = mask_matchlen(match->srcmask) +
192 		    mask_matchlen(match->dstmask);
193 	}
194 
195 	LIST_FOREACH(ep, &encaptab, chain) {
196 		if (ep->af != AF_INET)
197 			continue;
198 		if (ep->proto >= 0 && ep->proto != proto)
199 			continue;
200 		if (ep->func)
201 			prio = (*ep->func)(m, off, proto, ep->arg);
202 		else
203 			continue;
204 
205 		/*
206 		 * We prioritize the matches by using bit length of the
207 		 * matches.  mask_match() and user-supplied matching function
208 		 * should return the bit length of the matches (for example,
209 		 * if both src/dst are matched for IPv4, 64 should be returned).
210 		 * 0 or negative return value means "it did not match".
211 		 *
212 		 * The question is, since we have two "mask" portion, we
213 		 * cannot really define total order between entries.
214 		 * For example, which of these should be preferred?
215 		 * mask_match() returns 48 (32 + 16) for both of them.
216 		 *	src=3ffe::/16, dst=3ffe:501::/32
217 		 *	src=3ffe:501::/32, dst=3ffe::/16
218 		 *
219 		 * We need to loop through all the possible candidates
220 		 * to get the best match - the search takes O(n) for
221 		 * n attachments (i.e. interfaces).
222 		 *
223 		 * For radix-based lookup, I guess source takes precedence.
224 		 * See rn_{refines,lexobetter} for the correct answer.
225 		 */
226 		if (prio <= 0)
227 			continue;
228 		if (prio > matchprio) {
229 			matchprio = prio;
230 			match = ep;
231 		}
232 	}
233 
234 	return match;
235 }
236 
237 void
238 encap4_input(struct mbuf *m, ...)
239 {
240 	int off, proto;
241 	va_list ap;
242 	const struct encapsw *esw;
243 	struct encaptab *match;
244 
245 	va_start(ap, m);
246 	off = va_arg(ap, int);
247 	proto = va_arg(ap, int);
248 	va_end(ap);
249 
250 	match = encap4_lookup(m, off, proto, INBOUND);
251 
252 	if (match) {
253 		/* found a match, "match" has the best one */
254 		esw = match->esw;
255 		if (esw && esw->encapsw4.pr_input) {
256 			encap_fillarg(m, match);
257 			(*esw->encapsw4.pr_input)(m, off, proto);
258 		} else
259 			m_freem(m);
260 		return;
261 	}
262 
263 	/* last resort: inject to raw socket */
264 	rip_input(m, off, proto);
265 }
266 #endif
267 
268 #ifdef INET6
269 static struct encaptab *
270 encap6_lookup(struct mbuf *m, int off, int proto, enum direction dir)
271 {
272 	struct ip6_hdr *ip6;
273 	struct ip_pack6 pack;
274 	int prio, matchprio;
275 	struct encaptab *ep, *match;
276 	struct radix_node_head *rnh = encap_rnh(AF_INET6);
277 	struct radix_node *rn;
278 
279 	KASSERT(m->m_len >= sizeof(*ip6));
280 
281 	ip6 = mtod(m, struct ip6_hdr *);
282 
283 	memset(&pack, 0, sizeof(pack));
284 	pack.p.sp_len = sizeof(pack);
285 	pack.mine.sin6_family = pack.yours.sin6_family = AF_INET6;
286 	pack.mine.sin6_len = pack.yours.sin6_len = sizeof(struct sockaddr_in6);
287 	if (dir == INBOUND) {
288 		pack.mine.sin6_addr = ip6->ip6_dst;
289 		pack.yours.sin6_addr = ip6->ip6_src;
290 	} else {
291 		pack.mine.sin6_addr = ip6->ip6_src;
292 		pack.yours.sin6_addr = ip6->ip6_dst;
293 	}
294 
295 	match = NULL;
296 	matchprio = 0;
297 
298 	rn = rnh->rnh_matchaddr((void *)&pack, rnh);
299 	if (rn && (rn->rn_flags & RNF_ROOT) == 0) {
300 		match = (struct encaptab *)rn;
301 		matchprio = mask_matchlen(match->srcmask) +
302 		    mask_matchlen(match->dstmask);
303 	}
304 
305 	LIST_FOREACH(ep, &encaptab, chain) {
306 		if (ep->af != AF_INET6)
307 			continue;
308 		if (ep->proto >= 0 && ep->proto != proto)
309 			continue;
310 		if (ep->func)
311 			prio = (*ep->func)(m, off, proto, ep->arg);
312 		else
313 			continue;
314 
315 		/* see encap4_lookup() for issues here */
316 		if (prio <= 0)
317 			continue;
318 		if (prio > matchprio) {
319 			matchprio = prio;
320 			match = ep;
321 		}
322 	}
323 
324 	return match;
325 }
326 
327 int
328 encap6_input(struct mbuf **mp, int *offp, int proto)
329 {
330 	struct mbuf *m = *mp;
331 	const struct encapsw *esw;
332 	struct encaptab *match;
333 
334 	match = encap6_lookup(m, *offp, proto, INBOUND);
335 
336 	if (match) {
337 		/* found a match */
338 		esw = match->esw;
339 		if (esw && esw->encapsw6.pr_input) {
340 			encap_fillarg(m, match);
341 			return (*esw->encapsw6.pr_input)(mp, offp, proto);
342 		} else {
343 			m_freem(m);
344 			return IPPROTO_DONE;
345 		}
346 	}
347 
348 	/* last resort: inject to raw socket */
349 	return rip6_input(mp, offp, proto);
350 }
351 #endif
352 
353 static int
354 encap_add(struct encaptab *ep)
355 {
356 	struct radix_node_head *rnh = encap_rnh(ep->af);
357 	int error = 0;
358 
359 	LIST_INSERT_HEAD(&encaptab, ep, chain);
360 	if (!ep->func && rnh) {
361 		if (!rnh->rnh_addaddr((void *)ep->addrpack,
362 		    (void *)ep->maskpack, rnh, ep->nodes)) {
363 			error = EEXIST;
364 			goto fail;
365 		}
366 	}
367 	return error;
368 
369  fail:
370 	LIST_REMOVE(ep, chain);
371 	return error;
372 }
373 
374 static int
375 encap_remove(struct encaptab *ep)
376 {
377 	struct radix_node_head *rnh = encap_rnh(ep->af);
378 	int error = 0;
379 
380 	LIST_REMOVE(ep, chain);
381 	if (!ep->func && rnh) {
382 		if (!rnh->rnh_deladdr((void *)ep->addrpack,
383 		    (void *)ep->maskpack, rnh))
384 			error = ESRCH;
385 	}
386 	return error;
387 }
388 
389 static int
390 encap_afcheck(int af, const struct sockaddr *sp, const struct sockaddr *dp)
391 {
392 	if (sp && dp) {
393 		if (sp->sa_len != dp->sa_len)
394 			return EINVAL;
395 		if (af != sp->sa_family || af != dp->sa_family)
396 			return EINVAL;
397 	} else if (!sp && !dp)
398 		;
399 	else
400 		return EINVAL;
401 
402 	switch (af) {
403 	case AF_INET:
404 		if (sp && sp->sa_len != sizeof(struct sockaddr_in))
405 			return EINVAL;
406 		if (dp && dp->sa_len != sizeof(struct sockaddr_in))
407 			return EINVAL;
408 		break;
409 #ifdef INET6
410 	case AF_INET6:
411 		if (sp && sp->sa_len != sizeof(struct sockaddr_in6))
412 			return EINVAL;
413 		if (dp && dp->sa_len != sizeof(struct sockaddr_in6))
414 			return EINVAL;
415 		break;
416 #endif
417 	default:
418 		return EAFNOSUPPORT;
419 	}
420 
421 	return 0;
422 }
423 
424 /*
425  * sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
426  * length of mask (sm and dm) is assumed to be same as sp/dp.
427  * Return value will be necessary as input (cookie) for encap_detach().
428  */
429 const struct encaptab *
430 encap_attach(int af, int proto,
431     const struct sockaddr *sp, const struct sockaddr *sm,
432     const struct sockaddr *dp, const struct sockaddr *dm,
433     const struct encapsw *esw, void *arg)
434 {
435 	struct encaptab *ep;
436 	int error;
437 	int s;
438 	size_t l;
439 	struct ip_pack4 *pack4;
440 #ifdef INET6
441 	struct ip_pack6 *pack6;
442 #endif
443 
444 	s = splsoftnet();
445 	/* sanity check on args */
446 	error = encap_afcheck(af, sp, dp);
447 	if (error)
448 		goto fail;
449 
450 	/* check if anyone have already attached with exactly same config */
451 	LIST_FOREACH(ep, &encaptab, chain) {
452 		if (ep->af != af)
453 			continue;
454 		if (ep->proto != proto)
455 			continue;
456 		if (ep->func)
457 			continue;
458 
459 		KASSERT(ep->src != NULL);
460 		KASSERT(ep->dst != NULL);
461 		KASSERT(ep->srcmask != NULL);
462 		KASSERT(ep->dstmask != NULL);
463 
464 		if (ep->src->sa_len != sp->sa_len ||
465 		    memcmp(ep->src, sp, sp->sa_len) != 0 ||
466 		    memcmp(ep->srcmask, sm, sp->sa_len) != 0)
467 			continue;
468 		if (ep->dst->sa_len != dp->sa_len ||
469 		    memcmp(ep->dst, dp, dp->sa_len) != 0 ||
470 		    memcmp(ep->dstmask, dm, dp->sa_len) != 0)
471 			continue;
472 
473 		error = EEXIST;
474 		goto fail;
475 	}
476 
477 	switch (af) {
478 	case AF_INET:
479 		l = sizeof(*pack4);
480 		break;
481 #ifdef INET6
482 	case AF_INET6:
483 		l = sizeof(*pack6);
484 		break;
485 #endif
486 	default:
487 		goto fail;
488 	}
489 
490 	/* M_NETADDR ok? */
491 	ep = kmem_zalloc(sizeof(*ep), KM_NOSLEEP);
492 	if (ep == NULL) {
493 		error = ENOBUFS;
494 		goto fail;
495 	}
496 	ep->addrpack = kmem_zalloc(l, KM_NOSLEEP);
497 	if (ep->addrpack == NULL) {
498 		error = ENOBUFS;
499 		goto gc;
500 	}
501 	ep->maskpack = kmem_zalloc(l, KM_NOSLEEP);
502 	if (ep->maskpack == NULL) {
503 		error = ENOBUFS;
504 		goto gc;
505 	}
506 
507 	ep->af = af;
508 	ep->proto = proto;
509 	ep->addrpack->sa_len = l & 0xff;
510 	ep->maskpack->sa_len = l & 0xff;
511 	switch (af) {
512 	case AF_INET:
513 		pack4 = (struct ip_pack4 *)ep->addrpack;
514 		ep->src = (struct sockaddr *)&pack4->mine;
515 		ep->dst = (struct sockaddr *)&pack4->yours;
516 		pack4 = (struct ip_pack4 *)ep->maskpack;
517 		ep->srcmask = (struct sockaddr *)&pack4->mine;
518 		ep->dstmask = (struct sockaddr *)&pack4->yours;
519 		break;
520 #ifdef INET6
521 	case AF_INET6:
522 		pack6 = (struct ip_pack6 *)ep->addrpack;
523 		ep->src = (struct sockaddr *)&pack6->mine;
524 		ep->dst = (struct sockaddr *)&pack6->yours;
525 		pack6 = (struct ip_pack6 *)ep->maskpack;
526 		ep->srcmask = (struct sockaddr *)&pack6->mine;
527 		ep->dstmask = (struct sockaddr *)&pack6->yours;
528 		break;
529 #endif
530 	}
531 
532 	memcpy(ep->src, sp, sp->sa_len);
533 	memcpy(ep->srcmask, sm, sp->sa_len);
534 	memcpy(ep->dst, dp, dp->sa_len);
535 	memcpy(ep->dstmask, dm, dp->sa_len);
536 	ep->esw = esw;
537 	ep->arg = arg;
538 
539 	error = encap_add(ep);
540 	if (error)
541 		goto gc;
542 
543 	error = 0;
544 	splx(s);
545 	return ep;
546 
547 gc:
548 	if (ep->addrpack)
549 		kmem_free(ep->addrpack, l);
550 	if (ep->maskpack)
551 		kmem_free(ep->maskpack, l);
552 	if (ep)
553 		kmem_free(ep, sizeof(*ep));
554 fail:
555 	splx(s);
556 	return NULL;
557 }
558 
559 const struct encaptab *
560 encap_attach_func(int af, int proto,
561     int (*func)(struct mbuf *, int, int, void *),
562     const struct encapsw *esw, void *arg)
563 {
564 	struct encaptab *ep;
565 	int error;
566 	int s;
567 
568 	s = splsoftnet();
569 	/* sanity check on args */
570 	if (!func) {
571 		error = EINVAL;
572 		goto fail;
573 	}
574 
575 	error = encap_afcheck(af, NULL, NULL);
576 	if (error)
577 		goto fail;
578 
579 	ep = kmem_alloc(sizeof(*ep), KM_NOSLEEP);	/*XXX*/
580 	if (ep == NULL) {
581 		error = ENOBUFS;
582 		goto fail;
583 	}
584 	memset(ep, 0, sizeof(*ep));
585 
586 	ep->af = af;
587 	ep->proto = proto;
588 	ep->func = func;
589 	ep->esw = esw;
590 	ep->arg = arg;
591 
592 	error = encap_add(ep);
593 	if (error)
594 		goto fail;
595 
596 	error = 0;
597 	splx(s);
598 	return ep;
599 
600 fail:
601 	splx(s);
602 	return NULL;
603 }
604 
605 /* XXX encap4_ctlinput() is necessary if we set DF=1 on outer IPv4 header */
606 
607 #ifdef INET6
608 void *
609 encap6_ctlinput(int cmd, const struct sockaddr *sa, void *d0)
610 {
611 	void *d = d0;
612 	struct ip6_hdr *ip6;
613 	struct mbuf *m;
614 	int off;
615 	struct ip6ctlparam *ip6cp = NULL;
616 	int nxt;
617 	struct encaptab *ep;
618 	const struct encapsw *esw;
619 
620 	if (sa->sa_family != AF_INET6 ||
621 	    sa->sa_len != sizeof(struct sockaddr_in6))
622 		return NULL;
623 
624 	if ((unsigned)cmd >= PRC_NCMDS)
625 		return NULL;
626 	if (cmd == PRC_HOSTDEAD)
627 		d = NULL;
628 	else if (cmd == PRC_MSGSIZE)
629 		; /* special code is present, see below */
630 	else if (inet6ctlerrmap[cmd] == 0)
631 		return NULL;
632 
633 	/* if the parameter is from icmp6, decode it. */
634 	if (d != NULL) {
635 		ip6cp = (struct ip6ctlparam *)d;
636 		m = ip6cp->ip6c_m;
637 		ip6 = ip6cp->ip6c_ip6;
638 		off = ip6cp->ip6c_off;
639 		nxt = ip6cp->ip6c_nxt;
640 
641 		if (ip6 && cmd == PRC_MSGSIZE) {
642 			int valid = 0;
643 			struct encaptab *match;
644 
645 			/*
646 		 	* Check to see if we have a valid encap configuration.
647 		 	*/
648 			match = encap6_lookup(m, off, nxt, OUTBOUND);
649 			if (match)
650 				valid++;
651 
652 			/*
653 		 	* Depending on the value of "valid" and routing table
654 		 	* size (mtudisc_{hi,lo}wat), we will:
655 		 	* - recalcurate the new MTU and create the
656 		 	*   corresponding routing entry, or
657 		 	* - ignore the MTU change notification.
658 		 	*/
659 			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
660 		}
661 	} else {
662 		m = NULL;
663 		ip6 = NULL;
664 		nxt = -1;
665 	}
666 
667 	/* inform all listeners */
668 	LIST_FOREACH(ep, &encaptab, chain) {
669 		if (ep->af != AF_INET6)
670 			continue;
671 		if (ep->proto >= 0 && ep->proto != nxt)
672 			continue;
673 
674 		/* should optimize by looking at address pairs */
675 
676 		/* XXX need to pass ep->arg or ep itself to listeners */
677 		esw = ep->esw;
678 		if (esw && esw->encapsw6.pr_ctlinput) {
679 			(*esw->encapsw6.pr_ctlinput)(cmd, sa, d);
680 		}
681 	}
682 
683 	rip6_ctlinput(cmd, sa, d0);
684 	return NULL;
685 }
686 #endif
687 
688 int
689 encap_detach(const struct encaptab *cookie)
690 {
691 	const struct encaptab *ep = cookie;
692 	struct encaptab *p, *np;
693 	int error;
694 
695 	LIST_FOREACH_SAFE(p, &encaptab, chain, np) {
696 		if (p == ep) {
697 			error = encap_remove(p);
698 			if (error)
699 				return error;
700 			if (!ep->func) {
701 				kmem_free(p->addrpack, ep->addrpack->sa_len);
702 				kmem_free(p->maskpack, ep->maskpack->sa_len);
703 			}
704 			kmem_free(p, sizeof(*p));	/*XXX*/
705 			return 0;
706 		}
707 	}
708 
709 	return ENOENT;
710 }
711 
712 static struct radix_node_head *
713 encap_rnh(int af)
714 {
715 
716 	switch (af) {
717 	case AF_INET:
718 		return encap_head[0];
719 #ifdef INET6
720 	case AF_INET6:
721 		return encap_head[1];
722 #endif
723 	default:
724 		return NULL;
725 	}
726 }
727 
728 static int
729 mask_matchlen(const struct sockaddr *sa)
730 {
731 	const char *p, *ep;
732 	int l;
733 
734 	p = (const char *)sa;
735 	ep = p + sa->sa_len;
736 	p += 2;	/* sa_len + sa_family */
737 
738 	l = 0;
739 	while (p < ep) {
740 		l += (*p ? 8 : 0);	/* estimate */
741 		p++;
742 	}
743 	return l;
744 }
745 
746 static void
747 encap_fillarg(struct mbuf *m, const struct encaptab *ep)
748 {
749 	struct m_tag *mtag;
750 
751 	mtag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT);
752 	if (mtag) {
753 		*(void **)(mtag + 1) = ep->arg;
754 		m_tag_prepend(m, mtag);
755 	}
756 }
757 
758 void *
759 encap_getarg(struct mbuf *m)
760 {
761 	void *p;
762 	struct m_tag *mtag;
763 
764 	p = NULL;
765 	mtag = m_tag_find(m, PACKET_TAG_ENCAP, NULL);
766 	if (mtag != NULL) {
767 		p = *(void **)(mtag + 1);
768 		m_tag_delete(m, mtag);
769 	}
770 	return p;
771 }
772