1 /*-
2 * Copyright (C) 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $
30 */
31
32 /*-
33 * Copyright (c) 1989 Stephen Deering
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Stephen Deering of Stanford University.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
65 * BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp
66 */
67
68 /*
69 * IP multicast forwarding procedures
70 *
71 * Written by David Waitzman, BBN Labs, August 1988.
72 * Modified by Steve Deering, Stanford, February 1989.
73 * Modified by Mark J. Steiglitz, Stanford, May, 1991
74 * Modified by Van Jacobson, LBL, January 1993
75 * Modified by Ajit Thyagarajan, PARC, August 1993
76 * Modified by Bill Fenner, PARC, April 1994
77 *
78 * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
79 */
80
81 #include <sys/cdefs.h>
82 __FBSDID("$FreeBSD: src/sys/netinet6/ip6_mroute.c,v 1.52 2008/12/02 21:37:28 bz Exp $");
83
84 #include "opt_inet.h"
85 #include "opt_inet6.h"
86
87 #include <sys/param.h>
88 #include <sys/callout.h>
89 #include <sys/errno.h>
90 #include <sys/kernel.h>
91 #include <sys/lock.h>
92 #include <sys/malloc.h>
93 #include <sys/mbuf.h>
94 #include <sys/protosw.h>
95 #include <sys/signalvar.h>
96 #include <sys/socket.h>
97 #include <sys/socketvar.h>
98 #include <sys/sockio.h>
99 #include <sys/sx.h>
100 #include <sys/sysctl.h>
101 #include <sys/syslog.h>
102 #include <sys/systm.h>
103 #include <sys/time.h>
104 #include <sys/vimage.h>
105
106 #include <net/if.h>
107 #include <net/if_types.h>
108 #include <net/raw_cb.h>
109 #include <net/route.h>
110 #include <net/vnet.h>
111
112 #include <netinet/in.h>
113 #include <netinet/in_var.h>
114 #include <netinet/icmp6.h>
115 #include <netinet/vinet.h>
116
117 #include <netinet/ip6.h>
118 #include <netinet6/ip6_var.h>
119 #include <netinet6/scope6_var.h>
120 #include <netinet6/nd6.h>
121 #include <netinet6/ip6_mroute.h>
122 #include <netinet6/ip6protosw.h>
123 #include <netinet6/pim6.h>
124 #include <netinet6/pim6_var.h>
125 #include <netinet6/vinet6.h>
126
127 static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry");
128
129 /* XXX: this is a very common idiom; move to <sys/mbuf.h> ? */
130 #define M_HASCL(m) ((m)->m_flags & M_EXT)
131
132 static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
133 static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
134
135 static void pim6_init(void);
136 static int set_pim6(int *);
137 static int socket_send __P((struct socket *, struct mbuf *,
138 struct sockaddr_in6 *));
139 static int register_send __P((struct ip6_hdr *, struct mif6 *,
140 struct mbuf *));
141
142 extern struct domain inet6domain;
143
144 /* XXX: referenced from ip_mroute.c for dynamically loading this code. */
145 struct ip6protosw in6_pim_protosw = {
146 .pr_type = SOCK_RAW,
147 .pr_domain = &inet6domain,
148 .pr_protocol = IPPROTO_PIM,
149 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
150 .pr_input = pim6_input,
151 .pr_output = rip6_output,
152 .pr_ctloutput = rip6_ctloutput,
153 .pr_init = pim6_init,
154 .pr_usrreqs = &rip6_usrreqs
155 };
156
157 #ifdef VIMAGE_GLOBALS
158 static int ip6_mrouter_ver;
159 #endif
160
161 SYSCTL_DECL(_net_inet6);
162 SYSCTL_DECL(_net_inet6_ip6);
163 SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
164
165 static struct mrt6stat mrt6stat;
166 SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
167 &mrt6stat, mrt6stat,
168 "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)");
169
170 #define NO_RTE_FOUND 0x1
171 #define RTE_FOUND 0x2
172
173 static struct mf6c *mf6ctable[MF6CTBLSIZ];
174 SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD,
175 &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]",
176 "Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], "
177 "netinet6/ip6_mroute.h)");
178
179 static u_char n6expire[MF6CTBLSIZ];
180
181 static struct mif6 mif6table[MAXMIFS];
182 SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD,
183 &mif6table, sizeof(mif6table), "S,vif[MAXMIFS]",
184 "Multicast Interfaces (struct mif[MAXMIFS], netinet6/ip6_mroute.h)");
185
186 #ifdef MRT6DEBUG
187 #ifdef VIMAGE_GLOBALS
188 static u_int mrt6debug = 0; /* debug level */
189 #endif
190 #define DEBUG_MFC 0x02
191 #define DEBUG_FORWARD 0x04
192 #define DEBUG_EXPIRE 0x08
193 #define DEBUG_XMIT 0x10
194 #define DEBUG_REG 0x20
195 #define DEBUG_PIM 0x40
196 #endif
197
198 static void expire_upcalls(void *);
199 #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
200 #define UPCALL_EXPIRE 6 /* number of timeouts */
201
202 #ifdef INET
203 #ifdef MROUTING
204 extern struct socket *ip_mrouter;
205 #endif
206 #endif
207
208 /*
209 * 'Interfaces' associated with decapsulator (so we can tell
210 * packets that went through it from ones that get reflected
211 * by a broken gateway). Different from IPv4 register_if,
212 * these interfaces are linked into the system ifnet list,
213 * because per-interface IPv6 statistics are maintained in
214 * ifp->if_afdata. But it does not have any routes point
215 * to them. I.e., packets can't be sent this way. They
216 * only exist as a placeholder for multicast source
217 * verification.
218 */
219 static struct ifnet *multicast_register_if6;
220
221 #define ENCAP_HOPS 64
222
223 /*
224 * Private variables.
225 */
226 static mifi_t nummifs = 0;
227 static mifi_t reg_mif_num = (mifi_t)-1;
228
229 static struct pim6stat pim6stat;
230 SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RD,
231 &pim6stat, pim6stat,
232 "PIM Statistics (struct pim6stat, netinet6/pim_var.h)");
233
234 #ifdef VIMAGE_GLOBALS
235 static int pim6;
236 #endif
237
238 /*
239 * Hash function for a source, group entry
240 */
241 #define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
242 (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
243 (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
244 (g).s6_addr32[2] ^ (g).s6_addr32[3])
245
246 /*
247 * Find a route for a given origin IPv6 address and Multicast group address.
248 */
249 #define MF6CFIND(o, g, rt) do { \
250 struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
251 rt = NULL; \
252 mrt6stat.mrt6s_mfc_lookups++; \
253 while (_rt) { \
254 if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
255 IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
256 (_rt->mf6c_stall == NULL)) { \
257 rt = _rt; \
258 break; \
259 } \
260 _rt = _rt->mf6c_next; \
261 } \
262 if (rt == NULL) { \
263 mrt6stat.mrt6s_mfc_misses++; \
264 } \
265 } while (/*CONSTCOND*/ 0)
266
267 /*
268 * Macros to compute elapsed time efficiently
269 * Borrowed from Van Jacobson's scheduling code
270 * XXX: replace with timersub() ?
271 */
272 #define TV_DELTA(a, b, delta) do { \
273 int xxs; \
274 \
275 delta = (a).tv_usec - (b).tv_usec; \
276 if ((xxs = (a).tv_sec - (b).tv_sec)) { \
277 switch (xxs) { \
278 case 2: \
279 delta += 1000000; \
280 /* FALLTHROUGH */ \
281 case 1: \
282 delta += 1000000; \
283 break; \
284 default: \
285 delta += (1000000 * xxs); \
286 } \
287 } \
288 } while (/*CONSTCOND*/ 0)
289
290 /* XXX: replace with timercmp(a, b, <) ? */
291 #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
292 (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
293
294 #ifdef UPCALL_TIMING
295 #define UPCALL_MAX 50
296 static u_long upcall_data[UPCALL_MAX + 1];
297 static void collate();
298 #endif /* UPCALL_TIMING */
299
300 static int get_sg_cnt(struct sioc_sg_req6 *);
301 static int get_mif6_cnt(struct sioc_mif_req6 *);
302 static int ip6_mrouter_init(struct socket *, int, int);
303 static int add_m6if(struct mif6ctl *);
304 static int del_m6if(mifi_t *);
305 static int add_m6fc(struct mf6cctl *);
306 static int del_m6fc(struct mf6cctl *);
307
308 static struct callout expire_upcalls_ch;
309
310 int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m);
311 int X_ip6_mrouter_done(void);
312 int X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt);
313 int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt);
314 int X_mrt6_ioctl(int cmd, caddr_t data);
315
316 static void
317 pim6_init(void)
318 {
319 INIT_VNET_INET6(curvnet);
320
321 V_ip6_mrouter_ver = 0;
322 #ifdef MRT6DEBUG
323 V_mrt6debug = 0; /* debug level */
324 #endif
325 }
326
327 /*
328 * Handle MRT setsockopt commands to modify the multicast routing tables.
329 */
330 int
331 X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
332 {
333 int error = 0;
334 int optval;
335 struct mif6ctl mifc;
336 struct mf6cctl mfcc;
337 mifi_t mifi;
338
339 if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT)
340 return (EACCES);
341
342 switch (sopt->sopt_name) {
343 case MRT6_INIT:
344 #ifdef MRT6_OINIT
345 case MRT6_OINIT:
346 #endif
347 error = sooptcopyin(sopt, &optval, sizeof(optval),
348 sizeof(optval));
349 if (error)
350 break;
351 error = ip6_mrouter_init(so, optval, sopt->sopt_name);
352 break;
353 case MRT6_DONE:
354 error = X_ip6_mrouter_done();
355 break;
356 case MRT6_ADD_MIF:
357 error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc));
358 if (error)
359 break;
360 error = add_m6if(&mifc);
361 break;
362 case MRT6_ADD_MFC:
363 error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
364 if (error)
365 break;
366 error = add_m6fc(&mfcc);
367 break;
368 case MRT6_DEL_MFC:
369 error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
370 if (error)
371 break;
372 error = del_m6fc(&mfcc);
373 break;
374 case MRT6_DEL_MIF:
375 error = sooptcopyin(sopt, &mifi, sizeof(mifi), sizeof(mifi));
376 if (error)
377 break;
378 error = del_m6if(&mifi);
379 break;
380 case MRT6_PIM:
381 error = sooptcopyin(sopt, &optval, sizeof(optval),
382 sizeof(optval));
383 if (error)
384 break;
385 error = set_pim6(&optval);
386 break;
387 default:
388 error = EOPNOTSUPP;
389 break;
390 }
391
392 return (error);
393 }
394
395 /*
396 * Handle MRT getsockopt commands
397 */
398 int
399 X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
400 {
401 INIT_VNET_INET6(curvnet);
402 int error = 0;
403
404 if (so != ip6_mrouter)
405 return (EACCES);
406
407 switch (sopt->sopt_name) {
408 case MRT6_PIM:
409 error = sooptcopyout(sopt, &V_pim6, sizeof(V_pim6));
410 break;
411 }
412 return (error);
413 }
414
415 /*
416 * Handle ioctl commands to obtain information from the cache
417 */
418 int
419 X_mrt6_ioctl(int cmd, caddr_t data)
420 {
421 switch (cmd) {
422 case SIOCGETSGCNT_IN6:
423 return (get_sg_cnt((struct sioc_sg_req6 *)data));
424 case SIOCGETMIFCNT_IN6:
425 return (get_mif6_cnt((struct sioc_mif_req6 *)data));
426 default:
427 return (EINVAL);
428 }
429 }
430
431 /*
432 * returns the packet, byte, rpf-failure count for the source group provided
433 */
434 static int
435 get_sg_cnt(struct sioc_sg_req6 *req)
436 {
437 struct mf6c *rt;
438 int s;
439
440 s = splnet();
441 MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
442 splx(s);
443 if (rt != NULL) {
444 req->pktcnt = rt->mf6c_pkt_cnt;
445 req->bytecnt = rt->mf6c_byte_cnt;
446 req->wrong_if = rt->mf6c_wrong_if;
447 } else
448 return (ESRCH);
449 #if 0
450 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
451 #endif
452
453 return (0);
454 }
455
456 /*
457 * returns the input and output packet and byte counts on the mif provided
458 */
459 static int
460 get_mif6_cnt(struct sioc_mif_req6 *req)
461 {
462 mifi_t mifi = req->mifi;
463
464 if (mifi >= nummifs)
465 return (EINVAL);
466
467 req->icount = mif6table[mifi].m6_pkt_in;
468 req->ocount = mif6table[mifi].m6_pkt_out;
469 req->ibytes = mif6table[mifi].m6_bytes_in;
470 req->obytes = mif6table[mifi].m6_bytes_out;
471
472 return (0);
473 }
474
475 static int
476 set_pim6(int *i)
477 {
478 INIT_VNET_INET6(curvnet);
479 if ((*i != 1) && (*i != 0))
480 return (EINVAL);
481
482 V_pim6 = *i;
483
484 return (0);
485 }
486
487 /*
488 * Enable multicast routing
489 */
490 static int
491 ip6_mrouter_init(struct socket *so, int v, int cmd)
492 {
493 INIT_VNET_INET6(curvnet);
494
495 #ifdef MRT6DEBUG
496 if (V_mrt6debug)
497 log(LOG_DEBUG,
498 "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
499 so->so_type, so->so_proto->pr_protocol);
500 #endif
501
502 if (so->so_type != SOCK_RAW ||
503 so->so_proto->pr_protocol != IPPROTO_ICMPV6)
504 return (EOPNOTSUPP);
505
506 if (v != 1)
507 return (ENOPROTOOPT);
508
509 if (ip6_mrouter != NULL)
510 return (EADDRINUSE);
511
512 ip6_mrouter = so;
513 V_ip6_mrouter_ver = cmd;
514
515 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
516 bzero((caddr_t)n6expire, sizeof(n6expire));
517
518 V_pim6 = 0;/* used for stubbing out/in pim stuff */
519
520 callout_init(&expire_upcalls_ch, 0);
521 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
522 expire_upcalls, NULL);
523
524 #ifdef MRT6DEBUG
525 if (V_mrt6debug)
526 log(LOG_DEBUG, "ip6_mrouter_init\n");
527 #endif
528
529 return (0);
530 }
531
532 /*
533 * Disable multicast routing
534 */
535 int
536 X_ip6_mrouter_done(void)
537 {
538 INIT_VNET_INET6(curvnet);
539 mifi_t mifi;
540 int i;
541 struct mf6c *rt;
542 struct rtdetq *rte;
543 int s;
544
545 s = splnet();
546
547 /*
548 * For each phyint in use, disable promiscuous reception of all IPv6
549 * multicasts.
550 */
551 #ifdef INET
552 #ifdef MROUTING
553 /*
554 * If there is still IPv4 multicast routing daemon,
555 * we remain interfaces to receive all muliticasted packets.
556 * XXX: there may be an interface in which the IPv4 multicast
557 * daemon is not interested...
558 */
559 if (!V_ip_mrouter)
560 #endif
561 #endif
562 {
563 for (mifi = 0; mifi < nummifs; mifi++) {
564 if (mif6table[mifi].m6_ifp &&
565 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
566 if_allmulti(mif6table[mifi].m6_ifp, 0);
567 }
568 }
569 }
570 bzero((caddr_t)mif6table, sizeof(mif6table));
571 nummifs = 0;
572
573 V_pim6 = 0; /* used to stub out/in pim specific code */
574
575 callout_stop(&expire_upcalls_ch);
576
577 /*
578 * Free all multicast forwarding cache entries.
579 */
580 for (i = 0; i < MF6CTBLSIZ; i++) {
581 rt = mf6ctable[i];
582 while (rt) {
583 struct mf6c *frt;
584
585 for (rte = rt->mf6c_stall; rte != NULL; ) {
586 struct rtdetq *n = rte->next;
587
588 m_free(rte->m);
589 free(rte, M_MRTABLE6);
590 rte = n;
591 }
592 frt = rt;
593 rt = rt->mf6c_next;
594 free(frt, M_MRTABLE6);
595 }
596 }
597
598 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
599
600 /*
601 * Reset register interface
602 */
603 if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
604 if_detach(multicast_register_if6);
605 if_free(multicast_register_if6);
606 reg_mif_num = (mifi_t)-1;
607 multicast_register_if6 = NULL;
608 }
609
610 ip6_mrouter = NULL;
611 V_ip6_mrouter_ver = 0;
612
613 splx(s);
614
615 #ifdef MRT6DEBUG
616 if (V_mrt6debug)
617 log(LOG_DEBUG, "ip6_mrouter_done\n");
618 #endif
619
620 return (0);
621 }
622
623 static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
624
625 /*
626 * Add a mif to the mif table
627 */
628 static int
629 add_m6if(struct mif6ctl *mifcp)
630 {
631 INIT_VNET_NET(curvnet);
632 struct mif6 *mifp;
633 struct ifnet *ifp;
634 int error, s;
635
636 if (mifcp->mif6c_mifi >= MAXMIFS)
637 return (EINVAL);
638 mifp = mif6table + mifcp->mif6c_mifi;
639 if (mifp->m6_ifp)
640 return (EADDRINUSE); /* XXX: is it appropriate? */
641 if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index)
642 return (ENXIO);
643 ifp = ifnet_byindex(mifcp->mif6c_pifi);
644
645 if (mifcp->mif6c_flags & MIFF_REGISTER) {
646 if (reg_mif_num == (mifi_t)-1) {
647 ifp = if_alloc(IFT_OTHER);
648
649 if_initname(ifp, "register_mif", 0);
650 ifp->if_flags |= IFF_LOOPBACK;
651 if_attach(ifp);
652 multicast_register_if6 = ifp;
653 reg_mif_num = mifcp->mif6c_mifi;
654 /*
655 * it is impossible to guess the ifindex of the
656 * register interface. So mif6c_pifi is automatically
657 * calculated.
658 */
659 mifcp->mif6c_pifi = ifp->if_index;
660 } else {
661 ifp = multicast_register_if6;
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 = splnet();
671 error = if_allmulti(ifp, 1);
672 splx(s);
673 if (error)
674 return (error);
675 }
676
677 s = splnet();
678 mifp->m6_flags = mifcp->mif6c_flags;
679 mifp->m6_ifp = ifp;
680
681 /* initialize per mif pkt counters */
682 mifp->m6_pkt_in = 0;
683 mifp->m6_pkt_out = 0;
684 mifp->m6_bytes_in = 0;
685 mifp->m6_bytes_out = 0;
686 splx(s);
687
688 /* Adjust nummifs up if the mifi is higher than nummifs */
689 if (nummifs <= mifcp->mif6c_mifi)
690 nummifs = mifcp->mif6c_mifi + 1;
691
692 #ifdef MRT6DEBUG
693 if (V_mrt6debug)
694 log(LOG_DEBUG,
695 "add_mif #%d, phyint %s\n",
696 mifcp->mif6c_mifi,
697 ifp->if_xname);
698 #endif
699
700 return (0);
701 }
702
703 /*
704 * Delete a mif from the mif table
705 */
706 static int
707 del_m6if(mifi_t *mifip)
708 {
709 struct mif6 *mifp = mif6table + *mifip;
710 mifi_t mifi;
711 struct ifnet *ifp;
712 int s;
713
714 if (*mifip >= nummifs)
715 return (EINVAL);
716 if (mifp->m6_ifp == NULL)
717 return (EINVAL);
718
719 s = splnet();
720
721 if (!(mifp->m6_flags & MIFF_REGISTER)) {
722 /*
723 * XXX: what if there is yet IPv4 multicast daemon
724 * using the interface?
725 */
726 ifp = mifp->m6_ifp;
727
728 if_allmulti(ifp, 0);
729 } else {
730 if (reg_mif_num != (mifi_t)-1 &&
731 multicast_register_if6 != NULL) {
732 if_detach(multicast_register_if6);
733 if_free(multicast_register_if6);
734 reg_mif_num = (mifi_t)-1;
735 multicast_register_if6 = NULL;
736 }
737 }
738
739 bzero((caddr_t)mifp, sizeof(*mifp));
740
741 /* Adjust nummifs down */
742 for (mifi = nummifs; mifi > 0; mifi--)
743 if (mif6table[mifi - 1].m6_ifp)
744 break;
745 nummifs = mifi;
746
747 splx(s);
748
749 #ifdef MRT6DEBUG
750 if (V_mrt6debug)
751 log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
752 #endif
753
754 return (0);
755 }
756
757 /*
758 * Add an mfc entry
759 */
760 static int
761 add_m6fc(struct mf6cctl *mfccp)
762 {
763 struct mf6c *rt;
764 u_long hash;
765 struct rtdetq *rte;
766 u_short nstl;
767 int s;
768 char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
769
770 MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
771 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
772
773 /* If an entry already exists, just update the fields */
774 if (rt) {
775 #ifdef MRT6DEBUG
776 if (V_mrt6debug & DEBUG_MFC) {
777 log(LOG_DEBUG,
778 "add_m6fc no upcall h %d o %s g %s p %x\n",
779 ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
780 ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
781 mfccp->mf6cc_parent);
782 }
783 #endif
784
785 s = splnet();
786 rt->mf6c_parent = mfccp->mf6cc_parent;
787 rt->mf6c_ifset = mfccp->mf6cc_ifset;
788 splx(s);
789 return (0);
790 }
791
792 /*
793 * Find the entry for which the upcall was made and update
794 */
795 s = splnet();
796 hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
797 mfccp->mf6cc_mcastgrp.sin6_addr);
798 for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
799 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
800 &mfccp->mf6cc_origin.sin6_addr) &&
801 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
802 &mfccp->mf6cc_mcastgrp.sin6_addr) &&
803 (rt->mf6c_stall != NULL)) {
804
805 if (nstl++)
806 log(LOG_ERR,
807 "add_m6fc: %s o %s g %s p %x dbx %p\n",
808 "multiple kernel entries",
809 ip6_sprintf(ip6bufo,
810 &mfccp->mf6cc_origin.sin6_addr),
811 ip6_sprintf(ip6bufg,
812 &mfccp->mf6cc_mcastgrp.sin6_addr),
813 mfccp->mf6cc_parent, rt->mf6c_stall);
814
815 #ifdef MRT6DEBUG
816 if (V_mrt6debug & DEBUG_MFC)
817 log(LOG_DEBUG,
818 "add_m6fc o %s g %s p %x dbg %x\n",
819 ip6_sprintf(ip6bufo,
820 &mfccp->mf6cc_origin.sin6_addr),
821 ip6_sprintf(ip6bufg,
822 &mfccp->mf6cc_mcastgrp.sin6_addr),
823 mfccp->mf6cc_parent, rt->mf6c_stall);
824 #endif
825
826 rt->mf6c_origin = mfccp->mf6cc_origin;
827 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
828 rt->mf6c_parent = mfccp->mf6cc_parent;
829 rt->mf6c_ifset = mfccp->mf6cc_ifset;
830 /* initialize pkt counters per src-grp */
831 rt->mf6c_pkt_cnt = 0;
832 rt->mf6c_byte_cnt = 0;
833 rt->mf6c_wrong_if = 0;
834
835 rt->mf6c_expire = 0; /* Don't clean this guy up */
836 n6expire[hash]--;
837
838 /* free packets Qed at the end of this entry */
839 for (rte = rt->mf6c_stall; rte != NULL; ) {
840 struct rtdetq *n = rte->next;
841 ip6_mdq(rte->m, rte->ifp, rt);
842 m_freem(rte->m);
843 #ifdef UPCALL_TIMING
844 collate(&(rte->t));
845 #endif /* UPCALL_TIMING */
846 free(rte, M_MRTABLE6);
847 rte = n;
848 }
849 rt->mf6c_stall = NULL;
850 }
851 }
852
853 /*
854 * It is possible that an entry is being inserted without an upcall
855 */
856 if (nstl == 0) {
857 #ifdef MRT6DEBUG
858 if (V_mrt6debug & DEBUG_MFC)
859 log(LOG_DEBUG,
860 "add_mfc no upcall h %d o %s g %s p %x\n",
861 hash,
862 ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
863 ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
864 mfccp->mf6cc_parent);
865 #endif
866
867 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
868
869 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
870 &mfccp->mf6cc_origin.sin6_addr)&&
871 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
872 &mfccp->mf6cc_mcastgrp.sin6_addr)) {
873
874 rt->mf6c_origin = mfccp->mf6cc_origin;
875 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
876 rt->mf6c_parent = mfccp->mf6cc_parent;
877 rt->mf6c_ifset = mfccp->mf6cc_ifset;
878 /* initialize pkt counters per src-grp */
879 rt->mf6c_pkt_cnt = 0;
880 rt->mf6c_byte_cnt = 0;
881 rt->mf6c_wrong_if = 0;
882
883 if (rt->mf6c_expire)
884 n6expire[hash]--;
885 rt->mf6c_expire = 0;
886 }
887 }
888 if (rt == NULL) {
889 /* no upcall, so make a new entry */
890 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
891 M_NOWAIT);
892 if (rt == NULL) {
893 splx(s);
894 return (ENOBUFS);
895 }
896
897 /* insert new entry at head of hash chain */
898 rt->mf6c_origin = mfccp->mf6cc_origin;
899 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
900 rt->mf6c_parent = mfccp->mf6cc_parent;
901 rt->mf6c_ifset = mfccp->mf6cc_ifset;
902 /* initialize pkt counters per src-grp */
903 rt->mf6c_pkt_cnt = 0;
904 rt->mf6c_byte_cnt = 0;
905 rt->mf6c_wrong_if = 0;
906 rt->mf6c_expire = 0;
907 rt->mf6c_stall = NULL;
908
909 /* link into table */
910 rt->mf6c_next = mf6ctable[hash];
911 mf6ctable[hash] = rt;
912 }
913 }
914 splx(s);
915 return (0);
916 }
917
918 #ifdef UPCALL_TIMING
919 /*
920 * collect delay statistics on the upcalls
921 */
922 static void
923 collate(struct timeval *t)
924 {
925 u_long d;
926 struct timeval tp;
927 u_long delta;
928
929 GET_TIME(tp);
930
931 if (TV_LT(*t, tp))
932 {
933 TV_DELTA(tp, *t, delta);
934
935 d = delta >> 10;
936 if (d > UPCALL_MAX)
937 d = UPCALL_MAX;
938
939 ++upcall_data[d];
940 }
941 }
942 #endif /* UPCALL_TIMING */
943
944 /*
945 * Delete an mfc entry
946 */
947 static int
948 del_m6fc(struct mf6cctl *mfccp)
949 {
950 struct sockaddr_in6 origin;
951 struct sockaddr_in6 mcastgrp;
952 struct mf6c *rt;
953 struct mf6c **nptr;
954 u_long hash;
955 int s;
956
957 origin = mfccp->mf6cc_origin;
958 mcastgrp = mfccp->mf6cc_mcastgrp;
959 hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
960
961 #ifdef MRT6DEBUG
962 if (V_mrt6debug & DEBUG_MFC) {
963 char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
964 log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
965 ip6_sprintf(ip6bufo, &origin.sin6_addr),
966 ip6_sprintf(ip6bufg, &mcastgrp.sin6_addr));
967 }
968 #endif
969
970 s = splnet();
971
972 nptr = &mf6ctable[hash];
973 while ((rt = *nptr) != NULL) {
974 if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
975 &rt->mf6c_origin.sin6_addr) &&
976 IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
977 &rt->mf6c_mcastgrp.sin6_addr) &&
978 rt->mf6c_stall == NULL)
979 break;
980
981 nptr = &rt->mf6c_next;
982 }
983 if (rt == NULL) {
984 splx(s);
985 return (EADDRNOTAVAIL);
986 }
987
988 *nptr = rt->mf6c_next;
989 free(rt, M_MRTABLE6);
990
991 splx(s);
992
993 return (0);
994 }
995
996 static int
997 socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src)
998 {
999
1000 if (s) {
1001 if (sbappendaddr(&s->so_rcv,
1002 (struct sockaddr *)src,
1003 mm, (struct mbuf *)0) != 0) {
1004 sorwakeup(s);
1005 return (0);
1006 }
1007 }
1008 m_freem(mm);
1009 return (-1);
1010 }
1011
1012 /*
1013 * IPv6 multicast forwarding function. This function assumes that the packet
1014 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
1015 * pointed to by "ifp", and the packet is to be relayed to other networks
1016 * that have members of the packet's destination IPv6 multicast group.
1017 *
1018 * The packet is returned unscathed to the caller, unless it is
1019 * erroneous, in which case a non-zero return value tells the caller to
1020 * discard it.
1021 *
1022 * NOTE: this implementation assumes that m->m_pkthdr.rcvif is NULL iff
1023 * this function is called in the originating context (i.e., not when
1024 * forwarding a packet from other node). ip6_output(), which is currently the
1025 * only function that calls this function is called in the originating context,
1026 * explicitly ensures this condition. It is caller's responsibility to ensure
1027 * that if this function is called from somewhere else in the originating
1028 * context in the future.
1029 */
1030 int
1031 |