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