ip6_mroute.c revision 56738
1/*
2 * Copyright (C) 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/netinet6/ip6_mroute.c 56723 2000-01-28 05:27:14Z shin $
30 */
31
32/*	BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp	*/
33
34/*
35 * IP multicast forwarding procedures
36 *
37 * Written by David Waitzman, BBN Labs, August 1988.
38 * Modified by Steve Deering, Stanford, February 1989.
39 * Modified by Mark J. Steiglitz, Stanford, May, 1991
40 * Modified by Van Jacobson, LBL, January 1993
41 * Modified by Ajit Thyagarajan, PARC, August 1993
42 * Modified by Bill Fenenr, PARC, April 1994
43 *
44 * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
45 */
46
47#include "opt_inet.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/malloc.h>
52#include <sys/mbuf.h>
53#include <sys/socket.h>
54#include <sys/socketvar.h>
55#include <sys/sockio.h>
56#include <sys/protosw.h>
57#include <sys/errno.h>
58#include <sys/time.h>
59#include <sys/kernel.h>
60#include <sys/sockio.h>
61#include <sys/syslog.h>
62
63#include <net/if.h>
64#include <net/route.h>
65#include <net/raw_cb.h>
66
67#include <netinet/in.h>
68#include <netinet/in_var.h>
69
70#include <netinet6/ip6.h>
71#include <netinet6/ip6_var.h>
72#include <netinet6/ip6_mroute.h>
73#include <netinet6/pim6.h>
74#include <netinet6/pim6_var.h>
75
76static MALLOC_DEFINE(M_MRTABLE, "mf6c", "multicast forwarding cache entry");
77
78#define	M_HASCL(m) ((m)->m_flags & M_EXT)
79
80static int	ip6_mdq __P((struct mbuf *, struct ifnet *, struct mf6c *));
81static void	phyint_send __P((struct ip6_hdr *, struct mif6 *,
82				 struct mbuf *));
83
84static int	set_pim6 __P((int *));
85static int	socket_send __P((struct socket *, struct mbuf *,
86				 struct sockaddr_in6 *));
87static int	register_send __P((struct ip6_hdr *, struct mif6 *,
88				   struct mbuf *));
89
90/*
91 * Globals.  All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static,
92 * except for netstat or debugging purposes.
93 */
94struct	socket	*ip6_mrouter  = NULL;
95int	ip6_mrtproto = IPPROTO_PIM;    /* for netstat only */
96struct	mrt6stat	mrt6stat;
97
98#define	NO_RTE_FOUND 	0x1
99#define	RTE_FOUND	0x2
100
101struct	mf6c	*mf6ctable[MF6CTBLSIZ];
102u_char	nexpire[MF6CTBLSIZ];
103static	struct mif6 mif6table[MAXMIFS];
104#ifdef MRT6DEBUG
105u_int		mrt6debug = 0;	  /* debug level 	*/
106#define	DEBUG_MFC	0x02
107#define	DEBUG_FORWARD	0x04
108#define	DEBUG_EXPIRE	0x08
109#define	DEBUG_XMIT	0x10
110#define	DEBUG_REG       0x20
111#define	DEBUG_PIM       0x40
112#endif
113
114static void	expire_upcalls __P((void *));
115#define	EXPIRE_TIMEOUT	(hz / 4)	/* 4x / second */
116#define	UPCALL_EXPIRE	6		/* number of timeouts */
117
118#ifdef INET
119#ifdef MROUTING
120extern struct socket *ip_mrouter;
121#endif
122#endif
123
124/*
125 * 'Interfaces' associated with decapsulator (so we can tell
126 * packets that went through it from ones that get reflected
127 * by a broken gateway).  These interfaces are never linked into
128 * the system ifnet list & no routes point to them.  I.e., packets
129 * can't be sent this way.  They only exist as a placeholder for
130 * multicast source verification.
131 */
132struct ifnet multicast_register_if;
133
134#define	ENCAP_HOPS 64
135
136/*
137 * Private variables.
138 */
139static mifi_t nummifs = 0;
140static mifi_t reg_mif_num = (mifi_t)-1;
141
142static struct pim6stat pim6stat;
143static struct callout_handle expire_upcalls_ch;
144
145/*
146 * one-back cache used by ipip_input to locate a tunnel's mif
147 * given a datagram's src ip address.
148 */
149static int pim6;
150
151/*
152 * Hash function for a source, group entry
153 */
154#define	MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
155				   (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
156				   (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
157				   (g).s6_addr32[2] ^ (g).s6_addr32[3])
158
159/*
160 * Find a route for a given origin IPv6 address and Multicast group address.
161 * Quality of service parameter to be added in the future!!!
162 */
163
164#define	MF6CFIND(o, g, rt) { \
165	register struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
166	rt = NULL; \
167	mrt6stat.mrt6s_mfc_lookups++; \
168	while (_rt) { \
169		if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
170		    IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
171		    (_rt->mf6c_stall == NULL)) { \
172			rt = _rt; \
173			break; \
174		} \
175		_rt = _rt->mf6c_next; \
176	} \
177	if (rt == NULL) { \
178		mrt6stat.mrt6s_mfc_misses++; \
179	} \
180}
181
182/*
183 * Macros to compute elapsed time efficiently
184 * Borrowed from Van Jacobson's scheduling code
185 */
186#define	TV_DELTA(a, b, delta) { \
187	    register int xxs; \
188		\
189	    delta = (a).tv_usec - (b).tv_usec; \
190	    if ((xxs = (a).tv_sec - (b).tv_sec)) { \
191	       switch (xxs) { \
192		      case 2: \
193			  delta += 1000000; \
194			      /* fall through */ \
195		      case 1: \
196			  delta += 1000000; \
197			  break; \
198		      default: \
199			  delta += (1000000 * xxs); \
200	       } \
201	    } \
202}
203
204#define	TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
205	      (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
206
207#ifdef UPCALL_TIMING
208#define	UPCALL_MAX	50
209u_long upcall_data[UPCALL_MAX + 1];
210static void collate();
211#endif /* UPCALL_TIMING */
212
213static int get_sg_cnt __P((struct sioc_sg_req6 *));
214static int get_mif6_cnt __P((struct sioc_mif_req6 *));
215static int ip6_mrouter_init __P((struct socket *, struct mbuf *));
216static int add_m6if __P((struct mif6ctl *));
217static int del_m6if __P((mifi_t *));
218static int add_m6fc __P((struct mf6cctl *));
219static int del_m6fc __P((struct mf6cctl *));
220
221/*
222 * Handle MRT setsockopt commands to modify the multicast routing tables.
223 */
224int
225ip6_mrouter_set(so, sopt)
226	struct socket *so;
227	struct sockopt *sopt;
228{
229	int	error = 0;
230	struct mbuf *m;
231
232	if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT)
233		return (EACCES);
234
235	if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
236		return (error);
237	if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
238		return (error);
239
240	switch (sopt->sopt_name) {
241	 case MRT6_INIT:
242		 error = ip6_mrouter_init(so, m);
243		 break;
244	 case MRT6_DONE:
245		 error = ip6_mrouter_done();
246		 break;
247	 case MRT6_ADD_MIF:
248		 error = add_m6if(mtod(m, struct mif6ctl *));
249		 break;
250	 case MRT6_DEL_MIF:
251		 error = del_m6if(mtod(m, mifi_t *));
252		 break;
253	 case MRT6_ADD_MFC:
254		 error = add_m6fc(mtod(m, struct mf6cctl *));
255		 break;
256	 case MRT6_DEL_MFC:
257		 error = del_m6fc(mtod(m, struct mf6cctl *));
258		 break;
259	 case MRT6_PIM:
260		 error = set_pim6(mtod(m, int *));
261		 break;
262	 default:
263		 error = EOPNOTSUPP;
264		 break;
265	}
266
267	(void)m_freem(m);
268	return(error);
269}
270
271/*
272 * Handle MRT getsockopt commands
273 */
274int
275ip6_mrouter_get(so, sopt)
276	struct socket *so;
277	struct sockopt *sopt;
278{
279	int error = 0;
280
281	if (so != ip6_mrouter) return EACCES;
282
283	switch (sopt->sopt_name) {
284		case MRT6_PIM:
285			error = sooptcopyout(sopt, &pim6, sizeof(pim6));
286			break;
287	}
288	return (error);
289}
290
291/*
292 * Handle ioctl commands to obtain information from the cache
293 */
294int
295mrt6_ioctl(cmd, data)
296	int cmd;
297	caddr_t data;
298{
299    int error = 0;
300
301    switch (cmd) {
302     case SIOCGETSGCNT_IN6:
303	     return(get_sg_cnt((struct sioc_sg_req6 *)data));
304	     break;		/* for safety */
305     case SIOCGETMIFCNT_IN6:
306	     return(get_mif6_cnt((struct sioc_mif_req6 *)data));
307	     break;		/* for safety */
308     default:
309	     return (EINVAL);
310	     break;
311    }
312    return error;
313}
314
315/*
316 * returns the packet, byte, rpf-failure count for the source group provided
317 */
318static int
319get_sg_cnt(req)
320	register struct sioc_sg_req6 *req;
321{
322	register struct mf6c *rt;
323	int s;
324
325	s = splnet();
326	MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
327	splx(s);
328	if (rt != NULL) {
329		req->pktcnt = rt->mf6c_pkt_cnt;
330		req->bytecnt = rt->mf6c_byte_cnt;
331		req->wrong_if = rt->mf6c_wrong_if;
332	} else
333		return(ESRCH);
334
335	return 0;
336}
337
338/*
339 * returns the input and output packet and byte counts on the mif provided
340 */
341static int
342get_mif6_cnt(req)
343	register struct sioc_mif_req6 *req;
344{
345	register mifi_t mifi = req->mifi;
346
347	if (mifi >= nummifs)
348		return EINVAL;
349
350	req->icount = mif6table[mifi].m6_pkt_in;
351	req->ocount = mif6table[mifi].m6_pkt_out;
352	req->ibytes = mif6table[mifi].m6_bytes_in;
353	req->obytes = mif6table[mifi].m6_bytes_out;
354
355	return 0;
356}
357
358static int
359set_pim6(i)
360	int *i;
361{
362	if ((*i != 1) && (*i != 0))
363		return EINVAL;
364
365	pim6 = *i;
366
367	return 0;
368}
369
370/*
371 * Enable multicast routing
372 */
373static int
374ip6_mrouter_init(so, m)
375	struct socket *so;
376	struct mbuf *m;
377{
378	int *v;
379
380#ifdef MRT6DEBUG
381	if (mrt6debug)
382		log(LOG_DEBUG,
383		    "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
384		    so->so_type, so->so_proto->pr_protocol);
385#endif
386
387	if (so->so_type != SOCK_RAW ||
388	    so->so_proto->pr_protocol != IPPROTO_ICMPV6)
389		return EOPNOTSUPP;
390
391	if (!m || (m->m_len != sizeof(int *)))
392		return ENOPROTOOPT;
393
394	v = mtod(m, int *);
395	if (*v != 1)
396		return ENOPROTOOPT;
397
398	if (ip6_mrouter != NULL) return EADDRINUSE;
399
400	ip6_mrouter = so;
401
402	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
403	bzero((caddr_t)nexpire, sizeof(nexpire));
404
405	pim6 = 0;/* used for stubbing out/in pim stuff */
406
407	expire_upcalls_ch =
408		timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
409
410#ifdef MRT6DEBUG
411	if (mrt6debug)
412		log(LOG_DEBUG, "ip6_mrouter_init\n");
413#endif
414
415	return 0;
416}
417
418/*
419 * Disable multicast routing
420 */
421int
422ip6_mrouter_done()
423{
424	mifi_t mifi;
425	int i;
426	struct ifnet *ifp;
427	struct in6_ifreq ifr;
428	struct mf6c *rt;
429	struct rtdetq *rte;
430	int s;
431
432	s = splnet();
433
434	/*
435	 * For each phyint in use, disable promiscuous reception of all IPv6
436	 * multicasts.
437	 */
438#ifdef INET
439#ifdef MROUTING
440	/*
441	 * If there is still IPv4 multicast routing daemon,
442	 * we remain interfaces to receive all muliticasted packets.
443	 * XXX: there may be an interface in which the IPv4 multicast
444	 * daemon is not interested...
445	 */
446	if (!ip_mrouter)
447#endif
448#endif
449	{
450		for (mifi = 0; mifi < nummifs; mifi++) {
451			if (mif6table[mifi].m6_ifp &&
452			    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
453				ifr.ifr_addr.sin6_family = AF_INET6;
454				ifr.ifr_addr.sin6_addr= in6addr_any;
455				ifp = mif6table[mifi].m6_ifp;
456				(*ifp->if_ioctl)(ifp, SIOCDELMULTI,
457						 (caddr_t)&ifr);
458			}
459		}
460	}
461	bzero((caddr_t)mif6table, sizeof(mif6table));
462	nummifs = 0;
463
464	pim6 = 0; /* used to stub out/in pim specific code */
465
466	untimeout(expire_upcalls, (caddr_t)NULL, expire_upcalls_ch);
467
468	/*
469	 * Free all multicast forwarding cache entries.
470	 */
471	for (i = 0; i < MF6CTBLSIZ; i++) {
472		rt = mf6ctable[i];
473		while (rt) {
474			struct mf6c *frt;
475
476			for (rte = rt->mf6c_stall; rte != NULL; ) {
477				struct rtdetq *n = rte->next;
478
479				m_free(rte->m);
480				free(rte, M_MRTABLE);
481				rte = n;
482			}
483			frt = rt;
484			rt = rt->mf6c_next;
485			free(frt, M_MRTABLE);
486		}
487	}
488
489	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
490
491	/*
492	 * Reset de-encapsulation cache
493	 */
494	reg_mif_num = -1;
495
496	ip6_mrouter = NULL;
497
498	splx(s);
499
500#ifdef MRT6DEBUG
501	if (mrt6debug)
502		log(LOG_DEBUG, "ip6_mrouter_done\n");
503#endif
504
505	return 0;
506}
507
508static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
509
510/*
511 * Add a mif to the mif table
512 */
513static int
514add_m6if(mifcp)
515	register struct mif6ctl *mifcp;
516{
517	register struct mif6 *mifp;
518	struct ifnet *ifp;
519	int error, s;
520
521	if (mifcp->mif6c_mifi >= MAXMIFS)
522		return EINVAL;
523	mifp = mif6table + mifcp->mif6c_mifi;
524	if (mifp->m6_ifp)
525		return EADDRINUSE; /* XXX: is it appropriate? */
526	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index)
527		return ENXIO;
528	ifp = ifindex2ifnet[mifcp->mif6c_pifi];
529
530	if (mifcp->mif6c_flags & MIFF_REGISTER) {
531		if (reg_mif_num == (mifi_t)-1) {
532			multicast_register_if.if_name = "register_mif";
533			multicast_register_if.if_flags |= IFF_LOOPBACK;
534			multicast_register_if.if_index = mifcp->mif6c_mifi;
535			reg_mif_num = mifcp->mif6c_mifi;
536		}
537
538		ifp = &multicast_register_if;
539
540	} /* if REGISTER */
541	else {
542		/* Make sure the interface supports multicast */
543		if ((ifp->if_flags & IFF_MULTICAST) == 0)
544			return EOPNOTSUPP;
545
546		s = splnet();
547		error = if_allmulti(ifp, 1);
548		splx(s);
549		if (error)
550			return error;
551	}
552
553	s = splnet();
554	mifp->m6_flags     = mifcp->mif6c_flags;
555	mifp->m6_ifp       = ifp;
556	/* initialize per mif pkt counters */
557	mifp->m6_pkt_in    = 0;
558	mifp->m6_pkt_out   = 0;
559	mifp->m6_bytes_in  = 0;
560	mifp->m6_bytes_out = 0;
561	splx(s);
562
563	/* Adjust nummifs up if the mifi is higher than nummifs */
564	if (nummifs <= mifcp->mif6c_mifi)
565		nummifs = mifcp->mif6c_mifi + 1;
566
567#ifdef MRT6DEBUG
568	if (mrt6debug)
569		log(LOG_DEBUG,
570		    "add_mif #%d, phyint %s%d\n",
571		    mifcp->mif6c_mifi,
572		    ifp->if_name, ifp->if_unit);
573#endif
574
575	return 0;
576}
577
578/*
579 * Delete a mif from the mif table
580 */
581static int
582del_m6if(mifip)
583	mifi_t *mifip;
584{
585	register struct mif6 *mifp = mif6table + *mifip;
586	register mifi_t mifi;
587	struct ifnet *ifp;
588	int s;
589
590	if (*mifip >= nummifs)
591		return EINVAL;
592	if (mifp->m6_ifp == NULL)
593		return EINVAL;
594
595	s = splnet();
596
597	if (!(mifp->m6_flags & MIFF_REGISTER)) {
598		/*
599		 * XXX: what if there is yet IPv4 multicast daemon
600		 *      using the interface?
601		 */
602		ifp = mifp->m6_ifp;
603
604		if_allmulti(ifp, 0);
605	}
606
607	bzero((caddr_t)mifp, sizeof (*mifp));
608
609	/* Adjust nummifs down */
610	for (mifi = nummifs; mifi > 0; mifi--)
611		if (mif6table[mifi - 1].m6_ifp)
612			break;
613	nummifs = mifi;
614
615	splx(s);
616
617#ifdef MRT6DEBUG
618	if (mrt6debug)
619		log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
620#endif
621
622	return 0;
623}
624
625/*
626 * Add an mfc entry
627 */
628static int
629add_m6fc(mfccp)
630	struct mf6cctl *mfccp;
631{
632	struct mf6c *rt;
633	u_long hash;
634	struct rtdetq *rte;
635	register u_short nstl;
636	int s;
637
638	MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
639		 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
640
641	/* If an entry already exists, just update the fields */
642	if (rt) {
643#ifdef MRT6DEBUG
644		if (mrt6debug & DEBUG_MFC)
645			log(LOG_DEBUG,"add_m6fc update o %s g %s p %x\n",
646			    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
647			    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
648			    mfccp->mf6cc_parent);
649#endif
650
651		s = splnet();
652		rt->mf6c_parent = mfccp->mf6cc_parent;
653		rt->mf6c_ifset = mfccp->mf6cc_ifset;
654		splx(s);
655		return 0;
656	}
657
658	/*
659	 * Find the entry for which the upcall was made and update
660	 */
661	s = splnet();
662	hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
663			mfccp->mf6cc_mcastgrp.sin6_addr);
664	for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
665		if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
666				       &mfccp->mf6cc_origin.sin6_addr) &&
667		    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
668				       &mfccp->mf6cc_mcastgrp.sin6_addr) &&
669		    (rt->mf6c_stall != NULL)) {
670
671			if (nstl++)
672				log(LOG_ERR,
673				    "add_m6fc: %s o %s g %s p %x dbx %p\n",
674				    "multiple kernel entries",
675				    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
676				    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
677				    mfccp->mf6cc_parent, rt->mf6c_stall);
678
679#ifdef MRT6DEBUG
680			if (mrt6debug & DEBUG_MFC)
681				log(LOG_DEBUG,
682				    "add_m6fc o %s g %s p %x dbg %x\n",
683				    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
684				    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
685				    mfccp->mf6cc_parent, rt->mf6c_stall);
686#endif
687
688			rt->mf6c_origin     = mfccp->mf6cc_origin;
689			rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
690			rt->mf6c_parent     = mfccp->mf6cc_parent;
691			rt->mf6c_ifset	    = mfccp->mf6cc_ifset;
692			/* initialize pkt counters per src-grp */
693			rt->mf6c_pkt_cnt    = 0;
694			rt->mf6c_byte_cnt   = 0;
695			rt->mf6c_wrong_if   = 0;
696
697			rt->mf6c_expire = 0;	/* Don't clean this guy up */
698			nexpire[hash]--;
699
700			/* free packets Qed at the end of this entry */
701			for (rte = rt->mf6c_stall; rte != NULL; ) {
702				struct rtdetq *n = rte->next;
703				ip6_mdq(rte->m, rte->ifp, rt);
704				m_freem(rte->m);
705#ifdef UPCALL_TIMING
706				collate(&(rte->t));
707#endif /* UPCALL_TIMING */
708				free(rte, M_MRTABLE);
709				rte = n;
710			}
711			rt->mf6c_stall = NULL;
712		}
713	}
714
715	/*
716	 * It is possible that an entry is being inserted without an upcall
717	 */
718	if (nstl == 0) {
719#ifdef MRT6DEBUG
720		if (mrt6debug & DEBUG_MFC)
721			log(LOG_DEBUG,"add_mfc no upcall h %d o %s g %s p %x\n",
722			    hash,
723			    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
724			    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
725			    mfccp->mf6cc_parent);
726#endif
727
728		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
729
730			if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
731					       &mfccp->mf6cc_origin.sin6_addr)&&
732			    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
733					       &mfccp->mf6cc_mcastgrp.sin6_addr)) {
734
735				rt->mf6c_origin     = mfccp->mf6cc_origin;
736				rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
737				rt->mf6c_parent     = mfccp->mf6cc_parent;
738				/* initialize pkt counters per src-grp */
739				rt->mf6c_pkt_cnt    = 0;
740				rt->mf6c_byte_cnt   = 0;
741				rt->mf6c_wrong_if   = 0;
742
743				if (rt->mf6c_expire)
744					nexpire[hash]--;
745				rt->mf6c_expire	   = 0;
746			}
747		}
748		if (rt == NULL) {
749			/* no upcall, so make a new entry */
750			rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,
751						  M_NOWAIT);
752			if (rt == NULL) {
753				splx(s);
754				return ENOBUFS;
755			}
756
757			/* insert new entry at head of hash chain */
758			rt->mf6c_origin     = mfccp->mf6cc_origin;
759			rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
760			rt->mf6c_parent     = mfccp->mf6cc_parent;
761			/* initialize pkt counters per src-grp */
762			rt->mf6c_pkt_cnt    = 0;
763			rt->mf6c_byte_cnt   = 0;
764			rt->mf6c_wrong_if   = 0;
765			rt->mf6c_expire     = 0;
766			rt->mf6c_stall = NULL;
767
768			/* link into table */
769			rt->mf6c_next  = mf6ctable[hash];
770			mf6ctable[hash] = rt;
771		}
772	}
773	splx(s);
774	return 0;
775}
776
777#ifdef UPCALL_TIMING
778/*
779 * collect delay statistics on the upcalls
780 */
781static void
782collate(t)
783	register struct timeval *t;
784{
785	register u_long d;
786	register struct timeval tp;
787	register u_long delta;
788
789	GET_TIME(tp);
790
791	if (TV_LT(*t, tp))
792	{
793		TV_DELTA(tp, *t, delta);
794
795		d = delta >> 10;
796		if (d > UPCALL_MAX)
797			d = UPCALL_MAX;
798
799		++upcall_data[d];
800	}
801}
802#endif /* UPCALL_TIMING */
803
804/*
805 * Delete an mfc entry
806 */
807static int
808del_m6fc(mfccp)
809	struct mf6cctl *mfccp;
810{
811	struct sockaddr_in6 	origin;
812	struct sockaddr_in6 	mcastgrp;
813	struct mf6c 		*rt;
814	struct mf6c	 	**nptr;
815	u_long 		hash;
816	int s;
817
818	origin = mfccp->mf6cc_origin;
819	mcastgrp = mfccp->mf6cc_mcastgrp;
820	hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
821
822#ifdef MRT6DEBUG
823	if (mrt6debug & DEBUG_MFC)
824		log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
825		    ip6_sprintf(&origin.sin6_addr),
826		    ip6_sprintf(&mcastgrp.sin6_addr));
827#endif
828
829	s = splnet();
830
831	nptr = &mf6ctable[hash];
832	while ((rt = *nptr) != NULL) {
833		if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
834				       &rt->mf6c_origin.sin6_addr) &&
835		    IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
836				       &rt->mf6c_mcastgrp.sin6_addr) &&
837		    rt->mf6c_stall == NULL)
838			break;
839
840		nptr = &rt->mf6c_next;
841	}
842	if (rt == NULL) {
843		splx(s);
844		return EADDRNOTAVAIL;
845	}
846
847	*nptr = rt->mf6c_next;
848	free(rt, M_MRTABLE);
849
850	splx(s);
851
852	return 0;
853}
854
855static int
856socket_send(s, mm, src)
857	struct socket *s;
858	struct mbuf *mm;
859	struct sockaddr_in6 *src;
860{
861	if (s) {
862		if (sbappendaddr(&s->so_rcv,
863				 (struct sockaddr *)src,
864				 mm, (struct mbuf *)0) != 0) {
865			sorwakeup(s);
866			return 0;
867		}
868	}
869	m_freem(mm);
870	return -1;
871}
872
873/*
874 * IPv6 multicast forwarding function. This function assumes that the packet
875 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
876 * pointed to by "ifp", and the packet is to be relayed to other networks
877 * that have members of the packet's destination IPv6 multicast group.
878 *
879 * The packet is returned unscathed to the caller, unless it is
880 * erroneous, in which case a non-zero return value tells the caller to
881 * discard it.
882 */
883
884int
885ip6_mforward(ip6, ifp, m)
886	register struct ip6_hdr *ip6;
887	struct ifnet *ifp;
888	struct mbuf *m;
889{
890	register struct mf6c *rt;
891	register struct mif6 *mifp;
892	register struct mbuf *mm;
893	int s;
894	mifi_t mifi;
895
896#ifdef MRT6DEBUG
897	if (mrt6debug & DEBUG_FORWARD)
898		log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n",
899		    ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst),
900		    ifp->if_index);
901#endif
902
903	/*
904	 * Don't forward a packet with Hop limit of zero or one,
905	 * or a packet destined to a local-only group.
906	 */
907	if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_NODELOCAL(&ip6->ip6_dst) ||
908	    IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
909		return 0;
910	ip6->ip6_hlim--;
911
912	/*
913	 * Determine forwarding mifs from the forwarding cache table
914	 */
915	s = splnet();
916	MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
917
918	/* Entry exists, so forward if necessary */
919	if (rt) {
920		splx(s);
921		return (ip6_mdq(m, ifp, rt));
922	} else {
923		/*
924		 * If we don't have a route for packet's origin,
925		 * Make a copy of the packet &
926		 * send message to routing daemon
927		 */
928
929		register struct mbuf *mb0;
930		register struct rtdetq *rte;
931		register u_long hash;
932/*	register int i, npkts;*/
933#ifdef UPCALL_TIMING
934		struct timeval tp;
935
936		GET_TIME(tp);
937#endif /* UPCALL_TIMING */
938
939		mrt6stat.mrt6s_no_route++;
940#ifdef MRT6DEBUG
941		if (mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
942			log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
943			    ip6_sprintf(&ip6->ip6_src),
944			    ip6_sprintf(&ip6->ip6_dst));
945#endif
946
947		/*
948		 * Allocate mbufs early so that we don't do extra work if we
949		 * are just going to fail anyway.
950		 */
951		rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE,
952					      M_NOWAIT);
953		if (rte == NULL) {
954			splx(s);
955			return ENOBUFS;
956		}
957		mb0 = m_copy(m, 0, M_COPYALL);
958		/*
959		 * Pullup packet header if needed before storing it,
960		 * as other references may modify it in the meantime.
961		 */
962		if (mb0 &&
963		    (M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
964			mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
965		if (mb0 == NULL) {
966			free(rte, M_MRTABLE);
967			splx(s);
968			return ENOBUFS;
969		}
970
971		/* is there an upcall waiting for this packet? */
972		hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
973		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
974			if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
975					       &rt->mf6c_origin.sin6_addr) &&
976			    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
977					       &rt->mf6c_mcastgrp.sin6_addr) &&
978			    (rt->mf6c_stall != NULL))
979				break;
980		}
981
982		if (rt == NULL) {
983			struct mrt6msg *im;
984
985			/* no upcall, so make a new entry */
986			rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,
987						  M_NOWAIT);
988			if (rt == NULL) {
989				free(rte, M_MRTABLE);
990				m_freem(mb0);
991				splx(s);
992				return ENOBUFS;
993			}
994			/*
995			 * Make a copy of the header to send to the user
996			 * level process
997			 */
998			mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
999
1000			if (mm == NULL) {
1001				free(rte, M_MRTABLE);
1002				m_freem(mb0);
1003				free(rt, M_MRTABLE);
1004				splx(s);
1005				return ENOBUFS;
1006			}
1007
1008			/*
1009			 * Send message to routing daemon
1010			 */
1011			sin6.sin6_addr = ip6->ip6_src;
1012
1013			im = mtod(mm, struct mrt6msg *);
1014			im->im6_msgtype	= MRT6MSG_NOCACHE;
1015			im->im6_mbz		= 0;
1016
1017#ifdef MRT6DEBUG
1018			if (mrt6debug & DEBUG_FORWARD)
1019				log(LOG_DEBUG,
1020				    "getting the iif info in the kernel\n");
1021#endif
1022
1023			for (mifp = mif6table, mifi = 0;
1024			     mifi < nummifs && mifp->m6_ifp != ifp;
1025			     mifp++, mifi++)
1026				;
1027
1028			im->im6_mif = mifi;
1029
1030			if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
1031				log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
1032				    "socket queue full\n");
1033				mrt6stat.mrt6s_upq_sockfull++;
1034				free(rte, M_MRTABLE);
1035				m_freem(mb0);
1036				free(rt, M_MRTABLE);
1037				splx(s);
1038				return ENOBUFS;
1039			}
1040
1041			mrt6stat.mrt6s_upcalls++;
1042
1043			/* insert new entry at head of hash chain */
1044			bzero(rt, sizeof(*rt));
1045			rt->mf6c_origin.sin6_family = AF_INET6;
1046			rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6);
1047			rt->mf6c_origin.sin6_addr = ip6->ip6_src;
1048			rt->mf6c_mcastgrp.sin6_family = AF_INET6;
1049			rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
1050			rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
1051			rt->mf6c_expire = UPCALL_EXPIRE;
1052			nexpire[hash]++;
1053			rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
1054
1055			/* link into table */
1056			rt->mf6c_next  = mf6ctable[hash];
1057			mf6ctable[hash] = rt;
1058			/* Add this entry to the end of the queue */
1059			rt->mf6c_stall = rte;
1060		} else {
1061			/* determine if q has overflowed */
1062			struct rtdetq **p;
1063			register int npkts = 0;
1064
1065			for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
1066				if (++npkts > MAX_UPQ6) {
1067					mrt6stat.mrt6s_upq_ovflw++;
1068					free(rte, M_MRTABLE);
1069					m_freem(mb0);
1070					splx(s);
1071					return 0;
1072				}
1073
1074			/* Add this entry to the end of the queue */
1075			*p = rte;
1076		}
1077
1078		rte->next = NULL;
1079		rte->m = mb0;
1080		rte->ifp = ifp;
1081#ifdef UPCALL_TIMING
1082		rte->t = tp;
1083#endif /* UPCALL_TIMING */
1084
1085		splx(s);
1086
1087		return 0;
1088	}
1089}
1090
1091/*
1092 * Clean up cache entries if upcalls are not serviced
1093 * Call from the Slow Timeout mechanism, every half second.
1094 */
1095static void
1096expire_upcalls(unused)
1097	void *unused;
1098{
1099	struct rtdetq *rte;
1100	struct mf6c *mfc, **nptr;
1101	int i;
1102	int s;
1103
1104	s = splnet();
1105	for (i = 0; i < MF6CTBLSIZ; i++) {
1106		if (nexpire[i] == 0)
1107			continue;
1108		nptr = &mf6ctable[i];
1109		while ((mfc = *nptr) != NULL) {
1110			rte = mfc->mf6c_stall;
1111			/*
1112			 * Skip real cache entries
1113			 * Make sure it wasn't marked to not expire (shouldn't happen)
1114			 * If it expires now
1115			 */
1116			if (rte != NULL &&
1117			    mfc->mf6c_expire != 0 &&
1118			    --mfc->mf6c_expire == 0) {
1119#ifdef MRT6DEBUG
1120				if (mrt6debug & DEBUG_EXPIRE)
1121					log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n",
1122					    ip6_sprintf(&mfc->mf6c_origin.sin6_addr),
1123					    ip6_sprintf(&mfc->mf6c_mcastgrp.sin6_addr));
1124#endif
1125				/*
1126				 * drop all the packets
1127				 * free the mbuf with the pkt, if, timing info
1128				 */
1129				do {
1130					struct rtdetq *n = rte->next;
1131					m_freem(rte->m);
1132					free(rte, M_MRTABLE);
1133					rte = n;
1134				} while (rte != NULL);
1135				mrt6stat.mrt6s_cache_cleanups++;
1136				nexpire[i]--;
1137
1138				*nptr = mfc->mf6c_next;
1139				free(mfc, M_MRTABLE);
1140			} else {
1141				nptr = &mfc->mf6c_next;
1142			}
1143		}
1144	}
1145	splx(s);
1146	expire_upcalls_ch =
1147		timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
1148}
1149
1150/*
1151 * Packet forwarding routine once entry in the cache is made
1152 */
1153static int
1154ip6_mdq(m, ifp, rt)
1155	register struct mbuf *m;
1156	register struct ifnet *ifp;
1157	register struct mf6c *rt;
1158{
1159	register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1160	register mifi_t mifi, iif;
1161	register struct mif6 *mifp;
1162	register int plen = m->m_pkthdr.len;
1163
1164/*
1165 * Macro to send packet on mif.  Since RSVP packets don't get counted on
1166 * input, they shouldn't get counted on output, so statistics keeping is
1167 * seperate.
1168 */
1169
1170#define	MC6_SEND(ip6,mifp,m) {                             	\
1171		if ((mifp)->m6_flags & MIFF_REGISTER) 		\
1172		    register_send((ip6), (mifp), (m));	 	\
1173                else                                     	\
1174                    phyint_send((ip6), (mifp), (m));      	\
1175}
1176
1177	/*
1178	 * Don't forward if it didn't arrive from the parent mif
1179	 * for its origin.
1180	 */
1181	mifi = rt->mf6c_parent;
1182	if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
1183		/* came in the wrong interface */
1184#ifdef MRT6DEBUG
1185		if (mrt6debug & DEBUG_FORWARD)
1186			log(LOG_DEBUG,
1187			    "wrong if: ifid %d mifi %d mififid %x\n",
1188			    ifp->if_index, mifi,
1189			    mif6table[mifi].m6_ifp->if_index);
1190#endif
1191		mrt6stat.mrt6s_wrong_if++;
1192		rt->mf6c_wrong_if++;
1193		/*
1194		 * If we are doing PIM processing, and we are forwarding
1195		 * packets on this interface, send a message to the
1196		 * routing daemon.
1197		 */
1198		if(mifi < nummifs) /* have to make sure this is a valid mif */
1199			if(mif6table[mifi].m6_ifp)
1200
1201				if (pim6 && (m->m_flags & M_LOOP) == 0) {
1202					/*
1203					 * Check the M_LOOP flag to avoid an
1204					 * unnecessary PIM assert.
1205					 * XXX: M_LOOP is an ad-hoc hack...
1206					 */
1207					static struct sockaddr_in6 sin6 =
1208					{ sizeof(sin6), AF_INET6 };
1209
1210					register struct mbuf *mm;
1211					struct mrt6msg *im;
1212
1213					mm = m_copy(m, 0,
1214						    sizeof(struct ip6_hdr));
1215					if (mm &&
1216					    (M_HASCL(mm) ||
1217					     mm->m_len < sizeof(struct ip6_hdr)))
1218						mm = m_pullup(mm, sizeof(struct ip6_hdr));
1219					if (mm == NULL)
1220						return ENOBUFS;
1221
1222					im = mtod(mm, struct mrt6msg *);
1223					im->im6_msgtype	= MRT6MSG_WRONGMIF;
1224					im->im6_mbz	= 0;
1225
1226					for (mifp = mif6table, iif = 0;
1227					     iif < nummifs && mifp &&
1228						     mifp->m6_ifp != ifp;
1229					     mifp++, iif++);
1230
1231					im->im6_mif	= iif;
1232
1233					sin6.sin6_addr = im->im6_src;
1234
1235					mrt6stat.mrt6s_upcalls++;
1236
1237					if (socket_send(ip6_mrouter, mm,
1238							&sin6) < 0) {
1239#ifdef MRT6DEBUG
1240						if (mrt6debug)
1241							log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
1242#endif
1243						++mrt6stat.mrt6s_upq_sockfull;
1244						return ENOBUFS;
1245					}	/* if socket Q full */
1246				}		/* if PIM */
1247		return 0;
1248	}			/* if wrong iif */
1249
1250	/* If I sourced this packet, it counts as output, else it was input. */
1251	if (m->m_pkthdr.rcvif == NULL) {
1252		/* XXX: is rcvif really NULL when output?? */
1253		mif6table[mifi].m6_pkt_out++;
1254		mif6table[mifi].m6_bytes_out += plen;
1255	} else {
1256		mif6table[mifi].m6_pkt_in++;
1257		mif6table[mifi].m6_bytes_in += plen;
1258	}
1259	rt->mf6c_pkt_cnt++;
1260	rt->mf6c_byte_cnt += plen;
1261
1262	/*
1263	 * For each mif, forward a copy of the packet if there are group
1264	 * members downstream on the interface.
1265	 */
1266	for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++)
1267		if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
1268			mifp->m6_pkt_out++;
1269			mifp->m6_bytes_out += plen;
1270			MC6_SEND(ip6, mifp, m);
1271		}
1272	return 0;
1273}
1274
1275static void
1276phyint_send(ip6, mifp, m)
1277    struct ip6_hdr *ip6;
1278    struct mif6 *mifp;
1279    struct mbuf *m;
1280{
1281	register struct mbuf *mb_copy;
1282	struct ifnet *ifp = mifp->m6_ifp;
1283	int error = 0;
1284	int s = splnet();
1285	static struct route_in6 ro6;
1286	struct	in6_multi *in6m;
1287
1288	/*
1289	 * Make a new reference to the packet; make sure that
1290	 * the IPv6 header is actually copied, not just referenced,
1291	 * so that ip6_output() only scribbles on the copy.
1292	 */
1293	mb_copy = m_copy(m, 0, M_COPYALL);
1294	if (mb_copy &&
1295	    (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
1296		mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
1297	if (mb_copy == NULL)
1298		return;
1299	/* set MCAST flag to the outgoing packet */
1300	mb_copy->m_flags |= M_MCAST;
1301
1302	/*
1303	 * If we sourced the packet, call ip6_output since we may devide
1304	 * the packet into fragments when the packet is too big for the
1305	 * outgoing interface.
1306	 * Otherwise, we can simply send the packet to the interface
1307	 * sending queue.
1308	 */
1309	if (m->m_pkthdr.rcvif == NULL) {
1310		struct ip6_moptions im6o;
1311
1312		im6o.im6o_multicast_ifp = ifp;
1313		/* XXX: ip6_output will override ip6->ip6_hlim */
1314		im6o.im6o_multicast_hlim = ip6->ip6_hlim;
1315		im6o.im6o_multicast_loop = 1;
1316		error = ip6_output(mb_copy, NULL, &ro6,
1317				   IPV6_FORWARDING, &im6o, NULL);
1318
1319#ifdef MRT6DEBUG
1320		if (mrt6debug & DEBUG_XMIT)
1321			log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1322			    mifp - mif6table, error);
1323#endif
1324		splx(s);
1325		return;
1326	}
1327
1328	/*
1329	 * If we belong to the destination multicast group
1330	 * on the outgoing interface, loop back a copy.
1331	 */
1332	IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
1333	if (in6m != NULL) {
1334		ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
1335		ro6.ro_dst.sin6_family = AF_INET6;
1336		ro6.ro_dst.sin6_addr = ip6->ip6_dst;
1337		ip6_mloopback(ifp, m, &ro6.ro_dst);
1338	}
1339	/*
1340	 * Put the packet into the sending queue of the outgoing interface
1341	 * if it would fit in the MTU of the interface.
1342	 */
1343	if (mb_copy->m_pkthdr.len < ifp->if_mtu || ifp->if_mtu < IPV6_MMTU) {
1344		ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
1345		ro6.ro_dst.sin6_family = AF_INET6;
1346		ro6.ro_dst.sin6_addr = ip6->ip6_dst;
1347		/*
1348		 * We just call if_output instead of nd6_output here, since
1349		 * we need no ND for a multicast forwarded packet...right?
1350		 */
1351		error = (*ifp->if_output)(ifp, mb_copy,
1352					  (struct sockaddr *)&ro6.ro_dst,
1353					  NULL);
1354#ifdef MRT6DEBUG
1355		if (mrt6debug & DEBUG_XMIT)
1356			log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1357			    mifp - mif6table, error);
1358#endif
1359	}
1360	else {
1361#ifdef MULTICAST_PMTUD
1362		icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
1363		return;
1364#else
1365#ifdef MRT6DEBUG
1366		if (mrt6debug & DEBUG_XMIT)
1367			log(LOG_DEBUG,
1368			    "phyint_send: packet too big on %s%u o %s g %s"
1369			    " size %d(discarded)\n",
1370			    ifp->if_name, ifp->if_unit,
1371			    ip6_sprintf(&ip6->ip6_src),
1372			    ip6_sprintf(&ip6->ip6_dst),
1373			    mb_copy->m_pkthdr.len);
1374#endif /* MRT6DEBUG */
1375		m_freem(mb_copy); /* simply discard the packet */
1376		return;
1377#endif
1378	}
1379}
1380
1381static int
1382register_send(ip6, mif, m)
1383	register struct ip6_hdr *ip6;
1384	struct mif6 *mif;
1385	register struct mbuf *m;
1386{
1387	register struct mbuf *mm;
1388	register int i, len = m->m_pkthdr.len;
1389	static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
1390	struct mrt6msg *im6;
1391
1392#ifdef MRT6DEBUG
1393	if (mrt6debug)
1394		log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n",
1395		    ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst));
1396#endif
1397	++pim6stat.pim6s_snd_registers;
1398
1399	/* Make a copy of the packet to send to the user level process */
1400	MGETHDR(mm, M_DONTWAIT, MT_HEADER);
1401	if (mm == NULL)
1402		return ENOBUFS;
1403	mm->m_data += max_linkhdr;
1404	mm->m_len = sizeof(struct ip6_hdr);
1405
1406	if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
1407		m_freem(mm);
1408		return ENOBUFS;
1409	}
1410	i = MHLEN - M_LEADINGSPACE(mm);
1411	if (i > len)
1412		i = len;
1413	mm = m_pullup(mm, i);
1414	if (mm == NULL){
1415		m_freem(mm);
1416		return ENOBUFS;
1417	}
1418/* TODO: check it! */
1419	mm->m_pkthdr.len = len + sizeof(struct ip6_hdr);
1420
1421	/*
1422	 * Send message to routing daemon
1423	 */
1424	sin6.sin6_addr = ip6->ip6_src;
1425
1426	im6 = mtod(mm, struct mrt6msg *);
1427	im6->im6_msgtype      = MRT6MSG_WHOLEPKT;
1428	im6->im6_mbz          = 0;
1429
1430	im6->im6_mif = mif - mif6table;
1431
1432	/* iif info is not given for reg. encap.n */
1433	mrt6stat.mrt6s_upcalls++;
1434
1435	if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
1436#ifdef MRT6DEBUG
1437		if (mrt6debug)
1438			log(LOG_WARNING,
1439			    "register_send: ip_mrouter socket queue full\n");
1440#endif
1441                ++mrt6stat.mrt6s_upq_sockfull;
1442                return ENOBUFS;
1443	}
1444	return 0;
1445}
1446
1447/*
1448 * PIM sparse mode hook
1449 * Receives the pim control messages, and passes them up to the listening
1450 * socket, using rip6_input.
1451 * The only message processed is the REGISTER pim message; the pim header
1452 * is stripped off, and the inner packet is passed to register_mforward.
1453 */
1454int
1455pim6_input(mp, offp, proto)
1456	struct mbuf **mp;
1457	int *offp, proto;
1458{
1459        register struct pim *pim; /* pointer to a pim struct */
1460        register struct ip6_hdr *ip6;
1461        register int pimlen;
1462	struct mbuf *m = *mp;
1463        int minlen;
1464	int off = *offp;
1465
1466	++pim6stat.pim6s_rcv_total;
1467
1468        ip6 = mtod(m, struct ip6_hdr *);
1469        pimlen = m->m_pkthdr.len - *offp;
1470
1471        /*
1472         * Validate lengths
1473         */
1474	if (pimlen < PIM_MINLEN) {
1475		++pim6stat.pim6s_rcv_tooshort;
1476#ifdef MRT6DEBUG
1477		if (mrt6debug & DEBUG_PIM)
1478			log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
1479#endif
1480		m_freem(m);
1481		return(IPPROTO_DONE);
1482	}
1483
1484	/*
1485	 * if the packet is at least as big as a REGISTER, go ahead
1486	 * and grab the PIM REGISTER header size, to avoid another
1487	 * possible m_pullup() later.
1488	 *
1489	 * PIM_MINLEN       == pimhdr + u_int32 == 8
1490	 * PIM6_REG_MINLEN   == pimhdr + reghdr + eip6hdr == 4 + 4 + 40
1491	 */
1492	minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN;
1493
1494	/*
1495	 * Make sure that the IP6 and PIM headers in contiguous memory, and
1496	 * possibly the PIM REGISTER header
1497	 */
1498	IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE);
1499	/* adjust pointer */
1500	ip6 = mtod(m, struct ip6_hdr *);
1501
1502	/* adjust mbuf to point to the PIM header */
1503	pim = (struct pim *)((caddr_t)ip6 + off);
1504
1505#define	PIM6_CHECKSUM
1506#ifdef PIM6_CHECKSUM
1507	{
1508		int cksumlen;
1509
1510		/*
1511		 * Validate checksum.
1512		 * If PIM REGISTER, exclude the data packet
1513		 */
1514		if (pim->pim_type == PIM_REGISTER)
1515			cksumlen = PIM_MINLEN;
1516		else
1517			cksumlen = pimlen;
1518
1519		if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
1520			++pim6stat.pim6s_rcv_badsum;
1521#ifdef MRT6DEBUG
1522			if (mrt6debug & DEBUG_PIM)
1523				log(LOG_DEBUG,
1524				    "pim6_input: invalid checksum\n");
1525#endif
1526			m_freem(m);
1527			return(IPPROTO_DONE);
1528		}
1529	}
1530#endif /* PIM_CHECKSUM */
1531
1532	/* PIM version check */
1533	if (pim->pim_ver != PIM_VERSION) {
1534		++pim6stat.pim6s_rcv_badversion;
1535#ifdef MRT6DEBUG
1536		log(LOG_ERR,
1537		    "pim6_input: incorrect version %d, expecting %d\n",
1538		    pim->pim_ver, PIM_VERSION);
1539#endif
1540		m_freem(m);
1541		return(IPPROTO_DONE);
1542	}
1543
1544	if (pim->pim_type == PIM_REGISTER) {
1545		/*
1546		 * since this is a REGISTER, we'll make a copy of the register
1547		 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
1548		 * routing daemon.
1549		 */
1550		static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
1551
1552		struct mbuf *mcp;
1553		struct ip6_hdr *eip6;
1554		u_int32_t *reghdr;
1555		int rc;
1556
1557		++pim6stat.pim6s_rcv_registers;
1558
1559		if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
1560#ifdef MRT6DEBUG
1561			if (mrt6debug & DEBUG_PIM)
1562				log(LOG_DEBUG,
1563				    "pim6_input: register mif not set: %d\n",
1564				    reg_mif_num);
1565#endif
1566			m_freem(m);
1567			return(IPPROTO_DONE);
1568		}
1569
1570		reghdr = (u_int32_t *)(pim + 1);
1571
1572		if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
1573			goto pim6_input_to_daemon;
1574
1575		/*
1576		 * Validate length
1577		 */
1578		if (pimlen < PIM6_REG_MINLEN) {
1579			++pim6stat.pim6s_rcv_tooshort;
1580			++pim6stat.pim6s_rcv_badregisters;
1581#ifdef MRT6DEBUG
1582			log(LOG_ERR,
1583			    "pim6_input: register packet size too "
1584			    "small %d from %s\n",
1585			    pimlen, ip6_sprintf(&ip6->ip6_src));
1586#endif
1587			m_freem(m);
1588			return(IPPROTO_DONE);
1589		}
1590
1591		eip6 = (struct ip6_hdr *) (reghdr + 1);
1592#ifdef MRT6DEBUG
1593		if (mrt6debug & DEBUG_PIM)
1594			log(LOG_DEBUG,
1595			    "pim6_input[register], eip6: %s -> %s, "
1596			    "eip6 plen %d\n",
1597			    ip6_sprintf(&eip6->ip6_src),
1598			    ip6_sprintf(&eip6->ip6_dst),
1599			    ntohs(eip6->ip6_plen));
1600#endif
1601
1602		/* verify the inner packet is destined to a mcast group */
1603		if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
1604			++pim6stat.pim6s_rcv_badregisters;
1605#ifdef MRT6DEBUG
1606			if (mrt6debug & DEBUG_PIM)
1607				log(LOG_DEBUG,
1608				    "pim6_input: inner packet of register "
1609				    "is not multicast %s\n",
1610				    ip6_sprintf(&eip6->ip6_dst));
1611#endif
1612			m_freem(m);
1613			return(IPPROTO_DONE);
1614		}
1615
1616		/*
1617		 * make a copy of the whole header to pass to the daemon later.
1618		 */
1619		mcp = m_copy(m, 0, off + PIM6_REG_MINLEN);
1620		if (mcp == NULL) {
1621#ifdef MRT6DEBUG
1622			log(LOG_ERR,
1623			    "pim6_input: pim register: "
1624			    "could not copy register head\n");
1625#endif
1626			m_freem(m);
1627			return(IPPROTO_DONE);
1628		}
1629
1630		/*
1631		 * forward the inner ip6 packet; point m_data at the inner ip6.
1632		 */
1633		m_adj(m, off + PIM_MINLEN);
1634#ifdef MRT6DEBUG
1635		if (mrt6debug & DEBUG_PIM) {
1636			log(LOG_DEBUG,
1637			    "pim6_input: forwarding decapsulated register: "
1638			    "src %s, dst %s, mif %d\n",
1639			    ip6_sprintf(&eip6->ip6_src),
1640			    ip6_sprintf(&eip6->ip6_dst),
1641			    reg_mif_num);
1642		}
1643#endif
1644
1645 		rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
1646			      (struct sockaddr *) &dst, NULL);
1647
1648		/* prepare the register head to send to the mrouting daemon */
1649		m = mcp;
1650	}
1651
1652	/*
1653	 * Pass the PIM message up to the daemon; if it is a register message
1654	 * pass the 'head' only up to the daemon. This includes the
1655	 * encapsulator ip6 header, pim header, register header and the
1656	 * encapsulated ip6 header.
1657	 */
1658  pim6_input_to_daemon:
1659	rip6_input(&m, offp, proto);
1660	return(IPPROTO_DONE);
1661}
1662