|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * IP multicast forwarding procedures ! 24: * ! 25: * Written by David Waitzman, BBN Labs, August 1988. ! 26: * Modified by Steve Deering, Stanford, February 1989. ! 27: * Modified by Mark J. Steiglitz, Stanford, May, 1991 ! 28: * Modified by Van Jacobson, LBL, January 1993 ! 29: * Modified by Ajit Thyagarajan, PARC, August 1993 ! 30: * Modified by Bill Fenner, PARC, April 1995 ! 31: * ! 32: * MROUTING Revision: 3.5 ! 33: */ ! 34: ! 35: #if ISFB31 ! 36: #include "opt_mrouting.h" ! 37: #else ! 38: #define MROUTE_LKM 0 ! 39: #endif ! 40: ! 41: #include <sys/param.h> ! 42: #include <sys/systm.h> ! 43: #include <sys/malloc.h> ! 44: #include <sys/mbuf.h> ! 45: #include <sys/socket.h> ! 46: #include <sys/socketvar.h> ! 47: #include <sys/protosw.h> ! 48: #include <sys/time.h> ! 49: #include <sys/kernel.h> ! 50: #include <sys/sockio.h> ! 51: #include <sys/syslog.h> ! 52: #include <net/if.h> ! 53: #include <net/route.h> ! 54: #include <netinet/in.h> ! 55: #include <netinet/in_systm.h> ! 56: #include <netinet/ip.h> ! 57: #include <netinet/ip_var.h> ! 58: #include <netinet/in_var.h> ! 59: #include <netinet/igmp.h> ! 60: #include <netinet/ip_mroute.h> ! 61: #include <netinet/udp.h> ! 62: ! 63: #if !MROUTING ! 64: extern u_long _ip_mcast_src __P((int vifi)); ! 65: extern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp, ! 66: struct mbuf *m, struct ip_moptions *imo)); ! 67: extern int _ip_mrouter_done __P((void)); ! 68: extern int _ip_mrouter_get __P((struct socket *so, struct sockopt *sopt)); ! 69: extern int _ip_mrouter_set __P((struct socket *so, struct sockopt *sopt)); ! 70: extern int _mrt_ioctl __P((int req, caddr_t data, struct proc *p)); ! 71: ! 72: /* ! 73: * Dummy routines and globals used when multicast routing is not compiled in. ! 74: */ ! 75: ! 76: struct socket *ip_mrouter = NULL; ! 77: u_int rsvpdebug = 0; ! 78: ! 79: int ! 80: _ip_mrouter_set(so, sopt) ! 81: struct socket *so; ! 82: struct sockopt *sopt; ! 83: { ! 84: return(EOPNOTSUPP); ! 85: } ! 86: ! 87: int (*ip_mrouter_set)(struct socket *, struct sockopt *) = _ip_mrouter_set; ! 88: ! 89: ! 90: int ! 91: _ip_mrouter_get(so, sopt) ! 92: struct socket *so; ! 93: struct sockopt *sopt; ! 94: { ! 95: return(EOPNOTSUPP); ! 96: } ! 97: ! 98: int (*ip_mrouter_get)(struct socket *, struct sockopt *) = _ip_mrouter_get; ! 99: ! 100: int ! 101: _ip_mrouter_done() ! 102: { ! 103: return(0); ! 104: } ! 105: ! 106: int (*ip_mrouter_done)(void) = _ip_mrouter_done; ! 107: ! 108: int ! 109: _ip_mforward(ip, ifp, m, imo) ! 110: struct ip *ip; ! 111: struct ifnet *ifp; ! 112: struct mbuf *m; ! 113: struct ip_moptions *imo; ! 114: { ! 115: return(0); ! 116: } ! 117: ! 118: int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, ! 119: struct ip_moptions *) = _ip_mforward; ! 120: ! 121: int ! 122: _mrt_ioctl(int req, caddr_t data, struct proc *p) ! 123: { ! 124: return EOPNOTSUPP; ! 125: } ! 126: ! 127: int (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl; ! 128: ! 129: void ! 130: rsvp_input(m, iphlen) /* XXX must fixup manually */ ! 131: struct mbuf *m; ! 132: int iphlen; ! 133: { ! 134: /* Can still get packets with rsvp_on = 0 if there is a local member ! 135: * of the group to which the RSVP packet is addressed. But in this ! 136: * case we want to throw the packet away. ! 137: */ ! 138: if (!rsvp_on) { ! 139: m_freem(m); ! 140: return; ! 141: } ! 142: ! 143: if (ip_rsvpd != NULL) { ! 144: if (rsvpdebug) ! 145: printf("rsvp_input: Sending packet up old-style socket\n"); ! 146: rip_input(m, iphlen); ! 147: return; ! 148: } ! 149: /* Drop the packet */ ! 150: m_freem(m); ! 151: } ! 152: ! 153: void ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */ ! 154: rip_input(m, iphlen); ! 155: } ! 156: ! 157: int (*legal_vif_num)(int) = 0; ! 158: ! 159: /* ! 160: * This should never be called, since IP_MULTICAST_VIF should fail, but ! 161: * just in case it does get called, the code a little lower in ip_output ! 162: * will assign the packet a local address. ! 163: */ ! 164: u_long ! 165: _ip_mcast_src(int vifi) { return INADDR_ANY; } ! 166: u_long (*ip_mcast_src)(int) = _ip_mcast_src; ! 167: ! 168: int ! 169: ip_rsvp_vif_init(so, sopt) ! 170: struct socket *so; ! 171: struct sockopt *sopt; ! 172: { ! 173: return(EINVAL); ! 174: } ! 175: ! 176: int ! 177: ip_rsvp_vif_done(so, sopt) ! 178: struct socket *so; ! 179: struct sockopt *sopt; ! 180: { ! 181: return(EINVAL); ! 182: } ! 183: ! 184: void ! 185: ip_rsvp_force_done(so) ! 186: struct socket *so; ! 187: { ! 188: return; ! 189: } ! 190: ! 191: #else /* MROUTING */ ! 192: ! 193: #define M_HASCL(m) ((m)->m_flags & M_EXT) ! 194: ! 195: #define INSIZ sizeof(struct in_addr) ! 196: #define same(a1, a2) \ ! 197: (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0) ! 198: ! 199: static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables"); ! 200: ! 201: /* ! 202: * Globals. All but ip_mrouter and ip_mrtproto could be static, ! 203: * except for netstat or debugging purposes. ! 204: */ ! 205: #if !MROUTE_LKM ! 206: struct socket *ip_mrouter = NULL; ! 207: static struct mrtstat mrtstat; ! 208: #else /* MROUTE_LKM */ ! 209: extern void X_ipip_input __P((struct mbuf *m, int iphlen)); ! 210: extern struct mrtstat mrtstat; ! 211: static int ip_mrtproto; ! 212: #endif ! 213: ! 214: #define NO_RTE_FOUND 0x1 ! 215: #define RTE_FOUND 0x2 ! 216: ! 217: static struct mfc *mfctable[MFCTBLSIZ]; ! 218: static u_char nexpire[MFCTBLSIZ]; ! 219: static struct vif viftable[MAXVIFS]; ! 220: static u_int mrtdebug = 0; /* debug level */ ! 221: #define DEBUG_MFC 0x02 ! 222: #define DEBUG_FORWARD 0x04 ! 223: #define DEBUG_EXPIRE 0x08 ! 224: #define DEBUG_XMIT 0x10 ! 225: static u_int tbfdebug = 0; /* tbf debug level */ ! 226: static u_int rsvpdebug = 0; /* rsvp debug level */ ! 227: ! 228: ! 229: ! 230: #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ ! 231: #define UPCALL_EXPIRE 6 /* number of timeouts */ ! 232: ! 233: /* ! 234: * Define the token bucket filter structures ! 235: * tbftable -> each vif has one of these for storing info ! 236: */ ! 237: ! 238: static struct tbf tbftable[MAXVIFS]; ! 239: #define TBF_REPROCESS (hz / 100) /* 100x / second */ ! 240: ! 241: /* ! 242: * 'Interfaces' associated with decapsulator (so we can tell ! 243: * packets that went through it from ones that get reflected ! 244: * by a broken gateway). These interfaces are never linked into ! 245: * the system ifnet list & no routes point to them. I.e., packets ! 246: * can't be sent this way. They only exist as a placeholder for ! 247: * multicast source verification. ! 248: */ ! 249: static struct ifnet multicast_decap_if[MAXVIFS]; ! 250: ! 251: #define ENCAP_TTL 64 ! 252: #define ENCAP_PROTO IPPROTO_IPIP /* 4 */ ! 253: ! 254: /* prototype IP hdr for encapsulated packets */ ! 255: static struct ip multicast_encap_iphdr = { ! 256: #if BYTE_ORDER == LITTLE_ENDIAN ! 257: sizeof(struct ip) >> 2, IPVERSION, ! 258: #else ! 259: IPVERSION, sizeof(struct ip) >> 2, ! 260: #endif ! 261: 0, /* tos */ ! 262: sizeof(struct ip), /* total length */ ! 263: 0, /* id */ ! 264: 0, /* frag offset */ ! 265: ENCAP_TTL, ENCAP_PROTO, ! 266: 0, /* checksum */ ! 267: }; ! 268: ! 269: /* ! 270: * Private variables. ! 271: */ ! 272: static vifi_t numvifs = 0; ! 273: static int have_encap_tunnel = 0; ! 274: ! 275: /* ! 276: * one-back cache used by ipip_input to locate a tunnel's vif ! 277: * given a datagram's src ip address. ! 278: */ ! 279: static u_long last_encap_src; ! 280: static struct vif *last_encap_vif; ! 281: ! 282: static u_long X_ip_mcast_src __P((int vifi)); ! 283: static int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo)); ! 284: static int X_ip_mrouter_done __P((void)); ! 285: static int X_ip_mrouter_get __P((struct socket *so, struct sockopt *m)); ! 286: static int X_ip_mrouter_set __P((struct socket *so, struct sockopt *m)); ! 287: static int X_legal_vif_num __P((int vif)); ! 288: static int X_mrt_ioctl __P((int cmd, caddr_t data)); ! 289: ! 290: static int get_sg_cnt(struct sioc_sg_req *); ! 291: static int get_vif_cnt(struct sioc_vif_req *); ! 292: static int ip_mrouter_init(struct socket *, int); ! 293: static int add_vif(struct vifctl *); ! 294: static int del_vif(vifi_t); ! 295: static int add_mfc(struct mfcctl *); ! 296: static int del_mfc(struct mfcctl *); ! 297: static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); ! 298: static int set_assert(int); ! 299: static void expire_upcalls(void *); ! 300: static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, ! 301: vifi_t); ! 302: static void phyint_send(struct ip *, struct vif *, struct mbuf *); ! 303: static void encap_send(struct ip *, struct vif *, struct mbuf *); ! 304: static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long); ! 305: static void tbf_queue(struct vif *, struct mbuf *); ! 306: static void tbf_process_q(struct vif *); ! 307: static void tbf_reprocess_q(void *); ! 308: static int tbf_dq_sel(struct vif *, struct ip *); ! 309: static void tbf_send_packet(struct vif *, struct mbuf *); ! 310: static void tbf_update_tokens(struct vif *); ! 311: static int priority(struct vif *, struct ip *); ! 312: void multiencap_decap(struct mbuf *); ! 313: ! 314: /* ! 315: * whether or not special PIM assert processing is enabled. ! 316: */ ! 317: static int pim_assert; ! 318: /* ! 319: * Rate limit for assert notification messages, in usec ! 320: */ ! 321: #define ASSERT_MSG_TIME 3000000 ! 322: ! 323: /* ! 324: * Hash function for a source, group entry ! 325: */ ! 326: #define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \ ! 327: ((g) >> 20) ^ ((g) >> 10) ^ (g)) ! 328: ! 329: /* ! 330: * Find a route for a given origin IP address and Multicast group address ! 331: * Type of service parameter to be added in the future!!! ! 332: */ ! 333: ! 334: #define MFCFIND(o, g, rt) { \ ! 335: register struct mfc *_rt = mfctable[MFCHASH(o,g)]; \ ! 336: rt = NULL; \ ! 337: ++mrtstat.mrts_mfc_lookups; \ ! 338: while (_rt) { \ ! 339: if ((_rt->mfc_origin.s_addr == o) && \ ! 340: (_rt->mfc_mcastgrp.s_addr == g) && \ ! 341: (_rt->mfc_stall == NULL)) { \ ! 342: rt = _rt; \ ! 343: break; \ ! 344: } \ ! 345: _rt = _rt->mfc_next; \ ! 346: } \ ! 347: if (rt == NULL) { \ ! 348: ++mrtstat.mrts_mfc_misses; \ ! 349: } \ ! 350: } ! 351: ! 352: ! 353: /* ! 354: * Macros to compute elapsed time efficiently ! 355: * Borrowed from Van Jacobson's scheduling code ! 356: */ ! 357: #define TV_DELTA(a, b, delta) { \ ! 358: register int xxs; \ ! 359: \ ! 360: delta = (a).tv_usec - (b).tv_usec; \ ! 361: if ((xxs = (a).tv_sec - (b).tv_sec)) { \ ! 362: switch (xxs) { \ ! 363: case 2: \ ! 364: delta += 1000000; \ ! 365: /* fall through */ \ ! 366: case 1: \ ! 367: delta += 1000000; \ ! 368: break; \ ! 369: default: \ ! 370: delta += (1000000 * xxs); \ ! 371: } \ ! 372: } \ ! 373: } ! 374: ! 375: #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ ! 376: (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec) ! 377: ! 378: #if UPCALL_TIMING ! 379: u_long upcall_data[51]; ! 380: static void collate(struct timeval *); ! 381: #endif /* UPCALL_TIMING */ ! 382: ! 383: ! 384: /* ! 385: * Handle MRT setsockopt commands to modify the multicast routing tables. ! 386: */ ! 387: static int ! 388: X_ip_mrouter_set(so, sopt) ! 389: struct socket *so; ! 390: struct sockopt *sopt; ! 391: { ! 392: int error, optval; ! 393: vifi_t vifi; ! 394: struct vifctl vifc; ! 395: struct mfcctl mfc; ! 396: ! 397: if (so != ip_mrouter && sopt->sopt_name != MRT_INIT) ! 398: return (EPERM); ! 399: ! 400: error = 0; ! 401: switch (sopt->sopt_name) { ! 402: case MRT_INIT: ! 403: error = sooptcopyin(sopt, &optval, sizeof optval, ! 404: sizeof optval); ! 405: if (error) ! 406: break; ! 407: error = ip_mrouter_init(so, optval); ! 408: break; ! 409: ! 410: case MRT_DONE: ! 411: error = ip_mrouter_done(); ! 412: break; ! 413: ! 414: case MRT_ADD_VIF: ! 415: error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc); ! 416: if (error) ! 417: break; ! 418: error = add_vif(&vifc); ! 419: break; ! 420: ! 421: case MRT_DEL_VIF: ! 422: error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi); ! 423: if (error) ! 424: break; ! 425: error = del_vif(vifi); ! 426: break; ! 427: ! 428: case MRT_ADD_MFC: ! 429: case MRT_DEL_MFC: ! 430: error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc); ! 431: if (error) ! 432: break; ! 433: if (sopt->sopt_name == MRT_ADD_MFC) ! 434: error = add_mfc(&mfc); ! 435: else ! 436: error = del_mfc(&mfc); ! 437: break; ! 438: ! 439: case MRT_ASSERT: ! 440: error = sooptcopyin(sopt, &optval, sizeof optval, ! 441: sizeof optval); ! 442: if (error) ! 443: break; ! 444: set_assert(optval); ! 445: break; ! 446: ! 447: default: ! 448: error = EOPNOTSUPP; ! 449: break; ! 450: } ! 451: return (error); ! 452: } ! 453: ! 454: #if !MROUTE_LKM ! 455: int (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set; ! 456: #endif ! 457: ! 458: /* ! 459: * Handle MRT getsockopt commands ! 460: */ ! 461: static int ! 462: X_ip_mrouter_get(so, sopt) ! 463: struct socket *so; ! 464: struct sockopt *sopt; ! 465: { ! 466: int error; ! 467: static int version = 0x0305; /* !!! why is this here? XXX */ ! 468: ! 469: switch (sopt->sopt_name) { ! 470: case MRT_VERSION: ! 471: error = sooptcopyout(sopt, &version, sizeof version); ! 472: break; ! 473: ! 474: case MRT_ASSERT: ! 475: error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert); ! 476: break; ! 477: default: ! 478: error = EOPNOTSUPP; ! 479: break; ! 480: } ! 481: return (error); ! 482: } ! 483: ! 484: #if !MROUTE_LKM ! 485: int (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get; ! 486: #endif ! 487: ! 488: /* ! 489: * Handle ioctl commands to obtain information from the cache ! 490: */ ! 491: static int ! 492: X_mrt_ioctl(cmd, data) ! 493: int cmd; ! 494: caddr_t data; ! 495: { ! 496: int error = 0; ! 497: ! 498: switch (cmd) { ! 499: case (SIOCGETVIFCNT): ! 500: return (get_vif_cnt((struct sioc_vif_req *)data)); ! 501: break; ! 502: case (SIOCGETSGCNT): ! 503: return (get_sg_cnt((struct sioc_sg_req *)data)); ! 504: break; ! 505: default: ! 506: return (EINVAL); ! 507: break; ! 508: } ! 509: return error; ! 510: } ! 511: ! 512: #if !MROUTE_LKM ! 513: int (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl; ! 514: #endif ! 515: ! 516: /* ! 517: * returns the packet, byte, rpf-failure count for the source group provided ! 518: */ ! 519: static int ! 520: get_sg_cnt(req) ! 521: register struct sioc_sg_req *req; ! 522: { ! 523: register struct mfc *rt; ! 524: int s; ! 525: ! 526: s = splnet(); ! 527: MFCFIND(req->src.s_addr, req->grp.s_addr, rt); ! 528: splx(s); ! 529: if (rt != NULL) { ! 530: req->pktcnt = rt->mfc_pkt_cnt; ! 531: req->bytecnt = rt->mfc_byte_cnt; ! 532: req->wrong_if = rt->mfc_wrong_if; ! 533: } else ! 534: req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; ! 535: ! 536: return 0; ! 537: } ! 538: ! 539: /* ! 540: * returns the input and output packet and byte counts on the vif provided ! 541: */ ! 542: static int ! 543: get_vif_cnt(req) ! 544: register struct sioc_vif_req *req; ! 545: { ! 546: register vifi_t vifi = req->vifi; ! 547: ! 548: if (vifi >= numvifs) return EINVAL; ! 549: ! 550: req->icount = viftable[vifi].v_pkt_in; ! 551: req->ocount = viftable[vifi].v_pkt_out; ! 552: req->ibytes = viftable[vifi].v_bytes_in; ! 553: req->obytes = viftable[vifi].v_bytes_out; ! 554: ! 555: return 0; ! 556: } ! 557: ! 558: /* ! 559: * Enable multicast routing ! 560: */ ! 561: static int ! 562: ip_mrouter_init(so, version) ! 563: struct socket *so; ! 564: int version; ! 565: { ! 566: if (mrtdebug) ! 567: log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n", ! 568: so->so_type, so->so_proto->pr_protocol); ! 569: ! 570: if (so->so_type != SOCK_RAW || ! 571: so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP; ! 572: ! 573: if (version != 1) ! 574: return ENOPROTOOPT; ! 575: ! 576: if (ip_mrouter != NULL) return EADDRINUSE; ! 577: ! 578: ip_mrouter = so; ! 579: ! 580: bzero((caddr_t)mfctable, sizeof(mfctable)); ! 581: bzero((caddr_t)nexpire, sizeof(nexpire)); ! 582: ! 583: pim_assert = 0; ! 584: ! 585: timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); ! 586: ! 587: if (mrtdebug) ! 588: log(LOG_DEBUG, "ip_mrouter_init\n"); ! 589: ! 590: return 0; ! 591: } ! 592: ! 593: /* ! 594: * Disable multicast routing ! 595: */ ! 596: static int ! 597: X_ip_mrouter_done() ! 598: { ! 599: vifi_t vifi; ! 600: int i; ! 601: struct ifnet *ifp; ! 602: struct ifreq ifr; ! 603: struct mfc *rt; ! 604: struct rtdetq *rte; ! 605: int s; ! 606: ! 607: s = splnet(); ! 608: ! 609: /* ! 610: * For each phyint in use, disable promiscuous reception of all IP ! 611: * multicasts. ! 612: */ ! 613: for (vifi = 0; vifi < numvifs; vifi++) { ! 614: if (viftable[vifi].v_lcl_addr.s_addr != 0 && ! 615: !(viftable[vifi].v_flags & VIFF_TUNNEL)) { ! 616: ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ! 617: ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr ! 618: = INADDR_ANY; ! 619: ifp = viftable[vifi].v_ifp; ! 620: if_allmulti(ifp, 0); ! 621: } ! 622: } ! 623: bzero((caddr_t)tbftable, sizeof(tbftable)); ! 624: bzero((caddr_t)viftable, sizeof(viftable)); ! 625: numvifs = 0; ! 626: pim_assert = 0; ! 627: ! 628: untimeout(expire_upcalls, (caddr_t)NULL); ! 629: ! 630: /* ! 631: * Free all multicast forwarding cache entries. ! 632: */ ! 633: for (i = 0; i < MFCTBLSIZ; i++) { ! 634: for (rt = mfctable[i]; rt != NULL; ) { ! 635: struct mfc *nr = rt->mfc_next; ! 636: ! 637: for (rte = rt->mfc_stall; rte != NULL; ) { ! 638: struct rtdetq *n = rte->next; ! 639: ! 640: m_freem(rte->m); ! 641: FREE(rte, M_MRTABLE); ! 642: rte = n; ! 643: } ! 644: FREE(rt, M_MRTABLE); ! 645: rt = nr; ! 646: } ! 647: } ! 648: ! 649: bzero((caddr_t)mfctable, sizeof(mfctable)); ! 650: ! 651: /* ! 652: * Reset de-encapsulation cache ! 653: */ ! 654: last_encap_src = 0; ! 655: last_encap_vif = NULL; ! 656: have_encap_tunnel = 0; ! 657: ! 658: ip_mrouter = NULL; ! 659: ! 660: splx(s); ! 661: ! 662: if (mrtdebug) ! 663: log(LOG_DEBUG, "ip_mrouter_done\n"); ! 664: ! 665: return 0; ! 666: } ! 667: ! 668: #if !MROUTE_LKM ! 669: int (*ip_mrouter_done)(void) = X_ip_mrouter_done; ! 670: #endif ! 671: ! 672: /* ! 673: * Set PIM assert processing global ! 674: */ ! 675: static int ! 676: set_assert(i) ! 677: int i; ! 678: { ! 679: if ((i != 1) && (i != 0)) ! 680: return EINVAL; ! 681: ! 682: pim_assert = i; ! 683: ! 684: return 0; ! 685: } ! 686: ! 687: /* ! 688: * Add a vif to the vif table ! 689: */ ! 690: static int ! 691: add_vif(vifcp) ! 692: register struct vifctl *vifcp; ! 693: { ! 694: register struct vif *vifp = viftable + vifcp->vifc_vifi; ! 695: static struct sockaddr_in sin = {sizeof sin, AF_INET}; ! 696: struct ifaddr *ifa; ! 697: struct ifnet *ifp; ! 698: int error, s; ! 699: struct tbf *v_tbf = tbftable + vifcp->vifc_vifi; ! 700: ! 701: if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL; ! 702: if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE; ! 703: ! 704: /* Find the interface with an address in AF_INET family */ ! 705: sin.sin_addr = vifcp->vifc_lcl_addr; ! 706: ifa = ifa_ifwithaddr((struct sockaddr *)&sin); ! 707: if (ifa == 0) return EADDRNOTAVAIL; ! 708: ifp = ifa->ifa_ifp; ! 709: ! 710: if (vifcp->vifc_flags & VIFF_TUNNEL) { ! 711: if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) { ! 712: /* ! 713: * An encapsulating tunnel is wanted. Tell ipip_input() to ! 714: * start paying attention to encapsulated packets. ! 715: */ ! 716: if (have_encap_tunnel == 0) { ! 717: have_encap_tunnel = 1; ! 718: for (s = 0; s < MAXVIFS; ++s) { ! 719: multicast_decap_if[s].if_name = "mdecap"; ! 720: multicast_decap_if[s].if_unit = s; ! 721: multicast_decap_if[s].if_family = APPLE_IF_FAM_MDECAP; ! 722: } ! 723: } ! 724: /* ! 725: * Set interface to fake encapsulator interface ! 726: */ ! 727: ifp = &multicast_decap_if[vifcp->vifc_vifi]; ! 728: /* ! 729: * Prepare cached route entry ! 730: */ ! 731: bzero(&vifp->v_route, sizeof(vifp->v_route)); ! 732: } else { ! 733: log(LOG_ERR, "source routed tunnels not supported\n"); ! 734: return EOPNOTSUPP; ! 735: } ! 736: } else { ! 737: /* Make sure the interface supports multicast */ ! 738: if ((ifp->if_flags & IFF_MULTICAST) == 0) ! 739: return EOPNOTSUPP; ! 740: ! 741: /* Enable promiscuous reception of all IP multicasts from the if */ ! 742: s = splnet(); ! 743: error = if_allmulti(ifp, 1); ! 744: splx(s); ! 745: if (error) ! 746: return error; ! 747: } ! 748: ! 749: s = splnet(); ! 750: /* define parameters for the tbf structure */ ! 751: vifp->v_tbf = v_tbf; ! 752: GET_TIME(vifp->v_tbf->tbf_last_pkt_t); ! 753: vifp->v_tbf->tbf_n_tok = 0; ! 754: vifp->v_tbf->tbf_q_len = 0; ! 755: vifp->v_tbf->tbf_max_q_len = MAXQSIZE; ! 756: vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL; ! 757: ! 758: vifp->v_flags = vifcp->vifc_flags; ! 759: vifp->v_threshold = vifcp->vifc_threshold; ! 760: vifp->v_lcl_addr = vifcp->vifc_lcl_addr; ! 761: vifp->v_rmt_addr = vifcp->vifc_rmt_addr; ! 762: vifp->v_ifp = ifp; ! 763: /* scaling up here allows division by 1024 in critical code */ ! 764: vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000; ! 765: vifp->v_rsvp_on = 0; ! 766: vifp->v_rsvpd = NULL; ! 767: /* initialize per vif pkt counters */ ! 768: vifp->v_pkt_in = 0; ! 769: vifp->v_pkt_out = 0; ! 770: vifp->v_bytes_in = 0; ! 771: vifp->v_bytes_out = 0; ! 772: splx(s); ! 773: ! 774: /* Adjust numvifs up if the vifi is higher than numvifs */ ! 775: if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; ! 776: ! 777: if (mrtdebug) ! 778: log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n", ! 779: vifcp->vifc_vifi, ! 780: (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr), ! 781: (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask", ! 782: (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr), ! 783: vifcp->vifc_threshold, ! 784: vifcp->vifc_rate_limit); ! 785: ! 786: return 0; ! 787: } ! 788: ! 789: /* ! 790: * Delete a vif from the vif table ! 791: */ ! 792: static int ! 793: del_vif(vifi) ! 794: vifi_t vifi; ! 795: { ! 796: register struct vif *vifp = &viftable[vifi]; ! 797: register struct mbuf *m; ! 798: struct ifnet *ifp; ! 799: struct ifreq ifr; ! 800: int s; ! 801: ! 802: if (vifi >= numvifs) return EINVAL; ! 803: if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL; ! 804: ! 805: s = splnet(); ! 806: ! 807: if (!(vifp->v_flags & VIFF_TUNNEL)) { ! 808: ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ! 809: ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; ! 810: ifp = vifp->v_ifp; ! 811: if_allmulti(ifp, 0); ! 812: } ! 813: ! 814: if (vifp == last_encap_vif) { ! 815: last_encap_vif = 0; ! 816: last_encap_src = 0; ! 817: } ! 818: ! 819: /* ! 820: * Free packets queued at the interface ! 821: */ ! 822: while (vifp->v_tbf->tbf_q) { ! 823: m = vifp->v_tbf->tbf_q; ! 824: vifp->v_tbf->tbf_q = m->m_act; ! 825: m_freem(m); ! 826: } ! 827: ! 828: bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf))); ! 829: bzero((caddr_t)vifp, sizeof (*vifp)); ! 830: ! 831: if (mrtdebug) ! 832: log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs); ! 833: ! 834: /* Adjust numvifs down */ ! 835: for (vifi = numvifs; vifi > 0; vifi--) ! 836: if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break; ! 837: numvifs = vifi; ! 838: ! 839: splx(s); ! 840: ! 841: return 0; ! 842: } ! 843: ! 844: /* ! 845: * Add an mfc entry ! 846: */ ! 847: static int ! 848: add_mfc(mfccp) ! 849: struct mfcctl *mfccp; ! 850: { ! 851: struct mfc *rt; ! 852: u_long hash; ! 853: struct rtdetq *rte; ! 854: register u_short nstl; ! 855: int s; ! 856: int i; ! 857: ! 858: MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt); ! 859: ! 860: /* If an entry already exists, just update the fields */ ! 861: if (rt) { ! 862: if (mrtdebug & DEBUG_MFC) ! 863: log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n", ! 864: (u_long)ntohl(mfccp->mfcc_origin.s_addr), ! 865: (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), ! 866: mfccp->mfcc_parent); ! 867: ! 868: s = splnet(); ! 869: rt->mfc_parent = mfccp->mfcc_parent; ! 870: for (i = 0; i < numvifs; i++) ! 871: rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; ! 872: splx(s); ! 873: return 0; ! 874: } ! 875: ! 876: /* ! 877: * Find the entry for which the upcall was made and update ! 878: */ ! 879: s = splnet(); ! 880: hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); ! 881: for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { ! 882: ! 883: if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && ! 884: (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && ! 885: (rt->mfc_stall != NULL)) { ! 886: ! 887: if (nstl++) ! 888: log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n", ! 889: "multiple kernel entries", ! 890: (u_long)ntohl(mfccp->mfcc_origin.s_addr), ! 891: (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), ! 892: mfccp->mfcc_parent, (void *)rt->mfc_stall); ! 893: ! 894: if (mrtdebug & DEBUG_MFC) ! 895: log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n", ! 896: (u_long)ntohl(mfccp->mfcc_origin.s_addr), ! 897: (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), ! 898: mfccp->mfcc_parent, (void *)rt->mfc_stall); ! 899: ! 900: rt->mfc_origin = mfccp->mfcc_origin; ! 901: rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; ! 902: rt->mfc_parent = mfccp->mfcc_parent; ! 903: for (i = 0; i < numvifs; i++) ! 904: rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; ! 905: /* initialize pkt counters per src-grp */ ! 906: rt->mfc_pkt_cnt = 0; ! 907: rt->mfc_byte_cnt = 0; ! 908: rt->mfc_wrong_if = 0; ! 909: rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; ! 910: ! 911: rt->mfc_expire = 0; /* Don't clean this guy up */ ! 912: nexpire[hash]--; ! 913: ! 914: /* free packets Qed at the end of this entry */ ! 915: for (rte = rt->mfc_stall; rte != NULL; ) { ! 916: struct rtdetq *n = rte->next; ! 917: ! 918: ip_mdq(rte->m, rte->ifp, rt, -1); ! 919: m_freem(rte->m); ! 920: #if UPCALL_TIMING ! 921: collate(&(rte->t)); ! 922: #endif /* UPCALL_TIMING */ ! 923: FREE(rte, M_MRTABLE); ! 924: rte = n; ! 925: } ! 926: rt->mfc_stall = NULL; ! 927: } ! 928: } ! 929: ! 930: /* ! 931: * It is possible that an entry is being inserted without an upcall ! 932: */ ! 933: if (nstl == 0) { ! 934: if (mrtdebug & DEBUG_MFC) ! 935: log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n", ! 936: hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr), ! 937: (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), ! 938: mfccp->mfcc_parent); ! 939: ! 940: for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) { ! 941: ! 942: if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && ! 943: (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { ! 944: ! 945: rt->mfc_origin = mfccp->mfcc_origin; ! 946: rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; ! 947: rt->mfc_parent = mfccp->mfcc_parent; ! 948: for (i = 0; i < numvifs; i++) ! 949: rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; ! 950: /* initialize pkt counters per src-grp */ ! 951: rt->mfc_pkt_cnt = 0; ! 952: rt->mfc_byte_cnt = 0; ! 953: rt->mfc_wrong_if = 0; ! 954: rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; ! 955: if (rt->mfc_expire) ! 956: nexpire[hash]--; ! 957: rt->mfc_expire = 0; ! 958: } ! 959: } ! 960: if (rt == NULL) { ! 961: /* no upcall, so make a new entry */ ! 962: rt = (struct mfc *) _MALLOC(sizeof(*rt), M_MRTABLE, M_NOWAIT); ! 963: if (rt == NULL) { ! 964: splx(s); ! 965: return ENOBUFS; ! 966: } ! 967: ! 968: /* insert new entry at head of hash chain */ ! 969: rt->mfc_origin = mfccp->mfcc_origin; ! 970: rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; ! 971: rt->mfc_parent = mfccp->mfcc_parent; ! 972: for (i = 0; i < numvifs; i++) ! 973: rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; ! 974: /* initialize pkt counters per src-grp */ ! 975: rt->mfc_pkt_cnt = 0; ! 976: rt->mfc_byte_cnt = 0; ! 977: rt->mfc_wrong_if = 0; ! 978: rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; ! 979: rt->mfc_expire = 0; ! 980: rt->mfc_stall = NULL; ! 981: ! 982: /* link into table */ ! 983: rt->mfc_next = mfctable[hash]; ! 984: mfctable[hash] = rt; ! 985: } ! 986: } ! 987: splx(s); ! 988: return 0; ! 989: } ! 990: ! 991: #if UPCALL_TIMING ! 992: /* ! 993: * collect delay statistics on the upcalls ! 994: */ ! 995: static void collate(t) ! 996: register struct timeval *t; ! 997: { ! 998: register u_long d; ! 999: register struct timeval tp; ! 1000: register u_long delta; ! 1001: ! 1002: GET_TIME(tp); ! 1003: ! 1004: if (TV_LT(*t, tp)) ! 1005: { ! 1006: TV_DELTA(tp, *t, delta); ! 1007: ! 1008: d = delta >> 10; ! 1009: if (d > 50) ! 1010: d = 50; ! 1011: ! 1012: ++upcall_data[d]; ! 1013: } ! 1014: } ! 1015: #endif /* UPCALL_TIMING */ ! 1016: ! 1017: /* ! 1018: * Delete an mfc entry ! 1019: */ ! 1020: static int ! 1021: del_mfc(mfccp) ! 1022: struct mfcctl *mfccp; ! 1023: { ! 1024: struct in_addr origin; ! 1025: struct in_addr mcastgrp; ! 1026: struct mfc *rt; ! 1027: struct mfc **nptr; ! 1028: u_long hash; ! 1029: int s; ! 1030: ! 1031: origin = mfccp->mfcc_origin; ! 1032: mcastgrp = mfccp->mfcc_mcastgrp; ! 1033: hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); ! 1034: ! 1035: if (mrtdebug & DEBUG_MFC) ! 1036: log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n", ! 1037: (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr)); ! 1038: ! 1039: s = splnet(); ! 1040: ! 1041: nptr = &mfctable[hash]; ! 1042: while ((rt = *nptr) != NULL) { ! 1043: if (origin.s_addr == rt->mfc_origin.s_addr && ! 1044: mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && ! 1045: rt->mfc_stall == NULL) ! 1046: break; ! 1047: ! 1048: nptr = &rt->mfc_next; ! 1049: } ! 1050: if (rt == NULL) { ! 1051: splx(s); ! 1052: return EADDRNOTAVAIL; ! 1053: } ! 1054: ! 1055: *nptr = rt->mfc_next; ! 1056: FREE(rt, M_MRTABLE); ! 1057: ! 1058: splx(s); ! 1059: ! 1060: return 0; ! 1061: } ! 1062: ! 1063: /* ! 1064: * Send a message to mrouted on the multicast routing socket ! 1065: */ ! 1066: static int ! 1067: socket_send(s, mm, src) ! 1068: struct socket *s; ! 1069: struct mbuf *mm; ! 1070: struct sockaddr_in *src; ! 1071: { ! 1072: if (s) { ! 1073: if (sbappendaddr(&s->so_rcv, ! 1074: (struct sockaddr *)src, ! 1075: mm, (struct mbuf *)0) != 0) { ! 1076: sorwakeup(s); ! 1077: return 0; ! 1078: } ! 1079: } ! 1080: m_freem(mm); ! 1081: return -1; ! 1082: } ! 1083: ! 1084: /* ! 1085: * IP multicast forwarding function. This function assumes that the packet ! 1086: * pointed to by "ip" has arrived on (or is about to be sent to) the interface ! 1087: * pointed to by "ifp", and the packet is to be relayed to other networks ! 1088: * that have members of the packet's destination IP multicast group. ! 1089: * ! 1090: * The packet is returned unscathed to the caller, unless it is ! 1091: * erroneous, in which case a non-zero return value tells the caller to ! 1092: * discard it. ! 1093: */ ! 1094: ! 1095: #define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ ! 1096: #define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ ! 1097: ! 1098: static int ! 1099: X_ip_mforward(ip, ifp, m, imo) ! 1100: register struct ip *ip; ! 1101: struct ifnet *ifp; ! 1102: struct mbuf *m; ! 1103: struct ip_moptions *imo; ! 1104: { ! 1105: register struct mfc *rt; ! 1106: register u_char *ipoptions; ! 1107: static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; ! 1108: static int srctun = 0; ! 1109: register struct mbuf *mm; ! 1110: int s; ! 1111: vifi_t vifi; ! 1112: struct vif *vifp; ! 1113: ! 1114: if (mrtdebug & DEBUG_FORWARD) ! 1115: log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n", ! 1116: (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr), ! 1117: (void *)ifp); ! 1118: ! 1119: if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || ! 1120: (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { ! 1121: /* ! 1122: * Packet arrived via a physical interface or ! 1123: * an encapsulated tunnel. ! 1124: */ ! 1125: } else { ! 1126: /* ! 1127: * Packet arrived through a source-route tunnel. ! 1128: * Source-route tunnels are no longer supported. ! 1129: */ ! 1130: if ((srctun++ % 1000) == 0) ! 1131: log(LOG_ERR, ! 1132: "ip_mforward: received source-routed packet from %lx\n", ! 1133: (u_long)ntohl(ip->ip_src.s_addr)); ! 1134: ! 1135: return 1; ! 1136: } ! 1137: ! 1138: if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) { ! 1139: if (ip->ip_ttl < 255) ! 1140: ip->ip_ttl++; /* compensate for -1 in *_send routines */ ! 1141: if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { ! 1142: vifp = viftable + vifi; ! 1143: printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n", ! 1144: ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), vifi, ! 1145: (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "", ! 1146: vifp->v_ifp->if_name, vifp->v_ifp->if_unit); ! 1147: } ! 1148: return (ip_mdq(m, ifp, NULL, vifi)); ! 1149: } ! 1150: if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { ! 1151: printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", ! 1152: ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr)); ! 1153: if(!imo) ! 1154: printf("In fact, no options were specified at all\n"); ! 1155: } ! 1156: ! 1157: /* ! 1158: * Don't forward a packet with time-to-live of zero or one, ! 1159: * or a packet destined to a local-only group. ! 1160: */ ! 1161: if (ip->ip_ttl <= 1 || ! 1162: ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) ! 1163: return 0; ! 1164: ! 1165: /* ! 1166: * Determine forwarding vifs from the forwarding cache table ! 1167: */ ! 1168: s = splnet(); ! 1169: MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt); ! 1170: ! 1171: /* Entry exists, so forward if necessary */ ! 1172: if (rt != NULL) { ! 1173: splx(s); ! 1174: return (ip_mdq(m, ifp, rt, -1)); ! 1175: } else { ! 1176: /* ! 1177: * If we don't have a route for packet's origin, ! 1178: * Make a copy of the packet & ! 1179: * send message to routing daemon ! 1180: */ ! 1181: ! 1182: register struct mbuf *mb0; ! 1183: register struct rtdetq *rte; ! 1184: register u_long hash; ! 1185: int hlen = ip->ip_hl << 2; ! 1186: #if UPCALL_TIMING ! 1187: struct timeval tp; ! 1188: ! 1189: GET_TIME(tp); ! 1190: #endif ! 1191: ! 1192: mrtstat.mrts_no_route++; ! 1193: if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) ! 1194: log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n", ! 1195: (u_long)ntohl(ip->ip_src.s_addr), ! 1196: (u_long)ntohl(ip->ip_dst.s_addr)); ! 1197: ! 1198: /* ! 1199: * Allocate mbufs early so that we don't do extra work if we are ! 1200: * just going to fail anyway. Make sure to pullup the header so ! 1201: * that other people can't step on it. ! 1202: */ ! 1203: rte = (struct rtdetq *) _MALLOC((sizeof *rte), M_MRTABLE, M_NOWAIT); ! 1204: if (rte == NULL) { ! 1205: splx(s); ! 1206: return ENOBUFS; ! 1207: } ! 1208: mb0 = m_copy(m, 0, M_COPYALL); ! 1209: if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen)) ! 1210: mb0 = m_pullup(mb0, hlen); ! 1211: if (mb0 == NULL) { ! 1212: FREE(rte, M_MRTABLE); ! 1213: splx(s); ! 1214: return ENOBUFS; ! 1215: } ! 1216: ! 1217: /* is there an upcall waiting for this packet? */ ! 1218: hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr); ! 1219: for (rt = mfctable[hash]; rt; rt = rt->mfc_next) { ! 1220: if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) && ! 1221: (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) && ! 1222: (rt->mfc_stall != NULL)) ! 1223: break; ! 1224: } ! 1225: ! 1226: if (rt == NULL) { ! 1227: int i; ! 1228: struct igmpmsg *im; ! 1229: ! 1230: /* no upcall, so make a new entry */ ! 1231: rt = (struct mfc *) _MALLOC(sizeof(*rt), M_MRTABLE, M_NOWAIT); ! 1232: if (rt == NULL) { ! 1233: FREE(rte, M_MRTABLE); ! 1234: m_freem(mb0); ! 1235: splx(s); ! 1236: return ENOBUFS; ! 1237: } ! 1238: /* Make a copy of the header to send to the user level process */ ! 1239: mm = m_copy(mb0, 0, hlen); ! 1240: if (mm == NULL) { ! 1241: FREE(rte, M_MRTABLE); ! 1242: m_freem(mb0); ! 1243: FREE(rt, M_MRTABLE); ! 1244: splx(s); ! 1245: return ENOBUFS; ! 1246: } ! 1247: ! 1248: /* ! 1249: * Send message to routing daemon to install ! 1250: * a route into the kernel table ! 1251: */ ! 1252: k_igmpsrc.sin_addr = ip->ip_src; ! 1253: ! 1254: im = mtod(mm, struct igmpmsg *); ! 1255: im->im_msgtype = IGMPMSG_NOCACHE; ! 1256: im->im_mbz = 0; ! 1257: ! 1258: mrtstat.mrts_upcalls++; ! 1259: ! 1260: if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) { ! 1261: log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); ! 1262: ++mrtstat.mrts_upq_sockfull; ! 1263: FREE(rte, M_MRTABLE); ! 1264: m_freem(mb0); ! 1265: FREE(rt, M_MRTABLE); ! 1266: splx(s); ! 1267: return ENOBUFS; ! 1268: } ! 1269: ! 1270: /* insert new entry at head of hash chain */ ! 1271: rt->mfc_origin.s_addr = ip->ip_src.s_addr; ! 1272: rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; ! 1273: rt->mfc_expire = UPCALL_EXPIRE; ! 1274: nexpire[hash]++; ! 1275: for (i = 0; i < numvifs; i++) ! 1276: rt->mfc_ttls[i] = 0; ! 1277: rt->mfc_parent = -1; ! 1278: ! 1279: /* link into table */ ! 1280: rt->mfc_next = mfctable[hash]; ! 1281: mfctable[hash] = rt; ! 1282: rt->mfc_stall = rte; ! 1283: ! 1284: } else { ! 1285: /* determine if q has overflowed */ ! 1286: int npkts = 0; ! 1287: struct rtdetq **p; ! 1288: ! 1289: for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next) ! 1290: npkts++; ! 1291: ! 1292: if (npkts > MAX_UPQ) { ! 1293: mrtstat.mrts_upq_ovflw++; ! 1294: FREE(rte, M_MRTABLE); ! 1295: m_freem(mb0); ! 1296: splx(s); ! 1297: return 0; ! 1298: } ! 1299: ! 1300: /* Add this entry to the end of the queue */ ! 1301: *p = rte; ! 1302: } ! 1303: ! 1304: rte->m = mb0; ! 1305: rte->ifp = ifp; ! 1306: #if UPCALL_TIMING ! 1307: rte->t = tp; ! 1308: #endif ! 1309: rte->next = NULL; ! 1310: ! 1311: splx(s); ! 1312: ! 1313: return 0; ! 1314: } ! 1315: } ! 1316: ! 1317: #if !MROUTE_LKM ! 1318: int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, ! 1319: struct ip_moptions *) = X_ip_mforward; ! 1320: #endif ! 1321: ! 1322: /* ! 1323: * Clean up the cache entry if upcall is not serviced ! 1324: */ ! 1325: static void ! 1326: expire_upcalls(void *unused) ! 1327: { ! 1328: struct rtdetq *rte; ! 1329: struct mfc *mfc, **nptr; ! 1330: int i; ! 1331: int s; ! 1332: ! 1333: s = splnet(); ! 1334: for (i = 0; i < MFCTBLSIZ; i++) { ! 1335: if (nexpire[i] == 0) ! 1336: continue; ! 1337: nptr = &mfctable[i]; ! 1338: for (mfc = *nptr; mfc != NULL; mfc = *nptr) { ! 1339: /* ! 1340: * Skip real cache entries ! 1341: * Make sure it wasn't marked to not expire (shouldn't happen) ! 1342: * If it expires now ! 1343: */ ! 1344: if (mfc->mfc_stall != NULL && ! 1345: mfc->mfc_expire != 0 && ! 1346: --mfc->mfc_expire == 0) { ! 1347: if (mrtdebug & DEBUG_EXPIRE) ! 1348: log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n", ! 1349: (u_long)ntohl(mfc->mfc_origin.s_addr), ! 1350: (u_long)ntohl(mfc->mfc_mcastgrp.s_addr)); ! 1351: /* ! 1352: * drop all the packets ! 1353: * free the mbuf with the pkt, if, timing info ! 1354: */ ! 1355: for (rte = mfc->mfc_stall; rte; ) { ! 1356: struct rtdetq *n = rte->next; ! 1357: ! 1358: m_freem(rte->m); ! 1359: FREE(rte, M_MRTABLE); ! 1360: rte = n; ! 1361: } ! 1362: ++mrtstat.mrts_cache_cleanups; ! 1363: nexpire[i]--; ! 1364: ! 1365: *nptr = mfc->mfc_next; ! 1366: FREE(mfc, M_MRTABLE); ! 1367: } else { ! 1368: nptr = &mfc->mfc_next; ! 1369: } ! 1370: } ! 1371: } ! 1372: splx(s); ! 1373: timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); ! 1374: } ! 1375: ! 1376: /* ! 1377: * Packet forwarding routine once entry in the cache is made ! 1378: */ ! 1379: static int ! 1380: ip_mdq(m, ifp, rt, xmt_vif) ! 1381: register struct mbuf *m; ! 1382: register struct ifnet *ifp; ! 1383: register struct mfc *rt; ! 1384: register vifi_t xmt_vif; ! 1385: { ! 1386: register struct ip *ip = mtod(m, struct ip *); ! 1387: register vifi_t vifi; ! 1388: register struct vif *vifp; ! 1389: register int plen = ip->ip_len; ! 1390: ! 1391: /* ! 1392: * Macro to send packet on vif. Since RSVP packets don't get counted on ! 1393: * input, they shouldn't get counted on output, so statistics keeping is ! 1394: * seperate. ! 1395: */ ! 1396: #define MC_SEND(ip,vifp,m) { \ ! 1397: if ((vifp)->v_flags & VIFF_TUNNEL) \ ! 1398: encap_send((ip), (vifp), (m)); \ ! 1399: else \ ! 1400: phyint_send((ip), (vifp), (m)); \ ! 1401: } ! 1402: ! 1403: /* ! 1404: * If xmt_vif is not -1, send on only the requested vif. ! 1405: * ! 1406: * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) ! 1407: */ ! 1408: if (xmt_vif < numvifs) { ! 1409: MC_SEND(ip, viftable + xmt_vif, m); ! 1410: return 1; ! 1411: } ! 1412: ! 1413: /* ! 1414: * Don't forward if it didn't arrive from the parent vif for its origin. ! 1415: */ ! 1416: vifi = rt->mfc_parent; ! 1417: if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { ! 1418: /* came in the wrong interface */ ! 1419: if (mrtdebug & DEBUG_FORWARD) ! 1420: log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n", ! 1421: (void *)ifp, vifi, (void *)viftable[vifi].v_ifp); ! 1422: ++mrtstat.mrts_wrong_if; ! 1423: ++rt->mfc_wrong_if; ! 1424: /* ! 1425: * If we are doing PIM assert processing, and we are forwarding ! 1426: * packets on this interface, and it is a broadcast medium ! 1427: * interface (and not a tunnel), send a message to the routing daemon. ! 1428: */ ! 1429: if (pim_assert && rt->mfc_ttls[vifi] && ! 1430: (ifp->if_flags & IFF_BROADCAST) && ! 1431: !(viftable[vifi].v_flags & VIFF_TUNNEL)) { ! 1432: struct sockaddr_in k_igmpsrc; ! 1433: struct mbuf *mm; ! 1434: struct igmpmsg *im; ! 1435: int hlen = ip->ip_hl << 2; ! 1436: struct timeval now; ! 1437: register u_long delta; ! 1438: ! 1439: GET_TIME(now); ! 1440: ! 1441: TV_DELTA(rt->mfc_last_assert, now, delta); ! 1442: ! 1443: if (delta > ASSERT_MSG_TIME) { ! 1444: mm = m_copy(m, 0, hlen); ! 1445: if (mm && (M_HASCL(mm) || mm->m_len < hlen)) ! 1446: mm = m_pullup(mm, hlen); ! 1447: if (mm == NULL) { ! 1448: return ENOBUFS; ! 1449: } ! 1450: ! 1451: rt->mfc_last_assert = now; ! 1452: ! 1453: im = mtod(mm, struct igmpmsg *); ! 1454: im->im_msgtype = IGMPMSG_WRONGVIF; ! 1455: im->im_mbz = 0; ! 1456: im->im_vif = vifi; ! 1457: ! 1458: k_igmpsrc.sin_addr = im->im_src; ! 1459: ! 1460: socket_send(ip_mrouter, mm, &k_igmpsrc); ! 1461: } ! 1462: } ! 1463: return 0; ! 1464: } ! 1465: ! 1466: /* If I sourced this packet, it counts as output, else it was input. */ ! 1467: if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { ! 1468: viftable[vifi].v_pkt_out++; ! 1469: viftable[vifi].v_bytes_out += plen; ! 1470: } else { ! 1471: viftable[vifi].v_pkt_in++; ! 1472: viftable[vifi].v_bytes_in += plen; ! 1473: } ! 1474: rt->mfc_pkt_cnt++; ! 1475: rt->mfc_byte_cnt += plen; ! 1476: ! 1477: /* ! 1478: * For each vif, decide if a copy of the packet should be forwarded. ! 1479: * Forward if: ! 1480: * - the ttl exceeds the vif's threshold ! 1481: * - there are group members downstream on interface ! 1482: */ ! 1483: for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) ! 1484: if ((rt->mfc_ttls[vifi] > 0) && ! 1485: (ip->ip_ttl > rt->mfc_ttls[vifi])) { ! 1486: vifp->v_pkt_out++; ! 1487: vifp->v_bytes_out += plen; ! 1488: MC_SEND(ip, vifp, m); ! 1489: } ! 1490: ! 1491: return 0; ! 1492: } ! 1493: ! 1494: /* ! 1495: * check if a vif number is legal/ok. This is used by ip_output, to export ! 1496: * numvifs there, ! 1497: */ ! 1498: static int ! 1499: X_legal_vif_num(vif) ! 1500: int vif; ! 1501: { ! 1502: if (vif >= 0 && vif < numvifs) ! 1503: return(1); ! 1504: else ! 1505: return(0); ! 1506: } ! 1507: ! 1508: #if !MROUTE_LKM ! 1509: int (*legal_vif_num)(int) = X_legal_vif_num; ! 1510: #endif ! 1511: ! 1512: /* ! 1513: * Return the local address used by this vif ! 1514: */ ! 1515: static u_long ! 1516: X_ip_mcast_src(vifi) ! 1517: int vifi; ! 1518: { ! 1519: if (vifi >= 0 && vifi < numvifs) ! 1520: return viftable[vifi].v_lcl_addr.s_addr; ! 1521: else ! 1522: return INADDR_ANY; ! 1523: } ! 1524: ! 1525: #if !MROUTE_LKM ! 1526: u_long (*ip_mcast_src)(int) = X_ip_mcast_src; ! 1527: #endif ! 1528: ! 1529: static void ! 1530: phyint_send(ip, vifp, m) ! 1531: struct ip *ip; ! 1532: struct vif *vifp; ! 1533: struct mbuf *m; ! 1534: { ! 1535: register struct mbuf *mb_copy; ! 1536: register int hlen = ip->ip_hl << 2; ! 1537: ! 1538: /* ! 1539: * Make a new reference to the packet; make sure that ! 1540: * the IP header is actually copied, not just referenced, ! 1541: * so that ip_output() only scribbles on the copy. ! 1542: */ ! 1543: mb_copy = m_copy(m, 0, M_COPYALL); ! 1544: if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen)) ! 1545: mb_copy = m_pullup(mb_copy, hlen); ! 1546: if (mb_copy == NULL) ! 1547: return; ! 1548: ! 1549: if (vifp->v_rate_limit == 0) ! 1550: tbf_send_packet(vifp, mb_copy); ! 1551: else ! 1552: tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len); ! 1553: } ! 1554: ! 1555: static void ! 1556: encap_send(ip, vifp, m) ! 1557: register struct ip *ip; ! 1558: register struct vif *vifp; ! 1559: register struct mbuf *m; ! 1560: { ! 1561: register struct mbuf *mb_copy; ! 1562: register struct ip *ip_copy; ! 1563: register int i, len = ip->ip_len; ! 1564: ! 1565: /* ! 1566: * copy the old packet & pullup its IP header into the ! 1567: * new mbuf so we can modify it. Try to fill the new ! 1568: * mbuf since if we don't the ethernet driver will. ! 1569: */ ! 1570: MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER); ! 1571: if (mb_copy == NULL) ! 1572: return; ! 1573: mb_copy->m_data += max_linkhdr; ! 1574: mb_copy->m_len = sizeof(multicast_encap_iphdr); ! 1575: ! 1576: if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { ! 1577: m_freem(mb_copy); ! 1578: return; ! 1579: } ! 1580: i = MHLEN - M_LEADINGSPACE(mb_copy); ! 1581: if (i > len) ! 1582: i = len; ! 1583: mb_copy = m_pullup(mb_copy, i); ! 1584: if (mb_copy == NULL) ! 1585: return; ! 1586: mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr); ! 1587: ! 1588: /* ! 1589: * fill in the encapsulating IP header. ! 1590: */ ! 1591: ip_copy = mtod(mb_copy, struct ip *); ! 1592: *ip_copy = multicast_encap_iphdr; ! 1593: ip_copy->ip_id = htons(ip_id++); ! 1594: ip_copy->ip_len += len; ! 1595: ip_copy->ip_src = vifp->v_lcl_addr; ! 1596: ip_copy->ip_dst = vifp->v_rmt_addr; ! 1597: ! 1598: /* ! 1599: * turn the encapsulated IP header back into a valid one. ! 1600: */ ! 1601: ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr)); ! 1602: --ip->ip_ttl; ! 1603: HTONS(ip->ip_len); ! 1604: HTONS(ip->ip_off); ! 1605: ip->ip_sum = 0; ! 1606: mb_copy->m_data += sizeof(multicast_encap_iphdr); ! 1607: ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); ! 1608: mb_copy->m_data -= sizeof(multicast_encap_iphdr); ! 1609: ! 1610: if (vifp->v_rate_limit == 0) ! 1611: tbf_send_packet(vifp, mb_copy); ! 1612: else ! 1613: tbf_control(vifp, mb_copy, ip, ip_copy->ip_len); ! 1614: } ! 1615: ! 1616: /* ! 1617: * De-encapsulate a packet and feed it back through ip input (this ! 1618: * routine is called whenever IP gets a packet with proto type ! 1619: * ENCAP_PROTO and a local destination address). ! 1620: */ ! 1621: void ! 1622: #if MROUTE_LKM ! 1623: X_ipip_input(m, iphlen) ! 1624: #else ! 1625: ipip_input(m, iphlen) ! 1626: #endif ! 1627: register struct mbuf *m; ! 1628: int iphlen; ! 1629: { ! 1630: struct ifnet *ifp = m->m_pkthdr.rcvif; ! 1631: register struct ip *ip = mtod(m, struct ip *); ! 1632: register int hlen = ip->ip_hl << 2; ! 1633: register int s; ! 1634: register struct ifqueue *ifq; ! 1635: register struct vif *vifp; ! 1636: ! 1637: if (!have_encap_tunnel) { ! 1638: rip_input(m, iphlen); ! 1639: return; ! 1640: } ! 1641: /* ! 1642: * dump the packet if it's not to a multicast destination or if ! 1643: * we don't have an encapsulating tunnel with the source. ! 1644: * Note: This code assumes that the remote site IP address ! 1645: * uniquely identifies the tunnel (i.e., that this site has ! 1646: * at most one tunnel with the remote site). ! 1647: */ ! 1648: if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) { ! 1649: ++mrtstat.mrts_bad_tunnel; ! 1650: m_freem(m); ! 1651: return; ! 1652: } ! 1653: if (ip->ip_src.s_addr != last_encap_src) { ! 1654: register struct vif *vife; ! 1655: ! 1656: vifp = viftable; ! 1657: vife = vifp + numvifs; ! 1658: last_encap_src = ip->ip_src.s_addr; ! 1659: last_encap_vif = 0; ! 1660: for ( ; vifp < vife; ++vifp) ! 1661: if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) { ! 1662: if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT)) ! 1663: == VIFF_TUNNEL) ! 1664: last_encap_vif = vifp; ! 1665: break; ! 1666: } ! 1667: } ! 1668: if ((vifp = last_encap_vif) == 0) { ! 1669: last_encap_src = 0; ! 1670: mrtstat.mrts_cant_tunnel++; /*XXX*/ ! 1671: m_freem(m); ! 1672: if (mrtdebug) ! 1673: log(LOG_DEBUG, "ip_mforward: no tunnel with %lx\n", ! 1674: (u_long)ntohl(ip->ip_src.s_addr)); ! 1675: return; ! 1676: } ! 1677: ifp = vifp->v_ifp; ! 1678: ! 1679: if (hlen > IP_HDR_LEN) ! 1680: ip_stripoptions(m, (struct mbuf *) 0); ! 1681: m->m_data += IP_HDR_LEN; ! 1682: m->m_len -= IP_HDR_LEN; ! 1683: m->m_pkthdr.len -= IP_HDR_LEN; ! 1684: m->m_pkthdr.rcvif = ifp; ! 1685: ! 1686: ifq = &ipintrq; ! 1687: s = splimp(); ! 1688: if (IF_QFULL(ifq)) { ! 1689: IF_DROP(ifq); ! 1690: m_freem(m); ! 1691: } else { ! 1692: IF_ENQUEUE(ifq, m); ! 1693: /* ! 1694: * normally we would need a "schednetisr(NETISR_IP)" ! 1695: * here but we were called by ip_input and it is going ! 1696: * to loop back & try to dequeue the packet we just ! 1697: * queued as soon as we return so we avoid the ! 1698: * unnecessary software interrrupt. ! 1699: */ ! 1700: } ! 1701: splx(s); ! 1702: } ! 1703: ! 1704: /* ! 1705: * Token bucket filter module ! 1706: */ ! 1707: ! 1708: static void ! 1709: tbf_control(vifp, m, ip, p_len) ! 1710: register struct vif *vifp; ! 1711: register struct mbuf *m; ! 1712: register struct ip *ip; ! 1713: register u_long p_len; ! 1714: { ! 1715: register struct tbf *t = vifp->v_tbf; ! 1716: ! 1717: if (p_len > MAX_BKT_SIZE) { ! 1718: /* drop if packet is too large */ ! 1719: mrtstat.mrts_pkt2large++; ! 1720: m_freem(m); ! 1721: return; ! 1722: } ! 1723: ! 1724: tbf_update_tokens(vifp); ! 1725: ! 1726: /* if there are enough tokens, ! 1727: * and the queue is empty, ! 1728: * send this packet out ! 1729: */ ! 1730: ! 1731: if (t->tbf_q_len == 0) { ! 1732: /* queue empty, send packet if enough tokens */ ! 1733: if (p_len <= t->tbf_n_tok) { ! 1734: t->tbf_n_tok -= p_len; ! 1735: tbf_send_packet(vifp, m); ! 1736: } else { ! 1737: /* queue packet and timeout till later */ ! 1738: tbf_queue(vifp, m); ! 1739: timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); ! 1740: } ! 1741: } else if (t->tbf_q_len < t->tbf_max_q_len) { ! 1742: /* finite queue length, so queue pkts and process queue */ ! 1743: tbf_queue(vifp, m); ! 1744: tbf_process_q(vifp); ! 1745: } else { ! 1746: /* queue length too much, try to dq and queue and process */ ! 1747: if (!tbf_dq_sel(vifp, ip)) { ! 1748: mrtstat.mrts_q_overflow++; ! 1749: m_freem(m); ! 1750: return; ! 1751: } else { ! 1752: tbf_queue(vifp, m); ! 1753: tbf_process_q(vifp); ! 1754: } ! 1755: } ! 1756: return; ! 1757: } ! 1758: ! 1759: /* ! 1760: * adds a packet to the queue at the interface ! 1761: */ ! 1762: static void ! 1763: tbf_queue(vifp, m) ! 1764: register struct vif *vifp; ! 1765: register struct mbuf *m; ! 1766: { ! 1767: register int s = splnet(); ! 1768: register struct tbf *t = vifp->v_tbf; ! 1769: ! 1770: if (t->tbf_t == NULL) { ! 1771: /* Queue was empty */ ! 1772: t->tbf_q = m; ! 1773: } else { ! 1774: /* Insert at tail */ ! 1775: t->tbf_t->m_act = m; ! 1776: } ! 1777: ! 1778: /* Set new tail pointer */ ! 1779: t->tbf_t = m; ! 1780: ! 1781: #if DIAGNOSTIC ! 1782: /* Make sure we didn't get fed a bogus mbuf */ ! 1783: if (m->m_act) ! 1784: panic("tbf_queue: m_act"); ! 1785: #endif ! 1786: m->m_act = NULL; ! 1787: ! 1788: t->tbf_q_len++; ! 1789: ! 1790: splx(s); ! 1791: } ! 1792: ! 1793: ! 1794: /* ! 1795: * processes the queue at the interface ! 1796: */ ! 1797: static void ! 1798: tbf_process_q(vifp) ! 1799: register struct vif *vifp; ! 1800: { ! 1801: register struct mbuf *m; ! 1802: register int len; ! 1803: register int s = splnet(); ! 1804: register struct tbf *t = vifp->v_tbf; ! 1805: ! 1806: /* loop through the queue at the interface and send as many packets ! 1807: * as possible ! 1808: */ ! 1809: while (t->tbf_q_len > 0) { ! 1810: m = t->tbf_q; ! 1811: ! 1812: len = mtod(m, struct ip *)->ip_len; ! 1813: ! 1814: /* determine if the packet can be sent */ ! 1815: if (len <= t->tbf_n_tok) { ! 1816: /* if so, ! 1817: * reduce no of tokens, dequeue the packet, ! 1818: * send the packet. ! 1819: */ ! 1820: t->tbf_n_tok -= len; ! 1821: ! 1822: t->tbf_q = m->m_act; ! 1823: if (--t->tbf_q_len == 0) ! 1824: t->tbf_t = NULL; ! 1825: ! 1826: m->m_act = NULL; ! 1827: tbf_send_packet(vifp, m); ! 1828: ! 1829: } else break; ! 1830: } ! 1831: splx(s); ! 1832: } ! 1833: ! 1834: static void ! 1835: tbf_reprocess_q(xvifp) ! 1836: void *xvifp; ! 1837: { ! 1838: register struct vif *vifp = xvifp; ! 1839: if (ip_mrouter == NULL) ! 1840: return; ! 1841: ! 1842: tbf_update_tokens(vifp); ! 1843: ! 1844: tbf_process_q(vifp); ! 1845: ! 1846: if (vifp->v_tbf->tbf_q_len) ! 1847: timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); ! 1848: } ! 1849: ! 1850: /* function that will selectively discard a member of the queue ! 1851: * based on the precedence value and the priority ! 1852: */ ! 1853: static int ! 1854: tbf_dq_sel(vifp, ip) ! 1855: register struct vif *vifp; ! 1856: register struct ip *ip; ! 1857: { ! 1858: register int s = splnet(); ! 1859: register u_int p; ! 1860: register struct mbuf *m, *last; ! 1861: register struct mbuf **np; ! 1862: register struct tbf *t = vifp->v_tbf; ! 1863: ! 1864: p = priority(vifp, ip); ! 1865: ! 1866: np = &t->tbf_q; ! 1867: last = NULL; ! 1868: while ((m = *np) != NULL) { ! 1869: if (p > priority(vifp, mtod(m, struct ip *))) { ! 1870: *np = m->m_act; ! 1871: /* If we're removing the last packet, fix the tail pointer */ ! 1872: if (m == t->tbf_t) ! 1873: t->tbf_t = last; ! 1874: m_freem(m); ! 1875: /* it's impossible for the queue to be empty, but ! 1876: * we check anyway. */ ! 1877: if (--t->tbf_q_len == 0) ! 1878: t->tbf_t = NULL; ! 1879: splx(s); ! 1880: mrtstat.mrts_drop_sel++; ! 1881: return(1); ! 1882: } ! 1883: np = &m->m_act; ! 1884: last = m; ! 1885: } ! 1886: splx(s); ! 1887: return(0); ! 1888: } ! 1889: ! 1890: static void ! 1891: tbf_send_packet(vifp, m) ! 1892: register struct vif *vifp; ! 1893: register struct mbuf *m; ! 1894: { ! 1895: struct ip_moptions imo; ! 1896: int error; ! 1897: static struct route ro; ! 1898: int s = splnet(); ! 1899: ! 1900: if (vifp->v_flags & VIFF_TUNNEL) { ! 1901: /* If tunnel options */ ! 1902: ip_output(m, (struct mbuf *)0, &vifp->v_route, ! 1903: IP_FORWARDING, (struct ip_moptions *)0); ! 1904: } else { ! 1905: imo.imo_multicast_ifp = vifp->v_ifp; ! 1906: imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1; ! 1907: imo.imo_multicast_loop = 1; ! 1908: imo.imo_multicast_vif = -1; ! 1909: ! 1910: /* ! 1911: * Re-entrancy should not be a problem here, because ! 1912: * the packets that we send out and are looped back at us ! 1913: * should get rejected because they appear to come from ! 1914: * the loopback interface, thus preventing looping. ! 1915: */ ! 1916: error = ip_output(m, (struct mbuf *)0, &ro, ! 1917: IP_FORWARDING, &imo); ! 1918: ! 1919: if (mrtdebug & DEBUG_XMIT) ! 1920: log(LOG_DEBUG, "phyint_send on vif %d err %d\n", ! 1921: vifp - viftable, error); ! 1922: } ! 1923: splx(s); ! 1924: } ! 1925: ! 1926: /* determine the current time and then ! 1927: * the elapsed time (between the last time and time now) ! 1928: * in milliseconds & update the no. of tokens in the bucket ! 1929: */ ! 1930: static void ! 1931: tbf_update_tokens(vifp) ! 1932: register struct vif *vifp; ! 1933: { ! 1934: struct timeval tp; ! 1935: register u_long tm; ! 1936: register int s = splnet(); ! 1937: register struct tbf *t = vifp->v_tbf; ! 1938: ! 1939: GET_TIME(tp); ! 1940: ! 1941: TV_DELTA(tp, t->tbf_last_pkt_t, tm); ! 1942: ! 1943: /* ! 1944: * This formula is actually ! 1945: * "time in seconds" * "bytes/second". ! 1946: * ! 1947: * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8) ! 1948: * ! 1949: * The (1000/1024) was introduced in add_vif to optimize ! 1950: * this divide into a shift. ! 1951: */ ! 1952: t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8; ! 1953: t->tbf_last_pkt_t = tp; ! 1954: ! 1955: if (t->tbf_n_tok > MAX_BKT_SIZE) ! 1956: t->tbf_n_tok = MAX_BKT_SIZE; ! 1957: ! 1958: splx(s); ! 1959: } ! 1960: ! 1961: static int ! 1962: priority(vifp, ip) ! 1963: register struct vif *vifp; ! 1964: register struct ip *ip; ! 1965: { ! 1966: register int prio; ! 1967: ! 1968: /* temporary hack; may add general packet classifier some day */ ! 1969: ! 1970: /* ! 1971: * The UDP port space is divided up into four priority ranges: ! 1972: * [0, 16384) : unclassified - lowest priority ! 1973: * [16384, 32768) : audio - highest priority ! 1974: * [32768, 49152) : whiteboard - medium priority ! 1975: * [49152, 65536) : video - low priority ! 1976: */ ! 1977: if (ip->ip_p == IPPROTO_UDP) { ! 1978: struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2)); ! 1979: switch (ntohs(udp->uh_dport) & 0xc000) { ! 1980: case 0x4000: ! 1981: prio = 70; ! 1982: break; ! 1983: case 0x8000: ! 1984: prio = 60; ! 1985: break; ! 1986: case 0xc000: ! 1987: prio = 55; ! 1988: break; ! 1989: default: ! 1990: prio = 50; ! 1991: break; ! 1992: } ! 1993: if (tbfdebug > 1) ! 1994: log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio); ! 1995: } else { ! 1996: prio = 50; ! 1997: } ! 1998: return prio; ! 1999: } ! 2000: ! 2001: /* ! 2002: * End of token bucket filter modifications ! 2003: */ ! 2004: ! 2005: int ! 2006: ip_rsvp_vif_init(so, sopt) ! 2007: struct socket *so; ! 2008: struct sockopt *sopt; ! 2009: { ! 2010: int error, i, s; ! 2011: ! 2012: if (rsvpdebug) ! 2013: printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n", ! 2014: so->so_type, so->so_proto->pr_protocol); ! 2015: ! 2016: if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) ! 2017: return EOPNOTSUPP; ! 2018: ! 2019: /* Check mbuf. */ ! 2020: error = sooptcopyin(sopt, &i, sizeof i, sizeof i); ! 2021: if (error) ! 2022: return (error); ! 2023: ! 2024: if (rsvpdebug) ! 2025: printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on); ! 2026: ! 2027: s = splnet(); ! 2028: ! 2029: /* Check vif. */ ! 2030: if (!legal_vif_num(i)) { ! 2031: splx(s); ! 2032: return EADDRNOTAVAIL; ! 2033: } ! 2034: ! 2035: /* Check if socket is available. */ ! 2036: if (viftable[i].v_rsvpd != NULL) { ! 2037: splx(s); ! 2038: return EADDRINUSE; ! 2039: } ! 2040: ! 2041: viftable[i].v_rsvpd = so; ! 2042: /* This may seem silly, but we need to be sure we don't over-increment ! 2043: * the RSVP counter, in case something slips up. ! 2044: */ ! 2045: if (!viftable[i].v_rsvp_on) { ! 2046: viftable[i].v_rsvp_on = 1; ! 2047: rsvp_on++; ! 2048: } ! 2049: ! 2050: splx(s); ! 2051: return 0; ! 2052: } ! 2053: ! 2054: int ! 2055: ip_rsvp_vif_done(so, sopt) ! 2056: struct socket *so; ! 2057: struct sockopt *sopt; ! 2058: { ! 2059: int error, i, s; ! 2060: ! 2061: if (rsvpdebug) ! 2062: printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n", ! 2063: so->so_type, so->so_proto->pr_protocol); ! 2064: ! 2065: if (so->so_type != SOCK_RAW || ! 2066: so->so_proto->pr_protocol != IPPROTO_RSVP) ! 2067: return EOPNOTSUPP; ! 2068: ! 2069: error = sooptcopyin(sopt, &i, sizeof i, sizeof i); ! 2070: if (error) ! 2071: return (error); ! 2072: ! 2073: s = splnet(); ! 2074: ! 2075: /* Check vif. */ ! 2076: if (!legal_vif_num(i)) { ! 2077: splx(s); ! 2078: return EADDRNOTAVAIL; ! 2079: } ! 2080: ! 2081: if (rsvpdebug) ! 2082: printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n", ! 2083: viftable[i].v_rsvpd, so); ! 2084: ! 2085: viftable[i].v_rsvpd = NULL; ! 2086: /* ! 2087: * This may seem silly, but we need to be sure we don't over-decrement ! 2088: * the RSVP counter, in case something slips up. ! 2089: */ ! 2090: if (viftable[i].v_rsvp_on) { ! 2091: viftable[i].v_rsvp_on = 0; ! 2092: rsvp_on--; ! 2093: } ! 2094: ! 2095: splx(s); ! 2096: return 0; ! 2097: } ! 2098: ! 2099: void ! 2100: ip_rsvp_force_done(so) ! 2101: struct socket *so; ! 2102: { ! 2103: int vifi; ! 2104: register int s; ! 2105: ! 2106: /* Don't bother if it is not the right type of socket. */ ! 2107: if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) ! 2108: return; ! 2109: ! 2110: s = splnet(); ! 2111: ! 2112: /* The socket may be attached to more than one vif...this ! 2113: * is perfectly legal. ! 2114: */ ! 2115: for (vifi = 0; vifi < numvifs; vifi++) { ! 2116: if (viftable[vifi].v_rsvpd == so) { ! 2117: viftable[vifi].v_rsvpd = NULL; ! 2118: /* This may seem silly, but we need to be sure we don't ! 2119: * over-decrement the RSVP counter, in case something slips up. ! 2120: */ ! 2121: if (viftable[vifi].v_rsvp_on) { ! 2122: viftable[vifi].v_rsvp_on = 0; ! 2123: rsvp_on--; ! 2124: } ! 2125: } ! 2126: } ! 2127: ! 2128: splx(s); ! 2129: return; ! 2130: } ! 2131: ! 2132: void ! 2133: rsvp_input(m, iphlen) ! 2134: struct mbuf *m; ! 2135: int iphlen; ! 2136: { ! 2137: int vifi; ! 2138: register struct ip *ip = mtod(m, struct ip *); ! 2139: static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET }; ! 2140: register int s; ! 2141: struct ifnet *ifp; ! 2142: ! 2143: if (rsvpdebug) ! 2144: printf("rsvp_input: rsvp_on %d\n",rsvp_on); ! 2145: ! 2146: /* Can still get packets with rsvp_on = 0 if there is a local member ! 2147: * of the group to which the RSVP packet is addressed. But in this ! 2148: * case we want to throw the packet away. ! 2149: */ ! 2150: if (!rsvp_on) { ! 2151: m_freem(m); ! 2152: return; ! 2153: } ! 2154: ! 2155: /* If the old-style non-vif-associated socket is set, then use ! 2156: * it and ignore the new ones. ! 2157: */ ! 2158: if (ip_rsvpd != NULL) { ! 2159: if (rsvpdebug) ! 2160: printf("rsvp_input: Sending packet up old-style socket\n"); ! 2161: rip_input(m, iphlen); ! 2162: return; ! 2163: } ! 2164: ! 2165: s = splnet(); ! 2166: ! 2167: if (rsvpdebug) ! 2168: printf("rsvp_input: check vifs\n"); ! 2169: ! 2170: #if DIAGNOSTIC ! 2171: if (!(m->m_flags & M_PKTHDR)) ! 2172: panic("rsvp_input no hdr"); ! 2173: #endif ! 2174: ! 2175: ifp = m->m_pkthdr.rcvif; ! 2176: /* Find which vif the packet arrived on. */ ! 2177: for (vifi = 0; vifi < numvifs; vifi++) { ! 2178: if (viftable[vifi].v_ifp == ifp) ! 2179: break; ! 2180: } ! 2181: ! 2182: if (vifi == numvifs) { ! 2183: /* Can't find vif packet arrived on. Drop packet. */ ! 2184: if (rsvpdebug) ! 2185: printf("rsvp_input: Can't find vif for packet...dropping it.\n"); ! 2186: m_freem(m); ! 2187: splx(s); ! 2188: return; ! 2189: } ! 2190: ! 2191: if (rsvpdebug) ! 2192: printf("rsvp_input: check socket\n"); ! 2193: ! 2194: if (viftable[vifi].v_rsvpd == NULL) { ! 2195: /* drop packet, since there is no specific socket for this ! 2196: * interface */ ! 2197: if (rsvpdebug) ! 2198: printf("rsvp_input: No socket defined for vif %d\n",vifi); ! 2199: m_freem(m); ! 2200: splx(s); ! 2201: return; ! 2202: } ! 2203: rsvp_src.sin_addr = ip->ip_src; ! 2204: ! 2205: if (rsvpdebug && m) ! 2206: printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n", ! 2207: m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv))); ! 2208: ! 2209: if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) ! 2210: if (rsvpdebug) ! 2211: printf("rsvp_input: Failed to append to socket\n"); ! 2212: else ! 2213: if (rsvpdebug) ! 2214: printf("rsvp_input: send packet up\n"); ! 2215: ! 2216: splx(s); ! 2217: } ! 2218: ! 2219: #if MROUTE_LKM ! 2220: #include <sys/conf.h> ! 2221: #include <sys/exec.h> ! 2222: #include <sys/sysent.h> ! 2223: #include <sys/lkm.h> ! 2224: ! 2225: MOD_MISC("ip_mroute_mod") ! 2226: ! 2227: static int ! 2228: ip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd) ! 2229: { ! 2230: int i; ! 2231: struct lkm_misc *args = lkmtp->private.lkm_misc; ! 2232: int err = 0; ! 2233: ! 2234: switch(cmd) { ! 2235: static int (*old_ip_mrouter_cmd)(); ! 2236: static int (*old_ip_mrouter_done)(); ! 2237: static int (*old_ip_mforward)(); ! 2238: static int (*old_mrt_ioctl)(); ! 2239: static void (*old_proto4_input)(); ! 2240: static int (*old_legal_vif_num)(); ! 2241: extern struct protosw inetsw[]; ! 2242: ! 2243: case LKM_E_LOAD: ! 2244: if(lkmexists(lkmtp) || ip_mrtproto) ! 2245: return(EEXIST); ! 2246: old_ip_mrouter_cmd = ip_mrouter_cmd; ! 2247: ip_mrouter_cmd = X_ip_mrouter_cmd; ! 2248: old_ip_mrouter_done = ip_mrouter_done; ! 2249: ip_mrouter_done = X_ip_mrouter_done; ! 2250: old_ip_mforward = ip_mforward; ! 2251: ip_mforward = X_ip_mforward; ! 2252: old_mrt_ioctl = mrt_ioctl; ! 2253: mrt_ioctl = X_mrt_ioctl; ! 2254: old_proto4_input = ip_protox[ENCAP_PROTO]->pr_input; ! 2255: ip_protox[ENCAP_PROTO]->pr_input = X_ipip_input; ! 2256: old_legal_vif_num = legal_vif_num; ! 2257: legal_vif_num = X_legal_vif_num; ! 2258: ip_mrtproto = IGMP_DVMRP; ! 2259: ! 2260: printf("\nIP multicast routing loaded\n"); ! 2261: break; ! 2262: ! 2263: case LKM_E_UNLOAD: ! 2264: if (ip_mrouter) ! 2265: return EINVAL; ! 2266: ! 2267: ip_mrouter_cmd = old_ip_mrouter_cmd; ! 2268: ip_mrouter_done = old_ip_mrouter_done; ! 2269: ip_mforward = old_ip_mforward; ! 2270: mrt_ioctl = old_mrt_ioctl; ! 2271: ip_protox[ENCAP_PROTO]->pr_input = old_proto4_input; ! 2272: legal_vif_num = old_legal_vif_num; ! 2273: ip_mrtproto = 0; ! 2274: break; ! 2275: ! 2276: default: ! 2277: err = EINVAL; ! 2278: break; ! 2279: } ! 2280: ! 2281: return(err); ! 2282: } ! 2283: ! 2284: int ! 2285: ip_mroute_mod(struct lkm_table *lkmtp, int cmd, int ver) { ! 2286: DISPATCH(lkmtp, cmd, ver, ip_mroute_mod_handle, ip_mroute_mod_handle, ! 2287: nosys); ! 2288: } ! 2289: ! 2290: #endif /* MROUTE_LKM */ ! 2291: #endif /* MROUTING */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.