main.c revision 122760
1147999Semax/*
2147999Semax * Copyright (c) 1985, 1993
3147999Semax *	The Regents of the University of California.  All rights reserved.
4147999Semax *
5147999Semax * Copyright (c) 1995 John Hay.  All rights reserved.
6147999Semax *
7147999Semax * This file includes significant work done at Cornell University by
8147999Semax * Bill Nesheim.  That work included by permission.
9147999Semax *
10147999Semax * Redistribution and use in source and binary forms, with or without
11147999Semax * modification, are permitted provided that the following conditions
12147999Semax * are met:
13147999Semax * 1. Redistributions of source code must retain the above copyright
14147999Semax *    notice, this list of conditions and the following disclaimer.
15147999Semax * 2. Redistributions in binary form must reproduce the above copyright
16147999Semax *    notice, this list of conditions and the following disclaimer in the
17147999Semax *    documentation and/or other materials provided with the distribution.
18147999Semax * 3. All advertising materials mentioning features or use of this software
19147999Semax *    must display the following acknowledgement:
20147999Semax *	This product includes software developed by the University of
21147999Semax *	California, Berkeley and its contributors.
22147999Semax * 4. Neither the name of the University nor the names of its contributors
23147999Semax *    may be used to endorse or promote products derived from this software
24147999Semax *    without specific prior written permission.
25147999Semax *
26147999Semax * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27147999Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28147999Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29147999Semax * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30147999Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31147999Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32147999Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33147999Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34162711Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35147999Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36297685Semaste * SUCH DAMAGE.
37147999Semax *
38147999Semax * $FreeBSD: head/usr.sbin/IPXrouted/main.c 122760 2003-11-15 17:10:56Z trhodes $
39156167Semax */
40147999Semax
41147999Semax#ifndef lint
42147999Semaxstatic const char copyright[] =
43147999Semax"@(#) Copyright (c) 1985, 1993\n\
44147999Semax	The Regents of the University of California.  All rights reserved.\n";
45147999Semax#endif /* not lint */
46147999Semax
47147999Semax#ifndef lint
48147999Semaxstatic const char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93";
49147999Semax#endif /* not lint */
50147999Semax
51147999Semax/*
52147999Semax * IPX Routing Information Protocol Daemon
53147999Semax */
54147999Semax#include "defs.h"
55147999Semax#include <sys/time.h>
56147999Semax
57147999Semax#include <net/if.h>
58297685Semaste
59297685Semaste#include <errno.h>
60297685Semaste#include <nlist.h>
61297685Semaste#include <signal.h>
62297685Semaste#include <paths.h>
63297685Semaste#include <stdlib.h>
64297685Semaste#include <unistd.h>
65147999Semax
66147999Semax#define SAP_PKT		0
67147999Semax#define RIP_PKT		1
68147999Semax
69147999Semaxstruct	sockaddr_ipx addr;	/* Daemon's Address */
70147999Semaxint	ripsock;		/* RIP Socket to listen on */
71147999Semaxint	sapsock;		/* SAP Socket to listen on */
72147999Semaxint	kmem;
73147999Semaxint	install;		/* if 1 call kernel */
74147999Semaxint	lookforinterfaces;	/* if 1 probe kernel for new up interfaces */
75147999Semaxint	performnlist;		/* if 1 check if /kernel has changed */
76147999Semaxint	externalinterfaces;	/* # of remote and local interfaces */
77147999Semaxint	timeval;		/* local idea of time */
78147999Semaxint	noteremoterequests;	/* squawk on requests from non-local nets */
79147999Semaxint	r;			/* Routing socket to install updates with */
80147999Semaxstruct	sockaddr_ipx ipx_netmask;	/* Used in installing routes */
81147999Semax
82147999Semaxchar	packet[MAXRXPACKETSIZE+1];
83147999Semax
84147999Semaxchar	**argv0;
85147999Semax
86147999Semaxint	supplier = -1;		/* process should supply updates */
87147999Semaxint	dosap = 1;		/* By default do SAP services. */
88147999Semaxint	dobcast = 1;		/* A RIP/SAP broadcast is needed. */
89147999Semaxtime_t	lastbcast;		/* Time of last RIP/SAP broadcast */
90147999Semax
91147999Semaxstruct	rip *msg = (struct rip *) &packet[sizeof (struct ipx)];
92147999Semaxstruct	sap_packet *sap_msg =
93147999Semax		(struct sap_packet *) &packet[sizeof (struct ipx)];
94147999Semaxvoid	hup(), fkexit(), timer();
95147999Semaxvoid	process(int fd, int pkt_type);
96147999Semaxint	getsocket(int type, int proto, struct sockaddr_ipx *sipx);
97147999Semaxvoid	getinfo();
98147999Semaxvoid	catchtimer();
99147999Semax
100147999Semaxint
101147999Semaxmain(argc, argv)
102147999Semax	int argc;
103147999Semax	char *argv[];
104147999Semax{
105147999Semax	int nfds;
106147999Semax	fd_set fdvar;
107147999Semax	time_t ttime;
108147999Semax	struct itimerval tval;
109147999Semax
110147999Semax	argv0 = argv;
111147999Semax	argv++, argc--;
112147999Semax	while (argc > 0 && **argv == '-') {
113147999Semax		if (strcmp(*argv, "-s") == 0) {
114190857Semax			supplier = 1;
115190857Semax			argv++, argc--;
116190857Semax			continue;
117190857Semax		}
118147999Semax		if (strcmp(*argv, "-q") == 0) {
119147999Semax			supplier = 0;
120147999Semax			argv++, argc--;
121147999Semax			continue;
122147999Semax		}
123147999Semax		if (strcmp(*argv, "-R") == 0) {
124147999Semax			noteremoterequests++;
125147999Semax			argv++, argc--;
126147999Semax			continue;
127147999Semax		}
128147999Semax		if (strcmp(*argv, "-S") == 0) {
129147999Semax			dosap = 0;
130147999Semax			argv++, argc--;
131147999Semax			continue;
132147999Semax		}
133147999Semax		if (strcmp(*argv, "-t") == 0) {
134147999Semax			tracepackets++;
135147999Semax			argv++, argc--;
136147999Semax			ftrace = stderr;
137147999Semax			tracing = 1;
138147999Semax			continue;
139147999Semax		}
140147999Semax		if (strcmp(*argv, "-g") == 0) {
141147999Semax			gateway = 1;
142147999Semax			argv++, argc--;
143147999Semax			continue;
144193512Sed		}
145193512Sed		if (strcmp(*argv, "-l") == 0) {
146193512Sed			gateway = -1;
147147999Semax			argv++, argc--;
148147999Semax			continue;
149147999Semax		}
150147999Semax		if (strcmp(*argv, "-N") == 0) {
151147999Semax			dognreply = 0;
152147999Semax			argv++, argc--;
153147999Semax			continue;
154147999Semax		}
155147999Semax		fprintf(stderr,
156147999Semax			"usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n");
157147999Semax		exit(1);
158147999Semax	}
159147999Semax
160147999Semax
161147999Semax#ifndef DEBUG
162147999Semax	if (!tracepackets)
163147999Semax		daemon(0, 0);
164147999Semax#endif
165147999Semax	openlog("IPXrouted", LOG_PID, LOG_DAEMON);
166147999Semax
167147999Semax	addr.sipx_family = AF_IPX;
168147999Semax	addr.sipx_len = sizeof(addr);
169147999Semax	addr.sipx_port = htons(IPXPORT_RIP);
170147999Semax	ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1;
171147999Semax	ipx_netmask.sipx_addr.x_net = ipx_anynet;
172147999Semax	ipx_netmask.sipx_len = 6;
173147999Semax	ipx_netmask.sipx_family = AF_IPX;
174147999Semax	r = socket(AF_ROUTE, SOCK_RAW, 0);
175147999Semax	/* later, get smart about lookingforinterfaces */
176147999Semax	if (r)
177147999Semax		shutdown(r, 0); /* for now, don't want reponses */
178147999Semax	else {
179193512Sed		fprintf(stderr, "IPXrouted: no routing socket\n");
180193512Sed		exit(1);
181193512Sed	}
182193512Sed	ripsock = getsocket(SOCK_DGRAM, 0, &addr);
183193512Sed	if (ripsock < 0)
184193512Sed		exit(1);
185193512Sed
186193512Sed	if (dosap) {
187193512Sed		addr.sipx_port = htons(IPXPORT_SAP);
188193512Sed		sapsock = getsocket(SOCK_DGRAM, 0, &addr);
189193512Sed		if (sapsock < 0)
190193512Sed			exit(1);
191193512Sed	} else
192193752Sed		sapsock = -1;
193193512Sed
194193512Sed	/*
195193752Sed	 * Any extra argument is considered
196193512Sed	 * a tracing log file.
197193512Sed	 */
198193512Sed	if (argc > 0)
199193512Sed		traceon(*argv);
200193512Sed	/*
201193512Sed	 * Collect an initial view of the world by
202193512Sed	 * snooping in the kernel.  Then, send a request packet on all
203193512Sed	 * directly connected networks to find out what
204193512Sed	 * everyone else thinks.
205193512Sed	 */
206193512Sed	rtinit();
207147999Semax	sapinit();
208147999Semax	ifinit();
209147999Semax	if (supplier < 0)
210147999Semax		supplier = 0;
211147999Semax	/* request the state of the world */
212147999Semax	msg->rip_cmd = htons(RIPCMD_REQUEST);
213147999Semax	msg->rip_nets[0].rip_dst = ipx_anynet;
214147999Semax	msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
215147999Semax	msg->rip_nets[0].rip_ticks =  htons(-1);
216174984Swkoszek	toall(sndmsg, NULL, 0);
217147999Semax
218147999Semax	if (dosap) {
219147999Semax		sap_msg->sap_cmd = htons(SAP_REQ);
220147999Semax		sap_msg->sap[0].ServType = htons(SAP_WILDCARD);
221147999Semax		toall(sapsndmsg, NULL, 0);
222147999Semax	}
223147999Semax
224147999Semax	signal(SIGALRM, catchtimer);
225147999Semax	signal(SIGHUP, hup);
226147999Semax	signal(SIGINT, hup);
227147999Semax	signal(SIGEMT, fkexit);
228147999Semax	signal(SIGINFO, getinfo);
229147999Semax
230147999Semax	tval.it_interval.tv_sec = TIMER_RATE;
231147999Semax	tval.it_interval.tv_usec = 0;
232147999Semax	tval.it_value.tv_sec = TIMER_RATE;
233147999Semax	tval.it_value.tv_usec = 0;
234147999Semax	setitimer(ITIMER_REAL, &tval, NULL);
235147999Semax
236147999Semax	nfds = 1 + max(sapsock, ripsock);
237147999Semax
238147999Semax	for (;;) {
239147999Semax		if (dobcast) {
240147999Semax			dobcast = 0;
241147999Semax			lastbcast = time(NULL);
242147999Semax			timer();
243147999Semax		}
244147999Semax
245193512Sed		FD_ZERO(&fdvar);
246147999Semax		if (dosap) {
247147999Semax			FD_SET(sapsock, &fdvar);
248147999Semax		}
249147999Semax		FD_SET(ripsock, &fdvar);
250147999Semax
251147999Semax		if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL,
252147999Semax		   (struct timeval *)NULL) < 0) {
253147999Semax			if(errno == EINTR)
254147999Semax				continue;
255147999Semax			perror("during select");
256147999Semax			exit(1);
257147999Semax		}
258147999Semax
259147999Semax		if(FD_ISSET(ripsock, &fdvar))
260147999Semax			process(ripsock, RIP_PKT);
261147999Semax
262147999Semax		if(dosap && FD_ISSET(sapsock, &fdvar))
263147999Semax			process(sapsock, SAP_PKT);
264147999Semax
265147999Semax		ttime = time(NULL);
266147999Semax		if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) {
267156013Semax			dobcast = 1;
268156013Semax			syslog(LOG_ERR, "Missed alarm");
269156013Semax		}
270156013Semax	}
271156013Semax}
272156013Semax
273156013Semaxvoid
274156013Semaxprocess(fd, pkt_type)
275156013Semax	int fd;
276156013Semax	int pkt_type;
277174984Swkoszek{
278174984Swkoszek	struct sockaddr from;
279147999Semax	int fromlen = sizeof (from), cc, omask;
280156010Semax	struct ipx *ipxdp = (struct ipx *)packet;
281147999Semax
282147999Semax	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
283147999Semax	if (cc <= 0) {
284147999Semax		if (cc < 0 && errno != EINTR)
285147999Semax			syslog(LOG_ERR, "recvfrom: %m");
286193512Sed		return;
287147999Semax	}
288147999Semax	if (tracepackets > 1 && ftrace) {
289147999Semax	    fprintf(ftrace,"rcv %d bytes on %s ",
290193512Sed		    cc, ipxdp_ntoa(&ipxdp->ipx_dna));
291147999Semax	    fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
292147999Semax	}
293147999Semax
294147999Semax	if (noteremoterequests &&
295147999Semax	    !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
296147999Semax	    !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
297147999Semax	{
298147999Semax		syslog(LOG_ERR,
299147999Semax		       "net of interface (%s) != net on ether (%s)!\n",
300147999Semax		       ipxdp_nettoa(ipxdp->ipx_dna.x_net),
301147999Semax		       ipxdp_nettoa(ipxdp->ipx_sna.x_net));
302147999Semax	}
303147999Semax
304147999Semax	/* We get the IPX header in front of the RIF packet*/
305147999Semax	cc -= sizeof (struct ipx);
306147999Semax#define	mask(s)	(1<<((s)-1))
307147999Semax	omask = sigblock(mask(SIGALRM));
308147999Semax	switch(pkt_type) {
309147999Semax		case SAP_PKT: sap_input(&from, cc);
310147999Semax				break;
311147999Semax		case RIP_PKT: rip_input(&from, cc);
312147999Semax				break;
313147999Semax	}
314147999Semax	sigsetmask(omask);
315147999Semax}
316147999Semax
317147999Semaxint
318147999Semaxgetsocket(type, proto, sipx)
319147999Semax	int type, proto;
320147999Semax	struct sockaddr_ipx *sipx;
321147999Semax{
322147999Semax	int domain = sipx->sipx_family;
323147999Semax	int retry, s, on = 1;
324147999Semax
325147999Semax	retry = 1;
326147999Semax	while ((s = socket(domain, type, proto)) < 0 && retry) {
327147999Semax		syslog(LOG_ERR, "socket: %m");
328147999Semax		sleep(5 * retry);
329147999Semax		retry <<= 1;
330147999Semax	}
331147999Semax	if (retry == 0)
332147999Semax		return (-1);
333147999Semax	while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) {
334147999Semax		syslog(LOG_ERR, "bind: %m");
335147999Semax		sleep(5 * retry);
336147999Semax		retry <<= 1;
337147999Semax	}
338147999Semax	if (retry == 0)
339147999Semax		return (-1);
340147999Semax	if (domain==AF_IPX) {
341147999Semax		struct ipx ipxdp;
342147999Semax		if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
343147999Semax			syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
344147999Semax			exit(1);
345147999Semax		}
346147999Semax		if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP)
347147999Semax			ipxdp.ipx_pt = IPXPROTO_RI;
348147999Semax		else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP)
349147999Semax#ifdef IPXPROTO_SAP
350147999Semax			ipxdp.ipx_pt = IPXPROTO_SAP;
351147999Semax#else
352147999Semax			ipxdp.ipx_pt = IPXPROTO_PXP;
353147999Semax#endif
354147999Semax		else {
355147999Semax			syslog(LOG_ERR, "port should be either RIP or SAP");
356147999Semax			exit(1);
357147999Semax		}
358147999Semax		if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) {
359147999Semax			syslog(LOG_ERR, "setsockopt SET HEADER: %m");
360147999Semax			exit(1);
361147999Semax		}
362147999Semax	}
363147999Semax	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
364147999Semax		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
365147999Semax		exit(1);
366147999Semax	}
367147999Semax	return (s);
368147999Semax}
369147999Semax
370147999Semax/*
371147999Semax * Fork and exit on EMT-- for profiling.
372147999Semax */
373147999Semaxvoid
374147999Semaxfkexit()
375147999Semax{
376147999Semax	if (fork() == 0)
377147999Semax		exit(0);
378147999Semax}
379147999Semax
380147999Semaxvoid
381147999Semaxcatchtimer()
382147999Semax{
383147999Semax	dobcast = 1;
384147999Semax}
385147999Semax
386147999Semaxvoid
387147999Semaxgetinfo()
388147999Semax{
389241885Seadler	FILE *fh;
390241885Seadler
391156167Semax	fh = fopen("/var/log/ipxrouted.dmp", "a");
392147999Semax	if(fh == NULL)
393147999Semax		return;
394147999Semax
395147999Semax	dumpriptable(fh);
396147999Semax	dumpsaptable(fh, sap_head);
397147999Semax
398147999Semax	fclose(fh);
399147999Semax}
400147999Semax
401147999Semax