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