1 /* 2 * Copyright (c) 1989 Stephen Deering 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Stephen Deering of Stanford University. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93 38 * $Id: ip_mroute.c,v 1.10 1994/05/13 06:06:23 mycroft Exp $ 39 */ 40 41 /* 42 * Procedures for the kernel part of DVMRP, 43 * a Distance-Vector Multicast Routing Protocol. 44 * (See RFC-1075.) 45 * 46 * Written by David Waitzman, BBN Labs, August 1988. 47 * Modified by Steve Deering, Stanford, February 1989. 48 * 49 * MROUTING 1.1 50 */ 51 52 #ifndef MROUTING 53 int ip_mrtproto; /* for netstat only */ 54 #else 55 56 #include <sys/param.h> 57 #include <sys/errno.h> 58 #include <sys/ioctl.h> 59 #include <sys/malloc.h> 60 #include <sys/mbuf.h> 61 #include <sys/protosw.h> 62 #include <sys/socket.h> 63 #include <sys/socketvar.h> 64 #include <sys/time.h> 65 66 #include <net/if.h> 67 #include <net/route.h> 68 #include <net/raw_cb.h> 69 70 #include <netinet/in.h> 71 #include <netinet/in_systm.h> 72 #include <netinet/ip.h> 73 #include <netinet/in_pcb.h> 74 #include <netinet/in_var.h> 75 #include <netinet/ip_var.h> 76 77 #include <netinet/igmp.h> 78 #include <netinet/igmp_var.h> 79 #include <netinet/ip_mroute.h> 80 81 /* Static forwards */ 82 static int ip_mrouter_init __P((struct socket *)); 83 static int add_vif __P((struct vifctl *)); 84 static int del_vif __P((vifi_t *vifip)); 85 static int add_lgrp __P((struct lgrplctl *)); 86 static int del_lgrp __P((struct lgrplctl *)); 87 static int grplst_member __P((struct vif *, struct in_addr)); 88 static u_long nethash __P((struct in_addr in)); 89 static int add_mrt __P((struct mrtctl *)); 90 static int del_mrt __P((struct in_addr *)); 91 static struct mrt *mrtfind __P((struct in_addr)); 92 static void phyint_send __P((struct mbuf *, struct vif *)); 93 static void tunnel_send __P((struct mbuf *, struct vif *)); 94 95 #define INSIZ sizeof(struct in_addr) 96 #define same(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0) 97 #define satosin(sa) ((struct sockaddr_in *)(sa)) 98 99 /* 100 * Globals. All but ip_mrouter and ip_mrtproto could be static, 101 * except for netstat or debugging purposes. 102 */ 103 struct socket *ip_mrouter = NULL; 104 int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ 105 106 struct mrt *mrttable[MRTHASHSIZ]; 107 struct vif viftable[MAXVIFS]; 108 struct mrtstat mrtstat; 109 110 /* 111 * Private variables. 112 */ 113 static vifi_t numvifs = 0; 114 static struct mrt *cached_mrt = NULL; 115 static u_long cached_origin; 116 static u_long cached_originmask; 117 118 /* 119 * Handle DVMRP setsockopt commands to modify the multicast routing tables. 120 */ 121 int 122 ip_mrouter_cmd(cmd, so, m) 123 register int cmd; 124 register struct socket *so; 125 register struct mbuf *m; 126 { 127 register int error = 0; 128 129 if (cmd != DVMRP_INIT && so != ip_mrouter) 130 error = EACCES; 131 else switch (cmd) { 132 133 case DVMRP_INIT: 134 error = ip_mrouter_init(so); 135 break; 136 137 case DVMRP_DONE: 138 error = ip_mrouter_done(); 139 break; 140 141 case DVMRP_ADD_VIF: 142 if (m == NULL || m->m_len < sizeof(struct vifctl)) 143 error = EINVAL; 144 else 145 error = add_vif(mtod(m, struct vifctl *)); 146 break; 147 148 case DVMRP_DEL_VIF: 149 if (m == NULL || m->m_len < sizeof(short)) 150 error = EINVAL; 151 else 152 error = del_vif(mtod(m, vifi_t *)); 153 break; 154 155 case DVMRP_ADD_LGRP: 156 if (m == NULL || m->m_len < sizeof(struct lgrplctl)) 157 error = EINVAL; 158 else 159 error = add_lgrp(mtod(m, struct lgrplctl *)); 160 break; 161 162 case DVMRP_DEL_LGRP: 163 if (m == NULL || m->m_len < sizeof(struct lgrplctl)) 164 error = EINVAL; 165 else 166 error = del_lgrp(mtod(m, struct lgrplctl *)); 167 break; 168 169 case DVMRP_ADD_MRT: 170 if (m == NULL || m->m_len < sizeof(struct mrtctl)) 171 error = EINVAL; 172 else 173 error = add_mrt(mtod(m, struct mrtctl *)); 174 break; 175 176 case DVMRP_DEL_MRT: 177 if (m == NULL || m->m_len < sizeof(struct in_addr)) 178 error = EINVAL; 179 else 180 error = del_mrt(mtod(m, struct in_addr *)); 181 break; 182 183 default: 184 error = EOPNOTSUPP; 185 break; 186 } 187 return (error); 188 } 189 190 /* 191 * Enable multicast routing 192 */ 193 static int 194 ip_mrouter_init(so) 195 register struct socket *so; 196 { 197 if (so->so_type != SOCK_RAW || 198 so->so_proto->pr_protocol != IPPROTO_IGMP) 199 return (EOPNOTSUPP); 200 201 if (ip_mrouter != NULL) 202 return (EADDRINUSE); 203 204 ip_mrouter = so; 205 206 return (0); 207 } 208 209 /* 210 * Disable multicast routing 211 */ 212 int 213 ip_mrouter_done() 214 { 215 register vifi_t vifi; 216 register int i; 217 register struct ifnet *ifp; 218 register int s; 219 struct ifreq ifr; 220 221 s = splnet(); 222 223 /* 224 * For each phyint in use, free its local group list and 225 * disable promiscuous reception of all IP multicasts. 226 */ 227 for (vifi = 0; vifi < numvifs; vifi++) { 228 if (viftable[vifi].v_lcl_addr.s_addr != 0 && 229 !(viftable[vifi].v_flags & VIFF_TUNNEL)) { 230 if (viftable[vifi].v_lcl_grps) 231 free(viftable[vifi].v_lcl_grps, M_MRTABLE); 232 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 233 satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY; 234 ifp = viftable[vifi].v_ifp; 235 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); 236 } 237 } 238 bzero((caddr_t)viftable, sizeof(viftable)); 239 numvifs = 0; 240 241 /* 242 * Free any multicast route entries. 243 */ 244 for (i = 0; i < MRTHASHSIZ; i++) 245 if (mrttable[i]) 246 free(mrttable[i], M_MRTABLE); 247 bzero((caddr_t)mrttable, sizeof(mrttable)); 248 cached_mrt = NULL; 249 250 ip_mrouter = NULL; 251 252 splx(s); 253 return (0); 254 } 255 256 /* 257 * Add a vif to the vif table 258 */ 259 static int 260 add_vif(vifcp) 261 register struct vifctl *vifcp; 262 { 263 register struct vif *vifp = viftable + vifcp->vifc_vifi; 264 register struct ifaddr *ifa; 265 register struct ifnet *ifp; 266 struct ifreq ifr; 267 register int error, s; 268 static struct sockaddr_in sin = { sizeof(sin), AF_INET }; 269 270 if (vifcp->vifc_vifi >= MAXVIFS) 271 return (EINVAL); 272 if (vifp->v_lcl_addr.s_addr != 0) 273 return (EADDRINUSE); 274 275 /* Find the interface with an address in AF_INET family */ 276 sin.sin_addr = vifcp->vifc_lcl_addr; 277 ifa = ifa_ifwithaddr((struct sockaddr *)&sin); 278 if (ifa == 0) 279 return (EADDRNOTAVAIL); 280 281 s = splnet(); 282 283 if (vifcp->vifc_flags & VIFF_TUNNEL) 284 vifp->v_rmt_addr = vifcp->vifc_rmt_addr; 285 else { 286 /* Make sure the interface supports multicast */ 287 ifp = ifa->ifa_ifp; 288 if ((ifp->if_flags & IFF_MULTICAST) == 0) { 289 splx(s); 290 return (EOPNOTSUPP); 291 } 292 /* 293 * Enable promiscuous reception of all IP multicasts 294 * from the interface. 295 */ 296 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 297 satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY; 298 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); 299 if (error) { 300 splx(s); 301 return (error); 302 } 303 } 304 305 vifp->v_flags = vifcp->vifc_flags; 306 vifp->v_threshold = vifcp->vifc_threshold; 307 vifp->v_lcl_addr = vifcp->vifc_lcl_addr; 308 vifp->v_ifp = ifa->ifa_ifp; 309 310 /* Adjust numvifs up if the vifi is higher than numvifs */ 311 if (numvifs <= vifcp->vifc_vifi) 312 numvifs = vifcp->vifc_vifi + 1; 313 314 splx(s); 315 return (0); 316 } 317 318 /* 319 * Delete a vif from the vif table 320 */ 321 static int 322 del_vif(vifip) 323 register vifi_t *vifip; 324 { 325 register struct vif *vifp = viftable + *vifip; 326 register struct ifnet *ifp; 327 register int i, s; 328 struct ifreq ifr; 329 330 if (*vifip >= numvifs) 331 return (EINVAL); 332 if (vifp->v_lcl_addr.s_addr == 0) 333 return (EADDRNOTAVAIL); 334 335 s = splnet(); 336 337 if (!(vifp->v_flags & VIFF_TUNNEL)) { 338 if (vifp->v_lcl_grps) 339 free(vifp->v_lcl_grps, M_MRTABLE); 340 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 341 satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY; 342 ifp = vifp->v_ifp; 343 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); 344 } 345 346 bzero((caddr_t)vifp, sizeof (*vifp)); 347 348 /* Adjust numvifs down */ 349 for (i = numvifs - 1; i >= 0; i--) 350 if (viftable[i].v_lcl_addr.s_addr != 0) 351 break; 352 numvifs = i + 1; 353 354 splx(s); 355 return (0); 356 } 357 358 /* 359 * Add the multicast group in the lgrpctl to the list of local multicast 360 * group memberships associated with the vif indexed by gcp->lgc_vifi. 361 */ 362 static int 363 add_lgrp(gcp) 364 register struct lgrplctl *gcp; 365 { 366 register struct vif *vifp; 367 register int s; 368 369 if (gcp->lgc_vifi >= numvifs) 370 return (EINVAL); 371 372 vifp = viftable + gcp->lgc_vifi; 373 if (vifp->v_lcl_addr.s_addr == 0 || (vifp->v_flags & VIFF_TUNNEL)) 374 return (EADDRNOTAVAIL); 375 376 /* If not enough space in existing list, allocate a larger one */ 377 s = splnet(); 378 if (vifp->v_lcl_grps_n + 1 >= vifp->v_lcl_grps_max) { 379 register int num; 380 register struct in_addr *ip; 381 382 num = vifp->v_lcl_grps_max; 383 if (num <= 0) 384 num = 32; /* initial number */ 385 else 386 num += num; /* double last number */ 387 ip = (struct in_addr *)malloc(num * sizeof(*ip), 388 M_MRTABLE, M_NOWAIT); 389 if (ip == NULL) { 390 splx(s); 391 return (ENOBUFS); 392 } 393 394 bzero((caddr_t)ip, num * sizeof(*ip)); /* XXX paranoid */ 395 bcopy((caddr_t)vifp->v_lcl_grps, (caddr_t)ip, 396 vifp->v_lcl_grps_n * sizeof(*ip)); 397 398 vifp->v_lcl_grps_max = num; 399 if (vifp->v_lcl_grps) 400 free(vifp->v_lcl_grps, M_MRTABLE); 401 vifp->v_lcl_grps = ip; 402 403 splx(s); 404 } 405 406 vifp->v_lcl_grps[vifp->v_lcl_grps_n++] = gcp->lgc_gaddr; 407 408 if (gcp->lgc_gaddr.s_addr == vifp->v_cached_group) 409 vifp->v_cached_result = 1; 410 411 splx(s); 412 return (0); 413 } 414 415 /* 416 * Delete the the local multicast group associated with the vif 417 * indexed by gcp->lgc_vifi. 418 */ 419 420 static int 421 del_lgrp(gcp) 422 register struct lgrplctl *gcp; 423 { 424 register struct vif *vifp; 425 register int i, error, s; 426 427 if (gcp->lgc_vifi >= numvifs) 428 return (EINVAL); 429 vifp = viftable + gcp->lgc_vifi; 430 if (vifp->v_lcl_addr.s_addr == 0 || (vifp->v_flags & VIFF_TUNNEL)) 431 return (EADDRNOTAVAIL); 432 433 s = splnet(); 434 435 if (gcp->lgc_gaddr.s_addr == vifp->v_cached_group) 436 vifp->v_cached_result = 0; 437 438 error = EADDRNOTAVAIL; 439 for (i = 0; i < vifp->v_lcl_grps_n; ++i) 440 if (same(&gcp->lgc_gaddr, &vifp->v_lcl_grps[i])) { 441 error = 0; 442 vifp->v_lcl_grps_n--; 443 bcopy((caddr_t)&vifp->v_lcl_grps[i + 1], 444 (caddr_t)&vifp->v_lcl_grps[i], 445 (vifp->v_lcl_grps_n - i) * sizeof(struct in_addr)); 446 error = 0; 447 break; 448 } 449 450 splx(s); 451 return (error); 452 } 453 454 /* 455 * Return 1 if gaddr is a member of the local group list for vifp. 456 */ 457 static int 458 grplst_member(vifp, gaddr) 459 register struct vif *vifp; 460 struct in_addr gaddr; 461 { 462 register int i, s; 463 register u_long addr; 464 465 mrtstat.mrts_grp_lookups++; 466 467 addr = gaddr.s_addr; 468 if (addr == vifp->v_cached_group) 469 return (vifp->v_cached_result); 470 471 mrtstat.mrts_grp_misses++; 472 473 for (i = 0; i < vifp->v_lcl_grps_n; ++i) 474 if (addr == vifp->v_lcl_grps[i].s_addr) { 475 s = splnet(); 476 vifp->v_cached_group = addr; 477 vifp->v_cached_result = 1; 478 splx(s); 479 return (1); 480 } 481 s = splnet(); 482 vifp->v_cached_group = addr; 483 vifp->v_cached_result = 0; 484 splx(s); 485 return (0); 486 } 487 488 /* 489 * A simple hash function: returns MRTHASHMOD of the low-order octet of 490 * the argument's network or subnet number. 491 */ 492 static u_long 493 nethash(in) 494 struct in_addr in; 495 { 496 register u_long n; 497 498 n = in_netof(in); 499 while ((n & 0xff) == 0) 500 n >>= 8; 501 return (MRTHASHMOD(n)); 502 } 503 504 /* 505 * Add an mrt entry 506 */ 507 static int 508 add_mrt(mrtcp) 509 register struct mrtctl *mrtcp; 510 { 511 struct mrt *rt; 512 u_long hash; 513 int s; 514 515 if (rt = mrtfind(mrtcp->mrtc_origin)) { 516 /* Just update the route */ 517 s = splnet(); 518 rt->mrt_parent = mrtcp->mrtc_parent; 519 VIFM_COPY(mrtcp->mrtc_children, rt->mrt_children); 520 VIFM_COPY(mrtcp->mrtc_leaves, rt->mrt_leaves); 521 splx(s); 522 return (0); 523 } 524 525 s = splnet(); 526 527 rt = (struct mrt *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT); 528 if (rt == NULL) { 529 splx(s); 530 return (ENOBUFS); 531 } 532 533 /* 534 * insert new entry at head of hash chain 535 */ 536 rt->mrt_origin = mrtcp->mrtc_origin; 537 rt->mrt_originmask = mrtcp->mrtc_originmask; 538 rt->mrt_parent = mrtcp->mrtc_parent; 539 VIFM_COPY(mrtcp->mrtc_children, rt->mrt_children); 540 VIFM_COPY(mrtcp->mrtc_leaves, rt->mrt_leaves); 541 /* link into table */ 542 hash = nethash(mrtcp->mrtc_origin); 543 rt->mrt_next = mrttable[hash]; 544 mrttable[hash] = rt; 545 546 splx(s); 547 return (0); 548 } 549 550 /* 551 * Delete an mrt entry 552 */ 553 static int 554 del_mrt(origin) 555 register struct in_addr *origin; 556 { 557 register struct mrt *rt, *prev_rt; 558 register u_long hash = nethash(*origin); 559 register int s; 560 561 for (prev_rt = rt = mrttable[hash]; rt; prev_rt = rt, rt = rt->mrt_next) 562 if (origin->s_addr == rt->mrt_origin.s_addr) 563 break; 564 if (!rt) 565 return (ESRCH); 566 567 s = splnet(); 568 569 if (rt == cached_mrt) 570 cached_mrt = NULL; 571 572 if (prev_rt == rt) 573 mrttable[hash] = rt->mrt_next; 574 else 575 prev_rt->mrt_next = rt->mrt_next; 576 free(rt, M_MRTABLE); 577 578 splx(s); 579 return (0); 580 } 581 582 /* 583 * Find a route for a given origin IP address. 584 */ 585 static struct mrt * 586 mrtfind(origin) 587 struct in_addr origin; 588 { 589 register struct mrt *rt; 590 register u_int hash; 591 register int s; 592 593 mrtstat.mrts_mrt_lookups++; 594 595 if (cached_mrt != NULL && 596 (origin.s_addr & cached_originmask) == cached_origin) 597 return (cached_mrt); 598 599 mrtstat.mrts_mrt_misses++; 600 601 hash = nethash(origin); 602 for (rt = mrttable[hash]; rt; rt = rt->mrt_next) 603 if ((origin.s_addr & rt->mrt_originmask.s_addr) == 604 rt->mrt_origin.s_addr) { 605 s = splnet(); 606 cached_mrt = rt; 607 cached_origin = rt->mrt_origin.s_addr; 608 cached_originmask = rt->mrt_originmask.s_addr; 609 splx(s); 610 return (rt); 611 } 612 return (NULL); 613 } 614 615 /* 616 * IP multicast forwarding function. This function assumes that the packet 617 * pointed to by "ip" has arrived on (or is about to be sent to) the interface 618 * pointed to by "ifp", and the packet is to be relayed to other networks 619 * that have members of the packet's destination IP multicast group. 620 * 621 * The packet is returned unscathed to the caller, unless it is tunneled 622 * or erroneous, in which case a non-zero return value tells the caller to 623 * discard it. 624 */ 625 626 #define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ 627 #define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ 628 629 int 630 ip_mforward(m, ifp) 631 register struct mbuf *m; 632 register struct ifnet *ifp; 633 { 634 register struct ip *ip = mtod(m, struct ip *); 635 register struct mrt *rt; 636 register struct vif *vifp; 637 register int vifi; 638 register u_char *ipoptions; 639 u_long tunnel_src; 640 641 if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || 642 (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { 643 /* 644 * Packet arrived via a physical interface. 645 */ 646 tunnel_src = 0; 647 } else { 648 /* 649 * Packet arrived through a tunnel. 650 * 651 * A tunneled packet has a single NOP option and a 652 * two-element loose-source-and-record-route (LSRR) 653 * option immediately following the fixed-size part of 654 * the IP header. At this point in processing, the IP 655 * header should contain the following IP addresses: 656 * 657 * original source - in the source address field 658 * destination group - in the destination address field 659 * remote tunnel end-point - in the first element of LSRR 660 * one of this host's addrs - in the second element of LSRR 661 * 662 * NOTE: RFC-1075 would have the original source and 663 * remote tunnel end-point addresses swapped. However, 664 * that could cause delivery of ICMP error messages to 665 * innocent applications on intermediate routing 666 * hosts! Therefore, we hereby change the spec. 667 */ 668 669 /* 670 * Verify that the tunnel options are well-formed. 671 */ 672 if (ipoptions[0] != IPOPT_NOP || 673 ipoptions[2] != 11 || /* LSRR option length */ 674 ipoptions[3] != 12 || /* LSRR address pointer */ 675 (tunnel_src = *(u_long *)(&ipoptions[4])) == 0) { 676 mrtstat.mrts_bad_tunnel++; 677 return (1); 678 } 679 680 /* 681 * Delete the tunnel options from the packet. 682 */ 683 ovbcopy((caddr_t)(ipoptions + TUNNEL_LEN), (caddr_t)ipoptions, 684 (unsigned)(m->m_len - (IP_HDR_LEN + TUNNEL_LEN))); 685 m->m_len -= TUNNEL_LEN; 686 ip->ip_len -= TUNNEL_LEN; 687 ip->ip_hl -= TUNNEL_LEN >> 2; 688 } 689 690 /* 691 * Don't forward a packet with time-to-live of zero or one, 692 * or a packet destined to a local-only group. 693 */ 694 if (ip->ip_ttl <= 1 || 695 ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) 696 return ((int)tunnel_src); 697 698 /* 699 * Don't forward if we don't have a route for the packet's origin. 700 */ 701 if (!(rt = mrtfind(ip->ip_src))) { 702 mrtstat.mrts_no_route++; 703 return ((int)tunnel_src); 704 } 705 706 /* 707 * Don't forward if it didn't arrive from the parent vif for its origin. 708 */ 709 vifi = rt->mrt_parent; 710 if (tunnel_src == 0 ) { 711 if ((viftable[vifi].v_flags & VIFF_TUNNEL) || 712 viftable[vifi].v_ifp != ifp ) 713 return ((int)tunnel_src); 714 } else { 715 if (!(viftable[vifi].v_flags & VIFF_TUNNEL) || 716 viftable[vifi].v_rmt_addr.s_addr != tunnel_src ) 717 return ((int)tunnel_src); 718 } 719 720 /* 721 * For each vif, decide if a copy of the packet should be forwarded. 722 * Forward if: 723 * - the ttl exceeds the vif's threshold AND 724 * - the vif is a child in the origin's route AND 725 * - ( the vif is not a leaf in the origin's route OR 726 * the destination group has members on the vif ) 727 * 728 * (This might be speeded up with some sort of cache -- someday.) 729 */ 730 for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) { 731 if (ip->ip_ttl > vifp->v_threshold && 732 VIFM_ISSET(vifi, rt->mrt_children) && 733 (!VIFM_ISSET(vifi, rt->mrt_leaves) || 734 grplst_member(vifp, ip->ip_dst))) { 735 if (vifp->v_flags & VIFF_TUNNEL) 736 tunnel_send(m, vifp); 737 else 738 phyint_send(m, vifp); 739 } 740 } 741 742 return ((int)tunnel_src); 743 } 744 745 static void 746 phyint_send(m, vifp) 747 register struct mbuf *m; 748 register struct vif *vifp; 749 { 750 register struct ip *ip = mtod(m, struct ip *); 751 register struct mbuf *mb_copy; 752 register struct ip_moptions *imo; 753 register int error; 754 struct ip_moptions simo; 755 756 mb_copy = m_copy(m, 0, M_COPYALL); 757 if (mb_copy == NULL) 758 return; 759 760 imo = &simo; 761 imo->imo_multicast_ifp = vifp->v_ifp; 762 imo->imo_multicast_ttl = ip->ip_ttl - 1; 763 imo->imo_multicast_loop = 1; 764 765 error = ip_output(mb_copy, NULL, NULL, IP_FORWARDING, imo); 766 } 767 768 static void 769 tunnel_send(m, vifp) 770 register struct mbuf *m; 771 register struct vif *vifp; 772 { 773 register struct ip *ip = mtod(m, struct ip *); 774 register struct mbuf *mb_copy, *mb_opts; 775 register struct ip *ip_copy; 776 register int error; 777 register u_char *cp; 778 779 /* 780 * Make sure that adding the tunnel options won't exceed the 781 * maximum allowed number of option bytes. 782 */ 783 if (ip->ip_hl > (60 - TUNNEL_LEN) >> 2) { 784 mrtstat.mrts_cant_tunnel++; 785 return; 786 } 787 788 /* 789 * Get a private copy of the IP header so that changes to some 790 * of the IP fields don't damage the original header, which is 791 * examined later in ip_input.c. 792 */ 793 mb_copy = m_copy(m, IP_HDR_LEN, M_COPYALL); 794 if (mb_copy == NULL) 795 return; 796 MGETHDR(mb_opts, M_DONTWAIT, MT_HEADER); 797 if (mb_opts == NULL) { 798 m_freem(mb_copy); 799 return; 800 } 801 /* 802 * Make mb_opts be the new head of the packet chain. 803 * Any options of the packet were left in the old packet chain head 804 */ 805 mb_opts->m_next = mb_copy; 806 mb_opts->m_len = IP_HDR_LEN + TUNNEL_LEN; 807 mb_opts->m_data += MSIZE - mb_opts->m_len; 808 809 ip_copy = mtod(mb_opts, struct ip *); 810 /* 811 * Copy the base ip header to the new head mbuf. 812 */ 813 *ip_copy = *ip; 814 ip_copy->ip_ttl--; 815 ip_copy->ip_dst = vifp->v_rmt_addr; /* remote tunnel end-point */ 816 /* 817 * Adjust the ip header length to account for the tunnel options. 818 */ 819 ip_copy->ip_hl += TUNNEL_LEN >> 2; 820 ip_copy->ip_len += TUNNEL_LEN; 821 /* 822 * Add the NOP and LSRR after the base ip header 823 */ 824 cp = (u_char *)(ip_copy + 1); 825 *cp++ = IPOPT_NOP; 826 *cp++ = IPOPT_LSRR; 827 *cp++ = 11; /* LSRR option length */ 828 *cp++ = 8; /* LSSR pointer to second element */ 829 *(u_long*)cp = vifp->v_lcl_addr.s_addr; /* local tunnel end-point */ 830 cp += 4; 831 *(u_long*)cp = ip->ip_dst.s_addr; /* destination group */ 832 833 error = ip_output(mb_opts, NULL, NULL, IP_FORWARDING, NULL); 834 } 835 #endif 836