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