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

VxWorks

开发平台:

C/C++

  1. /* input.c - routines for processing incoming RIP messages */
  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.  *        @(#)input.c 8.3 (Berkeley) 4/28/95
  36.  */
  37. /*
  38. modification history
  39. --------------------
  40. 01s,22mar02,niq  Merged from Synth view, tor3_x.synth branch, ver 01z
  41. 01r,24jan02,niq  SPR 72415 - Added support for Route tags
  42. 01q,15oct01,rae  merge from truestack ver 01t, base 01n (SPRs 70188, 69983 etc.)
  43. 01p,21nov00,spm  fixed transmission of responses to wrong port (SPR #62532)
  44. 01o,10nov00,spm  merged from version 01p of tor3_x branch (SPR #33692 fix)
  45. 01n,16mar99,spm  recovered orphaned code from tor1_0_1.sens1_1 (SPR #25770)
  46. 01m,29sep98,spm  updated route modification time for IP group MIB (SPR #9374)
  47. 01l,11sep98,spm  general overhaul of input processing (SPR #22297); removed
  48.                  all references to bloated trace commands (SPR #22350)
  49. 01k,01sep98,spm  changed test of next hop address to detect supernet 
  50.                  matches (SPR #22220) and comply with RIP specification;
  51.                  modified whitespace (for coding standards) and added comments
  52. 01j,26jun98,spm  corrected timer setting for poisoned routes; removed duplicate
  53.                  tests from response processing; updated debug messages and
  54.                  added typecast to remove compiler warning
  55. 01i,03oct97,gnn  added includes and declarations to remove warnings
  56. 01h,15may97,gnn  fixed errors relating to ripSplitPacket.
  57. 01g,08may97,gnn  fixed more ANVL related errors.
  58. 01f,17apr97,gnn  fixed errors pointed out by ANVL.       
  59. 01e,14apr97,gnn  added input packet authentication.
  60. 01d,07apr97,gnn  cleared up some of the more egregious warnings.
  61.                  added MIB-II interface and option support.
  62. 01c,12mar97,gnn  added multicast support.
  63.                  added time variables.
  64. 01b,24feb97,gnn  added rip version 2 functionality
  65. 01a,26nov96,gnn  created from BSD4.4 routed
  66. */
  67. /*
  68. DESCRIPTION
  69. */
  70. /*
  71.  * Routing Table Management Daemon
  72.  */
  73. #include "vxWorks.h"
  74. #include "logLib.h"
  75. #include "tickLib.h"
  76. #include "rip/defs.h"
  77. #include "m2Lib.h"
  78. #include "routeEnhLib.h"
  79. #ifdef VIRTUAL_STACK
  80. #include "netinet/vsLib.h"
  81. #include "netinet/vsRip.h"
  82. #else
  83. IMPORT int routedDebug;
  84. #endif
  85. /* The random number generation limits the frequency of triggered updates. */
  86. LOCAL u_long ripRandTimeSeed = 1;
  87. LOCAL u_long ripRandTime (void);
  88. LOCAL void ripRouteAgeUpdate(struct rt_entry *pRtEntry);
  89. #define RANDOMDELAY()    (MIN_WAITTIME * 1000000 + 
  90.                ripRandTime() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
  91. #define osa(x) ((struct osockaddr *)(&(x)))
  92. /* forward declarations */
  93. void addrouteforif(register struct interface *ifp);
  94. void ripSplitPacket (struct interface* pIfp, struct sockaddr_in *src,
  95.                      struct sockaddr* orig, struct sockaddr* gateway, 
  96.                      struct sockaddr* netmask, int* pTag );
  97. void timevaladd (struct timeval *t1, struct timeval *t2);
  98. IMPORT STATUS ripAuthCheck (char *, RIP_PKT *);
  99. IMPORT void ripSockaddrPrint (struct sockaddr *);
  100. /*
  101.  * Process a newly received packet.
  102.  */
  103. void routedInput
  104.     (
  105.     struct sockaddr *from,
  106.     register RIP_PKT *rip,
  107.     int size
  108.     )
  109.     {
  110.     register struct rt_entry *rt;
  111.     register struct netinfo *n;
  112.     register struct netinfo *pFirst;
  113.     register struct interface *ifp;
  114.     register struct interface *pErrorIfp;
  115.     struct interface *ripIfWithDstAddr();
  116.     int count, changes = 0;
  117.     register struct afswitch *afp;
  118.     static struct sockaddr badfrom, badfrom2;
  119.     struct sockaddr gateway;
  120.     struct sockaddr netmask;
  121.     int tag;
  122.     int origMetric;
  123. #ifndef VIRTUAL_STACK
  124.     IMPORT RIP ripState;
  125. #endif
  126.     ifp = 0;
  127.     if (routedDebug > 2)
  128.         logMsg ("Received RIP message.n", 0, 0, 0, 0, 0, 0);
  129.     if (from->sa_family >= AF_MAX ||
  130.         (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0)
  131.         {
  132.         if (routedDebug)
  133.             logMsg ("Command %d received from unsupported address family %d.n",
  134.                     rip->rip_cmd, from->sa_family, 0, 0, 0, 0);
  135.         return;
  136.         }
  137.     /* 
  138.      * Determine the interface connected to the source of the 
  139.      * RIP message. If no match is found, the message will be ignored.
  140.      */
  141.     pErrorIfp = ripIfLookup (from);
  142.     if (pErrorIfp == NULL)
  143.         {
  144.         if (routedDebug)
  145.             logMsg ("RIP message received from unreachable router %s.n",
  146.                     (int)(*afswitch[from->sa_family].af_format)(from),
  147.                     0, 0, 0, 0, 0);
  148.          return;
  149.          }
  150.     /* If the interface has been disabled, silently drop received packets. */
  151.     if (pErrorIfp->ifConf.rip2IfConfStatus != M2_rip2IfConfStatus_valid)
  152.         return;
  153.     /* 
  154.      * Test for valid version numbers and filter RIP messages based on the 
  155.      * current setting of the interface's receive control switch. 
  156.      */
  157.     if (rip->rip_vers == 0)
  158.         {
  159.         if (routedDebug)
  160.             logMsg ("RIP version 0 packet received from %s! (cmd %d)n",
  161.                     (int)(*afswitch[from->sa_family].af_format)(from), 
  162.                     rip->rip_cmd, 0, 0, 0, 0);
  163.         pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  164.         return;
  165.         }
  166.     if (rip->rip_vers == 1 && 
  167.             pErrorIfp->ifConf.rip2IfConfReceive == M2_rip2IfConfReceive_rip2)
  168.         {
  169.         if (routedDebug)
  170.             logMsg ("RIP-1 message rejected by receive control switch.n",
  171.                      0, 0, 0, 0, 0, 0);
  172.         pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  173.         return;
  174.         }
  175.     if (rip->rip_vers == 2 && 
  176.             pErrorIfp->ifConf.rip2IfConfReceive == M2_rip2IfConfReceive_rip1)
  177.         {
  178.         if (routedDebug)
  179.             logMsg ("RIP-2 message rejected by receive control switch.n",
  180.                      0, 0, 0, 0, 0, 0);
  181.         pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  182.         return;
  183.         }
  184.     /* 
  185.      * Handle message authentication. If authentication is active, only 
  186.      * messages validated by the authentication hook are accepted. That 
  187.      * routine may allow RIP-1 messages if desired and must validate all 
  188.      * RIP-2 messages.
  189.      */
  190.     if (pErrorIfp->ifConf.rip2IfConfAuthType ==
  191.             M2_rip2IfConfAuthType_noAuthentication)
  192.         {
  193.         /*
  194.          * Authentication is not enabled. Discard any RIP-2 messages 
  195.          * containing authentication entries.
  196.          */
  197.         if (rip->rip_vers == 2)
  198.             {
  199.             pFirst = rip->rip_nets;
  200.             if (ntohs(osa(pFirst->rip_dst)->sa_family) == RIP2_AUTH)
  201.                 {
  202.                 if (routedDebug)
  203.                     logMsg ("Discarding message with unused authentication.n",
  204.                             0, 0, 0, 0, 0, 0);
  205.                 pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  206.                 return;
  207.                 }
  208.             }
  209.         /* Get the first rip entry for processing */
  210.         pFirst = n = rip->rip_nets;
  211.         }
  212.     else
  213.         {
  214.         /* 
  215.          * Authenticate message. All RIP-2 messages without authentication
  216.          * entries are rejected. RIP-2 messages with the current MD5 key
  217.          * or simple password are accepted. Under MD5 authentication, all
  218.          * other RIP-2 messages and all RIP-1 messages are rejected. Under
  219.          * simple password authentication, those messages are still accepted
  220.          * if the hook routine returns OK but are rejected if no hook routine
  221.          * is installed.
  222.          */
  223.         if (rip->rip_vers == 2)
  224.             {
  225.             pFirst = rip->rip_nets;
  226.             if (ntohs (osa (pFirst->rip_dst)->sa_family) != RIP2_AUTH)
  227.                 {
  228.                 if (routedDebug)
  229.                     logMsg ("Discarding unauthenticated RIP-2 message.n",
  230.                             0, 0, 0, 0, 0, 0);
  231.                 pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  232.                 return;
  233.                 }
  234.             }
  235. #ifdef RIP_MD5
  236.         /*
  237.          * When MD5 authentication is active, the validation routine discards
  238.          * all RIP-1 messages and any RIP-2 messages without a matching key.
  239.          */
  240.         if (pErrorIfp->ifConf.rip2IfConfAuthType == M2_rip2IfConfAuthType_md5)
  241.             {
  242.             if (ripAuthKeyInMD5(pErrorIfp, rip, size) == ERROR)
  243.                 {
  244.                 if (routedDebug)
  245.                     logMsg ("Unable to authenticate RIP message.n",
  246.                             0, 0, 0, 0, 0, 0);
  247.                 return;
  248.                 }
  249.             /*
  250.              * Reduce the reported size to ignore the entry which contains
  251.              * the MD5 authentication trailer (20 bytes).
  252.              */
  253.             size -= sizeof(struct netinfo);
  254.             }
  255.         else if (pErrorIfp->ifConf.rip2IfConfAuthType ==
  256.                  M2_rip2IfConfAuthType_simplePassword)
  257. #else
  258.         if (pErrorIfp->ifConf.rip2IfConfAuthType ==
  259.             M2_rip2IfConfAuthType_simplePassword)
  260. #endif /* RIP_MD5 */
  261.             {
  262.             /*
  263.              * The ripAuthCheck() routine automatically accepts any RIP-2 
  264.              * messages containing the correct simple password authentication 
  265.              * key. All other messages are handled by the authentication hook,
  266.              * or discarded if none is available.
  267.              */
  268.             if (ripAuthCheck (pErrorIfp->ifConf.rip2IfConfAuthKey,
  269.                               rip) == ERROR)
  270.                 {
  271.                 if (pErrorIfp->authHook)
  272.                     {
  273.                     if (pErrorIfp->authHook(pErrorIfp->ifConf.
  274.                                                        rip2IfConfAuthKey,
  275.                                             rip) != OK)
  276.                         {
  277.                         pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  278.                         return;
  279.                         }
  280.                     }
  281.                 else
  282.                     {
  283.                     if (routedDebug)
  284.                         logMsg("Discarding unvalidated RIP version %d message.n",
  285.                                rip->rip_vers, 0, 0, 0, 0, 0);
  286.                     pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  287.                     return;
  288.                     }
  289.                 }
  290.             }
  291.         else /* unknown auth type */
  292.             {
  293.             if (routedDebug)
  294.                 logMsg("Discarding unvalidated RIP version %d message (Unknown auth type).n",
  295.                        rip->rip_vers, 0, 0, 0, 0, 0);
  296.             pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  297.             return;
  298.             }
  299.         /* Skip the first rip entry which was used for authentication */
  300.         pFirst = n = rip->rip_nets + 1;
  301.         }
  302.     if (size > RIP_MAX_PACKET)
  303.         {
  304.         if (routedDebug)
  305.             logMsg ("Packet too large from %s. (cmd %d)n", 
  306.                     (int)(*afswitch[from->sa_family].af_format)(from), 
  307.                     rip->rip_cmd, 0, 0, 0, 0);
  308.         pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  309.         return;
  310.         }
  311.     if (((size - 4) % 20) != 0)
  312.         {
  313.         if (routedDebug)
  314.             logMsg("Badly formed packet from %s. (cmd %d)n", 
  315.                    (int)(*afswitch[from->sa_family].af_format)(from), 
  316.                    rip->rip_cmd, 0, 0, 0, 0);
  317.         pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  318.         return;
  319.         }
  320.     
  321.     /* Check that the unused RIP header field contains 0 if required. */
  322.     if (rip->rip_vers == 1)
  323.         {
  324.         if (rip->rip_domain[0] != 0 || rip->rip_domain[1] != 0)
  325.             {
  326.             pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  327.             return ;
  328.             }
  329.         }
  330.     /*
  331.      * Process the received message. RIP responses will exit the switch
  332.      * statement so that triggered updates will be scheduled if necessary.
  333.      * All other commands must execute return statements within the switch
  334.      * to prevent that activity.
  335.      */
  336.     switch (rip->rip_cmd)
  337.         {
  338.         case RIPCMD_REQUEST:
  339.             /*
  340.              * Preserve port number before converting source address to
  341.              * canonical form for testing against local interface addresses.
  342.              */
  343.             ((struct sockaddr_in *)&gateway)->sin_port = 
  344.                 ((struct sockaddr_in *)from)->sin_port;
  345.             
  346.             /* Ignore requests reflected from a local interface. */
  347.             (*afp->af_canon) (from);
  348.             ifp = ripIfWithAddr (from);
  349.             if (ifp)
  350.                 return;
  351.             /* Restore the port number for requests from valid interfaces. */
  352.             ((struct sockaddr_in *)from)->sin_port = 
  353.                 ((struct sockaddr_in *)&gateway)->sin_port;
  354.             /*
  355.              * Determine number of entries in message. If there are no
  356.              * entries, no response is given.
  357.              */
  358.             count = size - ((char *)n - (char *)rip);
  359.             if (count < sizeof (struct netinfo))
  360.                 return;
  361.             for (; count > 0; n++)
  362.                 {
  363.                 if (count < sizeof (struct netinfo))
  364.                     break;
  365.                 count -= sizeof (struct netinfo);
  366.                 if (rip->rip_vers == 1)
  367.                     {
  368.                     if ( ((RIP2PKT *)n)->tag != 0)
  369.                         {
  370.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  371.                         continue;
  372.                         }
  373.                     if ( ((RIP2PKT *)n)->subnet != 0)
  374.                         {
  375.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  376.                         continue;
  377.                         }
  378.                     if ( ((RIP2PKT *)n)->gateway != 0)
  379.                         {
  380.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  381.                         continue;
  382.                         }
  383.                     }
  384.                 
  385.                 n->rip_dst.sa_family = ntohs (osa (n->rip_dst)->sa_family);
  386.                 n->rip_dst.sa_len = sizeof (n->rip_dst);
  387.                 n->rip_metric = ntohl (n->rip_metric);
  388.                 /* 
  389.                  * Check for special case: the entire routing table is
  390.                  * sent if the message contains a single entry with a 
  391.                  * family identifier of 0 (meaning unspecified: AF_UNSPEC) 
  392.                  * and an infinite metric.
  393.                  */
  394.                 if (n->rip_dst.sa_family == AF_UNSPEC &&
  395.                     (count != 0 || n != pFirst))
  396.                     {
  397.                     /*
  398.                      * Ignore entry with family of 0 if the message 
  399.                      * contains multiple route entries.
  400.                      */
  401.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  402.                     continue;
  403.                     }
  404.                 if (n->rip_dst.sa_family == AF_UNSPEC &&
  405.                     n->rip_metric != HOPCNT_INFINITY)
  406.                     {
  407.                     /* 
  408.                      * Ignore message with single entry and family of 0 
  409.                      * if metric is finite. 
  410.                      */
  411.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  412.                     return;
  413.                     }
  414.                 if (n->rip_dst.sa_family == AF_UNSPEC)
  415.                     {
  416.                     /* 
  417.                      * Send the entire routing table, except for entries
  418.                      * learned from the interface which received the request.
  419.                      * Silent RIP processes will only respond to a query which
  420.                      * used a non-standard port. (RFC 1058, section 3.4.1).
  421.                      */
  422.                     if (ripState.supplier ||
  423.                         (*afp->af_portmatch)(from) == 0)
  424.                         {
  425.                         supply (from, 0, pErrorIfp, 0, rip->rip_vers);
  426.                         ripState.ripGlobal.rip2GlobalQueries++;
  427.                         }
  428.                     return;
  429.                     }
  430.                 /* 
  431.                  * Ignore entries with unsupported address families.
  432.                  * Currently, only entries with a family of AF_INET 
  433.                  * are accepted.
  434.                  */
  435.                 if (n->rip_dst.sa_family != AF_INET)
  436.                     {
  437.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  438.                     continue;
  439.                     }
  440.                 if (n->rip_dst.sa_family < AF_MAX &&
  441.                     afswitch[n->rip_dst.sa_family].af_hash)
  442.                     {
  443.                     rt = rtlookup(&n->rip_dst);
  444.                     /*
  445.                      * If the interface for the route is down, the
  446.                      * route is not reachable.
  447.                      */
  448.                     if (rt->rt_ifp && (rt->rt_ifp->int_flags & IFF_UP) == 0)
  449.                         rt = 0;
  450.                     }
  451.                 else
  452.                     rt = 0;
  453.                 n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
  454.                     min(rt->rt_metric + 1, HOPCNT_INFINITY);
  455.                 osa(n->rip_dst)->sa_family =
  456.                     htons(n->rip_dst.sa_family);
  457.                 n->rip_metric = htonl(n->rip_metric);
  458.                 changes++;
  459.                 }
  460.             /* 
  461.              * The RFC specification does not clearly define the desired
  462.              * behavior for the case where all entries in a request use 
  463.              * an unknown family. Although the individual entries must
  464.              * be ignored, it seems as if a response containing unchanged 
  465.              * metrics should be returned, but that behavior causes ANVL 
  466.              * test 6.5 to fail. The following test avoids that problem.
  467.              */
  468.             if (changes)
  469.                 {
  470.                 /* Send a reply if at least one entry was recognized. */
  471.                 rip->rip_cmd = RIPCMD_RESPONSE;
  472.                 memmove(ripState.packet, rip, size);
  473.                 (*afp->af_output)(ripState.s, 0, from, size);
  474.                 ripState.ripGlobal.rip2GlobalQueries++;
  475.                 }
  476.             return;
  477.             
  478.         case RIPCMD_TRACEON:
  479.         case RIPCMD_TRACEOFF:
  480.             /* Obsolete commands ignored by RIP. (RFC 1058, section 3.1) */
  481.             if (routedDebug)
  482.                 logMsg ("Ignoring obsolete trace command from router %s.n",
  483.                         (int)(*afswitch[from->sa_family].af_format)(from),
  484.                         0, 0, 0, 0, 0);
  485.             pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  486.             return;
  487.             
  488.         case RIPCMD_RESPONSE:
  489.             /* Verify that the message used the required port. */
  490.             if ((*afp->af_portmatch)(from) == 0)
  491.                 {
  492.                 pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  493.                 return;
  494.                 }
  495.             /* 
  496.              * Check for reflected updates from the router's own interface.
  497.              * The test also eliminates updates from a directed broadcast
  498.              * address which is one of the illegal source addresses forbidden
  499.              * by the router requirements RFC.
  500.              */
  501.             (*afp->af_canon) (from);
  502.             ifp = ripIfWithAddr (from);
  503.             if (ifp)
  504.                 {
  505.                 /*
  506.                  * When a router receives an invalid update, it uses it to 
  507.                  * track the status of a directly connected interface, but 
  508.                  * the message is otherwise ignored.
  509.                  */
  510.                 if (ifp->int_flags & IFF_PASSIVE)
  511.                     {
  512.                     if (routedDebug)
  513.                         logMsg ("bogus input (from passive interface, %s)n",
  514.                              (int)(*afswitch[from->sa_family].af_format)(from),
  515.                                 0, 0, 0, 0, 0);
  516.                     ifp->ifStat.rip2IfStatRcvBadPackets++;
  517.                     return;
  518.                     }
  519.                 /* 
  520.                  * Search for a route entry to the directly connected network
  521.                  * and reset the expiration timer if found. If no such route
  522.                  * is present or a non-interface route is detected, the 
  523.                  * receiving interface was either recently added or restarted. 
  524.                  * The addrouteforif routine will create a permanent interface 
  525.                  * route and remove any overlapping (learned) route.
  526.                  */
  527.                 rt = rtfind(from);
  528.                 if (rt == 0 || (((rt->rt_state & RTS_INTERFACE) == 0) &&
  529.                     rt->rt_metric >= ifp->int_metric))
  530.                     addrouteforif(ifp);
  531.                 else
  532.                     {
  533.                     rt->rt_timer = 0;
  534.                     /* Update age for IP group MIB. */
  535.                     if (rt->inKernel) 
  536.                         ripRouteAgeUpdate (rt); 
  537.                     }
  538.                 return;
  539.                 }
  540.             /*
  541.              * Update timer for interface route on which the message arrived.
  542.              * If none is found and the sender is the other end of a 
  543.              * point-to-point link that isn't registered in the routing 
  544.              * tables, add or restore that route.
  545.              */
  546.             if ((rt = rtfind(from)) &&
  547.                 (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
  548.                 {
  549.                 rt->rt_timer = 0;
  550.                 if (rt->inKernel) 
  551.                     ripRouteAgeUpdate (rt); /* Update age for IP group MIB. */
  552.                 }
  553.             else if ((ifp = ripIfWithDstAddr(from, NULL)) &&
  554.                      (rt == 0 || rt->rt_metric >= ifp->int_metric))
  555.                 addrouteforif(ifp);
  556.             /* 
  557.              * NOTE: The preceding rtfind() routine will not detect a 
  558.              * match for updates from a router on the same supernet with 
  559.              * a different class-based network number than the local
  560.              * interfaces. (For instance, it will not reset the route 
  561.              * timer for 192.168.254.0/23 when an update is received 
  562.              * from 192.168.255.x/23 if the local interface has the 
  563.              * address 192.168.254.x/23. This omission has no effect 
  564.              * because the timer for an interface route is never 
  565.              * incremented. The return value of 0 will not cause an
  566.              * incorrect call to addrouteforif() because the search in
  567.              *  ripIfWithDstAddr will always fail in this situation.
  568.              */
  569.             /*
  570.              * Reset the pointer to validate the interface from which the
  571.              * message arrived. Updates are accepted from routers directly 
  572.              * connected via broadcast or point-to-point networks.
  573.              */
  574.             ifp = pErrorIfp;    /* Results of ripIfLookup on source address. */
  575.             if ( (ifp->int_flags &
  576.                      (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
  577.                 ifp->int_flags & IFF_PASSIVE)
  578.                 {
  579.                 /* Error: source does not use a directly-connected network. */
  580.                 if (memcmp(from, &badfrom, sizeof(badfrom)) != 0)
  581.                     {
  582.                     if (routedDebug)
  583.                         logMsg ("packet from unknown router, %sn",
  584.                              (int)(*afswitch[from->sa_family].af_format)(from),
  585.                                 0, 0, 0, 0, 0);
  586.                     badfrom = *from;
  587.                     }
  588.                 pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  589.                 return;
  590.                 }
  591.             /*
  592.              * At this point, the source address and port number of the 
  593.              * response have been checked. It is from another host on a 
  594.              * directly connected network and was sent to the correct port. 
  595.              * Begin processing the datagram by ignoring the initial data 
  596.              * (command, version, and two unused bytes) and leading 
  597.              * authentication header, if any.
  598.              */
  599.             size = size - ((char *)n - (char *)rip);
  600.             /* Now start processing actual route entries. */
  601.             for (; size > 0; size -= sizeof (struct netinfo), n++)
  602.                 {
  603.                 if (size < sizeof (struct netinfo))
  604.                     break;
  605.                 n->rip_dst.sa_family =
  606.                     ntohs(osa(n->rip_dst)->sa_family);
  607.                 n->rip_dst.sa_len = sizeof(n->rip_dst);
  608.                 n->rip_metric = ntohl(n->rip_metric);
  609.                 /* Ignore any entry with an unknown address family. */
  610.                 if (n->rip_dst.sa_family >= AF_MAX ||
  611.                     (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
  612.                     (int (*)())0)
  613.                     {
  614.                     if (routedDebug)
  615.                         logMsg("route in unsupported address family %d from %s"
  616.                                "(af %d)n", n->rip_dst.sa_family, 
  617.                                (int)(*afswitch[from->sa_family].af_format)
  618.                                (from), from->sa_family, 0, 0, 0);
  619.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  620.                     continue;
  621.                     }
  622.                  /* 
  623.                   * Ignore an entry if the unused fields are not zero.
  624.                   * (These fields are only unused in version 1 updates).
  625.                   */
  626.                 if (rip->rip_vers == 1)
  627.                     {
  628.                     if ( ((RIP2PKT *)n)->tag != 0)
  629.                         {
  630.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  631.                         continue;
  632.                         }
  633.                     if ( ((RIP2PKT *)n)->subnet != 0)
  634.                         {
  635.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  636.                         continue;
  637.                         }
  638.                     if ( ((RIP2PKT *)n)->gateway != 0)
  639.                         {
  640.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  641.                         continue;
  642.                         }
  643.                     }
  644.                 /* 
  645.                  * Ignore any entry with an inappropriate address.
  646.                  * The receiving interface is used to detect broadcast
  647.                  * addresses if no netmask is present in the route update.
  648.                  */
  649.                 if ( ((*afp->af_checkhost)(&n->rip_dst, ifp)) == 0)
  650.                     {
  651.                     if (routedDebug)
  652.                         logMsg ("bad host in route from %s (af %d)n",
  653.                              (int)(*afswitch[from->sa_family].af_format)(from),
  654.                                 from->sa_family, 0, 0, 0, 0);
  655.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  656.                     continue;
  657.                     }
  658.                 if ((n->rip_metric == 0) ||
  659.                     ((unsigned) n->rip_metric > HOPCNT_INFINITY))
  660.                     {
  661.                     if (memcmp(from, &badfrom2,
  662.                                sizeof(badfrom2)) != 0)
  663.                         {
  664.                         if (routedDebug)
  665.                             logMsg ("bad metric (%d) from %sn", n->rip_metric,
  666.                              (int)(*afswitch[from->sa_family].af_format)(from),
  667.                                     0, 0, 0, 0);
  668.                         badfrom2 = *from;
  669.                         }
  670.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  671.                     continue;
  672.                     }
  673.                 rt = rtlookup (&n->rip_dst);
  674.                 /* 
  675.                  * Do not allow a route learnt from other protocols to be
  676.                  * replaced
  677.                  */
  678.                 if (rt && ((rt->rt_state & RTS_OTHER) != 0))
  679.                     continue;
  680.                 
  681.                 if (rt == 0 ||
  682.                     (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
  683.                     (RTS_INTERNAL|RTS_INTERFACE))
  684.                     {
  685.                     /*
  686.                      * If we're hearing a logical network route
  687.                      * back from a peer to which we sent it,
  688.                      * ignore it.
  689.                      */
  690.                     if (rt && rt->rt_state & RTS_SUBNET &&
  691.                         (*afp->af_sendroute)(rt, from, ifp))
  692.                         {
  693.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  694.                         continue;
  695.                         }
  696.                     /*
  697.                      * Adjust metric according to incoming interface.
  698.                      */
  699.                     if ((unsigned)n->rip_metric < HOPCNT_INFINITY)
  700.                         {
  701.                         /*
  702.                          * Look for an equivalent route that
  703.                          * includes this one before adding
  704.                          * this route.
  705.                          */
  706.                         rt = rtfind(&n->rip_dst);
  707.                         if ((rt && equal(from, &rt->rt_router)) &&
  708.                             (rt->rt_metric <= n->rip_metric))
  709.                             continue;
  710.                         n->rip_metric += ifp->int_metric;
  711.                         if (rip->rip_vers < 2)
  712.                             {
  713.                             rtadd (&n->rip_dst, from, n->rip_metric, 
  714.                                    0, NULL, M2_ipRouteProto_rip, 0,
  715.                                    ((struct sockaddr_in *)from)->
  716.                                     sin_addr.s_addr, pErrorIfp);
  717.                             }
  718.                         else
  719.                             {
  720.                             ripSplitPacket (ifp, (struct sockaddr_in *)from, 
  721.                                             &n->rip_dst, &gateway, &netmask,
  722.                                             &tag);
  723.                             if (((struct sockaddr_in *)&netmask)->
  724.                                 sin_addr.s_addr == -1)
  725.                                 {
  726.                                 pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  727.                                 continue;
  728.                                 }
  729.                             /*
  730.                              * RFC 1723, Section 3.4: check to see that the 
  731.                              * gateway is directly reachable. If not, treat 
  732.                              * that value as 0.0.0.0 by using the originator 
  733.                              * as the gateway.
  734.                              */
  735.                             if ((((struct sockaddr_in *)&gateway)->
  736.                                  sin_addr.s_addr & 
  737.                                  htonl (ifp->int_subnetmask)) != 
  738.                                 (((struct sockaddr_in *)&ifp->int_addr)->
  739.                                  sin_addr.s_addr & 
  740.                                  htonl (ifp->int_subnetmask)))
  741.                                 {
  742.                                 ((struct sockaddr_in *)&gateway)->
  743.                                     sin_addr.s_addr = 
  744.                                     ((struct sockaddr_in *)from)->
  745.                                     sin_addr.s_addr;
  746.                                 }
  747.                             rtadd(&n->rip_dst, &gateway, n->rip_metric, 0,
  748.                                   &netmask, M2_ipRouteProto_rip, tag,
  749.                                   ((struct sockaddr_in *)from)->
  750.                                   sin_addr.s_addr, pErrorIfp);
  751.                             }
  752.                         changes++;
  753.                         }
  754.                     continue;
  755.                     }
  756.                 /*
  757.                  * Update if from gateway and different,
  758.                  * shorter, or equivalent but old route
  759.                  * is getting stale.
  760.                  */
  761.                 /*
  762.                  * If this was a pre-existinng route then we can
  763.                  * update it to be "infinite" and should.
  764.                  * ANVL 7.13.
  765.                  */
  766.                 origMetric = n->rip_metric;
  767.                 if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
  768.                     n->rip_metric += ifp->int_metric;
  769.                 if (n->rip_metric > HOPCNT_INFINITY)
  770.                     {
  771.                     pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  772.                     continue;
  773.                     }
  774.                 if (rip->rip_vers > 1)
  775.                     {
  776.                     ripSplitPacket(ifp, (struct sockaddr_in *)from, 
  777.                                    &n->rip_dst, &gateway, &netmask,
  778.                                    &tag);
  779.                     if (((struct sockaddr_in *)&netmask)->
  780.                         sin_addr.s_addr == -1)
  781.                         {
  782.                         pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++;
  783.                         continue;
  784.                         }
  785.                     /*
  786.                      * RFC 1723, Section 3.4: check to see that the 
  787.                      * gateway is directly reachable. If not, treat 
  788.                      * that value as 0.0.0.0 by using the originator 
  789.                      * as the gateway.
  790.                      */
  791.                     if ((((struct sockaddr_in *)&gateway)->sin_addr.s_addr & 
  792.                          htonl (ifp->int_subnetmask)) != 
  793.                         (((struct sockaddr_in *)&ifp->int_addr)->
  794.                          sin_addr.s_addr & htonl (ifp->int_subnetmask)))
  795.                         {
  796.                         ((struct sockaddr_in *)&gateway)->sin_addr.s_addr = 
  797.                             ((struct sockaddr_in *)from)->sin_addr.s_addr;
  798.                         }
  799.                     }
  800.                 /*
  801.                  * We are making an assumption here that the address
  802.                  * is an internet address (4 bytes long). Since we currently
  803.                  * support only the AF_INET family its OK, but if that
  804.                  * changes, the following check will need to be changed
  805.                  * accordingly
  806.                  */
  807.                 if (((struct sockaddr_in *)from)->sin_addr.s_addr ==
  808.                     rt->rt_orgrouter)
  809.                     {
  810.                     /* 
  811.                      * If the metric changed then we should change our 
  812.                      * route. Also if this is a valid update with 
  813.                      * metric of 15 and we have already deleted the 
  814.                      * route from the routing database we should 
  815.                      * revalidate the route in our table and add it 
  816.                      * back to the system database 
  817.                      */
  818.                     if ((n->rip_metric != rt->rt_metric) || 
  819.                         (n->rip_metric == HOPCNT_INFINITY)) 
  820.                         {
  821.                         /* 
  822.                          * If this is a repeat advertisement of an 
  823.                          * unreachable destination, ignore it. 
  824.                          * Ignore it also if we have already expired 
  825.                          * this route and are being informed that it 
  826.                          * has expired. We have acted on it once already. 
  827.                          */
  828.                         if ((origMetric == HOPCNT_INFINITY) && 
  829.                             (rt->rt_metric == HOPCNT_INFINITY) && 
  830.                             !rt->inKernel && 
  831.                             (rt->rt_timer >= ripState.expire)) 
  832.                             break;
  833. /*
  834.  * If the advertised metric is (HOPCNT_INFINITY -1),
  835.  * a valid metric, check to see what we should
  836.  * do with it. If we already have the route
  837.  * in the system table, reset the timer,
  838.  * else trick rtchange() into adding the route back
  839.  */
  840. if (origMetric == (HOPCNT_INFINITY - 1))
  841.     {
  842.     if (rt->inKernel) 
  843.                                 {
  844.                                 rt->rt_timer = 0; 
  845.                                 /* Update age for IP group MIB. */ 
  846.                                 ripRouteAgeUpdate (rt);
  847.                                 break;
  848.                                 } 
  849.                             else 
  850.                                 n->rip_metric++;
  851.                             }
  852.                         if (rip->rip_vers > 1)
  853.                             {
  854.                             rtchange(rt, &gateway, n->rip_metric,
  855.                                      &netmask, tag, 0, NULL);
  856.                             }
  857.                         else
  858.                             {
  859.                             rtchange(rt, from, n->rip_metric, NULL, 0, 0, 
  860.                                      NULL);
  861.                             }
  862.                         changes++;
  863.                         rt->rt_timer = 0;
  864.                         if (origMetric == HOPCNT_INFINITY)
  865.                             rt->rt_timer = ripState.expire;
  866.                         else if (rt->inKernel) 
  867.                             {
  868.                             /* Update age for IP group MIB. */ 
  869.                             ripRouteAgeUpdate (rt);
  870.                             }
  871.                         }
  872.                     else if (rt->rt_metric < HOPCNT_INFINITY)
  873.                         {
  874.                         rt->rt_timer = 0;
  875.                         /* Update age for IP group MIB. */
  876.                         if (rt->inKernel) 
  877.                             ripRouteAgeUpdate (rt); 
  878.                         /*
  879.                          * Metric is same. Check if either the next hop
  880.                          * or the tag changed, for a V2 packet. If it did,
  881.                          * we need to record the change
  882.                          */
  883.                         if ((rip->rip_vers > 1) && 
  884.                             ((((RIP2PKT *)n)->tag != rt->rt_tag) || 
  885.                              (memcmp(&gateway, &(rt->rt_router), 
  886.                                      sizeof(gateway)) != 0))) 
  887.                             {
  888.                             rtchange(rt, &gateway, n->rip_metric,
  889.                                      &netmask, tag, 0, NULL);
  890.                             }
  891.                         }
  892.                     }
  893.                 else if ((unsigned) n->rip_metric < rt->rt_metric ||
  894.                          (rt->rt_metric == n->rip_metric &&
  895.                           rt->rt_timer > (ripState.expire/2) &&
  896.                           (unsigned) origMetric < HOPCNT_INFINITY))
  897.                     {
  898.                     if (rip->rip_vers > 1)
  899.                         {
  900.                         rtchange(rt, &gateway, n->rip_metric,
  901.                                  &netmask, tag, 
  902.                                  ((struct sockaddr_in *)from)->
  903.                                  sin_addr.s_addr, NULL);
  904.                         }
  905.                     else
  906.                         {
  907.                         rtchange(rt, from, n->rip_metric, NULL, 0,
  908.                                  ((struct sockaddr_in *)from)->
  909.                                  sin_addr.s_addr, NULL);
  910.                         }
  911.                     changes++;
  912.                     rt->rt_timer = 0;
  913.                     /* Update age for IP group MIB. */
  914.                     if (rt->inKernel) 
  915.                         ripRouteAgeUpdate (rt); 
  916.                     }
  917.                 }
  918.             break;
  919.         default:
  920.             /* 
  921.              * Ignore any unrecognized commands. Return from the routine
  922.              * to prevent any possibility of scheduling a triggered update.
  923.              */
  924.             pErrorIfp->ifStat.rip2IfStatRcvBadPackets++;
  925.             return;  
  926.         }
  927.     
  928.     /*
  929.      * This section of code schedules triggered updates whenever entries in
  930.      * the routing table change. No updates are sent for silent RIP
  931.      * configurations and are also suppressed if a regular update will
  932.      * occur within the next MAX_WAITTIME seconds.
  933.      */
  934.     if (changes && ripState.supplier &&
  935.         ripState.now.tv_sec - ripState.lastfullupdate.tv_sec < 
  936.             ripState.supplyInterval - MAX_WAITTIME)
  937.         {
  938.         /*
  939.          * No regular update is imminent. Check the elapsed time since
  940.          * the previous (regular or triggered) update and the time limit
  941.          * of the "nextbcast" quiet period which restricts the update
  942.          * frequency. 
  943.          */
  944.         if (ripState.now.tv_sec - ripState.lastbcast.tv_sec >= MIN_WAITTIME
  945.             && (ripState.nextbcast.tv_sec < ripState.now.tv_sec))
  946.             {
  947.             /*
  948.              * All conditions have been met. Send a triggered update over the 
  949.              * interfaces which did not receive the RIP response. The message 
  950.              * sent over each interface only includes routes which changed 
  951.              * since the last message sent.
  952.              */
  953.             if (routedDebug)
  954.                 logMsg ("send dynamic updaten", 0, 0, 0, 0, 0, 0);
  955.             ifp->ifStat.rip2IfStatSentUpdates++;
  956.             toall (supply, RTS_CHANGED, ifp);
  957.             ripState.lastbcast = ripState.now;
  958.             ripState.needupdate = 0;
  959.             ripState.nextbcast.tv_sec = 0;
  960.             }
  961.         else
  962.             {
  963.             /*
  964.              * The triggered update can't be sent because of frequency 
  965.              * limitations imposed to prevent excessive network traffic.
  966.              * Set the delayed update indicator so that the update will
  967.              * be sent when possible.
  968.              */
  969.             ripState.needupdate++;
  970.             }
  971.         
  972.         if (ripState.nextbcast.tv_sec == 0)
  973.             {
  974.             /*
  975.              * Select the earliest possible time for the next triggered 
  976.              * update. A random value is used to avoid periodic network
  977.              * congestion from synchronized routers.
  978.              */
  979.             u_long delay = RANDOMDELAY();
  980.             ripState.nextbcast.tv_sec = delay / 1000000;
  981.             ripState.nextbcast.tv_usec = delay % 100000;
  982.             timevaladd (&ripState.nextbcast, &ripState.now);
  983.             /*
  984.              * If the earliest allowable update occurs within MIN_WAITTIME 
  985.              * seconds before the next regular update, force the delay past 
  986.              * that point to avoid a redundant triggered update.
  987.              */
  988.             if (ripState.nextbcast.tv_sec >
  989.                 ripState.lastfullupdate.tv_sec +
  990.                 ripState.supplyInterval - MIN_WAITTIME)
  991.                 {
  992.                 ripState.nextbcast.tv_sec =
  993.                     ripState.lastfullupdate.tv_sec +
  994.                     ripState.supplyInterval + 1;
  995.                 }
  996.             }
  997.         }
  998.     }
  999. /* 
  1000.  * This pseudo-random number generator restricts the frequency of triggered
  1001.  * updates. It was plagiarized shamelessly from FreeBSD 2.1.7 where it was 
  1002.  * used for the same purpose by routed.
  1003.  */
  1004. LOCAL u_long ripRandTime (void)
  1005.     {
  1006.     register long x, hi, lo, t;
  1007.     /*
  1008.      * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1).
  1009.     * From "Random number generators: good ones are hard to find",
  1010.      * Park and Miller, Communications of the ACM, vol. 31, no. 10,
  1011.      * October 1988, p. 1195.
  1012.      */
  1013.     x = ripRandTimeSeed;
  1014.     hi = x / 127773;
  1015.     lo = x % 127773;
  1016.     t = 16807 * lo - 2836 * hi;
  1017.     if (t <= 0)
  1018.         t += 0x7fffffff;
  1019.     ripRandTimeSeed = t;
  1020.     return (t);
  1021.     }
  1022. /****************************************************************************
  1023. *
  1024. * ripRouteAgeUpdate - update the age for the RIP route
  1025. *
  1026. * This routine updates the age of the RIP route that is kept in the
  1027. * system Routing database.
  1028. * The parameter <pRtEntry> describes the RIP route that is kept in RIP's
  1029. * private database.
  1030. *
  1031. * This routine constructs a ROUTE DESCRIPTOR structure from the supplied
  1032. * parameter <pRtEntry> that describes the route whose age is to be updated
  1033. * and calls the routing extensions function routeAgeSet() to set the new
  1034. * age. tickGet() is used to get the current tick count and is used as the
  1035. * new age.
  1036. *
  1037. * RETURNS: N/A
  1038. *
  1039. * ERRNO: N/A
  1040. *
  1041. * NOMANUAL
  1042. */
  1043. LOCAL void ripRouteAgeUpdate 
  1044.     (
  1045.     struct rt_entry * pRtEntry /* Route entry describing the */
  1046.      /* RIP route to update */
  1047.     )
  1048.     {
  1049.     struct sockaddr_in * pDsin;
  1050.     struct sockaddr_in * pGsin;
  1051.     struct sockaddr_in * pNsin;
  1052.     
  1053.     /*
  1054.      * Retrieve the destination and netmask values from the
  1055.      * corresponding fields in the RIP route entry structure
  1056.      */
  1057.     ripRouteToAddrs (pRtEntry, &pDsin, &pGsin, &pNsin);
  1058.     /* 
  1059.      * If it is a host route, set netmask to NULL. RIP internally
  1060.      * assigns a host route the netmask of the interface. But the system
  1061.      * overrides that and stores the route as a host route with a NULL mask.
  1062.      * (which is the right thing to do). So we set the netmask field to
  1063.      * NULL so that the route lookup happens fine.
  1064.      */
  1065.     if (pRtEntry->rt_flags & RTF_HOST)
  1066.         pNsin = NULL;
  1067.     if (routedDebug > 2)
  1068.         {
  1069.         logMsg ("ripRouteAgeUpdate: setting new age = %d forn", 
  1070.                 tickGet (), 0, 0, 0, 0, 0);
  1071.         ripSockaddrPrint ((struct sockaddr *)pDsin);
  1072.         ripSockaddrPrint ((struct sockaddr *)pNsin);
  1073.         ripSockaddrPrint ((struct sockaddr *)pGsin);
  1074.         }
  1075.     /* Now set the route age */
  1076.     if (routeAgeSet ((struct sockaddr *)pDsin, (struct sockaddr *)pNsin, 
  1077.                      M2_ipRouteProto_rip, tickGet ()) == ERROR) 
  1078.         {
  1079.         if (routedDebug) 
  1080.             logMsg ("Couldn't set age for rtEntry = %x.n", (int)pRtEntry, 0, 
  1081.                     0, 0, 0, 0);
  1082.         }
  1083.     }