ip_mroute.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:74k
开发平台:

MultiPlatform

  1. /* ip_mroute.c - internet multicast routing routines */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * IP multicast forwarding procedures
  6.  *
  7.  * Written by David Waitzman, BBN Labs, August 1988.
  8.  * Modified by Steve Deering, Stanford, February 1989.
  9.  * Modified by Mark J. Steiglitz, Stanford, May, 1991
  10.  * Modified by Van Jacobson, LBL, January 1993
  11.  * Modified by Ajit Thyagarajan, PARC, August 1993
  12.  * Modified by Bill Fenner, PARC, April 1995
  13.  *
  14.  * MROUTING Revision: 3.5
  15.  * $Id: ip_mroute.c,v 1.53 1999/01/18 02:06:57 fenner Exp $
  16.  */
  17. /*
  18. modification history
  19. --------------------
  20. 01i,16jul02,gls  removed include of igmpRouterLib.h
  21. 01h,25oct01,rae  _mCastRouteFwdHook must be IMPORT
  22. 01g,12oct01,rae  merge from truestack ver 01x, base 01e (SPRs 70325,
  23.                  69594, 69643, upgrade to MROUTE 3.5, etc).
  24. 01f,24sep01,gls  removed definition and use of __P() macro (SPR #28330)
  25. 01e,21aug98,n_s  fixed add_lgrp () call to MALLOC(). spr20595.
  26. 01d,08apr97,vin  added mCastRouteFwdHook deleted ip_mrouter.
  27. 01c,05dec96,vin  changed malloc(..) to MALLOC(..) to use only network buffers,
  28.  changed free(..) to FREE(..).
  29. 01b,22nov96,vin  added cluster support replaced m_gethdr(..) with mHdrClGet(..)
  30. 01a,03mar96,vin  created from BSD4.4 stuff.
  31. */
  32. #include "vxWorks.h"/* mandatory vxWorks header */
  33. #include "errno.h"
  34. #include "timers.h"
  35. #include "net/mbuf.h"
  36. #include "sys/socket.h"
  37. #include "sys/times.h"
  38. #include "net/socketvar.h"
  39. #include "net/protosw.h"
  40. #include "sys/times.h"
  41. #include "net/route.h"
  42. #include "net/mbuf.h"
  43. #include "netinet/in.h"
  44. #include "netinet/in_systm.h"
  45. #include "netinet/ip.h"
  46. #include "netinet/ip_var.h"
  47. #include "netinet/in_var.h"
  48. #include "netinet/igmp.h"
  49. #include "netinet/igmp_var.h"
  50. #include "memPartLib.h"
  51. #include "tickLib.h"
  52. #include "wdLib.h"
  53. #include "sockLib.h"
  54. #include "timers.h"
  55. #include "net/mbuf.h"
  56. #include "wdLib.h"
  57. #include "netinet/ip_mroute.h"
  58. #include "netinet/udp.h"
  59. #include "netLib.h"
  60. #include "net/systm.h"
  61. #ifdef WV_INSTRUMENTATION
  62. #ifdef INCLUDE_WVNET
  63. #include "wvNetLib.h"
  64. #endif
  65. #endif
  66. #ifdef VIRTUAL_STACK
  67. #include "netinet/vsLib.h"
  68. #include "netinet/vsIgmp.h"
  69. #include "netinet/vsMcast.h"
  70. #endif /* VIRTUAL_STACK */
  71. #ifndef NTOHL
  72. #if BYTE_ORDER != BIG_ENDIAN
  73. #define NTOHL(d) ((d) = ntohl((d)))
  74. #define NTOHS(d) ((d) = ntohs((u_short)(d)))
  75. #define HTONL(d) ((d) = htonl((d)))
  76. #define HTONS(d) ((d) = htons((u_short)(d)))
  77. #else
  78. #define NTOHL(d)
  79. #define NTOHS(d)
  80. #define HTONL(d)
  81. #define HTONS(d)
  82. #endif
  83. #endif
  84. /*
  85.  * Macros for handling bitmaps with one bit per virtual interface.
  86.  */
  87. #define ALL_VIFS (vifi_t)-1
  88. #define VIFM_SET(n, m) ((m) |= (1 << (n)))
  89. #define VIFM_CLR(n, m) ((m) &= ~(1 << (n)))
  90. #define VIFM_ISSET(n, m) ((m) & (1 << (n)))
  91. #define VIFM_CLRALL(m) ((m) = 0x00000000)
  92. #define VIFM_COPY(mfrom, mto) ((mto) = (mfrom))
  93. #define VIFM_SAME(m1, m2) ((m1) == (m2))
  94. /*
  95.  * Globals.  All but ip_mrouter and ip_mrtproto could be static,
  96.  * except for netstat or debugging purposes.
  97.  */
  98. #ifndef VIRTUAL_STACK
  99. extern USHORT ip_id;
  100. struct socket * ip_mrouter = 0;
  101. IMPORT FUNCPTR _mCastRouteFwdHook;
  102. FUNCPTR _pimCacheMissSendHook;
  103. static struct mrtstat mrtstat;
  104. /* table of mfc entries */
  105. static struct mfc *mfctable[MFCTBLSIZ];
  106. static u_char nexpire[MFCTBLSIZ];
  107. /* table of virtual interfaces */
  108. static struct vif viftable[MAXVIFS];
  109. static u_int mrtdebug = 0;   /* debug level  */
  110. static u_int   tbfdebug = 0;     /* tbf debug level  */
  111. struct mroute_timer_struct*  expire_upcalls_ch;
  112. /*
  113.  * Define the token bucket filter structures
  114.  * tbftable -> each vif has one of these for storing info 
  115.  */
  116. static struct tbf tbftable[MAXVIFS];
  117. /*
  118.  * 'Interfaces' associated with decapsulator (so we can tell
  119.  * packets that went through it from ones that get reflected
  120.  * by a broken gateway).  These interfaces are never linked into
  121.  * the system ifnet list & no routes point to them.  I.e., packets
  122.  * can't be sent this way.  They only exist as a placeholder for
  123.  * multicast source verification.
  124.  */
  125. static struct ifnet multicast_decap_if[MAXVIFS];
  126. /*
  127.  * Private variables.
  128.  */
  129. static vifi_t    numvifs = 0;
  130. static int have_encap_tunnel = 0;
  131. /*
  132.  * one-back cache used by ipip_input to locate a tunnel's vif
  133.  * given a datagram's src ip address.
  134.  */
  135. static u_long last_encap_src;
  136. static struct vif *last_encap_vif;
  137. int pim_assert;
  138. #endif /* VIRTUAL_STACK */
  139. #ifdef WV_INSTRUMENTATION
  140. #ifdef INCLUDE_WVNET
  141.     /* Set common fields of event identifiers for this module. */
  142. LOCAL UCHAR wvNetModuleId = WV_NET_IPMROUTE_MODULE; /* Value for ip_mroute.c */
  143. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  144. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  145. #endif    /* INCLUDE_WVNET */
  146. #endif
  147. /* prototype IP hdr for encapsulated packets */
  148. static struct ip multicast_encap_iphdr = {
  149. #if BYTE_ORDER == LITTLE_ENDIAN
  150. sizeof(struct ip) >> 2, IPVERSION,
  151. #else
  152. IPVERSION, sizeof(struct ip) >> 2,
  153. #endif
  154. 0, /* tos */
  155. sizeof(struct ip), /* total length */
  156. 0, /* id */
  157. 0, /* frag offset */
  158. ENCAP_TTL, ENCAP_PROTO,
  159. 0, /* checksum */
  160. };
  161. /* 
  162.  * The timer is a wrapper for watchdog timers... functionality from the net/3 release of the bsd code.  
  163.  */
  164. enum sopt_dir { SOPT_GET, SOPT_SET };
  165. struct sockopt {
  166. enum sopt_dir sopt_dir; /* is this a get or a set? */
  167. int sopt_level; /* second arg of [gs]etsockopt */
  168. int sopt_name; /* third arg of [gs]etsockopt */
  169. void   *sopt_val; /* fourth arg of [gs]etsockopt */
  170. size_t sopt_valsize; /* (almost) fifth arg of [gs]etsockopt */
  171. struct proc *sopt_p; /* calling process or null if kernel */
  172. };
  173. /* timer struct here enables */
  174. typedef struct mroute_timer_struct
  175. {
  176. WDOG_ID watchdog_id;
  177. VOIDFUNCPTR expire_routine;
  178. void* argument;
  179. } MROUTE_TIMER_STRUCT;
  180. static u_long X_ip_mcast_src __P((int vifi));
  181. static int X_ip_mforward __P(( struct mbuf *m, struct ifnet *ifp, struct ip *ip, struct ip_moptions *imo) );
  182. static int X_ip_mrouter_done __P((void));
  183. static int X_ip_mrouter_get __P((struct socket *so, struct sockopt *m));
  184. static int X_ip_mrouter_set __P((struct socket *so, struct sockopt *m));
  185. static int X_legal_vif_num __P((int vif));
  186. static int X_mrt_ioctl __P((int cmd, caddr_t data));
  187. static int get_sg_cnt(struct sioc_sg_req *);
  188. static int get_vif_cnt(struct sioc_vif_req *);
  189. static int ip_mrouter_init(struct socket *, int);
  190. static int add_vif(struct vifctl *);
  191. static int del_vif(vifi_t);
  192. static int add_mfc(struct mfcctl *);
  193. static int del_mfc(struct mfcctl *);
  194. static int set_assert(FUNCPTR);
  195. static int setDebug(int);
  196. static void expire_upcalls(void *);
  197. static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *,
  198.   vifi_t);
  199. static void phyint_send(struct ip *, struct vif *, struct mbuf *);
  200. static void encap_send(struct ip *, struct vif *, struct mbuf *);
  201. static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long);
  202. static void tbf_queue(struct vif *, struct mbuf *);
  203. static void tbf_process_q(struct vif *);
  204. static void tbf_reprocess_q(void *);
  205. static int tbf_dq_sel(struct vif *, struct ip *);
  206. static void tbf_send_packet(struct vif *, struct mbuf *);
  207. static void tbf_update_tokens(struct vif *);
  208. static int priority(struct vif *, struct ip *);
  209. void multiencap_decap(struct mbuf *);
  210. static void mRouteDumpMfctable();
  211. static BOOL oifListIsEmpty(struct mfc* rt);
  212. static int mRouteOifsAdd(struct mfc* rt, int oif, int ttl);
  213. static int mRouteOifsRemove(struct mfc* rt, int oif);
  214. static int mRouteGroupLoopRemove(struct mfc* rt, struct mfc* root);
  215. int (*ip_mrouter_done)(void) = X_ip_mrouter_done;
  216. u_long (*ip_mcast_src)(int) = X_ip_mcast_src;
  217. /* From other BSD code that has yet to be ported */
  218. static int
  219. sooptcopyin(struct sockopt *, void *, size_t, size_t);
  220. static int
  221. sooptcopyout(struct sockopt *, void *, size_t);
  222. static int
  223. if_allmulti(struct ifnet *, int);
  224. /* wrappers for timers in mroute */
  225. static void mRouteNetJobAdd(MROUTE_TIMER_STRUCT* p_timer_struct_object);
  226. static MROUTE_TIMER_STRUCT* mRouteTimeout(VOIDFUNCPTR expire_routine, void* argument, int number_of_ticks);
  227. static void mRouteUntimeOut(MROUTE_TIMER_STRUCT*  p_timer_struct);
  228. #define timeout mRouteTimeout
  229. #define untimeout mRouteUntimeOut
  230. /* vxWorks wrapper for tickGet */
  231. #define GET_TIME(t) t = tickGet(); 
  232. #ifdef  _WRS_VXWORKS_5_X
  233. #define mRouteNameToPort(ignore, both)  1
  234. #else
  235. #define mRouteNameToPort igmpNameToPort
  236. #endif
  237. #ifndef MRT_ALLOC
  238. #define MRT_ALLOC KHEAP_ALLOC
  239. #endif
  240. #ifndef MRT_FREE 
  241. #define MRT_FREE  KHEAP_FREE
  242. #endif
  243. /* wrapper for header length */
  244. #define MLEN (MSIZE - sizeof(M_BLK_HDR)) /* normal data len */
  245. #define MHLEN (MLEN - sizeof(M_PKT_HDR)) /* data len w/pkthdr */
  246. #define MRTDEBUG(printThis, string, param1, param2, param3, param4, param5, param6) 
  247.    {
  248.    if ( (_func_logMsg != NULL) && (printThis) )
  249.       (* _func_logMsg) (string, param1, param2, param3, param4, param5, param6);
  250.    }
  251. /* bsd function wrapper */
  252. #define MGETHDR(m, how, type) {
  253. m = mHdrClGet(M_DONTWAIT, MT_DATA, sizeof(*m), TRUE);
  254. }
  255. /*
  256.  * Hash function for a source, group entry
  257.  */
  258. #define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ 
  259. ((g) >> 20) ^ ((g) >> 10) ^ (g))
  260. /*
  261.  * Find a route for a given origin IP address and Multicast group address
  262.  * Type of service parameter to be added in the future!!!
  263.  */
  264. #define MFCFIND(o, g, rt) { 
  265. struct mfc *_rt = mfctable[MFCHASH(o,g)]; 
  266. rt = NULL; 
  267. ++mrtstat.mrts_mfc_lookups; 
  268. while (_rt) { 
  269. if ((_rt->mfc_origin.s_addr == o) && 
  270.     (_rt->mfc_mcastgrp.s_addr == g) && 
  271.     (_rt->mfc_stall == NULL)) { 
  272. rt = _rt; 
  273. break; 
  274. _rt = _rt->mfc_next; 
  275. if (rt == NULL) { 
  276. ++mrtstat.mrts_mfc_misses; 
  277. }
  278. /*
  279.  * Macros to compute elapsed time efficiently
  280.  * Borrowed from Van Jacobson's scheduling code
  281.  */
  282. #define TV_DELTA(a, b, delta)  delta = (a) - (b);
  283. #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && 
  284.       (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
  285. /* The net/3 code uses the X_ip_mrouter_set command to handle socket options in
  286.  * a slightly different format.  X_ip_mrouter_cmd reformats the parameters */
  287. int 
  288. X_ip_mrouter_cmd(cmd, so, m)
  289. int cmd;
  290. struct socket* so;
  291. struct mbuf* m;
  292. struct sockopt socket_option; 
  293. int result;
  294. socket_option.sopt_name = cmd;
  295. if (m == NULL) 
  296. {
  297. return (ERROR);
  298. }
  299. else 
  300. {
  301. socket_option.sopt_val = m->m_data; 
  302. socket_option.sopt_valsize = m->mBlkHdr.mLen; 
  303. }
  304. result = X_ip_mrouter_set(so, &socket_option); 
  305. return (0);
  306. }
  307. int ip_mrouter_cmd (int cmd, struct socket* so, struct mbuf* m) 
  308. {
  309. #ifdef WV_INSTRUMENTATION
  310. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  311.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 10, 12,
  312.                      WV_NETEVENT_IPMRT_START, so->so_fd, cmd)
  313. #endif  /* INCLUDE_WVNET */
  314. #endif
  315. return X_ip_mrouter_cmd(cmd, so, m);
  316. }
  317. /*
  318.  * Handle MRT setsockopt commands to modify the multicast routing tables.
  319.  */
  320. static int
  321. X_ip_mrouter_set(so, sopt)
  322. struct socket *so;
  323. struct sockopt *sopt;
  324. {
  325. int error, optval;
  326. vifi_t vifi;
  327. struct vifctl vifc;
  328. struct mfcctl mfc;
  329. error = 0;
  330. optval = 0;
  331. switch (sopt->sopt_name) {
  332. case MRT_INIT:
  333. error = sooptcopyin(sopt, &optval, sizeof (optval), 
  334.     sizeof (optval) );
  335. optval = (int)(sopt->sopt_val);
  336. if (error)
  337. break;
  338.             MRTDEBUG
  339.             (
  340.                 (mrtdebug &DEBUG_MFC),
  341.                 "MROUTE: IP_MROUTER received ip_mrouter init so=%p, optval=%i.n", 
  342.                 (int)so, 
  343.                 optval,3,4,5,6
  344.             );
  345. error = ip_mrouter_init(so, optval);
  346. break;
  347. case MRT_DONE:
  348.             MRTDEBUG
  349.             (
  350.                 (mrtdebug &DEBUG_MFC),
  351.     "MROUTE: IP_MROUTER received MRT_DONE.n",
  352.                 1,2,3,4,5,6
  353.             );
  354. error = ip_mrouter_done();
  355. break;
  356. case MRT_ADD_VIF:
  357. MRTDEBUG
  358.             (
  359.                 (mrtdebug &DEBUG_MFC),
  360.     "MROUTE: IP_MROUTER received MRT_ADD_VIF.n",
  361.                 1,2,3,4,5,6
  362.             );
  363. error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
  364. if (error)
  365. break;
  366. error = add_vif(&vifc);
  367. break;
  368. case MRT_DEL_VIF:
  369. MRTDEBUG
  370.             (
  371.                 (mrtdebug &DEBUG_MFC),
  372.      "MROUTE: IP_MROUTER received MRT_DEL_VIF.n",
  373.                 1,2,3,4,5,6
  374.             );
  375. error = sooptcopyin(sopt, &vifi, sizeof (vifi), sizeof (vifi));
  376. if (error)
  377. break;
  378. error = del_vif(vifi);
  379. break;
  380. case MRT_ADD_MFC:
  381. case MRT_DEL_MFC:
  382.             MRTDEBUG
  383.             (
  384.                 (mrtdebug &DEBUG_MFC),
  385.                 "MROUTE: IP_MROUTER received MRT_ADD/DEL_MFC.n",
  386.                 1,2,3,4,5,6
  387.             );
  388. error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc);
  389. if (error){
  390. MRTDEBUG(mrtdebug,"MROUTE: I am not dqing...  sooptcopyin error.n",1,2,3,4,5,6);
  391. break;
  392.                    }
  393. if (sopt->sopt_name == MRT_ADD_MFC)
  394. error = add_mfc(&mfc);
  395. else
  396. error = del_mfc(&mfc);
  397. break;
  398. case MRT_ASSERT:
  399. MRTDEBUG
  400.             (
  401.                 (mrtdebug &DEBUG_MFC),
  402.     "MROUTE: IP_MROUTER received MRT_ASSERT.n",
  403.                 1,2,3,4,5,6
  404.             );
  405. error = sooptcopyin(sopt, &optval, sizeof optval, 
  406.     sizeof optval);
  407. if (error)
  408. break;
  409. set_assert( (FUNCPTR) optval);
  410. break;
  411. case MRT_DEBUG:
  412. MRTDEBUG
  413.         (
  414.             (mrtdebug &DEBUG_MFC),
  415.             "MROUTE: IP_MROUTER received MRT_DEBUG.n",
  416.             1,2,3,4,5,6
  417.         );
  418. error = sooptcopyin(sopt, &optval, sizeof optval, 
  419.     sizeof optval);
  420. if (error)
  421. break;
  422. setDebug(optval);
  423. break;
  424. default:
  425. #ifdef WV_INSTRUMENTATION
  426. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  427.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 23, 3,
  428.                              WV_NETEVENT_IPMRT_BADCMD, sopt->sopt_name)
  429. #endif  /* INCLUDE_WVNET */
  430. #endif
  431. error = EOPNOTSUPP;
  432. break;
  433. }
  434. return (error);
  435. }
  436. int (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set;
  437. /*
  438.  * Handle MRT getsockopt commands
  439.  */
  440. static int
  441. X_ip_mrouter_get(so, sopt)
  442. struct socket *so;
  443. struct sockopt *sopt;
  444. {
  445. int error;
  446. static int version = 0x0305; /* !!! why is this here? XXX */
  447. switch (sopt->sopt_name) {
  448. case MRT_VERSION:
  449. error = sooptcopyout(sopt, &version, sizeof version);
  450. break;
  451. case MRT_ASSERT:
  452. error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
  453. break;
  454. default:
  455. error = EOPNOTSUPP;
  456. break;
  457. }
  458. MRTDEBUG
  459.     (
  460.         (mrtdebug),
  461.     "MROUTE: ip_mrouter_get returns %i error", 
  462.         error,2,3,4,5,6
  463.     );
  464. return (error);
  465. }
  466. int (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get;
  467. /*
  468.  * Handle ioctl commands to obtain information from the cache
  469.  */
  470. static int
  471. X_mrt_ioctl(cmd, data)
  472.     int cmd;
  473.     caddr_t data;
  474. {
  475.     int error = 0;
  476.     switch (cmd) {
  477. case (SIOCGETVIFCNT):
  478.     return (get_vif_cnt((struct sioc_vif_req *)data));
  479.     break;
  480. case (SIOCGETSGCNT):
  481.     return (get_sg_cnt((struct sioc_sg_req *)data));
  482.     break;
  483. default:
  484.     return (EINVAL);
  485.     break;
  486.     }
  487.     return error;
  488. }
  489. int (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl;
  490. /*
  491.  * returns the packet, byte, rpf-failure count for the source group provided
  492.  */
  493. static int
  494. get_sg_cnt(req)
  495.     struct sioc_sg_req *req;
  496. {
  497.     struct mfc *rt;
  498.     int s;
  499.     s = splnet();
  500.     MFCFIND(req->src.s_addr, req->grp.s_addr, rt);
  501.     splx(s);
  502.     if (rt != NULL) {
  503. req->pktcnt = rt->mfc_pkt_cnt;
  504. req->bytecnt = rt->mfc_byte_cnt;
  505. req->wrong_if = rt->mfc_wrong_if;
  506.     } else
  507. req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
  508.     return 0;
  509. }
  510. /*
  511.  * returns the input and output packet and byte counts on the vif provided
  512.  */
  513. static int
  514. get_vif_cnt(req)
  515.     struct sioc_vif_req *req;
  516. {
  517.     vifi_t vifi = req->vifi;
  518.     if (vifi >= numvifs) return EINVAL;
  519.     req->icount = viftable[vifi].v_pkt_in;
  520.     req->ocount = viftable[vifi].v_pkt_out;
  521.     req->ibytes = viftable[vifi].v_bytes_in;
  522.     req->obytes = viftable[vifi].v_bytes_out;
  523.     return 0;
  524. }
  525. /*
  526.  * Enable multicast routing
  527.  */
  528. static int
  529. ip_mrouter_init(so, version)
  530. struct socket *so;
  531. int version;
  532. {
  533.     if (so == NULL)
  534.         return (EINVAL);
  535.     MRTDEBUG
  536.         (
  537.             (mrtdebug),
  538.             "MROUTE: ip_mrouter_init: so_type = %d, pr_protocol = %dn",
  539. so->so_type, 
  540.             so->so_proto->pr_protocol,
  541.             3,4,5,6
  542.         );
  543. if ( _mCastRouteFwdHook != NULL) /* if already installed */
  544.             return (EADDRINUSE);
  545. else
  546. _mCastRouteFwdHook = X_ip_mforward;  /* forwarding func ptr */
  547.     if (so->so_type != SOCK_RAW ||
  548. so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP;
  549.     if (ip_mrouter != 0) 
  550. {
  551. return EADDRINUSE;
  552. }
  553.     ip_mrouter = (struct socket*) so->so_fd;
  554.     bzero((caddr_t)mfctable, sizeof(mfctable));
  555.     bzero((caddr_t)nexpire, sizeof(nexpire));
  556.     pim_assert = 0;
  557.     expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
  558.     MRTDEBUG
  559.         (
  560.             (mrtdebug),
  561.     "MROUTE: ip_mrouter_init returning success.n",
  562.             1,2,3,4,5,6
  563.         );
  564.     return 0;
  565. }
  566. /*
  567.  * Disable multicast routing
  568.  */
  569. static int
  570. X_ip_mrouter_done()
  571. {
  572.     vifi_t vifi;
  573.     int i;
  574.     struct ifnet *ifp;
  575.     struct ifreq ifr;
  576.     struct mfc *rt;
  577.     struct rtdetq *rte;
  578.     int s;
  579.     s = splnet();
  580.     /*
  581.      * For each phyint in use, disable promiscuous reception of all IP
  582.      * multicasts.
  583.      */
  584.     for (vifi = 0; vifi < numvifs; vifi++) {
  585. if (viftable[vifi].v_lcl_addr.s_addr != 0 &&
  586.     !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
  587.     ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
  588.     ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr
  589. = INADDR_ANY;
  590.     ifp = viftable[vifi].v_ifp;
  591.     if_allmulti(ifp, 0);
  592. }
  593.     }
  594.     bzero((caddr_t)tbftable, sizeof(tbftable));
  595.     bzero((caddr_t)viftable, sizeof(viftable));
  596.     numvifs = 0;
  597.     pim_assert = 0;
  598.     untimeout(expire_upcalls_ch);
  599.     expire_upcalls_ch = 0;
  600.     _mCastRouteFwdHook = NULL;
  601.     _pimCacheMissSendHook = NULL;
  602.     /*
  603.      * Free all multicast forwarding cache entries.
  604.      */
  605.     for (i = 0; i < MFCTBLSIZ; i++) {
  606. for (rt = mfctable[i]; rt != NULL; ) {
  607.     struct mfc *nr = rt->mfc_next;
  608.     for (rte = rt->mfc_stall; rte != NULL; ) {
  609. struct rtdetq *n = rte->next;
  610. m_freem(rte->m);
  611. MRT_FREE((char*) rte);
  612. rte = n;
  613.     }
  614.     MRT_FREE((char*) rt);
  615.     rt = nr;
  616. }
  617.     }
  618.     bzero((caddr_t)mfctable, sizeof(mfctable));
  619.     /*
  620.      * Reset de-encapsulation cache
  621.      */
  622.     last_encap_src = 0;
  623.     last_encap_vif = NULL;
  624.     have_encap_tunnel = 0;
  625.  
  626.     ip_mrouter = 0;
  627.     splx(s);
  628.     MRTDEBUG
  629.         (
  630.             (mrtdebug),
  631.     "MROUTE: ip_mrouter_donen",
  632.             1,2,3,4,5,6
  633.         );
  634.     return 0;
  635. }
  636. /*
  637.  * Set PIM assert processing global
  638.  */
  639. static int
  640. set_assert(FUNCPTR i)
  641. {
  642.     pim_assert = (int)i;
  643. _pimCacheMissSendHook = (FUNCPTR)i;
  644.     return 0;
  645. }
  646. /*
  647.  * Sets mroute debug processing global
  648.  */
  649. static int
  650. setDebug( int i)
  651. {
  652.     mrtdebug = i;
  653.     return 0;
  654. }
  655. /*
  656.  * Add a vif to the vif table
  657.  */
  658. static int
  659. add_vif(vifcp)
  660.     struct vifctl *vifcp;
  661. {
  662.     struct vif *vifp = viftable + vifcp->vifc_vifi;
  663.     static struct sockaddr_in sin = {sizeof sin, AF_INET};
  664.     struct ifaddr *ifa;
  665.     struct ifnet *ifp;
  666.     int error, s;
  667.     struct tbf *v_tbf = tbftable + vifcp->vifc_vifi;
  668.     if (vifcp->vifc_vifi >= MAXVIFS)
  669.         {
  670. #ifdef WV_INSTRUMENTATION
  671. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  672.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 24, 4,
  673.                          WV_NETEVENT_ADDVIF_BADINDEX,
  674.                          vifcp->vifc_vifi, MAXVIFS)
  675. #endif  /* INCLUDE_WVNET */
  676. #endif
  677.         return EINVAL;
  678.         }
  679.     if (vifp->v_lcl_addr.s_addr != 0)
  680.         {
  681. #ifdef WV_INSTRUMENTATION
  682. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  683.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 25, 5,
  684.                          WV_NETEVENT_ADDVIF_BADENTRY,
  685.                          vifcp->vifc_vifi, vifp->v_lcl_addr.s_addr)
  686. #endif  /* INCLUDE_WVNET */
  687. #endif
  688.         return EADDRINUSE;
  689.         }
  690.     /* Find the interface with an address in AF_INET family */
  691.     sin.sin_addr = vifcp->vifc_lcl_addr;
  692.     ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
  693.     if (ifa == 0)
  694.         {
  695. #ifdef WV_INSTRUMENTATION
  696. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  697.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 26, 6,
  698.                          WV_NETEVENT_ADDVIF_SEARCHFAIL,
  699.                          vifcp->vifc_vifi, sin.sin_addr.s_addr)
  700. #endif  /* INCLUDE_WVNET */
  701. #endif
  702.         return EADDRNOTAVAIL;
  703.         }
  704.     ifp = ifa->ifa_ifp;
  705.     if (vifcp->vifc_flags & VIFF_TUNNEL) {
  706. if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) {
  707. /*
  708.  * An encapsulating tunnel is wanted.  Tell ipip_input() to
  709.  * start paying attention to encapsulated packets.
  710.  */
  711. if (have_encap_tunnel == 0) {
  712. have_encap_tunnel = 1;
  713. for (s = 0; s < MAXVIFS; ++s) {
  714. multicast_decap_if[s].if_name = "mdecap";
  715. multicast_decap_if[s].if_unit = s;
  716. }
  717. }
  718. /*
  719.  * Set interface to fake encapsulator interface
  720.  */
  721. ifp = &multicast_decap_if[vifcp->vifc_vifi];
  722. /*
  723.  * Prepare cached route entry
  724.  */
  725. bzero((char*)&vifp->v_route, sizeof(vifp->v_route));
  726. } else {
  727.         MRTDEBUG
  728.         (
  729.             (mrtdebug),
  730.     "MROUTE: source routed tunnels not supportedn",
  731.             1,2,3,4,5,6
  732.         );
  733.     return EOPNOTSUPP;
  734. }
  735.     } else {
  736. /* Make sure the interface supports multicast */
  737. if ((ifp->if_flags & IFF_MULTICAST) == 0)
  738.             {
  739. #ifdef WV_INSTRUMENTATION
  740. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  741.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 27, 7,
  742.                              WV_NETEVENT_ADDVIF_BADFLAGS,
  743.                              vifcp->vifc_vifi, ifp)
  744. #endif  /* INCLUDE_WVNET */
  745. #endif
  746.     return EOPNOTSUPP;
  747.             }
  748. /* Enable promiscuous reception of all IP multicasts from the if */
  749. s = splnet();
  750. error = if_allmulti(ifp, 1);/* Many wrs drivers don't support this */
  751. splx(s);
  752. if (error)
  753.     return error;
  754.     }
  755.     s = splnet();
  756.     /* define parameters for the tbf structure */
  757.     vifp->v_tbf = v_tbf;
  758.     GET_TIME(vifp->v_tbf->tbf_last_pkt_t);
  759.     vifp->v_tbf->tbf_n_tok = 0;
  760.     vifp->v_tbf->tbf_q_len = 0;
  761.     vifp->v_tbf->tbf_max_q_len = MAXQSIZE;
  762.     vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL;
  763.     vifp->v_flags     = vifcp->vifc_flags;
  764.     vifp->v_threshold = vifcp->vifc_threshold;
  765.     vifp->v_lcl_addr  = vifcp->vifc_lcl_addr;
  766.     vifp->v_rmt_addr  = vifcp->vifc_rmt_addr;
  767.     vifp->v_ifp       = ifp;
  768.     /* scaling up here allows division by 1024 in critical code */
  769.     vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000;
  770.     /* initialize per vif pkt counters */
  771.     vifp->v_pkt_in    = 0;
  772.     vifp->v_pkt_out   = 0;
  773.     vifp->v_bytes_in  = 0;
  774.     vifp->v_bytes_out = 0;
  775.     splx(s);
  776.     /* Adjust numvifs up if the vifi is higher than numvifs */
  777.     if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
  778.     MRTDEBUG
  779.     (
  780.         (mrtdebug),
  781. "MROUTE: add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %dn",
  782.         vifcp->vifc_vifi, 
  783. (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr),
  784.         (vifcp->vifc_flags & VIFF_TUNNEL) ? (int)"rmtaddr" : (int)"mask",
  785.         (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr),
  786.         (int)vifcp->vifc_threshold, 
  787.         1
  788.     );    
  789.     return 0;
  790. }
  791. /*
  792.  * Delete a vif from the vif table
  793.  */
  794. static int
  795. del_vif(vifi)
  796. vifi_t vifi;
  797. {
  798.     struct vif *vifp = &viftable[vifi];
  799.     struct mbuf *m;
  800.     struct ifnet *ifp;
  801.     struct ifreq ifr;
  802.     int s;
  803.     if (vifi >= numvifs)
  804.         {
  805. #ifdef WV_INSTRUMENTATION
  806. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  807.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 28, 8,
  808.                          WV_NETEVENT_DELVIF_BADINDEX, vifi, numvifs)
  809. #endif  /* INCLUDE_WVNET */
  810. #endif
  811.         return EINVAL;
  812.         }
  813.     if (vifp->v_lcl_addr.s_addr == 0)
  814.         {
  815. #ifdef WV_INSTRUMENTATION
  816. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  817.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 29, 9,
  818.                          WV_NETEVENT_DELVIF_BADENTRY, vifi)
  819. #endif  /* INCLUDE_WVNET */
  820. #endif
  821.         return EADDRNOTAVAIL;
  822.         }
  823.     s = splnet();
  824.     if (!(vifp->v_flags & VIFF_TUNNEL)) {
  825. ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
  826. ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY;
  827. ifp = vifp->v_ifp;
  828. if_allmulti(ifp, 0);
  829.     }
  830.     if (vifp == last_encap_vif) {
  831. last_encap_vif = 0;
  832. last_encap_src = 0;
  833.     }
  834.     /*
  835.      * Free packets queued at the interface
  836.      */
  837.     while (vifp->v_tbf->tbf_q) {
  838. m = vifp->v_tbf->tbf_q;
  839. vifp->v_tbf->tbf_q = m->m_act;
  840. m_freem(m);
  841.     }
  842.     bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf)));
  843.     bzero((caddr_t)vifp, sizeof (*vifp));
  844.     MRTDEBUG
  845.     (
  846.         (mrtdebug),
  847.         "MROUTE: del_vif %d, numvifs %dn", 
  848.         vifi, 
  849.         numvifs,
  850.         3,4,5,6
  851.     );
  852.     /* Adjust numvifs down */
  853.     for (vifi = numvifs; vifi > 0; vifi--)
  854. if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break;
  855.     numvifs = vifi;
  856.     splx(s);
  857.     return 0;
  858. }
  859. /* 
  860.  * modifies the outgoing viftable for an s,g entry
  861.  */
  862. static int 
  863. mRouteOifsAdd
  864.     (
  865.     struct mfc* rt, 
  866.     int oif, 
  867.     int ttl
  868.     )
  869. {
  870. struct mfc* probe;
  871. if(rt->mfc_root_rt== NULL)
  872. return (ERROR);
  873. rt->mfc_root_rt->mfc_ttls[oif] = ttl;
  874. probe = rt->mfc_root_rt;
  875.     while (probe->mfc_next_g != probe->mfc_root_rt)
  876.     {
  877.     probe = probe->mfc_next_g;
  878. probe->mfc_ttls[oif] = ttl;
  879.     }
  880. return (OK);
  881. }
  882.  
  883. /*
  884.  * Add an mfc entry
  885.  */
  886. static int
  887. add_mfc(mfccp)
  888.     struct mfcctl *mfccp;
  889. {
  890.     struct mfc *rt;
  891.     struct mfc *root_rt;
  892.     u_long hash;
  893.     struct rtdetq *rte;
  894.     u_short nstl;
  895.     int s;
  896.     int i;
  897. rt = NULL;
  898.     MRTDEBUG
  899.     (
  900.         (mrtdebug & DEBUG_MFC),
  901.         "MROUTE: add_mfc received o %p g %p p %pn",
  902.         ntohl(mfccp->mfcc_origin.s_addr),
  903.         ntohl(mfccp->mfcc_mcastgrp.s_addr),
  904. (u_long)mfccp->mfcc_parent,
  905.         4,5,6
  906.     );
  907.     MRTDEBUG
  908.     (
  909.         (mrtdebug & DEBUG_MFC),
  910.         "MROUTE: add_mfc ttls%i%i%i%i%in.",
  911.         mfccp->mfcc_ttls[0],
  912.         mfccp->mfcc_ttls[1],
  913.         mfccp->mfcc_ttls[2],
  914.         mfccp->mfcc_ttls[3],
  915.         mfccp->mfcc_ttls[4],
  916.         6
  917.     );
  918.     MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt);
  919.     /* If an entry already exists, just update the fields */
  920.     if (rt) 
  921. {
  922.         MRTDEBUG
  923.         (
  924.             (mrtdebug & DEBUG_MFC),
  925. "MROUTE: add_mfc update o %lx g %lx p %xn",
  926.             (u_long)ntohl(mfccp->mfcc_origin.s_addr),
  927.             (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
  928. mfccp->mfcc_parent,
  929.             4,5,6
  930.         );
  931. s = splnet();
  932. if (mfccp->mfcc_origin.s_addr == 0) 
  933. {/* updating a 0,g entry updates all s,g entries for that interface*/
  934. rt->mfc_parent = mfccp->mfcc_parent;
  935.             MRTDEBUG
  936.             (
  937.                 (mrtdebug & DEBUG_FORWARD),
  938. "MROUTE: add_mfc updating all rts %p p %x, val=%xn",
  939.                 ntohl(mfccp->mfcc_mcastgrp.s_addr),
  940.                 rt->mfc_parent, 
  941.                 viftable[rt->mfc_parent].v_threshold,
  942.                 4,5,6
  943.             );
  944. if (mfccp->mfcc_ttls[rt->mfc_parent] != 0)
  945. mRouteOifsAdd(rt, 
  946. rt->mfc_parent, 
  947. viftable[rt->mfc_parent].v_threshold);
  948. else
  949. mRouteOifsAdd(rt, rt->mfc_parent, 0);
  950. }
  951. else
  952. {
  953. for (i=0; i<numvifs; i++)
  954. {/* an s,g add/update doesn't affect other entries*/
  955. rt->mfc_parent = mfccp->mfcc_parent;
  956.     MRTDEBUG
  957.                 (
  958.                     (mrtdebug & DEBUG_FORWARD),
  959. "MROUTE: add_mfc updating rts o=%p g=%p p %x, val=%xn",
  960. ntohl(rt->mfc_origin.s_addr),
  961. ntohl(rt->mfc_mcastgrp.s_addr),
  962. rt->mfc_parent, 
  963.                     viftable[rt->mfc_parent].v_threshold,
  964.                     5,6
  965.                 );
  966. rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
  967. }
  968. rt->mfc_notify = mfccp->mfcc_notify;
  969. }
  970.         MRTDEBUG
  971.         (
  972.             (mrtdebug & DEBUG_MFC),
  973. "MROUTE: add_mfc updated o %p g%p p%p, root_rt=%p.n",
  974. ntohl(mfccp->mfcc_origin.s_addr),
  975. ntohl(mfccp->mfcc_mcastgrp.s_addr),
  976. (u_long)rt->mfc_parent, 
  977. (u_long)rt->mfc_root_rt,
  978.             5,6
  979.         );
  980. splx(s);
  981. return 0;
  982.     }
  983.     /* 
  984.      * Find the entry for which the upcall was made and update
  985.      */
  986.     s = splnet();
  987.     hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
  988.     for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) 
  989. {
  990. if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
  991. (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
  992. (rt->mfc_stall != NULL)) 
  993. {/* looking for entry with packet waiting on it */
  994. if (nstl++)
  995. {
  996.     MRTDEBUG
  997.                 (
  998.                     (mrtdebug), 
  999.     "MROUTE: add_mfc multiple kernel entries 
  1000.                     o %p g %p p %x dbx %pn",
  1001. ntohl(mfccp->mfcc_origin.s_addr),
  1002. ntohl(mfccp->mfcc_mcastgrp.s_addr),
  1003. mfccp->mfcc_parent, 
  1004.                     (int)rt->mfc_stall,
  1005.                     5,6
  1006.                 );
  1007. }
  1008.             MRTDEBUG
  1009.             (
  1010.                 (mrtdebug & DEBUG_MFC), 
  1011. "MROUTE: add_mfc o %p g %p p %x dbg %pn",
  1012. ntohl(mfccp->mfcc_origin.s_addr),
  1013. ntohl(mfccp->mfcc_mcastgrp.s_addr),
  1014. mfccp->mfcc_parent, 
  1015.                 (int)rt->mfc_stall,
  1016.                 5,6
  1017.             );
  1018. /* copy the information into rt entry */
  1019. rt->mfc_origin     = mfccp->mfcc_origin;
  1020. rt->mfc_mcastgrp   = mfccp->mfcc_mcastgrp;
  1021. rt->mfc_notify   = mfccp->mfcc_notify;
  1022. if (! (mfccp->mfcc_parent > numvifs) ) /* can't be less, it's a USHORT value */
  1023. rt->mfc_parent = mfccp->mfcc_parent;
  1024. if (mfccp->mfcc_origin.s_addr == 0)
  1025. {
  1026.          MRTDEBUG
  1027.                 (
  1028.                     (mrtdebug & DEBUG_FORWARD),
  1029. "MROUTE: add_mfc updating rts o=%p g=%p p %x, val=%xn",
  1030.                     ntohl(rt->mfc_origin.s_addr),
  1031. ntohl(rt->mfc_mcastgrp.s_addr),
  1032. rt->mfc_parent, 
  1033.                     viftable[rt->mfc_parent].v_threshold,
  1034.                     5,6
  1035.                 );
  1036. mRouteOifsAdd(rt, rt->mfc_parent, viftable[rt->mfc_parent].v_threshold);
  1037. }/* update all routes for *,g entry add */
  1038. else for (i = 0; i < numvifs; i++)
  1039. {
  1040. if ( (mfccp->mfcc_origin.s_addr != 0)
  1041. &&(mfccp->mfcc_ttls[i] != 0)
  1042. )
  1043. {
  1044.                     MRTDEBUG
  1045.                     (
  1046.                         (mrtdebug & DEBUG_FORWARD),
  1047. "MROUTE: add_mfc changing rt %p,%p vif %i to %in",
  1048.                         ntohl(rt->mfc_origin.s_addr),
  1049. ntohl(rt->mfc_mcastgrp.s_addr),
  1050. i, 
  1051.                         viftable[i].v_threshold,
  1052.                         5,6
  1053.                     );
  1054. rt->mfc_ttls[i] = viftable[i].v_threshold;
  1055. }/* copy the oif list for s,g entries */
  1056. }
  1057. /* initialize pkt counters per src-grp */
  1058. rt->mfc_pkt_cnt    = 0;
  1059. rt->mfc_byte_cnt   = 0;
  1060. rt->mfc_wrong_if   = 0;
  1061. rt->mfc_last_assert = 0;
  1062.             rt->mfc_last_assert = 0;
  1063. rt->mfc_expire = 0; /* Don't clean this guy up */
  1064. nexpire[hash]--;
  1065. /* free packets Qed at the end of this entry */
  1066. for (rte = rt->mfc_stall; rte != NULL; ) 
  1067. {
  1068. struct rtdetq *n = rte->next;
  1069.     MRTDEBUG
  1070.                 (
  1071.                     (mrtdebug & DEBUG_FORWARD),
  1072. "MROUTE: add_mfc add_mfc calls ip_mdq.n",
  1073.                     1,2,3,4,5,6
  1074.                 );
  1075. ip_mdq(rte->m, rte->ifp, rt, -1);
  1076.                 MRTDEBUG
  1077.                 (
  1078.                     (mrtdebug & DEBUG_FORWARD),
  1079. "MROUTE: add_mfc add_mfc done calling ip_mdq.n",
  1080.                     1,2,3,4,5,6
  1081.                 );
  1082. m_freem(rte->m);
  1083. MRT_FREE((char*) rte);
  1084. rte = n;
  1085. }
  1086. rt->mfc_stall = NULL;
  1087. }/* dQing stall entries */
  1088.     }/* for mfctable[hash] loop */
  1089.     /*
  1090.      * It is possible that an entry is being inserted without an upcall
  1091.  * This would be primarily found in s,g joins from an overlying protcol
  1092.  * e.g. PIM
  1093.      */
  1094.     if (nstl == 0) 
  1095. {
  1096.         MRTDEBUG
  1097.         (
  1098.             (mrtdebug & DEBUG_MFC),
  1099.     "MROUTE: add_mfc no upcall h %lu o %lx g %lx p %xn",
  1100.             hash, 
  1101.             (u_long)ntohl(mfccp->mfcc_origin.s_addr),
  1102. (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
  1103. mfccp->mfcc_parent,
  1104.             5,6
  1105.         );
  1106. for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) 
  1107. {
  1108. if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
  1109. (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
  1110. for (i = 0; i < numvifs; i++)
  1111. {/* if the entry exists, copy the oiflist */
  1112. if (mfccp->mfcc_ttls[i] != 0)
  1113. rt->mfc_ttls[i] = viftable[i].v_threshold;
  1114. else 
  1115. rt->mfc_ttls[i] = 0;
  1116. }
  1117. /* initialize pkt counters per src-grp */
  1118. rt->mfc_pkt_cnt    = 0;
  1119. rt->mfc_byte_cnt   = 0;
  1120. rt->mfc_wrong_if   = 0;
  1121. rt->mfc_last_assert = 0;
  1122.             rt->mfc_last_assert = 0;
  1123. if (rt->mfc_expire)
  1124. nexpire[hash]--;
  1125. rt->mfc_expire    = 0;
  1126. }
  1127. }
  1128. if (rt == NULL) 
  1129. {
  1130. /* no upcall, so make a new entry */
  1131. rt = MRT_ALLOC(sizeof(struct mfc));
  1132. if (rt == NULL) {
  1133. splx(s);
  1134. #ifdef WV_INSTRUMENTATION
  1135. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  1136.         WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 17, 1,
  1137.                          WV_NETEVENT_ADDMRT_NOBUFS)
  1138. #endif  /* INCLUDE_WVNET */
  1139. #endif
  1140. return ENOBUFS;
  1141. }
  1142. rt->mfc_notify = 0;
  1143. rt->mfc_origin     = mfccp->mfcc_origin;
  1144. rt->mfc_mcastgrp   = mfccp->mfcc_mcastgrp;
  1145. /* link into hash chain now so the search for the root_rt will work */
  1146. rt->mfc_next = mfctable[hash];
  1147. mfctable[hash] = rt;
  1148. for (i = 0; i < numvifs; i++)
  1149. {
  1150. if (mfccp->mfcc_ttls[i] != 0)
  1151. rt->mfc_ttls[i] = viftable[i].v_threshold;
  1152. else 
  1153. rt->mfc_ttls[i] = 0;
  1154. }
  1155. /* find the *,g entry and link in */
  1156. MFCFIND(0, mfccp->mfcc_mcastgrp.s_addr, root_rt);
  1157. if (root_rt == NULL)
  1158. {
  1159. root_rt = MRT_ALLOC(sizeof(struct mfc));
  1160. if (root_rt == NULL) 
  1161. {
  1162. MRT_FREE((char*) rt);
  1163. splx(s);
  1164. return ENOBUFS;
  1165. }
  1166. root_rt->mfc_notify = 0;
  1167. /* inset NULL entry at head of hash chain */
  1168. root_rt->mfc_origin.s_addr     = 0;
  1169. root_rt->mfc_mcastgrp   = mfccp->mfcc_mcastgrp;
  1170. root_rt->mfc_parent     = 0;
  1171. for (i = 0; i < numvifs; i++)
  1172. {
  1173. root_rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
  1174. }
  1175. /* initialize pkt counters per src-grp */
  1176. root_rt->mfc_pkt_cnt    = 0;
  1177. root_rt->mfc_byte_cnt   = 0;
  1178. root_rt->mfc_wrong_if   = 0;
  1179. root_rt->mfc_last_assert = 0;
  1180.                 rt->mfc_last_assert = 0;
  1181. root_rt->mfc_expire     = 0;
  1182. root_rt->mfc_stall      = NULL;
  1183. /* link *,g into table */
  1184. root_rt->mfc_next = 
  1185. mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr)];
  1186. mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr)] = root_rt;
  1187. root_rt->mfc_next_g = root_rt; /* next group in same chain */
  1188. root_rt->mfc_root_rt = root_rt; /* 0,g entry in hash table, itself in this case*/
  1189. }
  1190. rt->mfc_root_rt = root_rt;
  1191. /* insert into front of group chain*/
  1192. rt->mfc_next_g = root_rt->mfc_next_g;
  1193. root_rt->mfc_next_g = rt;
  1194.      if (!(mfccp->mfcc_parent > numvifs) )/* can't be less than 0, it's a USHORT */
  1195. rt->mfc_parent = mfccp->mfcc_parent;
  1196. /* take care of the details before you alter the forwarding state.  */
  1197. rt->mfc_pkt_cnt    = 0;
  1198. rt->mfc_byte_cnt   = 0;
  1199. rt->mfc_wrong_if   = 0;
  1200. rt->mfc_last_assert = 0;
  1201.             rt->mfc_last_assert = 0;
  1202. rt->mfc_expire     = 0;
  1203. rt->mfc_stall      = NULL;
  1204. }/* rt == null */
  1205.     }/* nstl == 0 */
  1206.     splx(s);
  1207.     return 0;
  1208. }
  1209. /* 
  1210.  * Resets the passed oif to 0 for a chain
  1211.  */
  1212. static int 
  1213. mRouteOifsRemove
  1214.     (
  1215.     struct mfc* rt, 
  1216.     int oif
  1217.     )
  1218. {
  1219. struct mfc* probe;
  1220. if (rt == NULL)
  1221. return (EINVAL);
  1222. rt->mfc_root_rt->mfc_ttls[oif] = 0;
  1223. probe = rt->mfc_root_rt;
  1224.     
  1225.     while (probe->mfc_next_g != probe->mfc_root_rt)
  1226.     {
  1227.     probe = probe->mfc_next_g;
  1228. probe->mfc_ttls[oif] = 0;
  1229.     }
  1230. return (OK);
  1231. }
  1232. /* 
  1233.  * Removes from the chain of all g entries
  1234.  */
  1235. static int
  1236. mRouteGroupLoopRemove
  1237.     (
  1238.     struct mfc* rt, 
  1239.     struct mfc* root
  1240.     )
  1241. {   
  1242. struct mfc* probe;
  1243. probe = root;
  1244.     while (probe->mfc_next_g != probe->mfc_root_rt)
  1245.     {
  1246.     probe = probe->mfc_next_g ;
  1247. if (probe->mfc_next_g == rt)
  1248. break;
  1249.     }
  1250. if (probe->mfc_next_g == rt)
  1251. {
  1252. probe->mfc_next_g = rt->mfc_next_g ;
  1253. }
  1254. return (OK);
  1255. }
  1256.  
  1257. /*
  1258.  * Delete an mfc entry
  1259.  */
  1260. static int
  1261. del_mfc(mfccp)
  1262.     struct mfcctl *mfccp;
  1263. {
  1264.     struct in_addr  origin;
  1265.     struct in_addr  mcastgrp;
  1266.     struct mfc  *rt;
  1267.     struct mfc  *root;
  1268. struct mfc   **nptr;
  1269.     u_long  hash;
  1270.     int s;
  1271.     origin = mfccp->mfcc_origin;
  1272.     mcastgrp = mfccp->mfcc_mcastgrp;
  1273.     hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
  1274.     MRTDEBUG
  1275.     (
  1276.         (mrtdebug & DEBUG_MFC),
  1277. "MROUTE: del_mfc orig %lx mcastgrp %lxn",
  1278.         (u_long)ntohl(origin.s_addr), 
  1279.         (u_long)ntohl(mcastgrp.s_addr),
  1280.         3,4,5,6
  1281.     );
  1282.     s = splnet();
  1283.     nptr = &mfctable[hash];
  1284.     while ((rt = *nptr) != NULL) 
  1285. {
  1286. if (origin.s_addr == rt->mfc_origin.s_addr &&
  1287. mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
  1288. rt->mfc_stall == NULL)
  1289. break;
  1290. nptr = &rt->mfc_next;
  1291.     }
  1292.     if (rt == NULL) 
  1293. {
  1294. splx(s);
  1295. return EADDRNOTAVAIL;
  1296.     }
  1297. /* if *,g remove, remove all oifs from group chain */
  1298. if (rt->mfc_origin.s_addr == 0)
  1299. mRouteOifsRemove(rt, mfccp->mfcc_parent);
  1300. else
  1301. {
  1302. /* remove entry from group chain */
  1303. root = rt->mfc_root_rt;
  1304. mRouteGroupLoopRemove(rt, root);
  1305. *nptr = rt->mfc_next;/* removes from hash chain */
  1306. MRT_FREE((char*) rt);/* removes the s,g entry */
  1307. if ( (u_long)root->mfc_next_g == (u_long)root->mfc_root_rt == (u_long)root)
  1308. /* this is the only g entry in the table */
  1309. {
  1310. hash = MFCHASH(0, mcastgrp.s_addr);
  1311. nptr = &mfctable[hash];
  1312. while ((rt = *nptr) != NULL) 
  1313. {
  1314. if (origin.s_addr == rt->mfc_origin.s_addr &&
  1315. mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
  1316. rt->mfc_stall == NULL)
  1317. break;
  1318. nptr = &rt->mfc_next;
  1319. }
  1320. if (root == rt)
  1321. {
  1322. *nptr = rt->mfc_next;/* removes from hash chain */
  1323. MRT_FREE((char*) rt);/* frees up the 0,g entry */
  1324. }
  1325. }
  1326. }/* origin not == NULL */
  1327. splx(s);
  1328.     return 0;
  1329. }
  1330. /******************************************************************************
  1331. *
  1332. * mRouteGroupAdd - add a multicast group to the given interface
  1333. *
  1334. * Adds the given group to the list of multicast groups on the given port.
  1335. * Thus, multicast packets to that address will go out the port.
  1336. *
  1337. * RETURNS: OK if successful, ERROR otherwise
  1338. *
  1339. */
  1340. STATUS mRouteGroupAdd
  1341.     (
  1342. struct ifnet* ifp, 
  1343.     struct in_addr srcAddr,       /* multicast source to add */
  1344.     struct in_addr groupAddr      /* multicast group to add */
  1345.     )
  1346.     {
  1347. struct mfcctl gCtl;
  1348. int sockfd;
  1349. int port;
  1350.     struct mfc *rt;
  1351. rt = NULL;
  1352. MFCFIND(0, groupAddr.s_addr, rt);
  1353. if (ifp == NULL)
  1354.     {
  1355.         return (ERROR);
  1356.     }
  1357. port = mRouteNameToPort(ifp->if_name, ifp->if_unit);
  1358.     if ( (port == ERROR) )
  1359.         return (ERROR);
  1360.     gCtl.mfcc_parent = port;
  1361.                     /* ports are vifs for now */
  1362.     gCtl.mfcc_mcastgrp = groupAddr;
  1363. gCtl.mfcc_origin = srcAddr;/* 0 for a star,g entry */
  1364. gCtl.mfcc_notify = 0;   /* mfcc_notify set to 0 so pimNotify never called */
  1365. if (rt != NULL)
  1366. {
  1367. memcpy(gCtl.mfcc_ttls, rt->mfc_ttls, numvifs);
  1368. }
  1369. else 
  1370. {
  1371. bzero (gCtl.mfcc_ttls, 32);
  1372. }
  1373. sockfd = (int)ip_mrouter;
  1374.     if (sockfd <= 0)
  1375.         return (ERROR);
  1376.     MRTDEBUG
  1377.     (
  1378.         (mrtdebug & DEBUG_MFC),
  1379. "MROUTE: IP_MROUTER calling mfc_add.n",
  1380.         1,2,3,4,5,6
  1381.     );
  1382. if (setsockopt (sockfd, IPPROTO_IP, MRT_ADD_MFC,
  1383.                    (char *) &gCtl, sizeof(gCtl)) == ERROR)
  1384.     {
  1385.     MRTDEBUG
  1386.         (
  1387.             (mrtdebug),
  1388.     "MROUTE: igmpGroupAdd failed with errno: %d",
  1389.             errno,2,3,4,5,6
  1390.         );       
  1391.         return ERROR;
  1392.     }
  1393. return (OK);
  1394. }
  1395. /******************************************************************************
  1396. *
  1397. * pimNotify - notifies pim daemon about new packet on an interface
  1398. *
  1399. * RETURNS: OK for success, ERROR for failure
  1400. *
  1401. */
  1402. static int pimNotify
  1403.     (
  1404.     struct ip * pIp, 
  1405.     struct mbuf* pMbuf, 
  1406.     struct mfc* pRt,
  1407.     vifi_t vifi, 
  1408.     struct ifnet* pIfnet
  1409.     )
  1410. {
  1411.     struct sockaddr_in k_igmpsrc;
  1412.     struct mbuf *pMbufCopy;
  1413.     struct igmpmsg *pIGMPMessage;
  1414. struct ip * pIpNew;
  1415.     UINT now;
  1416. int hlen;
  1417.         if ( 
  1418.               (pIp == NULL)
  1419.             ||(pMbuf == NULL)
  1420.             ||(pRt == NULL)
  1421.             ||(pIfnet == NULL)
  1422.            )
  1423.         {
  1424.             return (ERROR);
  1425.         }
  1426. GET_TIME(now);
  1427.     MRTDEBUG
  1428.         (
  1429.             (mrtdebug),
  1430. "MROUTE: pimNotify calling overlying routing protocol.n",
  1431.             1,2,3,4,5,6
  1432.         );
  1433. pMbufCopy = m_copy(pMbuf, 0, M_COPYALL);
  1434. if (pMbufCopy == NULL) 
  1435. {
  1436. return ENOBUFS;
  1437. }
  1438. hlen = pIp->ip_hl << 2;
  1439. if (pMbufCopy && (M_HASCL(pMbufCopy) || pMbufCopy->m_len < hlen))
  1440. pMbufCopy = m_pullup(pMbufCopy, hlen);
  1441. pRt->mfc_last_assert = now;
  1442. /* It looks like they're overlaying the igmpmsg structure on top of the 
  1443. ip structure.  This will allow us to access the im_src member 
  1444. (which in IP corresponds to the ip_src member of struct ip.  Note that 
  1445. both members are offset by 12 bytes.  
  1446. struct igmpmsg {
  1447.     u_long     unused1;
  1448.     u_long     unused2;
  1449.     u_char     im_msgtype;
  1450. #define IGMPMSG_NOCACHE 1
  1451. #define IGMPMSG_WRONGVIF 2
  1452.     u_char     im_mbz;
  1453.     u_char     im_vif;
  1454.     u_char     unused3;
  1455.     struct in_addr  im_src, im_dst;
  1456. };
  1457.   
  1458. struct ip {
  1459. #if _BYTE_ORDER == _LITTLE_ENDIAN
  1460. u_int ip_hl:4,
  1461. ip_v:4,
  1462. #endif
  1463. #if _BYTE_ORDER == _BIG_ENDIAN
  1464. u_int ip_v:4,
  1465. ip_hl:4,
  1466. #endif
  1467. ip_tos:8,
  1468. ip_len:16;
  1469. u_short ip_id;
  1470. short ip_off;
  1471. #define IP_DF 0x4000
  1472. #define IP_MF 0x2000
  1473. #define IP_OFFMASK 0x1fff
  1474. u_char ip_ttl;
  1475. u_char ip_p;
  1476. u_short ip_sum;
  1477. struct in_addr ip_src,ip_dst;
  1478. };
  1479. */
  1480. pIGMPMessage = mtod(pMbufCopy, struct igmpmsg *);
  1481.         if (pIGMPMessage == NULL)
  1482.         {
  1483.             return (ERROR);
  1484.         }
  1485. k_igmpsrc.sin_addr = pIGMPMessage->im_src;
  1486. /* The kernel stores these values in host order, pim requires net order*/
  1487. pIpNew = mtod (pMbufCopy, struct ip*);
  1488.         if (pIpNew == NULL)
  1489.         {
  1490.             return (ERROR);
  1491.         }
  1492.         pIpNew->ip_len = htons(pIpNew->ip_len);
  1493. pIpNew->ip_off = htons(pIpNew->ip_off);
  1494.         /* these values are in the wrong order for PIM*/
  1495.      MRTDEBUG
  1496.         (
  1497.             (mrtdebug),
  1498. "MROUTE: pimNotify calling pim=%p.n",
  1499.             (int)_pimCacheMissSendHook,2,3,4,5,6
  1500.         );
  1501. if ( _pimCacheMissSendHook != 0)
  1502. {
  1503. _pimCacheMissSendHook (pMbufCopy, pIfnet, &k_igmpsrc);
  1504. }
  1505. return (OK);
  1506. }
  1507. /*
  1508.  * IP multicast forwarding function. This function assumes that the packet
  1509.  * pointed to by "ip" has arrived on (or is about to be sent to) the interface
  1510.  * pointed to by "ifp", and the packet is to be relayed to other networks
  1511.  * that have members of the packet's destination IP multicast group.
  1512.  *
  1513.  * The packet is returned unscathed to the caller, unless it is
  1514.  * erroneous, in which case a non-zero return value tells the caller to
  1515.  * discard it.
  1516.  */
  1517. #define IP_HDR_LEN  20 /* # bytes of fixed IP header (excluding options) */
  1518. #define TUNNEL_LEN  12  /* # bytes of IP option for tunnel encapsulation  */
  1519. static int
  1520. X_ip_mforward(m, ifp, ip, imo )
  1521.     struct mbuf *m;
  1522.     struct ifnet *ifp;
  1523.     struct ip *ip;
  1524.     struct ip_moptions *imo;
  1525. {    
  1526.     struct mfc *rt;
  1527.     struct mfc *root_rt;
  1528.     u_char *ipoptions;
  1529.     static struct sockaddr_in  k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
  1530.     static int srctun = 0;
  1531.     int s;
  1532. BOOL null_list;
  1533.     vifi_t vifi = -1;
  1534.     MRTDEBUG
  1535.     (
  1536.         (mrtdebug & DEBUG_FORWARD),
  1537. "ip_mforward: src %lx, dst %lx, if=%p, %s%in",
  1538.         (u_long)ntohl(ip->ip_src.s_addr), 
  1539.         (u_long)ntohl(ip->ip_dst.s_addr),
  1540. (int)ifp, 
  1541.         (int)ifp->if_name, 
  1542.         ifp->if_unit,
  1543.         6
  1544.     );
  1545.     if ( (mrtdebug & DEBUG_TABLE) != 0)
  1546.         mRouteDumpMfctable();
  1547.     if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||
  1548. (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) {
  1549. /*
  1550.  * Packet arrived via a physical interface or
  1551.  * an encapsulated tunnel.
  1552.  */
  1553.     } else {
  1554.     MRTDEBUG
  1555.     (
  1556.         (mrtdebug & DEBUG_FORWARD),
  1557. "MROUTE: Packet arrived through a source-route tunnel.  
  1558.         Source-route tunnels are no longer supported.n",
  1559.         1,2,3,4,5,6
  1560.     );
  1561. /*
  1562.  * Packet arrived through a source-route tunnel.
  1563.  * Source-route tunnels are no longer supported.
  1564.  */
  1565. if ((srctun++ % 1000) == 0)
  1566. {
  1567.         MRTDEBUG
  1568.         (
  1569.             (mrtdebug),
  1570.     "MROUTE: ip_mforward: received source-routed packet from %lxn",
  1571.             (u_long)ntohl(ip->ip_src.s_addr),
  1572.             2,3,4,5,6
  1573.         );
  1574. }
  1575. return 1;
  1576.     }
  1577. if ( (imo) && (vifi < numvifs) ) 
  1578. if (ip->ip_ttl < 255)
  1579. ip->ip_ttl++; /* compensate for -1 in *_send routines */
  1580. vifi = -1;
  1581. return (ip_mdq(m, ifp, NULL, vifi));/* this is for a specific forwarding scenario...  
  1582. explicitly chosen vif.  we no longer support this */
  1583.     }
  1584.     /*
  1585.      * Don't forward a packet with time-to-live of zero or one,
  1586.      * or a packet destined to a local-only group.
  1587.      */
  1588.     if (ip->ip_ttl <= 1 ||
  1589.  (ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) )
  1590. {
  1591. return 0;
  1592. }
  1593.     /*
  1594.      * Determine forwarding vifs from the forwarding cache table
  1595.      */
  1596.     s = splnet();
  1597.     MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt);
  1598.     /* Entry exists, so forward if necessary */
  1599.     if (rt != NULL) 
  1600. {
  1601. null_list = oifListIsEmpty(rt);
  1602. splx(s);
  1603. if ( 
  1604.             (
  1605.     (null_list)
  1606.  && (pim_assert )
  1607.  && (ifp->if_flags & IFF_BROADCAST) 
  1608. )
  1609. || 
  1610. (
  1611.                 rt->mfc_notify != 0
  1612.             )
  1613.    )
  1614. {
  1615. rt->mfc_notify = 1;
  1616. pimNotify(ip, m, rt, vifi, ifp);
  1617. /* tell pim about new packet for old group.  
  1618.  * Pim will be responsible for forwarding*/
  1619. if (null_list )
  1620. {
  1621. return (OK);
  1622. }
  1623. }
  1624. return (ip_mdq(m, ifp, rt, -1));
  1625.     } 
  1626. else 
  1627. {
  1628. /*
  1629.  * If we don't have a route for packet's origin,
  1630.  * Make a copy of the packet &
  1631.  * send message to routing daemon
  1632.  */
  1633. struct mbuf *mb0;
  1634. struct rtdetq *rte;
  1635. u_long hash;
  1636. int hlen = ip->ip_hl << 2;
  1637.     mrtstat.mrts_no_route++;
  1638.     MRTDEBUG
  1639.     (
  1640.         (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)),
  1641.         "MROUTE: ip_mforward: origin unknown no rte s %lx g %lxn",
  1642. (u_long)ntohl(ip->ip_src.s_addr),
  1643. (u_long)ntohl(ip->ip_dst.s_addr),
  1644.         3,4,5,6
  1645.     );
  1646. /*
  1647.  * Allocate mbufs early so that we don't do extra work if we are
  1648.  * just going to fail anyway.  Make sure to pullup the header so
  1649.  * that other people can't step on it.
  1650.  */
  1651. rte = MRT_ALLOC (sizeof (struct rtdetq ) );
  1652. if (rte == NULL) {
  1653.     splx(s);
  1654.     return ENOBUFS;
  1655. }
  1656. rte->m = 0;
  1657. mb0 = m_copy(m, 0, M_COPYALL);
  1658. if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen))
  1659.     mb0 = m_pullup(mb0, hlen);
  1660. if (mb0 == NULL) {
  1661.     MRT_FREE((char*) rte);
  1662.     splx(s);
  1663.     return ENOBUFS;
  1664. }
  1665. /* is there an upcall waiting for this packet? */
  1666. hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr);
  1667. for (rt = mfctable[hash]; rt; rt = rt->mfc_next) 
  1668. {
  1669.     if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) &&
  1670. (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&
  1671. (rt->mfc_stall != NULL)
  1672. )
  1673. break;
  1674. }
  1675. if (rt == NULL) 
  1676. {
  1677.     int i;
  1678.     /* no upcall, so make a new entry */
  1679. rt = MRT_ALLOC(sizeof(struct mfc));
  1680. if (rt == NULL) 
  1681. {
  1682. MRT_FREE((char*) rte);
  1683. m_freem(mb0);
  1684. splx(s);
  1685. return ENOBUFS;
  1686. }
  1687.     /* Make a copy of the header to send to the user level process */
  1688. rt->mfc_notify = 0;
  1689.     /* 
  1690.      * Send message to routing daemon to install 
  1691.      * a route into the kernel table
  1692.      */
  1693.     k_igmpsrc.sin_addr = ip->ip_src;
  1694.     
  1695.     mrtstat.mrts_upcalls++;
  1696.     rt->mfc_origin.s_addr     = ip->ip_src.s_addr;
  1697.     rt->mfc_mcastgrp.s_addr   = ip->ip_dst.s_addr;
  1698.     rt->mfc_expire       = UPCALL_EXPIRE;
  1699.     nexpire[hash]++;
  1700. /* find the root route */
  1701. MFCFIND(0, rt->mfc_mcastgrp.s_addr, root_rt);
  1702. if (root_rt != NULL)
  1703. {/* it exists, do nothing */
  1704. }
  1705. else if (root_rt == NULL)
  1706. {/* create one */
  1707. root_rt = MRT_ALLOC(sizeof(struct mfc));
  1708. if (root_rt == NULL) 
  1709. {
  1710. MRT_FREE((char*) rt);
  1711. splx(s);
  1712. return ENOBUFS;
  1713. }
  1714. root_rt->mfc_notify = 0;
  1715. /* inset NULL entry at head of hash chain */
  1716. root_rt->mfc_origin.s_addr     = 0;
  1717. root_rt->mfc_mcastgrp   = rt->mfc_mcastgrp;
  1718. root_rt->mfc_parent     = 0;
  1719. for (i = 0; i < numvifs; i++)
  1720. root_rt->mfc_ttls[i] = 0;
  1721. /* initialize pkt counters per src-grp */
  1722. root_rt->mfc_pkt_cnt    = 0;
  1723. root_rt->mfc_byte_cnt   = 0;
  1724. root_rt->mfc_wrong_if   = 0;
  1725.             rt->mfc_last_assert = 0;
  1726. root_rt->mfc_last_assert = 0;
  1727. root_rt->mfc_expire     = 0;
  1728. root_rt->mfc_stall      = NULL;
  1729. /* link into table */
  1730. root_rt->mfc_next = mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr) ];
  1731. mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr) ]= root_rt;
  1732. root_rt->mfc_next_g = root_rt; /* next group in same chain */
  1733. root_rt->mfc_root_rt = root_rt; /* 0,g entry in hash table, itself in this case*/
  1734. }
  1735.     rt->mfc_parent = mRouteNameToPort(ifp->if_name, ifp->if_unit);
  1736. rt->mfc_root_rt = root_rt;/* set root_rt*/
  1737. rt->mfc_next_g = root_rt->mfc_next_g; /* insert into from of group chain*/
  1738. for (i = 0; i < numvifs; i++)
  1739. rt->mfc_ttls[i] = root_rt->mfc_ttls[i];
  1740. root_rt->mfc_next_g = rt;
  1741. /* insert new entry at head of hash chain */
  1742.     /* link into table */
  1743.     rt->mfc_next   = mfctable[hash];
  1744.     mfctable[hash] = rt;
  1745.     rt->mfc_stall = rte;
  1746. if (rte->m == 0)
  1747. {
  1748. rte->m  = mb0;
  1749. rte->ifp  = ifp;
  1750. rte->next = NULL;
  1751. }
  1752. if (pim_assert == 0)
  1753. {/* new route automatically inherits *,g entries */
  1754. if (mRouteGroupAdd( ifp, ip->ip_src, ip->ip_dst ) < 0) 
  1755. {
  1756.         MRTDEBUG    
  1757.                 (
  1758.                     (mrtdebug),
  1759. "MROUTE: ip_mforward: ip_mrouter socket queue full, mRouteGroupAdd failedn",
  1760.                     1,2,3,4,5,6
  1761.                 );
  1762. ++mrtstat.mrts_upq_sockfull;
  1763. MRT_FREE((char*) rte);
  1764. m_freem(mb0);
  1765. MRT_FREE((char*) rt);
  1766. splx(s);
  1767. return ENOBUFS;
  1768. }
  1769. }
  1770. else if (pim_assert 
  1771. && (ifp->if_flags & IFF_BROADCAST) 
  1772. )
  1773. {
  1774. pimNotify(ip, m, rt, vifi, ifp);/* tell pim about new group */
  1775. }
  1776. } else {
  1777.     /* determine if q has overflowed */
  1778.     int npkts = 0;
  1779.     struct rtdetq **p;
  1780.     for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next)
  1781. npkts++;
  1782.     if (npkts > MAX_UPQ) {
  1783. mrtstat.mrts_upq_ovflw++;
  1784. MRT_FREE((char*) rte);
  1785. m_freem(mb0);
  1786. splx(s);
  1787. return 0;
  1788.     }
  1789.     /* Add this entry to the end of the queue */
  1790.     *p = rte;
  1791. }
  1792. if (rte->m == 0)
  1793. {
  1794. rte->m  = mb0;
  1795. rte->ifp  = ifp;
  1796. rte->next = NULL;
  1797. }
  1798. splx(s);
  1799. return 0;
  1800.     }
  1801. }
  1802. int ip_mforward (struct mbuf * m, struct ifnet * ifp, struct ip *ip, struct ip_moptions *imo)
  1803. {
  1804. return(X_ip_mforward(m, ifp, ip, imo));
  1805. };
  1806. /*
  1807.  * Clean up the cache entry if upcall is not serviced
  1808.  */
  1809. static void
  1810. expire_upcalls(void *unused)
  1811. {
  1812.     struct rtdetq *rte;
  1813.     struct mfc *mfc, **nptr;
  1814.     int i;
  1815.     int s;
  1816.     s = splnet();
  1817.     for (i = 0; i < MFCTBLSIZ; i++) 
  1818. {
  1819. if (nexpire[i] == 0)
  1820. continue;
  1821. nptr = &mfctable[i];
  1822. for (mfc = *nptr; mfc != NULL; mfc = *nptr) 
  1823. {
  1824. /*
  1825.  * Skip real cache entries
  1826.  * Make sure it wasn't marked to not expire (shouldn't happen)
  1827.  * If it expires now
  1828.  */
  1829. if (mfc->mfc_stall != NULL &&
  1830. mfc->mfc_expire != 0 &&
  1831. --mfc->mfc_expire == 0) 
  1832. {
  1833. MRTDEBUG
  1834.                 (
  1835.                     (mrtdebug & DEBUG_EXPIRE),
  1836. "MROUTE: expire_upcalls: expiring (%lx %lx)n",
  1837.                     (u_long)ntohl(mfc->mfc_origin.s_addr),
  1838. (u_long)ntohl(mfc->mfc_mcastgrp.s_addr),
  1839.                     3,4,5,6
  1840.                 );
  1841. /*
  1842.  * drop all the packets
  1843.  * free the mbuf with the pkt, if, timing info
  1844.  */
  1845. for (rte = mfc->mfc_stall; rte; ) 
  1846. {
  1847. struct rtdetq *n = rte->next;
  1848. m_freem(rte->m);
  1849. MRT_FREE((char*) rte);
  1850. rte = n;
  1851. }
  1852. ++mrtstat.mrts_cache_cleanups;
  1853. nexpire[i]--;
  1854. *nptr = mfc->mfc_next;
  1855. MRT_FREE((char*) mfc);
  1856. else 
  1857. {
  1858. nptr = &mfc->mfc_next;
  1859. }
  1860. }
  1861.     }
  1862.     splx(s);
  1863.     expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
  1864. }
  1865. /*
  1866.  * Packet forwarding routine once entry in the cache is made
  1867.  */
  1868. static int
  1869. ip_mdq(m, ifp, rt, xmt_vif)
  1870.     struct mbuf *m;
  1871.     struct ifnet *ifp;
  1872.     struct mfc *rt;
  1873.     vifi_t xmt_vif;
  1874. {
  1875.     struct ip  *ip = mtod(m, struct ip *);
  1876.     vifi_t vifi;
  1877. vifi_t vifi_original;
  1878.     struct vif *vifp;
  1879. USHORT old_len;
  1880. int port;
  1881.     
  1882.     int plen = ip->ip_len;
  1883. int forwarded = 0;
  1884. /*
  1885.  * Macro to send packet on vif.  Since RSVP packets don't get counted on
  1886.  * input, they shouldn't get counted on output, so statistics keeping is
  1887.  * seperate.
  1888.  */
  1889. #define MC_SEND(ip,vifp,m) {                             
  1890.                 if ((vifp)->v_flags & VIFF_TUNNEL)    
  1891.                     encap_send((ip), (vifp), (m));       
  1892.                 else                                     
  1893.                     phyint_send((ip), (vifp), (m));      
  1894. }
  1895.     /*
  1896.      * If xmt_vif is not -1, send on only the requested vif.
  1897.      *
  1898.      * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
  1899.      */
  1900. port = mRouteNameToPort(ifp->if_name, ifp->if_unit);
  1901.     MRTDEBUG
  1902.     (
  1903.         (mrtdebug),
  1904. "MROUTE:  MDQ found VIF=%i, parent=%i.n",
  1905.         port,
  1906.         rt->mfc_parent,
  1907.         3,4,5,6
  1908.     ); 
  1909.  
  1910.     if ( (xmt_vif < numvifs) || (rt == NULL) ) {/* rt== NULL makes up for missing xmit vif in x_ip_mforward */
  1911. MRTDEBUG
  1912.     (
  1913.         (mrtdebug),
  1914. "MROUTE:  MDQ sending packet on VIF, xmt_vif=%i, numvifs=%i.n", 
  1915.         xmt_vif, 
  1916.         numvifs,
  1917.         3,4,5,6
  1918.     );
  1919. MC_SEND(ip, viftable + xmt_vif, m);
  1920. forwarded ++;
  1921. return 1;
  1922.     }
  1923.     /*
  1924.      * Don't forward if it didn't arrive from the parent vif for its origin.
  1925.      */
  1926.     vifi = rt->mfc_parent;
  1927.     if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) 
  1928. {
  1929. /* came in the wrong interface */
  1930. MRTDEBUG
  1931.         (
  1932.             (mrtdebug),
  1933. "MROUTE: wrong if: ifp %p vifi %d vififp %pn",
  1934.             (int)ifp, 
  1935.             vifi, 
  1936.             (int)viftable[vifi].v_ifp,
  1937.             4,5,6
  1938.         ); 
  1939. ++mrtstat.mrts_wrong_if;
  1940. ++rt->mfc_wrong_if;
  1941. /*
  1942.  * If we are doing PIM assert processing, and we are forwarding
  1943.  * packets on this interface, and it is a broadcast medium
  1944.  * interface (and not a tunnel), send a message to the routing daemon.
  1945.  */
  1946. if (pim_assert && rt->mfc_ttls[port] &&
  1947. (ifp->if_flags & IFF_BROADCAST) &&
  1948. !(viftable[vifi].v_flags & VIFF_TUNNEL)) 
  1949. {
  1950. pimNotify(ip, m, rt, vifi, ifp);
  1951. }
  1952. return 0;
  1953.     }
  1954. vifi_original = vifi;
  1955.     /* If I sourced this packet, it counts as output, else it was input. */
  1956.     if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) 
  1957. {
  1958. viftable[vifi].v_pkt_out++;
  1959. viftable[vifi].v_bytes_out += plen;
  1960.     } 
  1961. else 
  1962. {
  1963. viftable[vifi].v_pkt_in++;
  1964. viftable[vifi].v_bytes_in += plen;
  1965.     }
  1966.     rt->mfc_pkt_cnt++;
  1967.     rt->mfc_byte_cnt += plen;
  1968.     /*
  1969.      * For each vif, decide if a copy of the packet should be forwarded.
  1970.      * Forward if:
  1971.      * - the ttl exceeds the vif's threshold
  1972.      * - there are group members downstream on interface
  1973.      */
  1974.     MRTDEBUG
  1975.     (
  1976.         (mrtdebug),
  1977. "MROUTE:  MDQ iterating through vifs to find oifs.n",
  1978.         1,2,3,4,5,6
  1979.     ); 
  1980.     for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)
  1981.     {
  1982.         MRTDEBUG
  1983.         (
  1984.             (mrtdebug),
  1985. "MROUTE: mdq vif %i has forward threshold %i.  ip->ttl=%i, parent=%i.n",
  1986.             vifi, 
  1987.             rt->mfc_ttls[vifi],
  1988.             ip->ip_ttl,
  1989.             rt->mfc_parent,
  1990.             5,6
  1991.         ); 
  1992.     if (
  1993.     (rt->mfc_ttls[vifi] > 0) 
  1994.      &&(ip->ip_ttl > rt->mfc_ttls[vifi])
  1995.      &&(vifi != rt->mfc_parent)
  1996.      )
  1997.     {
  1998.     vifp->v_pkt_out++;
  1999.     vifp->v_bytes_out += plen;
  2000.     MRTDEBUG
  2001.                 (
  2002.                     (mrtdebug),
  2003.                     "MROUTE:  sending packet out vif %i name %s , ifp=%p.n",
  2004.                     vifi, 
  2005.                     (int)vifp->v_ifp->if_name, 
  2006.                     (int)ifp,
  2007.                     4,5,6
  2008.                 ); 
  2009.     old_len = ip->ip_len;
  2010.     MC_SEND(ip, vifp, m);
  2011.     if (old_len != ip->ip_len)
  2012.     {
  2013.     HTONS(ip->ip_len);/* the kernel sometimes changes 
  2014.     the byte ordering, 
  2015.     so we have to change it back */
  2016.     HTONS(ip->ip_off);
  2017.     }
  2018.                 ip->ip_ttl ++;  /* compensate for -1 in send routine */
  2019.     forwarded ++;
  2020.     }
  2021.     }
  2022.     MRTDEBUG
  2023.     (
  2024.         (mrtdebug),
  2025. "MROUTE:  MDQ forwarded %i times.n", forwarded,
  2026.         2,3,4,5,6
  2027.     ); 
  2028.     return 0;
  2029. }
  2030. /*
  2031.  * check if a vif number is legal/ok. This is used by ip_output, to export
  2032.  * numvifs there, 
  2033.  */
  2034. static int
  2035. X_legal_vif_num(vif)
  2036.     int vif;
  2037. {
  2038.     if (vif >= 0 && vif < numvifs)
  2039.        return(1);
  2040.     else
  2041.        return(0);
  2042. }
  2043. int (*legal_vif_num)(int) = X_legal_vif_num;
  2044. /*
  2045.  * Return the local address used by this vif
  2046.  */
  2047. static u_long
  2048. X_ip_mcast_src(vifi)
  2049.     int vifi;
  2050. {
  2051.     if (vifi >= 0 && vifi < numvifs)
  2052. return viftable[vifi].v_lcl_addr.s_addr;
  2053.     else
  2054. return INADDR_ANY;
  2055. }
  2056. static void
  2057. phyint_send(ip, vifp, m)
  2058.     struct ip *ip;
  2059.     struct vif *vifp;
  2060.     struct mbuf *m;
  2061. {
  2062.     struct mbuf *mb_copy;
  2063.     int hlen = ip->ip_hl << 2;
  2064.     /*
  2065.      * Make a new reference to the packet; make sure that
  2066.      * the IP header is actually copied, not just referenced,
  2067.      * so that ip_output() only scribbles on the copy.
  2068.      */
  2069.     mb_copy = m_copy(m, 0, M_COPYALL);
  2070.     if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen))
  2071. mb_copy = m_pullup(mb_copy, hlen);
  2072.     if (mb_copy == NULL)
  2073. return;
  2074.     if (vifp->v_rate_limit == 0)
  2075. tbf_send_packet(vifp, mb_copy);
  2076.     else
  2077. tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len);
  2078. }
  2079. static void
  2080. encap_send(ip, vifp, m)
  2081.     struct ip *ip;
  2082.     struct vif *vifp;
  2083.     struct mbuf *m;
  2084. {
  2085.     struct mbuf *mb_copy;
  2086.     struct ip *ip_copy;
  2087.     int i, len = ip->ip_len;
  2088.     /*
  2089.      * copy the old packet & pullup its IP header into the
  2090.      * new mbuf so we can modify it.  Try to fill the new
  2091.      * mbuf since if we don't the ethernet driver will.
  2092.      */
  2093.     MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER);
  2094.     if (mb_copy == NULL)
  2095. return;
  2096.     mb_copy->m_data += max_linkhdr;
  2097.     mb_copy->m_len = sizeof(multicast_encap_iphdr);
  2098.     if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
  2099. m_freem(mb_copy);
  2100. return;
  2101.     }
  2102.     i = MHLEN - M_LEADINGSPACE(mb_copy);
  2103.     if (i > len)
  2104. i = len;
  2105.     mb_copy = m_pullup(mb_copy, i);
  2106.     if (mb_copy == NULL)
  2107. return;
  2108.     mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr);
  2109.     /*
  2110.      * fill in the encapsulating IP header.
  2111.      */
  2112.     ip_copy = mtod(mb_copy, struct ip *);
  2113.     *ip_copy = multicast_encap_iphdr;
  2114. #ifndef VIRTUAL_STACK
  2115.     ip_copy->ip_id = htons(ip_id++);
  2116. #else
  2117.     ip_copy->ip_id = htons(_ip_id++);
  2118. #endif
  2119.     ip_copy->ip_len += len;
  2120.     ip_copy->ip_src = vifp->v_lcl_addr;
  2121.     ip_copy->ip_dst = vifp->v_rmt_addr;
  2122.     /*
  2123.      * turn the encapsulated IP header back into a valid one.
  2124.      */
  2125.     ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr));
  2126.     --ip->ip_ttl;
  2127.     HTONS(ip->ip_len);
  2128.     HTONS(ip->ip_off);
  2129.     ip->ip_sum = 0;
  2130.     mb_copy->m_data += sizeof(multicast_encap_iphdr);
  2131.     ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
  2132.     mb_copy->m_data -= sizeof(multicast_encap_iphdr);
  2133.     if (vifp->v_rate_limit == 0)
  2134. tbf_send_packet(vifp, mb_copy);
  2135.     else
  2136. tbf_control(vifp, mb_copy, ip, ip_copy->ip_len);
  2137. }
  2138. /*
  2139.  * De-encapsulate a packet and feed it back through ip input (this
  2140.  * routine is called whenever IP gets a packet with proto type
  2141.  * ENCAP_PROTO and a local destination address).
  2142.  */
  2143. void
  2144. ipip_input(m, iphlen)
  2145. struct mbuf *m;
  2146. int iphlen;
  2147. {
  2148.     struct ifnet *ifp = m->m_pkthdr.rcvif;
  2149.     struct ip *ip = mtod(m, struct ip *);
  2150.     int hlen = ip->ip_hl << 2;
  2151.     int s;
  2152.     struct ifqueue *ifq;
  2153.     struct vif *vifp;
  2154.     if (!have_encap_tunnel) 
  2155. {
  2156.     rip_input(m);
  2157.     return;
  2158.     }
  2159.     /*
  2160.      * dump the packet if it's not to a multicast destination or if
  2161.      * we don't have an encapsulating tunnel with the source.
  2162.      * Note:  This code assumes that the remote site IP address
  2163.      * uniquely identifies the tunnel (i.e., that this site has
  2164.      * at most one tunnel with the remote site).
  2165.      */
  2166.     if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) 
  2167. {
  2168. ++mrtstat.mrts_bad_tunnel;
  2169. m_freem(m);
  2170. return;
  2171.     }
  2172.     if (ip->ip_src.s_addr != last_encap_src) 
  2173. {
  2174. struct vif *vife;
  2175. vifp = viftable;
  2176. vife = vifp + numvifs;
  2177. last_encap_src = ip->ip_src.s_addr;
  2178. last_encap_vif = 0;
  2179. for ( ; vifp < vife; ++vifp)
  2180. if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) 
  2181. {
  2182. if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT))
  2183. == VIFF_TUNNEL)
  2184. last_encap_vif = vifp;
  2185. break;
  2186. }
  2187.     }
  2188.     if ((vifp = last_encap_vif) == 0) 
  2189. {
  2190. last_encap_src = 0;
  2191. mrtstat.mrts_cant_tunnel++; /*XXX*/
  2192. m_freem(m);
  2193. MRTDEBUG
  2194.         (
  2195.             (mrtdebug),
  2196.     "MROUTE: ip_mforward: no tunnel with %lxn",
  2197.             (u_long)ntohl(ip->ip_src.s_addr),
  2198.             2,3,4,5,6
  2199.         );
  2200. return;
  2201.     }
  2202.     ifp = vifp->v_ifp;
  2203.     if (hlen > IP_HDR_LEN)
  2204.       ip_stripoptions(m, (struct mbuf *) 0);
  2205.     m->m_data += IP_HDR_LEN;
  2206.     m->m_len -= IP_HDR_LEN;
  2207.     m->m_pkthdr.len -= IP_HDR_LEN;
  2208.     m->m_pkthdr.rcvif = ifp;
  2209.     ifq = &ipintrq;
  2210.     s = splimp();
  2211.     if (IF_QFULL(ifq)) 
  2212. {
  2213. IF_DROP(ifq);
  2214. m_freem(m);
  2215.     } else 
  2216. {
  2217. IF_ENQUEUE(ifq, m);
  2218. /*
  2219.  * normally we would need a "schednetisr(NETISR_IP)"
  2220.  * here but we were called by ip_input and it is going
  2221.  * to loop back & try to dequeue the packet we just
  2222.  * queued as soon as we return so we avoid the
  2223.  * unnecessary software interrrupt.
  2224.  */
  2225.     }
  2226.     splx(s);
  2227. }
  2228. static BOOL oifListIsEmpty
  2229.     (
  2230.     struct mfc* rt
  2231.     )  
  2232. {
  2233. int i;
  2234. int j = 0;
  2235. if (rt == NULL) return (TRUE);
  2236.     for (i=0;i<numvifs; i++)
  2237. {
  2238. j+=rt->mfc_ttls[i];
  2239. }
  2240.     if (j == 0)
  2241. return (TRUE);
  2242. return(FALSE);
  2243. }
  2244. static void mRouteDumpMfctable()
  2245. {
  2246. int i;
  2247. int j;
  2248. struct mfc* rt;
  2249. vifi_t vifi;
  2250.     struct vif *vifp;
  2251. MRTDEBUG
  2252.     (
  2253.         (1),
  2254. "MROUTE: IP_MROUTE dumping mfctable.n",
  2255.         1,2,3,4,5,6
  2256.     );
  2257. for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)
  2258. {
  2259. MRTDEBUG
  2260.         (
  2261.             (1),
  2262. "MROUTE:  vif %i is named %s%i.n", 
  2263.             vifi, 
  2264.             (int)vifp->v_ifp->if_name, vifp->v_ifp->if_index,
  2265.             4,5,6
  2266.         ); 
  2267. }
  2268. for (i=0;i<MFCTBLSIZ; i++)
  2269. {
  2270. if (mfctable[i] != NULL)
  2271. {
  2272. MRTDEBUG
  2273.             (
  2274.                 (1),
  2275.                 "MROUTE:  mfctable postion %i.n", i,
  2276.                 2,3,4,5,6
  2277.             );
  2278. for (rt = mfctable[i]; rt != NULL; rt = rt->mfc_next) 
  2279. {
  2280. MRTDEBUG
  2281.                 (
  2282.                     (1),
  2283.                     "MROUTE: tEntry g=%p, s=%p.n", 
  2284. ntohl(rt->mfc_mcastgrp.s_addr), 
  2285. ntohl(rt->mfc_origin.s_addr),
  2286.                     3,4,5,6
  2287.                 );
  2288. MRTDEBUG
  2289.                 (   
  2290.                     (1),
  2291.                     "MROUTE: tt OIFLIST=",1,2,3,4,5,6
  2292.                 );
  2293. for (j=0;j<=numvifs; j++)
  2294. MRTDEBUG
  2295.                     (
  2296.                         (1),
  2297.                         "vif %i ttl=%i,",j,(int)rt->mfc_ttls[j],3,4,5,6
  2298.                     );
  2299. MRTDEBUG
  2300.                 (
  2301.                     (1),
  2302.                     "MROUTE: n.",
  2303.                     1,2,3,4,5,6
  2304.                 );
  2305. }
  2306. }
  2307. }
  2308. }
  2309. /*
  2310.  * Token bucket filter module
  2311.  */
  2312. static void
  2313. tbf_control(vifp, m, ip, p_len)
  2314. struct vif *vifp;
  2315. struct mbuf *m;
  2316. struct ip *ip;
  2317. u_long p_len;
  2318. {
  2319.     struct tbf *t = vifp->v_tbf;
  2320.     if (p_len > MAX_BKT_SIZE) {
  2321. /* drop if packet is too large */
  2322. mrtstat.mrts_pkt2large++;
  2323. m_freem(m);
  2324. return;
  2325.     }
  2326.     tbf_update_tokens(vifp);
  2327.     /* if there are enough tokens, 
  2328.      * and the queue is empty,
  2329.      * send this packet out
  2330.      */
  2331.     if (t->tbf_q_len == 0) {
  2332. /* queue empty, send packet if enough tokens */
  2333. if (p_len <= t->tbf_n_tok) {
  2334.     t->tbf_n_tok -= p_len;
  2335.     tbf_send_packet(vifp, m);
  2336. } else {
  2337.     /* queue packet and timeout till later */
  2338.     tbf_queue(vifp, m);
  2339. timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);
  2340. }
  2341.     } else if (t->tbf_q_len < t->tbf_max_q_len) {
  2342. /* finite queue length, so queue pkts and process queue */
  2343. tbf_queue(vifp, m);
  2344. tbf_process_q(vifp);
  2345.     } else {
  2346. /* queue length too much, try to dq and queue and process */
  2347. if (!tbf_dq_sel(vifp, ip)) {
  2348.     mrtstat.mrts_q_overflow++;
  2349.     m_freem(m);
  2350.     return;
  2351. } else {
  2352.     tbf_queue(vifp, m);
  2353.     tbf_process_q(vifp);
  2354. }
  2355.     }
  2356.     return;
  2357. }
  2358. /* 
  2359.  * adds a packet to the queue at the interface
  2360.  */
  2361. static void
  2362. tbf_queue(vifp, m) 
  2363. struct vif *vifp;
  2364. struct mbuf *m;
  2365. {
  2366.     int s = splnet();
  2367.     struct tbf *t = vifp->v_tbf;
  2368.     if (t->tbf_t == NULL) {
  2369. /* Queue was empty */
  2370. t->tbf_q = m;
  2371.     } else {
  2372. /* Insert at tail */
  2373. t->tbf_t->m_act = m;
  2374.     }
  2375.     /* Set new tail pointer */
  2376.     t->tbf_t = m;
  2377. #ifdef DIAGNOSTIC
  2378.     /* Make sure we didn't get fed a bogus mbuf */
  2379.     if (m->m_act)
  2380. panic("tbf_queue: m_act");
  2381. #endif
  2382.     m->m_act = NULL;
  2383.     t->tbf_q_len++;
  2384.     splx(s);
  2385. }
  2386. /* 
  2387.  * processes the queue at the interface
  2388.  */
  2389. static void
  2390. tbf_process_q(vifp)
  2391.     struct vif *vifp;
  2392. {
  2393.     struct mbuf *m;
  2394.     int len;
  2395.     int s = splnet();
  2396.     struct tbf *t = vifp->v_tbf;
  2397.     /* loop through the queue at the interface and send as many packets
  2398.      * as possible
  2399.      */
  2400.     while (t->tbf_q_len > 0) {
  2401. m = t->tbf_q;
  2402. len = mtod(m, struct ip *)->ip_len;
  2403. /* determine if the packet can be sent */
  2404. if (len <= t->tbf_n_tok) {
  2405.     /* if so,
  2406.      * reduce no of tokens, dequeue the packet,
  2407.      * send the packet.
  2408.      */
  2409.     t->tbf_n_tok -= len;
  2410.     t->tbf_q = m->m_act;
  2411.     if (--t->tbf_q_len == 0)
  2412. t->tbf_t = NULL;
  2413.     m->m_act = NULL;
  2414.     tbf_send_packet(vifp, m);
  2415. } else break;
  2416.     }
  2417.     splx(s);
  2418. }
  2419. static void
  2420. tbf_reprocess_q(xvifp)
  2421. void *xvifp;
  2422. {
  2423.     struct vif *vifp = xvifp;
  2424.     if (ip_mrouter == 0) 
  2425. return;
  2426.     tbf_update_tokens(vifp);
  2427.     tbf_process_q(vifp);
  2428.     if (vifp->v_tbf->tbf_q_len)
  2429. timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);
  2430. }
  2431. /* function that will selectively discard a member of the queue
  2432.  * based on the precedence value and the priority
  2433.  */
  2434. static int
  2435. tbf_dq_sel(vifp, ip)
  2436.     struct vif *vifp;
  2437.     struct ip *ip;
  2438. {
  2439.     int s = splnet();
  2440.     u_int p;
  2441.     struct mbuf *m, *last;
  2442.     struct mbuf **np;
  2443.     struct tbf *t = vifp->v_tbf;
  2444.     p = priority(vifp, ip);
  2445.     np = &t->tbf_q;
  2446.     last = NULL;
  2447.     while ((m = *np) != NULL) {
  2448. if (p > priority(vifp, mtod(m, struct ip *))) {
  2449.     *np = m->m_act;
  2450.     /* If we're removing the last packet, fix the tail pointer */
  2451.     if (m == t->tbf_t)
  2452. t->tbf_t = last;
  2453.     m_freem(m);
  2454.     /* it's impossible for the queue to be empty, but
  2455.      * we check anyway. */
  2456.     if (--t->tbf_q_len == 0)
  2457. t->tbf_t = NULL;
  2458.     splx(s);
  2459.     mrtstat.mrts_drop_sel++;
  2460.     return(1);
  2461. }
  2462. np = &m->m_act;
  2463. last = m;
  2464.     }
  2465.     splx(s);
  2466.     return(0);
  2467. }
  2468. static void
  2469. tbf_send_packet(vifp, m)
  2470.     struct vif *vifp;
  2471.     struct mbuf *m;
  2472. {
  2473.     struct ip_moptions imo;
  2474.     int error;
  2475.     static struct route ro;
  2476.     int s = splnet();
  2477. #ifdef WV_INSTRUMENTATION
  2478. #ifdef INCLUDE_WVNET
  2479.     struct ip *ip = mtod(m, struct ip *);
  2480.     u_long dstAddr;  /* Destination group, unavailable if output fails. */
  2481. #endif
  2482. #endif
  2483.     if (vifp->v_flags & VIFF_TUNNEL) {
  2484. /* If tunnel options */
  2485. #ifdef WV_INSTRUMENTATION
  2486. #ifdef INCLUDE_WVNET
  2487.         /*
  2488.          * Save the multicast destination address from the original packet,
  2489.          * since it will be unavailable if the ip_output() call fails.
  2490.          */
  2491.         dstAddr = ip->ip_dst.s_addr;
  2492. #endif
  2493. #endif
  2494. error = ip_output(m, (struct mbuf *)0, &vifp->v_route,
  2495.   IP_FORWARDING, (struct ip_moptions *)0);
  2496. #ifdef WV_INSTRUMENTATION
  2497. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  2498.     WV_NET_ADDROUT_MARKER_4 (NET_CORE_EVENT, WV_NET_NOTICE, 12, 10,
  2499.                              vifp->v_lcl_addr.s_addr, vifp->v_rmt_addr.s_addr,
  2500.                              WV_NETEVENT_TUNNEL_STATUS,
  2501.                              error, vifp->v_lcl_addr.s_addr,
  2502.                              vifp->v_rmt_addr.s_addr, dstAddr)
  2503. #endif  /* INCLUDE_WVNET */
  2504. #endif
  2505.     } else {
  2506. imo.imo_multicast_ifp  = vifp->v_ifp;
  2507. imo.imo_multicast_ttl  = mtod(m, struct ip *)->ip_ttl - 1;
  2508. imo.imo_multicast_loop = 1;
  2509. /*imo.imo_multicast_vif  = -1;*/
  2510. /*
  2511.  * Re-entrancy should not be a problem here, because
  2512.  * the packets that we send out and are looped back at us
  2513.  * should get rejected because they appear to come from
  2514.  * the loopback interface, thus preventing looping.
  2515.  */
  2516. error = ip_output(m, (struct mbuf *)0, &ro,
  2517.   IP_FORWARDING, &imo);
  2518. #ifdef WV_INSTRUMENTATION
  2519. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  2520.         WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_NOTICE, 13, 11,
  2521.                         WV_NETEVENT_PHYINT_STATUS, WV_NET_SEND,
  2522.                         error, vifp->v_ifp)
  2523. #endif  /* INCLUDE_WVNET */
  2524. #endif
  2525. MRTDEBUG
  2526.     (
  2527.         (mrtdebug & DEBUG_XMIT),
  2528.         "MROUTE: phyint_send on vif %p err %pn", 
  2529.         (vifp - viftable), 
  2530.         error,3,4,5,6
  2531.     );
  2532.     }
  2533.     splx(s);
  2534. }
  2535. /* determine the current time and then
  2536.  * the elapsed time (between the last time and time now)
  2537.  * in milliseconds & update the no. of tokens in the bucket
  2538.  */
  2539. static void
  2540. tbf_update_tokens(vifp)
  2541.     struct vif *vifp;
  2542. {
  2543.     UINT tp;
  2544.     u_long tm;
  2545.     int s = splnet();
  2546.     struct tbf *t = vifp->v_tbf;
  2547.     GET_TIME(tp);
  2548.     TV_DELTA(tp, t->tbf_last_pkt_t, tm);
  2549.     /*
  2550.      * This formula is actually
  2551.      * "time in seconds" * "bytes/second".
  2552.      *
  2553.      * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8)
  2554.      *
  2555.      * The (1000/1024) was introduced in add_vif to optimize
  2556.      * this divide into a shift.
  2557.      */
  2558.     t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8;
  2559.     t->tbf_last_pkt_t = tp;
  2560.     if (t->tbf_n_tok > MAX_BKT_SIZE)
  2561. t->tbf_n_tok = MAX_BKT_SIZE;
  2562.     splx(s);
  2563. }
  2564. static int
  2565. priority(vifp, ip)
  2566.     struct vif *vifp;
  2567.     struct ip *ip;
  2568. {
  2569.     int prio;
  2570.     /* temporary hack; may add general packet classifier some day */
  2571.     /*
  2572.      * The UDP port space is divided up into four priority ranges:
  2573.      * [0, 16384)     : unclassified - lowest priority
  2574.      * [16384, 32768) : audio - highest priority
  2575.      * [32768, 49152) : whiteboard - medium priority
  2576.      * [49152, 65536) : video - low priority
  2577.      */
  2578.     if (ip->ip_p == IPPROTO_UDP) {
  2579. struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2));
  2580. switch (ntohs(udp->uh_dport) & 0xc000) {
  2581.     case 0x4000:
  2582. prio = 70;
  2583. break;
  2584.     case 0x8000:
  2585. prio = 60;
  2586. break;
  2587.     case 0xc000:
  2588. prio = 55;
  2589. break;
  2590.     default:
  2591. prio = 50;
  2592. break;
  2593. }
  2594. if (tbfdebug > 1)
  2595. MRTDEBUG
  2596.         (
  2597.             (1),
  2598.             "MROUTE: port %x prio%dn", ntohs(udp->uh_dport), prio,3,4,5,6
  2599.         );
  2600.     } else {
  2601.     prio = 50;
  2602.     }
  2603.     return prio;
  2604. }
  2605. /*
  2606.  * End of token bucket filter modifications 
  2607.  */
  2608.  
  2609.  
  2610.  /*
  2611.  * sooptcopyout copies out of the sockopt into a buffer 
  2612.  * it comes from the /kern/uipc_socket.c in the BSD releases
  2613.  */
  2614. static 
  2615. int
  2616. sooptcopyout(sopt, buf, len)
  2617. struct sockopt *sopt;
  2618. void *buf;
  2619. size_t len;
  2620. {
  2621. int error;
  2622. size_t valsize;
  2623. error = 0;
  2624. MRTDEBUG
  2625.     (
  2626.         (mrtdebug),
  2627. "MROUTE: soopcopyout sopt->sopt_valsize=%i len=%i.n", 
  2628.         (int)sopt->sopt_valsize, 
  2629.         (int)len,
  2630.         3,4,5,6
  2631.     );
  2632. /*
  2633.  * Documented get behavior is that we always return a value,
  2634.  * possibly truncated to fit in the user's buffer.
  2635.  * Traditional behavior is that we always tell the user
  2636.  * precisely how much we copied, rather than something useful
  2637.  * like the total amount we had available for her.
  2638.  * Note that this interface is not idempotent; the entire answer must
  2639.  * generated ahead of time.
  2640.  */
  2641. valsize = min(len, sopt->sopt_valsize);
  2642. sopt->sopt_valsize = valsize;
  2643. if (sopt->sopt_val != 0) {
  2644. if (sopt->sopt_p != 0)
  2645. error = copyout(buf, sopt->sopt_val, valsize);
  2646. else
  2647. memcpy(sopt->sopt_val, buf, valsize);
  2648. }
  2649. return error;
  2650. }
  2651. /*
  2652.  * sooptcopyin copies from a buffer into a sockopt 
  2653.  * it comes from the /kern/uipc_socket.c in the BSD releases
  2654.  */
  2655. static int
  2656. sooptcopyin(sopt, buf, len, minlen)
  2657. struct sockopt *sopt;
  2658. void *buf;
  2659. size_t len;
  2660. size_t minlen;
  2661. {
  2662. size_t valsize;
  2663. /*
  2664.  * If the user gives us more than we wanted, we ignore it,
  2665.  * but if we don't get the minimum length the caller
  2666.  * wants, we return EINVAL.  On success, sopt->sopt_valsize
  2667.  * is set to however much we actually retrieved.
  2668.  */
  2669. if ((valsize = sopt->sopt_valsize) < minlen){
  2670. return EINVAL;}
  2671. if (valsize > len)
  2672. sopt->sopt_valsize = valsize = len;
  2673. if (sopt->sopt_p != 0)
  2674. {
  2675. valsize = copyin(sopt->sopt_val, buf, valsize);
  2676. return (valsize );
  2677. }
  2678. memcpy(buf, sopt->sopt_val, valsize);
  2679. return 0;
  2680. }
  2681. /*
  2682.  * if_allmulti copies sets multicast characteristics on
  2683.  * an interface.  I have left it in for forward compatibility
  2684.  * it comes from the net/if.c in the net/3 BSD releases
  2685.  */
  2686. static int
  2687. if_allmulti(ifp, onswitch)
  2688. struct ifnet *ifp;
  2689. int onswitch;
  2690. {
  2691. struct ifreq ifr;
  2692. int error = 0;
  2693. int s;
  2694. bzero ((char*)&ifr, IFNAMSIZ);
  2695. s = splimp();
  2696. /* ifp->amcount was removed from the ifnet structure, 
  2697.    but this code was left for future compatibility issues */
  2698. if (onswitch) {
  2699. if (1   /*ifp->if_amcount++ == 0*/) {
  2700. ifp->if_flags |= IFF_ALLMULTI;
  2701. error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, (char*)&ifr);
  2702. }
  2703. } else {
  2704. if (1/*ifp->if_amcount > 1*/) {
  2705. /*ifp->if_amcount--*/;
  2706. } else {
  2707. /*ifp->if_amcount = 0;*/
  2708. ifp->if_flags &= ~IFF_ALLMULTI;
  2709. error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, (char*)&ifr);
  2710. }
  2711. }
  2712. splx(s);
  2713. return (error);
  2714. }
  2715. /*
  2716.  * Adds a timer task to the netJob ring buffer
  2717.  */
  2718. static void mRouteNetJobAdd(MROUTE_TIMER_STRUCT* p_timer_struct_object)
  2719. {
  2720. if ( netJobAdd (  (FUNCPTR)(*p_timer_struct_object->expire_routine) , (int) (p_timer_struct_object->argument), 0, 0,
  2721.                            0, 0) == ERROR)
  2722. {
  2723.         MRTDEBUG((mrtdebug), "MROUTE failed to execute timer expire.n", 1,2,3,4,5,6);
  2724. /* log error */
  2725. }
  2726.     wdDelete(p_timer_struct_object->watchdog_id);
  2727.     MRT_FREE((char*) p_timer_struct_object);
  2728. return;
  2729. }
  2730. /*
  2731.  * Sets the timeout of an routine, calls mRouteNetJobAdd
  2732.  */
  2733. static MROUTE_TIMER_STRUCT* mRouteTimeout(VOIDFUNCPTR expire_routine, void* argument, int number_of_ticks)
  2734. {
  2735. WDOG_ID timer_id;
  2736. MROUTE_TIMER_STRUCT* p_timer_struct_object;
  2737. p_timer_struct_object = MRT_ALLOC(sizeof (MROUTE_TIMER_STRUCT));
  2738. timer_id = wdCreate(); 
  2739. p_timer_struct_object->argument = argument;
  2740. p_timer_struct_object->expire_routine = expire_routine;
  2741. if (timer_id == NULL)
  2742. {
  2743. return (NULL);
  2744. }
  2745. p_timer_struct_object->watchdog_id = timer_id;
  2746. if (wdStart(timer_id, number_of_ticks, (FUNCPTR)(*mRouteNetJobAdd), (UINT)p_timer_struct_object) == ERROR)
  2747. {
  2748. /* log_error */
  2749. wdDelete(timer_id);
  2750. MRT_FREE((char*) p_timer_struct_object);
  2751. return (NULL);
  2752. }
  2753. return (p_timer_struct_object);
  2754. }
  2755. /*
  2756.  * Unsets the timeout of an routine, calls mRouteNetJobAdd
  2757.  */
  2758. static void mRouteUntimeOut(MROUTE_TIMER_STRUCT*  p_timer_struct)
  2759. {
  2760.     if (p_timer_struct == NULL)
  2761.         return;
  2762. if (wdCancel(p_timer_struct->watchdog_id) == ERROR)
  2763. {
  2764. MRTDEBUG
  2765.         (   
  2766.             (mrtdebug),
  2767. "MROUTE:  untimeout failed to cancel timer!n",
  2768.             1,2,3,4,5,6
  2769.         );
  2770. }
  2771. if (wdDelete(p_timer_struct->watchdog_id) == ERROR)
  2772. {
  2773. MRTDEBUG
  2774.         (
  2775.             (mrtdebug),
  2776. "MROUTE:  untimeout failed to delete watchdog id!n",
  2777.             1,2,3,4,5,6
  2778.         );
  2779. }
  2780.     MRT_FREE((char*) p_timer_struct);
  2781. return;
  2782. }