1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * Includes material written at Cornell University by Bill Nesheim 7 * with permission of the author. 8 */ 9 10 #ifndef lint 11 char copyright[] = 12 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 13 All rights reserved.\n"; 14 #endif not lint 15 16 #ifndef lint 17 static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 02/14/86"; 18 #endif not lint 19 20 /* 21 * XNS Routing Information Protocol Daemon 22 */ 23 #include "defs.h" 24 #include <sys/ioctl.h> 25 #include <sys/time.h> 26 27 #include <net/if.h> 28 29 #include <errno.h> 30 #include <nlist.h> 31 #include <signal.h> 32 33 int supplier = -1; /* process should supply updates */ 34 extern int gateway; 35 36 struct rip *msg = (struct rip *) &packet[sizeof (struct idp)]; 37 int hup(), fkexit(); 38 39 main(argc, argv) 40 int argc; 41 char *argv[]; 42 { 43 int cc; 44 struct sockaddr from; 45 u_char retry; 46 47 argv0 = argv; 48 argv++, argc--; 49 while (argc > 0 && **argv == '-') { 50 if (strcmp(*argv, "-s") == 0) { 51 supplier = 1; 52 argv++, argc--; 53 continue; 54 } 55 if (strcmp(*argv, "-q") == 0) { 56 supplier = 0; 57 argv++, argc--; 58 continue; 59 } 60 if (strcmp(*argv, "-R") == 0) { 61 noteremoterequests++; 62 argv++, argc--; 63 continue; 64 } 65 if (strcmp(*argv, "-t") == 0) { 66 tracepackets++; 67 argv++, argc--; 68 ftrace = stderr; 69 tracing = 1; 70 continue; 71 } 72 if (strcmp(*argv, "-g") == 0) { 73 gateway = 1; 74 argv++, argc--; 75 continue; 76 } 77 if (strcmp(*argv, "-l") == 0) { 78 gateway = -1; 79 argv++, argc--; 80 continue; 81 } 82 fprintf(stderr, 83 "usage: xnsrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 84 exit(1); 85 } 86 87 88 #ifndef DEBUG 89 if (!tracepackets) { 90 int t; 91 92 if (fork()) 93 exit(0); 94 for (t = 0; t < 20; t++) 95 (void) close(t); 96 (void) open("/", 0); 97 (void) dup2(0, 1); 98 (void) dup2(0, 2); 99 t = open("/dev/tty", 2); 100 if (t >= 0) { 101 ioctl(t, TIOCNOTTY, (char *)0); 102 (void) close(t); 103 } 104 } 105 #endif 106 openlog("XNSrouted", LOG_PID, LOG_DAEMON); 107 108 ns_anynet.s_net[0] = -1; ns_anynet.s_net[1] = -1; 109 addr.sns_family = AF_NS; 110 addr.sns_port = htons(IDPPORT_RIF); 111 s = getsocket(SOCK_DGRAM, 0, &addr); 112 if (s < 0) 113 exit(1); 114 /* 115 * Any extra argument is considered 116 * a tracing log file. 117 */ 118 if (argc > 0) 119 traceon(*argv); 120 /* 121 * Collect an initial view of the world by 122 * snooping in the kernel. Then, send a request packet on all 123 * directly connected networks to find out what 124 * everyone else thinks. 125 */ 126 rtinit(); 127 ifinit(); 128 if (supplier < 0) 129 supplier = 0; 130 /* request the state of the world */ 131 msg->rip_cmd = htons(RIPCMD_REQUEST); 132 msg->rip_nets[0].rip_dst = ns_anynet; 133 msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 134 toall(sendmsg); 135 signal(SIGALRM, timer); 136 signal(SIGHUP, hup); 137 signal(SIGINT, hup); 138 signal(SIGEMT, fkexit); 139 timer(); 140 141 142 for (;;) 143 process(s); 144 145 } 146 147 process(fd) 148 int fd; 149 { 150 struct sockaddr from; 151 int fromlen = sizeof (from), cc, omask; 152 struct idp *idp = (struct idp *)packet; 153 154 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 155 if (cc <= 0) { 156 if (cc < 0 && errno != EINTR) 157 syslog("recvfrom: %m"); 158 return; 159 } 160 if (tracepackets > 1 && ftrace) { 161 fprintf(ftrace,"rcv %d bytes on %s ", cc, xns_ntoa(&idp->idp_dna)); 162 fprintf(ftrace," from %s\n", xns_ntoa(&idp->idp_sna)); 163 } 164 165 if (noteremoterequests && !ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) 166 && !ns_neteq(idp->idp_sna, idp->idp_dna)) 167 { 168 syslog(LOG_ERR, 169 "net of interface (%s) != net on ether (%s)!\n", 170 xns_nettoa(idp->idp_dna.x_net), 171 xns_nettoa(idp->idp_sna.x_net)); 172 } 173 174 /* We get the IDP header in front of the RIF packet*/ 175 cc -= sizeof (struct idp); 176 #define mask(s) (1<<((s)-1)) 177 omask = sigblock(mask(SIGALRM)); 178 rip_input(&from, cc); 179 sigsetmask(omask); 180 } 181 182 getsocket(type, proto, sns) 183 int type, proto; 184 struct sockaddr_ns *sns; 185 { 186 int domain = sns->sns_family; 187 int retry, s, on = 1; 188 189 retry = 1; 190 while ((s = socket(domain, type, proto)) < 0 && retry) { 191 syslog("socket: %m"); 192 sleep(5 * retry); 193 retry <<= 1; 194 } 195 if (retry == 0) 196 return (-1); 197 while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) { 198 syslog("bind: %m"); 199 sleep(5 * retry); 200 retry <<= 1; 201 } 202 if (retry == 0) 203 return (-1); 204 if (domain==AF_NS) { 205 struct idp idp; 206 if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 207 syslog("setsockopt SEE HEADERS: %m"); 208 exit(1); 209 } 210 idp.idp_pt = NSPROTO_RI; 211 if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) { 212 syslog("setsockopt SET HEADER: %m"); 213 exit(1); 214 } 215 } 216 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 217 syslog("setsockopt SO_BROADCAST: %m"); 218 exit(1); 219 } 220 return (s); 221 } 222 223 /* 224 * Fork and exit on EMT-- for profiling. 225 */ 226 fkexit() 227 { 228 if (fork() == 0) 229 exit(0); 230 } 231