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

MultiPlatform

  1. /* routeUtilLib.c - miscellaneous utilities for routing interface library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01e,07aug01,spm  fixed lookup routine to retrieve default route entry
  7. 01d,03aug01,spm  added flag to prevent incorrect interface reference count
  8. 01c,02aug01,spm  added virtual stack support
  9. 01b,02aug01,spm  cleanup: replaced duplicate copy routine with routeDescFill;
  10.                  changed routeMetricInfoFromDescCopy to shorter name
  11. 01a,31jul01,spm  extracted from version 03s of routeEntryLib.c module
  12. */
  13. /*
  14. DESCRIPTION
  15. This library contains miscellaneous routines which handle duplicate routes
  16. to the same destination address. The router stack version of the network
  17. stack uses these routines support the add, delete, and change operations.
  18. None of the routines in this library are published or available to customers.
  19. INTERNAL
  20. All the routines within this library execute while the system holds the
  21. internal table lock, if needed.
  22. NOMANUAL
  23. */
  24. #ifdef ROUTER_STACK              /* only build for router stack */
  25. /* includes */
  26. #include "vxWorks.h"
  27. #include "memPartLib.h"     /* for KHEAP_FREE definition */
  28. #include "routeEnhLib.h"
  29. #ifdef VIRTUAL_STACK
  30. #include "netinet/vsLib.h"    /* for rt_tables definition */
  31. #endif
  32. #define SOCKADDR_IN(s) (((struct sockaddr_in*)(s))->sin_addr.s_addr)
  33. /* forward declarations */
  34. IMPORT STATUS routeCallBackSend (int, void *);
  35. IMPORT STATUS routeSocketMessageSend (int, ROUTE_DESC *);
  36. void routeDescFill (ROUTE_ENTRY *, ROUTE_DESC *, BOOL);
  37. void routeMetricsCopy (ROUTE_DESC *, ROUTE_ENTRY *);
  38. ROUTE_ENTRY * routeLookup (struct sockaddr *, ULONG *, int);
  39. /*******************************************************************************
  40. *
  41. * routeLookup - fetch an entry in the routing table
  42. *
  43. * This routine searches the routing table for an entry which matches the
  44. * destination address and the <pNetmask> and <protoId> parameters, if
  45. * provided. It returns a pointer to the route for later changes by
  46. * public routines. A mask value of zero retrieves a host-specific route,
  47. * if any.
  48. *
  49. * NOTE: If the <protoId> value is not zero, this routine searches the
  50. *       duplicate routes for a matching entry. That situation requires
  51. *       mutual exclusion protection with the internal lock. Otherwise,
  52. *       no additional protection is needed.
  53. *
  54. * RETURNS: Pointer to matching route entry, or NULL if none.
  55. *
  56. * NOMANUAL
  57. */
  58. ROUTE_ENTRY * routeLookup
  59.     (
  60.     struct sockaddr * pDest,  /* IP address reachable with matching route */
  61.     ULONG * pMask,  /* netmask value, in network byte order */
  62.     int protoId  /* route source from m2Lib.h, or 0 for any. */
  63.     )
  64.     {
  65.     struct radix_node_head * pHead = rt_tables[pDest->sa_family];
  66.     struct radix_node * pNode;        /* radix tree entry for route */
  67.     struct rtentry * pRoute = NULL;   /* candidate for matching route */
  68.     ROUTE_ENTRY * pMatch = NULL;      /* matching route entry */
  69.     struct sockaddr_in netmask;       /* netmask value, internal format */
  70.     char * pNetmask = NULL;           /* target netmask value from tree */
  71.     struct rtentry * pNextRoute;
  72.     STATUS result = ERROR;            /* OK indicates a successful search */
  73.     int  s;
  74.     if (pHead == NULL)
  75.         {
  76.         /* No route table exists for the given address family. */
  77.         return (NULL);
  78.         }
  79.     bzero ( (char *)&netmask, sizeof (struct sockaddr_in));
  80.     s = splnet ();
  81.     /*
  82.      * If a specific netmask match is required, find the target value
  83.      * (a pointer to the stored netmask entry) which will determine
  84.      * whether the match exists. A mask value of zero indicates a
  85.      * host-specific route, which does not contain a netmask entry.
  86.      */
  87.     if (pMask && *pMask)
  88.         {
  89.         /* Setup data structure to search mask's tree for given value. */
  90.         netmask.sin_family = AF_INET;
  91.         netmask.sin_len = sizeof (struct sockaddr_in);
  92.         netmask.sin_addr.s_addr = *pMask;
  93.         TOS_SET (&netmask, 0x1f);
  94.         in_socktrim (&netmask);    /* Adjust length field for tree search. */
  95.         /* Search for netmask from corresponding tree. */
  96.         pNode = rn_addmask (&netmask, 1, pHead->rnh_treetop->rn_off);
  97.         if (pNode == 0)
  98.             {
  99.             /* No route currently uses the specified netmask. */
  100. #ifdef DEBUG
  101.             logMsg ("routeLookup: requested mask does not exist.n",
  102.                     0, 0, 0, 0, 0, 0);
  103. #endif
  104.             splx(s);
  105.             return (NULL);
  106.             }
  107.         pNetmask = pNode->rn_key;
  108.         }
  109.     pNode = pHead->rnh_matchaddr ((caddr_t)pDest, pHead);
  110.     if (pNode && ((pNode->rn_flags & RNF_ROOT) == 0))
  111.         {
  112.         /* Possible match found. Save for later use. */
  113.         pRoute = (struct rtentry *)pNode;
  114.         }
  115.     else
  116.         {
  117.         /* No route matches the given key. */
  118.         splx (s);
  119.         return (NULL);
  120.         }
  121. #ifdef DEBUG
  122.     logMsg ("routeLookup: candidate for match at %p.n", pNode,
  123.             0, 0, 0, 0, 0);
  124. #endif
  125.     /*
  126.      * Compare the set of routes available with the initial key
  127.      * against the desired values. Each entry in the chain of
  128.      * routes with duplicate keys uses a different netmask value.
  129.      *
  130.      * NOTE: The pNode value is not necessarily the start of the
  131.      * chain. It is the first entry in the chain with a short
  132.      * enough netmask to produce a match against the destination.
  133.      */
  134.     for ( ; pRoute != NULL; pRoute = pNextRoute)
  135.         {
  136.         /* Select the next route candidate in case a test fails. */
  137.         pNextRoute = (struct rtentry *)
  138.                            ((struct radix_node *)pRoute)->rn_dupedkey;
  139.         if (pMask)
  140.             {
  141.             /*
  142.              * Check mask of route against corresponding entry from
  143.              * the stored netmasks (derived from the given value).
  144.              */
  145. #ifdef DEBUG
  146.             logMsg ("routeLookup: checking against specific mask.n",
  147.                     0, 0, 0, 0, 0, 0);
  148. #endif
  149.             if (*pMask)
  150.                 {
  151.                 if ( ((struct radix_node *)pRoute)->rn_mask != pNetmask)
  152.                     continue;   /* Mask values do not match. */
  153.                 }
  154.             else if ( ( (struct sockaddr_in *)pDest)->sin_addr.s_addr)
  155.                 {
  156.                 /* Searching for a host-specific route (no netmask entry). */
  157.                 if ( ((struct radix_node *)pRoute)->rn_mask != 0)
  158.                     continue;   /* Entry is not a host route. */
  159.                 }
  160.             }
  161.         /*
  162.          * Candidate passed any mask requirements. Search for entries
  163.          * which match the specified route source.
  164.          */
  165. #ifdef DEBUG
  166.         logMsg ("routeLookup: Current mask is OK.n", 0, 0, 0, 0, 0, 0);
  167. #endif
  168.         if (protoId)
  169.             {
  170.             /* Check source of route against specified value. */
  171. #ifdef DEBUG
  172.             logMsg ("routeLookup: testing protocol ID.n",
  173.                     0, 0, 0, 0, 0, 0);
  174. #endif
  175.             for (pMatch = (ROUTE_ENTRY *)pRoute; pMatch != NULL;
  176.                    pMatch = pMatch->diffNode.pFrwd)
  177.                 {
  178.                 if (RT_PROTO_GET(ROUTE_ENTRY_KEY(pMatch)) == protoId)
  179.                     break;
  180.                 }
  181.             if (pMatch == NULL)   /* Route protocol values do not match. */
  182.                 continue;
  183. #ifdef DEBUG
  184.             logMsg ("routeLookup: Current protocol ID is OK.n",
  185.                     0, 0, 0, 0, 0, 0);
  186. #endif
  187.             }
  188.         else
  189.             {
  190.             /*
  191.              * No route source is specified. Accept the entry
  192.              * which met any mask criteria.
  193.              */
  194.             pMatch = (ROUTE_ENTRY *)pRoute;
  195.             }
  196.  
  197.         /* The candidate route entry met all criteria. Stop the search. */
  198.         result = OK;
  199.         break;
  200.         }
  201.     if (result == OK)
  202.         {
  203.         /* Increase the reference count before returning the matching entry. */
  204.         pMatch->rtEntry.rt_refcnt++;
  205.         }
  206.     else
  207.         pMatch = NULL;
  208.     splx (s);
  209.     return (pMatch);
  210.     }
  211. /*******************************************************************************
  212. *
  213. * routeEntryFind - find a route entry and the appropriate location
  214. *
  215. * This routine searches the extended lists attached to the <pRoute>
  216. * entry which is visible to the IP forwarding process. It retrieves
  217. * any route entry which matches the supplied protocol identifier and
  218. * gateway. If the protocol is not specified, the routine selects an
  219. * entry in the first protocol group. If the gateway is not specified,
  220. * it retrieves the initial route entry in the selected group.
  221. *
  222. * Both the change and delete operations require a matching route. The add
  223. * operation fails in this situation, since the gateway and protocol 
  224. * identifier must be unique for a particular destination address and netmask.
  225. *
  226. * This routine also provides the adjacent entries for a route based on
  227. * the specified weight value, if pointers to retrieve those entries are
  228. * available. The first entry in a group uses a lower weight than all
  229. * subsequent entries from the same protocol. It is connected to the initial
  230. * entries from other groups and t * next entry with the same protocol type.
  231. * Subsequent entries in a group are only connected to successors and
  232. * predecessors within that group.
  233. *
  234. * The add and change operations use this neighboring route information
  235. * to store a new or altered entry at the correct location. The delete
  236. * operation uses a <weight> value of 0 to skip the search for neighboring
  237. * routes since it does not provide pointers to retrieve those values.
  238. *
  239. * NOTE: This routine requires the mutual exclusion protection for
  240. *       the routing table to prevent moving or replacing the matching
  241. *       route's adjacent entries.
  242. *
  243. * RETURNS: Pointer to existing route, or NULL if none.
  244. *
  245. * NOMANUAL
  246. */
  247. ROUTE_ENTRY * routeEntryFind
  248.     (
  249.     ROUTE_ENTRY * pRoute,  /* primary route for destination/netmask */
  250.     short protoId,  /* protocol identifer for route */
  251.     struct sockaddr * pGateway, /* next hop gateway for route */
  252.     ROUTE_ENTRY ** ppGroup,  /* initial entry (head) of existing group */
  253.     ROUTE_ENTRY ** ppLastGroup, /* predecessor if head of group changes */
  254.     ROUTE_ENTRY ** ppNextGroup, /* successor if head of group changes */
  255.     ROUTE_ENTRY ** ppLast,  /* previous entry in matching group */
  256.     ROUTE_ENTRY ** ppNext,  /* next entry in matching group */
  257.     UCHAR weight  /* weight value for route, 0 for delete */
  258.     )
  259.     {
  260.     ROUTE_ENTRY * pGroup;    /* initial route entry with matching protocol */
  261.     ROUTE_ENTRY * pMatch = NULL;  /* duplicate route entry, if any. */
  262.     ROUTE_ENTRY * pNextGroup = NULL;  /* Group with higher minimum weight. */
  263.     ROUTE_ENTRY * pLastGroup = NULL;  /* Previous group entry in list. */
  264.     ROUTE_ENTRY * pBack = NULL;   /* Preceding route entry in group. */
  265.     ROUTE_ENTRY * pNext = NULL;   /* Next route entry in group. */
  266.     ROUTE_ENTRY * pTemp;          /* Loop index. */
  267.     BOOL gatewayFlag;    /* Gateway value specified? */
  268.     UCHAR nextWeight;    /* Weight for initial group entry after increase. */
  269.     if (pGateway == NULL || SOCKADDR_IN (pGateway) == 0)
  270.         gatewayFlag = FALSE;
  271.     else
  272.         gatewayFlag = TRUE;
  273.  
  274.     /*
  275.      * Find the group which matches the protocol for the targeted route,
  276.      * if any. Use the first group if no value is specified. This search
  277.      * also finds an adjacent group if no match occurs or if the protocol
  278.      * does not match the first group and the provided weight value is less
  279.      * than the initial entry in the matching group.
  280.      */
  281.     for (pGroup = pRoute; pGroup != NULL; pGroup = pGroup->diffNode.pFrwd)
  282.         {
  283.         if (protoId == 0)    /* No protocol specified - use initial group. */
  284.             break;
  285.         if (RT_PROTO_GET(ROUTE_ENTRY_KEY(pGroup)) == protoId)
  286.             break;
  287.         /*
  288.          * If the weight value for the targeted route is less than
  289.          * the current minimum in an earlier group (which therefore
  290.          * uses a lower weight than the matching group), save the
  291.          * new successor for the matching group. Ignore this test
  292.          * for the delete operation, which selects a new adjacent
  293.          * group separately, if needed.
  294.          */
  295.         if (weight && pNextGroup == NULL &&
  296.                 weight < pGroup->rtEntry.rt_rmx.weight)
  297.             {
  298.             pNextGroup = pGroup;
  299. #ifdef DEBUG
  300.             logMsg ("routeEntryFind: inserting ahead of group at %x.n",
  301.                     pNextGroup, 0, 0, 0, 0, 0);
  302. #endif
  303.             }
  304.         /*
  305.          * Save the current group entry, which will eventually equal the
  306.          * tail of the list if no matching group exists. That final entry
  307.          * is required when creating a new group with a larger minimum
  308.          * weight than all existing groups.
  309.          */
  310.         pLastGroup = pGroup;
  311.         }
  312.     /*
  313.      * Assign the preceding group if the weight value inserts a new group
  314.      * into the list or promotes an existing group to an earlier position.
  315.      */
  316.     if (pNextGroup)
  317.         {
  318.         pLastGroup = pNextGroup->diffNode.pBack;
  319.         }
  320.     /*
  321.      * Find the specific route entry which matches the supplied gateway
  322.      * address within the selected group. Use the initial entry if no
  323.      * value is specified. The delete and change operations require a
  324.      * match, but the add operation fails in that case.
  325.      *
  326.      * This search also finds the neighboring routes within the matching
  327.      * group based on any specified weight value.
  328.      */
  329.     for (pTemp = pGroup; pTemp != NULL; pTemp = pTemp->sameNode.pFrwd)
  330.         {
  331.         /*
  332.          * Save the first entry which matches the specified gateway.
  333.          * The second condition is not strictly necessary, since each
  334.          * gateway value is unique, but bypasses needless tests once
  335.          * a match is found.
  336.          */
  337.         if (gatewayFlag && pMatch == NULL)
  338.             {
  339.             if (ROUTE_ENTRY_GATEWAY (pTemp)->sa_family == AF_LINK)
  340.                 {
  341.                 /*
  342.                  * The gateway field contains an ARP template. The entry
  343.                  * only matches for a search using the interface's assigned
  344.                  * IP address as the gateway.
  345.                  */
  346.                 if (SOCKADDR_IN (pTemp->rtEntry.rt_ifa->ifa_addr)
  347.                                         == SOCKADDR_IN (pGateway))
  348.                     {
  349.                     /* Specified route entry exists - save the match. */
  350.                     pMatch = pTemp;
  351.                     }
  352.                 }
  353.             else if (SOCKADDR_IN (ROUTE_ENTRY_GATEWAY (pTemp))
  354.                                         == SOCKADDR_IN (pGateway))
  355.                 {
  356.                 /* Specified route entry exists - save the match. */
  357.                 pMatch = pTemp;
  358.                 }
  359.             }
  360.         if (gatewayFlag == FALSE && pMatch == NULL) 
  361.             {
  362.             /* Use the initial entry if no gateway is specified. */
  363.             pMatch = pGroup;
  364.             }
  365.         /*
  366.          * The delete operation does not provide a weight value. Save
  367.          * the neighboring route for the add and change operations.
  368.          */
  369.         if (weight && pNext == NULL &&
  370.                 weight < pTemp->rtEntry.rt_rmx.weight)
  371.             {
  372.             pNext = pTemp;
  373.             }
  374.         /* Halt the search after finding the matching entry and location. */
  375.         if (pMatch && pNext)
  376.             break;
  377.         /*
  378.          * Save the current route, which eventually stores the last
  379.          * entry in the list. That value is only needed if the weight
  380.          * is larger than all existing entries in the group.
  381.          */
  382.         pBack = pTemp;
  383.         }
  384.     /*
  385.      * Save the correct predecessor if the weight does not place the
  386.      * corresponding route at the end of the list. That value will
  387.      * equal NULL if the new position is the head of the list.
  388.      *
  389.      * Otherwise, the preceding entry already equals the last item in the
  390.      * list (which occurs when appending a new route with the maximum weight
  391.      * to an existing group) or remains NULL (if the group does not exist).
  392.      * No correction is needed in either case.
  393.      */
  394.     if (pNext)
  395.         {
  396.         pBack = pNext->sameNode.pBack;
  397.         }
  398.     /*
  399.      * Update the chosen adjacent group, if needed. The results of the
  400.      * previous search are only valid if the weight value corresponds
  401.      * to the initial entry in a group, the selected route is not part
  402.      * of the first group, and the weight is reduced enough to alter
  403.      * the relative position of the selected group.
  404.      */
  405.     if (pNext == pGroup)
  406.         {
  407.         /*
  408.          * The specified weight corresponds to the initial entry in
  409.          * a group, so either the weight of the group is reduced or it
  410.          * corresponds to the first entry in a new group. Update the
  411.          * neighboring groups selected with the earlier search if needed.
  412.          */
  413.         if (pGroup && pNextGroup == NULL)
  414.             {
  415.             /*
  416.              * The group exists and no successor is assigned, so the
  417.              * earlier search found a matching group before detecting
  418.              * a different group with a higher weight than the specified
  419.              * value. This condition indicates that the reduced weight does
  420.              * not change the relative location of the matching group.
  421.              */
  422.             pNextGroup = pGroup->diffNode.pFrwd;
  423.             pLastGroup = pGroup->diffNode.pBack;
  424.             }
  425.         }
  426.     /*
  427.      * Finish assigning the adjacent group, if needed. The earlier search
  428.      * only selects an adjacent group when the specified weight value is
  429.      * less than the weight of the initial entry in the matching group or
  430.      * is the first entry in a new group.
  431.      */
  432.     if (pNext != pGroup && weight)
  433.         {
  434.         /*
  435.          * Find the correct adjacent group for an unchanged weight or an
  436.          * increase in the weight value of an entry in an existing group.
  437.          */
  438.         if (pMatch == NULL || pMatch != pGroup)
  439.             {
  440.             /*
  441.              * If the selected route is not the initial entry, it is
  442.              * not connected to any adjacent groups.
  443.              */
  444.             pLastGroup = pNextGroup = NULL;
  445.             }
  446.         else if (weight == pMatch->rtEntry.rt_rmx.weight)
  447.             {
  448.             /*
  449.              * The earlier search only finds an adjacent group when the
  450.              * weight of the group is reduced. Set the correct adjacent
  451.              * groups since the location in the group list is unchanged.
  452.              */
  453.             pNextGroup = pGroup->diffNode.pFrwd;
  454.             pLastGroup = pGroup->diffNode.pBack;
  455.             }
  456.         else
  457.             {
  458.             /*
  459.              * The initial entry in the group list uses an increased
  460.              * weight. Set the correct weight value and find the new
  461.              * adjacent group.
  462.              */
  463.             pTemp = pMatch->sameNode.pFrwd;
  464.             nextWeight = weight;
  465.             /*
  466.              * Use the weight value of the next initial group entry if 
  467.              * the new weight will change the location of the current
  468.              * initial entry in the group.  
  469.              */
  470.             if (pTemp && weight > pTemp->rtEntry.rt_rmx.weight)
  471.                 nextWeight = pTemp->rtEntry.rt_rmx.weight;
  472.             if (pMatch->rtEntry.rt_rmx.weight == nextWeight)
  473.                 {
  474.                 /*
  475.                  * The next entry in the list used the same weight
  476.                  * as the initial entry, so the position is unchanged.
  477.                  */
  478.                 pNextGroup = pGroup->diffNode.pFrwd;
  479.                 pLastGroup = pGroup->diffNode.pBack;
  480.                 }
  481.             else
  482.                 {
  483.                 /*
  484.                  * The minimum weight of the group increased. Find the
  485.                  * new location.
  486.                  */
  487.                 for (pTemp = pGroup; pTemp != NULL;
  488.                          pTemp = pTemp->diffNode.pFrwd)
  489.                     {
  490.                     if (nextWeight < pTemp->rtEntry.rt_rmx.weight)
  491.                         {
  492.                         pNextGroup = pTemp;
  493.                         break;
  494.                         }
  495.                     /*
  496.                      * Save the current entry in case the next entry
  497.                      * is the correct successor.
  498.                      */
  499.                     pLastGroup = pTemp;
  500.                     }
  501.                 /*
  502.                  * Set the preceding group to the correct value if the
  503.                  * increased weight does not change the relative location
  504.                  * of the group.
  505.                  */
  506.                 if (pLastGroup == pGroup)
  507.                     pLastGroup = pGroup->diffNode.pBack;
  508.                 }
  509.             }
  510.         }
  511.     /*
  512.      * Correct the adjacent route within the matching group, if needed.
  513.      * That search places a route after any other entries with the same
  514.      * weight. This behavior is not correct when the weight of an existing
  515.      * entry does not change.
  516.      */
  517.     if (pMatch && weight == pMatch->rtEntry.rt_rmx.weight)
  518.         {
  519.         pNext = pMatch->sameNode.pFrwd;
  520.         pBack = pMatch->sameNode.pBack;
  521.         }
  522.     /*
  523.      * Save the initial entry in the group and any adjacent entries in
  524.      * the supplied parameters. The delete operation does not retrieve
  525.      * any neighboring routes or specify the weight needed to assign
  526.      * those values.
  527.      */
  528.     if (ppGroup)
  529.         *ppGroup = pGroup;
  530.     if (ppLastGroup)
  531.         *ppLastGroup = pLastGroup;
  532.     if (ppNextGroup)
  533.         *ppNextGroup = pNextGroup;
  534.     if (ppLast)
  535.         *ppLast = pBack;
  536.     if (ppNext)
  537.         *ppNext = pNext;
  538.     return (pMatch);
  539.     }
  540. /*******************************************************************************
  541. *
  542. * routeDescFill - copies the relevant routing information 
  543. *
  544. * This routine copies routing information from a ROUTE_ENTRY structure
  545. * to the corresponding fields in a ROUTE_DESC structure. The callback
  546. * messages and the results of the public lookup routine use the resulting
  547. * structure. The delete operation provides a <copyAllFlag> parameter of
  548. * FALSE since it already assigns the destination and netmask of the given
  549. * <pRouteDesc> structure. All other operations set that parameter to TRUE
  550. * to get all relevant values from the route entry which the <pRoute>
  551. * parameter provides.
  552. *
  553. * RETURNS: N/A
  554. *
  555. * NOMANUAL
  556. */
  557. void routeDescFill
  558.     (
  559.     ROUTE_ENTRY * pRouteEntry,  /* reference to existing route */
  560.     ROUTE_DESC * pRouteDesc,  /* buffers for route information */
  561.     BOOL copyAllFlag  /* copy all information? */
  562.     )
  563.     {
  564.     if (copyAllFlag)
  565.         {
  566.         if (ROUTE_ENTRY_KEY (pRouteEntry) != NULL)
  567.             bcopy ( (char*) (ROUTE_ENTRY_KEY (pRouteEntry)),
  568.                    (char*) (pRouteDesc->pDstAddr), sizeof (struct sockaddr));
  569.         if ( (ROUTE_ENTRY_MASK (pRouteEntry) != NULL) &&
  570.             (pRouteDesc->pNetmask != 0))
  571.             bcopy ( (char*)ROUTE_ENTRY_MASK (pRouteEntry),
  572.                    (char*)pRouteDesc->pNetmask, sizeof (struct sockaddr));
  573.         else  /* If it is a host route, set netmask to NULL */
  574.             pRouteDesc->pNetmask = NULL;
  575.         }
  576.     if ( (ROUTE_ENTRY_GATEWAY (pRouteEntry))->sa_family == AF_LINK)
  577. {
  578.         bcopy ( (char*)pRouteEntry->rtEntry.rt_ifa->ifa_addr,
  579.                (char*)pRouteDesc->pGateway, sizeof (struct sockaddr));
  580.         }
  581.     else
  582. {
  583.         bcopy ( (char*)ROUTE_ENTRY_GATEWAY (pRouteEntry),
  584.                (char*)pRouteDesc->pGateway, sizeof (struct sockaddr));
  585.         }
  586.     pRouteDesc->flags = ROUTE_ENTRY_FLAGS (pRouteEntry);
  587.     pRouteDesc->protoId = RT_PROTO_GET (ROUTE_ENTRY_KEY (pRouteEntry));
  588.     pRouteDesc->pIf = pRouteEntry->rtEntry.rt_ifp;
  589.     pRouteDesc->value1 = pRouteEntry->rtEntry.rt_rmx.value1;
  590.     pRouteDesc->value2 = pRouteEntry->rtEntry.rt_rmx.value2;
  591.     pRouteDesc->value3 = pRouteEntry->rtEntry.rt_rmx.value3;
  592.     pRouteDesc->value4 = pRouteEntry->rtEntry.rt_rmx.value4;
  593.     pRouteDesc->value5 = pRouteEntry->rtEntry.rt_rmx.value5;
  594.     pRouteDesc->routeTag = pRouteEntry->rtEntry.rt_rmx.routeTag;
  595.     pRouteDesc->weight = pRouteEntry->rtEntry.rt_rmx.weight;
  596.     pRouteDesc->primaryRouteFlag = pRouteEntry->primaryRouteFlag;
  597.     return;
  598.     }
  599. /*******************************************************************************
  600. *
  601. * routeMetricsCopy - copies the extra metric information
  602. *
  603. * This routine copies all the additional metric information from
  604. * a ROUTE_DESC structure to a ROUTE_ENTRY structure. It completes
  605. * the modification of an existing entry and stores the initial data
  606. * when creating a new route entry.
  607. *
  608. * RETURNS: N/A
  609. *
  610. * NOMANUAL
  611. */
  612. void routeMetricsCopy
  613.     (
  614.     ROUTE_DESC * pRouteDesc,  /* buffers with new settings for route */
  615.     ROUTE_ENTRY * pRouteEntry  /* reference to existing route entry */
  616.     )
  617.     {
  618.     pRouteEntry->rtEntry.rt_rmx.value1 = pRouteDesc->value1;
  619.     pRouteEntry->rtEntry.rt_rmx.value2 = pRouteDesc->value2;
  620.     pRouteEntry->rtEntry.rt_rmx.value3 = pRouteDesc->value3;
  621.     pRouteEntry->rtEntry.rt_rmx.value4 = pRouteDesc->value4;
  622.     pRouteEntry->rtEntry.rt_rmx.value5 = pRouteDesc->value5;
  623.     pRouteEntry->rtEntry.rt_rmx.routeTag = pRouteDesc->routeTag;
  624.     pRouteEntry->rtEntry.rt_rmx.weight = pRouteDesc->weight;
  625.    
  626.     return;
  627.     }
  628. /*******************************************************************************
  629. *
  630. * routeEntryFree - free a ROUTE_ENTRY structure
  631. *
  632. * This routine removes a duplicate route entry. It executes when that
  633. * entry is specifically deleted or when a new copy of the entry is
  634. * installed as the visible route because of a weight change.
  635. *
  636. * It also executes within the internal rtfree() routine of the kernel.
  637. * That usage allows the original code to handle the reference counts
  638. * for duplicate and visible route entries. Since the current library
  639. * does not permit multiple references to the duplicate routes, this
  640. * ability is only important if future versions provide that feature.
  641. *
  642. * When executing within the rtfree() routine, the <countFlag> parameter
  643. * is FALSE since that routine decrements the reference count for the
  644. * associated interface address. That value is also FALSE when this
  645. * routine releases a partial route before the reference count increases.
  646. *
  647. * RETURNS: N/A 
  648. *
  649. * NOMANUAL
  650. */
  651. void routeEntryFree
  652.     (
  653.     ROUTE_ENTRY * pRouteEntry,  /* existing duplicate route entry */
  654.     BOOL  countFlag  /* decrement interface reference count? */
  655.     )
  656.     {
  657.     if (countFlag && pRouteEntry->rtEntry.rt_ifa)
  658.         pRouteEntry->rtEntry.rt_ifa->ifa_refcnt--;
  659.     if(pRouteEntry->rtEntry.rt_genmask)
  660. KHEAP_FREE( (char *)pRouteEntry->rtEntry.rt_genmask);
  661.     if(pRouteEntry->rtEntry.rt_nodes[0].rn_u.rn_leaf.rn_Mask)
  662. KHEAP_FREE(pRouteEntry->rtEntry.rt_nodes[0].rn_u.rn_leaf.rn_Mask);
  663.     KHEAP_FREE( (char *)pRouteEntry);
  664.     }
  665. #endif /* ROUTER_STACK */