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