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