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