1 #ifndef lint 2 static char sccsid[] = "@(#)main.c 4.12 (Berkeley) 02/25/85"; 3 #endif 4 5 /* 6 * Routing Table Management Daemon 7 */ 8 #include "defs.h" 9 #include <sys/ioctl.h> 10 #include <sys/time.h> 11 12 #include <net/if.h> 13 14 #include <errno.h> 15 #include <nlist.h> 16 #include <signal.h> 17 #include <syslog.h> 18 19 int supplier = -1; /* process should supply updates */ 20 extern int gateway; 21 22 struct rip *msg = (struct rip *)packet; 23 int hup(); 24 25 main(argc, argv) 26 int argc; 27 char *argv[]; 28 { 29 int cc; 30 struct sockaddr from; 31 u_char retry; 32 33 argv0 = argv; 34 openlog("routed", LOG_PID, 0); 35 sp = getservbyname("router", "udp"); 36 if (sp == NULL) { 37 fprintf(stderr, "routed: router/udp: unknown service\n"); 38 exit(1); 39 } 40 addr.sin_family = AF_INET; 41 addr.sin_port = sp->s_port; 42 s = getsocket(AF_INET, SOCK_DGRAM, &addr); 43 if (s < 0) 44 exit(1); 45 argv++, argc--; 46 while (argc > 0 && **argv == '-') { 47 if (strcmp(*argv, "-s") == 0) { 48 supplier = 1; 49 argv++, argc--; 50 continue; 51 } 52 if (strcmp(*argv, "-q") == 0) { 53 supplier = 0; 54 argv++, argc--; 55 continue; 56 } 57 if (strcmp(*argv, "-t") == 0) { 58 tracepackets++; 59 argv++, argc--; 60 continue; 61 } 62 if (strcmp(*argv, "-g") == 0) { 63 gateway = 1; 64 argv++, argc--; 65 continue; 66 } 67 if (strcmp(*argv, "-l") == 0) { 68 gateway = -1; 69 argv++, argc--; 70 continue; 71 } 72 fprintf(stderr, 73 "usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 74 exit(1); 75 } 76 #ifndef DEBUG 77 if (!tracepackets) { 78 int t; 79 80 if (fork()) 81 exit(0); 82 for (t = 0; t < 20; t++) 83 if (t != s) 84 (void) close(cc); 85 (void) open("/", 0); 86 (void) dup2(0, 1); 87 (void) dup2(0, 2); 88 t = open("/dev/tty", 2); 89 if (t >= 0) { 90 ioctl(t, TIOCNOTTY, (char *)0); 91 (void) close(t); 92 } 93 } 94 #endif 95 /* 96 * Any extra argument is considered 97 * a tracing log file. 98 */ 99 if (argc > 0) 100 traceon(*argv); 101 /* 102 * Collect an initial view of the world by 103 * snooping in the kernel and the gateway kludge 104 * file. Then, send a request packet on all 105 * directly connected networks to find out what 106 * everyone else thinks. 107 */ 108 rtinit(); 109 gwkludge(); 110 ifinit(); 111 if (supplier < 0) 112 supplier = 0; 113 msg->rip_cmd = RIPCMD_REQUEST; 114 msg->rip_vers = RIPVERSION; 115 msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 116 msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 117 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 118 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 119 toall(sendmsg); 120 signal(SIGALRM, timer); 121 signal(SIGHUP, hup); 122 signal(SIGTERM, hup); 123 timer(); 124 125 for (;;) { 126 int ibits; 127 register int n; 128 129 ibits = 1 << s; 130 n = select(20, &ibits, 0, 0, 0); 131 if (n < 0) 132 continue; 133 if (ibits & (1 << s)) 134 process(s); 135 /* handle ICMP redirects */ 136 } 137 } 138 139 process(fd) 140 int fd; 141 { 142 struct sockaddr from; 143 int fromlen = sizeof (from), cc, omask; 144 145 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 146 if (cc <= 0) { 147 if (cc < 0 && errno != EINTR) 148 perror("recvfrom"); 149 return; 150 } 151 if (fromlen != sizeof (struct sockaddr_in)) 152 return; 153 #define mask(s) (1<<((s)-1)) 154 omask = sigblock(mask(SIGALRM)); 155 rip_input(&from, cc); 156 sigsetmask(omask); 157 } 158 159 getsocket(domain, type, sin) 160 int domain, type; 161 struct sockaddr_in *sin; 162 { 163 int retry, s, on = 1; 164 165 retry = 1; 166 while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 167 perror("socket"); 168 sleep(5 * retry); 169 retry <<= 1; 170 } 171 if (retry == 0) { 172 syslog(LOG_ERR, "socket: %m"); 173 return (-1); 174 } 175 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 176 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 177 exit(1); 178 } 179 while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 180 perror("bind"); 181 sleep(5 * retry); 182 retry <<= 1; 183 } 184 if (retry == 0) { 185 syslog(LOG_ERR, "bind: %m"); 186 return (-1); 187 } 188 return (s); 189 } 190