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