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