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
main(argc,argv)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
process(fd)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
getsocket(type,proto,sns)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
fkexit()225 fkexit()
226 {
227 if (fork() == 0)
228 exit(0);
229 }
230