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