home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / routed / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-17  |  11.5 KB  |  364 lines

  1. /*
  2.  * Copyright (c) 1983, 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. /*static char sccsid[] = "from: @(#)input.c    5.22 (Berkeley) 6/1/90";*/
  36. static char rcsid[] = "$Id: input.c,v 1.4 1993/08/01 18:24:28 mycroft Exp $";
  37. #endif /* not lint */
  38.  
  39. /*
  40.  * Routing Table Management Daemon
  41.  */
  42. #include "defs.h"
  43. #include <sys/syslog.h>
  44.  
  45. /*
  46.  * Process a newly received packet.
  47.  */
  48. rip_input(from, rip, size)
  49.     struct sockaddr *from;
  50.     register struct rip *rip;
  51.     int size;
  52. {
  53.     register struct rt_entry *rt;
  54.     register struct netinfo *n;
  55.     register struct interface *ifp;
  56.     struct interface *if_ifwithdstaddr();
  57.     int count, changes = 0;
  58.     register struct afswitch *afp;
  59.     static struct sockaddr badfrom, badfrom2;
  60.  
  61.     ifp = 0;
  62.     TRACE_INPUT(ifp, from, (char *)rip, size);
  63.     if (from->sa_family >= af_max ||
  64.         (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) {
  65.         syslog(LOG_INFO,
  66.      "\"from\" address in unsupported address family (%d), cmd %d\n",
  67.             from->sa_family, rip->rip_cmd);
  68.         return;
  69.     }
  70.     if (rip->rip_vers == 0) {
  71.         syslog(LOG_ERR,
  72.             "RIP version 0 packet received from %s! (cmd %d)",
  73.             (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd);
  74.         return;
  75.     }
  76.     switch (rip->rip_cmd) {
  77.  
  78.     case RIPCMD_REQUEST:
  79.         n = rip->rip_nets;
  80.         count = size - ((char *)n - (char *)rip);
  81.         if (count < sizeof (struct netinfo))
  82.             return;
  83.         for (; count > 0; n++) {
  84.             if (count < sizeof (struct netinfo))
  85.                 break;
  86.             count -= sizeof (struct netinfo);
  87.  
  88. #if BSD < 198810
  89.             if (sizeof(n->rip_dst.sa_family) > 1)    /* XXX */
  90.                 n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
  91. #else
  92. #define osa(x) ((struct osockaddr *)(&(x)))
  93.                 n->rip_dst.sa_family =
  94.                     ntohs(osa(n->rip_dst)->sa_family);
  95.                 n->rip_dst.sa_len = sizeof(n->rip_dst);
  96. #endif
  97.             n->rip_metric = ntohl(n->rip_metric);
  98.             /* 
  99.              * A single entry with sa_family == AF_UNSPEC and
  100.              * metric ``infinity'' means ``all routes''.
  101.              * We respond to routers only if we are acting
  102.              * as a supplier, or to anyone other than a router
  103.              * (eg, query).
  104.              */
  105.             if (n->rip_dst.sa_family == AF_UNSPEC &&
  106.                 n->rip_metric == HOPCNT_INFINITY && count == 0) {
  107.                     if (supplier || (*afp->af_portmatch)(from) == 0)
  108.                     supply(from, 0, 0, 0);
  109.                 return;
  110.             }
  111.             if (n->rip_dst.sa_family < af_max &&
  112.                 afswitch[n->rip_dst.sa_family].af_hash)
  113.                 rt = rtlookup(&n->rip_dst);
  114.             else
  115.                 rt = 0;
  116. #define min(a, b) (a < b ? a : b)
  117.             n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
  118.                 min(rt->rt_metric + 1, HOPCNT_INFINITY);
  119. #if BSD < 198810
  120.             if (sizeof(n->rip_dst.sa_family) > 1)    /* XXX */
  121.                 n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
  122. #else
  123.                 osa(n->rip_dst)->sa_family =
  124.                         htons(n->rip_dst.sa_family);
  125. #endif
  126.             n->rip_metric = htonl(n->rip_metric);
  127.         }
  128.         rip->rip_cmd = RIPCMD_RESPONSE;
  129.         bcopy((char *)rip, packet, size);
  130.         (*afp->af_output)(s, 0, from, size);
  131.         return;
  132.  
  133.     case RIPCMD_TRACEON:
  134.     case RIPCMD_TRACEOFF:
  135.         /* verify message came from a privileged port */
  136.         if ((*afp->af_portcheck)(from) == 0)
  137.             return;
  138.         if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
  139.             (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
  140.             ifp->int_flags & IFF_PASSIVE) {
  141.             syslog(LOG_ERR, "trace command from unknown router, %s",
  142.                 (*afswitch[from->sa_family].af_format)(from));
  143.             return;
  144.         }
  145.         ((char *)rip)[size] = '\0';
  146.         if (rip->rip_cmd == RIPCMD_TRACEON)
  147.             traceon(rip->rip_tracefile);
  148.         else
  149.             traceoff();
  150.         return;
  151.  
  152.     case RIPCMD_RESPONSE:
  153.         /* verify message came from a router */
  154.         if ((*afp->af_portmatch)(from) == 0)
  155.             return;
  156.         (*afp->af_canon)(from);
  157.         /* are we talking to ourselves? */
  158.         ifp = if_ifwithaddr(from);
  159.         if (ifp) {
  160.             if (ifp->int_flags & IFF_PASSIVE) {
  161.                 syslog(LOG_ERR,
  162.                   "bogus input (from passive interface, %s)",
  163.                   (*afswitch[from->sa_family].af_format)(from));
  164.                 return;
  165.             }
  166.             rt = rtfind(from);
  167.             if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) &&
  168.                 rt->rt_metric >= ifp->int_metric) 
  169.                 addrouteforif(ifp);
  170.             else
  171.                 rt->rt_timer = 0;
  172.             return;
  173.         }
  174.         /*
  175.          * Update timer for interface on which the packet arrived.
  176.          * If from other end of a point-to-point link that isn't
  177.          * in the routing tables, (re-)add the route.
  178.          */
  179.         if ((rt = rtfind(from)) &&
  180.             (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
  181.             rt->rt_timer = 0;
  182.         else if ((ifp = if_ifwithdstaddr(from)) &&
  183.             (rt == 0 || rt->rt_metric >= ifp->int_metric))
  184.             addrouteforif(ifp);
  185.         /*
  186.          * "Authenticate" router from which message originated.
  187.          * We accept routing packets from routers directly connected
  188.          * via broadcast or point-to-point networks,
  189.          * and from those listed in /etc/gateways.
  190.          */
  191.         if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
  192.             (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
  193.             ifp->int_flags & IFF_PASSIVE) {
  194.             if (bcmp((char *)from, (char *)&badfrom,
  195.                 sizeof(badfrom)) != 0) {
  196.                 syslog(LOG_ERR,
  197.                   "packet from unknown router, %s",
  198.                   (*afswitch[from->sa_family].af_format)(from));
  199.                 badfrom = *from;
  200.             }
  201.             return;
  202.         }
  203.         size -= 4 * sizeof (char);
  204.         n = rip->rip_nets;
  205.         for (; size > 0; size -= sizeof (struct netinfo), n++) {
  206.             if (size < sizeof (struct netinfo))
  207.                 break;
  208. #if BSD < 198810
  209.             if (sizeof(n->rip_dst.sa_family) > 1)    /* XXX */
  210.                 n->rip_dst.sa_family =
  211.                     ntohs(n->rip_dst.sa_family);
  212. #else
  213.                 n->rip_dst.sa_family =
  214.                     ntohs(osa(n->rip_dst)->sa_family);
  215.                 n->rip_dst.sa_len = sizeof(n->rip_dst);
  216. #endif
  217.             n->rip_metric = ntohl(n->rip_metric);
  218.             if (n->rip_dst.sa_family >= af_max ||
  219.                 (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
  220.                 (int (*)())0) {
  221.                 syslog(LOG_INFO,
  222.         "route in unsupported address family (%d), from %s (af %d)\n",
  223.                    n->rip_dst.sa_family,
  224.                    (*afswitch[from->sa_family].af_format)(from),
  225.                    from->sa_family);
  226.                 continue;
  227.             }
  228.             if (((*afp->af_checkhost)(&n->rip_dst)) == 0) {
  229.                 syslog(LOG_DEBUG,
  230.                     "bad host in route from %s (af %d)\n",
  231.                    (*afswitch[from->sa_family].af_format)(from),
  232.                    from->sa_family);
  233.                 continue;
  234.             }
  235.             if (n->rip_metric == 0 ||
  236.                 (unsigned) n->rip_metric > HOPCNT_INFINITY) {
  237.                 if (bcmp((char *)from, (char *)&badfrom2,
  238.                     sizeof(badfrom2)) != 0) {
  239.                     syslog(LOG_ERR,
  240.                         "bad metric (%d) from %s\n",
  241.                         n->rip_metric,
  242.                   (*afswitch[from->sa_family].af_format)(from));
  243.                     badfrom2 = *from;
  244.                 }
  245.                 continue;
  246.             }
  247.             /*
  248.              * Adjust metric according to incoming interface.
  249.              */
  250.             if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
  251.                 n->rip_metric += ifp->int_metric;
  252.             if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
  253.                 n->rip_metric = HOPCNT_INFINITY;
  254.             rt = rtlookup(&n->rip_dst);
  255.             if (rt == 0 ||
  256.                 (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
  257.                 (RTS_INTERNAL|RTS_INTERFACE)) {
  258.                 /*
  259.                  * If we're hearing a logical network route
  260.                  * back from a peer to which we sent it,
  261.                  * ignore it.
  262.                  */
  263.                 if (rt && rt->rt_state & RTS_SUBNET &&
  264.                     (*afp->af_sendroute)(rt, from))
  265.                     continue;
  266.                 if ((unsigned)n->rip_metric < HOPCNT_INFINITY) {
  267.                     /*
  268.                      * Look for an equivalent route that
  269.                      * includes this one before adding
  270.                      * this route.
  271.                      */
  272.                     rt = rtfind(&n->rip_dst);
  273.                     if (rt && equal(from, &rt->rt_router))
  274.                         continue;
  275.                     rtadd(&n->rip_dst, from, n->rip_metric, 0);
  276.                     changes++;
  277.                 }
  278.                 continue;
  279.             }
  280.  
  281.             /*
  282.              * Update if from gateway and different,
  283.              * shorter, or equivalent but old route
  284.              * is getting stale.
  285.              */
  286.             if (equal(from, &rt->rt_router)) {
  287.                 if (n->rip_metric != rt->rt_metric) {
  288.                     rtchange(rt, from, n->rip_metric);
  289.                     changes++;
  290.                     rt->rt_timer = 0;
  291.                     if (rt->rt_metric >= HOPCNT_INFINITY)
  292.                         rt->rt_timer =
  293.                             GARBAGE_TIME - EXPIRE_TIME;
  294.                 } else if (rt->rt_metric < HOPCNT_INFINITY)
  295.                     rt->rt_timer = 0;
  296.             } else if ((unsigned) n->rip_metric < rt->rt_metric ||
  297.                 (rt->rt_metric == n->rip_metric &&
  298.                 rt->rt_timer > (EXPIRE_TIME/2) &&
  299.                 (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
  300.                 rtchange(rt, from, n->rip_metric);
  301.                 changes++;
  302.                 rt->rt_timer = 0;
  303.             }
  304.         }
  305.         break;
  306.     }
  307.  
  308.     /*
  309.      * If changes have occurred, and if we have not sent a broadcast
  310.      * recently, send a dynamic update.  This update is sent only
  311.      * on interfaces other than the one on which we received notice
  312.      * of the change.  If we are within MIN_WAITTIME of a full update,
  313.      * don't bother sending; if we just sent a dynamic update
  314.      * and set a timer (nextbcast), delay until that time.
  315.      * If we just sent a full update, delay the dynamic update.
  316.      * Set a timer for a randomized value to suppress additional
  317.      * dynamic updates until it expires; if we delayed sending
  318.      * the current changes, set needupdate.
  319.      */
  320.     if (changes && supplier &&
  321.        now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) {
  322.         u_long delay;
  323.         extern long random();
  324.  
  325.         if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME &&
  326.             timercmp(&nextbcast, &now, <)) {
  327.             if (traceactions)
  328.                 fprintf(ftrace, "send dynamic update\n");
  329.             toall(supply, RTS_CHANGED, ifp);
  330.             lastbcast = now;
  331.             needupdate = 0;
  332.             nextbcast.tv_sec = 0;
  333.         } else {
  334.             needupdate++;
  335.             if (traceactions)
  336.                 fprintf(ftrace, "delay dynamic update\n");
  337.         }
  338. #define RANDOMDELAY()    (MIN_WAITTIME * 1000000 + \
  339.         (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
  340.  
  341.         if (nextbcast.tv_sec == 0) {
  342.             delay = RANDOMDELAY();
  343.             if (traceactions)
  344.                 fprintf(ftrace,
  345.                     "inhibit dynamic update for %d usec\n",
  346.                     delay);
  347.             nextbcast.tv_sec = delay / 1000000;
  348.             nextbcast.tv_usec = delay % 1000000;
  349.             timevaladd(&nextbcast, &now);
  350.             /*
  351.              * If the next possibly dynamic update
  352.              * is within MIN_WAITTIME of the next full update,
  353.              * force the delay past the full update,
  354.              * or we might send a dynamic update just before
  355.              * the full update.
  356.              */
  357.             if (nextbcast.tv_sec > lastfullupdate.tv_sec +
  358.                 SUPPLY_INTERVAL - MIN_WAITTIME)
  359.                 nextbcast.tv_sec = lastfullupdate.tv_sec +
  360.                     SUPPLY_INTERVAL + 1;
  361.         }
  362.     }
  363. }
  364.