home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / routed / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  11.5 KB  |  363 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[] = "@(#)input.c    5.22 (Berkeley) 6/1/90";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Routing Table Management Daemon
  40.  */
  41. #include "defs.h"
  42. #include <sys/syslog.h>
  43.  
  44. /*
  45.  * Process a newly received packet.
  46.  */
  47. rip_input(from, rip, size)
  48.     struct sockaddr *from;
  49.     register struct rip *rip;
  50.     int size;
  51. {
  52.     register struct rt_entry *rt;
  53.     register struct netinfo *n;
  54.     register struct interface *ifp;
  55.     struct interface *if_ifwithdstaddr();
  56.     int count, changes = 0;
  57.     register struct afswitch *afp;
  58.     static struct sockaddr badfrom, badfrom2;
  59.  
  60.     ifp = 0;
  61.     TRACE_INPUT(ifp, from, (char *)rip, size);
  62.     if (from->sa_family >= af_max ||
  63.         (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) {
  64.         syslog(LOG_INFO,
  65.      "\"from\" address in unsupported address family (%d), cmd %d\n",
  66.             from->sa_family, rip->rip_cmd);
  67.         return;
  68.     }
  69.     if (rip->rip_vers == 0) {
  70.         syslog(LOG_ERR,
  71.             "RIP version 0 packet received from %s! (cmd %d)",
  72.             (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd);
  73.         return;
  74.     }
  75.     switch (rip->rip_cmd) {
  76.  
  77.     case RIPCMD_REQUEST:
  78.         n = rip->rip_nets;
  79.         count = size - ((char *)n - (char *)rip);
  80.         if (count < sizeof (struct netinfo))
  81.             return;
  82.         for (; count > 0; n++) {
  83.             if (count < sizeof (struct netinfo))
  84.                 break;
  85.             count -= sizeof (struct netinfo);
  86.  
  87. #if BSD < 198810
  88.             if (sizeof(n->rip_dst.sa_family) > 1)    /* XXX */
  89.                 n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
  90. #else
  91. #define osa(x) ((struct osockaddr *)(&(x)))
  92.                 n->rip_dst.sa_family =
  93.                     ntohs(osa(n->rip_dst)->sa_family);
  94.                 n->rip_dst.sa_len = sizeof(n->rip_dst);
  95. #endif
  96.             n->rip_metric = ntohl(n->rip_metric);
  97.             /* 
  98.              * A single entry with sa_family == AF_UNSPEC and
  99.              * metric ``infinity'' means ``all routes''.
  100.              * We respond to routers only if we are acting
  101.              * as a supplier, or to anyone other than a router
  102.              * (eg, query).
  103.              */
  104.             if (n->rip_dst.sa_family == AF_UNSPEC &&
  105.                 n->rip_metric == HOPCNT_INFINITY && count == 0) {
  106.                     if (supplier || (*afp->af_portmatch)(from) == 0)
  107.                     supply(from, 0, 0, 0);
  108.                 return;
  109.             }
  110.             if (n->rip_dst.sa_family < af_max &&
  111.                 afswitch[n->rip_dst.sa_family].af_hash)
  112.                 rt = rtlookup(&n->rip_dst);
  113.             else
  114.                 rt = 0;
  115. #define min(a, b) (a < b ? a : b)
  116.             n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
  117.                 min(rt->rt_metric + 1, HOPCNT_INFINITY);
  118. #if BSD < 198810
  119.             if (sizeof(n->rip_dst.sa_family) > 1)    /* XXX */
  120.                 n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
  121. #else
  122.                 osa(n->rip_dst)->sa_family =
  123.                         htons(n->rip_dst.sa_family);
  124. #endif
  125.             n->rip_metric = htonl(n->rip_metric);
  126.         }
  127.         rip->rip_cmd = RIPCMD_RESPONSE;
  128.         bcopy((char *)rip, packet, size);
  129.         (*afp->af_output)(s, 0, from, size);
  130.         return;
  131.  
  132.     case RIPCMD_TRACEON:
  133.     case RIPCMD_TRACEOFF:
  134.         /* verify message came from a privileged port */
  135.         if ((*afp->af_portcheck)(from) == 0)
  136.             return;
  137.         if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
  138.             (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
  139.             ifp->int_flags & IFF_PASSIVE) {
  140.             syslog(LOG_ERR, "trace command from unknown router, %s",
  141.                 (*afswitch[from->sa_family].af_format)(from));
  142.             return;
  143.         }
  144.         ((char *)rip)[size] = '\0';
  145.         if (rip->rip_cmd == RIPCMD_TRACEON)
  146.             traceon(rip->rip_tracefile);
  147.         else
  148.             traceoff();
  149.         return;
  150.  
  151.     case RIPCMD_RESPONSE:
  152.         /* verify message came from a router */
  153.         if ((*afp->af_portmatch)(from) == 0)
  154.             return;
  155.         (*afp->af_canon)(from);
  156.         /* are we talking to ourselves? */
  157.         ifp = if_ifwithaddr(from);
  158.         if (ifp) {
  159.             if (ifp->int_flags & IFF_PASSIVE) {
  160.                 syslog(LOG_ERR,
  161.                   "bogus input (from passive interface, %s)",
  162.                   (*afswitch[from->sa_family].af_format)(from));
  163.                 return;
  164.             }
  165.             rt = rtfind(from);
  166.             if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) &&
  167.                 rt->rt_metric >= ifp->int_metric) 
  168.                 addrouteforif(ifp);
  169.             else
  170.                 rt->rt_timer = 0;
  171.             return;
  172.         }
  173.         /*
  174.          * Update timer for interface on which the packet arrived.
  175.          * If from other end of a point-to-point link that isn't
  176.          * in the routing tables, (re-)add the route.
  177.          */
  178.         if ((rt = rtfind(from)) &&
  179.             (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
  180.             rt->rt_timer = 0;
  181.         else if ((ifp = if_ifwithdstaddr(from)) &&
  182.             (rt == 0 || rt->rt_metric >= ifp->int_metric))
  183.             addrouteforif(ifp);
  184.         /*
  185.          * "Authenticate" router from which message originated.
  186.          * We accept routing packets from routers directly connected
  187.          * via broadcast or point-to-point networks,
  188.          * and from those listed in /etc/gateways.
  189.          */
  190.         if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
  191.             (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
  192.             ifp->int_flags & IFF_PASSIVE) {
  193.             if (bcmp((char *)from, (char *)&badfrom,
  194.                 sizeof(badfrom)) != 0) {
  195.                 syslog(LOG_ERR,
  196.                   "packet from unknown router, %s",
  197.                   (*afswitch[from->sa_family].af_format)(from));
  198.                 badfrom = *from;
  199.             }
  200.             return;
  201.         }
  202.         size -= 4 * sizeof (char);
  203.         n = rip->rip_nets;
  204.         for (; size > 0; size -= sizeof (struct netinfo), n++) {
  205.             if (size < sizeof (struct netinfo))
  206.                 break;
  207. #if BSD < 198810
  208.             if (sizeof(n->rip_dst.sa_family) > 1)    /* XXX */
  209.                 n->rip_dst.sa_family =
  210.                     ntohs(n->rip_dst.sa_family);
  211. #else
  212.                 n->rip_dst.sa_family =
  213.                     ntohs(osa(n->rip_dst)->sa_family);
  214.                 n->rip_dst.sa_len = sizeof(n->rip_dst);
  215. #endif
  216.             n->rip_metric = ntohl(n->rip_metric);
  217.             if (n->rip_dst.sa_family >= af_max ||
  218.                 (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
  219.                 (int (*)())0) {
  220.                 syslog(LOG_INFO,
  221.         "route in unsupported address family (%d), from %s (af %d)\n",
  222.                    n->rip_dst.sa_family,
  223.                    (*afswitch[from->sa_family].af_format)(from),
  224.                    from->sa_family);
  225.                 continue;
  226.             }
  227.             if (((*afp->af_checkhost)(&n->rip_dst)) == 0) {
  228.                 syslog(LOG_DEBUG,
  229.                     "bad host in route from %s (af %d)\n",
  230.                    (*afswitch[from->sa_family].af_format)(from),
  231.                    from->sa_family);
  232.                 continue;
  233.             }
  234.             if (n->rip_metric == 0 ||
  235.                 (unsigned) n->rip_metric > HOPCNT_INFINITY) {
  236.                 if (bcmp((char *)from, (char *)&badfrom2,
  237.                     sizeof(badfrom2)) != 0) {
  238.                     syslog(LOG_ERR,
  239.                         "bad metric (%d) from %s\n",
  240.                         n->rip_metric,
  241.                   (*afswitch[from->sa_family].af_format)(from));
  242.                     badfrom2 = *from;
  243.                 }
  244.                 continue;
  245.             }
  246.             /*
  247.              * Adjust metric according to incoming interface.
  248.              */
  249.             if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
  250.                 n->rip_metric += ifp->int_metric;
  251.             if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
  252.                 n->rip_metric = HOPCNT_INFINITY;
  253.             rt = rtlookup(&n->rip_dst);
  254.             if (rt == 0 ||
  255.                 (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
  256.                 (RTS_INTERNAL|RTS_INTERFACE)) {
  257.                 /*
  258.                  * If we're hearing a logical network route
  259.                  * back from a peer to which we sent it,
  260.                  * ignore it.
  261.                  */
  262.                 if (rt && rt->rt_state & RTS_SUBNET &&
  263.                     (*afp->af_sendroute)(rt, from))
  264.                     continue;
  265.                 if ((unsigned)n->rip_metric < HOPCNT_INFINITY) {
  266.                     /*
  267.                      * Look for an equivalent route that
  268.                      * includes this one before adding
  269.                      * this route.
  270.                      */
  271.                     rt = rtfind(&n->rip_dst);
  272.                     if (rt && equal(from, &rt->rt_router))
  273.                         continue;
  274.                     rtadd(&n->rip_dst, from, n->rip_metric, 0);
  275.                     changes++;
  276.                 }
  277.                 continue;
  278.             }
  279.  
  280.             /*
  281.              * Update if from gateway and different,
  282.              * shorter, or equivalent but old route
  283.              * is getting stale.
  284.              */
  285.             if (equal(from, &rt->rt_router)) {
  286.                 if (n->rip_metric != rt->rt_metric) {
  287.                     rtchange(rt, from, n->rip_metric);
  288.                     changes++;
  289.                     rt->rt_timer = 0;
  290.                     if (rt->rt_metric >= HOPCNT_INFINITY)
  291.                         rt->rt_timer =
  292.                             GARBAGE_TIME - EXPIRE_TIME;
  293.                 } else if (rt->rt_metric < HOPCNT_INFINITY)
  294.                     rt->rt_timer = 0;
  295.             } else if ((unsigned) n->rip_metric < rt->rt_metric ||
  296.                 (rt->rt_metric == n->rip_metric &&
  297.                 rt->rt_timer > (EXPIRE_TIME/2) &&
  298.                 (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
  299.                 rtchange(rt, from, n->rip_metric);
  300.                 changes++;
  301.                 rt->rt_timer = 0;
  302.             }
  303.         }
  304.         break;
  305.     }
  306.  
  307.     /*
  308.      * If changes have occurred, and if we have not sent a broadcast
  309.      * recently, send a dynamic update.  This update is sent only
  310.      * on interfaces other than the one on which we received notice
  311.      * of the change.  If we are within MIN_WAITTIME of a full update,
  312.      * don't bother sending; if we just sent a dynamic update
  313.      * and set a timer (nextbcast), delay until that time.
  314.      * If we just sent a full update, delay the dynamic update.
  315.      * Set a timer for a randomized value to suppress additional
  316.      * dynamic updates until it expires; if we delayed sending
  317.      * the current changes, set needupdate.
  318.      */
  319.     if (changes && supplier &&
  320.        now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) {
  321.         u_long delay;
  322.         extern long random();
  323.  
  324.         if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME &&
  325.             timercmp(&nextbcast, &now, <)) {
  326.             if (traceactions)
  327.                 fprintf(ftrace, "send dynamic update\n");
  328.             toall(supply, RTS_CHANGED, ifp);
  329.             lastbcast = now;
  330.             needupdate = 0;
  331.             nextbcast.tv_sec = 0;
  332.         } else {
  333.             needupdate++;
  334.             if (traceactions)
  335.                 fprintf(ftrace, "delay dynamic update\n");
  336.         }
  337. #define RANDOMDELAY()    (MIN_WAITTIME * 1000000 + \
  338.         (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
  339.  
  340.         if (nextbcast.tv_sec == 0) {
  341.             delay = RANDOMDELAY();
  342.             if (traceactions)
  343.                 fprintf(ftrace,
  344.                     "inhibit dynamic update for %d usec\n",
  345.                     delay);
  346.             nextbcast.tv_sec = delay / 1000000;
  347.             nextbcast.tv_usec = delay % 1000000;
  348.             timevaladd(&nextbcast, &now);
  349.             /*
  350.              * If the next possibly dynamic update
  351.              * is within MIN_WAITTIME of the next full update,
  352.              * force the delay past the full update,
  353.              * or we might send a dynamic update just before
  354.              * the full update.
  355.              */
  356.             if (nextbcast.tv_sec > lastfullupdate.tv_sec +
  357.                 SUPPLY_INTERVAL - MIN_WAITTIME)
  358.                 nextbcast.tv_sec = lastfullupdate.tv_sec +
  359.                     SUPPLY_INTERVAL + 1;
  360.         }
  361.     }
  362. }
  363.