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

VxWorks

开发平台:

C/C++

  1. /* route.c - packet routing routines */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1980, 1986, 1991, 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.  *
  36.  * @(#)route.c 8.3 (Berkeley) 1/9/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01s,14mar02,vvv  fixed route addition check for dest=gateway in rt_setgate
  42.  (SPR #74244)
  43. 01r,24jan02,niq  fixed call to new address message hook (SPR #71670)
  44. 01q,03jan02,vvv  added check for rt_setgate return value in rtredirect 
  45.  (SPR #71518)
  46. 01p,05dec01,vvv  fixed NT simulator exception (SPR #71659)
  47. 01o,12oct01,rae  merge from truestack ver 02e, base 01l (SPR #69683 etc.)
  48. 01n,20feb01,ijm  corrected additional bug in rtalloc1.  Precedence bits
  49.  must be cleared before searching the table.
  50. 01m,02nov00,ijm  fixed rtalloc1 TOS bug, SPR# 30195
  51. 01l,04mar99,spm  fixed errors in SPR #23301 fix causing build failures
  52. 01k,02mar99,spm  eliminated EEXIST error caused by ARP entries (SPR #23301)
  53. 01j,26aug98,n_s  added return val check for mBufClGet in rtinit. spr #22238.
  54. 01i,07jul97,rjc  newer version of rtentry incorporated.
  55. 01h,01jul97,vin  added route socket message hooks for scalability, fixed
  56.  warnings.
  57. 01g,30jun97,rjc  restored old rtentry size.
  58. 01f,03jun97,rjc  netmask with RTF_HOST set to 0.
  59. 01e,13feb97,rjc  more changes for tos routing,
  60. 01e,05feb97,rjc  changes for tos routing,
  61. 01d,05dec96,vin  moved ifafree() to if.c
  62. 01c,22nov96,vin  added cluster support replaced m_get(..) with mBufClGet(..).
  63. 01b,24sep96,vin  rtioctl() fixed for multicast addresses.
  64. 01a,03mar96,vin  created from BSD4.4 stuff. added rtioctl for backward
  65.  compatibility. moved ifa_ifwithroute() to if.c.
  66. */
  67. #include "vxWorks.h"
  68. #include "logLib.h"
  69. #include "sysLib.h"
  70. #include "wdLib.h"
  71. #include "net/mbuf.h"
  72. #include "net/domain.h"
  73. #include "net/protosw.h"
  74. #include "sys/socket.h"
  75. #include "sys/ioctl.h"
  76. #include "net/socketvar.h"
  77. #include "errno.h"
  78. #include "net/if.h"
  79. #include "net/if_types.h"
  80. #include "net/route.h"
  81. #include "net/systm.h"
  82. #include "net/raw_cb.h"
  83. #include "routeEnhLib.h"
  84. #include "netinet/in.h"
  85. #include "netinet/in_var.h"
  86. #ifdef VIRTUAL_STACK
  87. #include "netinet/vsLib.h"
  88. #endif
  89. #ifdef NS
  90. #include <netns/ns.h>
  91. #endif
  92. #ifdef WV_INSTRUMENTATION
  93. #ifdef INCLUDE_WVNET
  94. #include "wvNetLib.h"
  95. #endif
  96. #endif
  97. #ifdef RTALLOC_DEBUG
  98. #include "stdio.h"
  99. #include "net/if_dl.h"
  100. #include "inetLib.h"
  101. LOCAL int routeEntryDebugShow (struct radix_node * newrt);
  102. #endif /* RTALLOC_DEBUG */
  103. /* externs */
  104. int tickGet();
  105. #define SA(p) ((struct sockaddr *)(p))
  106. #define SOCKADDR_IN(s) (((struct sockaddr_in*)(s))->sin_addr.s_addr)
  107. #define ROUTE_KILL_FREQUENCY 600    /* Check for old routes every 10 minutes */
  108. #define ROUTE_PEND_MAXIMUM  3600    /* Remove old routes after 1 hour (max). */
  109. #define ROUTE_PEND_MINIMUM  10      /* 10 second minimum for old routes. */
  110. #ifndef VIRTUAL_STACK
  111. struct rtstat rtstat;
  112. struct radix_node_head *rt_tables[AF_MAX+1];
  113. #endif
  114. struct rtqk_arg
  115.     {
  116.     struct radix_node_head *rnh;
  117.     int draining;
  118.     int killed;
  119.     int found;
  120.     int updating;
  121.     ULONG nextstop;
  122.     };
  123. #ifndef VIRTUAL_STACK
  124. int rttrash; /* routes not in table but not freed */
  125. int     rtmodified = 0;  /* route table modified */
  126. struct sockaddr wildcard;  /* zero valued cookie for wildcard searches */
  127. LOCAL WDOG_ID routeKillTimer;  /* Schedules removal of expired routes. */
  128. LOCAL ULONG routeKillInterval;  /* Removal frequency, in ticks. */
  129. LOCAL int routePendInterval;  /* Time to keep unused routes, in ticks. */
  130. LOCAL int routePendMinimum;  /* Minimum preservation time. */
  131. LOCAL int routePendLimit = 128;    /*
  132.                                     * Number of unused routes before
  133.                                     * reduced removal time.
  134.                                     */
  135. LOCAL int routeExpireChange = 0;
  136.                                    /* Most recent removal time adjustment. */
  137. #endif
  138. struct radix_node * routeSwap (struct radix_node_head *, struct rtentry *,
  139.                                struct sockaddr *, struct sockaddr *);
  140. #ifdef WV_INSTRUMENTATION
  141. #ifdef INCLUDE_WVNET
  142.     /* Set common fields of event identifiers for this module. */
  143. LOCAL UCHAR wvNetModuleId = WV_NET_ROUTE_MODULE;   /* Value for route.c */
  144. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  145. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  146. #endif    /* INCLUDE_WVNET */
  147. #endif
  148. LOCAL void routeKillCheck (void);
  149. LOCAL int routeUpdate (struct radix_node *, void *);
  150. IMPORT STATUS   netJobAdd (FUNCPTR routine, int param1, int param2, int param3,
  151.                            int param4, int param5);
  152. #ifndef VIRTUAL_STACK
  153. /*
  154.  * The routeStorageCreate routine replaces this version with an implementation
  155.  * to initialize radix trees for a virtual stack.
  156.  */
  157. void
  158. rtable_init(table)
  159. void **table;
  160. {
  161. struct domain *dom;
  162. for (dom = domains; dom; dom = dom->dom_next)
  163. if (dom->dom_rtattach)
  164. dom->dom_rtattach(&table[dom->dom_family],
  165.     dom->dom_rtoffset);
  166. }
  167. #endif
  168. #ifdef VIRTUAL_STACK
  169. /*******************************************************************************
  170. *
  171. * routeStorageCreate - initialize the routing database
  172. *
  173. * This routine sets up the radix tree and initializes the routing storage
  174. * for addresses in the AF_INET family. It mimics the more generic route_init
  175. * routine which uses the domains list to create storage for any address
  176. * type. That original routine can be compiled and used if support for
  177. * other domains is needed.
  178. *
  179. * INTERNAL
  180. * Currently, this routine assumes that the caller has assigned the
  181. * correct virtual stack number allowing creation of isolated routing storage.
  182. * That process could occur internally (with the stack number as an argument)
  183. * if that approach is more convenient.
  184. *
  185. * RETURNS: OK, or ERROR if initialization failed.
  186. */
  187. STATUS routeStorageCreate (void)
  188.     {
  189.     VS_RADIX * pGlobals;
  190.     STATUS result;
  191.     pGlobals = malloc (sizeof (VS_RADIX));
  192.     if (pGlobals == NULL)
  193.         return (ERROR);
  194.     bzero ( (char *)pGlobals, sizeof (VS_RADIX));
  195.     vsTbl [myStackNum]->pRadixGlobals = pGlobals;
  196.     /*
  197.      * The radixInit() routine replaces the rn_init() routine to avoid access
  198.      * to the (currently non-virtualized) "domains" global.
  199.      */
  200.     result = radixInit (); /* initialize all zeroes, all ones, mask table */
  201.     if (result == ERROR)
  202.         {
  203.         free (pGlobals);
  204.         return (ERROR);
  205.         }
  206.    /*
  207.     * Setup any routing tables required for the available domains. 
  208.     * Originally, this initialization routine executed indirectly
  209.     * through the rtable_init() routine which searched the domains
  210.     * list. This process skips that search since the only applicable
  211.     * entry involves AF_INET addresses with an offset of 27 bits
  212.     * (originally 32). The original offset skips the length, family,
  213.     * and port fields in a sockaddr_in structure. The adjusted offset
  214.     * examines five additional bits to incorporate TOS values into
  215.     * routing lookups.
  216.     *
  217.     * NOTE: The original route_init() routine (if compiled and used)
  218.     * will use the rtable_init() routine to complete the routing
  219.     * storage setup for other domains, if that capability is necessary.
  220.     */
  221.     result = rn_inithead (&rt_tables[AF_INET], 27);
  222.     if (result == 0)
  223.         {
  224.         /* Tree creation failed: release allocated memory and return. */
  225.         Free (rn_zeros);
  226.         Free (mask_rnhead);
  227.         free (pGlobals);
  228.         return (ERROR);
  229.         }
  230.     routeKillTimer = wdCreate ();
  231.     if (routeKillTimer == NULL)
  232.         {
  233.         Free (rn_zeros);
  234.         Free (mask_rnhead);
  235.         Free (rt_tables[AF_INET]);
  236.         free (pGlobals);
  237.         return (ERROR);
  238.         }
  239.     routeKillInterval = sysClkRateGet() * ROUTE_KILL_FREQUENCY;
  240.     routePendInterval = sysClkRateGet() * ROUTE_PEND_MAXIMUM;
  241.     routePendMinimum = sysClkRateGet() * ROUTE_PEND_MINIMUM;
  242.     wdStart (routeKillTimer, routeKillInterval, netJobAdd,
  243.              (int)routeKillCheck);
  244.     return (OK);
  245.     }
  246. #else
  247. /*
  248.  * The routeStorageCreate routine replaces this version with an implementation
  249.  * which creates an isolated set of (previously global) variables for a single
  250.  * virtual stack.
  251.  */
  252. int
  253. route_init()
  254. {
  255. #ifdef WV_INSTRUMENTATION
  256. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  257.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 33, 13,
  258.                      WV_NETEVENT_ROUTEINIT_START)
  259. #endif  /* INCLUDE_WVNET */
  260. #endif
  261. rn_init(); /* initialize all zeroes, all ones, mask table */
  262. rtable_init((void **)rt_tables);
  263.         routeKillTimer = wdCreate ();
  264.         if (routeKillTimer == NULL)
  265.             return (ERROR);
  266.         routeKillInterval = sysClkRateGet() * ROUTE_KILL_FREQUENCY;
  267.         routePendInterval = sysClkRateGet() * ROUTE_PEND_MAXIMUM;
  268.         routePendMinimum = sysClkRateGet() * ROUTE_PEND_MINIMUM;
  269.         wdStart (routeKillTimer, routeKillInterval, netJobAdd, (int) routeKillCheck);
  270. return (OK);
  271. }
  272. #endif
  273. /*
  274.  * Look for cloned routes to remote destinations which are no longer in
  275.  * use. Remove any expired route entries.
  276.  */
  277. void routeKillCheck (void)
  278.     {
  279.     struct radix_node_head *pHead;
  280.     struct rtqk_arg   count;
  281.     int s;
  282.     ULONG now;
  283.     pHead = rt_tables [AF_INET];
  284.     if (pHead == NULL)    /* Missing routing table. */
  285.         return;
  286.     count.found = count.killed = 0;
  287.     count.rnh = pHead;
  288.     count.nextstop = tickGet() + routeKillInterval;
  289.     count.draining = count.updating = 0;
  290.     /* Remove any old (currently unused) routes which expired. */
  291.     s = splnet ();
  292.     rn_walktree (pHead, routeUpdate, &count);
  293.     splx (s);
  294.     if (count.found - count.killed > routePendLimit)
  295.         {
  296.         /*
  297.          * The routing table still contains excessive unused routes.
  298.          * Reduce the expiration time and try to remove more entries.
  299.          */
  300.         now = tickGet ();
  301.         if ( (now - routeExpireChange >= routeKillInterval) &&
  302.             routePendInterval > routePendMinimum)
  303.             {
  304.             routePendInterval = 2 * routePendInterval / 3;
  305.             if (routePendInterval < routePendMinimum)
  306.                 routePendInterval = routePendMinimum;
  307.             routeExpireChange = now;
  308.             /*
  309.              * Reset the expiration time for old (currently unused) routes
  310.              * to the new (smaller) value. Also update the "nextstop" field
  311.              * to the nearest (new) expiration time.
  312.              */
  313.             count.found = count.killed = 0;
  314.             count.updating = 1;
  315.             s = splnet ();
  316.             rn_walktree (pHead, routeUpdate, &count);
  317.             splx (s);
  318.             }
  319.         }
  320.     /*
  321.      * The routeUpdate() routine may reduce the "nextstop" value to the
  322.      * nearest expiration time of a pending route. Set the timer to 
  323.      * restart at that point, or after the default interval if no old routes
  324.      * are found.
  325.      */
  326.     now = count.nextstop - tickGet ();
  327.     wdStart (routeKillTimer, now, netJobAdd, (int)routeKillCheck); 
  328.     return;
  329.     }
  330. /*
  331.  * This routine performs garbage collection on unused route entries.
  332.  * The system clones those routes (from entries to remote destinations)
  333.  * to store the path MTU results. 
  334.  *
  335.  * The <pArg> argument selects the operation to perform. Normally, both
  336.  * the "draining" and "updating" fields are 0. In that case, this routine
  337.  * completes the deletion of (unused) cloned entries triggered when rtfree()
  338.  * set the RTF_DELETE flag. Since the RTF_DELETE flag and RTF_ANNOUNCE flags
  339.  * have the same value, this routine also tests the RTF_STATIC flag to prevent
  340.  * the removal of manually added proxy ARP entries.
  341.  *
  342.  * If too many routes exist, the "updating" flag reduces the lifetime of
  343.  * appropriate entries. The "draining" flag removes all entries immediately
  344.  * due to severe memory limitations.
  345.  * 
  346.  * As a side effect, this routine resets the "nextstop" field to the 
  347.  * nearest expiration time of a route entry waiting for deletion, if any.
  348.  */
  349.       
  350. LOCAL int routeUpdate
  351.     (
  352.     struct radix_node * pNode,
  353.     void * pArg
  354.     )
  355.     {
  356.     struct rtqk_arg * pCount = pArg;
  357.     struct rtentry * pRoute = (struct rtentry *)pNode;
  358.     int error;
  359.     ULONG now;
  360.     now = tickGet();
  361.     if ( (pRoute->rt_flags & RTF_DELETE) && !(pRoute->rt_flags & RTF_STATIC))
  362.         {
  363.         pCount->found++;
  364.         if (pCount->draining || pRoute->rt_rmx.rmx_expire <= now)
  365.             {
  366.             if (pRoute->rt_refcnt > 0)
  367.                 panic ("routeKill removing route in use?");
  368.             error = rtrequest (RTM_DELETE, (struct sockaddr *)rt_key (pRoute),
  369.                                pRoute->rt_gateway, rt_mask (pRoute),
  370.                                pRoute->rt_flags, 0);
  371.             if (!error)
  372.                 pCount->killed++;
  373.             }
  374.         else
  375.             {
  376.             if (pCount->updating &&
  377.                 (pRoute->rt_rmx.rmx_expire - now > routePendInterval))
  378.                 pRoute->rt_rmx.rmx_expire = now + routePendInterval;
  379.             if (pRoute->rt_rmx.rmx_expire < pCount->nextstop)
  380.                 pCount->nextstop = pRoute->rt_rmx.rmx_expire;
  381.             }
  382.         }
  383.     return (0);
  384.     }
  385.     /*
  386.      * Remove all unused routes cloned from entries to remote destinations,
  387.      * regardless of expiration time.
  388.      */
  389. void routeDrain (void)
  390.     {
  391.     struct radix_node_head *pHead;
  392.     struct rtqk_arg   count;
  393.     int s;
  394.     pHead = rt_tables [AF_INET];
  395.     if (pHead == NULL)    /* Missing routing table. */
  396.         return;
  397.     count.found = count.killed = 0;
  398.     count.rnh = pHead;
  399.     count.nextstop = 0;
  400.     count.draining = 1;
  401.     count.updating = 0;
  402.     s = splnet ();
  403.     rn_walktree (pHead, routeUpdate, &count);
  404.     splx (s);
  405.     }
  406. /*
  407.  * Packet routing routines.
  408.  */
  409. void
  410. rtalloc(ro)
  411. register struct route *ro;
  412. {
  413. if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
  414. return;  /* XXX */
  415. ro->ro_rt = rtalloc1(&ro->ro_dst, 1);
  416. }
  417. struct rtentry *
  418. rtalloc1(dst, report)
  419. register struct sockaddr *dst;
  420. int report;
  421. {
  422. register struct radix_node_head *rnh = rt_tables[dst->sa_family];
  423. register struct rtentry *rt;
  424. register struct radix_node *rn;
  425. struct rtentry *newrt = 0;
  426. struct rt_addrinfo info;
  427. u_long tosRtMask; /* TOS route mask */
  428. u_long newRtMask; /* TOS 0 route mask */
  429. int  s = splnet(), err = 0, msgtype = RTM_MISS;
  430. struct rtentry *   tosRt = NULL;
  431.         u_char     savedTos;
  432.       /* 
  433.        * save original tos since we overwrite it temporarily in the 
  434.        * dst socketaddr
  435.        */
  436.        savedTos = TOS_GET (dst);
  437.        /*
  438. * The Type of Service octet consists of three fields:
  439. *
  440. *       0     1     2     3     4     5     6     7
  441. *     +-----+-----+-----+-----+-----+-----+-----+-----+
  442. *     |                 |                       |     |
  443. *     |   PRECEDENCE    |          TOS          | MBZ |
  444. *     |                 |                       |     |
  445. *     +-----+-----+-----+-----+-----+-----+-----+-----+
  446. *
  447. * Precedence bits should not be considered when searching
  448. * the table.  An existing matching route would not be found
  449. * and if a new route were created, since dst is copied to 
  450. * generate the key, precedence bits would be part
  451. * of the new route's TOS field which is wrong.  This
  452. * would create a leak if this wrong route were created
  453. * for a local address.  ARP would hold on to a packet,
  454. * while it resolves the local address.  When the reply
  455. * comes back, since ARP does not look for routes with
  456. * TOS set, the packet would never be sent.
  457. *
  458. */
  459. TOS_SET(dst, savedTos & 0x1f);
  460. match:
  461. if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
  462.     ((rn->rn_flags & RNF_ROOT) == 0)) {
  463. newrt = rt = (struct rtentry *)rn;
  464.                 if ( (dst->sa_family == AF_INET) && (rt->rt_refcnt == 0) &&
  465.                     (rt->rt_flags & RTF_DELETE) && !(rt->rt_flags & RTF_STATIC))
  466.                     {
  467.                     /*
  468.                      * Reusing a (cloned) route to a remote destination.
  469.                      * Remove deletion tag and reset timer.
  470.                      *
  471.                      * NOTE: All manually added proxy ARP entries include
  472.                      * the RTF_ANNOUNCE flag which uses the same value as
  473.                      * the RTF_DELETE flag. The preceding test for RTF_STATIC
  474.                      * preserves the flag settings for those ARP entries,
  475.                      * even though the removal of RTF_ANNOUNCE should be
  476.                      * harmless since its only purpose is to trigger the
  477.                      * gratuitous ARP request when the entry is created.
  478.                      */
  479.                     rt->rt_flags &= ~RTF_DELETE;
  480.                     rt->rt_rmx.rmx_expire = 0;
  481.                     }
  482. if (report && (rt->rt_flags & RTF_CLONING)) {
  483. #ifdef WV_INSTRUMENTATION
  484. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  485.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 17, 9,
  486.                              WV_NETEVENT_RTALLOC_CLONE,
  487.                          ((struct sockaddr_in *)rt_key (rt))->sin_addr.s_addr, 
  488.                          ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  489. #endif  /* INCLUDE_WVNET */
  490. #endif
  491. err = rtrequest(RTM_RESOLVE, dst, SA(0),
  492.       SA(0), 0, &newrt);
  493. if (err) {
  494. newrt = rt;
  495. rt->rt_refcnt++;
  496. goto miss;
  497. }
  498. if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
  499. msgtype = RTM_RESOLVE;
  500. goto miss;
  501. }
  502. } else
  503.                       {
  504. #ifdef WV_INSTRUMENTATION
  505. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  506.         WV_NET_DSTADDROUT_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 18, 10,
  507.                                ((struct sockaddr_in *)dst)->sin_addr.s_addr,
  508.                                     WV_NETEVENT_RTALLOC_SEARCHGOOD,
  509.                                ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  510. #endif  /* INCLUDE_WVNET */
  511. #endif
  512.                       rt->rt_refcnt++;
  513.                       }
  514. } else {
  515. rtstat.rts_unreach++;
  516. miss:
  517. #ifdef WV_INSTRUMENTATION
  518. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  519.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_CRITICAL, 26, 5,
  520.                          WV_NETEVENT_RTALLOC_SEARCHFAIL,
  521.                          ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  522. #endif  /* INCLUDE_WVNET */
  523. #endif
  524.                 if (report) {
  525. bzero((caddr_t)&info, sizeof(info));
  526. info.rti_info[RTAX_DST] = dst;
  527.                         if (rtMissMsgHook)
  528.                             (*rtMissMsgHook) (msgtype, &info, 0, err);
  529. }
  530. }
  531.         /*
  532.          *  RFC 1583 Section 11.1:
  533.          *
  534.          * "Select the routing table entry whose value matches the TOS found
  535.          *  in the packet header.  If there is no routing table entry for
  536.          *  this TOS, select the routing table entry for TOS 0.  In other
  537.          *  words, packets requesting TOS X are routed along the TOS 0
  538.          *  path if a TOS X path does not exist."
  539.  *  See also RFC 1349, Appendix B.4.
  540.          */
  541.         if (TOS_GET (dst) != 0)
  542.             {
  543.             TOS_SET (dst, 0);
  544.             tosRt = newrt;
  545.             newrt = NULL;
  546.             goto match;
  547.             }
  548.         /*
  549.          * tosRt is the TOS route match, if any. If none exists, tosRt is the
  550.          * default route ("0.0.0.0"), if any.  Otherwise, tosRt is NULL.
  551.          * newrt is the TOS 0 route.
  552.          */
  553.         if (tosRt != NULL)
  554.             {
  555.             if (newrt != NULL)
  556.                 {
  557.                 /*
  558.                  * Host route entries created by ARP have null masks with
  559.                  * implied mask = 0xffffffff
  560.                  */
  561.                 tosRtMask =  (rt_mask (tosRt) == NULL) ? 0xffffffff :
  562.                     ((struct sockaddr_in *) rt_mask (tosRt))->sin_addr.s_addr;
  563. #ifdef RTALLOC_DEBUG
  564.                 printf("nBEST MATCHING TOS ROUTE:n"); 
  565.                 routeEntryDebugShow ((struct radix_node *)tosRt);
  566.                 printf("nTOS 0 ROUTE:n"); 
  567.                 routeEntryDebugShow ((struct radix_node *)newrt);
  568. #endif /* RTALLOC_DEBUG */
  569.                 newRtMask =  (rt_mask (newrt) == NULL) ? 0xffffffff :
  570.                     ((struct sockaddr_in *) rt_mask (newrt))->sin_addr.s_addr;
  571.                 /*
  572.                  * select the route with longest netmask. we assume
  573.                  * contiguous masks starting at the same bit position.
  574.                  * The default route has a mask = 0x00000000
  575.                  */
  576.                 if (tosRtMask >= newRtMask)
  577.                     {
  578.                     RTFREE (newrt);
  579.                     newrt = tosRt;
  580.                     }
  581.                 else
  582.                     {
  583.                     /* newrt is more specific: keep it */
  584.                     RTFREE (tosRt);
  585.                    }
  586.                 }
  587.             else /* newrt is NULL */
  588.                 {
  589.                 /*
  590.                  * Restore previously found TOS route.  Can happen if there is a
  591.                  * route entered with TOS set, but no default route exists nor
  592.                  * route match with 0 TOS.
  593.                  */
  594.                 newrt = tosRt;
  595.                 }
  596.             }
  597. #ifdef RTALLOC_DEBUG
  598. if (savedTos && newrt != NULL)
  599.     {
  600.     printf ("nSELECTED ROUTE:n");
  601.     routeEntryDebugShow ((struct radix_node *)newrt);
  602.     }
  603. #endif /* RTALLOC_DEBUG */
  604.        /* Restore the saved TOS. */ 
  605.        TOS_SET (dst, savedTos);
  606.        splx(s);
  607.        return (newrt);
  608. }
  609.     /*
  610.      * This version of the route search routine is specifically designed
  611.      * for retrieving a route when forwarding packets. Unlike the original
  612.      * case, this route search never clones routes to remote destinations.
  613.      * Those cloned routes are necessary for path MTU discovery, but should
  614.      * only exist when the Internet host originates the traffic, not when
  615.      * it forwards it as a router.
  616.      */
  617. struct rtentry *
  618. rtalloc2(dst)
  619. register struct sockaddr *dst;
  620. {
  621. register struct radix_node_head *rnh = rt_tables[dst->sa_family];
  622. register struct rtentry *rt;
  623. register struct radix_node *rn;
  624. struct rtentry *newrt = 0;
  625. struct rt_addrinfo info;
  626. int  s = splnet(), err = 0, msgtype = RTM_MISS;
  627. struct rtentry *   tosRt = NULL;
  628.         u_long tosRtMask;       /* TOS route mask */
  629.         u_long newRtMask;       /* TOS 0 route mask */
  630.         u_char     savedTos;
  631.       /* 
  632.        * save original tos since we overwrite it temporarily in the 
  633.        * dst socketaddr
  634.        */
  635.        savedTos = TOS_GET (dst);
  636. match:
  637. if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
  638.     ((rn->rn_flags & RNF_ROOT) == 0)) {
  639. newrt = rt = (struct rtentry *)rn;
  640.                 if ( (dst->sa_family == AF_INET) && (rt->rt_refcnt == 0) &&
  641.                     (rt->rt_flags & RTF_DELETE) && !(rt->rt_flags & RTF_STATIC))
  642.                     {
  643.                     /*
  644.                      * Reusing a (cloned) route to a remote destination.
  645.                      * Remove deletion tag and reset timer.
  646.                      *
  647.                      * NOTE: All manually added proxy ARP entries include
  648.                      * the RTF_ANNOUNCE flag which uses the same value as
  649.                      * the RTF_DELETE flag. The preceding test for RTF_STATIC
  650.                      * preserves the flag settings for those ARP entries,
  651.                      * even though the removal of RTF_ANNOUNCE should be
  652.                      * harmless since its only purpose is to trigger the
  653.                      * gratuitous ARP request when the entry is created.
  654.                      */
  655.                     rt->rt_flags &= ~RTF_DELETE;
  656.                     rt->rt_rmx.rmx_expire = 0;
  657.                     }
  658.                 /*
  659.                  * Disable cloning when forwarding data to a remote
  660.                  * destination. This search will still create a 
  661.                  * cloned entry if the destination is directly reachable
  662.                  * to hold the ARP information for the target host.
  663.                  */
  664. if ( !(rt->rt_flags & RTF_GATEWAY) &&
  665.                     (rt->rt_flags & RTF_CLONING)) {
  666. err = rtrequest(RTM_RESOLVE, dst, SA(0),
  667.       SA(0), 0, &newrt);
  668. if (err) {
  669. newrt = rt;
  670. rt->rt_refcnt++;
  671. goto miss;
  672. }
  673. if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
  674. msgtype = RTM_RESOLVE;
  675. goto miss;
  676. }
  677. } else
  678. rt->rt_refcnt++;
  679. } else {
  680. rtstat.rts_unreach++;
  681. miss:
  682. bzero((caddr_t)&info, sizeof(info));
  683. info.rti_info[RTAX_DST] = dst;
  684.                 if (rtMissMsgHook)
  685.                     (*rtMissMsgHook) (msgtype, &info, 0, err);
  686. }
  687.     /*
  688.      *  RFC 1583 Section 11.1:
  689.      *
  690.      * "Select the routing table entry whose value matches the TOS found
  691.      *  in the packet header.  If there is no routing table entry for
  692.      *  this TOS, select the routing table entry for TOS 0.  In other
  693.      *  words, packets requesting TOS X are routed along the TOS 0
  694.      *  path if a TOS X path does not exist."
  695.      *  See also RFC 1349, Appendix B.4.
  696.      */
  697.     if (TOS_GET (dst) != 0)   
  698.         {
  699.         TOS_SET (dst, 0);
  700.         tosRt = newrt;
  701.         newrt = NULL;
  702.         goto match;
  703.         }
  704.     /*
  705.      * tosRt is the TOS route match, if any. If none exists, tosRt is the
  706.      * default route ("0.0.0.0"), if any.  Otherwise, tosRt is NULL.
  707.      * newrt is the TOS 0 route.
  708.      */
  709.     if (tosRt != NULL)
  710.         {
  711.         if (newrt != NULL)
  712.             {
  713.             /*
  714.              * Host route entries created by ARP have null masks with
  715.              * implied mask = 0xffffffff
  716.              */
  717.             tosRtMask =  (rt_mask (tosRt) == NULL) ? 0xffffffff :
  718.                 ((struct sockaddr_in *) rt_mask (tosRt))->sin_addr.s_addr;
  719.             newRtMask =  (rt_mask (newrt) == NULL) ? 0xffffffff :
  720.                 ((struct sockaddr_in *) rt_mask (newrt))->sin_addr.s_addr;
  721.             /*
  722.              * select the route with longest netmask. we assume
  723.              * contiguous masks starting at the same bit position.
  724.              * The default route has a mask = 0x00000000
  725.              */
  726.             if (tosRtMask >= newRtMask)
  727.                 {
  728.                 RTFREE (newrt);
  729.                 newrt = tosRt;
  730.                 }
  731.             else
  732.                 {
  733.                 /* newrt is more specific: keep it */
  734.                 RTFREE (tosRt);
  735.                }
  736.             }
  737.         else /* newrt is NULL */
  738.             {
  739.             /*
  740.              * Restore previously found TOS route.  Can happen if there is a
  741.              * route entered with TOS set, but no default route exists nor
  742.              * route match with 0 TOS.
  743.              */
  744.             newrt = tosRt;
  745.             }
  746.         }
  747.        /* 
  748.         * restore the saved tos. is redundant but harmless in case tos
  749.         * was default to  start with.
  750.         */
  751.         TOS_SET (dst, savedTos);
  752.         splx(s);
  753.         return (newrt);
  754.     }
  755. void
  756. rtfree(rt)
  757. register struct rtentry *rt;
  758. {
  759. register struct ifaddr *ifa;
  760. #ifdef WV_INSTRUMENTATION
  761. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  762.     if (rt)
  763.         {
  764.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 19, 11,
  765.                          WV_NETEVENT_RTFREE_START,
  766.                          ((struct sockaddr_in *)rt_key (rt))->sin_addr.s_addr,
  767.                          rt->rt_refcnt)
  768.         }
  769.     else
  770.         {
  771.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 19, 11,
  772.                          WV_NETEVENT_RTFREE_START, 0, 0)
  773.         }
  774. #endif  /* INCLUDE_WVNET */
  775. #endif
  776. if (rt == 0)
  777.             {
  778. #ifdef WV_INSTRUMENTATION
  779. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  780.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 21, 1,
  781.                      WV_NETEVENT_RTFREE_PANIC)
  782. #endif  /* INCLUDE_WVNET */
  783. #endif
  784.             panic("rtfree");
  785.             }
  786. rt->rt_refcnt--;
  787.         if (rt_key(rt)->sa_family == AF_INET)
  788.             {
  789.             /*
  790.              * If route was cloned for path MTU results, mark for later
  791.              * removal (if not reused) instead of deleting immediately.
  792.              */
  793.             if ( (rt->rt_refcnt == 0) && (rt->rt_flags & RTF_UP) &&
  794.                 (rt->rt_flags & RTF_HOST) && !(rt->rt_flags & RTF_LLINFO) &&
  795.                 (rt->rt_flags & RTF_CLONED))
  796.                 {
  797.                 rt->rt_flags |= RTF_DELETE;
  798.                 if (rt->rt_rmx.rmx_expire == 0)    /* Not yet assigned. */
  799.                     rt->rt_rmx.rmx_expire = tickGet() + routePendInterval;
  800.                 }
  801.             }
  802. if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
  803. if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
  804.                     {
  805. #ifdef WV_INSTRUMENTATION
  806. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  807.                     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 21, 1,
  808.                                      WV_NETEVENT_RTFREE_PANIC)
  809. #endif  /* INCLUDE_WVNET */
  810. #endif
  811.                     panic ("rtfree 2");
  812.                     }
  813. rttrash--;
  814. if (rt->rt_refcnt < 0) {
  815. #ifdef WV_INSTRUMENTATION
  816. #ifdef INCLUDE_WVNET    /* WV_NET_ALERT event */
  817.                     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_ALERT, 8, 4,
  818.                                      WV_NETEVENT_RTFREE_BADREFCNT)
  819. #endif  /* INCLUDE_WVNET */
  820. #endif
  821.                     logMsg ("rtfree: %x not freed (neg refs)n", (int)rt,
  822.                             0, 0, 0, 0, 0);
  823.                     return;
  824.                     }
  825. ifa = rt->rt_ifa;
  826. IFAFREE(ifa);
  827.                 if (rt->rt_parent)
  828.                     {
  829.                     RTFREE (rt->rt_parent)
  830.                     }
  831. Free(rt_key(rt));
  832. #ifdef ROUTER_STACK
  833.                 /*
  834.                  * Entries which are not directly attached to the
  835.                  * tree use a different free routine since the netmask
  836.                  * information is stored in a uniquely allocated buffer,
  837.                  * not shared among multiple route entries.
  838.                  */
  839. if ( ((ROUTE_ENTRY*)rt)->primaryRouteFlag == FALSE)
  840.     routeEntryFree ((ROUTE_ENTRY*)rt, FALSE);
  841.                 else
  842.     Free ((ROUTE_ENTRY*)rt);
  843. #else
  844.                 Free (rt);
  845. #endif /* ROUTER_STACK */
  846. }
  847. }
  848. /*
  849.  * Force a routing table entry to the specified
  850.  * destination to go through the given gateway.
  851.  * Normally called as a result of a routing redirect
  852.  * message from the network layer.
  853.  *
  854.  * N.B.: must be called at splnet
  855.  *
  856.  */
  857. int
  858. rtredirect(dst, gateway, netmask, flags, src, rtp)
  859. struct sockaddr *dst, *gateway, *netmask, *src;
  860. int flags;
  861. struct rtentry **rtp;
  862. {
  863. register struct rtentry *rt;
  864. int error = 0;
  865. short *stat = 0;
  866. struct rt_addrinfo info;
  867. struct ifaddr *ifa;
  868. /* verify the gateway is directly reachable */
  869. if ((ifa = ifa_ifwithnet(gateway)) == 0) {
  870. error = ENETUNREACH;
  871. goto out;
  872. }
  873. rt = rtalloc1(dst, 0);
  874. /*
  875.  * If the redirect isn't from our current router for this dst,
  876.  * it's either old or wrong.  If it redirects us to ourselves,
  877.  * we have a routing loop, perhaps as a result of an interface
  878.  * going down recently.
  879.  */
  880. #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
  881. if (!(flags & RTF_DONE) && rt &&
  882.      (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
  883. error = EINVAL;
  884. else if (ifa_ifwithaddr(gateway))
  885. error = EHOSTUNREACH;
  886. if (error)
  887. goto done;
  888. /*
  889.  * Create a new entry if we just got back a wildcard entry
  890.  * or the the lookup failed.  This is necessary for hosts
  891.  * which use routing redirects generated by smart gateways
  892.  * to dynamically build the routing tables.
  893.  */
  894. if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
  895. goto create;
  896. /*
  897.  * Don't listen to the redirect if it's
  898.  * for a route to an interface. 
  899.  */
  900. if (rt->rt_flags & RTF_GATEWAY) {
  901. if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
  902. /*
  903.  * Changing from route to net => route to host.
  904.  * Create new route, rather than smashing route to net.
  905.  */
  906. create:
  907. flags |=  RTF_GATEWAY | RTF_DYNAMIC;
  908.                         /*
  909.                          * Create the new route entry using the default
  910.                          * weight. Do not report the change since the
  911.                          * later hook generates both types of messages.
  912.                          */
  913.                         error = rtrequestAddEqui (dst, netmask, gateway, flags,
  914.                                                   M2_ipRouteProto_icmp, 0,
  915.                                                   FALSE, FALSE, NULL);
  916. /* error = rtrequest((int)RTM_ADD, dst, gateway,
  917.     netmask, flags,
  918.     (struct rtentry **)0);
  919.                         */
  920. stat = &rtstat.rts_dynamic;
  921. } else {
  922. /*
  923.  * Smash the current notion of the gateway to
  924.  * this destination.  Should check about netmask!!!
  925.  */
  926. if (!(error = rt_setgate (rt, rt_key(rt), gateway)))
  927.     {
  928.     rt->rt_flags |= RTF_MODIFIED;
  929.     flags |= RTF_MODIFIED;
  930.     stat = &rtstat.rts_newgateway;
  931.     rt->rt_mod = tickGet();      /* last modified */
  932.     rtmodified++; 
  933.     }
  934. }
  935. } else
  936. error = EHOSTUNREACH;
  937. done:
  938. if (rt) {
  939. if (rtp && !error)
  940. *rtp = rt;
  941. else
  942. rtfree(rt);
  943. }
  944. out:
  945. if (error)
  946.             {
  947. #ifdef WV_INSTRUMENTATION
  948. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  949.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 27, 6,
  950.                              WV_NETEVENT_RTRESET_BADDEST,
  951.                              error, 
  952.                              ((struct sockaddr_in *)gateway)->sin_addr.s_addr)
  953. #endif  /* INCLUDE_WVNET */
  954. #endif
  955.             rtstat.rts_badredirect++;
  956.             }
  957. else if (stat != NULL)
  958. (*stat)++;
  959. bzero((caddr_t)&info, sizeof(info));
  960. info.rti_info[RTAX_DST] = dst;
  961. info.rti_info[RTAX_GATEWAY] = gateway;
  962. info.rti_info[RTAX_NETMASK] = netmask;
  963. info.rti_info[RTAX_AUTHOR] = src;
  964.         if (rtMissMsgHook)
  965.             (*rtMissMsgHook) (RTM_REDIRECT, &info, flags, error);
  966. #ifdef WV_INSTRUMENTATION
  967. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  968.         WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_VERBOSE, 34, 14,
  969.                          WV_NETEVENT_RTRESET_STATUS,
  970.                          error, 
  971.                          ((struct sockaddr_in *)dst)->sin_addr.s_addr, 
  972.                          ((struct sockaddr_in *)gateway)->sin_addr.s_addr, 
  973.                          ((struct sockaddr_in *)netmask)->sin_addr.s_addr)
  974. #endif  /* INCLUDE_WVNET */
  975. #endif
  976. return (error); 
  977. }
  978. /*
  979. * Routing table ioctl interface.
  980. *
  981. * WRS MODS support for this function is being for backward compatibility.
  982. * This function has be moved else where because the routing code has 
  983. * nothing to do with internet specific addresses since routing is independent
  984. * of the sockaddress family.
  985. */
  986. int
  987. rtioctl(req, data)
  988. int req;
  989. caddr_t data;
  990. {
  991. struct ortentry * pORE = NULL;
  992. struct sockaddr netMask;
  993. struct sockaddr * pNetMask = &netMask; 
  994. register u_long i; 
  995. register u_long net;
  996. register struct in_ifaddr *ia;
  997. #ifdef WV_INSTRUMENTATION
  998. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  999.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 20, 12,
  1000.                      WV_NETEVENT_RTIOCTL_START, req)
  1001. #endif  /* INCLUDE_WVNET */
  1002. #endif
  1003.         if (req != SIOCADDRT && req != SIOCDELRT)
  1004.             {
  1005. #ifdef WV_INSTRUMENTATION
  1006. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  1007.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 37, 8,
  1008.                              WV_NETEVENT_RTIOCTL_BADREQ, req)
  1009. #endif  /* INCLUDE_WVNET */
  1010. #endif
  1011.             return (EINVAL);
  1012.             }
  1013. pORE = (struct ortentry *)data;
  1014. /* BSD4.3 to BSD4.4 conversion */
  1015. if (req == SIOCADDRT)
  1016.     req = RTM_ADD;
  1017. else
  1018.     req = RTM_DELETE;
  1019. /* 
  1020.  * Set the netmask to the netmask of the interface address.
  1021.  * This has to be removed if provision is made with routeAdd
  1022.  * to add the network mask. 
  1023.  */
  1024. bzero ((caddr_t)&netMask, sizeof (struct sockaddr));
  1025. /* check for default gateway address */
  1026. if (((struct sockaddr_in *)(&pORE->rt_dst))->sin_addr.s_addr 
  1027.     != INADDR_ANY )
  1028.     {
  1029.     i = ntohl(((struct sockaddr_in*)&pORE->rt_dst)->sin_addr.s_addr);
  1030.     pNetMask->sa_family = AF_INET; 
  1031.     pNetMask->sa_len    = 8;
  1032.     if (IN_CLASSA(i))
  1033. {
  1034. ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = 
  1035.     htonl(IN_CLASSA_NET);
  1036. net = i & IN_CLASSA_NET;
  1037. }
  1038.     else if (IN_CLASSB(i))
  1039. {
  1040. ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = 
  1041.     htonl(IN_CLASSB_NET);
  1042. net = i & IN_CLASSB_NET;
  1043. }
  1044.     else if (IN_CLASSC(i))
  1045. {
  1046. ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = 
  1047.     htonl(IN_CLASSC_NET);
  1048. net = i & IN_CLASSC_NET;
  1049. }
  1050.     else
  1051. {
  1052. ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr = 
  1053.     htonl(IN_CLASSD_NET);
  1054. net = i & IN_CLASSD_NET;
  1055. }
  1056.     /*
  1057.      * Check whether network is a subnet;
  1058.      * if so, return subnet number.
  1059.      */
  1060. #ifdef VIRTUAL_STACK
  1061.     for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  1062. #else
  1063.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  1064. #endif /* VIRTUAL_STACK */
  1065. if (net == ia->ia_net)
  1066.     ((struct sockaddr_in *)pNetMask)->sin_addr.s_addr =
  1067. htonl(ia->ia_subnetmask); 
  1068.     in_socktrim ((struct sockaddr_in *)pNetMask); 
  1069.     }
  1070.        pORE->rt_flags |= RTF_GATEWAY;
  1071.        if(pORE->rt_flags & RTF_HOST)
  1072.    pNetMask=0;
  1073.  
  1074. #ifdef DEBUG
  1075.        logMsg("rtIoctl:before rtrequestAddEqui/DelEquin",0,0,0,0,0,0);
  1076. #endif
  1077.         /*
  1078.          * Add the requested route using the default weight value or delete
  1079.          * the matching entry. In either case, report the change using both
  1080.          * routing socket messages and direct callbacks.
  1081.          */
  1082.        if(req==RTM_ADD)
  1083.    return (rtrequestAddEqui (&pORE->rt_dst, pNetMask,
  1084.                                      &pORE->rt_gateway, pORE->rt_flags,
  1085.                                      M2_ipRouteProto_other, 0,
  1086.                                      TRUE, TRUE, NULL));
  1087.        else
  1088.    return (rtrequestDelEqui (&pORE->rt_dst, pNetMask,
  1089.                                      &pORE->rt_gateway, pORE->rt_flags,
  1090.                                      M2_ipRouteProto_other, TRUE, TRUE, NULL));
  1091. }
  1092. #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  1093. int rt_fixdelete (struct radix_node *, void *);
  1094. static int rt_fixchange (struct radix_node *, void *);
  1095. int
  1096. rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
  1097. int req, flags;
  1098. struct sockaddr *dst, *gateway, *netmask;
  1099. struct rtentry **ret_nrt;
  1100. {
  1101. int s = splnet(); int error = 0;
  1102. register struct rtentry *rt;
  1103. register struct radix_node *rn;
  1104. register struct radix_node_head *rnh;
  1105. struct ifaddr *ifa;
  1106. struct sockaddr *ndst;
  1107. #define senderr(x) { error = x ; goto bad; }
  1108. if ((rnh = rt_tables[dst->sa_family]) == 0)
  1109. senderr(ESRCH);
  1110. if (flags & RTF_HOST)
  1111.             {
  1112.             netmask = 0;
  1113.     }
  1114.         if (netmask)
  1115.     {
  1116.     TOS_SET (netmask, 0x1f);  /* set the 5 bits in the mask corresponding
  1117.  to the TOS bits */
  1118.     }
  1119. switch (req) {
  1120. case RTM_DELETE:
  1121. if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0)
  1122. senderr(ESRCH);
  1123. if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
  1124.                     {
  1125. #ifdef WV_INSTRUMENTATION
  1126. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  1127.                     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 22, 2,
  1128.                                      WV_NETEVENT_RTREQ_PANIC)
  1129. #endif  /* INCLUDE_WVNET */
  1130. #endif
  1131.                     panic ("rtrequest delete");
  1132.                     }
  1133. rt = (struct rtentry *)rn;
  1134.                 /*
  1135.                  * Search the appropriate subtree to remove any children
  1136.                  * (created for path MTU results). This cleanup must occur
  1137.                  * before clearing the RTF_UP flag or the system might
  1138.                  * release the current node's memory prematurely if the
  1139.                  * search deletes the last reference.
  1140.                  */
  1141.                 if (dst->sa_family == AF_INET &&
  1142.                     (rt->rt_flags & RTF_CLONING) && netmask)
  1143.                     {
  1144.                     rn_walksubtree (rnh, dst, netmask, rt_fixdelete, rt);
  1145.                     }
  1146. rt->rt_flags &= ~RTF_UP;
  1147. if (rt->rt_gwroute) {
  1148. rt = rt->rt_gwroute; RTFREE(rt);
  1149. (rt = (struct rtentry *)rn)->rt_gwroute = 0;
  1150. }
  1151. if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
  1152. ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
  1153. rttrash++;
  1154. if (ret_nrt)
  1155. *ret_nrt = rt;
  1156. else if (rt->rt_refcnt <= 0) {
  1157. rt->rt_refcnt++;
  1158. rtfree(rt);
  1159. }
  1160. rtmodified++;
  1161. break;
  1162. case RTM_RESOLVE:
  1163. if (ret_nrt == 0 || (rt = *ret_nrt) == 0)
  1164.                         {
  1165. #ifdef DEBUG
  1166.                         logMsg("rtrequest: RTM_RESOLVE, EINVAL errorn",0,0,0,0,0,0);
  1167. #endif
  1168. senderr(EINVAL);
  1169.                         }
  1170. ifa = rt->rt_ifa;
  1171. flags = rt->rt_flags & ~RTF_CLONING;
  1172. gateway = rt->rt_gateway;
  1173. if ((netmask = rt->rt_genmask) == 0)
  1174. {
  1175. flags |= RTF_HOST;
  1176. }
  1177. goto makeroute;
  1178. case RTM_ADD:
  1179. if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
  1180. senderr(ENETUNREACH);
  1181. makeroute:
  1182. R_Malloc(rt, struct rtentry *, sizeof(ROUTE_ENTRY));
  1183. if (rt == 0)
  1184. senderr(ENOBUFS);
  1185. Bzero(rt, sizeof (ROUTE_ENTRY));
  1186. rt->rt_flags = RTF_UP | flags;
  1187. if (rt_setgate(rt, dst, gateway)) {
  1188. Free(rt);
  1189. senderr(ENOBUFS);
  1190. }
  1191. ndst = rt_key(rt);
  1192. if (netmask) {
  1193. rt_maskedcopy(dst, ndst, netmask);
  1194. } else
  1195. Bcopy(dst, ndst, dst->sa_len);
  1196.             /* Set IP routes to create children (for path MTU results). */
  1197.             if (ndst->sa_family == AF_INET &&
  1198.                 !IN_MULTICAST
  1199.                     (ntohl ( ((struct sockaddr_in *)ndst)->sin_addr.s_addr)) &&
  1200.                 ! (rt->rt_flags & RTF_HOST))
  1201.                 {
  1202.                 if (((struct sockaddr_in *)netmask)->sin_addr.s_addr 
  1203.                          != 0xffffffff)
  1204.                     {
  1205.                     rt->rt_flags |= RTF_CLONING;
  1206.                     }
  1207.                 }
  1208. rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
  1209. rnh, rt->rt_nodes);
  1210. /* update proto field of rt entry, in the gateway sockaddr */
  1211. if ((req == RTM_ADD) && (gateway->sa_family == AF_INET))
  1212.     RT_PROTO_SET (ndst, RT_PROTO_GET (dst));
  1213.                 if (rn == 0 && (rt->rt_flags & RTF_HOST))
  1214.                     {
  1215.                     /* Replace matching (cloned) entry if possible. */
  1216.                     rn = routeSwap (rnh, rt, ndst, netmask);
  1217.                     }
  1218. if (rn == 0) {
  1219. if (rt->rt_gwroute)
  1220. rtfree(rt->rt_gwroute);
  1221. Free(rt_key(rt));
  1222. Free(rt);
  1223. senderr(EEXIST);
  1224. }
  1225. ifa->ifa_refcnt++;
  1226. rt->rt_ifa = ifa;
  1227. rt->rt_ifp = ifa->ifa_ifp;
  1228. if (req == RTM_RESOLVE)
  1229.                     {
  1230.                     rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
  1231.                     rt->rt_parent = (*ret_nrt);   /* record source route */
  1232.                     (*ret_nrt)->rt_refcnt++;
  1233.                     rt->rt_flags |= RTF_CLONED;
  1234.                     
  1235.                     /*
  1236.                      * Mark the cloned route as a representative route
  1237.                      * so that when it is deleted, Fastpath is called with
  1238.                      * ROUTE_REP_DEL operation and the entry gets removed
  1239.                      * from the Fastpath cache
  1240.                      */
  1241.  
  1242.                     ((ROUTE_ENTRY*)rt)->primaryRouteFlag = TRUE;
  1243.                     }
  1244.                 if (rt->rt_ifp->if_type == IFT_PMP)
  1245.                     {
  1246.                     /*
  1247.                      * Point-to-multipoint devices do not use a common
  1248.                      * MTU value for all destinations or perform address
  1249.                      * resolution, so cloning the interface route to store
  1250.                      * that information is not necessary.
  1251.                      */
  1252.                     rt->rt_flags &= ~RTF_CLONING;
  1253.                     }
  1254.                 /* Assign initial path MTU estimate, if enabled for route. */
  1255.                 if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU)
  1256.                     && rt->rt_ifp)
  1257.                     rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
  1258. if (ifa->ifa_rtrequest)
  1259. ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
  1260.                 if (ndst->sa_family == AF_INET)
  1261.                     {
  1262.                     /*
  1263.                      * Remove any cloned routes which a new
  1264.                      * network route overrides.
  1265.                      */
  1266.                     if (!(rt->rt_flags & RTF_HOST) && rt_mask (rt) != 0)
  1267.                         {
  1268.                         rn_walksubtree (rnh, ndst, netmask, rt_fixchange, rt);
  1269.                         }
  1270.                     }
  1271. if (ret_nrt) {
  1272. *ret_nrt = rt;
  1273. rt->rt_refcnt++;
  1274. }
  1275. rt->rt_mod = tickGet();  /* last modified */
  1276. rtmodified++;
  1277. break;
  1278. }
  1279. bad:
  1280. #ifdef WV_INSTRUMENTATION
  1281. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1282.         if (error)
  1283.             {
  1284.             WV_NET_MARKER_4 (NET_AUX_EVENT, WV_NET_CRITICAL, 28, 7,
  1285.                              WV_NETEVENT_RTREQ_BADROUTE,
  1286.                              error, 
  1287.                              ((struct sockaddr_in *)dst)->sin_addr.s_addr, 
  1288.                              ((struct sockaddr_in *)gateway)->sin_addr.s_addr, 
  1289.                              ((struct sockaddr_in *)netmask)->sin_addr.s_addr)
  1290.             }
  1291. #endif  /* INCLUDE_WVNET */
  1292. #endif
  1293. splx(s);
  1294. return (error);
  1295. }
  1296.  /* 
  1297.   * This routine is called when adding a host-specific route to
  1298.   * the routing tree fails. That failure can occur because an
  1299.   * ARP entry for the destination already exists in the tree.
  1300.   * Alternatively, a cloned entry to a remote destination (for
  1301.   * path MTU results) might already exist. In either case, the
  1302.   * host-specific entry is added after the existing entry is removed.
  1303.   */
  1304. struct radix_node * routeSwap
  1305.     (
  1306.     struct radix_node_head *  pNodeHead,
  1307.     struct rtentry *  pRoute,
  1308.     struct sockaddr *  pDest,
  1309.     struct sockaddr *  pNetmask
  1310.     )
  1311.     {
  1312.     struct radix_node *  pNode;
  1313.     struct rtentry *  pTwinRt;
  1314.     struct ifaddr *  pIfAddr;
  1315.     struct rtentry *  pArpRt;
  1316.     struct radix_node_head *  pTwinHead;
  1317.     struct sockaddr *  pTwinKey;
  1318.     /*
  1319.      * Existing entries will prevent the addition of
  1320.      * matching host routes. Delete the entry and try
  1321.      * to add the host route again. The search is based
  1322.      * on the rtalloc1() routine.
  1323.      */
  1324.     pNode = rn_search ((caddr_t)pDest, pNodeHead->rnh_treetop);
  1325.     if ( (pNode->rn_flags & RNF_ROOT) == 0)
  1326.         {
  1327.         /* Check leaf node for ARP information or existing child route. */
  1328.         pTwinRt = (struct rtentry *)pNode;
  1329.         if ( (pTwinRt->rt_flags & RTF_CLONED) ||
  1330.                 (pTwinRt->rt_flags & RTF_LLINFO &&
  1331.                  pTwinRt->rt_flags & RTF_HOST &&
  1332.                  pTwinRt->rt_gateway &&
  1333.                  pTwinRt->rt_gateway->sa_family == AF_LINK))
  1334.             {
  1335.             /* Mimic RTM_DELETE case from rtrequest() routine. */
  1336.             pTwinKey = (struct sockaddr *)rt_key (pTwinRt);
  1337.             pTwinHead = rt_tables [pTwinKey->sa_family];
  1338.             if (pTwinHead)
  1339.                 {
  1340.                 pNode = pTwinHead->rnh_deladdr (pTwinKey, 0, pTwinHead);
  1341.                 if (pNode)
  1342.                     {
  1343.                     pArpRt = (struct rtentry *)pNode;
  1344.                     pArpRt->rt_flags &= ~RTF_UP;
  1345.                     if (pArpRt->rt_gwroute)
  1346.                         {
  1347.                         pArpRt = pArpRt->rt_gwroute;
  1348.                         RTFREE (pArpRt);
  1349.                         pArpRt = (struct rtentry *)pNode;
  1350.                         pArpRt->rt_gwroute = 0;
  1351.                         }
  1352.                     pIfAddr = pArpRt->rt_ifa;
  1353.                     if (pIfAddr && pIfAddr->ifa_rtrequest)
  1354.                         pIfAddr->ifa_rtrequest (RTM_DELETE, pArpRt, SA(0));
  1355.                     rttrash++;
  1356.                     if (pArpRt->rt_refcnt <= 0)
  1357.                         {
  1358.                         pArpRt->rt_refcnt++;
  1359.                         rtfree (pArpRt);
  1360.                         }
  1361.                     rtmodified++;
  1362.                     }
  1363.                 }    /* RTM_DELETE completed. */
  1364.             pNode = pNodeHead->rnh_addaddr ( (caddr_t)pDest, (caddr_t)pNetmask, 
  1365.                                             pNodeHead, pRoute->rt_nodes);
  1366.             }  /* End ARP entry replacement. */
  1367.         else
  1368.             {
  1369.             /*
  1370.              * Matching node was not a host entry. Reset node reference.
  1371.              */
  1372.             pNode = 0;
  1373.             }
  1374.         }    /* End handling for RNF_ROOT != 0 */
  1375.     else
  1376.         {
  1377.         /* 
  1378.          * No valid entry found: remove reference to leftmost/rightmost node.
  1379.          */
  1380.         pNode = 0;
  1381.         }
  1382.     return (pNode);
  1383.     }
  1384. /*
  1385.  * The rt_fixchange() routine adjusts the routing tree after adding a new
  1386.  * network route. If the system inserts the route between an older network
  1387.  * route and the corresponding (cloned) host routes, the new route might
  1388.  * incorporate existing cloned entries. This routine removes those (obsolete)
  1389.  * cloned routes. Unfortunately, it also needlessly examines a subtree and
  1390.  * removes valid cloned routes when adding a new (less specific) route above
  1391.  * a pre-existing entry. Since those routes will be regenerated if still in
  1392.  * use, this (wasteful) behavior does not prevent correct operation.
  1393.  */
  1394. static int
  1395. rt_fixchange(rn, vp)
  1396.         struct radix_node *rn;
  1397.         void *vp;
  1398. {
  1399.         struct rtentry *rt = (struct rtentry *)rn;
  1400.         struct rtentry *rt0 = vp;
  1401.         struct radix_node_head *rnh = rt_tables [AF_INET];
  1402.         u_char *xk1, *xm1, *xk2;
  1403.         int i, len;
  1404.         if (!rt->rt_parent)     /* Ignore uncloned entries. */
  1405.             return 0;
  1406.         /*
  1407.          * Check if the network number of the route entry matches
  1408.          * the destination of the new route.
  1409.          */
  1410.         len = min (rt_key (rt0)->sa_len, rt_key (rt)->sa_len);
  1411.         xk1 = (u_char *)rt_key (rt0);
  1412.         xm1 = (u_char *)rt_mask (rt0);
  1413.         xk2 = (u_char *)rt_key (rt);
  1414.         for (i = rnh->rnh_treetop->rn_off; i < len; i++) {
  1415.                 if ((xk2[i] & xm1[i]) != xk1[i]) {
  1416.                         return 0;
  1417.                 }
  1418.         }
  1419.         /* Remove the cloned route which is part of the new route's network. */
  1420.         return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
  1421.                          rt_mask(rt), rt->rt_flags, (struct rtentry **)0);
  1422. }
  1423. /*
  1424.  * The rt_fixdelete() routine removes any cloned routes (for storing path
  1425.  * MTU information) when the original route to the remote destination is
  1426.  * deleted or the gateway is changed. It has no affect on cloned entries
  1427.  * containing ARP information.
  1428.  */
  1429. int rt_fixdelete(rn, vp)
  1430.         struct radix_node *rn;
  1431.         void *vp;
  1432. {
  1433.         struct rtentry *rt = (struct rtentry *)rn;
  1434.         struct rtentry *rt0 = vp;
  1435.         if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_LLINFO)) {
  1436.                 return rtrequest(RTM_DELETE, rt_key(rt),
  1437.                                  (struct sockaddr *)0, rt_mask(rt),
  1438.                                  rt->rt_flags, (struct rtentry **)0);
  1439.         }
  1440.         return 0;
  1441. }
  1442. int
  1443. rt_setgate(rt0, dst, gate)
  1444. struct rtentry *rt0;
  1445. struct sockaddr *dst, *gate;
  1446. {
  1447. caddr_t new, old;
  1448. int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
  1449. register struct rtentry *rt = rt0;
  1450.         /*
  1451.  * Prevent addition of a host route with destination equal to
  1452.          * the gateway. Addition of such a route can cause infinite
  1453.  * recursion while doing a route search using rtalloc which might
  1454.  * result in stack overflow in tNetTask.
  1455.  */
  1456. if (((rt0->rt_flags & (RTF_HOST | RTF_GATEWAY | RTF_LLINFO)) ==
  1457.      (RTF_HOST | RTF_GATEWAY)) && (dst->sa_len == gate->sa_len) &&
  1458.      (((struct sockaddr_in *) dst)->sin_addr.s_addr ==
  1459.       ((struct sockaddr_in *) gate)->sin_addr.s_addr))
  1460.     return 1;
  1461. if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
  1462. old = (caddr_t)rt_key(rt);
  1463. R_Malloc(new, caddr_t, dlen + glen);
  1464. if (new == 0)
  1465.                     {
  1466. #ifdef WV_INSTRUMENTATION
  1467. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  1468.                     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 23, 3,
  1469.                                      WV_NETEVENT_RTSET_NOBUFS)
  1470. #endif  /* INCLUDE_WVNET */
  1471. #endif
  1472.                    return 1;
  1473.                    }
  1474. rt->rt_nodes->rn_key = new;
  1475. } else {
  1476. new = rt->rt_nodes->rn_key;
  1477. old = 0;
  1478. }
  1479. Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
  1480. if (old) {
  1481. Bcopy(dst, new, dlen);
  1482. Free(old);
  1483. }
  1484. if (rt->rt_gwroute) {
  1485. rt = rt->rt_gwroute; RTFREE(rt);
  1486. rt = rt0; rt->rt_gwroute = 0;
  1487. }
  1488. if (rt->rt_flags & RTF_GATEWAY) {
  1489. rt->rt_gwroute = rtalloc1(gate, 1);
  1490. }
  1491. return 0;
  1492. }
  1493. void
  1494. rt_maskedcopy(src, dst, netmask)
  1495. struct sockaddr *src, *dst, *netmask;
  1496. {
  1497. register u_char *cp1 = (u_char *)src;
  1498. register u_char *cp2 = (u_char *)dst;
  1499. register u_char *cp3 = (u_char *)netmask;
  1500. u_char *cplim = cp2 + *cp3;
  1501. u_char *cplim2 = cp2 + *cp1;
  1502. *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */
  1503. cp3 += 2;
  1504. if (cplim > cplim2)
  1505. cplim = cplim2;
  1506. while (cp2 < cplim)
  1507. *cp2++ = *cp1++ & *cp3++;
  1508. if (cp2 < cplim2)
  1509. bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2));
  1510. }
  1511. /*
  1512.  * Set up a routing table entry, normally
  1513.  * for an interface.
  1514.  */
  1515. int
  1516. rtinit(ifa, cmd, flags)
  1517. register struct ifaddr *ifa;
  1518. int cmd, flags;
  1519. {
  1520. register struct rtentry *rt;
  1521. register struct sockaddr *dst;
  1522. register struct sockaddr *deldst;
  1523. struct mbuf *m = 0;
  1524. struct rtentry *nrt = 0;
  1525. int error=0;
  1526. dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
  1527. #ifdef WV_INSTRUMENTATION
  1528. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  1529.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 35, 15,
  1530.                          WV_NETEVENT_RTINIT_START, cmd, 
  1531.                          ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  1532. #endif  /* INCLUDE_WVNET */
  1533. #endif
  1534. if (cmd == RTM_DELETE) {
  1535. if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
  1536. m = mBufClGet(M_WAIT, MT_SONAME, CL_SIZE_128, TRUE);
  1537. if (m == (struct mbuf *) NULL)
  1538.     {
  1539.     return (ENOBUFS);
  1540.     }
  1541. deldst = mtod(m, struct sockaddr *);
  1542. rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
  1543. dst = deldst;
  1544. }
  1545. if ((rt = rtalloc1(dst, 0))) {
  1546. rt->rt_refcnt--;
  1547. if (rt->rt_ifa != ifa) {
  1548. if (m)
  1549. (void) m_free(m);
  1550. return (flags & RTF_HOST ? EHOSTUNREACH
  1551. : ENETUNREACH);
  1552. }
  1553. }
  1554. }
  1555.         /*
  1556.          * Create the new route using the default weight value or delete
  1557.          * the matching entry. In either case, do not report the change
  1558.          * since the later hook generates both types of messages.
  1559.          */
  1560.        if(cmd==RTM_ADD)
  1561.    error=rtrequestAddEqui(dst, ifa->ifa_netmask, ifa->ifa_addr, 
  1562.               flags | ifa->ifa_flags,
  1563.                                   M2_ipRouteProto_local, 0, FALSE, FALSE,
  1564.   (ROUTE_ENTRY**)&nrt);
  1565.        if(cmd==RTM_DELETE)
  1566.    error=rtrequestDelEqui(dst, ifa->ifa_netmask, ifa->ifa_addr,
  1567.           flags | ifa->ifa_flags,
  1568.                                   M2_ipRouteProto_local, FALSE, FALSE,
  1569.   (ROUTE_ENTRY**)&nrt);
  1570. if (m)
  1571. (void) m_free(m);
  1572. if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
  1573.          if (rtNewAddrMsgHook) 
  1574. #ifdef ROUTER_STACK
  1575.                     (*rtNewAddrMsgHook) (cmd, ifa, nrt);
  1576. #else
  1577.                     (*rtNewAddrMsgHook) (cmd, ifa, error, nrt);
  1578. #endif /* ROUTER_STACK */
  1579. if (rt->rt_refcnt <= 0) {
  1580. rt->rt_refcnt++;
  1581. rtfree(rt);
  1582. }
  1583. }
  1584. if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
  1585. rt->rt_refcnt--;
  1586. if (rt->rt_ifa != ifa) {
  1587. logMsg("rtinit: wrong ifa (%x) was (%x)n", (int) ifa,
  1588. (int) rt->rt_ifa, 0, 0, 0, 0);
  1589. if (rt->rt_ifa->ifa_rtrequest)
  1590.     rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
  1591. IFAFREE(rt->rt_ifa);
  1592. rt->rt_ifa = ifa;
  1593. rt->rt_ifp = ifa->ifa_ifp;
  1594. ifa->ifa_refcnt++;
  1595. if (ifa->ifa_rtrequest)
  1596.     ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
  1597. }
  1598. if (rtNewAddrMsgHook)
  1599. #ifdef ROUTER_STACK
  1600.                     (*rtNewAddrMsgHook) (cmd, ifa, nrt);
  1601. #else
  1602.                     (*rtNewAddrMsgHook) (cmd, ifa, error, nrt);
  1603. #endif /* ROUTER_STACK */
  1604. }
  1605. return (error);
  1606. }
  1607. #ifdef RTALLOC_DEBUG
  1608. /*******************************************************************************
  1609. *
  1610. * routeEntryDebugShow - print an entry of the routing table
  1611. *
  1612. * This routine prints a routing table entry, displaying its mask, protocol,
  1613. * and type of service.
  1614. *
  1615. * RETURNS: OK or ERROR.
  1616. *
  1617. * NOMANUAL
  1618. */
  1619. LOCAL int routeEntryDebugShow
  1620.     (
  1621.     struct radix_node * rn              /* pointer to the node structure */
  1622.     )
  1623.     {
  1624.     FAST struct sockaddr *      destAddr = NULL;
  1625.     FAST struct sockaddr *      gateAddr;
  1626.     FAST struct rtentry *       pRt;
  1627.     char                        aStr [INET_ADDR_LEN];
  1628.     uint32_t                    mask;
  1629.     FAST UCHAR *                pChr;
  1630.  
  1631.     pRt = (struct rtentry *)rn;
  1632.     destAddr = rt_key(pRt);             /* get the destination address */
  1633.     gateAddr = pRt->rt_gateway;         /* get the gateway address */
  1634.     /*  arp entries */
  1635.     /*if ((gateAddr->sa_family == AF_LINK) && (pRt->rt_flags & RTF_HOST))
  1636.         return (0);*/
  1637.     /* print destination internet address */
  1638.     inet_ntoa_b (((struct sockaddr_in *)destAddr)->sin_addr, aStr);
  1639.     printf ("if_name: %s%dn",  pRt->rt_ifp->if_name, pRt->rt_ifp->if_unit);
  1640.     printf ("destination: %-16sn", (destAddr->sa_family == AF_INET) ?
  1641.                       aStr : "not AF_INETn");
  1642.     /* print netmask */
  1643.     if (rt_mask (pRt) == NULL)
  1644.         {
  1645.         mask = 0xffffffff;
  1646.         }
  1647.     else
  1648.         {
  1649.         mask = ((struct sockaddr_in *) rt_mask (pRt))->sin_addr.s_addr;
  1650.         mask = ntohl (mask);
  1651.         }
  1652.     printf ("mask: %-10lxn", mask);
  1653.     /* print the gateway address which: internet or linklevel */
  1654.     if (gateAddr->sa_family == AF_LINK)
  1655.         {
  1656.         if ( ((struct sockaddr_dl *)gateAddr)->sdl_alen == 6)
  1657.             {
  1658.             pChr = (UCHAR *)(LLADDR((struct sockaddr_dl *)gateAddr));
  1659.             printf ("ARP ROUTE: %02x:%02x:%02x:%02x:%02x:%-6xn",
  1660.                 pChr[0], pChr[1], pChr[2], pChr[3], pChr[4], pChr[5]);
  1661.             }
  1662.         else if ( ((struct sockaddr_dl *)gateAddr)->sdl_alen == 0)
  1663.             {
  1664.             printf("ARP Interface Route Entryn");
  1665.             }
  1666.         else
  1667.             {
  1668.             printf("Unknown Entryn");
  1669.             return(0);
  1670.             }
  1671.         }
  1672.     else
  1673.         {
  1674.         inet_ntoa_b (((struct sockaddr_in *)gateAddr)->sin_addr, aStr);
  1675.         printf ("Gateway: %-20s n", aStr);
  1676.         }
  1677.     /* print type of service */
  1678.     printf ("tos: %-5xn", TOS_GET (destAddr));
  1679.     printf ("flags: ");
  1680.     if (pRt->rt_flags & RTF_UP)
  1681.         printf("U");
  1682.     if (pRt->rt_flags & RTF_HOST)
  1683.         printf("H");
  1684.     if (pRt->rt_flags & RTF_LLINFO)
  1685.         printf("L");
  1686.     if (pRt->rt_flags & RTF_CLONING)
  1687.         printf("C ");
  1688.     if (pRt->rt_flags & RTF_STATIC)
  1689.         printf("S");
  1690.     if (pRt->rt_flags & RTF_GATEWAY)
  1691.         {
  1692.         printf("G");
  1693.         if (pRt->rt_gwroute)
  1694.             printf(": Gateway route entry = %p ", pRt->rt_gwroute);
  1695.         }
  1696.     printf ("n");
  1697.     printf ("refCnt: %-7dn",   pRt->rt_refcnt);
  1698.     printf ("rt_use: %-7ldn",  pRt->rt_use);
  1699.     printf ("proto: %-5dn",  RT_PROTO_GET (destAddr));
  1700.     return (0);
  1701.     }
  1702. #endif /* RTALLOC_DEBUG */