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 are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)main.c 5.14 (Berkeley) 06/18/88"; 26 #endif /* not lint */ 27 28 /* 29 * Routing Table Management Daemon 30 */ 31 #include "defs.h" 32 #include <sys/ioctl.h> 33 #include <sys/time.h> 34 35 #include <net/if.h> 36 37 #include <sys/errno.h> 38 #include <sys/signal.h> 39 #include <sys/syslog.h> 40 41 int supplier = -1; /* process should supply updates */ 42 int gateway = 0; /* 1 if we are a gateway to parts beyond */ 43 int debug = 0; 44 45 struct rip *msg = (struct rip *)packet; 46 int hup(), rtdeleteall(), sigtrace(); 47 48 main(argc, argv) 49 int argc; 50 char *argv[]; 51 { 52 int cc; 53 struct sockaddr from; 54 u_char retry; 55 56 argv0 = argv; 57 openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); 58 setlogmask(LOG_UPTO(LOG_WARNING)); 59 sp = getservbyname("router", "udp"); 60 if (sp == NULL) { 61 fprintf(stderr, "routed: router/udp: unknown service\n"); 62 exit(1); 63 } 64 addr.sin_family = AF_INET; 65 addr.sin_port = sp->s_port; 66 s = getsocket(AF_INET, SOCK_DGRAM, &addr); 67 if (s < 0) 68 exit(1); 69 argv++, argc--; 70 while (argc > 0 && **argv == '-') { 71 if (strcmp(*argv, "-s") == 0) { 72 supplier = 1; 73 argv++, argc--; 74 continue; 75 } 76 if (strcmp(*argv, "-q") == 0) { 77 supplier = 0; 78 argv++, argc--; 79 continue; 80 } 81 if (strcmp(*argv, "-t") == 0) { 82 if (tracehistory == 0) 83 tracehistory++; 84 else { 85 tracehistory = 0; 86 tracepackets++; 87 } 88 setlogmask(LOG_UPTO(LOG_DEBUG)); 89 argv++, argc--; 90 continue; 91 } 92 if (strcmp(*argv, "-d") == 0) { 93 debug++; 94 setlogmask(LOG_UPTO(LOG_DEBUG)); 95 argv++, argc--; 96 continue; 97 } 98 if (strcmp(*argv, "-g") == 0) { 99 gateway = 1; 100 argv++, argc--; 101 continue; 102 } 103 fprintf(stderr, 104 "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); 105 exit(1); 106 } 107 if (tracepackets == 0 && debug == 0) { 108 int t; 109 110 if (fork()) 111 exit(0); 112 for (t = 0; t < 20; t++) 113 if (t != s) 114 (void) close(t); 115 (void) open("/", 0); 116 (void) dup2(0, 1); 117 (void) dup2(0, 2); 118 t = open("/dev/tty", 2); 119 if (t >= 0) { 120 ioctl(t, TIOCNOTTY, (char *)0); 121 (void) close(t); 122 } 123 } 124 /* 125 * Any extra argument is considered 126 * a tracing log file. 127 */ 128 if (argc > 0) 129 traceon(*argv); 130 /* 131 * Collect an initial view of the world by 132 * checking the interface configuration and the gateway kludge 133 * file. Then, send a request packet on all 134 * directly connected networks to find out what 135 * everyone else thinks. 136 */ 137 rtinit(); 138 ifinit(); 139 gwkludge(); 140 if (gateway > 0) 141 rtdefault(); 142 if (supplier < 0) 143 supplier = 0; 144 msg->rip_cmd = RIPCMD_REQUEST; 145 msg->rip_vers = RIPVERSION; 146 msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 147 msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 148 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 149 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 150 toall(sendmsg); 151 signal(SIGALRM, timer); 152 signal(SIGHUP, hup); 153 signal(SIGTERM, hup); 154 signal(SIGINT, rtdeleteall); 155 signal(SIGUSR1, sigtrace); 156 signal(SIGUSR2, sigtrace); 157 timer(); 158 159 for (;;) { 160 int ibits; 161 register int n; 162 163 ibits = 1 << s; 164 n = select(20, &ibits, 0, 0, 0); 165 if (n < 0) 166 continue; 167 if (ibits & (1 << s)) 168 process(s); 169 /* handle ICMP redirects */ 170 } 171 } 172 173 process(fd) 174 int fd; 175 { 176 struct sockaddr from; 177 int fromlen = sizeof (from), cc, omask; 178 time_t now; 179 180 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 181 if (cc <= 0) { 182 if (cc < 0 && errno != EINTR) 183 perror("recvfrom"); 184 return; 185 } 186 if (fromlen != sizeof (struct sockaddr_in)) 187 return; 188 if (traceactions && !tracepackets) { 189 (void) time(&now); 190 curtime = ctime(&now); 191 } 192 omask = sigblock(sigmask(SIGALRM)); 193 rip_input(&from, cc); 194 sigsetmask(omask); 195 } 196 197 getsocket(domain, type, sin) 198 int domain, type; 199 struct sockaddr_in *sin; 200 { 201 int s, on = 1; 202 203 if ((s = socket(domain, type, 0)) < 0) { 204 perror("socket"); 205 syslog(LOG_ERR, "socket: %m"); 206 return (-1); 207 } 208 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 209 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 210 close(s); 211 return (-1); 212 } 213 on = 48*1024; 214 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) < 0) 215 syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); 216 if (bind(s, sin, sizeof (*sin), 0) < 0) { 217 perror("bind"); 218 syslog(LOG_ERR, "bind: %m"); 219 close(s); 220 return (-1); 221 } 222 return (s); 223 } 224