main.c revision 15248
1255570Strasz/*
2255570Strasz * Copyright (c) 1985, 1993
3255570Strasz *	The Regents of the University of California.  All rights reserved.
4255570Strasz *
5255570Strasz * Copyright (c) 1995 John Hay.  All rights reserved.
6255570Strasz *
7255570Strasz * This file includes significant work done at Cornell University by
8255570Strasz * Bill Nesheim.  That work included by permission.
9255570Strasz *
10255570Strasz * Redistribution and use in source and binary forms, with or without
11255570Strasz * modification, are permitted provided that the following conditions
12255570Strasz * are met:
13255570Strasz * 1. Redistributions of source code must retain the above copyright
14255570Strasz *    notice, this list of conditions and the following disclaimer.
15255570Strasz * 2. Redistributions in binary form must reproduce the above copyright
16255570Strasz *    notice, this list of conditions and the following disclaimer in the
17255570Strasz *    documentation and/or other materials provided with the distribution.
18255570Strasz * 3. All advertising materials mentioning features or use of this software
19255570Strasz *    must display the following acknowledgement:
20255570Strasz *	This product includes software developed by the University of
21255570Strasz *	California, Berkeley and its contributors.
22255570Strasz * 4. Neither the name of the University nor the names of its contributors
23255570Strasz *    may be used to endorse or promote products derived from this software
24255570Strasz *    without specific prior written permission.
25255570Strasz *
26255570Strasz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29255570Strasz * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36255570Strasz * SUCH DAMAGE.
37255570Strasz *
38255570Strasz *	$Id: main.c,v 1.3 1995/12/09 09:42:03 julian Exp $
39255570Strasz */
40255570Strasz
41255570Strasz#ifndef lint
42255570Straszstatic char copyright[] =
43255570Strasz"@(#) Copyright (c) 1985, 1993\n\
44255570Strasz	The Regents of the University of California.  All rights reserved.\n";
45255570Strasz#endif /* not lint */
46255570Strasz
47255570Strasz#ifndef lint
48255570Straszstatic char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93";
49255570Strasz#endif /* not lint */
50255570Strasz
51255570Strasz/*
52255570Strasz * IPX Routing Information Protocol Daemon
53255570Strasz */
54255570Strasz#include "defs.h"
55255570Strasz#include <sys/time.h>
56255570Strasz
57255570Strasz#include <net/if.h>
58255570Strasz
59255570Strasz#include <errno.h>
60255570Strasz#include <nlist.h>
61255570Strasz#include <signal.h>
62255570Strasz#include <paths.h>
63255570Strasz#include <stdlib.h>
64255570Strasz#include <unistd.h>
65255570Strasz
66255570Strasz#define SAP_PKT		0
67255570Strasz#define RIP_PKT		1
68255570Strasz
69255570Straszstruct	sockaddr_ipx addr;	/* Daemon's Address */
70255570Straszint	ripsock;		/* RIP Socket to listen on */
71265498Straszint	sapsock;		/* SAP Socket to listen on */
72265498Straszint	kmem;
73265498Straszint	install;		/* if 1 call kernel */
74265498Straszint	lookforinterfaces;	/* if 1 probe kernel for new up interfaces */
75265498Straszint	performnlist;		/* if 1 check if /kernel has changed */
76265498Straszint	externalinterfaces;	/* # of remote and local interfaces */
77265498Straszint	timeval;		/* local idea of time */
78265498Straszint	noteremoterequests;	/* squawk on requests from non-local nets */
79255570Straszint	r;			/* Routing socket to install updates with */
80255570Straszstruct	sockaddr_ipx ipx_netmask;	/* Used in installing routes */
81255570Strasz
82255570Straszchar	packet[MAXRXPACKETSIZE+1];
83255570Strasz
84255570Straszchar	**argv0;
85255570Strasz
86255570Straszint	supplier = -1;		/* process should supply updates */
87255570Straszint	dosap = 1;		/* By default do SAP services. */
88255570Strasz
89255570Straszstruct	rip *msg = (struct rip *) &packet[sizeof (struct ipx)];
90255570Straszstruct	sap_packet *sap_msg =
91255570Strasz		(struct sap_packet *) &packet[sizeof (struct ipx)];
92255570Straszvoid	hup(), fkexit(), timer();
93255570Straszvoid	process(int fd, int pkt_type);
94255570Straszint	getsocket(int type, int proto, struct sockaddr_ipx *sipx);
95255570Straszvoid	getinfo();
96265495Strasz
97265495Straszint
98265495Straszmain(argc, argv)
99265495Strasz	int argc;
100255570Strasz	char *argv[];
101255570Strasz{
102255570Strasz	int nfds;
103255570Strasz	fd_set fdvar;
104255570Strasz
105255570Strasz	argv0 = argv;
106255570Strasz	argv++, argc--;
107255570Strasz	while (argc > 0 && **argv == '-') {
108255570Strasz		if (strcmp(*argv, "-s") == 0) {
109255570Strasz			supplier = 1;
110255570Strasz			argv++, argc--;
111255570Strasz			continue;
112255570Strasz		}
113255570Strasz		if (strcmp(*argv, "-q") == 0) {
114255570Strasz			supplier = 0;
115255570Strasz			argv++, argc--;
116255570Strasz			continue;
117255570Strasz		}
118255570Strasz		if (strcmp(*argv, "-R") == 0) {
119255570Strasz			noteremoterequests++;
120255570Strasz			argv++, argc--;
121255570Strasz			continue;
122255570Strasz		}
123255570Strasz		if (strcmp(*argv, "-S") == 0) {
124255570Strasz			dosap = 0;
125255570Strasz			argv++, argc--;
126255570Strasz			continue;
127255570Strasz		}
128255570Strasz		if (strcmp(*argv, "-t") == 0) {
129255570Strasz			tracepackets++;
130255570Strasz			argv++, argc--;
131255570Strasz			ftrace = stderr;
132255570Strasz			tracing = 1;
133255570Strasz			continue;
134255570Strasz		}
135255570Strasz		if (strcmp(*argv, "-g") == 0) {
136255570Strasz			gateway = 1;
137255570Strasz			argv++, argc--;
138255570Strasz			continue;
139255570Strasz		}
140255570Strasz		if (strcmp(*argv, "-l") == 0) {
141255570Strasz			gateway = -1;
142255570Strasz			argv++, argc--;
143255570Strasz			continue;
144255570Strasz		}
145255570Strasz		fprintf(stderr,
146255570Strasz			"usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
147265488Strasz		exit(1);
148255570Strasz	}
149265488Strasz
150255570Strasz
151255570Strasz#ifndef DEBUG
152255570Strasz	if (!tracepackets)
153265488Strasz		daemon(0, 0);
154255570Strasz#endif
155265488Strasz	openlog("IPXrouted", LOG_PID, LOG_DAEMON);
156255570Strasz
157255570Strasz	addr.sipx_family = AF_IPX;
158255570Strasz	addr.sipx_len = sizeof(addr);
159255570Strasz	addr.sipx_port = htons(IPXPORT_RIP);
160255570Strasz	ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1;
161255570Strasz	ipx_netmask.sipx_addr.x_net = ipx_anynet;
162255570Strasz	ipx_netmask.sipx_len = 6;
163255570Strasz	ipx_netmask.sipx_family = AF_IPX;
164255570Strasz	r = socket(AF_ROUTE, SOCK_RAW, 0);
165255570Strasz	/* later, get smart about lookingforinterfaces */
166255570Strasz	if (r)
167255570Strasz		shutdown(r, 0); /* for now, don't want reponses */
168255570Strasz	else {
169255570Strasz		fprintf(stderr, "IPXrouted: no routing socket\n");
170255570Strasz		exit(1);
171255570Strasz	}
172255570Strasz	ripsock = getsocket(SOCK_DGRAM, 0, &addr);
173255570Strasz	if (ripsock < 0)
174255570Strasz		exit(1);
175265488Strasz
176255570Strasz	if (dosap) {
177265488Strasz		addr.sipx_port = htons(IPXPORT_SAP);
178255570Strasz		sapsock = getsocket(SOCK_DGRAM, 0, &addr);
179255570Strasz		if (sapsock < 0)
180255570Strasz			exit(1);
181255570Strasz	} else
182255570Strasz		sapsock = -1;
183255570Strasz
184255570Strasz	/*
185255570Strasz	 * Any extra argument is considered
186255570Strasz	 * a tracing log file.
187255570Strasz	 */
188255570Strasz	if (argc > 0)
189255570Strasz		traceon(*argv);
190255570Strasz	/*
191255570Strasz	 * Collect an initial view of the world by
192255570Strasz	 * snooping in the kernel.  Then, send a request packet on all
193255570Strasz	 * directly connected networks to find out what
194255570Strasz	 * everyone else thinks.
195255570Strasz	 */
196255570Strasz	rtinit();
197255570Strasz	sapinit();
198255570Strasz	ifinit();
199255570Strasz	if (supplier < 0)
200255570Strasz		supplier = 0;
201255570Strasz	/* request the state of the world */
202255570Strasz	msg->rip_cmd = htons(RIPCMD_REQUEST);
203255570Strasz	msg->rip_nets[0].rip_dst = ipx_anynet;
204255570Strasz	msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
205255570Strasz	msg->rip_nets[0].rip_ticks =  htons(-1);
206255570Strasz	toall(sndmsg, NULL);
207255570Strasz
208255570Strasz	if (dosap) {
209255570Strasz		sap_msg->sap_cmd = htons(SAP_REQ);
210255570Strasz		sap_msg->sap[0].ServType = htons(SAP_WILDCARD);
211255570Strasz		toall(sapsndmsg, NULL);
212255570Strasz	}
213255570Strasz
214255570Strasz	signal(SIGALRM, timer);
215255570Strasz	signal(SIGHUP, hup);
216255570Strasz	signal(SIGINT, hup);
217255570Strasz	signal(SIGEMT, fkexit);
218255570Strasz	signal(SIGINFO, getinfo);
219255570Strasz	timer();
220255570Strasz
221255570Strasz	nfds = 1 + max(sapsock, ripsock);
222255570Strasz
223255570Strasz	for (;;) {
224255570Strasz		FD_ZERO(&fdvar);
225255570Strasz		if (dosap) {
226255570Strasz			FD_SET(sapsock, &fdvar);
227255570Strasz		}
228255570Strasz		FD_SET(ripsock, &fdvar);
229255570Strasz
230255570Strasz		if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL,
231255570Strasz		   (struct timeval *)NULL) < 0) {
232255570Strasz			if(errno == EINTR)
233255570Strasz				continue;
234255570Strasz			perror("during select");
235255570Strasz			exit(1);
236255570Strasz		}
237255570Strasz
238255570Strasz		if(FD_ISSET(ripsock, &fdvar))
239255570Strasz			process(ripsock, RIP_PKT);
240255570Strasz
241255570Strasz		if(dosap && FD_ISSET(sapsock, &fdvar))
242255570Strasz			process(sapsock, SAP_PKT);
243255570Strasz	}
244255570Strasz}
245255570Strasz
246255570Straszvoid
247255570Straszprocess(fd, pkt_type)
248255570Strasz	int fd;
249255570Strasz	int pkt_type;
250255570Strasz{
251255570Strasz	struct sockaddr from;
252255570Strasz	int fromlen = sizeof (from), cc, omask;
253255570Strasz	struct ipx *ipxdp = (struct ipx *)packet;
254255570Strasz
255255570Strasz	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
256255570Strasz	if (cc <= 0) {
257261770Strasz		if (cc < 0 && errno != EINTR)
258255570Strasz			syslog(LOG_ERR, "recvfrom: %m");
259255570Strasz		return;
260255570Strasz	}
261255570Strasz	if (tracepackets > 1 && ftrace) {
262255570Strasz	    fprintf(ftrace,"rcv %d bytes on %s ",
263255570Strasz		    cc, ipxdp_ntoa(&ipxdp->ipx_dna));
264255570Strasz	    fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
265255570Strasz	}
266255570Strasz
267255570Strasz	if (noteremoterequests &&
268255570Strasz	    !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
269255570Strasz	    !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
270255570Strasz	{
271255570Strasz		syslog(LOG_ERR,
272255570Strasz		       "net of interface (%s) != net on ether (%s)!\n",
273255570Strasz		       ipxdp_nettoa(ipxdp->ipx_dna.x_net),
274255570Strasz		       ipxdp_nettoa(ipxdp->ipx_sna.x_net));
275255570Strasz	}
276255570Strasz
277255570Strasz	/* We get the IPX header in front of the RIF packet*/
278255570Strasz	cc -= sizeof (struct ipx);
279255570Strasz#define	mask(s)	(1<<((s)-1))
280255570Strasz	omask = sigblock(mask(SIGALRM));
281255570Strasz	switch(pkt_type) {
282255570Strasz		case SAP_PKT: sap_input(&from, cc);
283255570Strasz				break;
284255570Strasz		case RIP_PKT: rip_input(&from, cc);
285255570Strasz				break;
286255570Strasz	}
287255570Strasz	sigsetmask(omask);
288255570Strasz}
289255570Strasz
290255570Straszint
291255570Straszgetsocket(type, proto, sipx)
292255570Strasz	int type, proto;
293255570Strasz	struct sockaddr_ipx *sipx;
294255570Strasz{
295255570Strasz	int domain = sipx->sipx_family;
296255570Strasz	int retry, s, on = 1;
297255570Strasz
298255570Strasz	retry = 1;
299255570Strasz	while ((s = socket(domain, type, proto)) < 0 && retry) {
300255570Strasz		syslog(LOG_ERR, "socket: %m");
301255570Strasz		sleep(5 * retry);
302255570Strasz		retry <<= 1;
303255570Strasz	}
304255570Strasz	if (retry == 0)
305255570Strasz		return (-1);
306255570Strasz	while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) {
307255570Strasz		syslog(LOG_ERR, "bind: %m");
308255570Strasz		sleep(5 * retry);
309255570Strasz		retry <<= 1;
310255570Strasz	}
311255570Strasz	if (retry == 0)
312255570Strasz		return (-1);
313255570Strasz	if (domain==AF_IPX) {
314255570Strasz		struct ipx ipxdp;
315255570Strasz		if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
316255570Strasz			syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
317255570Strasz			exit(1);
318255570Strasz		}
319255570Strasz		if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP)
320255570Strasz			ipxdp.ipx_pt = IPXPROTO_RI;
321255570Strasz		else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP)
322255570Strasz			ipxdp.ipx_pt = IPXPROTO_SAP;
323255570Strasz		else {
324255570Strasz			syslog(LOG_ERR, "port should be either RIP or SAP");
325255570Strasz			exit(1);
326255570Strasz		}
327255570Strasz		if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) {
328255570Strasz			syslog(LOG_ERR, "setsockopt SET HEADER: %m");
329255570Strasz			exit(1);
330255570Strasz		}
331255570Strasz	}
332255570Strasz	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
333255570Strasz		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
334255570Strasz		exit(1);
335255570Strasz	}
336255570Strasz	return (s);
337255570Strasz}
338255570Strasz
339255570Strasz/*
340255570Strasz * Fork and exit on EMT-- for profiling.
341255570Strasz */
342261771Straszvoid
343255570Straszfkexit()
344255570Strasz{
345255570Strasz	if (fork() == 0)
346255570Strasz		exit(0);
347255570Strasz}
348255570Strasz
349255570Straszvoid
350255570Straszgetinfo()
351255570Strasz{
352255570Strasz	FILE *fh;
353255570Strasz
354255570Strasz	fh = fopen("/tmp/ipxrouted.dmp", "a");
355255570Strasz	if(fh == NULL)
356255570Strasz		return;
357255570Strasz
358255570Strasz	dumpriptable(fh);
359255570Strasz	dumpsaptable(fh, sap_head);
360255570Strasz
361255570Strasz	fclose(fh);
362255570Strasz}
363255570Strasz
364255570Strasz