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