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.10 (Berkeley) 06/29/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 daemon(0, 0); 93 #endif 94 openlog("XNSrouted", LOG_PID, LOG_DAEMON); 95 96 ns_anynet.s_net[0] = -1; ns_anynet.s_net[1] = -1; 97 addr.sns_family = AF_NS; 98 addr.sns_len = sizeof(addr); 99 addr.sns_port = htons(IDPPORT_RIF); 100 s = getsocket(SOCK_DGRAM, 0, &addr); 101 if (s < 0) 102 exit(1); 103 /* 104 * Any extra argument is considered 105 * a tracing log file. 106 */ 107 if (argc > 0) 108 traceon(*argv); 109 /* 110 * Collect an initial view of the world by 111 * snooping in the kernel. Then, send a request packet on all 112 * directly connected networks to find out what 113 * everyone else thinks. 114 */ 115 rtinit(); 116 ifinit(); 117 if (supplier < 0) 118 supplier = 0; 119 /* request the state of the world */ 120 msg->rip_cmd = htons(RIPCMD_REQUEST); 121 msg->rip_nets[0].rip_dst = ns_anynet; 122 msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 123 toall(sendmsg); 124 signal(SIGALRM, timer); 125 signal(SIGHUP, hup); 126 signal(SIGINT, hup); 127 signal(SIGEMT, fkexit); 128 timer(); 129 130 131 for (;;) 132 process(s); 133 134 } 135 136 process(fd) 137 int fd; 138 { 139 struct sockaddr from; 140 int fromlen = sizeof (from), cc, omask; 141 struct idp *idp = (struct idp *)packet; 142 143 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 144 if (cc <= 0) { 145 if (cc < 0 && errno != EINTR) 146 syslog("recvfrom: %m"); 147 return; 148 } 149 if (tracepackets > 1 && ftrace) { 150 fprintf(ftrace,"rcv %d bytes on %s ", cc, xns_ntoa(&idp->idp_dna)); 151 fprintf(ftrace," from %s\n", xns_ntoa(&idp->idp_sna)); 152 } 153 154 if (noteremoterequests && !ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) 155 && !ns_neteq(idp->idp_sna, idp->idp_dna)) 156 { 157 syslog(LOG_ERR, 158 "net of interface (%s) != net on ether (%s)!\n", 159 xns_nettoa(idp->idp_dna.x_net), 160 xns_nettoa(idp->idp_sna.x_net)); 161 } 162 163 /* We get the IDP header in front of the RIF packet*/ 164 cc -= sizeof (struct idp); 165 #define mask(s) (1<<((s)-1)) 166 omask = sigblock(mask(SIGALRM)); 167 rip_input(&from, cc); 168 sigsetmask(omask); 169 } 170 171 getsocket(type, proto, sns) 172 int type, proto; 173 struct sockaddr_ns *sns; 174 { 175 int domain = sns->sns_family; 176 int retry, s, on = 1; 177 178 retry = 1; 179 while ((s = socket(domain, type, proto)) < 0 && retry) { 180 syslog("socket: %m"); 181 sleep(5 * retry); 182 retry <<= 1; 183 } 184 if (retry == 0) 185 return (-1); 186 while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) { 187 syslog("bind: %m"); 188 sleep(5 * retry); 189 retry <<= 1; 190 } 191 if (retry == 0) 192 return (-1); 193 if (domain==AF_NS) { 194 struct idp idp; 195 if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 196 syslog("setsockopt SEE HEADERS: %m"); 197 exit(1); 198 } 199 idp.idp_pt = NSPROTO_RI; 200 if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) { 201 syslog("setsockopt SET HEADER: %m"); 202 exit(1); 203 } 204 } 205 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 206 syslog("setsockopt SO_BROADCAST: %m"); 207 exit(1); 208 } 209 return (s); 210 } 211 212 /* 213 * Fork and exit on EMT-- for profiling. 214 */ 215 fkexit() 216 { 217 if (fork() == 0) 218 exit(0); 219 } 220