main.c revision 12692
111820Sjulian/*
211820Sjulian * Copyright (c) 1985, 1993
311820Sjulian *	The Regents of the University of California.  All rights reserved.
411820Sjulian *
511820Sjulian * Copyright (c) 1995 John Hay.  All rights reserved.
611820Sjulian *
711820Sjulian * This file includes significant work done at Cornell University by
811820Sjulian * Bill Nesheim.  That work included by permission.
911820Sjulian *
1011820Sjulian * Redistribution and use in source and binary forms, with or without
1111820Sjulian * modification, are permitted provided that the following conditions
1211820Sjulian * are met:
1311820Sjulian * 1. Redistributions of source code must retain the above copyright
1411820Sjulian *    notice, this list of conditions and the following disclaimer.
1511820Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1611820Sjulian *    notice, this list of conditions and the following disclaimer in the
1711820Sjulian *    documentation and/or other materials provided with the distribution.
1811820Sjulian * 3. All advertising materials mentioning features or use of this software
1911820Sjulian *    must display the following acknowledgement:
2011820Sjulian *	This product includes software developed by the University of
2111820Sjulian *	California, Berkeley and its contributors.
2211820Sjulian * 4. Neither the name of the University nor the names of its contributors
2311820Sjulian *    may be used to endorse or promote products derived from this software
2411820Sjulian *    without specific prior written permission.
2511820Sjulian *
2611820Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2711820Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2811820Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2911820Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3011820Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3111820Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3211820Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3311820Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3411820Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3511820Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3611820Sjulian * SUCH DAMAGE.
3711820Sjulian *
3812692Sjulian *	$Id: main.c,v 1.2 1995/10/27 10:48:28 julian Exp $
3911820Sjulian */
4011820Sjulian
4111820Sjulian#ifndef lint
4211820Sjulianstatic char copyright[] =
4311820Sjulian"@(#) Copyright (c) 1985, 1993\n\
4411820Sjulian	The Regents of the University of California.  All rights reserved.\n";
4511820Sjulian#endif /* not lint */
4611820Sjulian
4711820Sjulian#ifndef lint
4811820Sjulianstatic char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93";
4911820Sjulian#endif /* not lint */
5011820Sjulian
5111820Sjulian/*
5211820Sjulian * IPX Routing Information Protocol Daemon
5311820Sjulian */
5411820Sjulian#include "defs.h"
5511820Sjulian#include <sys/time.h>
5611820Sjulian
5711820Sjulian#include <net/if.h>
5811820Sjulian
5911820Sjulian#include <errno.h>
6011820Sjulian#include <nlist.h>
6111820Sjulian#include <signal.h>
6211820Sjulian#include <paths.h>
6311820Sjulian#include <stdlib.h>
6411820Sjulian#include <unistd.h>
6511820Sjulian
6611820Sjulian#define SAP_PKT		0
6711820Sjulian#define RIP_PKT		1
6811820Sjulian
6911820Sjulianstruct	sockaddr_ipx addr;	/* Daemon's Address */
7011820Sjulianint	ripsock;		/* RIP Socket to listen on */
7111820Sjulianint	sapsock;		/* SAP Socket to listen on */
7211820Sjulianint	kmem;
7311820Sjulianint	install;		/* if 1 call kernel */
7411820Sjulianint	lookforinterfaces;	/* if 1 probe kernel for new up interfaces */
7511820Sjulianint	performnlist;		/* if 1 check if /kernel has changed */
7611820Sjulianint	externalinterfaces;	/* # of remote and local interfaces */
7711820Sjulianint	timeval;		/* local idea of time */
7811820Sjulianint	noteremoterequests;	/* squawk on requests from non-local nets */
7911820Sjulianint	r;			/* Routing socket to install updates with */
8011820Sjulianstruct	sockaddr_ipx ipx_netmask;	/* Used in installing routes */
8111820Sjulian
8211840Sjulianchar	packet[MAXPACKETSIZE+sizeof(struct ipx)+1];
8311820Sjulian
8411820Sjulianchar	**argv0;
8511820Sjulian
8611820Sjulianint	supplier = -1;		/* process should supply updates */
8711820Sjulianint	dosap = 1;		/* By default do SAP services. */
8811820Sjulian
8911840Sjulianstruct	rip *msg = (struct rip *) &packet[sizeof (struct ipx)];
9011820Sjulianstruct	sap_packet *sap_msg =
9111840Sjulian		(struct sap_packet *) &packet[sizeof (struct ipx)];
9211820Sjulianvoid	hup(), fkexit(), timer();
9311820Sjulianvoid	process(int fd, int pkt_type);
9411820Sjulianint	getsocket(int type, int proto, struct sockaddr_ipx *sipx);
9511820Sjulian
9611820Sjulianint
9711820Sjulianmain(argc, argv)
9811820Sjulian	int argc;
9911820Sjulian	char *argv[];
10011820Sjulian{
10111820Sjulian	int nfds;
10211820Sjulian	fd_set fdvar;
10311820Sjulian
10411820Sjulian	argv0 = argv;
10511820Sjulian	argv++, argc--;
10611820Sjulian	while (argc > 0 && **argv == '-') {
10711820Sjulian		if (strcmp(*argv, "-s") == 0) {
10811820Sjulian			supplier = 1;
10911820Sjulian			argv++, argc--;
11011820Sjulian			continue;
11111820Sjulian		}
11211820Sjulian		if (strcmp(*argv, "-q") == 0) {
11311820Sjulian			supplier = 0;
11411820Sjulian			argv++, argc--;
11511820Sjulian			continue;
11611820Sjulian		}
11711820Sjulian		if (strcmp(*argv, "-R") == 0) {
11811820Sjulian			noteremoterequests++;
11911820Sjulian			argv++, argc--;
12011820Sjulian			continue;
12111820Sjulian		}
12211820Sjulian		if (strcmp(*argv, "-S") == 0) {
12311820Sjulian			dosap = 0;
12411820Sjulian			argv++, argc--;
12511820Sjulian			continue;
12611820Sjulian		}
12711820Sjulian		if (strcmp(*argv, "-t") == 0) {
12811820Sjulian			tracepackets++;
12911820Sjulian			argv++, argc--;
13011820Sjulian			ftrace = stderr;
13111820Sjulian			tracing = 1;
13211820Sjulian			continue;
13311820Sjulian		}
13411820Sjulian		if (strcmp(*argv, "-g") == 0) {
13511820Sjulian			gateway = 1;
13611820Sjulian			argv++, argc--;
13711820Sjulian			continue;
13811820Sjulian		}
13911820Sjulian		if (strcmp(*argv, "-l") == 0) {
14011820Sjulian			gateway = -1;
14111820Sjulian			argv++, argc--;
14211820Sjulian			continue;
14311820Sjulian		}
14411820Sjulian		fprintf(stderr,
14511820Sjulian			"usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
14611820Sjulian		exit(1);
14711820Sjulian	}
14811820Sjulian
14911820Sjulian
15011820Sjulian#ifndef DEBUG
15111820Sjulian	if (!tracepackets)
15211820Sjulian		daemon(0, 0);
15311820Sjulian#endif
15411820Sjulian	openlog("IPXrouted", LOG_PID, LOG_DAEMON);
15511820Sjulian
15611820Sjulian	addr.sipx_family = AF_IPX;
15711820Sjulian	addr.sipx_len = sizeof(addr);
15811820Sjulian	addr.sipx_port = htons(IPXPORT_RIP);
15911820Sjulian	ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1;
16011820Sjulian	ipx_netmask.sipx_addr.x_net = ipx_anynet;
16111820Sjulian	ipx_netmask.sipx_len = 6;
16211820Sjulian	ipx_netmask.sipx_family = AF_IPX;
16311820Sjulian	r = socket(AF_ROUTE, SOCK_RAW, 0);
16411820Sjulian	/* later, get smart about lookingforinterfaces */
16511820Sjulian	if (r)
16611820Sjulian		shutdown(r, 0); /* for now, don't want reponses */
16711820Sjulian	else {
16811820Sjulian		fprintf(stderr, "IPXrouted: no routing socket\n");
16911820Sjulian		exit(1);
17011820Sjulian	}
17111820Sjulian	ripsock = getsocket(SOCK_DGRAM, 0, &addr);
17211820Sjulian	if (ripsock < 0)
17311820Sjulian		exit(1);
17411820Sjulian
17511820Sjulian	if (dosap) {
17611820Sjulian		addr.sipx_port = htons(IPXPORT_SAP);
17711820Sjulian		sapsock = getsocket(SOCK_DGRAM, 0, &addr);
17811820Sjulian		if (sapsock < 0)
17911820Sjulian			exit(1);
18011820Sjulian	} else
18111820Sjulian		sapsock = -1;
18211820Sjulian
18311820Sjulian	/*
18411820Sjulian	 * Any extra argument is considered
18511820Sjulian	 * a tracing log file.
18611820Sjulian	 */
18711820Sjulian	if (argc > 0)
18811820Sjulian		traceon(*argv);
18911820Sjulian	/*
19011820Sjulian	 * Collect an initial view of the world by
19111820Sjulian	 * snooping in the kernel.  Then, send a request packet on all
19211820Sjulian	 * directly connected networks to find out what
19311820Sjulian	 * everyone else thinks.
19411820Sjulian	 */
19511820Sjulian	rtinit();
19611820Sjulian	sapinit();
19711820Sjulian	ifinit();
19811820Sjulian	if (supplier < 0)
19911820Sjulian		supplier = 0;
20011820Sjulian	/* request the state of the world */
20111820Sjulian	msg->rip_cmd = htons(RIPCMD_REQUEST);
20211820Sjulian	msg->rip_nets[0].rip_dst = ipx_anynet;
20311820Sjulian	msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
20411820Sjulian	msg->rip_nets[0].rip_ticks =  htons(-1);
20511820Sjulian	toall(sndmsg, NULL);
20611820Sjulian
20711820Sjulian	if (dosap) {
20811820Sjulian		sap_msg->sap_cmd = htons(SAP_REQ);
20911820Sjulian		sap_msg->sap[0].ServType = htons(SAP_WILDCARD);
21011820Sjulian		toall(sapsndmsg, NULL);
21111820Sjulian	}
21211820Sjulian
21311820Sjulian	signal(SIGALRM, timer);
21411820Sjulian	signal(SIGHUP, hup);
21511820Sjulian	signal(SIGINT, hup);
21611820Sjulian	signal(SIGEMT, fkexit);
21711820Sjulian	timer();
21811820Sjulian
21911820Sjulian	nfds = 1 + max(sapsock, ripsock);
22011820Sjulian
22111820Sjulian	for (;;) {
22211820Sjulian		FD_ZERO(&fdvar);
22311820Sjulian		if (dosap) {
22411820Sjulian			FD_SET(sapsock, &fdvar);
22511820Sjulian		}
22611820Sjulian		FD_SET(ripsock, &fdvar);
22711820Sjulian
22811820Sjulian		if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL,
22911820Sjulian		   (struct timeval *)NULL) < 0) {
23012692Sjulian			if(errno == EINTR)
23112692Sjulian				continue;
23212692Sjulian			perror("during select");
23312692Sjulian			exit(1);
23411820Sjulian		}
23511820Sjulian
23611820Sjulian		if(FD_ISSET(ripsock, &fdvar))
23711820Sjulian			process(ripsock, RIP_PKT);
23811820Sjulian
23911820Sjulian		if(dosap && FD_ISSET(sapsock, &fdvar))
24011820Sjulian			process(sapsock, SAP_PKT);
24111820Sjulian	}
24211820Sjulian}
24311820Sjulian
24411820Sjulianvoid
24511820Sjulianprocess(fd, pkt_type)
24611820Sjulian	int fd;
24711820Sjulian	int pkt_type;
24811820Sjulian{
24911820Sjulian	struct sockaddr from;
25011820Sjulian	int fromlen = sizeof (from), cc, omask;
25111840Sjulian	struct ipx *ipxdp = (struct ipx *)packet;
25211820Sjulian
25311820Sjulian	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
25411820Sjulian	if (cc <= 0) {
25511820Sjulian		if (cc < 0 && errno != EINTR)
25611820Sjulian			syslog(LOG_ERR, "recvfrom: %m");
25711820Sjulian		return;
25811820Sjulian	}
25911820Sjulian	if (tracepackets > 1 && ftrace) {
26011820Sjulian	    fprintf(ftrace,"rcv %d bytes on %s ",
26111840Sjulian		    cc, ipxdp_ntoa(&ipxdp->ipx_dna));
26211840Sjulian	    fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
26311820Sjulian	}
26411820Sjulian
26511820Sjulian	if (noteremoterequests &&
26611840Sjulian	    !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
26711840Sjulian	    !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
26811820Sjulian	{
26911820Sjulian		syslog(LOG_ERR,
27011820Sjulian		       "net of interface (%s) != net on ether (%s)!\n",
27111840Sjulian		       ipxdp_nettoa(ipxdp->ipx_dna.x_net),
27211840Sjulian		       ipxdp_nettoa(ipxdp->ipx_sna.x_net));
27311820Sjulian	}
27411820Sjulian
27511820Sjulian	/* We get the IPX header in front of the RIF packet*/
27611840Sjulian	cc -= sizeof (struct ipx);
27711820Sjulian#define	mask(s)	(1<<((s)-1))
27811820Sjulian	omask = sigblock(mask(SIGALRM));
27911820Sjulian	switch(pkt_type) {
28011820Sjulian		case SAP_PKT: sap_input(&from, cc);
28111820Sjulian				break;
28211820Sjulian		case RIP_PKT: rip_input(&from, cc);
28311820Sjulian				break;
28411820Sjulian	}
28511820Sjulian	sigsetmask(omask);
28611820Sjulian}
28711820Sjulian
28811820Sjulianint
28911820Sjuliangetsocket(type, proto, sipx)
29011820Sjulian	int type, proto;
29111820Sjulian	struct sockaddr_ipx *sipx;
29211820Sjulian{
29311820Sjulian	int domain = sipx->sipx_family;
29411820Sjulian	int retry, s, on = 1;
29511820Sjulian
29611820Sjulian	retry = 1;
29711820Sjulian	while ((s = socket(domain, type, proto)) < 0 && retry) {
29811820Sjulian		syslog(LOG_ERR, "socket: %m");
29911820Sjulian		sleep(5 * retry);
30011820Sjulian		retry <<= 1;
30111820Sjulian	}
30211820Sjulian	if (retry == 0)
30311820Sjulian		return (-1);
30411820Sjulian	while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) {
30511820Sjulian		syslog(LOG_ERR, "bind: %m");
30611820Sjulian		sleep(5 * retry);
30711820Sjulian		retry <<= 1;
30811820Sjulian	}
30911820Sjulian	if (retry == 0)
31011820Sjulian		return (-1);
31111820Sjulian	if (domain==AF_IPX) {
31211840Sjulian		struct ipx ipxdp;
31311820Sjulian		if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
31411820Sjulian			syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
31511820Sjulian			exit(1);
31611820Sjulian		}
31711820Sjulian		if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP)
31811840Sjulian			ipxdp.ipx_pt = IPXPROTO_RI;
31911820Sjulian		else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP)
32011840Sjulian			ipxdp.ipx_pt = IPXPROTO_SAP;
32111820Sjulian		else {
32211820Sjulian			syslog(LOG_ERR, "port should be either RIP or SAP");
32311820Sjulian			exit(1);
32411820Sjulian		}
32511820Sjulian		if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) {
32611820Sjulian			syslog(LOG_ERR, "setsockopt SET HEADER: %m");
32711820Sjulian			exit(1);
32811820Sjulian		}
32911820Sjulian	}
33011820Sjulian	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
33111820Sjulian		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
33211820Sjulian		exit(1);
33311820Sjulian	}
33411820Sjulian	return (s);
33511820Sjulian}
33611820Sjulian
33711820Sjulian/*
33811820Sjulian * Fork and exit on EMT-- for profiling.
33911820Sjulian */
34011820Sjulianvoid
34111820Sjulianfkexit()
34211820Sjulian{
34311820Sjulian	if (fork() == 0)
34411820Sjulian		exit(0);
34511820Sjulian}
346