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