ip6_mroute.c revision 248321
11590Srgrimes/*-
21590Srgrimes * Copyright (C) 1998 WIDE Project.
31590Srgrimes * All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. Neither the name of the project nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes *
291590Srgrimes *	$KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $
3087674Smarkm */
3187674Smarkm
3287674Smarkm/*-
3387674Smarkm * Copyright (c) 1989 Stephen Deering
341590Srgrimes * Copyright (c) 1992, 1993
3587674Smarkm *      The Regents of the University of California.  All rights reserved.
3628694Scharnier *
371590Srgrimes * This code is derived from software contributed to Berkeley by
381590Srgrimes * Stephen Deering of Stanford University.
391590Srgrimes *
401590Srgrimes * Redistribution and use in source and binary forms, with or without
411590Srgrimes * modification, are permitted provided that the following conditions
42200462Sdelphij * are met:
43181922Sache * 1. Redistributions of source code must retain the above copyright
441590Srgrimes *    notice, this list of conditions and the following disclaimer.
451590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
461590Srgrimes *    notice, this list of conditions and the following disclaimer in the
471590Srgrimes *    documentation and/or other materials provided with the distribution.
481590Srgrimes * 4. Neither the name of the University nor the names of its contributors
498874Srgrimes *    may be used to endorse or promote products derived from this software
501590Srgrimes *    without specific prior written permission.
51196652Sume *
5297981Sjmallett * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
531590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54196652Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5553073Sdavidn * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
561590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57196956Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58196652Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
591590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6053073Sdavidn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6153073Sdavidn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
621590Srgrimes * SUCH DAMAGE.
631590Srgrimes *
641590Srgrimes *	@(#)ip_mroute.c	8.2 (Berkeley) 11/15/93
659987Swollman *	BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp
66196652Sume */
671590Srgrimes
681590Srgrimes/*
6953073Sdavidn * IP multicast forwarding procedures
7053073Sdavidn *
7153073Sdavidn * Written by David Waitzman, BBN Labs, August 1988.
7253073Sdavidn * Modified by Steve Deering, Stanford, February 1989.
7353073Sdavidn * Modified by Mark J. Steiglitz, Stanford, May, 1991
74196652Sume * Modified by Van Jacobson, LBL, January 1993
751590Srgrimes * Modified by Ajit Thyagarajan, PARC, August 1993
761590Srgrimes * Modified by Bill Fenner, PARC, April 1994
771590Srgrimes *
781590Srgrimes * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
79196652Sume */
801590Srgrimes
811590Srgrimes#include <sys/cdefs.h>
82196652Sume__FBSDID("$FreeBSD: head/sys/netinet6/ip6_mroute.c 248321 2013-03-15 12:50:29Z glebius $");
83196652Sume
84196652Sume#include "opt_inet6.h"
85196652Sume
86196652Sume#include <sys/param.h>
87196652Sume#include <sys/callout.h>
88196652Sume#include <sys/errno.h>
89196652Sume#include <sys/kernel.h>
90196652Sume#include <sys/lock.h>
91196652Sume#include <sys/malloc.h>
92196652Sume#include <sys/mbuf.h>
93196652Sume#include <sys/module.h>
941590Srgrimes#include <sys/domain.h>
951590Srgrimes#include <sys/protosw.h>
961590Srgrimes#include <sys/signalvar.h>
971590Srgrimes#include <sys/socket.h>
981590Srgrimes#include <sys/socketvar.h>
9942481Speter#include <sys/sockio.h>
1001590Srgrimes#include <sys/sx.h>
10122558Sdanny#include <sys/sysctl.h>
10297981Sjmallett#include <sys/syslog.h>
1031590Srgrimes#include <sys/systm.h>
1041590Srgrimes#include <sys/time.h>
10510948Sdima
10610948Sdima#include <net/if.h>
10711339Sache#include <net/if_types.h>
10842481Speter#include <net/raw_cb.h>
10942481Speter#include <net/vnet.h>
11022558Sdanny
11142481Speter#include <netinet/in.h>
11210948Sdima#include <netinet/in_var.h>
1131590Srgrimes#include <netinet/icmp6.h>
1141590Srgrimes#include <netinet/ip_encap.h>
1159987Swollman
1161590Srgrimes#include <netinet/ip6.h>
11732055Salex#include <netinet6/ip6_var.h>
1181590Srgrimes#include <netinet6/scope6_var.h>
1199987Swollman#include <netinet6/nd6.h>
1203138Sache#include <netinet6/ip6_mroute.h>
1213138Sache#include <netinet6/ip6protosw.h>
1221590Srgrimes#include <netinet6/pim6.h>
1231590Srgrimes#include <netinet6/pim6_var.h>
12432055Salex
12522558Sdannystatic MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry");
12642481Speter
1271590Srgrimes/* XXX: this is a very common idiom; move to <sys/mbuf.h> ? */
128#define M_HASCL(m) ((m)->m_flags & M_EXT)
129
130static int	ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
131static void	phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
132static int	register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
133static int	set_pim6(int *);
134static int	socket_send(struct socket *, struct mbuf *,
135		    struct sockaddr_in6 *);
136
137extern int in6_mcast_loop;
138extern struct domain inet6domain;
139
140static const struct encaptab *pim6_encap_cookie;
141static const struct ip6protosw in6_pim_protosw = {
142	.pr_type =		SOCK_RAW,
143	.pr_domain =		&inet6domain,
144	.pr_protocol =		IPPROTO_PIM,
145	.pr_flags =		PR_ATOMIC|PR_ADDR|PR_LASTHDR,
146	.pr_input =		pim6_input,
147	.pr_output =		rip6_output,
148	.pr_ctloutput =		rip6_ctloutput,
149	.pr_usrreqs =		&rip6_usrreqs
150};
151static int pim6_encapcheck(const struct mbuf *, int, int, void *);
152
153static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
154#define	V_ip6_mrouter_ver	VNET(ip6_mrouter_ver)
155
156SYSCTL_DECL(_net_inet6);
157SYSCTL_DECL(_net_inet6_ip6);
158static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
159
160static struct mrt6stat mrt6stat;
161SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
162    &mrt6stat, mrt6stat,
163    "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)");
164
165#define NO_RTE_FOUND	0x1
166#define RTE_FOUND	0x2
167
168static struct mtx mrouter6_mtx;
169#define	MROUTER6_LOCK()		mtx_lock(&mrouter6_mtx)
170#define	MROUTER6_UNLOCK()	mtx_unlock(&mrouter6_mtx)
171#define	MROUTER6_LOCK_ASSERT()	do {					\
172	mtx_assert(&mrouter6_mtx, MA_OWNED);				\
173	NET_ASSERT_GIANT();						\
174} while (0)
175#define	MROUTER6_LOCK_INIT()	\
176	mtx_init(&mrouter6_mtx, "IPv6 multicast forwarding", NULL, MTX_DEF)
177#define	MROUTER6_LOCK_DESTROY()	mtx_destroy(&mrouter6_mtx)
178
179static struct mf6c *mf6ctable[MF6CTBLSIZ];
180SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD,
181    &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]",
182    "IPv6 Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], "
183    "netinet6/ip6_mroute.h)");
184
185static struct mtx mfc6_mtx;
186#define	MFC6_LOCK()		mtx_lock(&mfc6_mtx)
187#define	MFC6_UNLOCK()		mtx_unlock(&mfc6_mtx)
188#define	MFC6_LOCK_ASSERT()	do {					\
189	mtx_assert(&mfc6_mtx, MA_OWNED);				\
190	NET_ASSERT_GIANT();						\
191} while (0)
192#define	MFC6_LOCK_INIT()		\
193	mtx_init(&mfc6_mtx, "IPv6 multicast forwarding cache", NULL, MTX_DEF)
194#define	MFC6_LOCK_DESTROY()	mtx_destroy(&mfc6_mtx)
195
196static u_char n6expire[MF6CTBLSIZ];
197
198static struct mif6 mif6table[MAXMIFS];
199SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD,
200    &mif6table, sizeof(mif6table), "S,mif6[MAXMIFS]",
201    "IPv6 Multicast Interfaces (struct mif6[MAXMIFS], netinet6/ip6_mroute.h)");
202
203static struct mtx mif6_mtx;
204#define	MIF6_LOCK()		mtx_lock(&mif6_mtx)
205#define	MIF6_UNLOCK()		mtx_unlock(&mif6_mtx)
206#define	MIF6_LOCK_ASSERT()	mtx_assert(&mif6_mtx, MA_OWNED)
207#define	MIF6_LOCK_INIT()	\
208	mtx_init(&mif6_mtx, "IPv6 multicast interfaces", NULL, MTX_DEF)
209#define	MIF6_LOCK_DESTROY()	mtx_destroy(&mif6_mtx)
210
211#ifdef MRT6DEBUG
212static VNET_DEFINE(u_int, mrt6debug) = 0;	/* debug level */
213#define	V_mrt6debug		VNET(mrt6debug)
214#define DEBUG_MFC	0x02
215#define DEBUG_FORWARD	0x04
216#define DEBUG_EXPIRE	0x08
217#define DEBUG_XMIT	0x10
218#define DEBUG_REG	0x20
219#define DEBUG_PIM	0x40
220#endif
221
222static void	expire_upcalls(void *);
223#define	EXPIRE_TIMEOUT	(hz / 4)	/* 4x / second */
224#define	UPCALL_EXPIRE	6		/* number of timeouts */
225
226/*
227 * XXX TODO: maintain a count to if_allmulti() calls in struct ifnet.
228 */
229
230/*
231 * 'Interfaces' associated with decapsulator (so we can tell
232 * packets that went through it from ones that get reflected
233 * by a broken gateway).  Different from IPv4 register_if,
234 * these interfaces are linked into the system ifnet list,
235 * because per-interface IPv6 statistics are maintained in
236 * ifp->if_afdata.  But it does not have any routes point
237 * to them.  I.e., packets can't be sent this way.  They
238 * only exist as a placeholder for multicast source
239 * verification.
240 */
241static struct ifnet *multicast_register_if6;
242
243#define ENCAP_HOPS 64
244
245/*
246 * Private variables.
247 */
248static mifi_t nummifs = 0;
249static mifi_t reg_mif_num = (mifi_t)-1;
250
251static struct pim6stat pim6stat;
252SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RW,
253    &pim6stat, pim6stat,
254    "PIM Statistics (struct pim6stat, netinet6/pim_var.h)");
255
256static VNET_DEFINE(int, pim6);
257#define	V_pim6		VNET(pim6)
258
259/*
260 * Hash function for a source, group entry
261 */
262#define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
263				   (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
264				   (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
265				   (g).s6_addr32[2] ^ (g).s6_addr32[3])
266
267/*
268 * Find a route for a given origin IPv6 address and Multicast group address.
269 */
270#define MF6CFIND(o, g, rt) do { \
271	struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
272	rt = NULL; \
273	mrt6stat.mrt6s_mfc_lookups++; \
274	while (_rt) { \
275		if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
276		    IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
277		    (_rt->mf6c_stall == NULL)) { \
278			rt = _rt; \
279			break; \
280		} \
281		_rt = _rt->mf6c_next; \
282	} \
283	if (rt == NULL) { \
284		mrt6stat.mrt6s_mfc_misses++; \
285	} \
286} while (/*CONSTCOND*/ 0)
287
288/*
289 * Macros to compute elapsed time efficiently
290 * Borrowed from Van Jacobson's scheduling code
291 * XXX: replace with timersub() ?
292 */
293#define TV_DELTA(a, b, delta) do { \
294	    int xxs; \
295		\
296	    delta = (a).tv_usec - (b).tv_usec; \
297	    if ((xxs = (a).tv_sec - (b).tv_sec)) { \
298	       switch (xxs) { \
299		      case 2: \
300			  delta += 1000000; \
301			      /* FALLTHROUGH */ \
302		      case 1: \
303			  delta += 1000000; \
304			  break; \
305		      default: \
306			  delta += (1000000 * xxs); \
307	       } \
308	    } \
309} while (/*CONSTCOND*/ 0)
310
311/* XXX: replace with timercmp(a, b, <) ? */
312#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
313	      (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
314
315#ifdef UPCALL_TIMING
316#define UPCALL_MAX	50
317static u_long upcall_data[UPCALL_MAX + 1];
318static void collate();
319#endif /* UPCALL_TIMING */
320
321static int ip6_mrouter_init(struct socket *, int, int);
322static int add_m6fc(struct mf6cctl *);
323static int add_m6if(struct mif6ctl *);
324static int del_m6fc(struct mf6cctl *);
325static int del_m6if(mifi_t *);
326static int del_m6if_locked(mifi_t *);
327static int get_mif6_cnt(struct sioc_mif_req6 *);
328static int get_sg_cnt(struct sioc_sg_req6 *);
329
330static struct callout expire_upcalls_ch;
331
332int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
333int X_ip6_mrouter_done(void);
334int X_ip6_mrouter_set(struct socket *, struct sockopt *);
335int X_ip6_mrouter_get(struct socket *, struct sockopt *);
336int X_mrt6_ioctl(u_long, caddr_t);
337
338/*
339 * Handle MRT setsockopt commands to modify the multicast routing tables.
340 */
341int
342X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
343{
344	int error = 0;
345	int optval;
346	struct mif6ctl mifc;
347	struct mf6cctl mfcc;
348	mifi_t mifi;
349
350	if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT)
351		return (EACCES);
352
353	switch (sopt->sopt_name) {
354	case MRT6_INIT:
355#ifdef MRT6_OINIT
356	case MRT6_OINIT:
357#endif
358		error = sooptcopyin(sopt, &optval, sizeof(optval),
359		    sizeof(optval));
360		if (error)
361			break;
362		error = ip6_mrouter_init(so, optval, sopt->sopt_name);
363		break;
364	case MRT6_DONE:
365		error = X_ip6_mrouter_done();
366		break;
367	case MRT6_ADD_MIF:
368		error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc));
369		if (error)
370			break;
371		error = add_m6if(&mifc);
372		break;
373	case MRT6_ADD_MFC:
374		error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
375		if (error)
376			break;
377		error = add_m6fc(&mfcc);
378		break;
379	case MRT6_DEL_MFC:
380		error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
381		if (error)
382			break;
383		error = del_m6fc(&mfcc);
384		break;
385	case MRT6_DEL_MIF:
386		error = sooptcopyin(sopt, &mifi, sizeof(mifi), sizeof(mifi));
387		if (error)
388			break;
389		error = del_m6if(&mifi);
390		break;
391	case MRT6_PIM:
392		error = sooptcopyin(sopt, &optval, sizeof(optval),
393		    sizeof(optval));
394		if (error)
395			break;
396		error = set_pim6(&optval);
397		break;
398	default:
399		error = EOPNOTSUPP;
400		break;
401	}
402
403	return (error);
404}
405
406/*
407 * Handle MRT getsockopt commands
408 */
409int
410X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
411{
412	int error = 0;
413
414	if (so != V_ip6_mrouter)
415		return (EACCES);
416
417	switch (sopt->sopt_name) {
418		case MRT6_PIM:
419			error = sooptcopyout(sopt, &V_pim6, sizeof(V_pim6));
420			break;
421	}
422	return (error);
423}
424
425/*
426 * Handle ioctl commands to obtain information from the cache
427 */
428int
429X_mrt6_ioctl(u_long cmd, caddr_t data)
430{
431	int ret;
432
433	ret = EINVAL;
434
435	switch (cmd) {
436	case SIOCGETSGCNT_IN6:
437		ret = get_sg_cnt((struct sioc_sg_req6 *)data);
438		break;
439
440	case SIOCGETMIFCNT_IN6:
441		ret = get_mif6_cnt((struct sioc_mif_req6 *)data);
442		break;
443
444	default:
445		break;
446	}
447
448	return (ret);
449}
450
451/*
452 * returns the packet, byte, rpf-failure count for the source group provided
453 */
454static int
455get_sg_cnt(struct sioc_sg_req6 *req)
456{
457	struct mf6c *rt;
458	int ret;
459
460	ret = 0;
461
462	MFC6_LOCK();
463
464	MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
465	if (rt == NULL) {
466		ret = ESRCH;
467	} else {
468		req->pktcnt = rt->mf6c_pkt_cnt;
469		req->bytecnt = rt->mf6c_byte_cnt;
470		req->wrong_if = rt->mf6c_wrong_if;
471	}
472
473	MFC6_UNLOCK();
474
475	return (ret);
476}
477
478/*
479 * returns the input and output packet and byte counts on the mif provided
480 */
481static int
482get_mif6_cnt(struct sioc_mif_req6 *req)
483{
484	mifi_t mifi;
485	int ret;
486
487	ret = 0;
488	mifi = req->mifi;
489
490	MIF6_LOCK();
491
492	if (mifi >= nummifs) {
493		ret = EINVAL;
494	} else {
495		req->icount = mif6table[mifi].m6_pkt_in;
496		req->ocount = mif6table[mifi].m6_pkt_out;
497		req->ibytes = mif6table[mifi].m6_bytes_in;
498		req->obytes = mif6table[mifi].m6_bytes_out;
499	}
500
501	MIF6_UNLOCK();
502
503	return (ret);
504}
505
506static int
507set_pim6(int *i)
508{
509	if ((*i != 1) && (*i != 0))
510		return (EINVAL);
511
512	V_pim6 = *i;
513
514	return (0);
515}
516
517/*
518 * Enable multicast routing
519 */
520static int
521ip6_mrouter_init(struct socket *so, int v, int cmd)
522{
523
524#ifdef MRT6DEBUG
525	if (V_mrt6debug)
526		log(LOG_DEBUG,
527		    "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
528		    so->so_type, so->so_proto->pr_protocol);
529#endif
530
531	if (so->so_type != SOCK_RAW ||
532	    so->so_proto->pr_protocol != IPPROTO_ICMPV6)
533		return (EOPNOTSUPP);
534
535	if (v != 1)
536		return (ENOPROTOOPT);
537
538	MROUTER6_LOCK();
539
540	if (V_ip6_mrouter != NULL) {
541		MROUTER6_UNLOCK();
542		return (EADDRINUSE);
543	}
544
545	V_ip6_mrouter = so;
546	V_ip6_mrouter_ver = cmd;
547
548	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
549	bzero((caddr_t)n6expire, sizeof(n6expire));
550
551	V_pim6 = 0;/* used for stubbing out/in pim stuff */
552
553	callout_init(&expire_upcalls_ch, 0);
554	callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
555	    expire_upcalls, NULL);
556
557	MROUTER6_UNLOCK();
558
559#ifdef MRT6DEBUG
560	if (V_mrt6debug)
561		log(LOG_DEBUG, "ip6_mrouter_init\n");
562#endif
563
564	return (0);
565}
566
567/*
568 * Disable IPv6 multicast forwarding.
569 */
570int
571X_ip6_mrouter_done(void)
572{
573	mifi_t mifi;
574	int i;
575	struct mf6c *rt;
576	struct rtdetq *rte;
577
578	MROUTER6_LOCK();
579
580	if (V_ip6_mrouter == NULL) {
581		MROUTER6_UNLOCK();
582		return (EINVAL);
583	}
584
585	/*
586	 * For each phyint in use, disable promiscuous reception of all IPv6
587	 * multicasts.
588	 */
589	for (mifi = 0; mifi < nummifs; mifi++) {
590		if (mif6table[mifi].m6_ifp &&
591		    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
592			if_allmulti(mif6table[mifi].m6_ifp, 0);
593		}
594	}
595	bzero((caddr_t)mif6table, sizeof(mif6table));
596	nummifs = 0;
597
598	V_pim6 = 0; /* used to stub out/in pim specific code */
599
600	callout_stop(&expire_upcalls_ch);
601
602	/*
603	 * Free all multicast forwarding cache entries.
604	 */
605	MFC6_LOCK();
606	for (i = 0; i < MF6CTBLSIZ; i++) {
607		rt = mf6ctable[i];
608		while (rt) {
609			struct mf6c *frt;
610
611			for (rte = rt->mf6c_stall; rte != NULL; ) {
612				struct rtdetq *n = rte->next;
613
614				m_free(rte->m);
615				free(rte, M_MRTABLE6);
616				rte = n;
617			}
618			frt = rt;
619			rt = rt->mf6c_next;
620			free(frt, M_MRTABLE6);
621		}
622	}
623	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
624	MFC6_UNLOCK();
625
626	/*
627	 * Reset register interface
628	 */
629	if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
630		if_detach(multicast_register_if6);
631		if_free(multicast_register_if6);
632		reg_mif_num = (mifi_t)-1;
633		multicast_register_if6 = NULL;
634	}
635
636	V_ip6_mrouter = NULL;
637	V_ip6_mrouter_ver = 0;
638
639	MROUTER6_UNLOCK();
640
641#ifdef MRT6DEBUG
642	if (V_mrt6debug)
643		log(LOG_DEBUG, "ip6_mrouter_done\n");
644#endif
645
646	return (0);
647}
648
649static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
650
651/*
652 * Add a mif to the mif table
653 */
654static int
655add_m6if(struct mif6ctl *mifcp)
656{
657	struct mif6 *mifp;
658	struct ifnet *ifp;
659	int error;
660
661	MIF6_LOCK();
662
663	if (mifcp->mif6c_mifi >= MAXMIFS) {
664		MIF6_UNLOCK();
665		return (EINVAL);
666	}
667	mifp = mif6table + mifcp->mif6c_mifi;
668	if (mifp->m6_ifp != NULL) {
669		MIF6_UNLOCK();
670		return (EADDRINUSE); /* XXX: is it appropriate? */
671	}
672	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) {
673		MIF6_UNLOCK();
674		return (ENXIO);
675	}
676
677	ifp = ifnet_byindex(mifcp->mif6c_pifi);
678
679	if (mifcp->mif6c_flags & MIFF_REGISTER) {
680		if (reg_mif_num == (mifi_t)-1) {
681			ifp = if_alloc(IFT_OTHER);
682
683			if_initname(ifp, "register_mif", 0);
684			ifp->if_flags |= IFF_LOOPBACK;
685			if_attach(ifp);
686			multicast_register_if6 = ifp;
687			reg_mif_num = mifcp->mif6c_mifi;
688			/*
689			 * it is impossible to guess the ifindex of the
690			 * register interface.  So mif6c_pifi is automatically
691			 * calculated.
692			 */
693			mifcp->mif6c_pifi = ifp->if_index;
694		} else {
695			ifp = multicast_register_if6;
696		}
697	} else {
698		/* Make sure the interface supports multicast */
699		if ((ifp->if_flags & IFF_MULTICAST) == 0) {
700			MIF6_UNLOCK();
701			return (EOPNOTSUPP);
702		}
703
704		error = if_allmulti(ifp, 1);
705		if (error) {
706			MIF6_UNLOCK();
707			return (error);
708		}
709	}
710
711	mifp->m6_flags     = mifcp->mif6c_flags;
712	mifp->m6_ifp       = ifp;
713
714	/* initialize per mif pkt counters */
715	mifp->m6_pkt_in    = 0;
716	mifp->m6_pkt_out   = 0;
717	mifp->m6_bytes_in  = 0;
718	mifp->m6_bytes_out = 0;
719
720	/* Adjust nummifs up if the mifi is higher than nummifs */
721	if (nummifs <= mifcp->mif6c_mifi)
722		nummifs = mifcp->mif6c_mifi + 1;
723
724	MIF6_UNLOCK();
725
726#ifdef MRT6DEBUG
727	if (V_mrt6debug)
728		log(LOG_DEBUG,
729		    "add_mif #%d, phyint %s\n",
730		    mifcp->mif6c_mifi,
731		    ifp->if_xname);
732#endif
733
734	return (0);
735}
736
737/*
738 * Delete a mif from the mif table
739 */
740static int
741del_m6if_locked(mifi_t *mifip)
742{
743	struct mif6 *mifp = mif6table + *mifip;
744	mifi_t mifi;
745	struct ifnet *ifp;
746
747	MIF6_LOCK_ASSERT();
748
749	if (*mifip >= nummifs)
750		return (EINVAL);
751	if (mifp->m6_ifp == NULL)
752		return (EINVAL);
753
754	if (!(mifp->m6_flags & MIFF_REGISTER)) {
755		/* XXX: TODO: Maintain an ALLMULTI refcount in struct ifnet. */
756		ifp = mifp->m6_ifp;
757		if_allmulti(ifp, 0);
758	} else {
759		if (reg_mif_num != (mifi_t)-1 &&
760		    multicast_register_if6 != NULL) {
761			if_detach(multicast_register_if6);
762			if_free(multicast_register_if6);
763			reg_mif_num = (mifi_t)-1;
764			multicast_register_if6 = NULL;
765		}
766	}
767
768	bzero((caddr_t)mifp, sizeof(*mifp));
769
770	/* Adjust nummifs down */
771	for (mifi = nummifs; mifi > 0; mifi--)
772		if (mif6table[mifi - 1].m6_ifp)
773			break;
774	nummifs = mifi;
775
776#ifdef MRT6DEBUG
777	if (V_mrt6debug)
778		log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
779#endif
780
781	return (0);
782}
783
784static int
785del_m6if(mifi_t *mifip)
786{
787	int cc;
788
789	MIF6_LOCK();
790	cc = del_m6if_locked(mifip);
791	MIF6_UNLOCK();
792
793	return (cc);
794}
795
796/*
797 * Add an mfc entry
798 */
799static int
800add_m6fc(struct mf6cctl *mfccp)
801{
802	struct mf6c *rt;
803	u_long hash;
804	struct rtdetq *rte;
805	u_short nstl;
806	char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
807
808	MFC6_LOCK();
809
810	MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
811		 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
812
813	/* If an entry already exists, just update the fields */
814	if (rt) {
815#ifdef MRT6DEBUG
816		if (V_mrt6debug & DEBUG_MFC) {
817		    log(LOG_DEBUG,
818			"add_m6fc no upcall h %d o %s g %s p %x\n",
819			ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
820			ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
821			mfccp->mf6cc_parent);
822		}
823#endif
824
825		rt->mf6c_parent = mfccp->mf6cc_parent;
826		rt->mf6c_ifset = mfccp->mf6cc_ifset;
827
828		MFC6_UNLOCK();
829		return (0);
830	}
831
832	/*
833	 * Find the entry for which the upcall was made and update
834	 */
835	hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
836			mfccp->mf6cc_mcastgrp.sin6_addr);
837	for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
838		if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
839				       &mfccp->mf6cc_origin.sin6_addr) &&
840		    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
841				       &mfccp->mf6cc_mcastgrp.sin6_addr) &&
842		    (rt->mf6c_stall != NULL)) {
843
844			if (nstl++)
845				log(LOG_ERR,
846				    "add_m6fc: %s o %s g %s p %x dbx %p\n",
847				    "multiple kernel entries",
848				    ip6_sprintf(ip6bufo,
849					    &mfccp->mf6cc_origin.sin6_addr),
850				    ip6_sprintf(ip6bufg,
851					    &mfccp->mf6cc_mcastgrp.sin6_addr),
852				    mfccp->mf6cc_parent, rt->mf6c_stall);
853
854#ifdef MRT6DEBUG
855			if (V_mrt6debug & DEBUG_MFC)
856				log(LOG_DEBUG,
857				    "add_m6fc o %s g %s p %x dbg %x\n",
858				    ip6_sprintf(ip6bufo,
859					    &mfccp->mf6cc_origin.sin6_addr),
860				    ip6_sprintf(ip6bufg,
861					    &mfccp->mf6cc_mcastgrp.sin6_addr),
862				    mfccp->mf6cc_parent, rt->mf6c_stall);
863#endif
864
865			rt->mf6c_origin     = mfccp->mf6cc_origin;
866			rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
867			rt->mf6c_parent     = mfccp->mf6cc_parent;
868			rt->mf6c_ifset	    = mfccp->mf6cc_ifset;
869			/* initialize pkt counters per src-grp */
870			rt->mf6c_pkt_cnt    = 0;
871			rt->mf6c_byte_cnt   = 0;
872			rt->mf6c_wrong_if   = 0;
873
874			rt->mf6c_expire = 0;	/* Don't clean this guy up */
875			n6expire[hash]--;
876
877			/* free packets Qed at the end of this entry */
878			for (rte = rt->mf6c_stall; rte != NULL; ) {
879				struct rtdetq *n = rte->next;
880				ip6_mdq(rte->m, rte->ifp, rt);
881				m_freem(rte->m);
882#ifdef UPCALL_TIMING
883				collate(&(rte->t));
884#endif /* UPCALL_TIMING */
885				free(rte, M_MRTABLE6);
886				rte = n;
887			}
888			rt->mf6c_stall = NULL;
889		}
890	}
891
892	/*
893	 * It is possible that an entry is being inserted without an upcall
894	 */
895	if (nstl == 0) {
896#ifdef MRT6DEBUG
897		if (V_mrt6debug & DEBUG_MFC)
898		    log(LOG_DEBUG,
899			"add_mfc no upcall h %d o %s g %s p %x\n",
900			hash,
901			ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
902			ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
903			mfccp->mf6cc_parent);
904#endif
905
906		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
907
908			if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
909					       &mfccp->mf6cc_origin.sin6_addr)&&
910			    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
911					       &mfccp->mf6cc_mcastgrp.sin6_addr)) {
912
913				rt->mf6c_origin     = mfccp->mf6cc_origin;
914				rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
915				rt->mf6c_parent     = mfccp->mf6cc_parent;
916				rt->mf6c_ifset	    = mfccp->mf6cc_ifset;
917				/* initialize pkt counters per src-grp */
918				rt->mf6c_pkt_cnt    = 0;
919				rt->mf6c_byte_cnt   = 0;
920				rt->mf6c_wrong_if   = 0;
921
922				if (rt->mf6c_expire)
923					n6expire[hash]--;
924				rt->mf6c_expire	   = 0;
925			}
926		}
927		if (rt == NULL) {
928			/* no upcall, so make a new entry */
929			rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
930						  M_NOWAIT);
931			if (rt == NULL) {
932				MFC6_UNLOCK();
933				return (ENOBUFS);
934			}
935
936			/* insert new entry at head of hash chain */
937			rt->mf6c_origin     = mfccp->mf6cc_origin;
938			rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
939			rt->mf6c_parent     = mfccp->mf6cc_parent;
940			rt->mf6c_ifset	    = mfccp->mf6cc_ifset;
941			/* initialize pkt counters per src-grp */
942			rt->mf6c_pkt_cnt    = 0;
943			rt->mf6c_byte_cnt   = 0;
944			rt->mf6c_wrong_if   = 0;
945			rt->mf6c_expire     = 0;
946			rt->mf6c_stall = NULL;
947
948			/* link into table */
949			rt->mf6c_next  = mf6ctable[hash];
950			mf6ctable[hash] = rt;
951		}
952	}
953
954	MFC6_UNLOCK();
955	return (0);
956}
957
958#ifdef UPCALL_TIMING
959/*
960 * collect delay statistics on the upcalls
961 */
962static void
963collate(struct timeval *t)
964{
965	u_long d;
966	struct timeval tp;
967	u_long delta;
968
969	GET_TIME(tp);
970
971	if (TV_LT(*t, tp))
972	{
973		TV_DELTA(tp, *t, delta);
974
975		d = delta >> 10;
976		if (d > UPCALL_MAX)
977			d = UPCALL_MAX;
978
979		++upcall_data[d];
980	}
981}
982#endif /* UPCALL_TIMING */
983
984/*
985 * Delete an mfc entry
986 */
987static int
988del_m6fc(struct mf6cctl *mfccp)
989{
990	struct sockaddr_in6	origin;
991	struct sockaddr_in6	mcastgrp;
992	struct mf6c		*rt;
993	struct mf6c		**nptr;
994	u_long		hash;
995
996	origin = mfccp->mf6cc_origin;
997	mcastgrp = mfccp->mf6cc_mcastgrp;
998	hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
999
1000#ifdef MRT6DEBUG
1001	if (V_mrt6debug & DEBUG_MFC) {
1002		char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
1003		log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
1004		    ip6_sprintf(ip6bufo, &origin.sin6_addr),
1005		    ip6_sprintf(ip6bufg, &mcastgrp.sin6_addr));
1006	}
1007#endif
1008
1009	MFC6_LOCK();
1010
1011	nptr = &mf6ctable[hash];
1012	while ((rt = *nptr) != NULL) {
1013		if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
1014				       &rt->mf6c_origin.sin6_addr) &&
1015		    IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
1016				       &rt->mf6c_mcastgrp.sin6_addr) &&
1017		    rt->mf6c_stall == NULL)
1018			break;
1019
1020		nptr = &rt->mf6c_next;
1021	}
1022	if (rt == NULL) {
1023		MFC6_UNLOCK();
1024		return (EADDRNOTAVAIL);
1025	}
1026
1027	*nptr = rt->mf6c_next;
1028	free(rt, M_MRTABLE6);
1029
1030	MFC6_UNLOCK();
1031
1032	return (0);
1033}
1034
1035static int
1036socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src)
1037{
1038
1039	if (s) {
1040		if (sbappendaddr(&s->so_rcv,
1041				 (struct sockaddr *)src,
1042				 mm, (struct mbuf *)0) != 0) {
1043			sorwakeup(s);
1044			return (0);
1045		}
1046	}
1047	m_freem(mm);
1048	return (-1);
1049}
1050
1051/*
1052 * IPv6 multicast forwarding function. This function assumes that the packet
1053 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
1054 * pointed to by "ifp", and the packet is to be relayed to other networks
1055 * that have members of the packet's destination IPv6 multicast group.
1056 *
1057 * The packet is returned unscathed to the caller, unless it is
1058 * erroneous, in which case a non-zero return value tells the caller to
1059 * discard it.
1060 *
1061 * NOTE: this implementation assumes that m->m_pkthdr.rcvif is NULL iff
1062 * this function is called in the originating context (i.e., not when
1063 * forwarding a packet from other node).  ip6_output(), which is currently the
1064 * only function that calls this function is called in the originating context,
1065 * explicitly ensures this condition.  It is caller's responsibility to ensure
1066 * that if this function is called from somewhere else in the originating
1067 * context in the future.
1068 */
1069int
1070X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
1071{
1072	struct mf6c *rt;
1073	struct mif6 *mifp;
1074	struct mbuf *mm;
1075	mifi_t mifi;
1076	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1077
1078#ifdef MRT6DEBUG
1079	if (V_mrt6debug & DEBUG_FORWARD)
1080		log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n",
1081		    ip6_sprintf(ip6bufs, &ip6->ip6_src),
1082		    ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1083		    ifp->if_index);
1084#endif
1085
1086	/*
1087	 * Don't forward a packet with Hop limit of zero or one,
1088	 * or a packet destined to a local-only group.
1089	 */
1090	if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
1091	    IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1092		return (0);
1093	ip6->ip6_hlim--;
1094
1095	/*
1096	 * Source address check: do not forward packets with unspecified
1097	 * source. It was discussed in July 2000, on ipngwg mailing list.
1098	 * This is rather more serious than unicast cases, because some
1099	 * MLD packets can be sent with the unspecified source address
1100	 * (although such packets must normally set 1 to the hop limit field).
1101	 */
1102	if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
1103		V_ip6stat.ip6s_cantforward++;
1104		if (V_ip6_log_time + V_ip6_log_interval < time_second) {
1105			V_ip6_log_time = time_second;
1106			log(LOG_DEBUG,
1107			    "cannot forward "
1108			    "from %s to %s nxt %d received on %s\n",
1109			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
1110			    ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1111			    ip6->ip6_nxt,
1112			    if_name(m->m_pkthdr.rcvif));
1113		}
1114		return (0);
1115	}
1116
1117	MFC6_LOCK();
1118
1119	/*
1120	 * Determine forwarding mifs from the forwarding cache table
1121	 */
1122	MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
1123
1124	/* Entry exists, so forward if necessary */
1125	if (rt) {
1126		MFC6_UNLOCK();
1127		return (ip6_mdq(m, ifp, rt));
1128	} else {
1129		/*
1130		 * If we don't have a route for packet's origin,
1131		 * Make a copy of the packet &
1132		 * send message to routing daemon
1133		 */
1134
1135		struct mbuf *mb0;
1136		struct rtdetq *rte;
1137		u_long hash;
1138/*		int i, npkts;*/
1139#ifdef UPCALL_TIMING
1140		struct timeval tp;
1141
1142		GET_TIME(tp);
1143#endif /* UPCALL_TIMING */
1144
1145		mrt6stat.mrt6s_no_route++;
1146#ifdef MRT6DEBUG
1147		if (V_mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
1148			log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
1149			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
1150			    ip6_sprintf(ip6bufd, &ip6->ip6_dst));
1151#endif
1152
1153		/*
1154		 * Allocate mbufs early so that we don't do extra work if we
1155		 * are just going to fail anyway.
1156		 */
1157		rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE6,
1158					      M_NOWAIT);
1159		if (rte == NULL) {
1160			MFC6_UNLOCK();
1161			return (ENOBUFS);
1162		}
1163		mb0 = m_copy(m, 0, M_COPYALL);
1164		/*
1165		 * Pullup packet header if needed before storing it,
1166		 * as other references may modify it in the meantime.
1167		 */
1168		if (mb0 &&
1169		    (M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
1170			mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
1171		if (mb0 == NULL) {
1172			free(rte, M_MRTABLE6);
1173			MFC6_UNLOCK();
1174			return (ENOBUFS);
1175		}
1176
1177		/* is there an upcall waiting for this packet? */
1178		hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
1179		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
1180			if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
1181					       &rt->mf6c_origin.sin6_addr) &&
1182			    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1183					       &rt->mf6c_mcastgrp.sin6_addr) &&
1184			    (rt->mf6c_stall != NULL))
1185				break;
1186		}
1187
1188		if (rt == NULL) {
1189			struct mrt6msg *im;
1190#ifdef MRT6_OINIT
1191			struct omrt6msg *oim;
1192#endif
1193
1194			/* no upcall, so make a new entry */
1195			rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
1196						  M_NOWAIT);
1197			if (rt == NULL) {
1198				free(rte, M_MRTABLE6);
1199				m_freem(mb0);
1200				MFC6_UNLOCK();
1201				return (ENOBUFS);
1202			}
1203			/*
1204			 * Make a copy of the header to send to the user
1205			 * level process
1206			 */
1207			mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
1208
1209			if (mm == NULL) {
1210				free(rte, M_MRTABLE6);
1211				m_freem(mb0);
1212				free(rt, M_MRTABLE6);
1213				MFC6_UNLOCK();
1214				return (ENOBUFS);
1215			}
1216
1217			/*
1218			 * Send message to routing daemon
1219			 */
1220			sin6.sin6_addr = ip6->ip6_src;
1221
1222			im = NULL;
1223#ifdef MRT6_OINIT
1224			oim = NULL;
1225#endif
1226			switch (V_ip6_mrouter_ver) {
1227#ifdef MRT6_OINIT
1228			case MRT6_OINIT:
1229				oim = mtod(mm, struct omrt6msg *);
1230				oim->im6_msgtype = MRT6MSG_NOCACHE;
1231				oim->im6_mbz = 0;
1232				break;
1233#endif
1234			case MRT6_INIT:
1235				im = mtod(mm, struct mrt6msg *);
1236				im->im6_msgtype = MRT6MSG_NOCACHE;
1237				im->im6_mbz = 0;
1238				break;
1239			default:
1240				free(rte, M_MRTABLE6);
1241				m_freem(mb0);
1242				free(rt, M_MRTABLE6);
1243				MFC6_UNLOCK();
1244				return (EINVAL);
1245			}
1246
1247#ifdef MRT6DEBUG
1248			if (V_mrt6debug & DEBUG_FORWARD)
1249				log(LOG_DEBUG,
1250				    "getting the iif info in the kernel\n");
1251#endif
1252
1253			for (mifp = mif6table, mifi = 0;
1254			     mifi < nummifs && mifp->m6_ifp != ifp;
1255			     mifp++, mifi++)
1256				;
1257
1258			switch (V_ip6_mrouter_ver) {
1259#ifdef MRT6_OINIT
1260			case MRT6_OINIT:
1261				oim->im6_mif = mifi;
1262				break;
1263#endif
1264			case MRT6_INIT:
1265				im->im6_mif = mifi;
1266				break;
1267			}
1268
1269			if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1270				log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
1271				    "socket queue full\n");
1272				mrt6stat.mrt6s_upq_sockfull++;
1273				free(rte, M_MRTABLE6);
1274				m_freem(mb0);
1275				free(rt, M_MRTABLE6);
1276				MFC6_UNLOCK();
1277				return (ENOBUFS);
1278			}
1279
1280			mrt6stat.mrt6s_upcalls++;
1281
1282			/* insert new entry at head of hash chain */
1283			bzero(rt, sizeof(*rt));
1284			rt->mf6c_origin.sin6_family = AF_INET6;
1285			rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6);
1286			rt->mf6c_origin.sin6_addr = ip6->ip6_src;
1287			rt->mf6c_mcastgrp.sin6_family = AF_INET6;
1288			rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
1289			rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
1290			rt->mf6c_expire = UPCALL_EXPIRE;
1291			n6expire[hash]++;
1292			rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
1293
1294			/* link into table */
1295			rt->mf6c_next  = mf6ctable[hash];
1296			mf6ctable[hash] = rt;
1297			/* Add this entry to the end of the queue */
1298			rt->mf6c_stall = rte;
1299		} else {
1300			/* determine if q has overflowed */
1301			struct rtdetq **p;
1302			int npkts = 0;
1303
1304			for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
1305				if (++npkts > MAX_UPQ6) {
1306					mrt6stat.mrt6s_upq_ovflw++;
1307					free(rte, M_MRTABLE6);
1308					m_freem(mb0);
1309					MFC6_UNLOCK();
1310					return (0);
1311				}
1312
1313			/* Add this entry to the end of the queue */
1314			*p = rte;
1315		}
1316
1317		rte->next = NULL;
1318		rte->m = mb0;
1319		rte->ifp = ifp;
1320#ifdef UPCALL_TIMING
1321		rte->t = tp;
1322#endif /* UPCALL_TIMING */
1323
1324		MFC6_UNLOCK();
1325
1326		return (0);
1327	}
1328}
1329
1330/*
1331 * Clean up cache entries if upcalls are not serviced
1332 * Call from the Slow Timeout mechanism, every half second.
1333 */
1334static void
1335expire_upcalls(void *unused)
1336{
1337	struct rtdetq *rte;
1338	struct mf6c *mfc, **nptr;
1339	int i;
1340
1341	MFC6_LOCK();
1342	for (i = 0; i < MF6CTBLSIZ; i++) {
1343		if (n6expire[i] == 0)
1344			continue;
1345		nptr = &mf6ctable[i];
1346		while ((mfc = *nptr) != NULL) {
1347			rte = mfc->mf6c_stall;
1348			/*
1349			 * Skip real cache entries
1350			 * Make sure it wasn't marked to not expire (shouldn't happen)
1351			 * If it expires now
1352			 */
1353			if (rte != NULL &&
1354			    mfc->mf6c_expire != 0 &&
1355			    --mfc->mf6c_expire == 0) {
1356#ifdef MRT6DEBUG
1357				if (V_mrt6debug & DEBUG_EXPIRE) {
1358					char ip6bufo[INET6_ADDRSTRLEN];
1359					char ip6bufg[INET6_ADDRSTRLEN];
1360					log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n",
1361					    ip6_sprintf(ip6bufo, &mfc->mf6c_origin.sin6_addr),
1362					    ip6_sprintf(ip6bufg, &mfc->mf6c_mcastgrp.sin6_addr));
1363				}
1364#endif
1365				/*
1366				 * drop all the packets
1367				 * free the mbuf with the pkt, if, timing info
1368				 */
1369				do {
1370					struct rtdetq *n = rte->next;
1371					m_freem(rte->m);
1372					free(rte, M_MRTABLE6);
1373					rte = n;
1374				} while (rte != NULL);
1375				mrt6stat.mrt6s_cache_cleanups++;
1376				n6expire[i]--;
1377
1378				*nptr = mfc->mf6c_next;
1379				free(mfc, M_MRTABLE6);
1380			} else {
1381				nptr = &mfc->mf6c_next;
1382			}
1383		}
1384	}
1385	MFC6_UNLOCK();
1386	callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
1387	    expire_upcalls, NULL);
1388}
1389
1390/*
1391 * Packet forwarding routine once entry in the cache is made
1392 */
1393static int
1394ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt)
1395{
1396	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1397	mifi_t mifi, iif;
1398	struct mif6 *mifp;
1399	int plen = m->m_pkthdr.len;
1400	struct in6_addr src0, dst0; /* copies for local work */
1401	u_int32_t iszone, idzone, oszone, odzone;
1402	int error = 0;
1403
1404/*
1405 * Macro to send packet on mif.  Since RSVP packets don't get counted on
1406 * input, they shouldn't get counted on output, so statistics keeping is
1407 * separate.
1408 */
1409
1410#define MC6_SEND(ip6, mifp, m) do {				\
1411	if ((mifp)->m6_flags & MIFF_REGISTER)			\
1412		register_send((ip6), (mifp), (m));		\
1413	else							\
1414		phyint_send((ip6), (mifp), (m));		\
1415} while (/*CONSTCOND*/ 0)
1416
1417	/*
1418	 * Don't forward if it didn't arrive from the parent mif
1419	 * for its origin.
1420	 */
1421	mifi = rt->mf6c_parent;
1422	if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
1423		/* came in the wrong interface */
1424#ifdef MRT6DEBUG
1425		if (V_mrt6debug & DEBUG_FORWARD)
1426			log(LOG_DEBUG,
1427			    "wrong if: ifid %d mifi %d mififid %x\n",
1428			    ifp->if_index, mifi,
1429			    mif6table[mifi].m6_ifp->if_index);
1430#endif
1431		mrt6stat.mrt6s_wrong_if++;
1432		rt->mf6c_wrong_if++;
1433		/*
1434		 * If we are doing PIM processing, and we are forwarding
1435		 * packets on this interface, send a message to the
1436		 * routing daemon.
1437		 */
1438		/* have to make sure this is a valid mif */
1439		if (mifi < nummifs && mif6table[mifi].m6_ifp)
1440			if (V_pim6 && (m->m_flags & M_LOOP) == 0) {
1441				/*
1442				 * Check the M_LOOP flag to avoid an
1443				 * unnecessary PIM assert.
1444				 * XXX: M_LOOP is an ad-hoc hack...
1445				 */
1446				static struct sockaddr_in6 sin6 =
1447				{ sizeof(sin6), AF_INET6 };
1448
1449				struct mbuf *mm;
1450				struct mrt6msg *im;
1451#ifdef MRT6_OINIT
1452				struct omrt6msg *oim;
1453#endif
1454
1455				mm = m_copy(m, 0, sizeof(struct ip6_hdr));
1456				if (mm &&
1457				    (M_HASCL(mm) ||
1458				     mm->m_len < sizeof(struct ip6_hdr)))
1459					mm = m_pullup(mm, sizeof(struct ip6_hdr));
1460				if (mm == NULL)
1461					return (ENOBUFS);
1462
1463#ifdef MRT6_OINIT
1464				oim = NULL;
1465#endif
1466				im = NULL;
1467				switch (V_ip6_mrouter_ver) {
1468#ifdef MRT6_OINIT
1469				case MRT6_OINIT:
1470					oim = mtod(mm, struct omrt6msg *);
1471					oim->im6_msgtype = MRT6MSG_WRONGMIF;
1472					oim->im6_mbz = 0;
1473					break;
1474#endif
1475				case MRT6_INIT:
1476					im = mtod(mm, struct mrt6msg *);
1477					im->im6_msgtype = MRT6MSG_WRONGMIF;
1478					im->im6_mbz = 0;
1479					break;
1480				default:
1481					m_freem(mm);
1482					return (EINVAL);
1483				}
1484
1485				for (mifp = mif6table, iif = 0;
1486				     iif < nummifs && mifp &&
1487					     mifp->m6_ifp != ifp;
1488				     mifp++, iif++)
1489					;
1490
1491				switch (V_ip6_mrouter_ver) {
1492#ifdef MRT6_OINIT
1493				case MRT6_OINIT:
1494					oim->im6_mif = iif;
1495					sin6.sin6_addr = oim->im6_src;
1496					break;
1497#endif
1498				case MRT6_INIT:
1499					im->im6_mif = iif;
1500					sin6.sin6_addr = im->im6_src;
1501					break;
1502				}
1503
1504				mrt6stat.mrt6s_upcalls++;
1505
1506				if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1507#ifdef MRT6DEBUG
1508					if (V_mrt6debug)
1509						log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
1510#endif
1511					++mrt6stat.mrt6s_upq_sockfull;
1512					return (ENOBUFS);
1513				}	/* if socket Q full */
1514			}		/* if PIM */
1515		return (0);
1516	}			/* if wrong iif */
1517
1518	/* If I sourced this packet, it counts as output, else it was input. */
1519	if (m->m_pkthdr.rcvif == NULL) {
1520		/* XXX: is rcvif really NULL when output?? */
1521		mif6table[mifi].m6_pkt_out++;
1522		mif6table[mifi].m6_bytes_out += plen;
1523	} else {
1524		mif6table[mifi].m6_pkt_in++;
1525		mif6table[mifi].m6_bytes_in += plen;
1526	}
1527	rt->mf6c_pkt_cnt++;
1528	rt->mf6c_byte_cnt += plen;
1529
1530	/*
1531	 * For each mif, forward a copy of the packet if there are group
1532	 * members downstream on the interface.
1533	 */
1534	src0 = ip6->ip6_src;
1535	dst0 = ip6->ip6_dst;
1536	if ((error = in6_setscope(&src0, ifp, &iszone)) != 0 ||
1537	    (error = in6_setscope(&dst0, ifp, &idzone)) != 0) {
1538		V_ip6stat.ip6s_badscope++;
1539		return (error);
1540	}
1541	for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
1542		if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
1543			/*
1544			 * check if the outgoing packet is going to break
1545			 * a scope boundary.
1546			 * XXX For packets through PIM register tunnel
1547			 * interface, we believe a routing daemon.
1548			 */
1549			if (!(mif6table[rt->mf6c_parent].m6_flags &
1550			      MIFF_REGISTER) &&
1551			    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
1552				if (in6_setscope(&src0, mif6table[mifi].m6_ifp,
1553				    &oszone) ||
1554				    in6_setscope(&dst0, mif6table[mifi].m6_ifp,
1555				    &odzone) ||
1556				    iszone != oszone ||
1557				    idzone != odzone) {
1558					V_ip6stat.ip6s_badscope++;
1559					continue;
1560				}
1561			}
1562
1563			mifp->m6_pkt_out++;
1564			mifp->m6_bytes_out += plen;
1565			MC6_SEND(ip6, mifp, m);
1566		}
1567	}
1568	return (0);
1569}
1570
1571static void
1572phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
1573{
1574	struct mbuf *mb_copy;
1575	struct ifnet *ifp = mifp->m6_ifp;
1576	int error = 0;
1577	u_long linkmtu;
1578
1579	/*
1580	 * Make a new reference to the packet; make sure that
1581	 * the IPv6 header is actually copied, not just referenced,
1582	 * so that ip6_output() only scribbles on the copy.
1583	 */
1584	mb_copy = m_copy(m, 0, M_COPYALL);
1585	if (mb_copy &&
1586	    (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
1587		mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
1588	if (mb_copy == NULL) {
1589		return;
1590	}
1591	/* set MCAST flag to the outgoing packet */
1592	mb_copy->m_flags |= M_MCAST;
1593
1594	/*
1595	 * If we sourced the packet, call ip6_output since we may devide
1596	 * the packet into fragments when the packet is too big for the
1597	 * outgoing interface.
1598	 * Otherwise, we can simply send the packet to the interface
1599	 * sending queue.
1600	 */
1601	if (m->m_pkthdr.rcvif == NULL) {
1602		struct ip6_moptions im6o;
1603
1604		im6o.im6o_multicast_ifp = ifp;
1605		/* XXX: ip6_output will override ip6->ip6_hlim */
1606		im6o.im6o_multicast_hlim = ip6->ip6_hlim;
1607		im6o.im6o_multicast_loop = 1;
1608		error = ip6_output(mb_copy, NULL, NULL, IPV6_FORWARDING, &im6o,
1609		    NULL, NULL);
1610
1611#ifdef MRT6DEBUG
1612		if (V_mrt6debug & DEBUG_XMIT)
1613			log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1614			    mifp - mif6table, error);
1615#endif
1616		return;
1617	}
1618
1619	/*
1620	 * If configured to loop back multicasts by default,
1621	 * loop back a copy now.
1622	 */
1623	if (in6_mcast_loop) {
1624		struct sockaddr_in6 dst6;
1625
1626		bzero(&dst6, sizeof(dst6));
1627		dst6.sin6_len = sizeof(struct sockaddr_in6);
1628		dst6.sin6_family = AF_INET6;
1629		dst6.sin6_addr = ip6->ip6_dst;
1630		ip6_mloopback(ifp, m, &dst6);
1631	}
1632
1633	/*
1634	 * Put the packet into the sending queue of the outgoing interface
1635	 * if it would fit in the MTU of the interface.
1636	 */
1637	linkmtu = IN6_LINKMTU(ifp);
1638	if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) {
1639		struct sockaddr_in6 dst6;
1640
1641		bzero(&dst6, sizeof(dst6));
1642		dst6.sin6_len = sizeof(struct sockaddr_in6);
1643		dst6.sin6_family = AF_INET6;
1644		dst6.sin6_addr = ip6->ip6_dst;
1645		/*
1646		 * We just call if_output instead of nd6_output here, since
1647		 * we need no ND for a multicast forwarded packet...right?
1648		 */
1649		error = (*ifp->if_output)(ifp, mb_copy,
1650		    (struct sockaddr *)&dst6, NULL);
1651#ifdef MRT6DEBUG
1652		if (V_mrt6debug & DEBUG_XMIT)
1653			log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1654			    mifp - mif6table, error);
1655#endif
1656	} else {
1657		/*
1658		 * pMTU discovery is intentionally disabled by default, since
1659		 * various router may notify pMTU in multicast, which can be
1660		 * a DDoS to a router
1661		 */
1662		if (V_ip6_mcast_pmtu)
1663			icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, linkmtu);
1664		else {
1665#ifdef MRT6DEBUG
1666			if (V_mrt6debug & DEBUG_XMIT) {
1667				char ip6bufs[INET6_ADDRSTRLEN];
1668				char ip6bufd[INET6_ADDRSTRLEN];
1669				log(LOG_DEBUG,
1670				    "phyint_send: packet too big on %s o %s "
1671				    "g %s size %d(discarded)\n",
1672				    if_name(ifp),
1673				    ip6_sprintf(ip6bufs, &ip6->ip6_src),
1674				    ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1675				    mb_copy->m_pkthdr.len);
1676			}
1677#endif /* MRT6DEBUG */
1678			m_freem(mb_copy); /* simply discard the packet */
1679		}
1680	}
1681}
1682
1683static int
1684register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m)
1685{
1686	struct mbuf *mm;
1687	int i, len = m->m_pkthdr.len;
1688	static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
1689	struct mrt6msg *im6;
1690
1691#ifdef MRT6DEBUG
1692	if (V_mrt6debug) {
1693		char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1694		log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n",
1695		    ip6_sprintf(ip6bufs, &ip6->ip6_src),
1696		    ip6_sprintf(ip6bufd, &ip6->ip6_dst));
1697	}
1698#endif
1699	++pim6stat.pim6s_snd_registers;
1700
1701	/* Make a copy of the packet to send to the user level process. */
1702	mm = m_gethdr(M_NOWAIT, MT_DATA);
1703	if (mm == NULL)
1704		return (ENOBUFS);
1705	mm->m_data += max_linkhdr;
1706	mm->m_len = sizeof(struct ip6_hdr);
1707
1708	if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
1709		m_freem(mm);
1710		return (ENOBUFS);
1711	}
1712	i = MHLEN - M_LEADINGSPACE(mm);
1713	if (i > len)
1714		i = len;
1715	mm = m_pullup(mm, i);
1716	if (mm == NULL)
1717		return (ENOBUFS);
1718/* TODO: check it! */
1719	mm->m_pkthdr.len = len + sizeof(struct ip6_hdr);
1720
1721	/*
1722	 * Send message to routing daemon
1723	 */
1724	sin6.sin6_addr = ip6->ip6_src;
1725
1726	im6 = mtod(mm, struct mrt6msg *);
1727	im6->im6_msgtype      = MRT6MSG_WHOLEPKT;
1728	im6->im6_mbz          = 0;
1729
1730	im6->im6_mif = mif - mif6table;
1731
1732	/* iif info is not given for reg. encap.n */
1733	mrt6stat.mrt6s_upcalls++;
1734
1735	if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1736#ifdef MRT6DEBUG
1737		if (V_mrt6debug)
1738			log(LOG_WARNING,
1739			    "register_send: ip6_mrouter socket queue full\n");
1740#endif
1741		++mrt6stat.mrt6s_upq_sockfull;
1742		return (ENOBUFS);
1743	}
1744	return (0);
1745}
1746
1747/*
1748 * pim6_encapcheck() is called by the encap6_input() path at runtime to
1749 * determine if a packet is for PIM; allowing PIM to be dynamically loaded
1750 * into the kernel.
1751 */
1752static int
1753pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
1754{
1755
1756#ifdef DIAGNOSTIC
1757    KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
1758#endif
1759    if (proto != IPPROTO_PIM)
1760	return 0;	/* not for us; reject the datagram. */
1761
1762    return 64;		/* claim the datagram. */
1763}
1764
1765/*
1766 * PIM sparse mode hook
1767 * Receives the pim control messages, and passes them up to the listening
1768 * socket, using rip6_input.
1769 * The only message processed is the REGISTER pim message; the pim header
1770 * is stripped off, and the inner packet is passed to register_mforward.
1771 */
1772int
1773pim6_input(struct mbuf **mp, int *offp, int proto)
1774{
1775	struct pim *pim; /* pointer to a pim struct */
1776	struct ip6_hdr *ip6;
1777	int pimlen;
1778	struct mbuf *m = *mp;
1779	int minlen;
1780	int off = *offp;
1781
1782	++pim6stat.pim6s_rcv_total;
1783
1784	ip6 = mtod(m, struct ip6_hdr *);
1785	pimlen = m->m_pkthdr.len - *offp;
1786
1787	/*
1788	 * Validate lengths
1789	 */
1790	if (pimlen < PIM_MINLEN) {
1791		++pim6stat.pim6s_rcv_tooshort;
1792#ifdef MRT6DEBUG
1793		if (V_mrt6debug & DEBUG_PIM)
1794			log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
1795#endif
1796		m_freem(m);
1797		return (IPPROTO_DONE);
1798	}
1799
1800	/*
1801	 * if the packet is at least as big as a REGISTER, go ahead
1802	 * and grab the PIM REGISTER header size, to avoid another
1803	 * possible m_pullup() later.
1804	 *
1805	 * PIM_MINLEN       == pimhdr + u_int32 == 8
1806	 * PIM6_REG_MINLEN   == pimhdr + reghdr + eip6hdr == 4 + 4 + 40
1807	 */
1808	minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN;
1809
1810	/*
1811	 * Make sure that the IP6 and PIM headers in contiguous memory, and
1812	 * possibly the PIM REGISTER header
1813	 */
1814#ifndef PULLDOWN_TEST
1815	IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE);
1816	/* adjust pointer */
1817	ip6 = mtod(m, struct ip6_hdr *);
1818
1819	/* adjust mbuf to point to the PIM header */
1820	pim = (struct pim *)((caddr_t)ip6 + off);
1821#else
1822	IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen);
1823	if (pim == NULL) {
1824		pim6stat.pim6s_rcv_tooshort++;
1825		return (IPPROTO_DONE);
1826	}
1827#endif
1828
1829#define PIM6_CHECKSUM
1830#ifdef PIM6_CHECKSUM
1831	{
1832		int cksumlen;
1833
1834		/*
1835		 * Validate checksum.
1836		 * If PIM REGISTER, exclude the data packet
1837		 */
1838		if (pim->pim_type == PIM_REGISTER)
1839			cksumlen = PIM_MINLEN;
1840		else
1841			cksumlen = pimlen;
1842
1843		if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
1844			++pim6stat.pim6s_rcv_badsum;
1845#ifdef MRT6DEBUG
1846			if (V_mrt6debug & DEBUG_PIM)
1847				log(LOG_DEBUG,
1848				    "pim6_input: invalid checksum\n");
1849#endif
1850			m_freem(m);
1851			return (IPPROTO_DONE);
1852		}
1853	}
1854#endif /* PIM_CHECKSUM */
1855
1856	/* PIM version check */
1857	if (pim->pim_ver != PIM_VERSION) {
1858		++pim6stat.pim6s_rcv_badversion;
1859#ifdef MRT6DEBUG
1860		log(LOG_ERR,
1861		    "pim6_input: incorrect version %d, expecting %d\n",
1862		    pim->pim_ver, PIM_VERSION);
1863#endif
1864		m_freem(m);
1865		return (IPPROTO_DONE);
1866	}
1867
1868	if (pim->pim_type == PIM_REGISTER) {
1869		/*
1870		 * since this is a REGISTER, we'll make a copy of the register
1871		 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
1872		 * routing daemon.
1873		 */
1874		static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
1875
1876		struct mbuf *mcp;
1877		struct ip6_hdr *eip6;
1878		u_int32_t *reghdr;
1879		int rc;
1880#ifdef MRT6DEBUG
1881		char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1882#endif
1883
1884		++pim6stat.pim6s_rcv_registers;
1885
1886		if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
1887#ifdef MRT6DEBUG
1888			if (V_mrt6debug & DEBUG_PIM)
1889				log(LOG_DEBUG,
1890				    "pim6_input: register mif not set: %d\n",
1891				    reg_mif_num);
1892#endif
1893			m_freem(m);
1894			return (IPPROTO_DONE);
1895		}
1896
1897		reghdr = (u_int32_t *)(pim + 1);
1898
1899		if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
1900			goto pim6_input_to_daemon;
1901
1902		/*
1903		 * Validate length
1904		 */
1905		if (pimlen < PIM6_REG_MINLEN) {
1906			++pim6stat.pim6s_rcv_tooshort;
1907			++pim6stat.pim6s_rcv_badregisters;
1908#ifdef MRT6DEBUG
1909			log(LOG_ERR,
1910			    "pim6_input: register packet size too "
1911			    "small %d from %s\n",
1912			    pimlen, ip6_sprintf(ip6bufs, &ip6->ip6_src));
1913#endif
1914			m_freem(m);
1915			return (IPPROTO_DONE);
1916		}
1917
1918		eip6 = (struct ip6_hdr *) (reghdr + 1);
1919#ifdef MRT6DEBUG
1920		if (V_mrt6debug & DEBUG_PIM)
1921			log(LOG_DEBUG,
1922			    "pim6_input[register], eip6: %s -> %s, "
1923			    "eip6 plen %d\n",
1924			    ip6_sprintf(ip6bufs, &eip6->ip6_src),
1925			    ip6_sprintf(ip6bufd, &eip6->ip6_dst),
1926			    ntohs(eip6->ip6_plen));
1927#endif
1928
1929		/* verify the version number of the inner packet */
1930		if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1931			++pim6stat.pim6s_rcv_badregisters;
1932#ifdef MRT6DEBUG
1933			log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
1934			    "of the inner packet\n",
1935			    (eip6->ip6_vfc & IPV6_VERSION));
1936#endif
1937			m_freem(m);
1938			return (IPPROTO_NONE);
1939		}
1940
1941		/* verify the inner packet is destined to a mcast group */
1942		if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
1943			++pim6stat.pim6s_rcv_badregisters;
1944#ifdef MRT6DEBUG
1945			if (V_mrt6debug & DEBUG_PIM)
1946				log(LOG_DEBUG,
1947				    "pim6_input: inner packet of register "
1948				    "is not multicast %s\n",
1949				    ip6_sprintf(ip6bufd, &eip6->ip6_dst));
1950#endif
1951			m_freem(m);
1952			return (IPPROTO_DONE);
1953		}
1954
1955		/*
1956		 * make a copy of the whole header to pass to the daemon later.
1957		 */
1958		mcp = m_copy(m, 0, off + PIM6_REG_MINLEN);
1959		if (mcp == NULL) {
1960#ifdef MRT6DEBUG
1961			log(LOG_ERR,
1962			    "pim6_input: pim register: "
1963			    "could not copy register head\n");
1964#endif
1965			m_freem(m);
1966			return (IPPROTO_DONE);
1967		}
1968
1969		/*
1970		 * forward the inner ip6 packet; point m_data at the inner ip6.
1971		 */
1972		m_adj(m, off + PIM_MINLEN);
1973#ifdef MRT6DEBUG
1974		if (V_mrt6debug & DEBUG_PIM) {
1975			log(LOG_DEBUG,
1976			    "pim6_input: forwarding decapsulated register: "
1977			    "src %s, dst %s, mif %d\n",
1978			    ip6_sprintf(ip6bufs, &eip6->ip6_src),
1979			    ip6_sprintf(ip6bufd, &eip6->ip6_dst),
1980			    reg_mif_num);
1981		}
1982#endif
1983
1984		rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
1985				dst.sin6_family, 0);
1986
1987		/* prepare the register head to send to the mrouting daemon */
1988		m = mcp;
1989	}
1990
1991	/*
1992	 * Pass the PIM message up to the daemon; if it is a register message
1993	 * pass the 'head' only up to the daemon. This includes the
1994	 * encapsulator ip6 header, pim header, register header and the
1995	 * encapsulated ip6 header.
1996	 */
1997  pim6_input_to_daemon:
1998	rip6_input(&m, offp, proto);
1999	return (IPPROTO_DONE);
2000}
2001
2002static int
2003ip6_mroute_modevent(module_t mod, int type, void *unused)
2004{
2005
2006	switch (type) {
2007	case MOD_LOAD:
2008		MROUTER6_LOCK_INIT();
2009		MFC6_LOCK_INIT();
2010		MIF6_LOCK_INIT();
2011
2012		pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
2013			pim6_encapcheck,
2014			(const struct protosw *)&in6_pim_protosw, NULL);
2015		if (pim6_encap_cookie == NULL) {
2016			printf("ip6_mroute: unable to attach pim6 encap\n");
2017			MIF6_LOCK_DESTROY();
2018			MFC6_LOCK_DESTROY();
2019			MROUTER6_LOCK_DESTROY();
2020			return (EINVAL);
2021		}
2022
2023		ip6_mforward = X_ip6_mforward;
2024		ip6_mrouter_done = X_ip6_mrouter_done;
2025		ip6_mrouter_get = X_ip6_mrouter_get;
2026		ip6_mrouter_set = X_ip6_mrouter_set;
2027		mrt6_ioctl = X_mrt6_ioctl;
2028		break;
2029
2030	case MOD_UNLOAD:
2031		if (V_ip6_mrouter != NULL)
2032			return EINVAL;
2033
2034		if (pim6_encap_cookie) {
2035			encap_detach(pim6_encap_cookie);
2036			pim6_encap_cookie = NULL;
2037		}
2038		X_ip6_mrouter_done();
2039		ip6_mforward = NULL;
2040		ip6_mrouter_done = NULL;
2041		ip6_mrouter_get = NULL;
2042		ip6_mrouter_set = NULL;
2043		mrt6_ioctl = NULL;
2044
2045		MIF6_LOCK_DESTROY();
2046		MFC6_LOCK_DESTROY();
2047		MROUTER6_LOCK_DESTROY();
2048		break;
2049
2050	default:
2051		return (EOPNOTSUPP);
2052	}
2053
2054	return (0);
2055}
2056
2057static moduledata_t ip6_mroutemod = {
2058	"ip6_mroute",
2059	ip6_mroute_modevent,
2060	0
2061};
2062
2063DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
2064