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