xref: /netbsd-src/sys/netinet/ip_encap.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: ip_encap.c,v 1.47 2015/12/09 06:00:51 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  * FreeBSD is excluded here as they make max_keylen a static variable, and
69  * thus forbid definition of radix table other than proper domains.
70  */
71 
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.47 2015/12/09 06:00:51 knakahara Exp $");
74 
75 #ifdef _KERNEL_OPT
76 #include "opt_mrouting.h"
77 #include "opt_inet.h"
78 #endif
79 
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/socket.h>
83 #include <sys/sockio.h>
84 #include <sys/mbuf.h>
85 #include <sys/errno.h>
86 #include <sys/protosw.h>
87 #include <sys/queue.h>
88 #include <sys/kmem.h>
89 
90 #include <net/if.h>
91 #include <net/route.h>
92 
93 #include <netinet/in.h>
94 #include <netinet/in_systm.h>
95 #include <netinet/ip.h>
96 #include <netinet/ip_var.h>
97 #include <netinet/ip_encap.h>
98 #ifdef MROUTING
99 #include <netinet/ip_mroute.h>
100 #endif /* MROUTING */
101 
102 #ifdef INET6
103 #include <netinet/ip6.h>
104 #include <netinet6/ip6_var.h>
105 #include <netinet6/ip6protosw.h>
106 #include <netinet6/in6_var.h>
107 #include <netinet6/in6_pcb.h>
108 #include <netinet/icmp6.h>
109 #endif
110 
111 #include <net/net_osdep.h>
112 
113 enum direction { INBOUND, OUTBOUND };
114 
115 #ifdef INET
116 static struct encaptab *encap4_lookup(struct mbuf *, int, int, enum direction);
117 #endif
118 #ifdef INET6
119 static struct encaptab *encap6_lookup(struct mbuf *, int, int, enum direction);
120 #endif
121 static int encap_add(struct encaptab *);
122 static int encap_remove(struct encaptab *);
123 static int encap_afcheck(int, const struct sockaddr *, const struct sockaddr *);
124 static struct radix_node_head *encap_rnh(int);
125 static int mask_matchlen(const struct sockaddr *);
126 static void encap_fillarg(struct mbuf *, const struct encaptab *);
127 
128 LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab);
129 
130 extern int max_keylen;	/* radix.c */
131 struct radix_node_head *encap_head[2];	/* 0 for AF_INET, 1 for AF_INET6 */
132 
133 void
134 encap_init(void)
135 {
136 	static int initialized = 0;
137 
138 	if (initialized)
139 		return;
140 	initialized++;
141 #if 0
142 	/*
143 	 * we cannot use LIST_INIT() here, since drivers may want to call
144 	 * encap_attach(), on driver attach.  encap_init() will be called
145 	 * on AF_INET{,6} initialization, which happens after driver
146 	 * initialization - using LIST_INIT() here can nuke encap_attach()
147 	 * from drivers.
148 	 */
149 	LIST_INIT(&encaptab);
150 #endif
151 
152 	/*
153 	 * initialize radix lookup table when the radix subsystem is inited.
154 	 */
155 	rn_delayedinit((void *)&encap_head[0],
156 	    sizeof(struct sockaddr_pack) << 3);
157 #ifdef INET6
158 	rn_delayedinit((void *)&encap_head[1],
159 	    sizeof(struct sockaddr_pack) << 3);
160 #endif
161 }
162 
163 #ifdef INET
164 static struct encaptab *
165 encap4_lookup(struct mbuf *m, int off, int proto, enum direction dir)
166 {
167 	struct ip *ip;
168 	struct ip_pack4 pack;
169 	struct encaptab *ep, *match;
170 	int prio, matchprio;
171 	struct radix_node_head *rnh = encap_rnh(AF_INET);
172 	struct radix_node *rn;
173 
174 	KASSERT(m->m_len >= sizeof(*ip));
175 
176 	ip = mtod(m, struct ip *);
177 
178 	memset(&pack, 0, sizeof(pack));
179 	pack.p.sp_len = sizeof(pack);
180 	pack.mine.sin_family = pack.yours.sin_family = AF_INET;
181 	pack.mine.sin_len = pack.yours.sin_len = sizeof(struct sockaddr_in);
182 	if (dir == INBOUND) {
183 		pack.mine.sin_addr = ip->ip_dst;
184 		pack.yours.sin_addr = ip->ip_src;
185 	} else {
186 		pack.mine.sin_addr = ip->ip_src;
187 		pack.yours.sin_addr = ip->ip_dst;
188 	}
189 
190 	match = NULL;
191 	matchprio = 0;
192 
193 	rn = rnh->rnh_matchaddr((void *)&pack, rnh);
194 	if (rn && (rn->rn_flags & RNF_ROOT) == 0) {
195 		match = (struct encaptab *)rn;
196 		matchprio = mask_matchlen(match->srcmask) +
197 		    mask_matchlen(match->dstmask);
198 	}
199 
200 	LIST_FOREACH(ep, &encaptab, chain) {
201 		if (ep->af != AF_INET)
202 			continue;
203 		if (ep->proto >= 0 && ep->proto != proto)
204 			continue;
205 		if (ep->func)
206 			prio = (*ep->func)(m, off, proto, ep->arg);
207 		else
208 			continue;
209 
210 		/*
211 		 * We prioritize the matches by using bit length of the
212 		 * matches.  mask_match() and user-supplied matching function
213 		 * should return the bit length of the matches (for example,
214 		 * if both src/dst are matched for IPv4, 64 should be returned).
215 		 * 0 or negative return value means "it did not match".
216 		 *
217 		 * The question is, since we have two "mask" portion, we
218 		 * cannot really define total order between entries.
219 		 * For example, which of these should be preferred?
220 		 * mask_match() returns 48 (32 + 16) for both of them.
221 		 *	src=3ffe::/16, dst=3ffe:501::/32
222 		 *	src=3ffe:501::/32, dst=3ffe::/16
223 		 *
224 		 * We need to loop through all the possible candidates
225 		 * to get the best match - the search takes O(n) for
226 		 * n attachments (i.e. interfaces).
227 		 *
228 		 * For radix-based lookup, I guess source takes precedence.
229 		 * See rn_{refines,lexobetter} for the correct answer.
230 		 */
231 		if (prio <= 0)
232 			continue;
233 		if (prio > matchprio) {
234 			matchprio = prio;
235 			match = ep;
236 		}
237 	}
238 
239 	return match;
240 }
241 
242 void
243 encap4_input(struct mbuf *m, ...)
244 {
245 	int off, proto;
246 	va_list ap;
247 	const struct protosw *psw;
248 	struct encaptab *match;
249 
250 	va_start(ap, m);
251 	off = va_arg(ap, int);
252 	proto = va_arg(ap, int);
253 	va_end(ap);
254 
255 	match = encap4_lookup(m, off, proto, INBOUND);
256 
257 	if (match) {
258 		/* found a match, "match" has the best one */
259 		psw = match->psw;
260 		if (psw && psw->pr_input) {
261 			encap_fillarg(m, match);
262 			(*psw->pr_input)(m, off, proto);
263 		} else
264 			m_freem(m);
265 		return;
266 	}
267 
268 	/* last resort: inject to raw socket */
269 	rip_input(m, off, proto);
270 }
271 #endif
272 
273 #ifdef INET6
274 static struct encaptab *
275 encap6_lookup(struct mbuf *m, int off, int proto, enum direction dir)
276 {
277 	struct ip6_hdr *ip6;
278 	struct ip_pack6 pack;
279 	int prio, matchprio;
280 	struct encaptab *ep, *match;
281 	struct radix_node_head *rnh = encap_rnh(AF_INET6);
282 	struct radix_node *rn;
283 
284 	KASSERT(m->m_len >= sizeof(*ip6));
285 
286 	ip6 = mtod(m, struct ip6_hdr *);
287 
288 	memset(&pack, 0, sizeof(pack));
289 	pack.p.sp_len = sizeof(pack);
290 	pack.mine.sin6_family = pack.yours.sin6_family = AF_INET6;
291 	pack.mine.sin6_len = pack.yours.sin6_len = sizeof(struct sockaddr_in6);
292 	if (dir == INBOUND) {
293 		pack.mine.sin6_addr = ip6->ip6_dst;
294 		pack.yours.sin6_addr = ip6->ip6_src;
295 	} else {
296 		pack.mine.sin6_addr = ip6->ip6_src;
297 		pack.yours.sin6_addr = ip6->ip6_dst;
298 	}
299 
300 	match = NULL;
301 	matchprio = 0;
302 
303 	rn = rnh->rnh_matchaddr((void *)&pack, rnh);
304 	if (rn && (rn->rn_flags & RNF_ROOT) == 0) {
305 		match = (struct encaptab *)rn;
306 		matchprio = mask_matchlen(match->srcmask) +
307 		    mask_matchlen(match->dstmask);
308 	}
309 
310 	LIST_FOREACH(ep, &encaptab, chain) {
311 		if (ep->af != AF_INET6)
312 			continue;
313 		if (ep->proto >= 0 && ep->proto != proto)
314 			continue;
315 		if (ep->func)
316 			prio = (*ep->func)(m, off, proto, ep->arg);
317 		else
318 			continue;
319 
320 		/* see encap4_lookup() for issues here */
321 		if (prio <= 0)
322 			continue;
323 		if (prio > matchprio) {
324 			matchprio = prio;
325 			match = ep;
326 		}
327 	}
328 
329 	return match;
330 }
331 
332 int
333 encap6_input(struct mbuf **mp, int *offp, int proto)
334 {
335 	struct mbuf *m = *mp;
336 	const struct ip6protosw *psw;
337 	struct encaptab *match;
338 
339 	match = encap6_lookup(m, *offp, proto, INBOUND);
340 
341 	if (match) {
342 		/* found a match */
343 		psw = (const struct ip6protosw *)match->psw;
344 		if (psw && psw->pr_input) {
345 			encap_fillarg(m, match);
346 			return (*psw->pr_input)(mp, offp, proto);
347 		} else {
348 			m_freem(m);
349 			return IPPROTO_DONE;
350 		}
351 	}
352 
353 	/* last resort: inject to raw socket */
354 	return rip6_input(mp, offp, proto);
355 }
356 #endif
357 
358 static int
359 encap_add(struct encaptab *ep)
360 {
361 	struct radix_node_head *rnh = encap_rnh(ep->af);
362 	int error = 0;
363 
364 	LIST_INSERT_HEAD(&encaptab, ep, chain);
365 	if (!ep->func && rnh) {
366 		if (!rnh->rnh_addaddr((void *)ep->addrpack,
367 		    (void *)ep->maskpack, rnh, ep->nodes)) {
368 			error = EEXIST;
369 			goto fail;
370 		}
371 	}
372 	return error;
373 
374  fail:
375 	LIST_REMOVE(ep, chain);
376 	return error;
377 }
378 
379 static int
380 encap_remove(struct encaptab *ep)
381 {
382 	struct radix_node_head *rnh = encap_rnh(ep->af);
383 	int error = 0;
384 
385 	LIST_REMOVE(ep, chain);
386 	if (!ep->func && rnh) {
387 		if (!rnh->rnh_deladdr((void *)ep->addrpack,
388 		    (void *)ep->maskpack, rnh))
389 			error = ESRCH;
390 	}
391 	return error;
392 }
393 
394 static int
395 encap_afcheck(int af, const struct sockaddr *sp, const struct sockaddr *dp)
396 {
397 	if (sp && dp) {
398 		if (sp->sa_len != dp->sa_len)
399 			return EINVAL;
400 		if (af != sp->sa_family || af != dp->sa_family)
401 			return EINVAL;
402 	} else if (!sp && !dp)
403 		;
404 	else
405 		return EINVAL;
406 
407 	switch (af) {
408 	case AF_INET:
409 		if (sp && sp->sa_len != sizeof(struct sockaddr_in))
410 			return EINVAL;
411 		if (dp && dp->sa_len != sizeof(struct sockaddr_in))
412 			return EINVAL;
413 		break;
414 #ifdef INET6
415 	case AF_INET6:
416 		if (sp && sp->sa_len != sizeof(struct sockaddr_in6))
417 			return EINVAL;
418 		if (dp && dp->sa_len != sizeof(struct sockaddr_in6))
419 			return EINVAL;
420 		break;
421 #endif
422 	default:
423 		return EAFNOSUPPORT;
424 	}
425 
426 	return 0;
427 }
428 
429 /*
430  * sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
431  * length of mask (sm and dm) is assumed to be same as sp/dp.
432  * Return value will be necessary as input (cookie) for encap_detach().
433  */
434 const struct encaptab *
435 encap_attach(int af, int proto,
436     const struct sockaddr *sp, const struct sockaddr *sm,
437     const struct sockaddr *dp, const struct sockaddr *dm,
438     const struct protosw *psw, void *arg)
439 {
440 	struct encaptab *ep;
441 	int error;
442 	int s;
443 	size_t l;
444 	struct ip_pack4 *pack4;
445 #ifdef INET6
446 	struct ip_pack6 *pack6;
447 #endif
448 
449 	s = splsoftnet();
450 	/* sanity check on args */
451 	error = encap_afcheck(af, sp, dp);
452 	if (error)
453 		goto fail;
454 
455 	/* check if anyone have already attached with exactly same config */
456 	LIST_FOREACH(ep, &encaptab, chain) {
457 		if (ep->af != af)
458 			continue;
459 		if (ep->proto != proto)
460 			continue;
461 		if (ep->func)
462 			continue;
463 
464 		KASSERT(ep->src != NULL);
465 		KASSERT(ep->dst != NULL);
466 		KASSERT(ep->srcmask != NULL);
467 		KASSERT(ep->dstmask != NULL);
468 
469 		if (ep->src->sa_len != sp->sa_len ||
470 		    memcmp(ep->src, sp, sp->sa_len) != 0 ||
471 		    memcmp(ep->srcmask, sm, sp->sa_len) != 0)
472 			continue;
473 		if (ep->dst->sa_len != dp->sa_len ||
474 		    memcmp(ep->dst, dp, dp->sa_len) != 0 ||
475 		    memcmp(ep->dstmask, dm, dp->sa_len) != 0)
476 			continue;
477 
478 		error = EEXIST;
479 		goto fail;
480 	}
481 
482 	switch (af) {
483 	case AF_INET:
484 		l = sizeof(*pack4);
485 		break;
486 #ifdef INET6
487 	case AF_INET6:
488 		l = sizeof(*pack6);
489 		break;
490 #endif
491 	default:
492 		goto fail;
493 	}
494 
495 	/* M_NETADDR ok? */
496 	ep = kmem_zalloc(sizeof(*ep), KM_NOSLEEP);
497 	if (ep == NULL) {
498 		error = ENOBUFS;
499 		goto fail;
500 	}
501 	ep->addrpack = kmem_zalloc(l, KM_NOSLEEP);
502 	if (ep->addrpack == NULL) {
503 		error = ENOBUFS;
504 		goto gc;
505 	}
506 	ep->maskpack = kmem_zalloc(l, KM_NOSLEEP);
507 	if (ep->maskpack == NULL) {
508 		error = ENOBUFS;
509 		goto gc;
510 	}
511 
512 	ep->af = af;
513 	ep->proto = proto;
514 	ep->addrpack->sa_len = l & 0xff;
515 	ep->maskpack->sa_len = l & 0xff;
516 	switch (af) {
517 	case AF_INET:
518 		pack4 = (struct ip_pack4 *)ep->addrpack;
519 		ep->src = (struct sockaddr *)&pack4->mine;
520 		ep->dst = (struct sockaddr *)&pack4->yours;
521 		pack4 = (struct ip_pack4 *)ep->maskpack;
522 		ep->srcmask = (struct sockaddr *)&pack4->mine;
523 		ep->dstmask = (struct sockaddr *)&pack4->yours;
524 		break;
525 #ifdef INET6
526 	case AF_INET6:
527 		pack6 = (struct ip_pack6 *)ep->addrpack;
528 		ep->src = (struct sockaddr *)&pack6->mine;
529 		ep->dst = (struct sockaddr *)&pack6->yours;
530 		pack6 = (struct ip_pack6 *)ep->maskpack;
531 		ep->srcmask = (struct sockaddr *)&pack6->mine;
532 		ep->dstmask = (struct sockaddr *)&pack6->yours;
533 		break;
534 #endif
535 	}
536 
537 	memcpy(ep->src, sp, sp->sa_len);
538 	memcpy(ep->srcmask, sm, sp->sa_len);
539 	memcpy(ep->dst, dp, dp->sa_len);
540 	memcpy(ep->dstmask, dm, dp->sa_len);
541 	ep->psw = psw;
542 	ep->arg = arg;
543 
544 	error = encap_add(ep);
545 	if (error)
546 		goto gc;
547 
548 	error = 0;
549 	splx(s);
550 	return ep;
551 
552 gc:
553 	if (ep->addrpack)
554 		kmem_free(ep->addrpack, l);
555 	if (ep->maskpack)
556 		kmem_free(ep->maskpack, l);
557 	if (ep)
558 		kmem_free(ep, sizeof(*ep));
559 fail:
560 	splx(s);
561 	return NULL;
562 }
563 
564 const struct encaptab *
565 encap_attach_func(int af, int proto,
566     int (*func)(struct mbuf *, int, int, void *),
567     const struct protosw *psw, void *arg)
568 {
569 	struct encaptab *ep;
570 	int error;
571 	int s;
572 
573 	s = splsoftnet();
574 	/* sanity check on args */
575 	if (!func) {
576 		error = EINVAL;
577 		goto fail;
578 	}
579 
580 	error = encap_afcheck(af, NULL, NULL);
581 	if (error)
582 		goto fail;
583 
584 	ep = kmem_alloc(sizeof(*ep), KM_NOSLEEP);	/*XXX*/
585 	if (ep == NULL) {
586 		error = ENOBUFS;
587 		goto fail;
588 	}
589 	memset(ep, 0, sizeof(*ep));
590 
591 	ep->af = af;
592 	ep->proto = proto;
593 	ep->func = func;
594 	ep->psw = psw;
595 	ep->arg = arg;
596 
597 	error = encap_add(ep);
598 	if (error)
599 		goto fail;
600 
601 	error = 0;
602 	splx(s);
603 	return ep;
604 
605 fail:
606 	splx(s);
607 	return NULL;
608 }
609 
610 /* XXX encap4_ctlinput() is necessary if we set DF=1 on outer IPv4 header */
611 
612 #ifdef INET6
613 void *
614 encap6_ctlinput(int cmd, const struct sockaddr *sa, void *d0)
615 {
616 	void *d = d0;
617 	struct ip6_hdr *ip6;
618 	struct mbuf *m;
619 	int off;
620 	struct ip6ctlparam *ip6cp = NULL;
621 	int nxt;
622 	struct encaptab *ep;
623 	const struct ip6protosw *psw;
624 
625 	if (sa->sa_family != AF_INET6 ||
626 	    sa->sa_len != sizeof(struct sockaddr_in6))
627 		return NULL;
628 
629 	if ((unsigned)cmd >= PRC_NCMDS)
630 		return NULL;
631 	if (cmd == PRC_HOSTDEAD)
632 		d = NULL;
633 	else if (cmd == PRC_MSGSIZE)
634 		; /* special code is present, see below */
635 	else if (inet6ctlerrmap[cmd] == 0)
636 		return NULL;
637 
638 	/* if the parameter is from icmp6, decode it. */
639 	if (d != NULL) {
640 		ip6cp = (struct ip6ctlparam *)d;
641 		m = ip6cp->ip6c_m;
642 		ip6 = ip6cp->ip6c_ip6;
643 		off = ip6cp->ip6c_off;
644 		nxt = ip6cp->ip6c_nxt;
645 
646 		if (ip6 && cmd == PRC_MSGSIZE) {
647 			int valid = 0;
648 			struct encaptab *match;
649 
650 			/*
651 		 	* Check to see if we have a valid encap configuration.
652 		 	*/
653 			match = encap6_lookup(m, off, nxt, OUTBOUND);
654 			if (match)
655 				valid++;
656 
657 			/*
658 		 	* Depending on the value of "valid" and routing table
659 		 	* size (mtudisc_{hi,lo}wat), we will:
660 		 	* - recalcurate the new MTU and create the
661 		 	*   corresponding routing entry, or
662 		 	* - ignore the MTU change notification.
663 		 	*/
664 			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
665 		}
666 	} else {
667 		m = NULL;
668 		ip6 = NULL;
669 		nxt = -1;
670 	}
671 
672 	/* inform all listeners */
673 	LIST_FOREACH(ep, &encaptab, chain) {
674 		if (ep->af != AF_INET6)
675 			continue;
676 		if (ep->proto >= 0 && ep->proto != nxt)
677 			continue;
678 
679 		/* should optimize by looking at address pairs */
680 
681 		/* XXX need to pass ep->arg or ep itself to listeners */
682 		psw = (const struct ip6protosw *)ep->psw;
683 		if (psw && psw->pr_ctlinput)
684 			(*psw->pr_ctlinput)(cmd, sa, d);
685 	}
686 
687 	rip6_ctlinput(cmd, sa, d0);
688 	return NULL;
689 }
690 #endif
691 
692 int
693 encap_detach(const struct encaptab *cookie)
694 {
695 	const struct encaptab *ep = cookie;
696 	struct encaptab *p, *np;
697 	int error;
698 
699 	LIST_FOREACH_SAFE(p, &encaptab, chain, np) {
700 		if (p == ep) {
701 			error = encap_remove(p);
702 			if (error)
703 				return error;
704 			if (!ep->func) {
705 				kmem_free(p->addrpack, ep->addrpack->sa_len);
706 				kmem_free(p->maskpack, ep->maskpack->sa_len);
707 			}
708 			kmem_free(p, sizeof(*p));	/*XXX*/
709 			return 0;
710 		}
711 	}
712 
713 	return ENOENT;
714 }
715 
716 static struct radix_node_head *
717 encap_rnh(int af)
718 {
719 
720 	switch (af) {
721 	case AF_INET:
722 		return encap_head[0];
723 #ifdef INET6
724 	case AF_INET6:
725 		return encap_head[1];
726 #endif
727 	default:
728 		return NULL;
729 	}
730 }
731 
732 static int
733 mask_matchlen(const struct sockaddr *sa)
734 {
735 	const char *p, *ep;
736 	int l;
737 
738 	p = (const char *)sa;
739 	ep = p + sa->sa_len;
740 	p += 2;	/* sa_len + sa_family */
741 
742 	l = 0;
743 	while (p < ep) {
744 		l += (*p ? 8 : 0);	/* estimate */
745 		p++;
746 	}
747 	return l;
748 }
749 
750 static void
751 encap_fillarg(struct mbuf *m, const struct encaptab *ep)
752 {
753 	struct m_tag *mtag;
754 
755 	mtag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT);
756 	if (mtag) {
757 		*(void **)(mtag + 1) = ep->arg;
758 		m_tag_prepend(m, mtag);
759 	}
760 }
761 
762 void *
763 encap_getarg(struct mbuf *m)
764 {
765 	void *p;
766 	struct m_tag *mtag;
767 
768 	p = NULL;
769 	mtag = m_tag_find(m, PACKET_TAG_ENCAP, NULL);
770 	if (mtag != NULL) {
771 		p = *(void **)(mtag + 1);
772 		m_tag_delete(m, mtag);
773 	}
774 	return p;
775 }
776