1 //==========================================================================
3 // src/sys/netinet6/ip6_mroute.c
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
8 // -------------------------------------------
10 // Portions of this software may have been derived from OpenBSD,
11 // FreeBSD or other sources, and are covered by the appropriate
12 // copyright disclaimers included herein.
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
17 // -------------------------------------------
19 //####BSDCOPYRIGHTEND####
20 //==========================================================================
22 /* $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $ */
25 * Copyright (C) 1998 WIDE Project.
26 * All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. Neither the name of the project nor the names of its contributors
37 * may be used to endorse or promote products derived from this software
38 * without specific prior written permission.
40 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 /* BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp */
56 * IP multicast forwarding procedures
58 * Written by David Waitzman, BBN Labs, August 1988.
59 * Modified by Steve Deering, Stanford, February 1989.
60 * Modified by Mark J. Steiglitz, Stanford, May, 1991
61 * Modified by Van Jacobson, LBL, January 1993
62 * Modified by Ajit Thyagarajan, PARC, August 1993
63 * Modified by Bill Fenenr, PARC, April 1994
65 * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
69 * XXX it seems that home address option processing should be reverted
70 * before calls to socket_send(). see sys/netinet6/dest6.c for details.
73 #include <sys/param.h>
74 #include <sys/malloc.h>
76 #include <sys/socket.h>
77 #include <sys/socketvar.h>
78 #include <sys/sockio.h>
79 #include <sys/protosw.h>
80 #include <sys/errno.h>
84 #include <net/route.h>
85 #include <net/raw_cb.h>
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
90 #include <netinet/ip6.h>
91 #include <netinet6/ip6_var.h>
92 #include <netinet6/ip6_mroute.h>
93 #include <netinet6/pim6.h>
94 #include <netinet6/pim6_var.h>
96 #define M_HASCL(m) ((m)->m_flags & M_EXT)
98 static int ip6_mdq __P((struct mbuf *, struct ifnet *, struct mf6c *));
99 static void phyint_send __P((struct ip6_hdr *, struct mif6 *, struct mbuf *));
101 static int set_pim6 __P((int *));
102 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
103 static int get_pim6 __P((struct mbuf *));
105 static int socket_send __P((struct socket *, struct mbuf *,
106 struct sockaddr_in6 *));
107 static int register_send __P((struct ip6_hdr *, struct mif6 *,
111 * Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static,
112 * except for netstat or debugging purposes.
114 struct socket *ip6_mrouter = NULL;
115 int ip6_mrouter_ver = 0;
116 int ip6_mrtproto = IPPROTO_PIM; /* for netstat only */
117 struct mrt6stat mrt6stat;
119 #define NO_RTE_FOUND 0x1
120 #define RTE_FOUND 0x2
122 struct mf6c *mf6ctable[MF6CTBLSIZ];
123 u_char n6expire[MF6CTBLSIZ];
124 #if (defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802))
125 struct mif6 mif6table[MAXMIFS];
127 static struct mif6 mif6table[MAXMIFS];
130 u_int mrt6debug = 0; /* debug level */
131 #define DEBUG_MFC 0x02
132 #define DEBUG_FORWARD 0x04
133 #define DEBUG_EXPIRE 0x08
134 #define DEBUG_XMIT 0x10
135 #define DEBUG_REG 0x20
136 #define DEBUG_PIM 0x40
139 static void expire_upcalls __P((void *));
140 #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
141 #define UPCALL_EXPIRE 6 /* number of timeouts */
145 extern struct socket *ip_mrouter;
150 * 'Interfaces' associated with decapsulator (so we can tell
151 * packets that went through it from ones that get reflected
152 * by a broken gateway). These interfaces are never linked into
153 * the system ifnet list & no routes point to them. I.e., packets
154 * can't be sent this way. They only exist as a placeholder for
155 * multicast source verification.
157 struct ifnet multicast_register_if;
159 #define ENCAP_HOPS 64
164 static mifi_t nummifs = 0;
165 static mifi_t reg_mif_num = (mifi_t)-1;
167 struct pim6stat pim6stat;
171 * Hash function for a source, group entry
173 #define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
174 (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
175 (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
176 (g).s6_addr32[2] ^ (g).s6_addr32[3])
179 * Find a route for a given origin IPv6 address and Multicast group address.
180 * Quality of service parameter to be added in the future!!!
183 #define MF6CFIND(o, g, rt) do { \
184 struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
186 mrt6stat.mrt6s_mfc_lookups++; \
188 if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
189 IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
190 (_rt->mf6c_stall == NULL)) { \
194 _rt = _rt->mf6c_next; \
197 mrt6stat.mrt6s_mfc_misses++; \
202 * Macros to compute elapsed time efficiently
203 * Borrowed from Van Jacobson's scheduling code
205 #define TV_DELTA(a, b, delta) do { \
208 delta = (a).tv_usec - (b).tv_usec; \
209 if ((xxs = (a).tv_sec - (b).tv_sec)) { \
218 delta += (1000000 * xxs); \
223 #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
224 (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
227 #define UPCALL_MAX 50
228 u_long upcall_data[UPCALL_MAX + 1];
229 static void collate();
230 #endif /* UPCALL_TIMING */
232 static int get_sg_cnt __P((struct sioc_sg_req6 *));
233 static int get_mif6_cnt __P((struct sioc_mif_req6 *));
234 static int ip6_mrouter_init __P((struct socket *, struct mbuf *, int));
235 static int add_m6if __P((struct mif6ctl *));
236 static int del_m6if __P((mifi_t *));
237 static int add_m6fc __P((struct mf6cctl *));
238 static int del_m6fc __P((struct mf6cctl *));
241 static struct callout expire_upcalls_ch = CALLOUT_INITIALIZER;
242 #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3)
243 static struct callout expire_upcalls_ch;
244 #elif defined(__OpenBSD__)
245 static struct timeout expire_upcalls_ch;
249 * Handle MRT setsockopt commands to modify the multicast routing tables.
251 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
253 ip6_mrouter_set(so, sopt)
255 struct sockopt *sopt;
260 if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT)
263 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
265 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
268 switch (sopt->sopt_name) {
273 error = ip6_mrouter_init(so, m, sopt->sopt_name);
276 error = ip6_mrouter_done();
279 error = add_m6if(mtod(m, struct mif6ctl *));
282 error = del_m6if(mtod(m, mifi_t *));
285 error = add_m6fc(mtod(m, struct mf6cctl *));
288 error = del_m6fc(mtod(m, struct mf6cctl *));
291 error = set_pim6(mtod(m, int *));
303 ip6_mrouter_set(cmd, so, m)
308 if (cmd != MRT6_INIT && so != ip6_mrouter)
313 case MRT6_OINIT: return ip6_mrouter_init(so, m, cmd);
315 case MRT6_INIT: return ip6_mrouter_init(so, m, cmd);
316 case MRT6_DONE: return ip6_mrouter_done();
317 case MRT6_ADD_MIF: return add_m6if(mtod(m, struct mif6ctl *));
318 case MRT6_DEL_MIF: return del_m6if(mtod(m, mifi_t *));
319 case MRT6_ADD_MFC: return add_m6fc(mtod(m, struct mf6cctl *));
320 case MRT6_DEL_MFC: return del_m6fc(mtod(m, struct mf6cctl *));
321 case MRT6_PIM: return set_pim6(mtod(m, int *));
322 default: return EOPNOTSUPP;
328 * Handle MRT getsockopt commands
330 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
332 ip6_mrouter_get(so, sopt)
334 struct sockopt *sopt;
338 if (so != ip6_mrouter) return EACCES;
340 switch (sopt->sopt_name) {
342 error = sooptcopyout(sopt, &pim6, sizeof(pim6));
349 ip6_mrouter_get(cmd, so, m)
356 if (so != ip6_mrouter) return EACCES;
358 *m = mb = m_get(M_WAIT, MT_SOOPTS);
371 * Handle ioctl commands to obtain information from the cache
374 mrt6_ioctl(cmd, data)
381 case SIOCGETSGCNT_IN6:
382 return(get_sg_cnt((struct sioc_sg_req6 *)data));
383 break; /* for safety */
384 case SIOCGETMIFCNT_IN6:
385 return(get_mif6_cnt((struct sioc_mif_req6 *)data));
386 break; /* for safety */
395 * returns the packet, byte, rpf-failure count for the source group provided
399 struct sioc_sg_req6 *req;
409 MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
412 req->pktcnt = rt->mf6c_pkt_cnt;
413 req->bytecnt = rt->mf6c_byte_cnt;
414 req->wrong_if = rt->mf6c_wrong_if;
418 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
425 * returns the input and output packet and byte counts on the mif provided
429 struct sioc_mif_req6 *req;
431 mifi_t mifi = req->mifi;
436 req->icount = mif6table[mifi].m6_pkt_in;
437 req->ocount = mif6table[mifi].m6_pkt_out;
438 req->ibytes = mif6table[mifi].m6_bytes_in;
439 req->obytes = mif6table[mifi].m6_bytes_out;
444 #if !(defined(__FreeBSD__) && __FreeBSD__ >=3)
446 * Get PIM processiong global
466 if ((*i != 1) && (*i != 0))
475 * Enable multicast routing
478 ip6_mrouter_init(so, m, cmd)
488 "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
489 so->so_type, so->so_proto->pr_protocol);
492 if (so->so_type != SOCK_RAW ||
493 so->so_proto->pr_protocol != IPPROTO_ICMPV6)
496 if (!m || (m->m_len != sizeof(int *)))
503 if (ip6_mrouter != NULL) return EADDRINUSE;
506 ip6_mrouter_ver = cmd;
508 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
509 bzero((caddr_t)n6expire, sizeof(n6expire));
511 pim6 = 0;/* used for stubbing out/in pim stuff */
513 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
514 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
515 expire_upcalls, NULL);
516 #elif defined(__OpenBSD__)
517 timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);
518 timeout_add(&expire_upcalls_ch, EXPIRE_TIMEOUT);
520 timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
525 log(LOG_DEBUG, "ip6_mrouter_init\n");
532 * Disable multicast routing
540 struct in6_ifreq ifr;
552 * For each phyint in use, disable promiscuous reception of all IPv6
558 * If there is still IPv4 multicast routing daemon,
559 * we remain interfaces to receive all muliticasted packets.
560 * XXX: there may be an interface in which the IPv4 multicast
561 * daemon is not interested...
567 for (mifi = 0; mifi < nummifs; mifi++) {
568 if (mif6table[mifi].m6_ifp &&
569 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
570 ifr.ifr_addr.sin6_family = AF_INET6;
571 ifr.ifr_addr.sin6_addr= in6addr_any;
572 ifp = mif6table[mifi].m6_ifp;
573 (*ifp->if_ioctl)(ifp, SIOCDELMULTI,
579 bzero((caddr_t)qtable, sizeof(qtable));
580 bzero((caddr_t)tbftable, sizeof(tbftable));
582 bzero((caddr_t)mif6table, sizeof(mif6table));
585 pim6 = 0; /* used to stub out/in pim specific code */
587 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
588 callout_stop(&expire_upcalls_ch);
589 #elif defined(__OpenBSD__)
590 timeout_del(&expire_upcalls_ch);
592 untimeout(expire_upcalls, (caddr_t)NULL);
596 * Free all multicast forwarding cache entries.
598 for (i = 0; i < MF6CTBLSIZ; i++) {
603 for (rte = rt->mf6c_stall; rte != NULL; ) {
604 struct rtdetq *n = rte->next;
607 free(rte, M_MRTABLE);
612 free(frt, M_MRTABLE);
616 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
619 * Reset de-encapsulation cache
630 log(LOG_DEBUG, "ip6_mrouter_done\n");
636 static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
639 * Add a mif to the mif table
643 struct mif6ctl *mifcp;
647 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
648 struct in6_ifreq ifr;
652 struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;
655 if (mifcp->mif6c_mifi >= MAXMIFS)
657 mifp = mif6table + mifcp->mif6c_mifi;
659 return EADDRINUSE; /* XXX: is it appropriate? */
660 if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index)
663 * XXX: some OSes can remove ifp and clear ifindex2ifnet[id]
664 * even for id between 0 and if_index.
666 #if defined(__FreeBSD__) && __FreeBSD__ >= 5
667 ifp = ifnet_byindex(mifcp->mif6c_pifi);
669 ifp = ifindex2ifnet[mifcp->mif6c_pifi];
674 if (mifcp->mif6c_flags & MIFF_REGISTER) {
675 if (reg_mif_num == (mifi_t)-1) {
676 #if defined(__NetBSD__) || defined(__OpenBSD__)
677 strcpy(multicast_register_if.if_xname,
678 "register_mif"); /* XXX */
680 multicast_register_if.if_name = "register_mif";
682 multicast_register_if.if_flags |= IFF_LOOPBACK;
683 multicast_register_if.if_index = mifcp->mif6c_mifi;
684 reg_mif_num = mifcp->mif6c_mifi;
687 ifp = &multicast_register_if;
691 /* Make sure the interface supports multicast */
692 if ((ifp->if_flags & IFF_MULTICAST) == 0)
700 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3)
701 error = if_allmulti(ifp, 1);
704 * Enable promiscuous reception of all IPv6 multicasts
705 * from the interface.
707 ifr.ifr_addr.sin6_family = AF_INET6;
708 ifr.ifr_addr.sin6_addr = in6addr_any;
709 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
721 mifp->m6_flags = mifcp->mif6c_flags;
724 /* scaling up here allows division by 1024 in critical code */
725 mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
727 /* initialize per mif pkt counters */
729 mifp->m6_pkt_out = 0;
730 mifp->m6_bytes_in = 0;
731 mifp->m6_bytes_out = 0;
734 /* Adjust nummifs up if the mifi is higher than nummifs */
735 if (nummifs <= mifcp->mif6c_mifi)
736 nummifs = mifcp->mif6c_mifi + 1;
741 "add_mif #%d, phyint %s%d\n",
743 ifp->if_name, ifp->if_unit);
750 * Delete a mif from the mif table
756 struct mif6 *mifp = mif6table + *mifip;
759 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
760 struct in6_ifreq ifr;
764 if (*mifip >= nummifs)
766 if (mifp->m6_ifp == NULL)
775 if (!(mifp->m6_flags & MIFF_REGISTER)) {
777 * XXX: what if there is yet IPv4 multicast daemon
778 * using the interface?
782 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3)
785 ifr.ifr_addr.sin6_family = AF_INET6;
786 ifr.ifr_addr.sin6_addr = in6addr_any;
787 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
792 bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));
793 bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));
795 bzero((caddr_t)mifp, sizeof (*mifp));
797 /* Adjust nummifs down */
798 for (mifi = nummifs; mifi > 0; mifi--)
799 if (mif6table[mifi - 1].m6_ifp)
807 log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
818 struct mf6cctl *mfccp;
826 MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
827 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
829 /* If an entry already exists, just update the fields */
832 if (mrt6debug & DEBUG_MFC)
833 log(LOG_DEBUG,"add_m6fc update o %s g %s p %x\n",
834 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
835 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
836 mfccp->mf6cc_parent);
844 rt->mf6c_parent = mfccp->mf6cc_parent;
845 rt->mf6c_ifset = mfccp->mf6cc_ifset;
851 * Find the entry for which the upcall was made and update
858 hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
859 mfccp->mf6cc_mcastgrp.sin6_addr);
860 for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
861 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
862 &mfccp->mf6cc_origin.sin6_addr) &&
863 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
864 &mfccp->mf6cc_mcastgrp.sin6_addr) &&
865 (rt->mf6c_stall != NULL)) {
869 "add_m6fc: %s o %s g %s p %x dbx %p\n",
870 "multiple kernel entries",
871 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
872 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
873 mfccp->mf6cc_parent, rt->mf6c_stall);
876 if (mrt6debug & DEBUG_MFC)
878 "add_m6fc o %s g %s p %x dbg %x\n",
879 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
880 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
881 mfccp->mf6cc_parent, rt->mf6c_stall);
884 rt->mf6c_origin = mfccp->mf6cc_origin;
885 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
886 rt->mf6c_parent = mfccp->mf6cc_parent;
887 rt->mf6c_ifset = mfccp->mf6cc_ifset;
888 /* initialize pkt counters per src-grp */
889 rt->mf6c_pkt_cnt = 0;
890 rt->mf6c_byte_cnt = 0;
891 rt->mf6c_wrong_if = 0;
893 rt->mf6c_expire = 0; /* Don't clean this guy up */
896 /* free packets Qed at the end of this entry */
897 for (rte = rt->mf6c_stall; rte != NULL; ) {
898 struct rtdetq *n = rte->next;
899 ip6_mdq(rte->m, rte->ifp, rt);
903 #endif /* UPCALL_TIMING */
904 free(rte, M_MRTABLE);
907 rt->mf6c_stall = NULL;
912 * It is possible that an entry is being inserted without an upcall
916 if (mrt6debug & DEBUG_MFC)
918 "add_m6fc no upcall h %d o %s g %s p %x\n",
920 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
921 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
922 mfccp->mf6cc_parent);
925 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
927 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
928 &mfccp->mf6cc_origin.sin6_addr)&&
929 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
930 &mfccp->mf6cc_mcastgrp.sin6_addr)) {
932 rt->mf6c_origin = mfccp->mf6cc_origin;
933 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
934 rt->mf6c_parent = mfccp->mf6cc_parent;
935 rt->mf6c_ifset = mfccp->mf6cc_ifset;
936 /* initialize pkt counters per src-grp */
937 rt->mf6c_pkt_cnt = 0;
938 rt->mf6c_byte_cnt = 0;
939 rt->mf6c_wrong_if = 0;
947 /* no upcall, so make a new entry */
948 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,
955 /* insert new entry at head of hash chain */
956 rt->mf6c_origin = mfccp->mf6cc_origin;
957 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
958 rt->mf6c_parent = mfccp->mf6cc_parent;
959 rt->mf6c_ifset = mfccp->mf6cc_ifset;
960 /* initialize pkt counters per src-grp */
961 rt->mf6c_pkt_cnt = 0;
962 rt->mf6c_byte_cnt = 0;
963 rt->mf6c_wrong_if = 0;
965 rt->mf6c_stall = NULL;
967 /* link into table */
968 rt->mf6c_next = mf6ctable[hash];
969 mf6ctable[hash] = rt;
978 * collect delay statistics on the upcalls
992 TV_DELTA(tp, *t, delta);
1001 #endif /* UPCALL_TIMING */
1004 * Delete an mfc entry
1008 struct mf6cctl *mfccp;
1010 struct sockaddr_in6 origin;
1011 struct sockaddr_in6 mcastgrp;
1017 origin = mfccp->mf6cc_origin;
1018 mcastgrp = mfccp->mf6cc_mcastgrp;
1019 hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
1022 if (mrt6debug & DEBUG_MFC)
1023 log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
1024 ip6_sprintf(&origin.sin6_addr),
1025 ip6_sprintf(&mcastgrp.sin6_addr));
1034 nptr = &mf6ctable[hash];
1035 while ((rt = *nptr) != NULL) {
1036 if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
1037 &rt->mf6c_origin.sin6_addr) &&
1038 IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
1039 &rt->mf6c_mcastgrp.sin6_addr) &&
1040 rt->mf6c_stall == NULL)
1043 nptr = &rt->mf6c_next;
1047 return EADDRNOTAVAIL;
1050 *nptr = rt->mf6c_next;
1051 free(rt, M_MRTABLE);
1059 socket_send(s, mm, src)
1062 struct sockaddr_in6 *src;
1065 if (sbappendaddr(&s->so_rcv,
1066 (struct sockaddr *)src,
1067 mm, (struct mbuf *)0) != 0) {
1077 * IPv6 multicast forwarding function. This function assumes that the packet
1078 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
1079 * pointed to by "ifp", and the packet is to be relayed to other networks
1080 * that have members of the packet's destination IPv6 multicast group.
1082 * The packet is returned unscathed to the caller, unless it is
1083 * erroneous, in which case a non-zero return value tells the caller to
1088 ip6_mforward(ip6, ifp, m)
1089 struct ip6_hdr *ip6;
1098 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
1099 long time_second = time.tv_sec;
1103 if (mrt6debug & DEBUG_FORWARD)
1104 log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n",
1105 ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst),
1110 * Don't forward a packet with Hop limit of zero or one,
1111 * or a packet destined to a local-only group.
1113 if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
1114 IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1119 * Source address check: do not forward packets with unspecified
1120 * source. It was discussed in July 2000, on ipngwg mailing list.
1121 * This is rather more serious than unicast cases, because some
1122 * MLD packets can be sent with the unspecified source address
1123 * (although such packets must normally set 1 to the hop limit field).
1125 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
1126 ip6stat.ip6s_cantforward++;
1127 if (ip6_log_time + ip6_log_interval < time_second) {
1128 ip6_log_time = time_second;
1131 "from %s to %s nxt %d received on %s\n",
1132 ip6_sprintf(&ip6->ip6_src),
1133 ip6_sprintf(&ip6->ip6_dst),
1136 if_name(m->m_pkthdr.rcvif) : "?");
1142 * Determine forwarding mifs from the forwarding cache table
1149 MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
1151 /* Entry exists, so forward if necessary */
1154 return (ip6_mdq(m, ifp, rt));
1157 * If we don't have a route for packet's origin,
1158 * Make a copy of the packet &
1159 * send message to routing daemon
1166 #ifdef UPCALL_TIMING
1170 #endif /* UPCALL_TIMING */
1172 mrt6stat.mrt6s_no_route++;
1174 if (mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
1175 log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
1176 ip6_sprintf(&ip6->ip6_src),
1177 ip6_sprintf(&ip6->ip6_dst));
1181 * Allocate mbufs early so that we don't do extra work if we
1182 * are just going to fail anyway.
1184 rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE,
1190 mb0 = m_copy(m, 0, M_COPYALL);
1192 * Pullup packet header if needed before storing it,
1193 * as other references may modify it in the meantime.
1196 (M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
1197 mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
1199 free(rte, M_MRTABLE);
1204 /* is there an upcall waiting for this packet? */
1205 hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
1206 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
1207 if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
1208 &rt->mf6c_origin.sin6_addr) &&
1209 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1210 &rt->mf6c_mcastgrp.sin6_addr) &&
1211 (rt->mf6c_stall != NULL))
1218 struct omrt6msg *oim;
1221 /* no upcall, so make a new entry */
1222 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,
1225 free(rte, M_MRTABLE);
1231 * Make a copy of the header to send to the user
1234 mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
1237 free(rte, M_MRTABLE);
1239 free(rt, M_MRTABLE);
1245 * Send message to routing daemon
1247 sin6.sin6_addr = ip6->ip6_src;
1253 switch (ip6_mrouter_ver) {
1256 oim = mtod(mm, struct omrt6msg *);
1257 oim->im6_msgtype = MRT6MSG_NOCACHE;
1262 im = mtod(mm, struct mrt6msg *);
1263 im->im6_msgtype = MRT6MSG_NOCACHE;
1267 free(rte, M_MRTABLE);
1269 free(rt, M_MRTABLE);
1275 if (mrt6debug & DEBUG_FORWARD)
1277 "getting the iif info in the kernel\n");
1280 for (mifp = mif6table, mifi = 0;
1281 mifi < nummifs && mifp->m6_ifp != ifp;
1285 switch (ip6_mrouter_ver) {
1288 oim->im6_mif = mifi;
1296 if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
1297 log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
1298 "socket queue full\n");
1299 mrt6stat.mrt6s_upq_sockfull++;
1300 free(rte, M_MRTABLE);
1302 free(rt, M_MRTABLE);
1307 mrt6stat.mrt6s_upcalls++;
1309 /* insert new entry at head of hash chain */
1310 bzero(rt, sizeof(*rt));
1311 rt->mf6c_origin.sin6_family = AF_INET6;
1312 rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6);
1313 rt->mf6c_origin.sin6_addr = ip6->ip6_src;
1314 rt->mf6c_mcastgrp.sin6_family = AF_INET6;
1315 rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
1316 rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
1317 rt->mf6c_expire = UPCALL_EXPIRE;
1319 rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
1321 /* link into table */
1322 rt->mf6c_next = mf6ctable[hash];
1323 mf6ctable[hash] = rt;
1324 /* Add this entry to the end of the queue */
1325 rt->mf6c_stall = rte;
1327 /* determine if q has overflowed */
1331 for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
1332 if (++npkts > MAX_UPQ6) {
1333 mrt6stat.mrt6s_upq_ovflw++;
1334 free(rte, M_MRTABLE);
1340 /* Add this entry to the end of the queue */
1347 #ifdef UPCALL_TIMING
1349 #endif /* UPCALL_TIMING */
1358 * Clean up cache entries if upcalls are not serviced
1359 * Call from the Slow Timeout mechanism, every half second.
1362 expire_upcalls(unused)
1366 struct mf6c *mfc, **nptr;
1375 for (i = 0; i < MF6CTBLSIZ; i++) {
1376 if (n6expire[i] == 0)
1378 nptr = &mf6ctable[i];
1379 while ((mfc = *nptr) != NULL) {
1380 rte = mfc->mf6c_stall;
1382 * Skip real cache entries
1383 * Make sure it wasn't marked to not expire (shouldn't happen)
1387 mfc->mf6c_expire != 0 &&
1388 --mfc->mf6c_expire == 0) {
1390 if (mrt6debug & DEBUG_EXPIRE)
1391 log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n",
1392 ip6_sprintf(&mfc->mf6c_origin.sin6_addr),
1393 ip6_sprintf(&mfc->mf6c_mcastgrp.sin6_addr));
1396 * drop all the packets
1397 * free the mbuf with the pkt, if, timing info
1400 struct rtdetq *n = rte->next;
1402 free(rte, M_MRTABLE);
1404 } while (rte != NULL);
1405 mrt6stat.mrt6s_cache_cleanups++;
1408 *nptr = mfc->mf6c_next;
1409 free(mfc, M_MRTABLE);
1411 nptr = &mfc->mf6c_next;
1416 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
1417 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
1418 expire_upcalls, NULL);
1419 #elif defined(__OpenBSD__)
1420 timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);
1421 timeout_add(&expire_upcalls_ch, EXPIRE_TIMEOUT);
1423 timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
1428 * Packet forwarding routine once entry in the cache is made
1436 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1439 int plen = m->m_pkthdr.len;
1442 * Macro to send packet on mif. Since RSVP packets don't get counted on
1443 * input, they shouldn't get counted on output, so statistics keeping is
1447 #define MC6_SEND(ip6, mifp, m) do { \
1448 if ((mifp)->m6_flags & MIFF_REGISTER) \
1449 register_send((ip6), (mifp), (m)); \
1451 phyint_send((ip6), (mifp), (m)); \
1455 * Don't forward if it didn't arrive from the parent mif
1458 mifi = rt->mf6c_parent;
1459 if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
1460 /* came in the wrong interface */
1462 if (mrt6debug & DEBUG_FORWARD)
1464 "wrong if: ifid %d mifi %d mififid %x\n",
1465 ifp->if_index, mifi,
1466 mif6table[mifi].m6_ifp->if_index);
1468 mrt6stat.mrt6s_wrong_if++;
1469 rt->mf6c_wrong_if++;
1471 * If we are doing PIM processing, and we are forwarding
1472 * packets on this interface, send a message to the
1475 /* have to make sure this is a valid mif */
1476 if (mifi < nummifs && mif6table[mifi].m6_ifp)
1477 if (pim6 && (m->m_flags & M_LOOP) == 0) {
1479 * Check the M_LOOP flag to avoid an
1480 * unnecessary PIM assert.
1481 * XXX: M_LOOP is an ad-hoc hack...
1483 static struct sockaddr_in6 sin6 =
1484 { sizeof(sin6), AF_INET6 };
1489 struct omrt6msg *oim;
1492 mm = m_copy(m, 0, sizeof(struct ip6_hdr));
1495 mm->m_len < sizeof(struct ip6_hdr)))
1496 mm = m_pullup(mm, sizeof(struct ip6_hdr));
1504 switch (ip6_mrouter_ver) {
1507 oim = mtod(mm, struct omrt6msg *);
1508 oim->im6_msgtype = MRT6MSG_WRONGMIF;
1513 im = mtod(mm, struct mrt6msg *);
1514 im->im6_msgtype = MRT6MSG_WRONGMIF;
1522 for (mifp = mif6table, iif = 0;
1523 iif < nummifs && mifp &&
1524 mifp->m6_ifp != ifp;
1528 switch (ip6_mrouter_ver) {
1532 sin6.sin6_addr = oim->im6_src;
1537 sin6.sin6_addr = im->im6_src;
1541 mrt6stat.mrt6s_upcalls++;
1543 if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
1546 log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
1548 ++mrt6stat.mrt6s_upq_sockfull;
1550 } /* if socket Q full */
1553 } /* if wrong iif */
1555 /* If I sourced this packet, it counts as output, else it was input. */
1556 if (m->m_pkthdr.rcvif == NULL) {
1557 /* XXX: is rcvif really NULL when output?? */
1558 mif6table[mifi].m6_pkt_out++;
1559 mif6table[mifi].m6_bytes_out += plen;
1561 mif6table[mifi].m6_pkt_in++;
1562 mif6table[mifi].m6_bytes_in += plen;
1565 rt->mf6c_byte_cnt += plen;
1568 * For each mif, forward a copy of the packet if there are group
1569 * members downstream on the interface.
1571 for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++)
1572 if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
1573 int64_t dscopein, sscopein, dscopeout, sscopeout;
1576 * check if the outgoing packet is going to break
1578 * XXX For packets through PIM register tunnel
1579 * interface, we believe a routing daemon.
1581 if ((mif6table[rt->mf6c_parent].m6_flags &
1582 MIFF_REGISTER) == 0 &&
1583 (mif6table[mifi].m6_flags & MIFF_REGISTER) == 0) {
1584 if ((dscopein = in6_addr2zoneid(ifp, &ip6->ip6_dst)) < 0 ||
1585 (dscopeout = in6_addr2zoneid(mif6table[mifi].m6_ifp, &ip6->ip6_dst)) < 0 ||
1586 (sscopein = in6_addr2zoneid(ifp, &ip6->ip6_src)) < 0 ||
1587 (sscopeout = in6_addr2zoneid(mif6table[mifi].m6_ifp, &ip6->ip6_src)) < 0 ||
1588 dscopein != dscopeout ||
1589 sscopein != sscopeout) {
1590 ip6stat.ip6s_badscope++;
1596 mifp->m6_bytes_out += plen;
1597 MC6_SEND(ip6, mifp, m);
1603 phyint_send(ip6, mifp, m)
1604 struct ip6_hdr *ip6;
1608 struct mbuf *mb_copy;
1609 struct ifnet *ifp = mifp->m6_ifp;
1612 int s = splsoftnet(); /* needs to protect static "ro" below. */
1614 int s = splnet(); /* needs to protect static "ro" below. */
1616 #ifdef NEW_STRUCT_ROUTE
1617 static struct route ro;
1619 static struct route_in6 ro;
1621 struct in6_multi *in6m;
1622 struct sockaddr_in6 *dst6;
1625 * Make a new reference to the packet; make sure that
1626 * the IPv6 header is actually copied, not just referenced,
1627 * so that ip6_output() only scribbles on the copy.
1629 mb_copy = m_copy(m, 0, M_COPYALL);
1631 (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
1632 mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
1633 if (mb_copy == NULL) {
1637 /* set MCAST flag to the outgoing packet */
1638 mb_copy->m_flags |= M_MCAST;
1641 * If we sourced the packet, call ip6_output since we may devide
1642 * the packet into fragments when the packet is too big for the
1643 * outgoing interface.
1644 * Otherwise, we can simply send the packet to the interface
1647 if (m->m_pkthdr.rcvif == NULL) {
1648 struct ip6_moptions im6o;
1650 im6o.im6o_multicast_ifp = ifp;
1651 /* XXX: ip6_output will override ip6->ip6_hlim */
1652 im6o.im6o_multicast_hlim = ip6->ip6_hlim;
1653 im6o.im6o_multicast_loop = 1;
1654 error = ip6_output(mb_copy, NULL, &ro,
1655 IPV6_FORWARDING, &im6o, NULL);
1658 if (mrt6debug & DEBUG_XMIT)
1659 log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1660 mifp - mif6table, error);
1667 * If we belong to the destination multicast group
1668 * on the outgoing interface, loop back a copy.
1670 dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
1671 IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
1673 dst6->sin6_len = sizeof(struct sockaddr_in6);
1674 dst6->sin6_family = AF_INET6;
1675 dst6->sin6_addr = ip6->ip6_dst;
1676 ip6_mloopback(ifp, m, (struct sockaddr_in6 *)&ro.ro_dst);
1679 * Put the packet into the sending queue of the outgoing interface
1680 * if it would fit in the MTU of the interface.
1682 if (mb_copy->m_pkthdr.len < ifp->if_mtu || ifp->if_mtu < IPV6_MMTU) {
1683 dst6->sin6_len = sizeof(struct sockaddr_in6);
1684 dst6->sin6_family = AF_INET6;
1685 dst6->sin6_addr = ip6->ip6_dst;
1687 * We just call if_output instead of nd6_output here, since
1688 * we need no ND for a multicast forwarded packet...right?
1690 error = (*ifp->if_output)(ifp, mb_copy,
1691 (struct sockaddr *)&ro.ro_dst, NULL);
1693 if (mrt6debug & DEBUG_XMIT)
1694 log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1695 mifp - mif6table, error);
1698 #ifdef MULTICAST_PMTUD
1699 icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
1702 if (mrt6debug & DEBUG_XMIT)
1704 "phyint_send: packet too big on %s o %s g %s"
1705 " size %d(discarded)\n",
1707 ip6_sprintf(&ip6->ip6_src),
1708 ip6_sprintf(&ip6->ip6_dst),
1709 mb_copy->m_pkthdr.len);
1710 #endif /* MRT6DEBUG */
1711 m_freem(mb_copy); /* simply discard the packet */
1719 register_send(ip6, mif, m)
1720 struct ip6_hdr *ip6;
1725 int i, len = m->m_pkthdr.len;
1726 static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
1727 struct mrt6msg *im6;
1731 log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n",
1732 ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst));
1734 ++pim6stat.pim6s_snd_registers;
1736 /* Make a copy of the packet to send to the user level process */
1737 MGETHDR(mm, M_DONTWAIT, MT_HEADER);
1740 mm->m_pkthdr.rcvif = NULL;
1741 mm->m_data += max_linkhdr;
1742 mm->m_len = sizeof(struct ip6_hdr);
1744 if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
1748 i = MHLEN - M_LEADINGSPACE(mm);
1751 mm = m_pullup(mm, i);
1756 /* TODO: check it! */
1757 mm->m_pkthdr.len = len + sizeof(struct ip6_hdr);
1760 * Send message to routing daemon
1762 sin6.sin6_addr = ip6->ip6_src;
1764 im6 = mtod(mm, struct mrt6msg *);
1765 im6->im6_msgtype = MRT6MSG_WHOLEPKT;
1768 im6->im6_mif = mif - mif6table;
1770 /* iif info is not given for reg. encap.n */
1771 mrt6stat.mrt6s_upcalls++;
1773 if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
1777 "register_send: ip6_mrouter socket queue full\n");
1779 ++mrt6stat.mrt6s_upq_sockfull;
1786 * PIM sparse mode hook
1787 * Receives the pim control messages, and passes them up to the listening
1788 * socket, using rip6_input.
1789 * The only message processed is the REGISTER pim message; the pim header
1790 * is stripped off, and the inner packet is passed to register_mforward.
1793 pim6_input(mp, offp, proto)
1797 struct pim *pim; /* pointer to a pim struct */
1798 struct ip6_hdr *ip6;
1800 struct mbuf *m = *mp;
1804 ++pim6stat.pim6s_rcv_total;
1806 ip6 = mtod(m, struct ip6_hdr *);
1807 pimlen = m->m_pkthdr.len - *offp;
1812 if (pimlen < PIM_MINLEN) {
1813 ++pim6stat.pim6s_rcv_tooshort;
1815 if (mrt6debug & DEBUG_PIM)
1816 log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
1819 return(IPPROTO_DONE);
1823 * if the packet is at least as big as a REGISTER, go ahead
1824 * and grab the PIM REGISTER header size, to avoid another
1825 * possible m_pullup() later.
1827 * PIM_MINLEN == pimhdr + u_int32 == 8
1828 * PIM6_REG_MINLEN == pimhdr + reghdr + eip6hdr == 4 + 4 + 40
1830 minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN;
1833 * Make sure that the IP6 and PIM headers in contiguous memory, and
1834 * possibly the PIM REGISTER header
1836 #ifndef PULLDOWN_TEST
1837 IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE);
1838 /* adjust pointer */
1839 ip6 = mtod(m, struct ip6_hdr *);
1841 /* adjust mbuf to point to the PIM header */
1842 pim = (struct pim *)((caddr_t)ip6 + off);
1844 IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen);
1846 pim6stat.pim6s_rcv_tooshort++;
1847 return IPPROTO_DONE;
1851 #define PIM6_CHECKSUM
1852 #ifdef PIM6_CHECKSUM
1857 * Validate checksum.
1858 * If PIM REGISTER, exclude the data packet
1860 if (pim->pim_type == PIM_REGISTER)
1861 cksumlen = PIM_MINLEN;
1865 if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
1866 ++pim6stat.pim6s_rcv_badsum;
1868 if (mrt6debug & DEBUG_PIM)
1870 "pim6_input: invalid checksum\n");
1873 return(IPPROTO_DONE);
1876 #endif /* PIM_CHECKSUM */
1878 /* PIM version check */
1879 if (pim->pim_ver != PIM_VERSION) {
1880 ++pim6stat.pim6s_rcv_badversion;
1883 "pim6_input: incorrect version %d, expecting %d\n",
1884 pim->pim_ver, PIM_VERSION);
1887 return(IPPROTO_DONE);
1890 if (pim->pim_type == PIM_REGISTER) {
1892 * since this is a REGISTER, we'll make a copy of the register
1893 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
1896 static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
1899 struct ip6_hdr *eip6;
1903 ++pim6stat.pim6s_rcv_registers;
1905 if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
1907 if (mrt6debug & DEBUG_PIM)
1909 "pim6_input: register mif not set: %d\n",
1913 return(IPPROTO_DONE);
1916 reghdr = (u_int32_t *)(pim + 1);
1918 if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
1919 goto pim6_input_to_daemon;
1924 if (pimlen < PIM6_REG_MINLEN) {
1925 ++pim6stat.pim6s_rcv_tooshort;
1926 ++pim6stat.pim6s_rcv_badregisters;
1929 "pim6_input: register packet size too "
1930 "small %d from %s\n",
1931 pimlen, ip6_sprintf(&ip6->ip6_src));
1934 return(IPPROTO_DONE);
1937 eip6 = (struct ip6_hdr *) (reghdr + 1);
1939 if (mrt6debug & DEBUG_PIM)
1941 "pim6_input[register], eip6: %s -> %s, "
1943 ip6_sprintf(&eip6->ip6_src),
1944 ip6_sprintf(&eip6->ip6_dst),
1945 ntohs(eip6->ip6_plen));
1948 /* verify the version number of the inner packet */
1949 if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1950 ++pim6stat.pim6s_rcv_badregisters;
1952 log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
1953 "of the inner packet\n",
1954 (eip6->ip6_vfc & IPV6_VERSION));
1957 return(IPPROTO_NONE);
1960 /* verify the inner packet is destined to a mcast group */
1961 if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
1962 ++pim6stat.pim6s_rcv_badregisters;
1964 if (mrt6debug & DEBUG_PIM)
1966 "pim6_input: inner packet of register "
1967 "is not multicast %s\n",
1968 ip6_sprintf(&eip6->ip6_dst));
1971 return(IPPROTO_DONE);
1975 * make a copy of the whole header to pass to the daemon later.
1977 mcp = m_copy(m, 0, off + PIM6_REG_MINLEN);
1981 "pim6_input: pim register: "
1982 "could not copy register head\n");
1985 return(IPPROTO_DONE);
1989 * forward the inner ip6 packet; point m_data at the inner ip6.
1991 m_adj(m, off + PIM_MINLEN);
1993 if (mrt6debug & DEBUG_PIM) {
1995 "pim6_input: forwarding decapsulated register: "
1996 "src %s, dst %s, mif %d\n",
1997 ip6_sprintf(&eip6->ip6_src),
1998 ip6_sprintf(&eip6->ip6_dst),
2003 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2004 #if (__FreeBSD_version >= 410000)
2005 rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
2006 dst.sin6_family, (int)NULL);
2008 rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
2009 (struct sockaddr *) &dst, NULL);
2013 rc = looutput(mif6table[reg_mif_num].m6_ifp, m,
2014 (struct sockaddr *) &dst,
2015 (struct rtentry *) NULL);
2018 /* prepare the register head to send to the mrouting daemon */
2023 * Pass the PIM message up to the daemon; if it is a register message
2024 * pass the 'head' only up to the daemon. This includes the
2025 * encapsulator ip6 header, pim header, register header and the
2026 * encapsulated ip6 header.
2028 pim6_input_to_daemon:
2029 rip6_input(&m, offp, proto);
2030 return(IPPROTO_DONE);