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