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 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 char copyright[] = 23 "@(#) Copyright (c) 1985 The Regents of the University of California.\n\ 24 All rights reserved.\n"; 25 #endif /* not lint */ 26 27 #ifndef lint 28 static char sccsid[] = "@(#)main.c 5.6 (Berkeley) 09/19/88"; 29 #endif /* not lint */ 30 31 /* 32 * XNS Routing Information Protocol Daemon 33 */ 34 #include "defs.h" 35 #include <sys/ioctl.h> 36 #include <sys/time.h> 37 38 #include <net/if.h> 39 40 #include <errno.h> 41 #include <nlist.h> 42 #include <signal.h> 43 44 int supplier = -1; /* process should supply updates */ 45 extern int gateway; 46 47 struct rip *msg = (struct rip *) &packet[sizeof (struct idp)]; 48 int hup(), fkexit(); 49 50 main(argc, argv) 51 int argc; 52 char *argv[]; 53 { 54 int cc; 55 struct sockaddr from; 56 u_char retry; 57 58 argv0 = argv; 59 argv++, argc--; 60 while (argc > 0 && **argv == '-') { 61 if (strcmp(*argv, "-s") == 0) { 62 supplier = 1; 63 argv++, argc--; 64 continue; 65 } 66 if (strcmp(*argv, "-q") == 0) { 67 supplier = 0; 68 argv++, argc--; 69 continue; 70 } 71 if (strcmp(*argv, "-R") == 0) { 72 noteremoterequests++; 73 argv++, argc--; 74 continue; 75 } 76 if (strcmp(*argv, "-t") == 0) { 77 tracepackets++; 78 argv++, argc--; 79 ftrace = stderr; 80 tracing = 1; 81 continue; 82 } 83 if (strcmp(*argv, "-g") == 0) { 84 gateway = 1; 85 argv++, argc--; 86 continue; 87 } 88 if (strcmp(*argv, "-l") == 0) { 89 gateway = -1; 90 argv++, argc--; 91 continue; 92 } 93 fprintf(stderr, 94 "usage: xnsrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 95 exit(1); 96 } 97 98 99 #ifndef DEBUG 100 if (!tracepackets) { 101 int t; 102 103 if (fork()) 104 exit(0); 105 for (t = 0; t < 20; t++) 106 (void) close(t); 107 (void) open("/", 0); 108 (void) dup2(0, 1); 109 (void) dup2(0, 2); 110 t = open("/dev/tty", 2); 111 if (t >= 0) { 112 ioctl(t, TIOCNOTTY, (char *)0); 113 (void) close(t); 114 } 115 } 116 #endif 117 openlog("XNSrouted", LOG_PID, LOG_DAEMON); 118 119 ns_anynet.s_net[0] = -1; ns_anynet.s_net[1] = -1; 120 addr.sns_family = AF_NS; 121 addr.sns_port = htons(IDPPORT_RIF); 122 s = getsocket(SOCK_DGRAM, 0, &addr); 123 if (s < 0) 124 exit(1); 125 /* 126 * Any extra argument is considered 127 * a tracing log file. 128 */ 129 if (argc > 0) 130 traceon(*argv); 131 /* 132 * Collect an initial view of the world by 133 * snooping in the kernel. 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 if (supplier < 0) 140 supplier = 0; 141 /* request the state of the world */ 142 msg->rip_cmd = htons(RIPCMD_REQUEST); 143 msg->rip_nets[0].rip_dst = ns_anynet; 144 msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 145 toall(sendmsg); 146 signal(SIGALRM, timer); 147 signal(SIGHUP, hup); 148 signal(SIGINT, hup); 149 signal(SIGEMT, fkexit); 150 timer(); 151 152 153 for (;;) 154 process(s); 155 156 } 157 158 process(fd) 159 int fd; 160 { 161 struct sockaddr from; 162 int fromlen = sizeof (from), cc, omask; 163 struct idp *idp = (struct idp *)packet; 164 165 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 166 if (cc <= 0) { 167 if (cc < 0 && errno != EINTR) 168 syslog("recvfrom: %m"); 169 return; 170 } 171 if (tracepackets > 1 && ftrace) { 172 fprintf(ftrace,"rcv %d bytes on %s ", cc, xns_ntoa(&idp->idp_dna)); 173 fprintf(ftrace," from %s\n", xns_ntoa(&idp->idp_sna)); 174 } 175 176 if (noteremoterequests && !ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) 177 && !ns_neteq(idp->idp_sna, idp->idp_dna)) 178 { 179 syslog(LOG_ERR, 180 "net of interface (%s) != net on ether (%s)!\n", 181 xns_nettoa(idp->idp_dna.x_net), 182 xns_nettoa(idp->idp_sna.x_net)); 183 } 184 185 /* We get the IDP header in front of the RIF packet*/ 186 cc -= sizeof (struct idp); 187 #define mask(s) (1<<((s)-1)) 188 omask = sigblock(mask(SIGALRM)); 189 rip_input(&from, cc); 190 sigsetmask(omask); 191 } 192 193 getsocket(type, proto, sns) 194 int type, proto; 195 struct sockaddr_ns *sns; 196 { 197 int domain = sns->sns_family; 198 int retry, s, on = 1; 199 200 retry = 1; 201 while ((s = socket(domain, type, proto)) < 0 && retry) { 202 syslog("socket: %m"); 203 sleep(5 * retry); 204 retry <<= 1; 205 } 206 if (retry == 0) 207 return (-1); 208 while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) { 209 syslog("bind: %m"); 210 sleep(5 * retry); 211 retry <<= 1; 212 } 213 if (retry == 0) 214 return (-1); 215 if (domain==AF_NS) { 216 struct idp idp; 217 if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 218 syslog("setsockopt SEE HEADERS: %m"); 219 exit(1); 220 } 221 idp.idp_pt = NSPROTO_RI; 222 if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) { 223 syslog("setsockopt SET HEADER: %m"); 224 exit(1); 225 } 226 } 227 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 228 syslog("setsockopt SO_BROADCAST: %m"); 229 exit(1); 230 } 231 return (s); 232 } 233 234 /* 235 * Fork and exit on EMT-- for profiling. 236 */ 237 fkexit() 238 { 239 if (fork() == 0) 240 exit(0); 241 } 242