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

VxWorks

开发平台:

C/C++

  1. /* ripLib.c - Routing Information Protocol (RIP) v1 and v2 library */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1983, 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36. /*
  37. modification history
  38. --------------------
  39. 02c,22mar02,niq  Merged from Synth view, tor3_x.synth branch, ver 02x
  40. 02b,24jan02,niq  SPR 72415 - Added support for Route tags
  41.                  SPR 62733 - Initialize parameters correctly in ripSplitPacket
  42. 02a,15oct01,rae  merge from truestack ver 02n, base 01x (SPRs 70188, 69983 etc.) 
  43. 01z,10nov00,spm  merged from version 02b of tor3_x branch (multiple SPR fixes)
  44. 01y,06nov00,rae  Fixed SPR #26462
  45. 01x,16mar99,spm  recovered orphaned code from tor1_0_1.sens1_1 (SPR #25770)
  46. 01w,05oct98,spm  made task parameters adjustable and optimized stack 
  47.                  size (SPR #22422)
  48. 01v,11sep98,spm  general overhaul - moved expanded ripShutdown routine
  49.                  from ripTimer.c (SPR #22352); altered ripBuildPacket to 
  50.                  allow class-based masks for internal supernets (SPR #22350)
  51. 01u,01sep98,spm  changed ripBuildPacket to include correct netmask for
  52.                  classless routing (SPR #22220 and #22065); added support
  53.                  for default next hop routers (SPR #21940)
  54. 01t,26jun98,spm  corrected ripBuildPacket to test version against MIB values 
  55.                  (allowing RIPv1 updates) and added subnet test to use valid
  56.                  router in RIPv2 updates; moved semaphore creation before 
  57.                  first use; changed RIP_MCAST_ADDR constant from string to
  58.                  value; added ripClearInterfaces routine needed to comply
  59.                  with ANVL RIP tests; removed compiler warnings
  60. 01s,14dec97,jdi  doc: cleanup.
  61. 01r,21oct97,kbw  made minor man page font fix
  62. 01q,06oct97,gnn  added sendHook routines and cleaned up warnings
  63. 01p,04aug97,kbw  fixed man page problems found in beta review
  64. 01o,02jun97,gnn  fixed SPR 8685 so that the timer task does not respawn.
  65. 01n,16may97,gnn  added code to implement leaking routes.
  66.                  modified ripSplitPacket to handle stupid packets (ANVL).
  67.                  renamed myHook to ripAuthHook.
  68. 01m,08may97,gnn  fixed an authentication bug.
  69. 01l,05may97,rjc  changed error return value to m2Lib stuff.
  70. 01k,28apr97,gnn  added some descriptive text.
  71. 01j,20apr97,kbw  fixed man page format, did spell check.
  72. 01h,18apr97,gnn  removed device specific code.
  73. 01g,17apr97,gnn  fixed errors pointed out by ANVL.
  74. 01f,14apr97,gnn  added authentication hook routines.
  75. 01e,07apr97,gnn  removed device specific code.
  76. 01d,07apr97,gnn  cleared up some of the more egregious warnings.
  77.                  added MIB-II interfaces and options.
  78. 01c,12mar97,gnn  added multicast support.
  79.                  added time variables.
  80. 01b,24feb97,gnn  added routines for version 2 support.
  81. 01a,26nov96,gnn  created from BSD4.4 routed main.c
  82. */
  83. /*
  84. DESCRIPTION
  85. This library implements versions 1 and 2 of the Routing Information Protocol 
  86. (RIP). The protocol is intended to operate as an interior gateway protocol
  87. within a relatively small network with a longest path of 15 hops.
  88. HIGH-LEVEL INTERFACE
  89. The ripLibInit() routine links this library into the VxWorks image and begins
  90. a RIP session. This happens automatically if INCLUDE_RIP is defined at the
  91. time the image is built. Once started, RIP will maintain the network routing 
  92. table until deactivated by a call to the ripShutdown() routine, which will 
  93. remove all route entries and disable the RIP library routines. All RIP
  94. requests and responses are handled as defined in the RFC specifications.
  95. RFC 1058 defines the basic protocol operation and RFC 1723 details the
  96. extensions that constitute version 2.
  97. When acting as a supplier, outgoing route updates are filtered using simple
  98. split horizon. Split horizon with poisoned reverse is not currently available.
  99. Additional route entries may be excluded from the periodic update with the
  100. ripSendHookAdd() routine. 
  101. If a RIP session is terminated, the networking subsystem may not function 
  102. correctly until RIP is restarted with a new call to ripLibInit() unless
  103. routing information is provided by some other method.
  104. CONFIGURATION INTERFACE
  105. By default, a RIP session only uses the network interfaces created before it
  106. started. The ripIfSearch() routine allows RIP to recognize any interfaces 
  107. added to the system after that point. If the address or netmask of an
  108. existing interface is changed during a RIP session, the ripIfReset() 
  109. routine must be used to update the RIP configuration appropriately.
  110. The current RIP implementation also automatically performs the border
  111. gateway filtering required by the RFC specification. Those restrictions
  112. provide correct operation in a mixed environment of RIP-1 and RIP-2 routers.
  113. The ripFilterDisable() routine will remove those limitations, and can produce
  114. more efficient routing for some topologies. However, you must not use that 
  115. routine if any version 1 routers are present. The ripFilterEnable() routine 
  116. will restore the default behavior. 
  117. AUTHENTICATION INTERFACE
  118. By default, authentication is disabled, but may be activated by an SNMP
  119. agent on an interface-specific basis. While authentication is disabled,
  120. any RIP-2 messages containing authentication entries are discarded. When
  121. enabled, all RIP-2 messages without authentication entries are automatically
  122. rejected. To fully support authentication, an authentication routine should
  123. be specified with the ripAuthHookAdd() routine. The specified function
  124. will be called to screen every RIP-1 message and all unverified RIP-2 
  125. messages containing authentication entries. It may be removed with the 
  126. ripAuthHookDelete() routine. All RIP-1 and unverified RIP-2 messages will 
  127. be discarded while authentication is enabled unless a hook is present.
  128. OPTIONAL INTERFACE
  129. The ripLeakHookAdd() routine allows the use of an alternative routing
  130. protocol that uses RIP as a transport mechanism. The specified function
  131. can prevent the RIP session from creating any table entries from the
  132. received messages. The ripLeakHookDelete() routine will restore the
  133. default operation. 
  134. DEBUGGING INTERFACE
  135. As required by the RFC specification, the obsolete traceon and traceoff 
  136. messages are not supported by this implementation. The ripRouteShow()
  137. routine will display the contents of the internal RIP routing table.
  138. Routines such as mRouteShow() to display the corresponding kernel routing 
  139. table will also be available if INCLUDE_NET_SHOW is defined when the image 
  140. is built. If additional information is required, the ripDebugLevelSet() 
  141. routine will enable predefined debugging messages that will be sent to 
  142. the standard output.
  143. INCLUDE FILES: ripLib.h
  144. SEE ALSO: RFC 1058, RFC 1723
  145. */
  146. /*
  147.  * Routing Table Management Daemon
  148.  */
  149. #include "vxWorks.h"
  150. #include "rip/defs.h"
  151. #include "m2Lib.h"
  152. #include "sys/ioctl.h"
  153. #include "sys/socket.h"
  154. #include "inetLib.h"
  155. #include "taskLib.h"
  156. #include "tickLib.h"
  157. #include "sockLib.h"
  158. #include "sysLib.h"
  159. #include "lstLib.h"
  160. #include "routeEnhLib.h"
  161. #include "net/if.h"
  162. #include "errnoLib.h"
  163. #include "errno.h"
  164. #include "logLib.h"
  165. #include "wdLib.h"
  166. #include "semLib.h"
  167. #include "ioLib.h"
  168. #ifdef VIRTUAL_STACK
  169. #include "netinet/vsLib.h"
  170. #include "netinet/vsRip.h"
  171. #endif /* VIRTUAL_STACK */
  172. #ifdef RIP_MD5
  173. #include "rip/md5.h"
  174. #endif /* RIP_MD5 */
  175. /* forward declarations. */
  176. IMPORT void addrouteforif(register struct interface *ifp);
  177. IMPORT void ripRouteMetricSet (struct rt_entry * pRtEntry);
  178. void ripIfShow (void);
  179. #define SOCKADDR_IN(s) (((struct sockaddr_in*)(s))->sin_addr.s_addr)
  180. #define RIP_TASK_PRIORITY 101
  181. #define RIP_TIMER_TASK_PRIORITY 100
  182. #define RIP_TASK_STACK_SIZE 3750
  183. #define RIP_TIMER_TASK_STACK_SIZE 3000
  184. #define RIP_TASK_OPTIONS 0
  185. #define RIP_TIMER_TASK_OPTIONS 0
  186. #ifndef VIRTUAL_STACK
  187. /* globals */
  188. RIP  ripState;
  189. int routedDebug = 0;
  190. SEM_ID  ripLockSem;
  191. BOOL  ripFilterFlag = TRUE;
  192. LIST  ripIfExcludeList;
  193. /*
  194.  * Settings for primary and timer tasks. For correct operation, the timer
  195.  * task must run at a higher priority than the primary task. The stack
  196.  * sizes are chosen based on the high-water mark measured on a Sparc target,
  197.  * since the high use of registers in that architecture provides a likely
  198.  * maximum. The actual values measured were 2524 bytes for the primary task 
  199.  * and 1824 bytes for the timer task.
  200.  *
  201.  * Use a task priority between 100 and 255 as that is the default priority 
  202.  * range for a user protection domain.
  203.  */
  204. int _ripTaskPriority = RIP_TASK_PRIORITY;
  205. int _ripTaskOptions = RIP_TASK_OPTIONS;
  206. int _ripTaskStackSize = RIP_TASK_STACK_SIZE;
  207. int _ripTimerTaskPriority = RIP_TIMER_TASK_PRIORITY;
  208. int _ripTimerTaskOptions = RIP_TIMER_TASK_OPTIONS;
  209. int _ripTimerTaskStackSize = RIP_TIMER_TASK_STACK_SIZE;
  210. /* locals */
  211. LOCAL BOOL ripInitFlag = FALSE;
  212. IMPORT struct interface *ripIfNet;
  213. IMPORT struct interface **ifnext;
  214. #endif /* VIRTUAL_STACK */
  215. #ifdef ROUTER_STACK
  216. LOCAL char rtmMessages [][16] = {
  217.     "ILLEGAL",
  218.     "RTM_ADD",
  219.     "RTM_DELETE",
  220.     "RTM_CHANGE",
  221.     "RTM_GET",
  222.     "RTM_LOSING",
  223.     "RTM_REDIRECT",
  224.     "RTM_MISS",
  225.     "RTM_LOCK",
  226.     "RTM_OLDADD",
  227.     "RTM_OLDDEL",
  228.     "RTM_RESOLVE",
  229.     "RTM_NEWADDR",
  230.     "RTM_DELADDR",
  231.     "RTM_IFINFO",
  232.     "RTM_ADDEXTRA",
  233.     "RTM_DELEXTRA",
  234.     "RTM_NEWCHANGE",
  235.     "RTM_NEWGET",
  236.     "RTM_GETALL",
  237.     "RTM_NEWIPROUTE",
  238.     "RTM_OLDIPROUTE"
  239.     };
  240. #endif /* ROUTER_STACK */
  241. /* defines */
  242. #define BUFSPACE 127*1024
  243. #define ROUNDUP(a) 
  244.         ((a) > 0 ? (1 + (((a) - 1) | (sizeof (long) - 1))) : sizeof (long))
  245. #define ADVANCE(x, n) (x += ROUNDUP ((n)->sa_len))
  246.  
  247. /* forward declarations */
  248.    
  249. void rtdeleteall ();
  250. IMPORT void ripTimer ();
  251. int ripTask ();
  252. void timevaladd (struct timeval *t1, struct timeval *t2);
  253. void timevalsub (struct timeval *t1, struct timeval *t2);
  254. void ripTimeSet (struct timeval *pTimer);
  255. void process (int fd);
  256. #ifdef ROUTER_STACK
  257. LOCAL void ripRouteMsgProcess (void);
  258. LOCAL BOOL ripRouteSame (struct rt_entry *pRtEntry, struct sockaddr *pDstAddr, 
  259.                          struct sockaddr *pNetmask, struct sockaddr *pGateway);
  260. LOCAL STATUS ripInterfaceUpFlagSet (u_short ifIndex, BOOL up);
  261. LOCAL STATUS ripInterfaceDelete (struct interface *pIf);
  262. #endif /* ROUTER_STACK */
  263. void ripTimerArm (long timeout);
  264. int getsocket (int domain, int type, struct sockaddr_in *sin);
  265. void routedTableInit ();
  266. void rtdefault ();
  267. STATUS routedIfInit (BOOL resetFlag, long ifIndex);
  268. void routedInput (struct sockaddr *from, register RIP_PKT *rip, int size);
  269. void toall (int (*f)(), int rtstate, struct interface *skipif);
  270. LOCAL STATUS ripRoutesDelete (struct interface *pIf, BOOL deleteAllRoutes);
  271. LOCAL STATUS ripInterfaceIntDelete (struct interface *pIf, 
  272.                                     struct interface *pPrevIf);
  273. void _ripAddrsXtract (caddr_t cp, caddr_t cpLim, struct rt_addrinfo *pRtInfo);
  274. /******************************************************************************
  275. *
  276. * ripLibInit - initialize the RIP routing library
  277. *
  278. * This routine creates and initializes the global data structures used by 
  279. * the RIP routing library and starts a RIP session to maintain routing 
  280. * tables for a host. You must call ripLibInit() before you can use any other 
  281. * ripLib routines. A VxWorks image automatically invokes ripLibInit() 
  282. * if INCLUDE_RIP was defined when the image was built.
  283. *
  284. * The resulting RIP session will monitor all network interfaces that are 
  285. * currently available for messages from other RIP routers. If the <supplier>
  286. * parameter is true, it will also respond to specific requests from other
  287. * routers and transmit route updates over every known interface at the 
  288. * interval specified by <supplyInterval>.
  289. *
  290. * Specifying a <gateway> setting of true establishes this router as a
  291. * gateway to the wider Internet, capable of routing packets anywhere within 
  292. * the local networks. The final <multicast> flag indicates whether the
  293. * RIP messages are sent to the pre-defined multicast address of 224.0.0.9
  294. * (which requires a <version> setting of 2) or to the broadcast address of 
  295. * the interfaces.
  296. *
  297. * The <version> parameter determines the format used for outgoing RIP 
  298. * messages, and also sets the initial settings of the MIB-II compatibility 
  299. * switches in combination with the <multicast> flag. A <version> of 1 will 
  300. * restrict all incoming traffic to that older message type. A <version> of 
  301. * 2 will set the receive switch to accept either type unless <multicast> is 
  302. * true, which limits reception to version 2 messages only. SNMP agents may 
  303. * alter those settings on a per-interface basis once startup is complete.
  304. *
  305. * The remaining parameters set various system timers used to maintain the
  306. * routing table. All of the values are expressed in seconds, and must be
  307. * greater than or equal to 1. The <timerRate> determines how often
  308. * the routing table is examined for changes and expired routes. The
  309. * <supplyInterval> must be an exact multiple of that value. The
  310. * <expire> parameter specifies the maximum time between updates before
  311. * a route is invalidated and removed from the kernel table. Expired routes 
  312. * are then deleted from the internal RIP routing table if no update has
  313. * been received within the time set by the <garbage> parameter.
  314. *
  315. * The following configuration parameters determine the initial values for
  316. * all these settings. The default timer values match the settings indicated
  317. * in the RFC specification.
  318. *
  319. * ts
  320. * Parameter Name    | Default Value   | Configuration Parameter
  321. * ------------------+-----------------+------------------------
  322. * <supplier>        | 0 (FALSE)       | RIP_SUPPLIER
  323. * <gateway>         | 0 (FALSE)       | RIP_GATEWAY
  324. * <multicast>       | 0 (FALSE)       | RIP_MULTICAST
  325. * <version>         | 1               | RIP_VERSION
  326. * <timerRate>       | 1               | RIP_TIMER_RATE
  327. * <supplyInterval>  | 30              | RIP_SUPPLY_INTERVAL
  328. * <expire>          | 180             | RIP_EXPIRE_TIME
  329. * <garbage>         | 300             | RIP_GARBAGE_TIME
  330. * <authType>        | 1               | RIP_AUTH_TYPE
  331. * te
  332. *
  333. * INTERNAL
  334. * This routine creates two tasks, 'tRip' and 'tRipTimer'.  The first is the 
  335. * main loop of the routing task that monitors the routing port (520) for 
  336. * updates and request messages. The second task uses a watchdog timer and
  337. * signalling semaphore to update the internal RIP routing table. The 
  338. * 'ripLockSem' blocking semaphore provides any necessary interlocking between 
  339. * each of the tasks and the user routines that alter the RIP configuration.
  340. * RETURNS: OK; or ERROR, if configuration fails.
  341. *
  342. */
  343. STATUS ripLibInit
  344.     (
  345.     BOOL supplier,     /* operate in silent mode? */
  346.     BOOL gateway,     /* act as gateway to the Internet? */
  347.     BOOL multicast,     /* use multicast or broadcast addresses? */
  348.     int version,            /* 1 or 2: selects format of outgoing messages */
  349.     int timerRate,          /* update frequency for internal routing table */
  350.     int supplyInterval,     /* update frequency for neighboring routers */
  351.     int expire,             /* maximum interval for renewing learned routes */
  352.     int garbage,            /* elapsed time before deleting stale route */
  353.     int authType            /* default authentication type to use */
  354.     )
  355.     {
  356.     IMPORT STATUS m2RipInit ();
  357. #ifdef VIRTUAL_STACK
  358.     if ((vsTbl [myStackNum]->pRipGlobals != NULL) &&
  359.         (ripInitFlag))
  360.         return (OK);
  361. #else
  362.     if (ripInitFlag)
  363.         return (OK);
  364. #endif /* VIRTUAL_STACK */
  365.     if (version < 1 || version > 2)
  366.         return (ERROR);
  367.     if ((version < 2) && (multicast == TRUE))
  368.         return (ERROR);
  369.     
  370.     if (timerRate < 1)
  371.         return (ERROR);
  372.     if (supplyInterval < 1)
  373.         return (ERROR);
  374.     if (expire < 1)
  375.         return (ERROR);
  376.     if (garbage < 1)
  377.         return (ERROR);
  378. #ifdef VIRTUAL_STACK
  379.     /* Allocate space for former global variables. */
  380.     if (vsTbl[myStackNum]->pRipGlobals == NULL)
  381.         {
  382.         vsTbl[myStackNum]->pRipGlobals = malloc (sizeof (VS_RIP));
  383.         if (vsTbl[myStackNum]->pRipGlobals == NULL)
  384.             return (ERROR);
  385.         }
  386.     bzero ((char *)vsTbl [myStackNum]->pRipGlobals, sizeof (VS_RIP));
  387. #else
  388.     bzero ((char *)&ripState, sizeof (ripState));
  389. #endif /* VIRTUAL_STACK */
  390.  
  391.     /* Set the global state. */
  392.     ripState.version = version;
  393.     ripState.multicast = multicast;
  394.     ripState.timerRate = timerRate;
  395.     ripState.supplyInterval = supplyInterval;
  396.     ripState.expire = expire;
  397.     ripState.garbage = garbage;
  398.     ripState.pRouteHook = NULL;
  399.     ripFilterFlag = TRUE;  /* Enable border gateway filtering. */
  400.     routedDebug = 0;  /* Disable debugging messages by default. */
  401.     /* Initialize the list of interfaces on which RIP should not be started */
  402.     lstInit (&ripIfExcludeList);
  403. #ifdef VIRTUAL_STACK
  404.     /*
  405.      * Assign (former) global variables previously initialized by the compiler.
  406.      * Setting 0 is repeated for clarity - the vsLib.c setup zeroes all values.
  407.      */
  408.    _ripTaskPriority = RIP_TASK_PRIORITY;  /* ripLib.c */
  409.    _ripTaskOptions = RIP_TASK_OPTIONS;  /* ripLib.c */
  410.    _ripTaskStackSize = RIP_TASK_STACK_SIZE;  /* ripLib.c */
  411.    _ripTimerTaskPriority = RIP_TIMER_TASK_PRIORITY;  /* ripLib.c */
  412.    _ripTimerTaskOptions = RIP_TIMER_TASK_OPTIONS;  /* ripLib.c */
  413.    _ripTimerTaskStackSize = RIP_TIMER_TASK_STACK_SIZE;  /* ripLib.c */
  414.    ifnext = &ripIfNet;
  415. #endif
  416.     /*
  417.      * This all has to do with RIP MIB II stuff.
  418.      *
  419.      * We set a global configuration that all interfaces will have
  420.      * at startup time.  SNMP agents can then modify these values
  421.      * on a per interface basis.
  422.      */
  423.     m2RipInit ();
  424.     if (version == 1)
  425.         ripState.ripConf.rip2IfConfSend = M2_rip2IfConfSend_ripVersion1;
  426.     else if (multicast)
  427.         ripState.ripConf.rip2IfConfSend = M2_rip2IfConfSend_ripVersion2;
  428.     else
  429.         ripState.ripConf.rip2IfConfSend = M2_rip2IfConfSend_rip1Compatible;
  430.         
  431.     if (version == 1)
  432.         ripState.ripConf.rip2IfConfReceive = M2_rip2IfConfReceive_rip1;
  433.     else if (multicast)
  434.         ripState.ripConf.rip2IfConfReceive = M2_rip2IfConfReceive_rip2;
  435.     else
  436.         ripState.ripConf.rip2IfConfReceive = M2_rip2IfConfReceive_rip1OrRip2;
  437.     ripState.ripConf.rip2IfConfAuthType = authType;
  438.     ripState.ripConf.rip2IfConfStatus = M2_rip2IfConfStatus_valid;
  439.     /* Create the monitor task to receive and process RIP messages. */
  440.     ripState.ripTaskId = taskSpawn (RIP_TASK, _ripTaskPriority, 
  441.                                     _ripTaskOptions, _ripTaskStackSize, 
  442.                                     ripTask, supplier, gateway, multicast, 
  443. #ifdef VIRTUAL_STACK
  444.                                     myStackNum, 0, 0, 0, 0, 0, 0);
  445. #else
  446.                                     0, 0, 0, 0, 0, 0, 0);
  447. #endif
  448.     if (ripState.ripTaskId == ERROR)
  449.         {
  450. #ifdef VIRTUAL_STACK
  451.         free (vsTbl[myStackNum]->pRipGlobals);
  452.         vsTbl[myStackNum]->pRipGlobals = NULL;
  453. #endif
  454.         return (ERROR);
  455.         }
  456.     ripInitFlag = TRUE;
  457.     return (OK);
  458.     }
  459. STATUS ripTask
  460.     (
  461.     BOOL supplier,
  462.     BOOL gateway,
  463.     BOOL multicast
  464. #ifdef VIRTUAL_STACK
  465.     ,
  466.     int  stackNum
  467. #endif
  468.     )
  469.     {
  470.     int n, nfd, on;
  471.     struct timeval *pTimeout;
  472.     struct timeval waittime;
  473.     fd_set ibits;
  474.     extern STATUS ripLeakHook ();
  475. #ifdef VIRTUAL_STACK
  476.     register RIP_PKT *query;
  477.     /* Assign virtual stack number to access appropriate data structures. */
  478.     if (virtualStackNumTaskIdSet (stackNum) == ERROR)
  479.         {
  480.         if (routedDebug)
  481.             logMsg ("Unable to access stack data.n", 0, 0, 0, 0, 0, 0);
  482.         return (ERROR);
  483.         }
  484.     query = (RIP_PKT *)ripState.packet;
  485. #else
  486.     register RIP_PKT *query = (RIP_PKT *)ripState.packet;
  487. #endif
  488.     ripState.msg = (RIP_PKT *)ripState.packet;
  489.     
  490.     /* Fake out getservbyname. */
  491.     ripState.port = htons (RIP_PORT);
  492.     
  493.     ripState.addr.sin_family = AF_INET;
  494.     ripState.addr.sin_port = ripState.port;
  495.     ripState.addr.sin_addr.s_addr = INADDR_ANY;
  496.         
  497.     ripState.s = getsocket (AF_INET, SOCK_DGRAM, &ripState.addr);
  498.     if (ripState.s < 0)
  499.         {
  500.         if (routedDebug)
  501.             logMsg ("Unable to get input/output socket.n", 0, 0, 0, 0, 0, 0);
  502.         return (ERROR);
  503.         }
  504.     /* 
  505.      * Now open a routing socket so that we can receive routing messages
  506.      * from the Routing system
  507.      */
  508.     
  509.     ripState.routeSocket = socket (AF_ROUTE, SOCK_RAW, 0);
  510.     if (ripState.routeSocket < 0)
  511.         {
  512.         if (routedDebug)
  513.             logMsg ("Unable to get route socket.n", 0, 0, 0, 0, 0, 0);
  514.         close (ripState.s); 
  515.         return (ERROR);
  516.         }
  517.     /* Set the non-block option on the routing socket */
  518.     on = 1;
  519.     if (ioctl (ripState.routeSocket, FIONBIO, (int) &on) == -1) 
  520.         if (routedDebug) 
  521.             logMsg ("error setting O_NONBLOCK option on route socket.n", 
  522.                     0, 0, 0, 0, 0, 0);
  523.     /*
  524.      * Turn off the loopback option on the socket as we do not want
  525.      * routing messages for events generated a write on this socket.
  526.      * Currently we only read from this socket, never write to it.
  527.      * So this operation is a virtual no-op, but will come in handy
  528.      * if we ever use routing sockets to add/delete/change routes.
  529.      */
  530.     on = 0;
  531.     if (setsockopt (ripState.routeSocket, SOL_SOCKET, SO_USELOOPBACK, 
  532.                     (char *)&on, sizeof (on)) == ERROR)
  533.         if (routedDebug) 
  534.             logMsg ("error resetting SO_USELOOPBACK option on route socket.n", 
  535.                     0, 0, 0, 0, 0, 0);
  536.     ripState.supplier = supplier;
  537.     ripState.gateway = gateway;
  538.     /* VxWorks specific setup. */
  539.     ripState.timerDog = wdCreate ();
  540.     ripState.timerSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
  541.     if (ripState.timerSem == NULL)
  542.         {
  543.         if (routedDebug)
  544.             logMsg ("Error creating timer semaphore.n", 0, 0, 0, 0, 0, 0);
  545.         close (ripState.s); 
  546.         close (ripState.routeSocket); 
  547.         wdDelete (ripState.timerDog);
  548.         return (ERROR);
  549.         }
  550.     ripLockSem = semBCreate (SEM_Q_FIFO, SEM_FULL);
  551.     if (ripLockSem == NULL)
  552.         {
  553.         if (routedDebug)
  554.             logMsg ("Error creating mutex semaphore.n", 0, 0, 0, 0, 0, 0);
  555.         close (ripState.s); 
  556.         close (ripState.routeSocket); 
  557.         wdDelete (ripState.timerDog);
  558.         semDelete (ripState.timerSem);
  559.         return (ERROR);
  560.         }
  561.     /*
  562.      * Setup the hash tables for route entries and create entries to
  563.      * access the directly connected networks through the current
  564.      * interfaces. 
  565.      */
  566.     routedTableInit ();
  567.     if (routedIfInit (TRUE, 0) == ERROR)
  568.         {
  569.         if (routedDebug)
  570.             logMsg ("Error building interface list.n", 0, 0, 0, 0, 0, 0);
  571.         close (ripState.s); 
  572.         close (ripState.routeSocket); 
  573.         wdDelete (ripState.timerDog);
  574.         semDelete (ripState.timerSem);
  575.         semDelete (ripLockSem);
  576.         return (ERROR);
  577.         }
  578.     /*
  579.      * If configured as a gateway to the wider Internet, add an internal
  580.      * entry to the RIP routing table so that any default routes received 
  581.      * will be ignored.
  582.      */
  583.     if (ripState.gateway > 0)
  584.         rtdefault ();
  585.     if (ripState.supplier < 0)
  586.         ripState.supplier = 0;
  587.     /* 
  588.      * Send a request message over all available interfaces
  589.      * to retrieve the tables from neighboring RIP routers.
  590.      */
  591.     query->rip_cmd = RIPCMD_REQUEST;
  592.     query->rip_vers = ripState.version;
  593.     if (sizeof (query->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */
  594.         query->rip_nets[0].rip_dst.sa_family = htons ( (u_short)AF_UNSPEC);
  595.     else
  596.         query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
  597.     query->rip_nets[0].rip_metric = htonl ( (u_long)HOPCNT_INFINITY);
  598.     toall (sndmsg, 0, NULL);
  599.     
  600.     /* Start the watchdog used by the timer task to send periodic updates. */
  601.     ripTimerArm (ripState.timerRate);
  602.     /* Create the timer task. */
  603.     ripState.ripTimerTaskId = taskSpawn (RIP_TIMER, _ripTimerTaskPriority, 
  604.                                          _ripTimerTaskOptions, 
  605.                                          _ripTimerTaskStackSize,
  606.                                          (FUNCPTR)ripTimer,
  607. #ifdef VIRTUAL_STACK
  608.                                          stackNum, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  609. #else
  610.                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  611. #endif
  612.     if (ripState.ripTimerTaskId == ERROR)
  613.         {
  614.         if (routedDebug)
  615.             logMsg ("Error creating timer task. : errno=0x%xn", errno, 0, 0, 0, 
  616.                     0, 0);
  617.         close (ripState.s); 
  618.         close (ripState.routeSocket); 
  619.         wdCancel (ripState.timerDog);
  620.         wdDelete (ripState.timerDog);
  621.         semDelete (ripState.timerSem);
  622.         semDelete (ripLockSem);
  623.         return (ERROR);
  624.         }
  625.     FD_ZERO (&ibits);
  626.     nfd = max (ripState.s, ripState.routeSocket) + 1; /* 1 + max (fd's) */
  627.     for (;;)
  628.         {
  629.         FD_SET (ripState.s, &ibits);
  630.         FD_SET (ripState.routeSocket, &ibits);
  631.         if (ripState.needupdate)
  632.             {
  633.             /*
  634.              * Changes to the routing table entries occurred within the
  635.              * mandatory (random) quiet period following an earlier
  636.              * triggered update. Set the selection interval for incoming 
  637.              * messages to the remaining delay so that the pending 
  638.              * (cumulative) triggered update will be sent on schedule.
  639.              */
  640.             pTimeout = &waittime;
  641.             waittime = ripState.nextbcast;
  642.             timevalsub (&waittime, &ripState.now);
  643.             if (waittime.tv_sec < 0)
  644.                 {
  645.                 /* 
  646.                  * The scheduled update time has passed. Just poll the
  647.                  * interface before sending the triggered update.
  648.                  */
  649.                 waittime.tv_sec = 0;
  650.                 waittime.tv_usec = 0;
  651.                 }
  652.             if (routedDebug)
  653.                 logMsg ("Pending dynamic update scheduled in %d/%d sec/usecn",
  654.                         waittime.tv_sec, waittime.tv_usec, 0, 0, 0, 0);
  655.             }
  656.         else
  657.             {
  658.             /* 
  659.              * No triggered updates are pending. Wait for 
  660.              * messages indefinitely. 
  661.              */
  662.             pTimeout = (struct timeval *)NULL;
  663.             }
  664.         n = select (nfd, &ibits, 0, 0, pTimeout);
  665.         if (n <= 0)
  666.             {
  667.             /*
  668.              * No input received during specified interval: generate 
  669.              * (delayed) triggered update if needed. Ignore all other 
  670.              * errors (e.g. EINTR).
  671.              */
  672.             if (n < 0)
  673.                 {
  674.                 if (errno == EINTR)
  675.                     continue;
  676.                 if (routedDebug)
  677.                     logMsg ("Error %d (%x) from select call", 
  678.                             n, errno, 0, 0, 0, 0);
  679.                 }
  680.             /* Block timer task to prevent overlapping updates. */
  681.             semTake (ripLockSem, WAIT_FOREVER);
  682.             if (n == 0 && ripState.needupdate)
  683.                 {
  684.                 /* 
  685.                  * The pending triggered update was not subsumed by a
  686.                  * regular update during the selection interval. Send it
  687.                  * and reset the update flag and timers.
  688.                  */
  689.                 if (routedDebug)
  690.                     logMsg ("send delayed dynamic updaten", 0, 0, 0, 0, 0, 0);
  691.                 ripTimeSet (&ripState.now);
  692.                 toall (supply, RTS_CHANGED, (struct interface *)NULL);
  693.                 ripState.lastbcast = ripState.now;
  694.                 ripState.needupdate = 0;
  695.                 ripState.nextbcast.tv_sec = 0;
  696.                 }
  697.             semGive (ripLockSem);
  698.             continue;
  699.             }
  700.         ripTimeSet (&ripState.now);
  701.         /* 
  702.          * Block the timer task to prevent overlapping updates or
  703.          * route addition/deletion during 
  704.          * processing of RIP and route messages.
  705.          */
  706.         semTake  (ripLockSem, WAIT_FOREVER);
  707.         /* If RIP messages have arrived, process them */
  708.         if (FD_ISSET (ripState.s, &ibits))
  709.             process (ripState.s);
  710.         semGive (ripLockSem);
  711. #ifdef ROUTER_STACK
  712.         /* If there are any routing messages, process them */
  713.         if (FD_ISSET (ripState.routeSocket, &ibits))
  714.             ripRouteMsgProcess ();
  715. #endif /* ROUTER_STACK */
  716. }
  717.     }
  718. void timevaladd (t1, t2)
  719. struct timeval *t1, *t2;
  720. {
  721. t1->tv_sec += t2->tv_sec;
  722. if ((t1->tv_usec += t2->tv_usec) > 100000) {
  723. t1->tv_sec++;
  724. t1->tv_usec -= 1000000;
  725. }
  726. }
  727. void timevalsub (t1, t2)
  728. struct timeval *t1, *t2;
  729. {
  730. t1->tv_sec -= t2->tv_sec;
  731. if ((t1->tv_usec -= t2->tv_usec) < 0) {
  732. t1->tv_sec--;
  733. t1->tv_usec += 1000000;
  734. }
  735. }
  736. /******************************************************************************
  737. *
  738. * ripTimeSet - update a RIP timer
  739. *
  740. * This routine sets the various RIP timers used to track periodic updates
  741. * to the elapsed time since startup. Because all events use relative
  742. * times, the actual (calendar) time is not necessary.
  743. *
  744. * RETURNS: N/A
  745. *
  746. * ERRNO: N/A
  747. *
  748. * NOMANUAL
  749. */
  750. void ripTimeSet
  751.     (
  752.     struct timeval *  pTimer  /* destination for timestamp */
  753.     ) 
  754.     {
  755.     int clockrate;
  756.     ULONG tickcount;
  757.     tickcount = tickGet ();
  758.     clockrate = sysClkRateGet ();
  759.     pTimer->tv_sec = tickcount / clockrate;
  760.     pTimer->tv_usec = (1000000 * tickcount % clockrate) / clockrate;
  761.     return;
  762.     }
  763. void process (fd)
  764. int fd;
  765. {
  766. struct sockaddr from;
  767. int fromlen, cc;
  768. union {
  769. char buf[MAXPACKETSIZE+1];
  770. RIP_PKT rip;
  771. } inbuf;
  772.         bzero ((char *)&from, sizeof (from));
  773. for (;;) {
  774. fromlen = sizeof (from);
  775. cc = recvfrom (fd, (char *)&inbuf, sizeof (inbuf), 0, 
  776.                                &from, &fromlen);
  777. if (cc <= 0) {
  778. if (cc < 0 && errno != EWOULDBLOCK)
  779.                             {
  780.                             if (routedDebug)
  781. logMsg ("Error %d (%x) reading RIP message.n",
  782.                                         cc, errno, 0, 0, 0, 0);
  783.                             }
  784. break;
  785. }
  786. if (fromlen != sizeof (struct sockaddr_in))
  787. break;
  788. routedInput (&from, &inbuf.rip, cc);
  789. }
  790. }
  791. /******************************************************************************
  792. *
  793. * _ripAddrsXtract - extract socket addresses
  794. *
  795. * This routine is a copy of the rt_xaddrs() routine in rtsock.c
  796. * Copied here so that RIP can access it from a non-kernel domain
  797. * it basicaly fills in the rti_info array with pointers to the
  798. * sockaddr structures denoted by the rti_addrs field.
  799. * The sockaddr structures themselves start at <cp> and end at <cpLim>.
  800. *
  801. * RETURNS: N/A
  802. *
  803. * ERRNO: N/A
  804. *
  805. * NOMANUAL
  806. */
  807. void _ripAddrsXtract
  808.     (
  809.     caddr_t cp,
  810.     caddr_t cpLim, 
  811.     struct rt_addrinfo * pRtInfo
  812.     ) 
  813.     {
  814.     register struct sockaddr * pSockAddr; 
  815.     register int  i;
  816.  
  817.     bzero ((char *)pRtInfo->rti_info, sizeof (pRtInfo->rti_info));
  818.     for (i = 0; (i < RTAX_MAX) && (cp < cpLim); i++) 
  819.         {
  820.         if ((pRtInfo->rti_addrs & (1 << i)) == 0)
  821.             continue;
  822.         pRtInfo->rti_info[i] = pSockAddr = (struct sockaddr *)cp;
  823.         if (pSockAddr->sa_len == 0)
  824.             pRtInfo->rti_info[i] = NULL;
  825.         ADVANCE (cp, pSockAddr);
  826.         }
  827.     }
  828. /******************************************************************************
  829. *
  830. * ripAddrsXtract - extract socket address pointers from the route message
  831. *
  832. * This routine extracts the socket addresses from the route message in 
  833. * <pRtInfo> and uses the other parameters to return pointers to the 
  834. * extracted messages.
  835. * is
  836. * i <pRtInfo>
  837. * Passes in a pointer to a route information message. 
  838. * i <pDstAddr>    
  839. * Returns a pointer to the destination address.
  840. * i <pNetmask>    
  841. * Returns a pointer to the netmask.
  842. * i <pGateway>    
  843. * Returns a pointer to the gateway address.
  844. * i <pOldGateway>  
  845. * Returns a pointer to the OLD gateway address if it exists.
  846. * ie
  847. *              
  848. * If the route message doesn't specify an address, the corresponding
  849. * address pointer is set to NULL
  850. *
  851. * RETURNS: N/A
  852. *
  853. * ERRNO: N/A
  854. */
  855. void ripAddrsXtract
  856.     (
  857.     ROUTE_INFO * pRtInfo, /* Route information message */
  858.     struct sockaddr ** pDstAddr, /* Where to store the Destination addr
  859.                                            pointer */
  860.     struct sockaddr ** pNetmask, /* Where to store the netmask pointer*/
  861.     struct sockaddr ** pGateway, /* Where to store the Gateway addr
  862.                                            pointer */
  863.     struct sockaddr ** pOldGateway /* Where to store the Old gateway addr
  864.                                            (if any) pointer */
  865.     ) 
  866.     {
  867.     struct rt_addrinfo rtInfo; 
  868.     /* First extract pointers to the addresses into the info structure */
  869.     rtInfo.rti_addrs = pRtInfo->rtm.rtm_addrs;
  870.     _ripAddrsXtract ((caddr_t)pRtInfo->addrs, 
  871.                      (caddr_t)&pRtInfo->addrs[RTAX_MAX], 
  872.                      &rtInfo);
  873.  
  874.     /* Now set the users's pointers to point to the addresses */
  875.     *pDstAddr = INFO_DST (&rtInfo);
  876.     *pNetmask = INFO_MASK (&rtInfo);
  877.     *pGateway = INFO_GATE (&rtInfo);
  878.     *pOldGateway = INFO_AUTHOR (&rtInfo);
  879.     }
  880. /******************************************************************************
  881. *
  882. * ripSockaddrPrint - print a sockaddr structure
  883. *
  884. * This routine is a copy of the db_print_sa() routine in if_ether.c
  885. * Copied here so that RIP can access it from a non-kernel domain.
  886. * It prints out the sockaddr structure pointed to by <pSockAddr>
  887. *
  888. * RETURNS: N/A
  889. *
  890. * ERRNO: N/A
  891. *
  892. * NOMANUAL
  893. */
  894. void ripSockaddrPrint
  895.     (
  896.     struct sockaddr * pSockAddr /* Sockaddr to be printed */
  897.     )
  898.     {
  899.     int  len;
  900.     u_char * p;
  901.     if (pSockAddr == 0) 
  902.         {
  903.         printf ("[NULL]n");
  904.         return;
  905.         }
  906.     p = (u_char *)pSockAddr;
  907.     len = pSockAddr->sa_len;
  908.     printf ("[");
  909.     while (len > 0) 
  910.         {
  911.         printf ("%d", *p);
  912.         p++; len--;
  913.         if (len) 
  914.             printf (",");
  915.         }
  916.     printf ("]n");
  917.     }
  918. #ifdef ROUTER_STACK
  919. /***************************************************************************
  920. *
  921. * ripRouteMsgProcess - Process the routing socket messages
  922. *
  923. * This function retrieves the messages from the routing sockets 
  924. * and processes them. It handles the following messages:
  925. *
  926. * RTM_IFINFO:
  927. *       This message indicates if an interface has been brought up or down.
  928. *       If the interface is brought up, this routine does the following:
  929. *         For all interfaces that match the name, it marks the interface UP
  930. *         and adds the interface route.
  931. *         Then it calls the routedIfInit() call to pick up any addresses that
  932. *         were added to the interface when the interface was down
  933. *       If the interface is brought down, this routine does the following:
  934. *         For all interfaces that match the name, it marks the interface DOWN.
  935. *         Routes passing through the interface are deleted except the
  936. *         routes we learned through the Routing socket messages. Those routes
  937. *         will not be advertised though.
  938. * RTM_NEWADDR:
  939. * Calls the routedIfInit() routine to pick up the new address. If the
  940. * interface is down, routedIfInit() doesn't do anything. The new address
  941. * is picked up when the interface comes back up.
  942. * RTM_DELADDR:
  943. * Deletes all routes that pass though the interface whose address
  944. * matches the deleted address and then deletes the interface structure
  945. * Deleting the interface structure would cause the MIB settings for
  946. * the structure to be lost, but that is OK as the MIB settings do
  947. * not apply to an interface name, but to an interface addr. Thus if
  948. * the address goes away, it is reasonable to remove whatever settings
  949. * were associated with it.
  950. * RTM_ADD:
  951. * RTM_ADDEXTRA:
  952. * This message indicates that a route has been added. If the route 
  953. * is installed by us or the system (interface route) it is ignored.
  954. * All other routes are passed to the user route handler hook routine
  955. * if it is installed. If the handler is not installed the route is
  956. * ignored. If the handler returns a metric < HOPCNT_INFINITY, then we
  957. * install the route if none exists already. If a route already exists
  958. * for the same destination then we use the following logic to determine
  959. * if we need to replace the old route with the new one:
  960. *   If the old route is a RIP route, we replace it with the new one
  961. *   If the metric of the old route is greater than or equal to
  962. *         the metric of the new route, then we replace the old route.
  963. * RTM_ADD signifies that it the route is the primary route and
  964. * RTM_ADDEXTRA signifies a duplicate route. We don't prefer
  965. * one over the other and let the user route hook do that.
  966. * RTM_NEWIPROUTE:
  967. * This message indicates that a formerly duplicate route has been
  968. * promoted to being a primary route because either the previously
  969. * primary route was deleted or demoted because of weight change.
  970. * We treat this just as we would treat the RTM_ADD command, except
  971. *       that we mark the previous primary route as non-primary.
  972. * RTM_DELETE:
  973. * RTM_DELEXTRA:
  974. * This message indicates that the route has been deleted. Again if
  975. * the route has been installed by us or by the system, we ignore it,
  976. * else if the exact same route exists in our table we delete it.
  977. * RTM_DELETE signifies that the route is the primary route and
  978. * RTM_DELEXTRA signifies a duplicate route. 
  979. * RTM_OLDIPROUTE:
  980. * This message indicates that a formerly primary route has been
  981. * demoted to being a duplicate route because either a new
  982. * primary route was added or because of weight change.
  983. * If we have this route in our cache we mark it non-primary.
  984. *
  985. * RTM_CHANGE:
  986. * RTM_NEWCHANGE:
  987. * This message indicates that either the route metric and or the
  988. * route gateway has been changed. We first check if we know about this
  989. * route. If we don't, we ignore it, else if it is only a metric change,
  990. * we record that in our copy of the route. If the gateway has changed,
  991. * we invoke the user route hook routine, if installed, to provide
  992. * us an alternate metric, else we use the metric in the route. Finally
  993. * we change the gateway in our copy of the route.
  994. * RTM_REDIRECT:
  995. * This message indicates a gateway change caused by an ICMP redirect
  996. * message. This should happen only with static routes. 
  997. * We simply invoke the route Hook if it is installed to notify the
  998. * user of the redirect. If is the user's responsibility to deal
  999. * with the redirect message.
  1000. *
  1001. * RETURNS: N/A
  1002. *
  1003. * NOMANUAL
  1004. */
  1005. LOCAL void ripRouteMsgProcess (void) 
  1006.     {
  1007.     int cmd;
  1008.     int flags;
  1009.     int routeProto;
  1010.     int metric;
  1011.     int hookFlag;
  1012.     long count; 
  1013.     u_short index;
  1014.     struct rt_addrinfo rtInfo; 
  1015.     struct sockaddr * pDstAddr = NULL; 
  1016.     struct sockaddr * pNetmask = NULL; 
  1017.     struct sockaddr * pGateway = NULL;
  1018.     struct sockaddr * pOldGateway;
  1019.     struct interface *  pIf; 
  1020.     struct rt_entry * pRtEntry;
  1021.     BOOL primaryRoute;
  1022.     union 
  1023.         {
  1024.         ROUTE_INFO rtMsg; /* Route message */
  1025.         struct if_msghdr ifMsg; /* Interface message header */
  1026.         struct 
  1027.             {
  1028.             struct ifa_msghdr ifa; 
  1029.             struct sockaddr addrs [RTAX_MAX];
  1030.             }  ifaMsg; /* Interface address message */
  1031.         }  msg;  /* Routing socket message */
  1032.     /*
  1033.      * Receive the messages from the routing socket. Return when there
  1034.      * are no more
  1035.      */
  1036.     FOREVER
  1037.         {
  1038.         count = recv (ripState.routeSocket, (char *)&msg, sizeof (msg), 0);
  1039.         if (count <= 0) 
  1040.             {
  1041.             if (count < 0 && errno != EWOULDBLOCK)
  1042.                 if (routedDebug)
  1043.                     logMsg ("Error %d (%x) reading Route message.n",
  1044.                             count, errno, 0, 0, 0, 0);
  1045.             return;
  1046.             }
  1047.         /* Skip if not the correct version of routing socket message */
  1048.         if (msg.rtMsg.rtm.rtm_version != RTM_VERSION) 
  1049.             {
  1050.             logMsg ("Bogus routing message version %dn", 
  1051.                     msg.rtMsg.rtm.rtm_version, 0, 0, 0, 0, 0);
  1052.             continue;
  1053.             }
  1054.         cmd = msg.rtMsg.rtm.rtm_type;
  1055.         /*
  1056.          * Retrieve the interface index and validate parameters
  1057.          * based on the command value
  1058.          */
  1059.         switch (cmd)
  1060.             {
  1061.             case RTM_ADD: /* Fall through */
  1062.             case RTM_DELETE: /* Fall through */
  1063.             case RTM_CHANGE: /* Fall through */
  1064.             case RTM_REDIRECT: /* Fall through */
  1065.             case RTM_ADDEXTRA: /* Fall through */
  1066.             case RTM_DELEXTRA: /* Fall through */
  1067.             case RTM_NEWCHANGE: /* Fall through */
  1068.             case RTM_NEWIPROUTE: /* Fall through */
  1069.             case RTM_OLDIPROUTE:
  1070.                 index = msg.rtMsg.rtm.rtm_index;
  1071.                 if (msg.rtMsg.rtm.rtm_flags & RTF_LLINFO) 
  1072.                     {
  1073.                     if (routedDebug)
  1074.                         logMsg ("ignore route message %s for ifindex %d ARPn", 
  1075.                                 (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); 
  1076.                     continue;
  1077.                     }
  1078.                 /* Now extract the sockaddr structures into the rtInfo array */
  1079.                 rtInfo.rti_addrs = msg.rtMsg.rtm.rtm_addrs;
  1080.                 _ripAddrsXtract ((caddr_t)msg.rtMsg.addrs, 
  1081.                                  (caddr_t)&msg.rtMsg.addrs[RTAX_MAX], 
  1082.                                  &rtInfo);
  1083.                 /* Set the destination, netmask and gateway address pointers */
  1084.                 pDstAddr = INFO_DST (&rtInfo);
  1085.                 pGateway = INFO_GATE (&rtInfo);
  1086.                 pNetmask = INFO_MASK (&rtInfo);
  1087.                 /* So some sanity checking on the addresses */
  1088.                 /* No destination address ? Reject it */
  1089.                 if (pDstAddr == 0) 
  1090.                     {
  1091.                     if (routedDebug)
  1092.                         logMsg ("ignore route message %s for ifindex %d without"
  1093.                                 "dstn", (int)(rtmMessages [cmd]), 
  1094.                                 index, 0, 0, 0, 0);
  1095.                     continue;
  1096.                     }
  1097.                 /* Destination address doesn't belong to the Internet family */
  1098.                 if (pDstAddr->sa_family != AF_INET) 
  1099.                     {
  1100.                     if (routedDebug)
  1101.                         logMsg ("ignore route message %s for ifindex %d for AF %dn",
  1102.                                 (int)(rtmMessages [cmd]), index, 
  1103.                                 pDstAddr->sa_family, 0, 0, 0);
  1104.                     continue;
  1105.                     }
  1106.                 /* Destination address is a multicast address ?  Reject it */
  1107.                 if (IN_MULTICAST (ntohl (S_ADDR (pDstAddr)))) 
  1108.                     {
  1109.                     if (routedDebug)
  1110.                         logMsg ("ignore route message %s for ifindex %d multicastn",
  1111.                                 (int)(rtmMessages [cmd]), index, 0, 0, 0, 0);
  1112.                         continue;
  1113.                     }
  1114.                 /* 
  1115.                  * If the gateway address is AF_LINK, this is an interface
  1116.                  * route. Ignore it.
  1117.                  */
  1118.                 if (pGateway != NULL) 
  1119.                     {
  1120.                     if (pGateway->sa_family == AF_LINK) 
  1121.                         {
  1122.                         if (routedDebug)
  1123.                             {
  1124.                             logMsg ("Got interface address in %s for ifindex %dn",
  1125.                                     (int)(rtmMessages [cmd]), index, 
  1126.                                     0, 0, 0, 0);
  1127.                             ripSockaddrPrint (pDstAddr);
  1128.                             ripSockaddrPrint (pNetmask);
  1129.                             ripSockaddrPrint (pGateway);
  1130.                             }
  1131.                         continue;
  1132.                         }
  1133.                     }
  1134.                 /* 
  1135.                  * If the gateway flag is not set, if must be an 
  1136.                  * interface route. Ignore it.
  1137.                  */
  1138.                 if ((msg.rtMsg.rtm.rtm_flags & RTF_GATEWAY) == 0) 
  1139.                     {
  1140.                     if (routedDebug)
  1141.                         {
  1142.                         logMsg ("got i/f route message %s for ifindex %d ARPn", 
  1143.                                 (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); 
  1144.                         ripSockaddrPrint (pDstAddr);
  1145.                         ripSockaddrPrint (pNetmask);
  1146.                         ripSockaddrPrint (pGateway);
  1147.                         }
  1148.                     continue;
  1149.                     }
  1150.                 break;
  1151.             case RTM_NEWADDR: /* Fall through */
  1152.             case RTM_DELADDR:
  1153.                 index = msg.ifaMsg.ifa.ifam_index;
  1154.                 /* 
  1155.                  * Now extract the sockaddr structures into the
  1156.                  * rtInfo array 
  1157.                  */
  1158.                 rtInfo.rti_addrs = msg.ifaMsg.ifa.ifam_addrs;
  1159.                 _ripAddrsXtract ((caddr_t)msg.ifaMsg.addrs, 
  1160.                                  (caddr_t)&msg.ifaMsg.addrs[RTAX_MAX], 
  1161.                                  &rtInfo);
  1162.                 break;
  1163.             default:
  1164.                 index = msg.ifMsg.ifm_index; 
  1165.                 break;
  1166.             }
  1167.         if (routedDebug)
  1168.             {
  1169.             if (cmd <= (sizeof (rtmMessages) / sizeof (rtmMessages[0]))) 
  1170.                 logMsg ("nripRouteMsgProcess:cmd = %s Interface index = %dn", 
  1171.                         (int)(rtmMessages [cmd]), index, 0, 0, 0, 0);
  1172.             else
  1173.                 logMsg ("nripRouteMsgProcess:cmd = %d Interface index = %dn", 
  1174.                         cmd, index, 0, 0, 0, 0);
  1175.             }
  1176.         /* Now process the actual commands */
  1177.         switch (cmd) 
  1178.             {
  1179.             case RTM_ADD:
  1180.             case RTM_ADDEXTRA:
  1181.             case RTM_NEWIPROUTE:
  1182.                 if (msg.rtMsg.rtm.rtm_errno != 0) 
  1183.                     {
  1184.                     if (routedDebug)
  1185.                         logMsg ("ignore route message %s for index %d" 
  1186.                                 " error = %dn", (int)rtmMessages [cmd], 
  1187.                                 index, msg.rtMsg.rtm.rtm_errno, 0, 0, 0);
  1188.                     break;
  1189.                     } 
  1190.                 if (routedDebug) 
  1191.                     {
  1192.                     logMsg ("RIP: %s received for index %dn", 
  1193.                             (int)rtmMessages [cmd], index, 0, 0, 0, 0);
  1194.                     ripSockaddrPrint (pDstAddr);
  1195.                     ripSockaddrPrint (pNetmask);
  1196.                     ripSockaddrPrint (pGateway);
  1197.                     }
  1198.                 /* 
  1199.                  * If the route was installed by us or is an interface
  1200.                  * route, ignore it. We already know about it
  1201.                  */
  1202.                 routeProto = RT_PROTO_GET (pDstAddr);
  1203.                 if (routeProto == M2_ipRouteProto_rip ||
  1204.                     routeProto == M2_ipRouteProto_local)
  1205.                     break;
  1206.                 primaryRoute = (cmd == RTM_ADDEXTRA) ? FALSE : TRUE;
  1207.                 /*
  1208.                  * The destination sockaddr structure has the 
  1209.                  * protocol value set. Make it zero since 
  1210.                  * we compare the entire sockaddr structure at other
  1211.                  * places (input.c for example) that expect the
  1212.                  * standard fields to be zero.
  1213.                  * We set the gateway sockaddr fields to be zero
  1214.                  * too (just being paranoid, in case they aren't already zero)
  1215.                  * as rtlookup() expects it to be zero. Do the same
  1216.                  * for the TOS value too.
  1217.                  * We store the proto value anyway in the rtentry
  1218.                  * structure.
  1219.                  */
  1220.                 RT_PROTO_SET (pGateway, 0);
  1221.                 TOS_SET (pGateway, 0);
  1222.                 RT_PROTO_SET (pDstAddr, 0);
  1223.                 TOS_SET (pDstAddr, 0);
  1224.                 /*
  1225.                  * If a new primary route is coming into being,
  1226.                  * we should mark our primary route, if any, as non-primary
  1227.                  * We don't need to do this for RTM_ADD as it will be preceded
  1228.                  * by a RTM_OLDIPROUTE if there was a pre existing primary
  1229.                  * route
  1230.                  */
  1231.                 if (cmd == RTM_NEWIPROUTE)
  1232.                     {
  1233.                     /* Take the semaphore to lock the RIP timer task out */
  1234.                     semTake (ripLockSem, WAIT_FOREVER); 
  1235.                     pRtEntry = rtlookup (pDstAddr);
  1236.                     if (pRtEntry != NULL && 
  1237.                         ripRouteSame (pRtEntry, pDstAddr, pNetmask, NULL))
  1238.                         {
  1239.                         if (routedDebug)
  1240.                             logMsg ("RTM_NEWIPROUTE: demoting primary routen", 
  1241.                                     0, 0, 0, 0, 0, 0); 
  1242.                         pRtEntry->rt_state &= ~RTS_PRIMARY;
  1243.                         }
  1244.                     /*
  1245.                      * If we have the exact same route in our table,
  1246.                      * then mark it as primary 
  1247.                      */
  1248.                     if (pRtEntry != NULL && 
  1249.                         ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway))
  1250.                         {
  1251.                         if (routedDebug)
  1252.                             logMsg ("RTM_NEWIPROUTE: restoring primary routen", 
  1253.                                     0, 0, 0, 0, 0, 0); 
  1254.                         pRtEntry->rt_state |= RTS_PRIMARY;
  1255.                         }
  1256.                     /* Now release the semaphore we took earlier */
  1257.                     semGive (ripLockSem);
  1258.                     }
  1259. addIt:
  1260.                 /* 
  1261.                  * Now set the route hook flag to signify whether it
  1262.                  * is an add operation or a change operation.
  1263.                  * Note that we can get here from change processing too.
  1264.                  * Also we treat RTM_NEWIPROUTE as a change since it is
  1265.                  * not a new route that is being added to the system.
  1266.                  */
  1267.                 hookFlag = (cmd == RTM_ADD || cmd == RTM_ADDEXTRA) ?
  1268.                     0 : RIP_ROUTE_CHANGE_RECD;
  1269.                 /*
  1270.                  * Call the user hook routine if installed. If the routine
  1271.                  * returns a metric less than infinity, add the route to
  1272.                  * our table, else just ignore it. The user is responsible
  1273.                  * for setting the metric of the route. In case he forgets
  1274.                  * to assign a valid metric, assign a default metric of 1
  1275.                  */
  1276.                 if (ripState.pRouteHook == NULL)
  1277.                     break; 
  1278.                 if ((metric = (ripState.pRouteHook)
  1279.                      (&msg.rtMsg, routeProto, primaryRoute, hookFlag)) >= 
  1280.                     HOPCNT_INFINITY)
  1281.                     {
  1282.                     /* Take the semaphore to lock the RIP timer task out */
  1283.                     semTake (ripLockSem, WAIT_FOREVER); 
  1284.                     pRtEntry = rtlookup (pDstAddr);
  1285.                     /*
  1286.                      * If we have the exact same route in our table,
  1287.                      * then delete it as the user doesn't want it.
  1288.                      */
  1289.                     if (pRtEntry != NULL && 
  1290.                         ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway))
  1291.                         {
  1292.                         if (routedDebug)
  1293.                             logMsg ("ripRouteMsgProcess:cmd = %s: deleting primary"
  1294.                                     "routen", (int)(rtmMessages [cmd]),
  1295.                                     0, 0, 0, 0, 0); 
  1296.                         rtdelete (pRtEntry);
  1297.                         }
  1298.                     /* Now release the semaphore we took earlier */
  1299.                     semGive (ripLockSem);
  1300.                     break;
  1301.                     }
  1302.                 if (metric < 0)
  1303.                     metric = 1;
  1304.                 /* Take the semaphore to lock the RIP timer task out */
  1305.                 semTake (ripLockSem, WAIT_FOREVER); 
  1306.                 /* 
  1307.                  * Check if we already have an entry for the specified 
  1308.                  * destination. If we do and it is a RIP route 
  1309.                  * (RTS_OTHER not set) or if the route belongs to another
  1310.                  * protocol, but has a higher or same metric than this new
  1311.                  * route, delete the old route. We always give precedence
  1312.                  * to OTHER routes over RIP routes. In any case, we 
  1313.                  * do not allow an interface route to be replaced. Also
  1314.                  * if we have the same route and its metric is being changed
  1315.                  * we need to record that change. For simplicity, we just
  1316.                  * delete the old route and add the new one.
  1317.                  */
  1318.                 pRtEntry = rtlookup (pDstAddr);
  1319.                 if ((pRtEntry == NULL) ||
  1320.                     (!(pRtEntry->rt_state & RTS_INTERFACE) && 
  1321.                      (((pRtEntry->rt_state & RTS_OTHER) == 0) || 
  1322.                       (pRtEntry->rt_metric >= metric) || 
  1323.                       ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway)))) 
  1324.                     {
  1325.                     if (pRtEntry)
  1326.                         rtdelete (pRtEntry);
  1327.                     flags = RTS_OTHER;
  1328.                     /* Record whether this route is the primary route or not */
  1329.                     if (primaryRoute)
  1330.                         flags |= RTS_PRIMARY;
  1331.                     rtadd (pDstAddr, pGateway, metric, flags,
  1332.                            pNetmask, routeProto, 0, 0, NULL);
  1333.                     
  1334.                     if (routedDebug)
  1335.                         logMsg ("%s: Added new routen", (int)rtmMessages [cmd], 
  1336.                                 0, 0, 0, 0, 0);
  1337.                     }
  1338.                 /* Now release the semaphore we took earlier */
  1339.                 semGive (ripLockSem);
  1340.                 break; 
  1341.             case RTM_CHANGE:  /* Primary route changing */
  1342.             case RTM_NEWCHANGE:  /* Duplicate route changing */
  1343.                 if (msg.rtMsg.rtm.rtm_errno != 0) 
  1344.                     {
  1345.                     if (routedDebug)
  1346.                         logMsg ("ignore route message %s for index %d" 
  1347.                                 " error = %dn", (int)rtmMessages [cmd], 
  1348.                                 index, msg.rtMsg.rtm.rtm_errno, 0, 0, 0);
  1349.                     break;
  1350.                     } 
  1351.                 /* 
  1352.                  * Get the address of the old gateway. This information
  1353.                  * is only available for the RTM_NEWCHANGE and not for
  1354.                  * RTM_CHANGE (for compatibility reasons)
  1355.                  */
  1356.                 if (cmd == RTM_NEWCHANGE) 
  1357.                     {
  1358.                     pOldGateway = INFO_AUTHOR (&rtInfo);
  1359.                     /* 
  1360.                      * If Gateway didn't change, set old gateway to
  1361.                      * the previous gateway address, so that ripRouteSame
  1362.                      * can work properly.
  1363.                      */
  1364.                     if (pOldGateway == NULL)
  1365.                         pOldGateway = pGateway;
  1366.                     if (pOldGateway == NULL)
  1367.                         {
  1368.                         /*
  1369.                          * This is a route change for a duplicate route
  1370.                          * for which the gateway didn't change.
  1371.                          * Also, we don't have enough information
  1372.                          * to determine if we have this particular route
  1373.                          * in our cache. We need a gateway
  1374.                          * address to identify a duplicate route.
  1375.                          * Since we can't do that, simply exit.
  1376.                          */
  1377.                         if (routedDebug)
  1378.                             logMsg ("RTM_NEWCHANGE: gateway not specified. "
  1379.                                     "Doing nothing.n", 0, 0, 0, 0, 0, 0);
  1380.                         break;
  1381.                         }
  1382.                     }
  1383.                 else
  1384.                     pOldGateway = NULL;
  1385.                 if (routedDebug) 
  1386.                     {
  1387.                     logMsg ("RIP: %s receivedn", 
  1388.                             (int)rtmMessages [cmd],0,0,0,0,0);
  1389.                     ripSockaddrPrint (pDstAddr);
  1390.                     ripSockaddrPrint (pNetmask);
  1391.                     ripSockaddrPrint (pGateway);
  1392.                     logMsg ("RIP: %s received: old Gateway addrn", 
  1393.                             (int)rtmMessages [cmd],0,0,0,0,0);
  1394.                     ripSockaddrPrint (pOldGateway);
  1395.                     logMsg ("RIP: new metric %dn", 
  1396.                             msg.rtMsg.rtm.rtm_rmx.rmx_hopcount,0,0,0,0,0);
  1397.                     }
  1398.                 /* 
  1399.                  * If the route was installed by us or was an interface
  1400.                  * route, ignore it. Nobody should be changing this route.
  1401.                  */
  1402.                 routeProto = RT_PROTO_GET (pDstAddr);
  1403.                 if (routeProto == M2_ipRouteProto_rip ||
  1404.                     routeProto == M2_ipRouteProto_local)
  1405.                     break;
  1406.                 /*
  1407.                  * The destination sockaddr structure has the 
  1408.                  * protocol value set. Make it zero since 
  1409.                  * we compare the entire sockaddr structure at other
  1410.                  * places (input.c for example) that expect the
  1411.                  * standard fields to be zero.
  1412.                  * We set the gateway sockaddr fields to be zero
  1413.                  * too (just being paranoid, in case they aren't already zero)
  1414.                  * as rtlookup() expects it to be zero. Do the same
  1415.                  * for the TOS value too.
  1416.                  * We store the proto value anyway in the rtentry
  1417.                  * structure.
  1418.                  */
  1419.                 if (pGateway)
  1420.                     {
  1421.                     RT_PROTO_SET (pGateway, 0);
  1422.                     TOS_SET (pGateway, 0);
  1423.                     }
  1424.                 RT_PROTO_SET (pDstAddr, 0);
  1425.                 TOS_SET (pDstAddr, 0);
  1426.                 /* Take the semaphore to lock the RIP timer task out */
  1427.                 semTake (ripLockSem, WAIT_FOREVER); 
  1428.                 /* 
  1429.                  * Check if we have this route in our table. 
  1430.                  * If we have it, 
  1431.                  *   make sure it is the exact
  1432.                  *   same route:
  1433.                  *     same dst, gateway and netmask values
  1434.                  *     same routing protocol
  1435.                  *
  1436.                  *   If we know about this route, record the gateway change,
  1437.                  *   if any. If the hop count field was modified, then
  1438.                  *   that indicates that the RIP metric was stored in that
  1439.                  *   field; so we copy the metric from that field,
  1440.                  *   else we call the user hook for a new metric.
  1441.                  *   If they return a metric >= HOPCNT_INFINITY we delete the
  1442.                  *   route. else we update the metric.
  1443.                  *   Note that pOldGateway would be NULL if the primary route
  1444.                  *   is being changed. We account for that in the 
  1445.                  *   ripRouteSame routine by checking if the route we have
  1446.                  *   is the primary route
  1447.                  *
  1448.                  * If we don't have the route in our table, call the user
  1449.                  * hook to decide if they want us to propagate this route.
  1450.                  */
  1451.                 pRtEntry = rtlookup (pDstAddr);
  1452.                 if (pRtEntry && 
  1453.                     ((pRtEntry->rt_state & RTS_OTHER) != 0) && 
  1454.                     (pRtEntry->rt_proto == routeProto) &&
  1455.                     ripRouteSame (pRtEntry, pDstAddr, pNetmask, pOldGateway))
  1456.                     {
  1457.                     /* If the gateway has changed, record the change */
  1458.                     if (pGateway && !equal (&pRtEntry->rt_router, pGateway))
  1459.                         {
  1460.                         /* Now record the new gateway and its interface */
  1461.                         pRtEntry->rt_router = *pGateway; 
  1462.                         pRtEntry->rt_ifp = 
  1463.                             ripIfWithDstAddr (&pRtEntry->rt_router, NULL);
  1464.                         if (pRtEntry->rt_ifp == 0) 
  1465.                             pRtEntry->rt_ifp = 
  1466.                                 ripIfWithNet (&pRtEntry->rt_router);
  1467.                         pRtEntry->rt_state |= RTS_CHANGED;
  1468.                         if (routedDebug)
  1469.                             logMsg ("%s: Changed gatewayn", 
  1470.                                     (int)rtmMessages [cmd], 0, 0, 0, 0, 0);
  1471.                         }
  1472.                     /* If the metric changed, record it. */
  1473.                     if ((msg.rtMsg.rtm.rtm_inits & RTV_HOPCOUNT) != 0) 
  1474.                         {
  1475.                         pRtEntry->rt_metric = 
  1476.                             msg.rtMsg.rtm.rtm_rmx.rmx_hopcount;
  1477.                         pRtEntry->rt_state |= RTS_CHANGED;
  1478.                         if (pRtEntry->rt_metric >= HOPCNT_INFINITY)
  1479.                             {
  1480.                             /* The user wants the route deleted. Do so */
  1481.                             rtdelete (pRtEntry);
  1482.                             }
  1483.                         }
  1484.                     else if (ripState.pRouteHook != NULL)
  1485.                         {
  1486.                         /* Allow the use to specify a new metric */
  1487.                         metric = (ripState.pRouteHook) 
  1488.                             (&msg.rtMsg, routeProto, (cmd == RTM_CHANGE), 
  1489.                              RIP_ROUTE_CHANGE_RECD);
  1490.                         /* If the user wants the route to be deleted, do so */
  1491.                         if (metric >= HOPCNT_INFINITY)
  1492.                             {
  1493.                             pRtEntry->rt_state |= RTS_CHANGED;
  1494.                             rtdelete (pRtEntry);
  1495.                             }
  1496.                         else if (metric > 0)
  1497.                             {
  1498.                             /* Record the metric change */
  1499.                             pRtEntry->rt_metric = metric;
  1500.                             pRtEntry->rt_state |= RTS_CHANGED;
  1501.                             }
  1502.                         }
  1503.                     }
  1504.                 else
  1505.                     {
  1506.                     /* 
  1507.                      * This might be a route that was duplicate, but
  1508.                      * because it's weight changed for the better, it became
  1509.                      * primary. Or it just might be a route that we ere told to
  1510.                      * ignore earlier on, but since things have changed,
  1511.                      * Allow the user to decide if he wants this
  1512.                      * route to be propagated. 
  1513.                      */
  1514.                     if (routedDebug)
  1515.                         logMsg ("%s: Trying to add new routen", 
  1516.                                 (int)rtmMessages [cmd], 0, 0, 0, 0, 0);
  1517.                     semGive (ripLockSem);
  1518.                     primaryRoute = (cmd == RTM_CHANGE) ? TRUE : FALSE;
  1519.                     goto addIt;
  1520.                     }
  1521.                 semGive (ripLockSem);
  1522.                 break;
  1523.             case RTM_OLDIPROUTE:
  1524.                 if (routedDebug) 
  1525.                     {
  1526.                     logMsg ("RIP: %s received for index %dn", 
  1527.                             (int)rtmMessages [cmd], index, 0, 0, 0, 0);
  1528.                     ripSockaddrPrint (pDstAddr);
  1529.                     ripSockaddrPrint (pNetmask);
  1530.                     ripSockaddrPrint (pGateway);
  1531.                     }
  1532.                 /* 
  1533.                  * If the route was installed by us or is an interface
  1534.                  * route, ignore it. We don't care about these routes.
  1535.                  */
  1536.                 routeProto = RT_PROTO_GET (pDstAddr);
  1537.                 if (routeProto == M2_ipRouteProto_rip ||
  1538.                     routeProto == M2_ipRouteProto_local)
  1539.                     break;
  1540.                 /*
  1541.                  * The destination sockaddr structure has the 
  1542.                  * protocol value set. Make it zero since 
  1543.                  * we compare the entire sockaddr structure at other
  1544.                  * places (input.c for example) that expect the
  1545.                  * standard fields to be zero.
  1546.                  * We set the gateway sockaddr fields to be zero
  1547.                  * too (just being paranoid, in case they aren't already zero)
  1548.                  * as rtlookup() expects it to be zero. Do the same
  1549.                  * for the TOS value too.
  1550.                  * We store the proto value anyway in the rtentry
  1551.                  * structure.
  1552.                  */
  1553.                 RT_PROTO_SET (pGateway, 0);
  1554.                 TOS_SET (pGateway, 0);
  1555.                 RT_PROTO_SET (pDstAddr, 0);
  1556.                 TOS_SET (pDstAddr, 0);
  1557.                 /*
  1558.                  * If the current primary route is being demoted
  1559.                  * we should mark our primary route, if any, as non-primary
  1560.                  */
  1561.                 /* Take the semaphore to lock the RIP timer task out */
  1562.                 semTake (ripLockSem, WAIT_FOREVER); 
  1563.                 pRtEntry = rtlookup (pDstAddr);
  1564.                 if (pRtEntry != NULL && 
  1565.                     ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway))
  1566.                     {
  1567.                     if (routedDebug)
  1568.                         logMsg ("RTM_OLDIPROUTE: demoting primary routen", 
  1569.                                 0, 0, 0, 0, 0, 0);
  1570.                     pRtEntry->rt_state &= ~RTS_PRIMARY;
  1571.                     }
  1572.                 /* Now release the semaphore we took earlier */
  1573.                 semGive (ripLockSem);
  1574.                 break;
  1575.             case RTM_REDIRECT:
  1576.                 /* Get the address of the old gateway */
  1577.                 pOldGateway = INFO_AUTHOR (&rtInfo);
  1578.                 if (msg.rtMsg.rtm.rtm_errno != 0) 
  1579.                     {
  1580.                     if (routedDebug)
  1581.                         logMsg ("ignore route message RTM_REDIRECT for index %d" 
  1582.                                 " error = %dn", 
  1583.                                 index, msg.rtMsg.rtm.rtm_errno, 0, 0, 0, 0);
  1584.                     break;
  1585.                     } 
  1586.                 if (routedDebug) 
  1587.                     {
  1588.                     logMsg ("RIP: route redirect received for index %dn", 
  1589.                             index, 0, 0, 0, 0, 0);
  1590.                     ripSockaddrPrint (pDstAddr);
  1591.                     ripSockaddrPrint (pNetmask);
  1592.                     ripSockaddrPrint (pGateway);
  1593.                     logMsg ("RIP: route redirect old gatewayn", 0,0,0,0,0,0);
  1594.                     ripSockaddrPrint (pOldGateway);
  1595.                     }
  1596.                 routeProto = RT_PROTO_GET (pDstAddr);
  1597.                 /*
  1598.                  * The destination sockaddr structure has the 
  1599.                  * protocol value set. Make it zero as the user may not expect
  1600.                  * to see it. Do the same with the gateway address
  1601.                  * even though it might already be zero. it doesn't hurt
  1602.                  * being paranoid.
  1603.                  */
  1604.                 RT_PROTO_SET (pGateway, 0);
  1605.                 TOS_SET (pGateway, 0);
  1606.                 RT_PROTO_SET (pDstAddr, 0);
  1607.                 TOS_SET (pDstAddr, 0);
  1608.                 /* If the routeHook is installed call it */
  1609.                 if (ripState.pRouteHook != NULL)
  1610.                     {
  1611.                     (ripState.pRouteHook)(&msg.rtMsg, routeProto, FALSE,
  1612.                                           RIP_REDIRECT_RECD);
  1613.                     }
  1614.                 break; 
  1615.             case RTM_DELETE:
  1616.             case RTM_DELEXTRA:
  1617.                 if (msg.rtMsg.rtm.rtm_errno != 0 && 
  1618.                     msg.rtMsg.rtm.rtm_errno != ESRCH) 
  1619.                     {
  1620.                     if (routedDebug)
  1621.                         logMsg ("ignore route message %s for ifindex"
  1622.                                 " %d error = %dn", (int)rtmMessages [cmd],
  1623.                                 index, msg.rtMsg.rtm.rtm_errno, 0, 0, 0);
  1624.                     break;
  1625.                     } 
  1626.                 if (routedDebug) 
  1627.                     {
  1628.                     logMsg ("route message %s for ifindex %dn", 
  1629.                             (int)rtmMessages [cmd], index, 0, 0, 0, 0);
  1630.                     ripSockaddrPrint (pDstAddr);
  1631.                     ripSockaddrPrint (pNetmask);
  1632.                     ripSockaddrPrint (pGateway);
  1633.                     } 
  1634.                 /* 
  1635.                  * If the route was installed by us or is an interface
  1636.                  * route, ignore it. We already know about it
  1637.                  */
  1638.                 routeProto = RT_PROTO_GET (pDstAddr);
  1639.                 if (routeProto == M2_ipRouteProto_rip ||
  1640.                     routeProto == M2_ipRouteProto_local)
  1641.                     break;
  1642.                 /*
  1643.                  * The destination sockaddr structure has the 
  1644.                  * protocol value set. Make it zero since 
  1645.                  * we compare the entire sockaddr structure at other
  1646.                  * places (input.c for example) that expect the
  1647.                  * standard fields to be zero.
  1648.                  * We set the gateway sockaddr fields to be zero
  1649.                  * too (just being paranoid, in case they aren't already zero)
  1650.                  * as rtlookup() expects it to be zero. Do the same
  1651.                  * for the TOS value too.
  1652.                  * We store the proto value anyway in the rtentry
  1653.                  * structure.
  1654.                  */
  1655.                 RT_PROTO_SET (pGateway, 0);
  1656.                 TOS_SET (pGateway, 0);
  1657.                 RT_PROTO_SET (pDstAddr, 0);
  1658.                 TOS_SET (pDstAddr, 0);
  1659.                 /* Take the semaphore to lock the RIP timer task out */
  1660.                 semTake (ripLockSem, WAIT_FOREVER); 
  1661.                 /* 
  1662.                  * Check if we have this route in our table. 
  1663.                  * If we do, delete it. Make sure it is the exact
  1664.                  * same route:
  1665.                  *   same dst, gateway and netmask values
  1666.                  *   same routing protocol
  1667.                  */
  1668.                 pRtEntry = rtlookup (pDstAddr);
  1669.                 if (pRtEntry && 
  1670.                     ((pRtEntry->rt_state & RTS_OTHER) != 0) &&
  1671.                     pRtEntry->rt_proto == routeProto &&
  1672.                     ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway))
  1673.                     {
  1674.                     if (routedDebug)
  1675.                         logMsg ("%s: deleted routen", (int)rtmMessages [cmd], 
  1676.                                 0, 0, 0, 0, 0);
  1677.                     rtdelete (pRtEntry);
  1678.                     }
  1679.                 /* Now release the semaphore we took earlier */
  1680.                 semGive (ripLockSem);
  1681.                 break; 
  1682.             case RTM_IFINFO:
  1683.                 /* Take the semaphore to lock the RIP timer task out */
  1684.                 semTake (ripLockSem, WAIT_FOREVER); 
  1685.                 if ((msg.ifMsg.ifm_flags & IFF_UP) == IFF_UP)
  1686.                     {
  1687.                     /* 
  1688.                      * Now change the interface flag to UP for all interfaces
  1689.                      * that match the given name. If this is a new interface
  1690.                      * the routine below does nothing. The routine below also
  1691.                      * adds the interface route for all logical interfaces.
  1692.                      */ 
  1693.                     if (routedDebug) 
  1694.                         logMsg ("setting up interface for %dn", 
  1695.                                 index, 0, 0, 0, 0, 0);
  1696.                     ripInterfaceUpFlagSet (index, TRUE);
  1697.                     /* 
  1698.                      * Either this might be a new interface, or a new address
  1699.                      * might have been added to the interface while it was down
  1700.                      * in which case the routedIfInit call would have simply
  1701.                      * returned without getting the new address.
  1702.                      * Call routedIfInit now to get any new addresses.
  1703.                      * It is perfectly safe to call routedIfInit() 
  1704.                      * even if nothing
  1705.                      * has changed since routedIfInit() doesn't do anything
  1706.                      * in that case
  1707.                      */
  1708.                     if (routedDebug)
  1709.                         logMsg ("Calling routedIfInit for index %d.n", 
  1710.                                 index, 0, 0, 0, 0, 0);
  1711.                     routedIfInit (FALSE, index); 
  1712.                     }
  1713.                 else
  1714.                     {
  1715.                     /* 
  1716.                      * Now change the interface flag to DOWN for all interfaces
  1717.                      * that match the given name. The routine below will also
  1718.                      * delete all routes that pass through the interface
  1719.                      * except the routes learnt through the Routing system
  1720.                      * callback.
  1721.                      */ 
  1722.                     if (routedDebug)
  1723.                         logMsg ("setting down interface for %dn", 
  1724.                                 index, 0, 0, 0, 0, 0); 
  1725.                     ripInterfaceUpFlagSet (index, FALSE);
  1726.                     }
  1727.                 /* Now release the semaphore we took earlier */
  1728.                 semGive (ripLockSem);
  1729.                 break; 
  1730.             case RTM_NEWADDR:
  1731.                 /* Take the semaphore to lock the RIP task out */
  1732.                 semTake (ripLockSem, WAIT_FOREVER); 
  1733.                 /* 
  1734.                  * A new address has been added to the interface.
  1735.                  * Call routedifInit() to pick it up. If the interface
  1736.                  * is down, routedIfInit() will simply return, but when
  1737.                  * the interface comes back up, the new address will be
  1738.                  * picked up.
  1739.                  */
  1740.                 if (routedDebug)
  1741.                     {
  1742.                     logMsg ("RTM_NEWADDR: added interface addressn",
  1743.                             0, 0, 0, 0, 0, 0);
  1744.                     ripSockaddrPrint (INFO_IFA (&rtInfo)); 
  1745.                     logMsg ("Calling routedIfInit for index %d.n", 
  1746.                             index, 0, 0, 0, 0, 0);
  1747.                     }
  1748.                 routedIfInit (FALSE, index); 
  1749.                 /* Now release the semaphore we took earlier */
  1750.                 semGive (ripLockSem);
  1751.                 break; 
  1752.             case RTM_DELADDR:
  1753.                 /* Take the semaphore to lock the RIP task out */
  1754.                 semTake (ripLockSem, WAIT_FOREVER); 
  1755.                 /* 
  1756.                  * Now delete all routes that pass though the interface
  1757.                  * corresponding to the address being deleted.
  1758.                  * Note that we create a separate interface for each
  1759.                  * alias. So even if the system has one interface with
  1760.                  * two address, we treat them as two logical interfaces.
  1761.                  * After the routes have been deleted, delete the
  1762.                  * interface structure from our list.
  1763.                  */
  1764.                 if (routedDebug)
  1765.                     {
  1766.                     logMsg ("RTM_DELADDR: deleted interface addressn",
  1767.                             0, 0, 0, 0, 0, 0);
  1768.                     ripSockaddrPrint (INFO_IFA (&rtInfo)); 
  1769.                     }
  1770.                 if ((pIf = ripIfWithAddrAndIndex (INFO_IFA (&rtInfo), index))
  1771.                     != NULL)
  1772.                     {
  1773.                     /*
  1774.                      * Mark the interface down so that ifRouteAdd() will not
  1775.                      * select this interface. This status change is harmless
  1776.                      * as we are about to delete the interface structure.
  1777.                      */
  1778.                     pIf->int_flags &=  ~IFF_UP;
  1779.                     ripRoutesDelete (pIf, TRUE);
  1780.                     ripInterfaceDelete (pIf);
  1781.                     }
  1782.                 /* Now release the semaphore we took earlier */
  1783.                 semGive (ripLockSem);
  1784.                 break; 
  1785.             default:
  1786.                 if (routedDebug)
  1787.                     logMsg ("route unknown message %d for ifindex %dn", 
  1788.                             cmd, index, 0, 0, 0, 0);
  1789.                 break;
  1790.             } /* End switch (cmd) */
  1791. } /* End FOREVER */
  1792.     }
  1793. #endif /* ROUTER_STACK */
  1794. int getsocket (domain, type, sin)
  1795. int domain, type;
  1796. struct sockaddr_in *sin;
  1797. {
  1798. int sock, on = 1;
  1799. if ((sock = socket (domain, type, 0)) < 0) {
  1800.                 if (routedDebug)
  1801.     logMsg ("Error creating socket.n", 0, 0, 0, 0, 0, 0);
  1802. return (-1);
  1803. }
  1804. #ifdef SO_BROADCAST
  1805. if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, 
  1806.                         sizeof (on)) < 0) {
  1807.                 if (routedDebug)
  1808.     logMsg ("error setting SO_BROADCAST option", 
  1809.                             0, 0, 0, 0, 0, 0);
  1810. close (sock);
  1811. return (-1);
  1812. }
  1813. #endif
  1814. #ifdef SO_RCVBUF
  1815. for (on = BUFSPACE; ; on -= 1024) {
  1816. if (setsockopt (sock, SOL_SOCKET, SO_RCVBUF, 
  1817.                                 (char *)&on, sizeof (on)) == 0)
  1818. break;
  1819. if (on <= 8*1024) {
  1820.                         if (routedDebug)
  1821.     logMsg ("unable to set SO_RCVBUF option", 
  1822.                                      0, 0, 0, 0, 0, 0);
  1823. break;
  1824. }
  1825. }
  1826. if (routedDebug)
  1827. logMsg ("Receive buffer size %d.n", on, 0, 0, 0, 0, 0);
  1828. #endif
  1829. if (bind (sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
  1830.                 if (routedDebug)
  1831.     logMsg ("error binding socket.n", 0, 0, 0, 0, 0, 0);
  1832. close (sock);
  1833. return (-1);
  1834. }
  1835.         on = 1;
  1836. if (ioctl (sock, FIONBIO, (int) &on) == -1)
  1837.                 if (routedDebug)
  1838.     logMsg ("error setting O_NONBLOCK option.n", 
  1839.                             0, 0, 0, 0, 0, 0);
  1840. return (sock);
  1841. }
  1842. /******************************************************************************
  1843. *
  1844. * ripTimerArm - arm the timeout to do routing updates
  1845. *
  1846. * This routine starts (or resets) the watchdog timer to trigger periodic
  1847. * updates at the assigned interval.
  1848. *
  1849. * RETURNS: N/A
  1850. *
  1851. * NOMANUAL        
  1852. */
  1853. void ripTimerArm
  1854.     (
  1855.     long timeout  /* update interval in seconds */
  1856.     )
  1857.     {
  1858.     int ticks;
  1859.     ticks = timeout * sysClkRateGet ();
  1860. #ifdef _WRS_VXWORKS_5_X
  1861.     wdStart (ripState.timerDog, ticks, semGive, (int)ripState.timerSem);
  1862. #else
  1863.     /*
  1864.      * VxWorks AE applications outside the kernel domain are not
  1865.      * permitted to access the semGive() function directly. 
  1866.      */      
  1867.     wdSemStart (ripState.timerDog, ticks, ripState.timerSem);
  1868. #endif /* _WRS_VXWORKS_5_X */
  1869.     }
  1870. /******************************************************************************
  1871. *
  1872. * ripSplitPacket - split up a rip packet for version 2
  1873. *
  1874. * INTERNAL 
  1875. *
  1876. * The <orig> parameter accesses a single route entry within the payload
  1877. * of a RIP message. In order for the rtadd() routine to store the data in
  1878. * the expected format, the sin_port and sin_zero fields of the overlayed
  1879. * structure (which correspond to the route tag, subnet mask, and next hop
  1880. * values) must be cleared after that data is extracted.
  1881. *
  1882. * NOMANUAL
  1883. */
  1884. void ripSplitPacket
  1885.     (
  1886.     struct interface* pIfp,
  1887.     struct sockaddr_in *src,  /* Address of router which sent update. */
  1888.     struct sockaddr* orig,
  1889.     struct sockaddr* gateway,
  1890.     struct sockaddr* netmask,
  1891.     int* pTag
  1892.     )
  1893.     {
  1894.     BOOL noGate = FALSE;
  1895.     BOOL noMask = FALSE;
  1896.     char zero[4];
  1897.     long tmpNetmask;
  1898.     bzero ( (char *)&zero, 4);
  1899.     /* Check to see if the packet has the proper info. */
  1900.     if (bcmp ((orig->sa_data + RIP2_MASK_OFFSET), (char *)&zero, 4) == 0)
  1901.         noMask = TRUE;
  1902.     if (bcmp ((orig->sa_data + RIP2_GATE_OFFSET), (char *)&zero, 4) == 0)
  1903.         noGate = TRUE;
  1904.     
  1905.     /* 
  1906.      * Clear the provided storage for packet data. The rtadd routine used
  1907.      * later requires zero values for all unused fields for correct 
  1908.      * operation of the protocol. Later queries will fail if this condition 
  1909.      * is not met. 
  1910.      */
  1911.     bzero ( (char *)gateway, sizeof (*gateway));
  1912.     bzero ( (char *)netmask, sizeof (*netmask));
  1913.     
  1914.     /* Duplicate the shared parameters from the current route entry. */
  1915.     gateway->sa_family = orig->sa_family;
  1916.     gateway->sa_len = orig->sa_len;
  1917.     
  1918.     netmask->sa_family = orig->sa_family;
  1919.     netmask->sa_len = orig->sa_len;
  1920.     /* Extract the data from the original packet. */
  1921.     if (noGate)
  1922.         {
  1923.         /* 
  1924.          * RFC 1723, Section 3.4: If a value of 0.0.0.0 is given in the next
  1925.          * hop field, use the originator of the RIP advertisement as the 
  1926.          * gateway.
  1927.          */
  1928.         bcopy ( (char *)&(src->sin_addr.s_addr), 
  1929.                (char *)gateway->sa_data + 2, 4);
  1930.         }
  1931.     else
  1932.         bcopy ( (char *)(orig->sa_data + RIP2_GATE_OFFSET), 
  1933.                (char *)gateway->sa_data + 2, 4);
  1934.     if (noMask)
  1935.         {
  1936.         bcopy ( (char *)&pIfp->int_subnetmask, 
  1937.                (char *)&tmpNetmask, 4);
  1938.         tmpNetmask = htonl (tmpNetmask);
  1939.         bcopy ( (char *)&tmpNetmask,
  1940.                (char *)netmask->sa_data + 2, 4);
  1941.         }
  1942.     else
  1943.         bcopy ( (char *)(orig->sa_data + RIP2_MASK_OFFSET), 
  1944.                (char *)netmask->sa_data + 2, 4);
  1945.     /* 
  1946.      * Clear the fields in the original data now that the values have been
  1947.      * copied. This step converts that structure into a format suitable
  1948.      * for use with the rtadd() function.
  1949.      */
  1950.     /* Erase the route tag (sin_port field). */
  1951.     *pTag = (int)(*((unsigned short *)(orig->sa_data)));
  1952.     bzero ( (char *)orig->sa_data, 2); 
  1953.     /* Erase the adjacent subnet mask and next hop values (sin_zero field). */
  1954.     bzero ( (char *)(orig->sa_data + RIP2_MASK_OFFSET), 8);
  1955.     return;
  1956.     }
  1957. /******************************************************************************
  1958. *
  1959. * ripRouteToAddrs - convert a route entry into separate sockaddr_in structures
  1960. *
  1961. * This routine takes a pointer to an rt_entry and parses it out into
  1962. * three sockaddr_in structures.  pDsin contains the destination, pGsin contains
  1963. * the gateway and pNsin contains the subnetmask.
  1964. *
  1965. * RETURNS: N/A
  1966. *
  1967. * NOMANUAL
  1968. */
  1969. void ripRouteToAddrs
  1970.     (
  1971.     struct rt_entry* pRoute,    /* Route to convert. */
  1972.     struct sockaddr_in** ppDsin,  /* Destination sin. */
  1973.     struct sockaddr_in** ppGsin,  /* Gateway sin. */
  1974.     struct sockaddr_in** ppNsin  /* Netmask sin. */
  1975.     )
  1976.     {
  1977.     if (ppDsin != NULL)
  1978.         *ppDsin = (struct sockaddr_in *) &(pRoute->rt_dst);
  1979.     if (ppGsin != NULL)
  1980.         *ppGsin = (struct sockaddr_in *) &(pRoute->rt_router);
  1981.     if (ppNsin != NULL)
  1982.         *ppNsin = (struct sockaddr_in *) &(pRoute->rt_netmask);
  1983.     }
  1984. /******************************************************************************
  1985. *
  1986. * ripBuildPacket - this routine builds a packet from the route passed
  1987. *
  1988. * This routine takes the routing entry that we are passed and properly
  1989. * fills the fields in the packet. If RIP version 1 packets are requested,
  1990. * then the sections that must be zero are left alone, otherwise they are 
  1991. * properly filled. The version parameter uses the values for the MIB variable
  1992. * stored in ripState.ripConf.rip2IfConfSend instead of the actual version
  1993. * number. This routine is never called if that value is set to disable
  1994. * transmission.
  1995. *
  1996. * RETURNS: N/A
  1997. *
  1998. * NOMANUAL
  1999. */
  2000. void ripBuildPacket
  2001.     (
  2002.     RIP2PKT *pPacket,
  2003.     struct rt_entry* rt,
  2004.     struct interface *  pIf,
  2005.     int version
  2006.     )
  2007.     {
  2008.     UINT32  routenet = 0;  /* Network number of route gateway */
  2009.     UINT32  destnet = 0;  /* Network number of route destination */
  2010.     struct sockaddr_in* dSin;
  2011.     struct sockaddr_in* gSin;
  2012.     struct sockaddr_in* nSin;
  2013.     if (version == M2_rip2IfConfSend_ripVersion1)
  2014.         {
  2015.         pPacket->tag = 0;
  2016.         ripRouteToAddrs (rt, &dSin, &gSin, &nSin);
  2017.         pPacket->dest = dSin->sin_addr.s_addr;
  2018.         pPacket->subnet = 0;
  2019.         pPacket->gateway = 0;
  2020.         pPacket->metric = htonl (rt->rt_metric);
  2021.         }
  2022.     else
  2023.         {
  2024.         /* 
  2025.          * Building version 2 packets requires special processing to 
  2026.          * support both RIP-1 and RIP-2 routers in all situations.
  2027.          */
  2028.         pPacket->tag = rt->rt_tag;
  2029.         ripRouteToAddrs (rt, &dSin, &gSin, &nSin);
  2030.         if (nSin->sin_addr.s_addr)
  2031.             {
  2032.             /* 
  2033.              * Don't apply the route's netmask if it is shorter than the 
  2034.              * mask of the outgoing interface. The interface's mask is used
  2035.              * for those destinations so that an unreachable gateway is not 
  2036.              * sent. The shorter mask could conceal the network mismatch,
  2037.              * (e.g. - 147.11.151.47/23 and 147.11.150.48/24 would match
  2038.              * in that case).
  2039.              */
  2040.             if ( (nSin->sin_addr.s_addr & htonl (pIf->int_subnetmask)) ==
  2041.                     pIf->int_subnetmask)
  2042.                 routenet = gSin->sin_addr.s_addr & nSin->sin_addr.s_addr;
  2043.             else
  2044.                 routenet = gSin->sin_addr.s_addr & pIf->int_subnetmask;
  2045.             }
  2046.         else
  2047.             routenet = gSin->sin_addr.s_addr & pIf->int_subnetmask;
  2048.         destnet = (*(UINT32 *)(&pIf->int_addr.sa_data[0] + 2) &
  2049.                                       pIf->int_subnetmask);
  2050.         /* No special processing is required for the advertised destination. */
  2051.         pPacket->dest = dSin->sin_addr.s_addr;
  2052.         /*
  2053.          * Internally generated entries that substitute for supernets
  2054.          * still contain the classless netmask so that the border gateway 
  2055.          * filtering can select the correct entry for both directly connected 
  2056.          * and "distant" destinations. That value must be replaced with
  2057.          * the "natural" (class-based) network mask before the update is
  2058.          * sent so that the route will be understood by RIP-2 routers. If 
  2059.          * border gateway filtering was disabled, none of the internally 
  2060.          * generated entries will be included in any update, so this
  2061.          * substitution is (correctly) ignored.
  2062.          */
  2063.         if ( (rt->rt_state & (RTS_INTERNAL | RTS_SUBNET)) == 
  2064.                 (RTS_INTERNAL | RTS_SUBNET))
  2065.             {
  2066.             /*
  2067.              * For internal routes, the route entry's netmask is equal to 
  2068.              * rt->rt_ifp->int_netmask unless it is a substitute for a
  2069.              * supernet.
  2070.              */
  2071.             if (ntohl (nSin->sin_addr.s_addr) != rt->rt_ifp->int_netmask)
  2072.                 {
  2073.                 /* 
  2074.                  * Substitute the class-based value for the 
  2075.                  * supernet mask in the outgoing message.
  2076.                  */
  2077.                 pPacket->subnet = htonl (rt->rt_ifp->int_netmask);
  2078.                 }
  2079.             else
  2080.                 {
  2081.                 /* 
  2082.                  * For subnet replacements, use the existing 
  2083.                  * (class-based) value.
  2084.                  */
  2085.                 pPacket->subnet = nSin->sin_addr.s_addr;
  2086.                 }
  2087.             }
  2088.         else
  2089.             {
  2090.             /* 
  2091.              * Common case: use mask from actual route entry. This
  2092.              * case includes the internally generated default route
  2093.              * created when the gateway flag is set during initialization.
  2094.              */
  2095.             pPacket->subnet = nSin->sin_addr.s_addr;
  2096.             }
  2097.         /* 
  2098.          * For RIPv2 packets, the network number of the published gateway 
  2099.          * must match the network number of the outgoing interface. Unless
  2100.          * the host contains multiple interfaces with the same network
  2101.          * number, the value stored in the RIP routing table generally
  2102.          * contains an address on a different network. In that case,
  2103.          * use the interface IP address to include a reachable gateway in 
  2104.          * the route update.
  2105.          */
  2106.         if (routenet != destnet)
  2107.             pPacket->gateway = *(UINT32 *)(&pIf->int_addr.sa_data[0] + 2);
  2108.         else
  2109.             pPacket->gateway = gSin->sin_addr.s_addr;
  2110.         /* 
  2111.          * Unlike the gateway and netmask, the specified metric
  2112.          * can always be copied directly. 
  2113.          */
  2114.         pPacket->metric = htonl (rt->rt_metric);
  2115.         }
  2116.     }
  2117. /******************************************************************************
  2118. *
  2119. * ripRouteShow - display the internal routing table maintained by RIP
  2120. *
  2121. * This routine prints every entry in the local RIP routing table. The
  2122. * flags displayed below the destination, gateway, and netmask addresses
  2123. * indicate the current route status. Entries with the RTS_INTERFACE flag
  2124. * indicate locally generated routes to directly connected networks. 
  2125. * If RTS_SUBNET is set for an entry, it is subject to border
  2126. * gateway filtering (if enabled). When RTS_INTERNAL is also present, the 
  2127. * corresponding entry is an "artificial" route created to supply distant
  2128. * networks with legitimate destinations if border filtering excludes the
  2129. * actual entry. Those entries are not copied to the kernel routing table.
  2130. * The RTS_CHANGED flag marks entries added or modified in the last timer 
  2131. * interval that will be included in a triggered update. The RTS_OTHER 
  2132. * flag is set for routes learnt from other sources. The RTS_PRIMARY
  2133. * flag (set only if the RTS_OTHER flag is also set) indicates that the route
  2134. * is a primary route, visible to the IP forwarding process. The DOWN flag
  2135. * indicates that the interface through which the gateway is reachable is
  2136. * down.
  2137. */
  2138. void ripRouteShow ()
  2139.     {
  2140.     int doinghost = 1;
  2141.     register struct rthash *rh;
  2142.     register struct rt_entry *rt;
  2143.     struct rthash *base = hosthash;
  2144.     struct sockaddr_in* dSin;
  2145.     struct sockaddr_in* gSin;
  2146.     struct sockaddr_in* nSin;
  2147.     char address[32];
  2148.     if (!ripInitFlag)
  2149.         return;
  2150.     /* Block all processing to guarantee a stable list of routes. */
  2151.     semTake (ripLockSem, WAIT_FOREVER);
  2152.  
  2153.     printf ("Destination      Gateway          Netmask          Metric Proto Timer "
  2154.             "Tag n");
  2155.     again:
  2156.     for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
  2157.         {
  2158.         rt = rh->rt_forw;
  2159.         for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
  2160.             {
  2161.             ripRouteToAddrs (rt, &dSin, &gSin, &nSin);
  2162.             inet_ntoa_b (dSin->sin_addr, (char *)&address);
  2163.             printf ("%-17s", address);
  2164.             inet_ntoa_b (gSin->sin_addr, (char *)&address);
  2165.             printf ("%-17s", address);
  2166.             inet_ntoa_b (nSin->sin_addr, (char *)&address);
  2167.             printf ("%-17s", address);
  2168.             printf (" %-6d", rt->rt_metric);
  2169.             printf (" %-5d", rt->rt_proto);
  2170.             printf (" %-5d", rt->rt_timer);
  2171.             printf ("%-6xn", (unsigned short)ntohs((unsigned short)(rt->rt_tag)));
  2172.             /* Now figure out all the state. */
  2173.             if (rt->rt_state & RTS_CHANGED)
  2174.                 printf ("RTS_CHANGED ");
  2175.             if (rt->rt_state & RTS_EXTERNAL)
  2176.                 printf ("RTS_EXTERNAL ");
  2177.             if (rt->rt_state & RTS_INTERNAL)
  2178.                 printf ("RTS_INTERNAL ");
  2179.             if (rt->rt_state & RTS_PASSIVE)
  2180.                 printf ("RTS_PASSIVE ");
  2181.             if (rt->rt_state & RTS_INTERFACE)
  2182.                 printf ("RTS_INTERFACE ");
  2183.             if (rt->rt_state & RTS_REMOTE)
  2184.                 printf ("RTS_REMOTE ");
  2185.             if (rt->rt_state & RTS_SUBNET)
  2186.                 printf ("RTS_SUBNET ");
  2187.             if (rt->rt_state & RTS_OTHER)
  2188.                 {
  2189.                 printf ("RTS_OTHER ");
  2190.                 if (rt->rt_state & RTS_PRIMARY)
  2191.                     printf ("RTS_PRIMARY ");
  2192.                 }
  2193.             if (rt->rt_ifp && (rt->rt_ifp->int_flags & IFF_UP) == 0)
  2194.                 printf ("DOWN ");
  2195.             printf ("n");
  2196.             }
  2197.         }
  2198.     if (doinghost)
  2199.         {
  2200.         doinghost = 0;
  2201.         base = nethash;
  2202.         goto again;
  2203.         }
  2204.     semGive (ripLockSem);
  2205.     return;
  2206.     }
  2207. /******************************************************************************
  2208. *
  2209. * ripDbgRouteShow - display debug info about RIP's internal route table
  2210. *
  2211. * This routine prints every entry in the local RIP routing table. The
  2212. * flags displayed below the destination, gateway, and netmask addresses
  2213. * indicate the current route status. Entries with the RTS_INTERFACE flag
  2214. * indicate locally generated routes to directly connected networks. 
  2215. * If RTS_SUBNET is set for an entry, it is subject to border
  2216. * gateway filtering (if enabled). When RTS_INTERNAL is also present, the 
  2217. * corresponding entry is an "artificial" route created to supply distant
  2218. * networks with legitimate destinations if border filtering excludes the
  2219. * actual entry. Those entries are not copied to the kernel routing table.
  2220. * The RTS_CHANGED flag marks entries added or modified in the last timer 
  2221. * interval that will be included in a triggered update. The RTS_OTHER 
  2222. * flag is set for routes learnt from other sources. The RTS_PRIMARY
  2223. * flag (set only if the RTS_OTHER flag is also set) indicates that the route
  2224. * is a primary route, visible to the IP forwarding process. The DOWN flag
  2225. * indicates that the interface through which the gateway is reachable is
  2226. * down.
  2227. *
  2228. * NOMANUAL
  2229. */
  2230. void ripDbgRouteShow ()
  2231.     {
  2232.     int doinghost = 1;
  2233.     register struct rthash *rh;
  2234.     register struct rt_entry *rt;
  2235.     struct rthash *base = hosthash;
  2236.     struct sockaddr_in* dSin;
  2237.     struct sockaddr_in* gSin;
  2238.     struct sockaddr_in* nSin;
  2239.     char address[32];
  2240.     if (!ripInitFlag)
  2241.         return;
  2242.     /* Block all processing to guarantee a stable list of routes. */
  2243.     printf ("Destination      Gateway          Netmask          Metric Proto Timer Tag "
  2244.             "  ref  sref  from              Interfacen");
  2245.     again:
  2246.     for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
  2247.         {
  2248.         rt = rh->rt_forw;
  2249.         for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
  2250.             {
  2251.             ripRouteToAddrs (rt, &dSin, &gSin, &nSin);
  2252.             inet_ntoa_b (dSin->sin_addr, (char *)&address);
  2253.             printf ("%-17s", address);
  2254.             inet_ntoa_b (gSin->sin_addr, (char *)&address);
  2255.             printf ("%-17s", address);
  2256.             inet_ntoa_b (nSin->sin_addr, (char *)&address);
  2257.             printf ("%-17s", address);
  2258.             printf (" %-6d", rt->rt_metric);
  2259.             printf (" %-5d", rt->rt_proto);
  2260.             printf (" %-5d", rt->rt_timer);
  2261.             printf ("%-6x", (unsigned short)ntohs((unsigned short)(rt->rt_tag)));
  2262.             printf (" %-4d", rt->rt_refcnt);
  2263.             printf (" %-5d ", rt->rt_subnets_cnt);
  2264.             inet_ntoa_b (*(struct in_addr *)&(rt->rt_orgrouter), 
  2265.                          (char *)&address); 
  2266.             printf ("%-17s", address);