tables.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:36k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* tables.c - routines for managing RIP internal routing table */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1983, 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  * @(#)tables.c 8.2 (Berkeley) 4/28/95
  36.  */
  37. /*
  38. modification history
  39. --------------------
  40. 01r,22mar02,niq  Merged from Synth view, tor3_x.synth branch, ver 02c
  41. 01q,24jan02,niq  SPR 72415 - Added support for Route tags
  42. 01p,15oct01,rae  merge from truestack ver 01w, base 01m (SPRs 70188, 69983,
  43.                  65547, etc.)
  44. 01o,21nov00,spm  fixed creation of internal default route (SPR #62533)
  45. 01n,10nov00,spm  merged from version 01n of tor3_x branch (code cleanup)
  46. 01m,16mar99,spm  recovered orphaned code from tor1_0_1.sens1_1 (SPR #25770)
  47. 01l,29sep98,spm  added support for IP group MIB (SPR #9374); removed unneeded
  48.                  routine (SPR #21109).
  49. 01k,11sep98,spm  moved mutual exclusion semaphore to prevent any collisions
  50.                  between RIP tasks (SPR #22350), removed all references to 
  51.                  bloated trace commands (SPR #22350)
  52. 01j,01sep98,spm  corrected processing of RIPv2 route updates to support
  53.                  version changes (SPR #22158); added support for default
  54.                  routes (SPR #22067)
  55. 01i,26jul98,spm  removed compiler warnings
  56. 01h,06oct97,gnn  fixed insque/remque casting bug and cleaned up warnings
  57. 01g,12aug97,gnn  fixed prototypes for mRouteEntryDelete().
  58. 01f,15may97,gnn  added code to implement route leaking.
  59. 01e,14apr97,gnn  fixed calls to mRouteEntryAdd to follow Rajesh's changes.
  60. 01d,07apr97,gnn  cleared up some of the more egregious warnings.
  61.                  added MIB-II interfaces and options.
  62. 01c,24feb97,gnn  added rip version 2 functionality.
  63. 01b,05dec96,gnn  changed insque/remque to _insque/_remque for compatability.
  64. 01a,26nov96,gnn  created from BSD4.4 routed
  65. */
  66. /*
  67. DESCRIPTION
  68. */
  69. /*
  70.  * Routing Table Management Daemon
  71.  */
  72. #include "vxWorks.h"
  73. #include "rip/defs.h"
  74. #include "sys/ioctl.h"
  75. #include "netinet/in.h"
  76. #include "routeLib.h"
  77. #include "errno.h"
  78. #include "inetLib.h"
  79. #include "semLib.h"
  80. #include "logLib.h"
  81. #include "m2Lib.h" 
  82. #include "stdlib.h"
  83. #include "routeEnhLib.h"
  84. #ifdef VIRTUAL_STACK
  85. #include "netinet/vsLib.h"
  86. #include "netinet/vsRip.h"
  87. #endif /* VIRTUAL_STACK */
  88. /* defines */
  89. #ifdef RTM_ADD
  90. #define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
  91. #else
  92. #define FIXLEN(s) { }
  93. #endif /* RTM_ADD */
  94. /* globals */
  95. #ifndef VIRTUAL_STACK
  96. IMPORT int routedDebug;
  97. IMPORT RIP ripState;
  98. #endif /* VIRTUAL_STACK */
  99. /* locals */
  100. LOCAL struct sockaddr_in inet_default = {
  101. #ifdef RTM_ADD
  102.         sizeof (inet_default),
  103. #endif
  104.         AF_INET, INADDR_ANY };
  105. /* forward declarations */
  106. IMPORT void ripSockaddrPrint (struct sockaddr * pSockAddr);
  107. LOCAL void ripInsque (NODE * pNode, NODE * pPrev);
  108. LOCAL void ripRemque (NODE * pNode);
  109. LOCAL STATUS ripSystemRouteAdd (long dstIp, long gateIp, long mask, int flags);
  110. LOCAL STATUS ripSystemRouteDelete (long dstIp, long gateIp, long mask, int flags);
  111. void ripRouteMetricSet (struct rt_entry * pRtEntry);
  112. /*
  113.  * Lookup dst in the tables for an exact match.
  114.  */
  115. struct rt_entry *
  116. rtlookup (dst)
  117. struct sockaddr *dst;
  118. {
  119. register struct rt_entry *rt;
  120. register struct rthash *rh;
  121. register u_int hash;
  122. struct sockaddr target;
  123. struct afhash h;
  124. int doinghost = 1;
  125. if (dst->sa_family >= AF_MAX)
  126. return (0);
  127. (*afswitch[dst->sa_family].af_hash) (dst, &h);
  128. hash = h.afh_hosthash;
  129. rh = &hosthash[hash & ROUTEHASHMASK];
  130.         /* 
  131.          * The equal() comparison within the following loop expects all
  132.          * members of the structure except the family, length, and address
  133.          * fields to be zero. This condition may not be met when processing a
  134.          * RIPv2 packet. In that case, the destination passed to this routine 
  135.          * accesses a route within the payload of a RIP message, so some
  136.          * fields of the overlayed structure will not be zero as expected.
  137.          * Duplicate or incorrect routes will be added because matching routes
  138.          * are not detected. To avoid this problem, copy the required fields 
  139.          * from the route destination value to a clean structure.
  140.          */
  141.         bzero ( (char *)&target, sizeof (struct sockaddr));
  142.         target.sa_family = dst->sa_family;
  143.         target.sa_len = dst->sa_len;
  144.         ((struct sockaddr_in *)&target)->sin_addr.s_addr = 
  145.                     ((struct sockaddr_in *)dst)->sin_addr.s_addr;
  146.         
  147. again:
  148. for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
  149. if (rt->rt_hash != hash)
  150. continue;
  151. if (equal (&rt->rt_dst, &target))
  152. return (rt);
  153. }
  154. if (doinghost) {
  155. doinghost = 0;
  156. hash = h.afh_nethash;
  157. rh = &nethash[hash & ROUTEHASHMASK];
  158. goto again;
  159. }
  160. return (0);
  161. }
  162. #ifdef notyet
  163. #ifndef VIRTUAL_STACK
  164. struct sockaddr wildcard; /* zero valued cookie for wildcard searches */
  165. #endif
  166. #endif
  167. /*
  168.  * Find a route to dst as the kernel would.
  169.  */
  170. struct rt_entry *
  171. rtfind (dst)
  172. struct sockaddr *dst;
  173. {
  174. register struct rt_entry *rt;
  175. register struct rthash *rh;
  176. register u_int hash;
  177. struct sockaddr target;
  178. struct afhash h;
  179. int af = dst->sa_family;
  180. int doinghost = 1;
  181.         int (*match) () = NULL;  /* Assigned later for network hash search. */
  182. if (af >= AF_MAX)
  183. return (0);
  184. (*afswitch[af].af_hash) (dst, &h);
  185. hash = h.afh_hosthash;
  186. rh = &hosthash[hash & ROUTEHASHMASK];
  187.         /* 
  188.          * The equal() comparison within the following loop expects all
  189.          * members of the structure except the family, length, and address
  190.          * fields to be zero. This condition may not be met when processing a
  191.          * RIPv2 packet. In that case, the destination passed to this routine 
  192.          * accesses a route within the payload of a RIP message, so some
  193.          * fields of the overlayed structure will not be zero as expected,
  194.          * and existing host routes would be missed. To avoid this problem,              * copy the required fields from the route destination value to a 
  195.          * clean structure.
  196.          */
  197.         bzero ( (char *)&target, sizeof (struct sockaddr));
  198.         target.sa_family = dst->sa_family;
  199.         target.sa_len = dst->sa_len;
  200.         ((struct sockaddr_in *)&target)->sin_addr.s_addr = 
  201.                     ((struct sockaddr_in *)dst)->sin_addr.s_addr;
  202.         
  203. again:
  204. for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
  205. if (rt->rt_hash != hash)
  206. continue;
  207. if (doinghost) {
  208. if (equal (&rt->rt_dst, &target))
  209. return (rt);
  210. } else {
  211. if (rt->rt_dst.sa_family == af &&
  212.     (*match) (&rt->rt_dst, dst))
  213. return (rt);
  214. }
  215. }
  216. if (doinghost) {
  217. doinghost = 0;
  218. hash = h.afh_nethash;
  219. rh = &nethash[hash & ROUTEHASHMASK];
  220. match = afswitch[af].af_netmatch;
  221. goto again;
  222. }
  223. #ifdef notyet
  224. /*
  225.  * Check for wildcard gateway, by convention network 0.
  226.  */
  227. if (dst != &wildcard) {
  228. dst = &wildcard, hash = 0;
  229. goto again;
  230. }
  231. #endif
  232. return (0);
  233. }
  234. struct rt_entry * rtadd
  235.     (
  236.     struct sockaddr *dst, 
  237.     struct sockaddr *gate, 
  238.     int metric, 
  239.     int state, 
  240.     struct sockaddr *netmask, 
  241.     int proto, 
  242.     int tag, 
  243.     int from, 
  244.     struct interface *ifp
  245.     )
  246.     {
  247.     struct afhash h;
  248.     register struct rt_entry *rt;
  249.     struct rthash *rh;
  250.     int af = dst->sa_family, flags;
  251.     struct sockaddr_in* pDsin;
  252.     struct sockaddr_in* pGsin;
  253.     struct sockaddr_in* pNsin;
  254.     u_int hash;
  255.     struct interface* pIfp;
  256.     int ret = ERROR;
  257.     if (af >= AF_MAX)
  258.         return ((struct rt_entry *)NULL);
  259.     (*afswitch[af].af_hash) (dst, &h);
  260.     flags = (*afswitch[af].af_rtflags) (dst);
  261.     /*
  262.      * Subnet flag isn't visible to kernel, move to state. XXX
  263.      */
  264.     FIXLEN (dst);
  265.     FIXLEN (gate);
  266.     if (flags & RTF_SUBNET)
  267.         {
  268.         state |= RTS_SUBNET;
  269.         flags &= ~RTF_SUBNET;
  270.         }
  271.     if (flags & RTF_HOST)
  272.         {
  273.         hash = h.afh_hosthash;
  274.         rh = &hosthash[hash & ROUTEHASHMASK];
  275. }
  276.     else
  277.         {
  278.         hash = h.afh_nethash;
  279.         rh = &nethash[hash & ROUTEHASHMASK];
  280. }
  281.     rt = (struct rt_entry *)malloc (sizeof (*rt));
  282.     if (rt == 0)
  283.         return ((struct rt_entry *)NULL);
  284.     rt->inKernel = FALSE;
  285.     rt->rt_hash = hash;
  286.     rt->rt_dst = *dst;
  287.     rt->rt_router = *gate;
  288.     rt->rt_timer = 0;
  289.     rt->rt_flags = RTF_UP | flags;
  290.     rt->rt_state = state | RTS_CHANGED;
  291.     rt->rt_proto = proto;
  292.     rt->rt_tag = tag;
  293.     rt->rt_refcnt = 0;
  294.     rt->rt_subnets_cnt = 0;
  295.     rt->rt_orgrouter = from;
  296.     /*
  297.      * A matching interface exists for all standard destinations or
  298.      * the RIP session will not begin the add operation, but no
  299.      * interface exists for the default route. The rt_ifp field is
  300.      * equal to zero in that case.
  301.      * Also, we need to search for the gateway address for the non-rip 
  302.      * route.
  303.      */
  304.     if (ifp)
  305.         rt->rt_ifp = ifp;
  306.     else
  307.         {
  308.         rt->rt_ifp = ripIfWithDstAddr (&rt->rt_dst, &rt->rt_router);
  309.         if (rt->rt_ifp == 0) 
  310.             rt->rt_ifp = ripIfWithNet (&rt->rt_router);
  311.         }
  312.     if ((state & RTS_INTERFACE) == 0)
  313.         {
  314.         rt->rt_flags |= RTF_GATEWAY;
  315.         flags |= RTF_GATEWAY;
  316.         }
  317.     rt->rt_metric = metric;
  318.     /* 
  319.      * Set the netmask. The interface's netmask is used if none is included
  320.      * in the RIP message. Otherwise, the specified netmask is used, except
  321.      * for default routes, which always use a netmask of 0.
  322.      */
  323.     if (netmask != (struct sockaddr *)NULL && 
  324.          ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  325.         {
  326.         rt->rt_netmask = *netmask; 
  327.         }
  328.     else
  329.         {
  330.         /* Leave the netmask value as zero if a default route is used. */
  331.         bzero ((char *)&rt->rt_netmask, sizeof (rt->rt_netmask));
  332.         rt->rt_netmask.sa_family = AF_INET;
  333.         rt->rt_netmask.sa_len = 16;
  334.         pNsin = (struct sockaddr_in *)&rt->rt_netmask;
  335.         if ( ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  336.             {
  337.             pNsin->sin_addr.s_addr = htonl (rt->rt_ifp->int_subnetmask);
  338.             /* 
  339.              * Learned routes and locally generated interface routes use the
  340.              * (possibly classless) subnet mask value. Internally generated 
  341.              * routes provided to implement border gateway filtering will
  342.              * use a class-based netmask in all updates to be understood 
  343.              * by RIP-2 routers on "distant" hosts not directly connected to 
  344.              * the destination. Since supernet routes must use the classless 
  345.              * netmask during border gateway filtering to correctly detect 
  346.              * matching supernet numbers, they retain that value internally 
  347.              * while the subnetted routes replace it with the class-based 
  348.              * value.
  349.              */
  350.             if (rt->rt_state & RTS_INTERNAL)
  351.                 {
  352.                 /* 
  353.                  * Check if the subnetmask is shorter than the (class-based)
  354.                  * netmask. This test works because equal values are not 
  355.                  * possible for these routes (RTS_SUBNET is always set).
  356.                  */
  357.                 if ( (rt->rt_ifp->int_subnetmask | rt->rt_ifp->int_netmask) ==
  358.                     rt->rt_ifp->int_subnetmask)
  359.                     {
  360.                     /* Longer mask. Replace with class-based value. */ 
  361.                     pNsin->sin_addr.s_addr = htonl (rt->rt_ifp->int_netmask);
  362.                     }
  363.                 }
  364.             }
  365.         }
  366.     ripRouteToAddrs (rt, &pDsin, &pGsin, &pNsin);
  367.     
  368.     pIfp = rt->rt_ifp;
  369.     if (((state & RTS_OTHER) == 0) && (pIfp) && (pIfp->leakHook))
  370.         {
  371.         if (pIfp->leakHook (pDsin->sin_addr.s_addr,
  372.                             pGsin->sin_addr.s_addr,
  373.                             pNsin->sin_addr.s_addr) == OK)
  374.             {
  375.             free ((char *)rt);
  376.             return ((struct rt_entry *)NULL);
  377.             }
  378.         }
  379.     ripInsque ((NODE *)rt, (NODE *)rh);
  380.     if (routedDebug > 1)
  381.         logMsg ("Adding route to %x through %x (mask %x).n", 
  382.                 pDsin->sin_addr.s_addr, 
  383.                 pGsin->sin_addr.s_addr, 
  384.                 pNsin->sin_addr.s_addr, 0, 0, 0);
  385.     if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL | RTS_OTHER)) == 0 &&
  386.         (ret = ripSystemRouteAdd (pDsin->sin_addr.s_addr, 
  387.                                   pGsin->sin_addr.s_addr, 
  388.                                   pNsin->sin_addr.s_addr, flags)) == ERROR)
  389.         {
  390.         if (errno != EEXIST && gate->sa_family < AF_MAX)
  391.             {
  392.             if (routedDebug)
  393.                 logMsg ("Error %x adding route to %s through gateway %s.n",
  394.                         errno, 
  395.                         (int)(*afswitch[dst->sa_family].af_format) (dst),
  396.                         (int)(*afswitch[gate->sa_family].af_format) (gate),
  397.                         0, 0, 0);
  398.             }
  399.         if (routedDebug)
  400.             logMsg ("Error %x adding new route.n", errno, 0, 0, 0, 0, 0);
  401.         if (errno == ENETUNREACH)
  402.             {
  403.             ripRemque ((NODE *)rt);
  404.             free ((char *)rt);
  405.             rt = 0;
  406.             }
  407.         }
  408.     else
  409.         {
  410.         /* Store copy of metric in kernel routing table for IP group MIB. */
  411.         if (ret == OK)
  412.             {
  413.             rt->inKernel = TRUE;
  414.             ripRouteMetricSet (rt);
  415.             }
  416.         ripState.ripGlobal.rip2GlobalRouteChanges++;
  417.         }
  418.     return ((struct rt_entry *)rt);
  419.     }
  420. STATUS rtchange
  421.     (
  422.     struct rt_entry *rt,
  423.     struct sockaddr *gate,
  424.     short metric,
  425.     struct sockaddr *netmask, 
  426.     int tag,
  427.     int from,
  428.     struct interface *ifp
  429.     )
  430.     {
  431.     int add = 0, delete = 0, newgateway = 0;
  432.     struct rt_entry oldroute;
  433.     struct sockaddr_in *pDsin;
  434.     struct sockaddr_in *pGsin;
  435.     struct sockaddr_in *pNsin;
  436.     char address[32];
  437.     int flags;
  438.     BOOL wasInterfaceRoute = FALSE;
  439.     FIXLEN (gate);
  440.     FIXLEN (&(rt->rt_router));
  441.     FIXLEN (&(rt->rt_dst));
  442.     if (!equal (&rt->rt_router, gate))
  443.         {
  444.         newgateway++;
  445.         if (routedDebug > 1)
  446.             logMsg ("Changing route gateway.n", 0, 0, 0, 0, 0, 0);
  447.         }
  448.     else if (metric != rt->rt_metric)
  449.         if (routedDebug > 1)
  450.             logMsg ("Changing route metric.n", 0, 0, 0, 0, 0, 0);
  451.     if (tag != rt->rt_tag)
  452.         if (routedDebug > 1)
  453.             logMsg ("Changing route tag.n", 0, 0, 0, 0, 0, 0);
  454.     
  455.     if ((rt->rt_state & RTS_INTERNAL) == 0)
  456.         {
  457.         /*
  458.          * If changing to different router, we need to add
  459.          * new route and delete old one if in the kernel.
  460.          * If the router is the same, we need to delete
  461.          * the route if has become unreachable, or re-add
  462.          * it if it had been unreachable.
  463.          */
  464.         if (newgateway)
  465.             {
  466.             add++;
  467.             if ((rt->rt_metric != HOPCNT_INFINITY) || rt->inKernel)
  468.                 delete++;
  469.             }
  470.         else if (metric == HOPCNT_INFINITY)
  471.             delete++;
  472.         else if (rt->rt_metric == HOPCNT_INFINITY)
  473.             add++;
  474. }
  475.     /*
  476.      * If routedInput() had set the metric to HOPCNT_INFINITY + 1 to 
  477.      * trick us into adding a route with orignal metric of 15 (adjusted to 16
  478.      * to accommodate the additional hop), reset the metric to
  479.      * HOPCNT_INFINITY
  480.      */
  481.     if (metric > HOPCNT_INFINITY)
  482.         metric = HOPCNT_INFINITY;
  483.     if (delete)
  484.         oldroute = *rt;
  485.     /* Record the route flags ignoring the UP flag */
  486.     flags = rt->rt_flags & ~RTF_UP;
  487.     if ((rt->rt_state & RTS_INTERFACE) && delete)
  488.         {
  489.         wasInterfaceRoute = TRUE;
  490.         rt->rt_state &= ~RTS_INTERFACE;
  491.         rt->rt_flags |= RTF_GATEWAY;
  492.         if (metric > rt->rt_metric && delete)
  493.             if (routedDebug)
  494.                 logMsg ("Warning! %s route to interface %s (timed out).n",
  495.                         (int)(add ? "Changing" : "Deleting"),
  496.                         (int)(rt->rt_ifp ? rt->rt_ifp->int_name : "?"), 
  497.                         0, 0, 0, 0);
  498.         }
  499.     if (add)
  500.         {
  501.         rt->rt_router = *gate;
  502.         if (ifp)
  503.             rt->rt_ifp = ifp;
  504.         else
  505.             {
  506.             rt->rt_ifp = ripIfWithDstAddr (&rt->rt_router, NULL);
  507.             if (rt->rt_ifp == 0) 
  508.                 rt->rt_ifp = ripIfWithNet (&rt->rt_router);
  509.             }
  510.         if (netmask != (struct sockaddr *)NULL)
  511.             {
  512.             rt->rt_netmask = *netmask; 
  513.             }
  514.         else
  515.             {
  516.             /*
  517.              * Leave the netmask value as zero if a default route is used.
  518.              * The rt_ifp field is zero in that case, so no other value
  519.              * is available.
  520.              */
  521.             bzero ((char *)&rt->rt_netmask, sizeof (rt->rt_netmask));
  522.             rt->rt_netmask.sa_family = AF_INET;
  523.             rt->rt_netmask.sa_len = 16;
  524.             pNsin = (struct sockaddr_in *)&rt->rt_netmask;
  525.             if ( ((struct sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr)
  526.                 pNsin->sin_addr.s_addr = htonl (rt->rt_ifp->int_subnetmask);
  527.             }
  528.         }
  529.     rt->rt_metric = metric;
  530.     rt->rt_tag = tag;
  531.     if (from != 0)
  532.         rt->rt_orgrouter = from;
  533.     rt->rt_state |= RTS_CHANGED;
  534.     if (newgateway)
  535.         if (routedDebug > 1)
  536.             logMsg ("Changing route gateway.n", 0, 0, 0, 0, 0, 0);
  537.     
  538.     if (delete && !add)
  539.         {
  540.         ripRouteToAddrs (&oldroute, &pDsin, &pGsin, &pNsin);
  541.         inet_ntoa_b (pDsin->sin_addr, (char *)&address);
  542.         if (ripSystemRouteDelete (pDsin->sin_addr.s_addr, 
  543.                                   pGsin->sin_addr.s_addr, 
  544.                                   pNsin->sin_addr.s_addr, flags) == ERROR)
  545.             {
  546.             if (routedDebug)
  547.                 logMsg ("Route change - error %x removing old route.n",
  548.                         errno, 0, 0, 0, 0, 0);
  549.             }
  550.         else
  551.             {
  552.             rt->inKernel = FALSE;
  553.             ripState.ripGlobal.rip2GlobalRouteChanges++;
  554.             }
  555.         }
  556.     else if (!delete && add)
  557.         {
  558.         ripRouteToAddrs (rt, &pDsin, &pGsin, &pNsin);
  559.         if (ripSystemRouteAdd (pDsin->sin_addr.s_addr, 
  560.                                pGsin->sin_addr.s_addr, 
  561.                                pNsin->sin_addr.s_addr, flags) == ERROR)
  562.             {
  563.             if (routedDebug)
  564.                 logMsg ("Route change - error %x adding new route.n",
  565.                         errno, 0, 0, 0, 0, 0);
  566.             }
  567.         else
  568.             {
  569.             /* Store metric in kernel routing table for IP group MIB. */
  570.             rt->inKernel = TRUE;
  571.             ripRouteMetricSet (rt);
  572.             ripState.ripGlobal.rip2GlobalRouteChanges++;
  573.             }
  574.         }
  575.     else if (delete && add)
  576.         {
  577.         ripRouteToAddrs (&oldroute, &pDsin, &pGsin, &pNsin);
  578.         inet_ntoa_b (pDsin->sin_addr, (char *)&address);
  579.         if (ripSystemRouteDelete (pDsin->sin_addr.s_addr, 
  580.                                   pGsin->sin_addr.s_addr, 
  581.                                   pNsin->sin_addr.s_addr, flags) == ERROR)
  582.             {
  583.             if (routedDebug)
  584.                 logMsg ("Route change - error %x replacing old route.n",
  585.                         errno, 0, 0, 0, 0, 0);
  586.             }
  587.         else
  588.             {
  589.             /* 
  590.              * If it was an interface route, now we are changing it to a 
  591.              * gateway route. Update the flags to reflect that
  592.              */
  593.             if (wasInterfaceRoute)
  594.                 flags |= RTF_GATEWAY;
  595.             ripRouteToAddrs (rt, &pDsin, &pGsin, &pNsin);
  596.             if (ripSystemRouteAdd (pDsin->sin_addr.s_addr, 
  597.                                    pGsin->sin_addr.s_addr, 
  598.                                    pNsin->sin_addr.s_addr, flags) == ERROR)
  599.                 {
  600.                 if (routedDebug)
  601.                     logMsg ("Route change - error %x creating new route.n",
  602.                             errno, 0, 0, 0, 0, 0);
  603.                 rt->inKernel = FALSE;
  604.                 }
  605.             else
  606.                 {
  607.                 /* Store metric in kernel routing table for IP group MIB. */
  608.                 rt->inKernel = TRUE;
  609.                 ripRouteMetricSet (rt);
  610.                 ripState.ripGlobal.rip2GlobalRouteChanges++;
  611.                 }
  612.             }
  613.         }
  614.     else
  615.         {
  616.         /* Neither delete nor add - must be a metric change */ 
  617.         ripRouteMetricSet (rt);
  618.         }
  619.     return (OK);
  620.     }
  621. STATUS rtdelete (rt)
  622.     struct rt_entry *rt;
  623.     {
  624.     
  625.     char address[32];
  626.     struct sockaddr_in *pDsin;
  627.     struct sockaddr_in *pGsin;
  628.     struct sockaddr_in *pNsin;
  629.     if (routedDebug > 1)
  630.         logMsg ("Removing route entry.n", 0, 0, 0, 0, 0, 0);
  631.     FIXLEN (&(rt->rt_router));
  632.     FIXLEN (&(rt->rt_dst));
  633.     if (rt->rt_metric < HOPCNT_INFINITY || rt->inKernel)
  634.         {
  635.         if ( (rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
  636.             {
  637.             if (routedDebug)
  638.                 logMsg ("Deleting route to interface %s? (timed out?).n",
  639.                         (int)rt->rt_ifp->int_name, 0, 0, 0, 0, 0);
  640.             }
  641.         if ( (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL | RTS_OTHER)) == 0)
  642.             {
  643.             ripRouteToAddrs (rt, &pDsin, &pGsin, &pNsin);
  644.             inet_ntoa_b (pDsin->sin_addr, (char *)&address);
  645.             if (ripSystemRouteDelete (pDsin->sin_addr.s_addr, 
  646.                                       pGsin->sin_addr.s_addr, 
  647.                                       pNsin->sin_addr.s_addr, 
  648.                                       rt->rt_flags & ~RTF_UP) == ERROR)
  649.                 {
  650.                 if (routedDebug)
  651.                     logMsg ("Route delete - error %x removing route.n",
  652.                             errno, 0, 0, 0, 0, 0);
  653.                 }
  654.             else
  655.                 {
  656.                 rt->inKernel = FALSE;
  657.                 ripState.ripGlobal.rip2GlobalRouteChanges++;
  658.                 }
  659.             }
  660.         }
  661.     ripRemque ((NODE *)rt);
  662.     /*
  663.      * If this is an interface route and there exists reference to it,
  664.      * then that means that there are other interfaces that have
  665.      * addresses that match this route. We need to add new routes for
  666.      * those interfaces.
  667.      * if rt_refcnt == rt_subnets_cnt, it means that all the interfaces
  668.      * are subnetted, ie 164.10.1.1/24, 164.10.2.2/24, etc
  669.      * if rt_refcnt != rt_subnets_cnt, it means that atleast one 
  670.      * interface is not subnetted, e.g 164.10.1.1/16, 164.10.2.2/24, etc
  671.      */
  672.     if (rt->rt_state & RTS_INTERFACE && rt->rt_refcnt && 
  673.         ! (rt->rt_state & RTS_EXTERNAL))
  674.         {
  675.         if (rt->rt_refcnt != rt->rt_subnets_cnt) 
  676.             {
  677.             /*
  678.              * We are deleting a non-subnetted interface route and there
  679.              * exist other non-subnetted interfaces on the same network.
  680.              * We need to add a route for the network through one of those
  681.              * interfaces
  682.              */
  683.             ifRouteAdd (&(rt->rt_dst), rt->rt_refcnt - 1, rt->rt_subnets_cnt,
  684.                         FALSE, rt->rt_ifp->int_subnetmask);
  685.             }
  686.         else
  687.             {
  688.             /*
  689.              * We are deleting an "internal" route that we had generated
  690.              * for border gateway filtering. There exist other interfaces
  691.              * that need this route. We need to add another route through
  692.              * one of those interfaces
  693.              */
  694.             ifRouteAdd (&(rt->rt_dst), rt->rt_refcnt - 1, 
  695.                         rt->rt_subnets_cnt - 1, TRUE, 
  696.                         rt->rt_ifp->int_subnetmask);
  697.             }
  698.         }
  699.     free ((char *)rt);
  700.     
  701.     return (OK);
  702.     }
  703. void rtdeleteall (void)
  704.     {
  705.     register struct rthash *rh;
  706.     register struct rt_entry *rt;
  707.     struct rthash *base = hosthash;
  708.     int doinghost = 1;
  709.     
  710.     char address[32];
  711.     struct sockaddr_in *pDsin;
  712.     struct sockaddr_in *pGsin;
  713.     struct sockaddr_in *pNsin;
  714.     again:
  715.     for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
  716.         {
  717.         rt = rh->rt_forw;
  718. for (; rt != (struct rt_entry *)rh; 
  719.                  rt = ( (struct rt_entry *)rh)->rt_forw)
  720.             {
  721.             /* Remove the entry from the kernel routing table if present. */
  722.             if ( (rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL|RTS_OTHER)) == 0)
  723.                 {
  724.                 ripRouteToAddrs (rt, &pDsin, &pGsin, &pNsin);
  725.                 inet_ntoa_b (pDsin->sin_addr, (char *)&address);
  726.                 /*
  727.                  * Expired route entries were already removed from the kernel
  728.                  * routing table, but may remain in the RIP routing table
  729.                  * if the garbage collection interval has not passed. 
  730.                  * These entries are usually detectable by their infinite 
  731.                  * metric, but all metrics are infinite in this case.
  732.                  * However, the pointer to the kernel route will be
  733.                  * NULL, so the following call will not attempt to
  734.                  * delete a (non-existent) expired entry.
  735.                  */
  736.                 if (rt->inKernel)
  737.                     {
  738.                     if (ripSystemRouteDelete (pDsin->sin_addr.s_addr, 
  739.                                               pGsin->sin_addr.s_addr, 
  740.                                               pNsin->sin_addr.s_addr, 
  741.                                               0) == ERROR)
  742.                         {
  743.                         if (routedDebug) 
  744.                             logMsg ("Error %x removing route from kernel table.n", 
  745.                                     errno, 0, 0, 0, 0, 0);
  746.                         }
  747.                     else
  748.                         {
  749.                         rt->inKernel = FALSE;
  750.                         ripState.ripGlobal.rip2GlobalRouteChanges++;
  751.                         }
  752.                     }
  753.                 }
  754.             /* Remove the entry from the RIP routing table. */
  755.             ((struct rt_entry *)rh)->rt_forw = rt->rt_forw;
  756.             free ((char *)rt);
  757.             }
  758.         }
  759.     if (doinghost)
  760.         {
  761.         doinghost = 0;
  762.         base = nethash;
  763.         goto again;
  764.         }
  765.     return;
  766.     }
  767. /*
  768.  * If we have an interface to the wide, wide world,
  769.  * add an entry for an Internet default route (wildcard) to the internal
  770.  * tables and advertise it.  This route is not added to the kernel routes,
  771.  * but this entry prevents us from listening to other people's defaults
  772.  * and installing them in the kernel here.
  773.  */
  774. void rtdefault (void)
  775.     {
  776.     rtadd ( (struct sockaddr *)&inet_default, (struct sockaddr *)&inet_default,
  777.             1, RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL, NULL,
  778.             M2_ipRouteProto_rip, 0, 0, NULL);
  779.     }
  780. void routedTableInit (void)
  781.     {
  782.     register struct rthash *rh;
  783.     
  784.     for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
  785.         rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
  786.     for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
  787.         rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
  788.     }
  789. /******************************************************************************
  790. *
  791. * ripSystemRouteAdd - add a RIP route to the system routing database
  792. *
  793. * This routine adds the route to the system routing database using the
  794. * method which the particular product supports.
  795. *
  796. * RETURNS: ERROR or OK (return value from selected add method)
  797. *
  798. * ERRNO: N/A
  799. *
  800. * NOMANUAL
  801. */
  802. LOCAL STATUS ripSystemRouteAdd 
  803.     (
  804.     long             dstIp,     /* destination address, network order */
  805.     long             gateIp,     /* gateway address, network order */
  806.     long             mask,       /* mask for destination, network order */
  807.     int              flags       /* route flags */ 
  808.     )
  809.     {
  810. #ifdef ROUTER_STACK
  811.     ROUTE_DESC routeDesc;
  812.     struct sockaddr_in dstAddr;
  813.     struct sockaddr_in netmask;
  814.     struct sockaddr_in gateway;
  815.     /* Initialize the routeDesc structure and the sockaddr structures */
  816.     bzero ((char *)&routeDesc, sizeof (routeDesc));
  817.     routeDesc.pDstAddr = (struct sockaddr *)&dstAddr;
  818.     routeDesc.pNetmask = (struct sockaddr *)&netmask;
  819.     routeDesc.pGateway = (struct sockaddr *)&gateway;
  820.     bzero ((char *)&dstAddr, sizeof (struct sockaddr_in));
  821.     bzero ((char *)&netmask, sizeof (struct sockaddr_in));
  822.     bzero ((char *)&gateway, sizeof (struct sockaddr_in));
  823.     dstAddr.sin_len = sizeof (struct sockaddr_in);
  824.     netmask.sin_len = sizeof (struct sockaddr_in);
  825.     gateway.sin_len = sizeof (struct sockaddr_in);
  826.     dstAddr.sin_family = AF_INET;
  827.     netmask.sin_family = AF_INET;
  828.     gateway.sin_family = AF_INET;
  829.     dstAddr.sin_addr.s_addr = dstIp;
  830.     netmask.sin_addr.s_addr = mask;
  831.     gateway.sin_addr.s_addr = gateIp;
  832.     routeDesc.flags = flags;
  833.     routeDesc.protoId = M2_ipRouteProto_rip;
  834.     /* 
  835.      * If it is a host route, set netmask to NULL. RIP internally
  836.      * assigns a host route the netmask of the interface. But the system
  837.      * expect a NULL or all zero's netmask.
  838.      */
  839.     if (flags & RTF_HOST)
  840.         routeDesc.pNetmask = NULL;
  841.     /* Now add the route */
  842.     return (routeEntryAdd (&routeDesc));
  843. #else
  844.     /* 
  845.      * If it is a host route, set netmask to NULL. RIP internally
  846.      * assigns a host route the netmask of the interface. But the system
  847.      * expect a NULL netmask
  848.      */
  849.     if (flags & RTF_HOST)
  850.         mask = 0;
  851.     return (mRouteEntryAdd (dstIp, gateIp, mask, 0, flags, 
  852.                             M2_ipRouteProto_rip));
  853. #endif /* ROUTER_STACK */
  854.     }
  855. /******************************************************************************
  856. *
  857. * ripSystemRouteDelete - delete a RIP route from the system routing database
  858. *
  859. * This routine deletes a route from the system routing database using the
  860. * method which the particular product supports.
  861. *
  862. * RETURNS: ERROR or OK (return value from selected delete method)
  863. *
  864. * ERRNO: N/A
  865. *
  866. * NOMANUAL
  867. */
  868. LOCAL STATUS ripSystemRouteDelete 
  869.     (
  870.     long dstIp,     /* destination address, network order */
  871.     long gateIp,     /* gateway address, network order */
  872.     long mask,       /* mask for destination, network order */
  873.     int flags       /* route flags */ 
  874.     )
  875.     {
  876. #ifdef ROUTER_STACK
  877.     ROUTE_DESC routeDesc;
  878.     struct sockaddr_in dstAddr;
  879.     struct sockaddr_in netmask;
  880.     struct sockaddr_in gateway;
  881.     /* Initialize the routeDesc structure and the sockaddr structures */
  882.     bzero ((char *)&routeDesc, sizeof (routeDesc));
  883.     routeDesc.pDstAddr = (struct sockaddr *)&dstAddr;
  884.     routeDesc.pNetmask = (struct sockaddr *)&netmask;
  885.     routeDesc.pGateway = (struct sockaddr *)&gateway;
  886.     bzero ((char *)&dstAddr, sizeof (struct sockaddr_in));
  887.     bzero ((char *)&netmask, sizeof (struct sockaddr_in));
  888.     bzero ((char *)&gateway, sizeof (struct sockaddr_in));
  889.     dstAddr.sin_len = sizeof (struct sockaddr_in);
  890.     netmask.sin_len = sizeof (struct sockaddr_in);
  891.     gateway.sin_len = sizeof (struct sockaddr_in);
  892.     dstAddr.sin_family = AF_INET;
  893.     netmask.sin_family = AF_INET;
  894.     gateway.sin_family = AF_INET;
  895.     dstAddr.sin_addr.s_addr = dstIp;
  896.     netmask.sin_addr.s_addr = mask;
  897.     gateway.sin_addr.s_addr = gateIp;
  898.     routeDesc.flags = flags;
  899.     routeDesc.protoId = M2_ipRouteProto_rip;
  900.     /* 
  901.      * If it is a host route, set netmask to NULL. RIP internally
  902.      * assigns a host route the netmask of the interface. But the system
  903.      * expect a NULL or all zero's netmask.
  904.      */
  905.     if (flags & RTF_HOST)
  906.         routeDesc.pNetmask = NULL;
  907.     /* Now delete the route */
  908.     return (routeEntryDelete (&routeDesc));
  909. #else
  910.     /* 
  911.      * If it is a host route, set netmask to NULL. RIP internally
  912.      * assigns a host route the netmask of the interface. But the system
  913.      * expect a NULL or all zero's netmask.
  914.      */
  915.     if (flags & RTF_HOST)
  916.         mask = 0;
  917.     return (mRouteEntryDelete (dstIp, gateIp, mask, 0, flags, 
  918.                                M2_ipRouteProto_rip));
  919. #endif /* ROUTER_STACK */
  920.     }
  921. /******************************************************************************
  922. *
  923. * ripRouteMetricSet - Set the metric for the RIP route
  924. *
  925. * This routine changes the metric of the RIP route that is kept in the
  926. * system Routing database.
  927. * The parameter <pRtEntry> describes the RIP route that is kept in RIP's
  928. * private database. It also contains the metric value that is to be set.
  929. *
  930. * This routine calls the routing extensions function routeMetricSet() 
  931. * to set the metric
  932. *
  933. * RETURNS: N/A
  934. *
  935. * ERRNO: N/A
  936. *
  937. * NOMANUAL
  938. */
  939. void ripRouteMetricSet 
  940.     (
  941.     struct rt_entry * pRtEntry /* Route entry describing the */
  942.      /* Kernel route to update */
  943.     )
  944.     {
  945.     struct sockaddr_in * pDsin;
  946.     struct sockaddr_in * pGsin;
  947.     struct sockaddr_in * pNsin;
  948.     
  949.     /*
  950.      * Retrieve the destination and netmask values from the
  951.      * corresponding fields in the RIP route entry structure
  952.      */
  953.     ripRouteToAddrs (pRtEntry, &pDsin, &pGsin, &pNsin);
  954.     /* 
  955.      * If it is a host route, set netmask to NULL. RIP internally
  956.      * assigns a host route the netmask of the interface. But the system
  957.      * overrides that and stores the route as a host route with a NULL mask.
  958.      * (which is the right thing to do). So we set the netmask field to
  959.      * NULL so that the route lookup happens fine.
  960.      */
  961.     if (pRtEntry->rt_flags & RTF_HOST)
  962.         pNsin = NULL;
  963.     if (routedDebug > 2)
  964.         {
  965.         logMsg ("ripRouteMetricSet: setting new metric = %d forn", 
  966.                 pRtEntry->rt_metric , 0, 0, 0, 0, 0);
  967.         ripSockaddrPrint ((struct sockaddr *)pDsin);
  968.         ripSockaddrPrint ((struct sockaddr *)pNsin);
  969.         ripSockaddrPrint ((struct sockaddr *)pGsin);
  970.         }
  971.     /* Now set the route metric */
  972.     if (routeMetricSet ((struct sockaddr *)pDsin, (struct sockaddr *)pNsin,
  973.                         M2_ipRouteProto_rip, pRtEntry->rt_metric) == ERROR) 
  974.         {
  975.         if (routedDebug) 
  976.             logMsg ("Couldn't set metric for rtEntry = %x.n", (int)pRtEntry, 0, 
  977.                     0, 0, 0, 0);
  978.         }
  979.     }
  980. /*****************************************************************************
  981. *
  982. * ripInsque - insert node in list after specified node.
  983. *
  984. * Portable version of _insque ().
  985. *
  986. * NOMANUAL
  987. */
  988.  
  989. LOCAL void ripInsque
  990.     (
  991.     NODE *pNode,
  992.     NODE *pPrev
  993.     )
  994.     {
  995.     NODE *pNext;
  996.  
  997.     pNext = pPrev->next;
  998.     pPrev->next = pNode;
  999.     pNext->previous = pNode;
  1000.     pNode->next = pNext;
  1001.     pNode->previous = pPrev;
  1002.     }
  1003.  
  1004. /*****************************************************************************
  1005. *
  1006. * ripRemque - remove specified node in list.
  1007. *
  1008. * Portable version of _remque ().
  1009. *
  1010. * NOMANUAL
  1011. */
  1012.  
  1013. LOCAL void ripRemque 
  1014.     (
  1015.     NODE * pNode /* Node to remove */
  1016.     )
  1017.     {
  1018.     pNode->previous->next = pNode->next;
  1019.     pNode->next->previous = pNode->previous;
  1020.     }