ip6_mroute.c revision 121816
1/* $FreeBSD: head/sys/netinet6/ip6_mroute.c 121816 2003-10-31 18:32:15Z brooks $ */ 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 strlcpy(multicast_register_if.if_xname, "register_mif", 588 IFNAMSIZ); 589 multicast_register_if.if_flags |= IFF_LOOPBACK; 590 multicast_register_if.if_index = mifcp->mif6c_mifi; 591 reg_mif_num = mifcp->mif6c_mifi; 592 } 593 594 ifp = &multicast_register_if; 595 596 } /* if REGISTER */ 597 else { 598 /* Make sure the interface supports multicast */ 599 if ((ifp->if_flags & IFF_MULTICAST) == 0) 600 return (EOPNOTSUPP); 601 602 s = splnet(); 603 error = if_allmulti(ifp, 1); 604 splx(s); 605 if (error) 606 return (error); 607 } 608 609 s = splnet(); 610 mifp->m6_flags = mifcp->mif6c_flags; 611 mifp->m6_ifp = ifp; 612#ifdef notyet 613 /* scaling up here allows division by 1024 in critical code */ 614 mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000; 615#endif 616 /* initialize per mif pkt counters */ 617 mifp->m6_pkt_in = 0; 618 mifp->m6_pkt_out = 0; 619 mifp->m6_bytes_in = 0; 620 mifp->m6_bytes_out = 0; 621 splx(s); 622 623 /* Adjust nummifs up if the mifi is higher than nummifs */ 624 if (nummifs <= mifcp->mif6c_mifi) 625 nummifs = mifcp->mif6c_mifi + 1; 626 627#ifdef MRT6DEBUG 628 if (mrt6debug) 629 log(LOG_DEBUG, 630 "add_mif #%d, phyint %s\n", 631 mifcp->mif6c_mifi, 632 ifp->if_xname); 633#endif 634 635 return (0); 636} 637 638/* 639 * Delete a mif from the mif table 640 */ 641static int 642del_m6if(mifip) 643 mifi_t *mifip; 644{ 645 struct mif6 *mifp = mif6table + *mifip; 646 mifi_t mifi; 647 struct ifnet *ifp; 648 int s; 649 650 if (*mifip >= nummifs) 651 return (EINVAL); 652 if (mifp->m6_ifp == NULL) 653 return (EINVAL); 654 655 s = splnet(); 656 657 if (!(mifp->m6_flags & MIFF_REGISTER)) { 658 /* 659 * XXX: what if there is yet IPv4 multicast daemon 660 * using the interface? 661 */ 662 ifp = mifp->m6_ifp; 663 664 if_allmulti(ifp, 0); 665 } 666 667#ifdef notyet 668 bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip])); 669 bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf))); 670#endif 671 bzero((caddr_t)mifp, sizeof (*mifp)); 672 673 /* Adjust nummifs down */ 674 for (mifi = nummifs; mifi > 0; mifi--) 675 if (mif6table[mifi - 1].m6_ifp) 676 break; 677 nummifs = mifi; 678 679 splx(s); 680 681#ifdef MRT6DEBUG 682 if (mrt6debug) 683 log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs); 684#endif 685 686 return (0); 687} 688 689/* 690 * Add an mfc entry 691 */ 692static int 693add_m6fc(mfccp) 694 struct mf6cctl *mfccp; 695{ 696 struct mf6c *rt; 697 u_long hash; 698 struct rtdetq *rte; 699 u_short nstl; 700 int s; 701 702 MF6CFIND(mfccp->mf6cc_origin.sin6_addr, 703 mfccp->mf6cc_mcastgrp.sin6_addr, rt); 704 705 /* If an entry already exists, just update the fields */ 706 if (rt) { 707#ifdef MRT6DEBUG 708 if (mrt6debug & DEBUG_MFC) 709 log(LOG_DEBUG, 710 "add_m6fc no upcall h %d o %s g %s p %x\n", 711 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr), 712 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr), 713 mfccp->mf6cc_parent); 714#endif 715 716 s = splnet(); 717 rt->mf6c_parent = mfccp->mf6cc_parent; 718 rt->mf6c_ifset = mfccp->mf6cc_ifset; 719 splx(s); 720 return (0); 721 } 722 723 /* 724 * Find the entry for which the upcall was made and update 725 */ 726 s = splnet(); 727 hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr, 728 mfccp->mf6cc_mcastgrp.sin6_addr); 729 for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) { 730 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, 731 &mfccp->mf6cc_origin.sin6_addr) && 732 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, 733 &mfccp->mf6cc_mcastgrp.sin6_addr) && 734 (rt->mf6c_stall != NULL)) { 735 736 if (nstl++) 737 log(LOG_ERR, 738 "add_m6fc: %s o %s g %s p %x dbx %p\n", 739 "multiple kernel entries", 740 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr), 741 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr), 742 mfccp->mf6cc_parent, rt->mf6c_stall); 743 744#ifdef MRT6DEBUG 745 if (mrt6debug & DEBUG_MFC) 746 log(LOG_DEBUG, 747 "add_m6fc o %s g %s p %x dbg %x\n", 748 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr), 749 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr), 750 mfccp->mf6cc_parent, rt->mf6c_stall); 751#endif 752 753 rt->mf6c_origin = mfccp->mf6cc_origin; 754 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp; 755 rt->mf6c_parent = mfccp->mf6cc_parent; 756 rt->mf6c_ifset = mfccp->mf6cc_ifset; 757 /* initialize pkt counters per src-grp */ 758 rt->mf6c_pkt_cnt = 0; 759 rt->mf6c_byte_cnt = 0; 760 rt->mf6c_wrong_if = 0; 761 762 rt->mf6c_expire = 0; /* Don't clean this guy up */ 763 n6expire[hash]--; 764 765 /* free packets Qed at the end of this entry */ 766 for (rte = rt->mf6c_stall; rte != NULL; ) { 767 struct rtdetq *n = rte->next; 768 ip6_mdq(rte->m, rte->ifp, rt); 769 m_freem(rte->m); 770#ifdef UPCALL_TIMING 771 collate(&(rte->t)); 772#endif /* UPCALL_TIMING */ 773 free(rte, M_MRTABLE); 774 rte = n; 775 } 776 rt->mf6c_stall = NULL; 777 } 778 } 779 780 /* 781 * It is possible that an entry is being inserted without an upcall 782 */ 783 if (nstl == 0) { 784#ifdef MRT6DEBUG 785 if (mrt6debug & DEBUG_MFC) 786 log(LOG_DEBUG, 787 "add_mfc no upcall h %d o %s g %s p %x\n", 788 hash, 789 ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr), 790 ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr), 791 mfccp->mf6cc_parent); 792#endif 793 794 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { 795 796 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, 797 &mfccp->mf6cc_origin.sin6_addr)&& 798 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, 799 &mfccp->mf6cc_mcastgrp.sin6_addr)) { 800 801 rt->mf6c_origin = mfccp->mf6cc_origin; 802 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp; 803 rt->mf6c_parent = mfccp->mf6cc_parent; 804 rt->mf6c_ifset = mfccp->mf6cc_ifset; 805 /* initialize pkt counters per src-grp */ 806 rt->mf6c_pkt_cnt = 0; 807 rt->mf6c_byte_cnt = 0; 808 rt->mf6c_wrong_if = 0; 809 810 if (rt->mf6c_expire) 811 n6expire[hash]--; 812 rt->mf6c_expire = 0; 813 } 814 } 815 if (rt == NULL) { 816 /* no upcall, so make a new entry */ 817 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE, 818 M_NOWAIT); 819 if (rt == NULL) { 820 splx(s); 821 return (ENOBUFS); 822 } 823 824 /* insert new entry at head of hash chain */ 825 rt->mf6c_origin = mfccp->mf6cc_origin; 826 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp; 827 rt->mf6c_parent = mfccp->mf6cc_parent; 828 rt->mf6c_ifset = mfccp->mf6cc_ifset; 829 /* initialize pkt counters per src-grp */ 830 rt->mf6c_pkt_cnt = 0; 831 rt->mf6c_byte_cnt = 0; 832 rt->mf6c_wrong_if = 0; 833 rt->mf6c_expire = 0; 834 rt->mf6c_stall = NULL; 835 836 /* link into table */ 837 rt->mf6c_next = mf6ctable[hash]; 838 mf6ctable[hash] = rt; 839 } 840 } 841 splx(s); 842 return (0); 843} 844 845#ifdef UPCALL_TIMING 846/* 847 * collect delay statistics on the upcalls 848 */ 849static void 850collate(t) 851 struct timeval *t; 852{ 853 u_long d; 854 struct timeval tp; 855 u_long delta; 856 857 GET_TIME(tp); 858 859 if (TV_LT(*t, tp)) 860 { 861 TV_DELTA(tp, *t, delta); 862 863 d = delta >> 10; 864 if (d > UPCALL_MAX) 865 d = UPCALL_MAX; 866 867 ++upcall_data[d]; 868 } 869} 870#endif /* UPCALL_TIMING */ 871 872/* 873 * Delete an mfc entry 874 */ 875static int 876del_m6fc(mfccp) 877 struct mf6cctl *mfccp; 878{ 879 struct sockaddr_in6 origin; 880 struct sockaddr_in6 mcastgrp; 881 struct mf6c *rt; 882 struct mf6c **nptr; 883 u_long hash; 884 int s; 885 886 origin = mfccp->mf6cc_origin; 887 mcastgrp = mfccp->mf6cc_mcastgrp; 888 hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr); 889 890#ifdef MRT6DEBUG 891 if (mrt6debug & DEBUG_MFC) 892 log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n", 893 ip6_sprintf(&origin.sin6_addr), 894 ip6_sprintf(&mcastgrp.sin6_addr)); 895#endif 896 897 s = splnet(); 898 899 nptr = &mf6ctable[hash]; 900 while ((rt = *nptr) != NULL) { 901 if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr, 902 &rt->mf6c_origin.sin6_addr) && 903 IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr, 904 &rt->mf6c_mcastgrp.sin6_addr) && 905 rt->mf6c_stall == NULL) 906 break; 907 908 nptr = &rt->mf6c_next; 909 } 910 if (rt == NULL) { 911 splx(s); 912 return (EADDRNOTAVAIL); 913 } 914 915 *nptr = rt->mf6c_next; 916 free(rt, M_MRTABLE); 917 918 splx(s); 919 920 return (0); 921} 922 923static int 924socket_send(s, mm, src) 925 struct socket *s; 926 struct mbuf *mm; 927 struct sockaddr_in6 *src; 928{ 929 if (s) { 930 if (sbappendaddr(&s->so_rcv, 931 (struct sockaddr *)src, 932 mm, (struct mbuf *)0) != 0) { 933 sorwakeup(s); 934 return (0); 935 } 936 } 937 m_freem(mm); 938 return (-1); 939} 940 941/* 942 * IPv6 multicast forwarding function. This function assumes that the packet 943 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface 944 * pointed to by "ifp", and the packet is to be relayed to other networks 945 * that have members of the packet's destination IPv6 multicast group. 946 * 947 * The packet is returned unscathed to the caller, unless it is 948 * erroneous, in which case a non-zero return value tells the caller to 949 * discard it. 950 */ 951 952int 953ip6_mforward(ip6, ifp, m) 954 struct ip6_hdr *ip6; 955 struct ifnet *ifp; 956 struct mbuf *m; 957{ 958 struct mf6c *rt; 959 struct mif6 *mifp; 960 struct mbuf *mm; 961 int s; 962 mifi_t mifi; 963 964#ifdef MRT6DEBUG 965 if (mrt6debug & DEBUG_FORWARD) 966 log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n", 967 ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst), 968 ifp->if_index); 969#endif 970 971 /* 972 * Don't forward a packet with Hop limit of zero or one, 973 * or a packet destined to a local-only group. 974 */ 975 if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) || 976 IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) 977 return (0); 978 ip6->ip6_hlim--; 979 980 /* 981 * Source address check: do not forward packets with unspecified 982 * source. It was discussed in July 2000, on ipngwg mailing list. 983 * This is rather more serious than unicast cases, because some 984 * MLD packets can be sent with the unspecified source address 985 * (although such packets must normally set 1 to the hop limit field). 986 */ 987 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { 988 ip6stat.ip6s_cantforward++; 989 if (ip6_log_time + ip6_log_interval < time_second) { 990 ip6_log_time = time_second; 991 log(LOG_DEBUG, 992 "cannot forward " 993 "from %s to %s nxt %d received on %s\n", 994 ip6_sprintf(&ip6->ip6_src), 995 ip6_sprintf(&ip6->ip6_dst), 996 ip6->ip6_nxt, 997 if_name(m->m_pkthdr.rcvif)); 998 } 999 return (0); 1000 } 1001 1002 /* 1003 * Determine forwarding mifs from the forwarding cache table 1004 */ 1005 s = splnet(); 1006 MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt); 1007 1008 /* Entry exists, so forward if necessary */ 1009 if (rt) { 1010 splx(s); 1011 return (ip6_mdq(m, ifp, rt)); 1012 } else { 1013 /* 1014 * If we don't have a route for packet's origin, 1015 * Make a copy of the packet & 1016 * send message to routing daemon 1017 */ 1018 1019 struct mbuf *mb0; 1020 struct rtdetq *rte; 1021 u_long hash; 1022/* int i, npkts;*/ 1023#ifdef UPCALL_TIMING 1024 struct timeval tp; 1025 1026 GET_TIME(tp); 1027#endif /* UPCALL_TIMING */ 1028 1029 mrt6stat.mrt6s_no_route++; 1030#ifdef MRT6DEBUG 1031 if (mrt6debug & (DEBUG_FORWARD | DEBUG_MFC)) 1032 log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n", 1033 ip6_sprintf(&ip6->ip6_src), 1034 ip6_sprintf(&ip6->ip6_dst)); 1035#endif 1036 1037 /* 1038 * Allocate mbufs early so that we don't do extra work if we 1039 * are just going to fail anyway. 1040 */ 1041 rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE, 1042 M_NOWAIT); 1043 if (rte == NULL) { 1044 splx(s); 1045 return (ENOBUFS); 1046 } 1047 mb0 = m_copy(m, 0, M_COPYALL); 1048 /* 1049 * Pullup packet header if needed before storing it, 1050 * as other references may modify it in the meantime. 1051 */ 1052 if (mb0 && 1053 (M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr))) 1054 mb0 = m_pullup(mb0, sizeof(struct ip6_hdr)); 1055 if (mb0 == NULL) { 1056 free(rte, M_MRTABLE); 1057 splx(s); 1058 return (ENOBUFS); 1059 } 1060 1061 /* is there an upcall waiting for this packet? */ 1062 hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst); 1063 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { 1064 if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, 1065 &rt->mf6c_origin.sin6_addr) && 1066 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, 1067 &rt->mf6c_mcastgrp.sin6_addr) && 1068 (rt->mf6c_stall != NULL)) 1069 break; 1070 } 1071 1072 if (rt == NULL) { 1073 struct mrt6msg *im; 1074#ifdef MRT6_OINIT 1075 struct omrt6msg *oim; 1076#endif 1077 1078 /* no upcall, so make a new entry */ 1079 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE, 1080 M_NOWAIT); 1081 if (rt == NULL) { 1082 free(rte, M_MRTABLE); 1083 m_freem(mb0); 1084 splx(s); 1085 return (ENOBUFS); 1086 } 1087 /* 1088 * Make a copy of the header to send to the user 1089 * level process 1090 */ 1091 mm = m_copy(mb0, 0, sizeof(struct ip6_hdr)); 1092 1093 if (mm == NULL) { 1094 free(rte, M_MRTABLE); 1095 m_freem(mb0); 1096 free(rt, M_MRTABLE); 1097 splx(s); 1098 return (ENOBUFS); 1099 } 1100 1101 /* 1102 * Send message to routing daemon 1103 */ 1104 sin6.sin6_addr = ip6->ip6_src; 1105 1106 im = NULL; 1107#ifdef MRT6_OINIT 1108 oim = NULL; 1109#endif 1110 switch (ip6_mrouter_ver) { 1111#ifdef MRT6_OINIT 1112 case MRT6_OINIT: 1113 oim = mtod(mm, struct omrt6msg *); 1114 oim->im6_msgtype = MRT6MSG_NOCACHE; 1115 oim->im6_mbz = 0; 1116 break; 1117#endif 1118 case MRT6_INIT: 1119 im = mtod(mm, struct mrt6msg *); 1120 im->im6_msgtype = MRT6MSG_NOCACHE; 1121 im->im6_mbz = 0; 1122 break; 1123 default: 1124 free(rte, M_MRTABLE); 1125 m_freem(mb0); 1126 free(rt, M_MRTABLE); 1127 splx(s); 1128 return (EINVAL); 1129 } 1130 1131#ifdef MRT6DEBUG 1132 if (mrt6debug & DEBUG_FORWARD) 1133 log(LOG_DEBUG, 1134 "getting the iif info in the kernel\n"); 1135#endif 1136 1137 for (mifp = mif6table, mifi = 0; 1138 mifi < nummifs && mifp->m6_ifp != ifp; 1139 mifp++, mifi++) 1140 ; 1141 1142 switch (ip6_mrouter_ver) { 1143#ifdef MRT6_OINIT 1144 case MRT6_OINIT: 1145 oim->im6_mif = mifi; 1146 break; 1147#endif 1148 case MRT6_INIT: 1149 im->im6_mif = mifi; 1150 break; 1151 } 1152 1153 if (socket_send(ip6_mrouter, mm, &sin6) < 0) { 1154 log(LOG_WARNING, "ip6_mforward: ip6_mrouter " 1155 "socket queue full\n"); 1156 mrt6stat.mrt6s_upq_sockfull++; 1157 free(rte, M_MRTABLE); 1158 m_freem(mb0); 1159 free(rt, M_MRTABLE); 1160 splx(s); 1161 return (ENOBUFS); 1162 } 1163 1164 mrt6stat.mrt6s_upcalls++; 1165 1166 /* insert new entry at head of hash chain */ 1167 bzero(rt, sizeof(*rt)); 1168 rt->mf6c_origin.sin6_family = AF_INET6; 1169 rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6); 1170 rt->mf6c_origin.sin6_addr = ip6->ip6_src; 1171 rt->mf6c_mcastgrp.sin6_family = AF_INET6; 1172 rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6); 1173 rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst; 1174 rt->mf6c_expire = UPCALL_EXPIRE; 1175 n6expire[hash]++; 1176 rt->mf6c_parent = MF6C_INCOMPLETE_PARENT; 1177 1178 /* link into table */ 1179 rt->mf6c_next = mf6ctable[hash]; 1180 mf6ctable[hash] = rt; 1181 /* Add this entry to the end of the queue */ 1182 rt->mf6c_stall = rte; 1183 } else { 1184 /* determine if q has overflowed */ 1185 struct rtdetq **p; 1186 int npkts = 0; 1187 1188 for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next) 1189 if (++npkts > MAX_UPQ6) { 1190 mrt6stat.mrt6s_upq_ovflw++; 1191 free(rte, M_MRTABLE); 1192 m_freem(mb0); 1193 splx(s); 1194 return (0); 1195 } 1196 1197 /* Add this entry to the end of the queue */ 1198 *p = rte; 1199 } 1200 1201 rte->next = NULL; 1202 rte->m = mb0; 1203 rte->ifp = ifp; 1204#ifdef UPCALL_TIMING 1205 rte->t = tp; 1206#endif /* UPCALL_TIMING */ 1207 1208 splx(s); 1209 1210 return (0); 1211 } 1212} 1213 1214/* 1215 * Clean up cache entries if upcalls are not serviced 1216 * Call from the Slow Timeout mechanism, every half second. 1217 */ 1218static void 1219expire_upcalls(unused) 1220 void *unused; 1221{ 1222 struct rtdetq *rte; 1223 struct mf6c *mfc, **nptr; 1224 int i; 1225 int s; 1226 1227 s = splnet(); 1228 for (i = 0; i < MF6CTBLSIZ; i++) { 1229 if (n6expire[i] == 0) 1230 continue; 1231 nptr = &mf6ctable[i]; 1232 while ((mfc = *nptr) != NULL) { 1233 rte = mfc->mf6c_stall; 1234 /* 1235 * Skip real cache entries 1236 * Make sure it wasn't marked to not expire (shouldn't happen) 1237 * If it expires now 1238 */ 1239 if (rte != NULL && 1240 mfc->mf6c_expire != 0 && 1241 --mfc->mf6c_expire == 0) { 1242#ifdef MRT6DEBUG 1243 if (mrt6debug & DEBUG_EXPIRE) 1244 log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n", 1245 ip6_sprintf(&mfc->mf6c_origin.sin6_addr), 1246 ip6_sprintf(&mfc->mf6c_mcastgrp.sin6_addr)); 1247#endif 1248 /* 1249 * drop all the packets 1250 * free the mbuf with the pkt, if, timing info 1251 */ 1252 do { 1253 struct rtdetq *n = rte->next; 1254 m_freem(rte->m); 1255 free(rte, M_MRTABLE); 1256 rte = n; 1257 } while (rte != NULL); 1258 mrt6stat.mrt6s_cache_cleanups++; 1259 n6expire[i]--; 1260 1261 *nptr = mfc->mf6c_next; 1262 free(mfc, M_MRTABLE); 1263 } else { 1264 nptr = &mfc->mf6c_next; 1265 } 1266 } 1267 } 1268 splx(s); 1269 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, 1270 expire_upcalls, NULL); 1271} 1272 1273/* 1274 * Packet forwarding routine once entry in the cache is made 1275 */ 1276static int 1277ip6_mdq(m, ifp, rt) 1278 struct mbuf *m; 1279 struct ifnet *ifp; 1280 struct mf6c *rt; 1281{ 1282 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1283 mifi_t mifi, iif; 1284 struct mif6 *mifp; 1285 int plen = m->m_pkthdr.len; 1286 u_int32_t dscopein, sscopein; 1287 1288/* 1289 * Macro to send packet on mif. Since RSVP packets don't get counted on 1290 * input, they shouldn't get counted on output, so statistics keeping is 1291 * separate. 1292 */ 1293 1294#define MC6_SEND(ip6, mifp, m) do { \ 1295 if ((mifp)->m6_flags & MIFF_REGISTER) \ 1296 register_send((ip6), (mifp), (m)); \ 1297 else \ 1298 phyint_send((ip6), (mifp), (m)); \ 1299} while (/*CONSTCOND*/ 0) 1300 1301 /* 1302 * Don't forward if it didn't arrive from the parent mif 1303 * for its origin. 1304 */ 1305 mifi = rt->mf6c_parent; 1306 if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) { 1307 /* came in the wrong interface */ 1308#ifdef MRT6DEBUG 1309 if (mrt6debug & DEBUG_FORWARD) 1310 log(LOG_DEBUG, 1311 "wrong if: ifid %d mifi %d mififid %x\n", 1312 ifp->if_index, mifi, 1313 mif6table[mifi].m6_ifp->if_index); 1314#endif 1315 mrt6stat.mrt6s_wrong_if++; 1316 rt->mf6c_wrong_if++; 1317 /* 1318 * If we are doing PIM processing, and we are forwarding 1319 * packets on this interface, send a message to the 1320 * routing daemon. 1321 */ 1322 /* have to make sure this is a valid mif */ 1323 if (mifi < nummifs && mif6table[mifi].m6_ifp) 1324 if (pim6 && (m->m_flags & M_LOOP) == 0) { 1325 /* 1326 * Check the M_LOOP flag to avoid an 1327 * unnecessary PIM assert. 1328 * XXX: M_LOOP is an ad-hoc hack... 1329 */ 1330 static struct sockaddr_in6 sin6 = 1331 { sizeof(sin6), AF_INET6 }; 1332 1333 struct mbuf *mm; 1334 struct mrt6msg *im; 1335#ifdef MRT6_OINIT 1336 struct omrt6msg *oim; 1337#endif 1338 1339 mm = m_copy(m, 0, sizeof(struct ip6_hdr)); 1340 if (mm && 1341 (M_HASCL(mm) || 1342 mm->m_len < sizeof(struct ip6_hdr))) 1343 mm = m_pullup(mm, sizeof(struct ip6_hdr)); 1344 if (mm == NULL) 1345 return (ENOBUFS); 1346 1347#ifdef MRT6_OINIT 1348 oim = NULL; 1349#endif 1350 im = NULL; 1351 switch (ip6_mrouter_ver) { 1352#ifdef MRT6_OINIT 1353 case MRT6_OINIT: 1354 oim = mtod(mm, struct omrt6msg *); 1355 oim->im6_msgtype = MRT6MSG_WRONGMIF; 1356 oim->im6_mbz = 0; 1357 break; 1358#endif 1359 case MRT6_INIT: 1360 im = mtod(mm, struct mrt6msg *); 1361 im->im6_msgtype = MRT6MSG_WRONGMIF; 1362 im->im6_mbz = 0; 1363 break; 1364 default: 1365 m_freem(mm); 1366 return (EINVAL); 1367 } 1368 1369 for (mifp = mif6table, iif = 0; 1370 iif < nummifs && mifp && 1371 mifp->m6_ifp != ifp; 1372 mifp++, iif++) 1373 ; 1374 1375 switch (ip6_mrouter_ver) { 1376#ifdef MRT6_OINIT 1377 case MRT6_OINIT: 1378 oim->im6_mif = iif; 1379 sin6.sin6_addr = oim->im6_src; 1380 break; 1381#endif 1382 case MRT6_INIT: 1383 im->im6_mif = iif; 1384 sin6.sin6_addr = im->im6_src; 1385 break; 1386 } 1387 1388 mrt6stat.mrt6s_upcalls++; 1389 1390 if (socket_send(ip6_mrouter, mm, &sin6) < 0) { 1391#ifdef MRT6DEBUG 1392 if (mrt6debug) 1393 log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n"); 1394#endif 1395 ++mrt6stat.mrt6s_upq_sockfull; 1396 return (ENOBUFS); 1397 } /* if socket Q full */ 1398 } /* if PIM */ 1399 return (0); 1400 } /* if wrong iif */ 1401 1402 /* If I sourced this packet, it counts as output, else it was input. */ 1403 if (m->m_pkthdr.rcvif == NULL) { 1404 /* XXX: is rcvif really NULL when output?? */ 1405 mif6table[mifi].m6_pkt_out++; 1406 mif6table[mifi].m6_bytes_out += plen; 1407 } else { 1408 mif6table[mifi].m6_pkt_in++; 1409 mif6table[mifi].m6_bytes_in += plen; 1410 } 1411 rt->mf6c_pkt_cnt++; 1412 rt->mf6c_byte_cnt += plen; 1413 1414 /* 1415 * For each mif, forward a copy of the packet if there are group 1416 * members downstream on the interface. 1417 */ 1418 if (in6_addr2zoneid(ifp, &ip6->ip6_dst, &dscopein) || 1419 in6_addr2zoneid(ifp, &ip6->ip6_src, &sscopein)) 1420 return (EINVAL); 1421 for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) { 1422 if (IF_ISSET(mifi, &rt->mf6c_ifset)) { 1423 u_int32_t dscopeout, sscopeout; 1424 1425 /* 1426 * check if the outgoing packet is going to break 1427 * a scope boundary. 1428 * XXX For packets through PIM register tunnel 1429 * interface, we believe a routing daemon. 1430 */ 1431 if (!(mif6table[rt->mf6c_parent].m6_flags & 1432 MIFF_REGISTER) && 1433 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { 1434 if (in6_addr2zoneid(mif6table[mifi].m6_ifp, 1435 &ip6->ip6_dst, 1436 &dscopeout) || 1437 in6_addr2zoneid(mif6table[mifi].m6_ifp, 1438 &ip6->ip6_src, 1439 &sscopeout) || 1440 dscopein != dscopeout || 1441 sscopein != sscopeout) { 1442 ip6stat.ip6s_badscope++; 1443 continue; 1444 } 1445 } 1446 1447 mifp->m6_pkt_out++; 1448 mifp->m6_bytes_out += plen; 1449 MC6_SEND(ip6, mifp, m); 1450 } 1451 } 1452 return (0); 1453} 1454 1455static void 1456phyint_send(ip6, mifp, m) 1457 struct ip6_hdr *ip6; 1458 struct mif6 *mifp; 1459 struct mbuf *m; 1460{ 1461 struct mbuf *mb_copy; 1462 struct ifnet *ifp = mifp->m6_ifp; 1463 int error = 0; 1464 int s = splnet(); /* needs to protect static "ro" below. */ 1465 static struct route_in6 ro; 1466 struct in6_multi *in6m; 1467 struct sockaddr_in6 *dst6; 1468 u_long linkmtu; 1469 1470 /* 1471 * Make a new reference to the packet; make sure that 1472 * the IPv6 header is actually copied, not just referenced, 1473 * so that ip6_output() only scribbles on the copy. 1474 */ 1475 mb_copy = m_copy(m, 0, M_COPYALL); 1476 if (mb_copy && 1477 (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr))) 1478 mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr)); 1479 if (mb_copy == NULL) { 1480 splx(s); 1481 return; 1482 } 1483 /* set MCAST flag to the outgoing packet */ 1484 mb_copy->m_flags |= M_MCAST; 1485 1486 /* 1487 * If we sourced the packet, call ip6_output since we may devide 1488 * the packet into fragments when the packet is too big for the 1489 * outgoing interface. 1490 * Otherwise, we can simply send the packet to the interface 1491 * sending queue. 1492 */ 1493 if (m->m_pkthdr.rcvif == NULL) { 1494 struct ip6_moptions im6o; 1495 1496 im6o.im6o_multicast_ifp = ifp; 1497 /* XXX: ip6_output will override ip6->ip6_hlim */ 1498 im6o.im6o_multicast_hlim = ip6->ip6_hlim; 1499 im6o.im6o_multicast_loop = 1; 1500 error = ip6_output(mb_copy, NULL, &ro, 1501 IPV6_FORWARDING, &im6o, NULL, NULL); 1502 1503#ifdef MRT6DEBUG 1504 if (mrt6debug & DEBUG_XMIT) 1505 log(LOG_DEBUG, "phyint_send on mif %d err %d\n", 1506 mifp - mif6table, error); 1507#endif 1508 splx(s); 1509 return; 1510 } 1511 1512 /* 1513 * If we belong to the destination multicast group 1514 * on the outgoing interface, loop back a copy. 1515 */ 1516 dst6 = (struct sockaddr_in6 *)&ro.ro_dst; 1517 IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m); 1518 if (in6m != NULL) { 1519 dst6->sin6_len = sizeof(struct sockaddr_in6); 1520 dst6->sin6_family = AF_INET6; 1521 dst6->sin6_addr = ip6->ip6_dst; 1522 ip6_mloopback(ifp, m, (struct sockaddr_in6 *)&ro.ro_dst); 1523 } 1524 /* 1525 * Put the packet into the sending queue of the outgoing interface 1526 * if it would fit in the MTU of the interface. 1527 */ 1528 linkmtu = IN6_LINKMTU(ifp); 1529 if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) { 1530 dst6->sin6_len = sizeof(struct sockaddr_in6); 1531 dst6->sin6_family = AF_INET6; 1532 dst6->sin6_addr = ip6->ip6_dst; 1533 /* 1534 * We just call if_output instead of nd6_output here, since 1535 * we need no ND for a multicast forwarded packet...right? 1536 */ 1537 error = (*ifp->if_output)(ifp, mb_copy, 1538 (struct sockaddr *)&ro.ro_dst, NULL); 1539#ifdef MRT6DEBUG 1540 if (mrt6debug & DEBUG_XMIT) 1541 log(LOG_DEBUG, "phyint_send on mif %d err %d\n", 1542 mifp - mif6table, error); 1543#endif 1544 } else { 1545#ifdef MULTICAST_PMTUD 1546 icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, linkmtu); 1547#else 1548#ifdef MRT6DEBUG 1549 if (mrt6debug & DEBUG_XMIT) 1550 log(LOG_DEBUG, 1551 "phyint_send: packet too big on %s o %s g %s" 1552 " size %d(discarded)\n", 1553 if_name(ifp), 1554 ip6_sprintf(&ip6->ip6_src), 1555 ip6_sprintf(&ip6->ip6_dst), 1556 mb_copy->m_pkthdr.len); 1557#endif /* MRT6DEBUG */ 1558 m_freem(mb_copy); /* simply discard the packet */ 1559#endif 1560 } 1561 1562 splx(s); 1563} 1564 1565static int 1566register_send(ip6, mif, m) 1567 struct ip6_hdr *ip6; 1568 struct mif6 *mif; 1569 struct mbuf *m; 1570{ 1571 struct mbuf *mm; 1572 int i, len = m->m_pkthdr.len; 1573 static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 }; 1574 struct mrt6msg *im6; 1575 1576#ifdef MRT6DEBUG 1577 if (mrt6debug) 1578 log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n", 1579 ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst)); 1580#endif 1581 ++pim6stat.pim6s_snd_registers; 1582 1583 /* Make a copy of the packet to send to the user level process */ 1584 MGETHDR(mm, M_DONTWAIT, MT_HEADER); 1585 if (mm == NULL) 1586 return (ENOBUFS); 1587 mm->m_pkthdr.rcvif = NULL; 1588 mm->m_data += max_linkhdr; 1589 mm->m_len = sizeof(struct ip6_hdr); 1590 1591 if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { 1592 m_freem(mm); 1593 return (ENOBUFS); 1594 } 1595 i = MHLEN - M_LEADINGSPACE(mm); 1596 if (i > len) 1597 i = len; 1598 mm = m_pullup(mm, i); 1599 if (mm == NULL) 1600 return (ENOBUFS); 1601/* TODO: check it! */ 1602 mm->m_pkthdr.len = len + sizeof(struct ip6_hdr); 1603 1604 /* 1605 * Send message to routing daemon 1606 */ 1607 sin6.sin6_addr = ip6->ip6_src; 1608 1609 im6 = mtod(mm, struct mrt6msg *); 1610 im6->im6_msgtype = MRT6MSG_WHOLEPKT; 1611 im6->im6_mbz = 0; 1612 1613 im6->im6_mif = mif - mif6table; 1614 1615 /* iif info is not given for reg. encap.n */ 1616 mrt6stat.mrt6s_upcalls++; 1617 1618 if (socket_send(ip6_mrouter, mm, &sin6) < 0) { 1619#ifdef MRT6DEBUG 1620 if (mrt6debug) 1621 log(LOG_WARNING, 1622 "register_send: ip6_mrouter socket queue full\n"); 1623#endif 1624 ++mrt6stat.mrt6s_upq_sockfull; 1625 return (ENOBUFS); 1626 } 1627 return (0); 1628} 1629 1630/* 1631 * PIM sparse mode hook 1632 * Receives the pim control messages, and passes them up to the listening 1633 * socket, using rip6_input. 1634 * The only message processed is the REGISTER pim message; the pim header 1635 * is stripped off, and the inner packet is passed to register_mforward. 1636 */ 1637int 1638pim6_input(mp, offp, proto) 1639 struct mbuf **mp; 1640 int *offp, proto; 1641{ 1642 struct pim *pim; /* pointer to a pim struct */ 1643 struct ip6_hdr *ip6; 1644 int pimlen; 1645 struct mbuf *m = *mp; 1646 int minlen; 1647 int off = *offp; 1648 1649 ++pim6stat.pim6s_rcv_total; 1650 1651 ip6 = mtod(m, struct ip6_hdr *); 1652 pimlen = m->m_pkthdr.len - *offp; 1653 1654 /* 1655 * Validate lengths 1656 */ 1657 if (pimlen < PIM_MINLEN) { 1658 ++pim6stat.pim6s_rcv_tooshort; 1659#ifdef MRT6DEBUG 1660 if (mrt6debug & DEBUG_PIM) 1661 log(LOG_DEBUG,"pim6_input: PIM packet too short\n"); 1662#endif 1663 m_freem(m); 1664 return (IPPROTO_DONE); 1665 } 1666 1667 /* 1668 * if the packet is at least as big as a REGISTER, go ahead 1669 * and grab the PIM REGISTER header size, to avoid another 1670 * possible m_pullup() later. 1671 * 1672 * PIM_MINLEN == pimhdr + u_int32 == 8 1673 * PIM6_REG_MINLEN == pimhdr + reghdr + eip6hdr == 4 + 4 + 40 1674 */ 1675 minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN; 1676 1677 /* 1678 * Make sure that the IP6 and PIM headers in contiguous memory, and 1679 * possibly the PIM REGISTER header 1680 */ 1681#ifndef PULLDOWN_TEST 1682 IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE); 1683 /* adjust pointer */ 1684 ip6 = mtod(m, struct ip6_hdr *); 1685 1686 /* adjust mbuf to point to the PIM header */ 1687 pim = (struct pim *)((caddr_t)ip6 + off); 1688#else 1689 IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen); 1690 if (pim == NULL) { 1691 pim6stat.pim6s_rcv_tooshort++; 1692 return (IPPROTO_DONE); 1693 } 1694#endif 1695 1696#define PIM6_CHECKSUM 1697#ifdef PIM6_CHECKSUM 1698 { 1699 int cksumlen; 1700 1701 /* 1702 * Validate checksum. 1703 * If PIM REGISTER, exclude the data packet 1704 */ 1705 if (pim->pim_type == PIM_REGISTER) 1706 cksumlen = PIM_MINLEN; 1707 else 1708 cksumlen = pimlen; 1709 1710 if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) { 1711 ++pim6stat.pim6s_rcv_badsum; 1712#ifdef MRT6DEBUG 1713 if (mrt6debug & DEBUG_PIM) 1714 log(LOG_DEBUG, 1715 "pim6_input: invalid checksum\n"); 1716#endif 1717 m_freem(m); 1718 return (IPPROTO_DONE); 1719 } 1720 } 1721#endif /* PIM_CHECKSUM */ 1722 1723 /* PIM version check */ 1724 if (pim->pim_ver != PIM_VERSION) { 1725 ++pim6stat.pim6s_rcv_badversion; 1726#ifdef MRT6DEBUG 1727 log(LOG_ERR, 1728 "pim6_input: incorrect version %d, expecting %d\n", 1729 pim->pim_ver, PIM_VERSION); 1730#endif 1731 m_freem(m); 1732 return (IPPROTO_DONE); 1733 } 1734 1735 if (pim->pim_type == PIM_REGISTER) { 1736 /* 1737 * since this is a REGISTER, we'll make a copy of the register 1738 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the 1739 * routing daemon. 1740 */ 1741 static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 }; 1742 1743 struct mbuf *mcp; 1744 struct ip6_hdr *eip6; 1745 u_int32_t *reghdr; 1746 int rc; 1747 1748 ++pim6stat.pim6s_rcv_registers; 1749 1750 if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) { 1751#ifdef MRT6DEBUG 1752 if (mrt6debug & DEBUG_PIM) 1753 log(LOG_DEBUG, 1754 "pim6_input: register mif not set: %d\n", 1755 reg_mif_num); 1756#endif 1757 m_freem(m); 1758 return (IPPROTO_DONE); 1759 } 1760 1761 reghdr = (u_int32_t *)(pim + 1); 1762 1763 if ((ntohl(*reghdr) & PIM_NULL_REGISTER)) 1764 goto pim6_input_to_daemon; 1765 1766 /* 1767 * Validate length 1768 */ 1769 if (pimlen < PIM6_REG_MINLEN) { 1770 ++pim6stat.pim6s_rcv_tooshort; 1771 ++pim6stat.pim6s_rcv_badregisters; 1772#ifdef MRT6DEBUG 1773 log(LOG_ERR, 1774 "pim6_input: register packet size too " 1775 "small %d from %s\n", 1776 pimlen, ip6_sprintf(&ip6->ip6_src)); 1777#endif 1778 m_freem(m); 1779 return (IPPROTO_DONE); 1780 } 1781 1782 eip6 = (struct ip6_hdr *) (reghdr + 1); 1783#ifdef MRT6DEBUG 1784 if (mrt6debug & DEBUG_PIM) 1785 log(LOG_DEBUG, 1786 "pim6_input[register], eip6: %s -> %s, " 1787 "eip6 plen %d\n", 1788 ip6_sprintf(&eip6->ip6_src), 1789 ip6_sprintf(&eip6->ip6_dst), 1790 ntohs(eip6->ip6_plen)); 1791#endif 1792 1793 /* verify the version number of the inner packet */ 1794 if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 1795 ++pim6stat.pim6s_rcv_badregisters; 1796#ifdef MRT6DEBUG 1797 log(LOG_DEBUG, "pim6_input: invalid IP version (%d) " 1798 "of the inner packet\n", 1799 (eip6->ip6_vfc & IPV6_VERSION)); 1800#endif 1801 m_freem(m); 1802 return (IPPROTO_NONE); 1803 } 1804 1805 /* verify the inner packet is destined to a mcast group */ 1806 if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) { 1807 ++pim6stat.pim6s_rcv_badregisters; 1808#ifdef MRT6DEBUG 1809 if (mrt6debug & DEBUG_PIM) 1810 log(LOG_DEBUG, 1811 "pim6_input: inner packet of register " 1812 "is not multicast %s\n", 1813 ip6_sprintf(&eip6->ip6_dst)); 1814#endif 1815 m_freem(m); 1816 return (IPPROTO_DONE); 1817 } 1818 1819 /* 1820 * make a copy of the whole header to pass to the daemon later. 1821 */ 1822 mcp = m_copy(m, 0, off + PIM6_REG_MINLEN); 1823 if (mcp == NULL) { 1824#ifdef MRT6DEBUG 1825 log(LOG_ERR, 1826 "pim6_input: pim register: " 1827 "could not copy register head\n"); 1828#endif 1829 m_freem(m); 1830 return (IPPROTO_DONE); 1831 } 1832 1833 /* 1834 * forward the inner ip6 packet; point m_data at the inner ip6. 1835 */ 1836 m_adj(m, off + PIM_MINLEN); 1837#ifdef MRT6DEBUG 1838 if (mrt6debug & DEBUG_PIM) { 1839 log(LOG_DEBUG, 1840 "pim6_input: forwarding decapsulated register: " 1841 "src %s, dst %s, mif %d\n", 1842 ip6_sprintf(&eip6->ip6_src), 1843 ip6_sprintf(&eip6->ip6_dst), 1844 reg_mif_num); 1845 } 1846#endif 1847 1848 rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m, 1849 dst.sin6_family, NULL); 1850 1851 /* prepare the register head to send to the mrouting daemon */ 1852 m = mcp; 1853 } 1854 1855 /* 1856 * Pass the PIM message up to the daemon; if it is a register message 1857 * pass the 'head' only up to the daemon. This includes the 1858 * encapsulator ip6 header, pim header, register header and the 1859 * encapsulated ip6 header. 1860 */ 1861 pim6_input_to_daemon: 1862 rip6_input(&m, offp, proto); 1863 return (IPPROTO_DONE); 1864} 1865