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