careful about deleting route to interface in addrouteforif
[unix-history] / usr / src / sbin / routed / main.c
index 263e9e5..b605783 100644 (file)
@@ -1,21 +1,26 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)main.c     4.1 %G%";
+static char sccsid[] = "@(#)main.c     4.11 (Berkeley) %G%";
 #endif
 
 /*
  * Routing Table Management Daemon
  */
 #endif
 
 /*
  * Routing Table Management Daemon
  */
-#include "router.h"
+#include "defs.h"
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
+#include <sys/time.h>
+
 #include <net/if.h>
 #include <net/if.h>
+
 #include <errno.h>
 #include <nlist.h>
 #include <signal.h>
 #include <errno.h>
 #include <nlist.h>
 #include <signal.h>
-#include <time.h>
+#include <syslog.h>
 
 int    supplier = -1;          /* process should supply updates */
 
 int    supplier = -1;          /* process should supply updates */
+extern int gateway;
 
 struct rip *msg = (struct rip *)packet;
 
 struct rip *msg = (struct rip *)packet;
+int    hup();
 
 main(argc, argv)
        int argc;
 
 main(argc, argv)
        int argc;
@@ -23,79 +28,90 @@ main(argc, argv)
 {
        int cc;
        struct sockaddr from;
 {
        int cc;
        struct sockaddr from;
+       u_char retry;
+#ifdef COMPAT
+       int snoroute;
+#endif
        
        argv0 = argv;
        
        argv0 = argv;
-#ifndef DEBUG
-       if (fork())
-               exit(0);
-       for (cc = 0; cc < 10; cc++)
-               (void) close(cc);
-       (void) open("/", 0);
-       (void) dup2(0, 1);
-       (void) dup2(0, 2);
-       { int t = open("/dev/tty", 2);
-         if (t >= 0) {
-               ioctl(t, TIOCNOTTY, (char *)0);
-               (void) close(t);
-         }
-       }
-#endif
-       if (tracing)
-               traceon("/etc/routerlog");
-
-       /*
-        * We use two sockets.  One for which outgoing
-        * packets are routed and for which they're not.
-        * The latter allows us to delete routing table
-        * entries in the kernel for network interfaces
-        * attached to our host which we believe are down
-        * while still polling it to see when/if it comes
-        * back up.  With the new ipc interface we'll be
-        * able to specify ``don't route'' as an option
-        * to send, but until then we utilize a second port.
-        */
+       openlog("routed", LOG_PID, 0);
        sp = getservbyname("router", "udp");
        sp = getservbyname("router", "udp");
-       if (sp == 0) {
-               fprintf(stderr, "routed: udp/router: unknown service\n");
+       if (sp == NULL) {
+               fprintf(stderr, "routed: router/udp: unknown service\n");
                exit(1);
        }
                exit(1);
        }
-       routingaddr.sin_family = AF_INET;
-       routingaddr.sin_port = htons(sp->s_port);
-       noroutingaddr.sin_family = AF_INET;
-       noroutingaddr.sin_port = htons(sp->s_port + 1);
-again:
-       s = socket(SOCK_DGRAM, 0, &routingaddr, 0);
-       if (s < 0) {
-               perror("socket");
-               sleep(30);
-               goto again;
-       }
-again2:
-       snoroute = socket(SOCK_DGRAM, 0, &noroutingaddr, SO_DONTROUTE);
-       if (snoroute < 0) {
-               perror("socket");
-               sleep(30);
-               goto again2;
-       }
+       addr.sin_family = AF_INET;
+       addr.sin_port = sp->s_port;
+       s = getsocket(AF_INET, SOCK_DGRAM, &addr);
+       if (s < 0)
+               exit(1);
+#ifdef COMPAT
+       bzero(&addr, sizeof (addr));
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(ntohs(sp->s_port) + 1);
+       snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr);
+       if (snoroute < 0)
+               exit(1);
+#endif
        argv++, argc--;
        while (argc > 0 && **argv == '-') {
        argv++, argc--;
        while (argc > 0 && **argv == '-') {
-               if (!strcmp(*argv, "-s") == 0) {
+               if (strcmp(*argv, "-s") == 0) {
                        supplier = 1;
                        argv++, argc--;
                        continue;
                }
                        supplier = 1;
                        argv++, argc--;
                        continue;
                }
-               if (!strcmp(*argv, "-q") == 0) {
+               if (strcmp(*argv, "-q") == 0) {
                        supplier = 0;
                        argv++, argc--;
                        continue;
                }
                        supplier = 0;
                        argv++, argc--;
                        continue;
                }
-               goto usage;
-       }
-       if (argc > 0) {
-usage:
-               fprintf(stderr, "usage: routed [ -s ] [ -q ]\n");
+               if (strcmp(*argv, "-t") == 0) {
+                       tracepackets++;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-g") == 0) {
+                       gateway = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-l") == 0) {
+                       gateway = -1;
+                       argv++, argc--;
+                       continue;
+               }
+               fprintf(stderr,
+                       "usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
                exit(1);
        }
                exit(1);
        }
+#ifndef DEBUG
+       if (!tracepackets) {
+               int t;
+
+               if (fork())
+                       exit(0);
+               for (t = 0; t < 20; t++)
+                       if (t != s)
+#ifdef COMPAT
+                               if (t != snoroute)
+#endif
+                               (void) close(cc);
+               (void) open("/", 0);
+               (void) dup2(0, 1);
+               (void) dup2(0, 2);
+               t = open("/dev/tty", 2);
+               if (t >= 0) {
+                       ioctl(t, TIOCNOTTY, (char *)0);
+                       (void) close(t);
+               }
+       }
+#endif
+       /*
+        * Any extra argument is considered
+        * a tracing log file.
+        */
+       if (argc > 0)
+               traceon(*argv);
        /*
         * Collect an initial view of the world by
         * snooping in the kernel and the gateway kludge
        /*
         * Collect an initial view of the world by
         * snooping in the kernel and the gateway kludge
@@ -109,41 +125,86 @@ usage:
        if (supplier < 0)
                supplier = 0;
        msg->rip_cmd = RIPCMD_REQUEST;
        if (supplier < 0)
                supplier = 0;
        msg->rip_cmd = RIPCMD_REQUEST;
+       msg->rip_vers = RIPVERSION;
        msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
        msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
        msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
        msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
+       msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
+       msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
        toall(sendmsg);
        toall(sendmsg);
-       sigset(SIGALRM, timer);
+       signal(SIGALRM, timer);
+       signal(SIGHUP, hup);
+       signal(SIGTERM, hup);
        timer();
 
        timer();
 
-#define        INFINITY        1000000
        for (;;) {
                int ibits;
                register int n;
 
        for (;;) {
                int ibits;
                register int n;
 
-               ibits = (1 << s) | (1 << snoroute);
-               n = select(32, &ibits, 0, INFINITY);
+               ibits = 1 << s;
+#ifdef COMPAT
+               ibits |= 1 << snoroute;
+#endif
+               n = select(20, &ibits, 0, 0, 0);
                if (n < 0)
                        continue;
                if (ibits & (1 << s))
                        process(s);
                if (n < 0)
                        continue;
                if (ibits & (1 << s))
                        process(s);
+#ifdef COMPAT
                if (ibits & (1 << snoroute))
                        process(snoroute);
                if (ibits & (1 << snoroute))
                        process(snoroute);
+#endif
+               /* handle ICMP redirects */
        }
 }
 
 process(fd)
        int fd;
 {
        }
 }
 
 process(fd)
        int fd;
 {
-       register int cc;
        struct sockaddr from;
        struct sockaddr from;
+       int fromlen = sizeof (from), cc, omask;
 
 
-       cc = receive(fd, &from, packet, sizeof (packet));
+       cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
        if (cc <= 0) {
                if (cc < 0 && errno != EINTR)
        if (cc <= 0) {
                if (cc < 0 && errno != EINTR)
-                       perror("receive");
+                       perror("recvfrom");
                return;
        }
                return;
        }
-       sighold(SIGALRM);
+       if (fromlen != sizeof (struct sockaddr_in))
+               return;
+#define        mask(s) (1<<((s)-1))
+       omask = sigblock(mask(SIGALRM));
        rip_input(&from, cc);
        rip_input(&from, cc);
-       sigrelse(SIGALRM);
+       sigsetmask(omask);
+}
+
+getsocket(domain, type, sin)
+       int domain, type;
+       struct sockaddr_in *sin;
+{
+       int retry, s, on = 1;
+
+       retry = 1;
+       while ((s = socket(domain, type, 0, 0)) < 0 && retry) {
+               perror("socket");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0) {
+               syslog(LOG_ERR, "socket: %m");
+               return (-1);
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+               syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+               exit(1);
+       }
+       while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) {
+               perror("bind");
+               sleep(5 * retry);
+               retry <<= 1;
+       }
+       if (retry == 0) {
+               syslog(LOG_ERR, "bind: %m");
+               return (-1);
+       }
+       return (s);
 }
 }