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