main.c revision 45988
114125Speter/*
214125Speter * Copyright (c) 1985, 1993
314125Speter *	The Regents of the University of California.  All rights reserved.
414125Speter *
514125Speter * Copyright (c) 1995 John Hay.  All rights reserved.
614125Speter *
714125Speter * This file includes significant work done at Cornell University by
814125Speter * Bill Nesheim.  That work included by permission.
914125Speter *
1014125Speter * Redistribution and use in source and binary forms, with or without
1114125Speter * modification, are permitted provided that the following conditions
1214125Speter * are met:
1314125Speter * 1. Redistributions of source code must retain the above copyright
1414125Speter *    notice, this list of conditions and the following disclaimer.
1514125Speter * 2. Redistributions in binary form must reproduce the above copyright
1614125Speter *    notice, this list of conditions and the following disclaimer in the
1714125Speter *    documentation and/or other materials provided with the distribution.
1814125Speter * 3. All advertising materials mentioning features or use of this software
1914125Speter *    must display the following acknowledgement:
2014125Speter *	This product includes software developed by the University of
2114125Speter *	California, Berkeley and its contributors.
2214125Speter * 4. Neither the name of the University nor the names of its contributors
2314125Speter *    may be used to endorse or promote products derived from this software
2414125Speter *    without specific prior written permission.
2514125Speter *
2614125Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2714125Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2814125Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2914125Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3014125Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3114125Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3274499Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3374499Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3414125Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3514125Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3630376Scharnier * SUCH DAMAGE.
3730376Scharnier *
3830376Scharnier *	$Id: main.c,v 1.7 1997/07/06 07:38:30 jhay Exp $
39180025Sdfr */
4014125Speter
4130376Scharnier#ifndef lint
4214125Speterstatic char copyright[] =
4314125Speter"@(#) Copyright (c) 1985, 1993\n\
4414125Speter	The Regents of the University of California.  All rights reserved.\n";
4514125Speter#endif /* not lint */
4614125Speter
4799786Salfred#ifndef lint
4814125Speterstatic char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93";
4914125Speter#endif /* not lint */
5014125Speter
5114125Speter/*
5214125Speter * IPX Routing Information Protocol Daemon
5314125Speter */
5414125Speter#include "defs.h"
5514125Speter#include <sys/time.h>
5614125Speter
5714125Speter#include <net/if.h>
5814125Speter
5914125Speter#include <errno.h>
6014125Speter#include <nlist.h>
6114125Speter#include <signal.h>
6214125Speter#include <paths.h>
6314125Speter#include <stdlib.h>
6414125Speter#include <unistd.h>
6514125Speter
6614125Speter#define SAP_PKT		0
6714125Speter#define RIP_PKT		1
6814125Speter
6914125Speterstruct	sockaddr_ipx addr;	/* Daemon's Address */
7014125Speterint	ripsock;		/* RIP Socket to listen on */
7114125Speterint	sapsock;		/* SAP Socket to listen on */
7214125Speterint	kmem;
7314125Speterint	install;		/* if 1 call kernel */
7414125Speterint	lookforinterfaces;	/* if 1 probe kernel for new up interfaces */
7514125Speterint	performnlist;		/* if 1 check if /kernel has changed */
7614125Speterint	externalinterfaces;	/* # of remote and local interfaces */
7714125Speterint	timeval;		/* local idea of time */
7814125Speterint	noteremoterequests;	/* squawk on requests from non-local nets */
7914125Speterint	r;			/* Routing socket to install updates with */
8014125Speterstruct	sockaddr_ipx ipx_netmask;	/* Used in installing routes */
8114125Speter
82180025Sdfrchar	packet[MAXRXPACKETSIZE+1];
8314125Speter
8414125Speterchar	**argv0;
85180025Sdfr
86180025Sdfrint	supplier = -1;		/* process should supply updates */
8714125Speterint	dosap = 1;		/* By default do SAP services. */
8814125Speterint	dobcast = 1;		/* A RIP/SAP broadcast is needed. */
8914125Spetertime_t	lastbcast;		/* Time of last RIP/SAP broadcast */
9014125Speter
9114125Speterstruct	rip *msg = (struct rip *) &packet[sizeof (struct ipx)];
9214125Speterstruct	sap_packet *sap_msg =
9314125Speter		(struct sap_packet *) &packet[sizeof (struct ipx)];
94180025Sdfrvoid	hup(), fkexit(), timer();
95180025Sdfrvoid	process(int fd, int pkt_type);
96180025Sdfrint	getsocket(int type, int proto, struct sockaddr_ipx *sipx);
97180025Sdfrvoid	getinfo();
98180025Sdfrvoid	catchtimer();
99180025Sdfr
100180025Sdfrint
101180025Sdfrmain(argc, argv)
102180025Sdfr	int argc;
103180025Sdfr	char *argv[];
104180025Sdfr{
105180025Sdfr	int nfds;
106180025Sdfr	fd_set fdvar;
107180025Sdfr	time_t ttime;
108180025Sdfr	struct itimerval tval;
109180025Sdfr
110180025Sdfr	argv0 = argv;
111180025Sdfr	argv++, argc--;
112180025Sdfr	while (argc > 0 && **argv == '-') {
113180025Sdfr		if (strcmp(*argv, "-s") == 0) {
114180025Sdfr			supplier = 1;
115180025Sdfr			argv++, argc--;
116180025Sdfr			continue;
117180025Sdfr		}
11814125Speter		if (strcmp(*argv, "-q") == 0) {
11914125Speter			supplier = 0;
12014125Speter			argv++, argc--;
121180025Sdfr			continue;
122180025Sdfr		}
12314125Speter		if (strcmp(*argv, "-R") == 0) {
12414125Speter			noteremoterequests++;
12514125Speter			argv++, argc--;
12614125Speter			continue;
12714125Speter		}
12814125Speter		if (strcmp(*argv, "-S") == 0) {
12914125Speter			dosap = 0;
13014125Speter			argv++, argc--;
13114125Speter			continue;
13214125Speter		}
13314125Speter		if (strcmp(*argv, "-t") == 0) {
13414125Speter			tracepackets++;
13514125Speter			argv++, argc--;
13614125Speter			ftrace = stderr;
13714125Speter			tracing = 1;
13814125Speter			continue;
13914125Speter		}
14014125Speter		if (strcmp(*argv, "-g") == 0) {
14114125Speter			gateway = 1;
14214125Speter			argv++, argc--;
14314125Speter			continue;
14414125Speter		}
14514125Speter		if (strcmp(*argv, "-l") == 0) {
14614125Speter			gateway = -1;
14714125Speter			argv++, argc--;
14814125Speter			continue;
14914125Speter		}
15014125Speter		if (strcmp(*argv, "-N") == 0) {
15114125Speter			dognreply = 0;
15214125Speter			argv++, argc--;
15314125Speter			continue;
15414125Speter		}
15514125Speter		fprintf(stderr,
15614125Speter			"usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n");
15714125Speter		exit(1);
15814125Speter	}
15914125Speter
16014125Speter
16114125Speter#ifndef DEBUG
16214125Speter	if (!tracepackets)
16314125Speter		daemon(0, 0);
16414125Speter#endif
16514125Speter	openlog("IPXrouted", LOG_PID, LOG_DAEMON);
16614125Speter
16714125Speter	addr.sipx_family = AF_IPX;
16814125Speter	addr.sipx_len = sizeof(addr);
16914125Speter	addr.sipx_port = htons(IPXPORT_RIP);
17099798Salfred	ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1;
17114125Speter	ipx_netmask.sipx_addr.x_net = ipx_anynet;
17214125Speter	ipx_netmask.sipx_len = 6;
17314125Speter	ipx_netmask.sipx_family = AF_IPX;
17414125Speter	r = socket(AF_ROUTE, SOCK_RAW, 0);
17514125Speter	/* later, get smart about lookingforinterfaces */
17614125Speter	if (r)
17714125Speter		shutdown(r, 0); /* for now, don't want reponses */
17814125Speter	else {
17914125Speter		fprintf(stderr, "IPXrouted: no routing socket\n");
18014125Speter		exit(1);
18114125Speter	}
18214125Speter	ripsock = getsocket(SOCK_DGRAM, 0, &addr);
18314125Speter	if (ripsock < 0)
18430376Scharnier		exit(1);
18514125Speter
18614125Speter	if (dosap) {
18714125Speter		addr.sipx_port = htons(IPXPORT_SAP);
18814125Speter		sapsock = getsocket(SOCK_DGRAM, 0, &addr);
18914125Speter		if (sapsock < 0)
19014125Speter			exit(1);
19121786Salex	} else
192171816Struckman		sapsock = -1;
19314125Speter
19414125Speter	/*
19514125Speter	 * Any extra argument is considered
19614125Speter	 * a tracing log file.
19714125Speter	 */
19814125Speter	if (argc > 0)
19914125Speter		traceon(*argv);
20014125Speter	/*
20114125Speter	 * Collect an initial view of the world by
20214125Speter	 * snooping in the kernel.  Then, send a request packet on all
20330376Scharnier	 * directly connected networks to find out what
20414125Speter	 * everyone else thinks.
20514125Speter	 */
20614125Speter	rtinit();
20714125Speter	sapinit();
20814125Speter	ifinit();
20914125Speter	if (supplier < 0)
21014125Speter		supplier = 0;
21114125Speter	/* request the state of the world */
21214125Speter	msg->rip_cmd = htons(RIPCMD_REQUEST);
21314125Speter	msg->rip_nets[0].rip_dst = ipx_anynet;
21414125Speter	msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
21514125Speter	msg->rip_nets[0].rip_ticks =  htons(-1);
21614125Speter	toall(sndmsg, NULL, 0);
21714125Speter
21814125Speter	if (dosap) {
21914125Speter		sap_msg->sap_cmd = htons(SAP_REQ);
22014125Speter		sap_msg->sap[0].ServType = htons(SAP_WILDCARD);
22114125Speter		toall(sapsndmsg, NULL, 0);
22214125Speter	}
22314125Speter
22414125Speter	signal(SIGALRM, catchtimer);
22514125Speter	signal(SIGHUP, hup);
22614125Speter	signal(SIGINT, hup);
22714125Speter	signal(SIGEMT, fkexit);
22814125Speter	signal(SIGINFO, getinfo);
22914125Speter
23014125Speter	tval.it_interval.tv_sec = TIMER_RATE;
23114125Speter	tval.it_interval.tv_usec = 0;
23214125Speter	tval.it_value.tv_sec = TIMER_RATE;
23314125Speter	tval.it_value.tv_usec = 0;
23414125Speter	setitimer(ITIMER_REAL, &tval, NULL);
23514125Speter
23614125Speter	nfds = 1 + max(sapsock, ripsock);
23714125Speter
23814125Speter	for (;;) {
23914125Speter		if (dobcast) {
24014125Speter			dobcast = 0;
24114125Speter			lastbcast = time(NULL);
24214125Speter			timer();
24314125Speter		}
24414125Speter
24514125Speter		FD_ZERO(&fdvar);
24614125Speter		if (dosap) {
24714125Speter			FD_SET(sapsock, &fdvar);
24814125Speter		}
24914125Speter		FD_SET(ripsock, &fdvar);
25014125Speter
25114125Speter		if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL,
25214125Speter		   (struct timeval *)NULL) < 0) {
25314125Speter			if(errno == EINTR)
25414125Speter				continue;
25514125Speter			perror("during select");
25614125Speter			exit(1);
25714125Speter		}
25814125Speter
25914125Speter		if(FD_ISSET(ripsock, &fdvar))
26014125Speter			process(ripsock, RIP_PKT);
26114125Speter
26214125Speter		if(dosap && FD_ISSET(sapsock, &fdvar))
26314125Speter			process(sapsock, SAP_PKT);
26414125Speter
26514125Speter		ttime = time(NULL);
26614125Speter		if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) {
26714125Speter			dobcast = 1;
26814125Speter			syslog(LOG_ERR, "Missed alarm");
26914125Speter		}
27014125Speter	}
27114125Speter}
272121560Speter
273121560Spetervoid
27414125Speterprocess(fd, pkt_type)
27514125Speter	int fd;
27614125Speter	int pkt_type;
27714125Speter{
27814125Speter	struct sockaddr from;
27914125Speter	int fromlen = sizeof (from), cc, omask;
28014125Speter	struct ipx *ipxdp = (struct ipx *)packet;
28114125Speter
28214125Speter	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
28314125Speter	if (cc <= 0) {
28414125Speter		if (cc < 0 && errno != EINTR)
28514125Speter			syslog(LOG_ERR, "recvfrom: %m");
28614125Speter		return;
28714125Speter	}
28814125Speter	if (tracepackets > 1 && ftrace) {
28914125Speter	    fprintf(ftrace,"rcv %d bytes on %s ",
29014125Speter		    cc, ipxdp_ntoa(&ipxdp->ipx_dna));
29114125Speter	    fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
29214125Speter	}
29314125Speter
29414125Speter	if (noteremoterequests &&
29514125Speter	    !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
29614125Speter	    !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
29714125Speter	{
29814125Speter		syslog(LOG_ERR,
29914125Speter		       "net of interface (%s) != net on ether (%s)!\n",
30014125Speter		       ipxdp_nettoa(ipxdp->ipx_dna.x_net),
30114125Speter		       ipxdp_nettoa(ipxdp->ipx_sna.x_net));
30214125Speter	}
30314125Speter
30414125Speter	/* We get the IPX header in front of the RIF packet*/
30514125Speter	cc -= sizeof (struct ipx);
30614125Speter#define	mask(s)	(1<<((s)-1))
30714125Speter	omask = sigblock(mask(SIGALRM));
30814125Speter	switch(pkt_type) {
30914125Speter		case SAP_PKT: sap_input(&from, cc);
31014125Speter				break;
31114125Speter		case RIP_PKT: rip_input(&from, cc);
31214125Speter				break;
31314125Speter	}
31414125Speter	sigsetmask(omask);
31514125Speter}
31614125Speter
31714125Speterint
31814125Spetergetsocket(type, proto, sipx)
31914125Speter	int type, proto;
32014125Speter	struct sockaddr_ipx *sipx;
32114125Speter{
32214125Speter	int domain = sipx->sipx_family;
32314125Speter	int retry, s, on = 1;
32414125Speter
32514125Speter	retry = 1;
32614125Speter	while ((s = socket(domain, type, proto)) < 0 && retry) {
32714125Speter		syslog(LOG_ERR, "socket: %m");
32814125Speter		sleep(5 * retry);
32914125Speter		retry <<= 1;
33014125Speter	}
33114125Speter	if (retry == 0)
33214125Speter		return (-1);
33314125Speter	while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) {
33414125Speter		syslog(LOG_ERR, "bind: %m");
33514125Speter		sleep(5 * retry);
33614125Speter		retry <<= 1;
33714125Speter	}
33814125Speter	if (retry == 0)
33914125Speter		return (-1);
34014125Speter	if (domain==AF_IPX) {
34114125Speter		struct ipx ipxdp;
34214125Speter		if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
34314125Speter			syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
34414125Speter			exit(1);
34514125Speter		}
34614125Speter		if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP)
34714125Speter			ipxdp.ipx_pt = IPXPROTO_RI;
34814125Speter		else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP)
34914125Speter#ifdef IPXPROTO_SAP
35014125Speter			ipxdp.ipx_pt = IPXPROTO_SAP;
35114125Speter#else
35214125Speter			ipxdp.ipx_pt = IPXPROTO_PXP;
35314125Speter#endif
35414125Speter		else {
35514125Speter			syslog(LOG_ERR, "port should be either RIP or SAP");
35614125Speter			exit(1);
35714125Speter		}
35814125Speter		if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) {
35914125Speter			syslog(LOG_ERR, "setsockopt SET HEADER: %m");
36014125Speter			exit(1);
36114125Speter		}
362	}
363	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
364		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
365		exit(1);
366	}
367	return (s);
368}
369
370/*
371 * Fork and exit on EMT-- for profiling.
372 */
373void
374fkexit()
375{
376	if (fork() == 0)
377		exit(0);
378}
379
380void
381catchtimer()
382{
383	dobcast = 1;
384}
385
386void
387getinfo()
388{
389	FILE *fh;
390
391	fh = fopen("/tmp/ipxrouted.dmp", "a");
392	if(fh == NULL)
393		return;
394
395	dumpriptable(fh);
396	dumpsaptable(fh, sap_head);
397
398	fclose(fh);
399}
400
401