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

VxWorks

开发平台:

C/C++

  1. /* output.c - routines for generating outgoing RIP messages */
  2. /* Copyright 1984 - 2001 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.  *            @(#)output.c 8.2 (Berkeley) 4/28/95";
  36.  */
  37. /*
  38. modification history
  39. --------------------
  40. 01m,22mar02,niq  Merged from Synth view, tor3_x.synth branch, ver 01p
  41. 01l,15oct01,rae  merge from truestack ver 01n, base 01i (VIRTUAL_STACK etc.)
  42. 01k,21nov00,spm  fixed handling of interface for default route (SPR #62533)
  43. 01j,10nov00,spm  merged from version 01j of tor3_x branch (SPR #33692 fix)
  44. 01i,11sep98,spm  added option to disable gateway filtering and removed
  45.                  all references to bloated trace commands (SPR #22350)
  46. 01h,01sep98,spm  extended gateway filtering tests to handle classless 
  47.                  netmasks and host-specific routes
  48. 01g,26jul98,spm  removed duplicate condition from test in supply routine;
  49.                  corrected stray pointer in ripBuildPacket call and added
  50.                  parameter needed for RIPv2 updates; removed compiler warnings
  51. 01f,06oct97,gnn  added sendHook functionality to sending
  52. 01e,08may97,gnn  fixed an authentication bug.
  53. 01d,07apr97,gnn  cleared up some of the more egregious warnings.
  54.                  added MIB-II interface and option support.
  55. 01c,13mar97,gnn  fixed a minor bug in the output routine
  56. 01b,24feb97,gnn  added rip version 2 functionality
  57. 01a,26nov96,gnn  created from BSD4.4 routed
  58. */
  59. /*
  60. DESCRIPTION
  61. */
  62. /*
  63.  * Routing Table Management Daemon
  64.  */
  65. #include "vxWorks.h"
  66. #include "logLib.h"
  67. #include "rip/defs.h"
  68. #include "rip/m2RipLib.h"
  69. #ifdef VIRTUAL_STACK
  70. #include "netinet/vsLib.h"
  71. #include "netinet/vsRip.h"
  72. #else
  73. IMPORT int routedDebug;
  74. IMPORT BOOL ripFilterFlag;
  75. #endif
  76. /*
  77.  * Apply the function "f" to all non-passive
  78.  * interfaces.  If the interface supports the
  79.  * use of broadcasting use it, otherwise address
  80.  * the output to the known router.
  81.  */
  82. void toall(f, rtstate, skipif)
  83. int (*f)();
  84. int rtstate;
  85. struct interface *skipif;
  86. {
  87. register struct interface *ifp;
  88. register struct sockaddr *dst;
  89. register int flags;
  90. #ifndef VIRTUAL_STACK
  91. extern struct interface *ripIfNet;
  92. #endif
  93. for (ifp = ripIfNet; ifp; ifp = ifp->int_next)
  94.             {
  95.             if (ifp->int_flags & IFF_PASSIVE || ifp == skipif || 
  96.                 (ifp->int_flags & IFF_UP) == 0)
  97.                 continue;
  98.             dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
  99.                 ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
  100.                 &ifp->int_addr;
  101.             flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
  102.             
  103.             if (f == supply)
  104.                 (*f)(dst, flags, ifp, rtstate, 0);
  105.             else
  106.                 (*f)(dst, flags, ifp, rtstate);
  107. }
  108. }
  109. /*
  110.  * Output a preformed packet.
  111.  */
  112. /*ARGSUSED*/
  113. STATUS sndmsg(dst, flags, ifp, rtstate)
  114. struct sockaddr *dst;
  115. int flags;
  116. struct interface *ifp;
  117. int rtstate;
  118. {
  119. #ifndef VIRTUAL_STACK
  120.         IMPORT RIP ripState;
  121. #endif
  122. (*afswitch[dst->sa_family].af_output)(ripState.s, flags,
  123. dst, sizeof (RIP_PKT));
  124.        if (routedDebug > 2)
  125.            logMsg ("Transmitting RIP message.n", 0, 0, 0, 0, 0, 0);
  126.         return (OK);
  127. }
  128. /*
  129.  * Supply dst with the contents of the routing tables.
  130.  * If this won't fit in one packet, chop it up into several.
  131.  */
  132. STATUS supply
  133.     (
  134.     struct sockaddr *dst,
  135.     int flags,
  136.     register struct interface *ifp,
  137.     int rtstate,
  138.     int version
  139.     )
  140.     {
  141. #ifndef VIRTUAL_STACK
  142.     IMPORT RIP ripState;
  143. #endif
  144.     register struct rt_entry *rt;
  145.     register struct netinfo *pNetinfo = ripState.msg->rip_nets;
  146.     register struct rthash *rh;
  147.     struct rthash *base = hosthash;
  148.     int doinghost = 1, size;
  149.     int (*output)() = afswitch[dst->sa_family].af_output;
  150.     int (*sendroute)() = afswitch[dst->sa_family].af_sendroute;
  151.     int npackets = 0;
  152.     struct interface* pIfp;
  153. #ifdef RIP_MD5
  154.     RIP2_AUTH_PKT_HDR * pAuthHdr;
  155.     RIP_AUTH_KEY * pAuthKey;
  156. #endif /* RIP_MD5 */
  157.     ripState.msg->rip_cmd = RIPCMD_RESPONSE;
  158.     
  159.     if (ifp == NULL)
  160.         pIfp = ripIfLookup(dst);
  161.     else
  162.         pIfp = ifp;
  163.     
  164.     if (pIfp == NULL)
  165.         return (ERROR);
  166.     
  167.      /*
  168.       * Check actual interface status before transmitting
  169.       * The interface might have been disabled. 
  170.       */
  171.      if ((pIfp->int_flags & IFF_UP) == 0)
  172.          return (ERROR);
  173.     /*
  174.      * Next, check the status from the MIB-II RIP group. If this
  175.      * interface has been turned off then silently drop packets on it.
  176.      */
  177.     if (pIfp->ifConf.rip2IfConfStatus != M2_rip2IfConfStatus_valid)
  178.         return (ERROR);
  179.     if (pIfp->ifConf.rip2IfConfSend == M2_rip2IfConfSend_doNotSend)
  180.         return (ERROR);
  181.     else if (pIfp->ifConf.rip2IfConfSend == M2_rip2IfConfSend_ripVersion1)
  182.             ripState.msg->rip_vers = 1;
  183.     else if ((pIfp->ifConf.rip2IfConfSend == M2_rip2IfConfSend_rip1Compatible)
  184.              && version != 0)
  185.              ripState.msg->rip_vers = version;
  186.     else if ((pIfp->ifConf.rip2IfConfSend == M2_rip2IfConfSend_rip1Compatible)
  187.              || (pIfp->ifConf.rip2IfConfSend == M2_rip2IfConfSend_ripVersion2))
  188.              ripState.msg->rip_vers = 2;
  189.     else
  190.         return (ERROR);
  191.              
  192.     memset(ripState.msg->rip_domain, 0, sizeof(ripState.msg->rip_domain));
  193.     /*
  194.      * If we are doing authentication then properly fill in the first field.
  195.      *
  196.      */
  197. #ifdef RIP_MD5
  198.     if (pIfp->ifConf.rip2IfConfAuthType == M2_rip2IfConfAuthType_md5)
  199.         {
  200.         if (ripAuthKeyOut1MD5 (pIfp, pNetinfo, &pAuthHdr, &pAuthKey) == ERROR)
  201.             return (ERROR);
  202.         pNetinfo++;
  203.         }
  204.     else if (pIfp->ifConf.rip2IfConfAuthType ==
  205.              M2_rip2IfConfAuthType_simplePassword)
  206. #else
  207.     if (pIfp->ifConf.rip2IfConfAuthType ==
  208.         M2_rip2IfConfAuthType_simplePassword)
  209. #endif /* RIP_MD5 */
  210.         {
  211.         bzero((char *)pNetinfo, sizeof(RIP2PKT));
  212.         ((RIP2PKT *)pNetinfo)->family = RIP2_AUTH;
  213.         ((RIP2PKT *)pNetinfo)->tag = M2_rip2IfConfAuthType_simplePassword;
  214.         bcopy((char *)pIfp->ifConf.rip2IfConfAuthKey,
  215.               (char *)pNetinfo + 4, RIP2_AUTH_LEN);
  216.         pNetinfo++;
  217.         }
  218.     again:
  219.     for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
  220. for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
  221.             {
  222.             if (routedDebug > 1)
  223.                 logMsg ("Looking at IF %s, route to %d %d %d %d n",
  224.                         (int)(rt->rt_ifp ? rt->rt_ifp->int_name : "?"),
  225.                         (u_char)rt->rt_dst.sa_data[2], 
  226.                         (u_char)rt->rt_dst.sa_data[3],
  227.                         (u_char)rt->rt_dst.sa_data[4], 
  228.                         (u_char)rt->rt_dst.sa_data[5], 0);
  229.             /*
  230.              * This calls the per interface send hook.  The user may
  231.              * add their own hook that allows them to decide on a route
  232.              * by route basis what routes to add to the update.
  233.              */
  234.             if (pIfp->sendHook != NULL)
  235.                 if (!pIfp->sendHook(rt))
  236.                     continue;
  237.             /*
  238.              * When sending in response to a query, ifp is zero, disabling
  239.              * this test. Otherwise, information is not sent on the network 
  240.              * from which it was received (simple split horizon).
  241.              */
  242.             if (ifp && (rt->rt_ifp == ifp))
  243.                 continue;
  244.             /*
  245.              * If the route's interface is down, then we don't really
  246.              * want to advertise that route. Skip it
  247.              */
  248.             if (rt->rt_ifp && (rt->rt_ifp->int_flags & IFF_UP) == 0)
  249.                 continue;
  250.             /* 
  251.              * "External" routes are only created for a loopback interface and
  252.              * are never sent.
  253.              */
  254.             if (rt->rt_state & RTS_EXTERNAL)
  255.                 continue;
  256.             /*
  257.              * This test detects routes with the specified state. It limits 
  258.              * the contents of dynamic updates to route entries with 
  259.              * the RTS_CHANGED flag set. 
  260.              */
  261.             if (rtstate && (rt->rt_state & rtstate) == 0)
  262.                 continue;
  263.             /*
  264.              * This test implements the network-related border gateway 
  265.              * filtering specified by RFC 1058 as well as the restrictions 
  266.              * in section 3.3 of RFC 1723 needed for compatibility between 
  267.              * RIPv1 and RIPv2. It selects between the internally generated
  268.              * routes sent to "distant" hosts (which are not directly
  269.              * connected to the destination) and the (possibly classless)
  270.              * route entries which are only sent to neighbors on the same 
  271.              * logical network.
  272.              */
  273.             if (doinghost == 0 && rt->rt_state & RTS_SUBNET)
  274.                 {
  275.                 if (rt->rt_dst.sa_family != dst->sa_family)
  276.                     continue;
  277.                 if (ripFilterFlag)
  278.                     {
  279.                     /* 
  280.                      * Perform border gateway filtering if enabled. The 
  281.                      * restrictions are only needed if RIP-1 routers are
  282.                      * in use on the network.
  283.                      */
  284.                     if ( (*sendroute)(rt, dst, pIfp) == 0)
  285.                         continue;
  286.                     }
  287.                 else
  288.                     {
  289.                     /* 
  290.                      * Border gateway filtering is disabled. Internally 
  291.                      * generated routes (which represent the network as
  292.                      * a whole) are never sent. All other classless routes
  293.                      * are included unconditionally.
  294.                      */
  295.                     if (rt->rt_state & RTS_INTERNAL)
  296.                         continue;
  297.                     }
  298.                 }
  299.             /* 
  300.              * Limit any host route to neighbors within the same logical
  301.              * network. This test also handles some network routes that
  302.              * appear to be host routes to a router because they use a 
  303.              * longer prefix than the receiving interface. These
  304.              * restrictions are only necessary if border gateway filtering
  305.              * is enabled to support an environment with mixed RIP-1 and
  306.              * RIP-2 routers.
  307.              */
  308.             if (doinghost == 1 && ripFilterFlag)
  309.                 {
  310.                 if (rt->rt_dst.sa_family != dst->sa_family)
  311.                     continue;
  312.                 if ((*sendroute)(rt, dst, pIfp) == 0)
  313.                     continue;
  314.                 }
  315.             size = (char *)pNetinfo - ripState.packet;
  316. #ifdef RIP_MD5
  317.             if (pIfp->ifConf.rip2IfConfAuthType == M2_rip2IfConfAuthType_md5)
  318.                 {
  319.                 /* must save a trailing entry for the MD5 auth digest */
  320.                 if (size > (MAXPACKETSIZE - (2 * sizeof(struct netinfo))))
  321.                     {
  322.                     ripAuthKeyOut2MD5(ripState.msg, &size, pNetinfo,
  323.                                       pAuthHdr, pAuthKey);
  324.                     if (routedDebug > 2)
  325.                         logMsg ("Transmitting RIP message.n",
  326.                                 0, 0, 0, 0, 0, 0);
  327.                     (*output)(ripState.s, flags, dst, size);
  328.                     /*
  329.                      * If only sending to ourselves,
  330.                      * one packet is enough to monitor interface.
  331.                      */
  332.                     if (ifp && (ifp->int_flags &
  333.                                 (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE))
  334.                         == 0)
  335.                         return (ERROR);
  336.                     /* set pNetinfo to second entry because first is auth */
  337.                     pNetinfo = (ripState.msg->rip_nets +
  338.                                 sizeof(struct netinfo));
  339.                     npackets++;
  340.                     }
  341.                 }
  342.             else
  343.                 {
  344. #endif /* RIP_MD5 */
  345.                 if (size > MAXPACKETSIZE - sizeof (struct netinfo))
  346.                     {
  347.                     if (routedDebug > 2)
  348.                         logMsg ("Transmitting RIP message.n",
  349.                                 0, 0, 0, 0, 0, 0);
  350.                     (*output)(ripState.s, flags, dst, size);
  351.                     /*
  352.                      * If only sending to ourselves,
  353.                      * one packet is enough to monitor interface.
  354.                      */
  355.                     if (ifp && (ifp->int_flags &
  356.                                 (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE))
  357.                         == 0)
  358.                         return (ERROR);
  359.                     if (pIfp->ifConf.rip2IfConfAuthType ==
  360.                         M2_rip2IfConfAuthType_simplePassword)
  361.                         {
  362.                         /* set pNetinfo to second entry because first is auth */
  363.                         pNetinfo = (ripState.msg->rip_nets +
  364.                                     sizeof(struct netinfo));
  365.                         }
  366.                     else
  367.                         {
  368.                         /* else set pNetinfo to the first entry */
  369.                         pNetinfo = ripState.msg->rip_nets;
  370.                         }
  371.                     npackets++;
  372.                     }
  373. #ifdef RIP_MD5
  374.                 }
  375. #endif /* RIP_MD5 */
  376. #define osa(x) ((struct osockaddr *)(&(x)))
  377.             osa(pNetinfo->rip_dst)->sa_family =
  378.                 htons(rt->rt_dst.sa_family);
  379.             ripBuildPacket((RIP2PKT *)pNetinfo, rt,
  380.                            pIfp, pIfp->ifConf.rip2IfConfSend);
  381.             pNetinfo++;
  382.             }
  383. if (doinghost)
  384.             {
  385.             doinghost = 0;
  386.             base = nethash;
  387.             goto again;
  388.             }
  389. /*
  390.  * If we have something to send or if someone explicitly
  391.  * requested a dump of whatever we have, send the packet.
  392.  * If we are doing a regular/triggered update and there is
  393.  * nothing to send, skip the update
  394.  */
  395. if (pNetinfo != ripState.msg->rip_nets || version != 0)
  396.             {
  397.             size = (char *)pNetinfo - ripState.packet;
  398. #ifdef RIP_MD5
  399.             if (pIfp->ifConf.rip2IfConfAuthType == M2_rip2IfConfAuthType_md5)
  400.                 {
  401.                 ripAuthKeyOut2MD5(ripState.msg, &size, pNetinfo,
  402.                                   pAuthHdr, pAuthKey);
  403.                 }
  404. #endif /* RIP_MD5 */
  405.             if (routedDebug > 2)
  406.                 logMsg ("Transmitting RIP message.n", 0, 0, 0, 0, 0, 0);
  407.             (*output)(ripState.s, flags, dst, size);
  408.             }
  409.         return (OK);
  410.     }