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