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 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-23  |  8.8 KB  |  345 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. char copyright[] =
  36. "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. /*static char sccsid[] = "from: @(#)main.c    5.23 (Berkeley) 7/1/91";*/
  42. static char rcsid[] = "$Id: main.c,v 1.1 1994/05/23 09:08:11 rzsfl Exp rzsfl $";
  43. #endif /* not lint */
  44.  
  45. /*
  46.  * Routing Table Management Daemon
  47.  */
  48. #include "defs.h"
  49. #include <sys/ioctl.h>
  50. #include <sys/file.h>
  51.  
  52. #include <net/if.h>
  53.  
  54. #include <sys/errno.h>
  55. #include <sys/signal.h>
  56. #include <sys/syslog.h>
  57. #include "pathnames.h"
  58.  
  59. int    supplier = -1;        /* process should supply updates */
  60. int    gateway = 0;        /* 1 if we are a gateway to parts beyond */
  61. int    debug = 0;
  62. int    bufspace = 127*1024;    /* max. input buffer size to request */
  63.  
  64. struct    rip *msg = (struct rip *)packet;
  65. void    hup(), rtdeleteall(), sigtrace(), timer();
  66.  
  67. main(argc, argv)
  68.     int argc;
  69.     char *argv[];
  70. {
  71.     int n, cc, nfd, omask, tflags = 0;
  72.     struct sockaddr from;
  73.     struct timeval *tvp, waittime;
  74.     struct itimerval itval;
  75.     register struct rip *query = msg;
  76.     fd_set ibits;
  77.     u_char retry;
  78.     
  79.     argv0 = argv;
  80. #if BSD >= 43 || defined(__linux__)
  81.     openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
  82.     setlogmask(LOG_UPTO(LOG_WARNING));
  83. #else
  84.     openlog("routed", LOG_PID);
  85. #define LOG_UPTO(x) (x)
  86. #define setlogmask(x) (x)
  87. #endif
  88.     sp = getservbyname("router", "udp");
  89.     if (sp == NULL) {
  90.         fprintf(stderr, "routed: router/udp: unknown service\n");
  91.         exit(1);
  92.     }
  93.     addr.sin_family = AF_INET;
  94.     addr.sin_port = sp->s_port;
  95.     s = getsocket(AF_INET, SOCK_DGRAM, &addr);
  96.     if (s < 0)
  97.         exit(1);
  98.     argv++, argc--;
  99.     while (argc > 0 && **argv == '-') {
  100.         if (strcmp(*argv, "-s") == 0) {
  101.             supplier = 1;
  102.             argv++, argc--;
  103.             continue;
  104.         }
  105.         if (strcmp(*argv, "-q") == 0) {
  106.             supplier = 0;
  107.             argv++, argc--;
  108.             continue;
  109.         }
  110.         if (strcmp(*argv, "-t") == 0) {
  111.             tflags++;
  112.             setlogmask(LOG_UPTO(LOG_DEBUG));
  113.             argv++, argc--;
  114.             continue;
  115.         }
  116.         if (strcmp(*argv, "-d") == 0) {
  117.             debug++;
  118.             setlogmask(LOG_UPTO(LOG_DEBUG));
  119.             argv++, argc--;
  120.             continue;
  121.         }
  122.         if (strcmp(*argv, "-g") == 0) {
  123.             gateway = 1;
  124.             argv++, argc--;
  125.             continue;
  126.         }
  127.         fprintf(stderr,
  128.             "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
  129.         exit(1);
  130.     }
  131.  
  132.     if (debug == 0)
  133.         daemon(0, 0);
  134.     /*
  135.      * Any extra argument is considered
  136.      * a tracing log file.
  137.      */
  138.     if (argc > 0)
  139.         traceon(*argv);
  140.     while (tflags-- > 0)
  141.         bumploglevel();
  142.  
  143.     (void) gettimeofday(&now, (struct timezone *)NULL);
  144.     /*
  145.      * Collect an initial view of the world by
  146.      * checking the interface configuration and the gateway kludge
  147.      * file.  Then, send a request packet on all
  148.      * directly connected networks to find out what
  149.      * everyone else thinks.
  150.      */
  151.     rtinit();
  152.     ifinit();
  153.     gwkludge();
  154.     if (gateway > 0)
  155.         rtdefault();
  156.     if (supplier < 0)
  157.         supplier = 0;
  158.     query->rip_cmd = RIPCMD_REQUEST;
  159.     query->rip_vers = RIPVERSION;
  160.     if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1)    /* XXX */
  161.         query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC);
  162.     else
  163.         query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
  164.     query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
  165.     toall(sndmsg);
  166.     signal(SIGALRM, timer);
  167.     signal(SIGHUP, hup);
  168.     signal(SIGTERM, hup);
  169.     signal(SIGINT, rtdeleteall);
  170.     signal(SIGUSR1, sigtrace);
  171.     signal(SIGUSR2, sigtrace);
  172.     itval.it_interval.tv_sec = TIMER_RATE;
  173.     itval.it_value.tv_sec = TIMER_RATE;
  174.     itval.it_interval.tv_usec = 0;
  175.     itval.it_value.tv_usec = 0;
  176.     srandom(getpid());
  177.     if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
  178.         syslog(LOG_ERR, "setitimer: %m\n");
  179.  
  180.     FD_ZERO(&ibits);
  181.     nfd = s + 1;            /* 1 + max(fd's) */
  182.     for (;;) {
  183.         FD_SET(s, &ibits);
  184.         /*
  185.          * If we need a dynamic update that was held off,
  186.          * needupdate will be set, and nextbcast is the time
  187.          * by which we want select to return.  Compute time
  188.          * until dynamic update should be sent, and select only
  189.          * until then.  If we have already passed nextbcast,
  190.          * just poll.
  191.          */
  192.         if (needupdate) {
  193.             waittime = nextbcast;
  194.             timevalsub(&waittime, &now);
  195.             if (waittime.tv_sec < 0) {
  196.                 waittime.tv_sec = 0;
  197.                 waittime.tv_usec = 0;
  198.             }
  199.             if (traceactions)
  200.                 fprintf(ftrace,
  201.                  "select until dynamic update %d/%d sec/usec\n",
  202.                     waittime.tv_sec, waittime.tv_usec);
  203.             tvp = &waittime;
  204.         } else
  205.             tvp = (struct timeval *)NULL;
  206.         n = select(nfd, &ibits, 0, 0, tvp);
  207.         if (n <= 0) {
  208.             /*
  209.              * Need delayed dynamic update if select returned
  210.              * nothing and we timed out.  Otherwise, ignore
  211.              * errors (e.g. EINTR).
  212.              */
  213.             if (n < 0) {
  214.                 if (errno == EINTR)
  215.                     continue;
  216.                 syslog(LOG_ERR, "select: %m");
  217.             }
  218.             omask = sigblock(sigmask(SIGALRM));
  219.             if (n == 0 && needupdate) {
  220.                 if (traceactions)
  221.                     fprintf(ftrace,
  222.                         "send delayed dynamic update\n");
  223.                 (void) gettimeofday(&now,
  224.                         (struct timezone *)NULL);
  225.                 toall(supply, RTS_CHANGED,
  226.                     (struct interface *)NULL);
  227.                 lastbcast = now;
  228.                 needupdate = 0;
  229.                 nextbcast.tv_sec = 0;
  230.             }
  231.             sigsetmask(omask);
  232.             continue;
  233.         }
  234.         (void) gettimeofday(&now, (struct timezone *)NULL);
  235.         omask = sigblock(sigmask(SIGALRM));
  236. #ifdef doesntwork
  237. /*
  238. printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
  239.     s,
  240.     ibits.fds_bits[0],
  241.     (s)/(sizeof(fd_mask) * 8),
  242.     ((s) % (sizeof(fd_mask) * 8)),
  243.     (1 << ((s) % (sizeof(fd_mask) * 8))),
  244.     ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
  245.     &ibits
  246.     );
  247. */
  248.         if (FD_ISSET(s, &ibits))
  249. #else
  250.         if (ibits.fds_bits[s/32] & (1 << s))
  251. #endif
  252.             process(s);
  253.         /* handle ICMP redirects */
  254.         sigsetmask(omask);
  255.     }
  256. }
  257.  
  258. timevaladd(t1, t2)
  259.     struct timeval *t1, *t2;
  260. {
  261.  
  262.     t1->tv_sec += t2->tv_sec;
  263.     if ((t1->tv_usec += t2->tv_usec) > 1000000) {
  264.         t1->tv_sec++;
  265.         t1->tv_usec -= 1000000;
  266.     }
  267. }
  268.  
  269. timevalsub(t1, t2)
  270.     struct timeval *t1, *t2;
  271. {
  272.  
  273.     t1->tv_sec -= t2->tv_sec;
  274.     if ((t1->tv_usec -= t2->tv_usec) < 0) {
  275.         t1->tv_sec--;
  276.         t1->tv_usec += 1000000;
  277.     }
  278. }
  279.  
  280. process(fd)
  281.     int fd;
  282. {
  283.     struct sockaddr from;
  284.     int fromlen, cc;
  285.     union {
  286.         char    buf[MAXPACKETSIZE+1];
  287.         struct    rip rip;
  288.     } inbuf;
  289.  
  290.     for (;;) {
  291.         fromlen = sizeof (from);
  292.         cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
  293.         if (cc <= 0) {
  294.             if (cc < 0 && errno != EWOULDBLOCK)
  295.                 perror("recvfrom");
  296.             break;
  297.         }
  298.         if (fromlen != sizeof (struct sockaddr_in))
  299.             break;
  300.         rip_input(&from, &inbuf.rip, cc);
  301.     }
  302. }
  303.  
  304. getsocket(domain, type, sin)
  305.     int domain, type;
  306.     struct sockaddr_in *sin;
  307. {
  308.     int sock, on = 1;
  309.  
  310.     if ((sock = socket(domain, type, 0)) < 0) {
  311.         perror("socket");
  312.         syslog(LOG_ERR, "socket: %m");
  313.         return (-1);
  314.     }
  315. #ifdef SO_BROADCAST
  316.     if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
  317.         syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
  318.         close(sock);
  319.         return (-1);
  320.     }
  321. #endif
  322. #ifdef SO_RCVBUF
  323.     for (on = bufspace; ; on -= 1024) {
  324.         if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
  325.             &on, sizeof (on)) == 0)
  326.             break;
  327.         if (on <= 8*1024) {
  328.             syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
  329.             break;
  330.         }
  331.     }
  332.     if (traceactions)
  333.         fprintf(ftrace, "recv buf %d\n", on);
  334. #endif
  335.     if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
  336.         perror("bind");
  337.         syslog(LOG_ERR, "bind: %m");
  338.         close(sock);
  339.         return (-1);
  340.     }
  341.     if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
  342.         syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
  343.     return (sock);
  344. }
  345.