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