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