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