xref: /csrg-svn/sbin/routed/main.c (revision 30930)
121996Sdist /*
221996Sdist  * Copyright (c) 1983 Regents of the University of California.
321996Sdist  * All rights reserved.  The Berkeley software License Agreement
421996Sdist  * specifies the terms and conditions for redistribution.
521996Sdist  */
621996Sdist 
79017Ssam #ifndef lint
821996Sdist char copyright[] =
921996Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
1021996Sdist  All rights reserved.\n";
1121996Sdist #endif not lint
129017Ssam 
1321996Sdist #ifndef lint
14*30930Skarels static char sccsid[] = "@(#)main.c	5.10 (Berkeley) 04/20/87";
1521996Sdist #endif not lint
1621996Sdist 
179017Ssam /*
189017Ssam  * Routing Table Management Daemon
199017Ssam  */
2010245Ssam #include "defs.h"
219017Ssam #include <sys/ioctl.h>
2213602Ssam #include <sys/time.h>
2313602Ssam 
249017Ssam #include <net/if.h>
2513602Ssam 
269017Ssam #include <errno.h>
279017Ssam #include <signal.h>
2817570Skarels #include <syslog.h>
299017Ssam 
309017Ssam int	supplier = -1;		/* process should supply updates */
3121847Skarels int	gateway = 0;		/* 1 if we are a gateway to parts beyond */
329017Ssam 
339017Ssam struct	rip *msg = (struct rip *)packet;
3416314Skarels int	hup();
359017Ssam 
369017Ssam main(argc, argv)
379017Ssam 	int argc;
389017Ssam 	char *argv[];
399017Ssam {
409017Ssam 	int cc;
419017Ssam 	struct sockaddr from;
4210245Ssam 	u_char retry;
439017Ssam 
449017Ssam 	argv0 = argv;
4524848Seric 	openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
46*30930Skarels 	setlogmask(LOG_UPTO(LOG_WARNING));
479017Ssam 	sp = getservbyname("router", "udp");
4810245Ssam 	if (sp == NULL) {
4910245Ssam 		fprintf(stderr, "routed: router/udp: unknown service\n");
509017Ssam 		exit(1);
519017Ssam 	}
5210245Ssam 	addr.sin_family = AF_INET;
5310245Ssam 	addr.sin_port = sp->s_port;
5410245Ssam 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
5510245Ssam 	if (s < 0)
5610245Ssam 		exit(1);
579017Ssam 	argv++, argc--;
589017Ssam 	while (argc > 0 && **argv == '-') {
5910636Ssam 		if (strcmp(*argv, "-s") == 0) {
609017Ssam 			supplier = 1;
619017Ssam 			argv++, argc--;
629017Ssam 			continue;
639017Ssam 		}
6410636Ssam 		if (strcmp(*argv, "-q") == 0) {
659017Ssam 			supplier = 0;
669017Ssam 			argv++, argc--;
679017Ssam 			continue;
689017Ssam 		}
6910636Ssam 		if (strcmp(*argv, "-t") == 0) {
7010636Ssam 			tracepackets++;
71*30930Skarels 			setlogmask(LOG_UPTO(LOG_DEBUG));
7210636Ssam 			argv++, argc--;
7310636Ssam 			continue;
7410636Ssam 		}
7526341Skarels 		if (strcmp(*argv, "-d") == 0) {
76*30930Skarels 			setlogmask(LOG_UPTO(LOG_DEBUG));
7726341Skarels 			argv++, argc--;
7826341Skarels 			continue;
7926341Skarels 		}
8016326Skarels 		if (strcmp(*argv, "-g") == 0) {
8116326Skarels 			gateway = 1;
8216326Skarels 			argv++, argc--;
8316326Skarels 			continue;
8416326Skarels 		}
8516326Skarels 		fprintf(stderr,
8621847Skarels 			"usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
879017Ssam 		exit(1);
889017Ssam 	}
8910636Ssam #ifndef DEBUG
9010636Ssam 	if (!tracepackets) {
9110636Ssam 		int t;
9210636Ssam 
9310636Ssam 		if (fork())
9410636Ssam 			exit(0);
9510637Ssam 		for (t = 0; t < 20; t++)
9610637Ssam 			if (t != s)
9724761Ssklower 				(void) close(t);
9810636Ssam 		(void) open("/", 0);
9910636Ssam 		(void) dup2(0, 1);
10010636Ssam 		(void) dup2(0, 2);
10110636Ssam 		t = open("/dev/tty", 2);
10210636Ssam 		if (t >= 0) {
10310636Ssam 			ioctl(t, TIOCNOTTY, (char *)0);
10410636Ssam 			(void) close(t);
10510636Ssam 		}
10610636Ssam 	}
10710636Ssam #endif
1089017Ssam 	/*
10910245Ssam 	 * Any extra argument is considered
11010245Ssam 	 * a tracing log file.
11110245Ssam 	 */
11210245Ssam 	if (argc > 0)
11310245Ssam 		traceon(*argv);
11410245Ssam 	/*
1159017Ssam 	 * Collect an initial view of the world by
11621847Skarels 	 * checking the interface configuration and the gateway kludge
1179017Ssam 	 * file.  Then, send a request packet on all
1189017Ssam 	 * directly connected networks to find out what
1199017Ssam 	 * everyone else thinks.
1209017Ssam 	 */
1219017Ssam 	rtinit();
12230927Skarels 	ifinit();
1239017Ssam 	gwkludge();
12421847Skarels 	if (gateway > 0)
12521847Skarels 		rtdefault();
1269017Ssam 	if (supplier < 0)
1279017Ssam 		supplier = 0;
1289017Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
12912726Ssam 	msg->rip_vers = RIPVERSION;
1309017Ssam 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
1319017Ssam 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
13212726Ssam 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
13312726Ssam 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
1349017Ssam 	toall(sendmsg);
13513036Ssam 	signal(SIGALRM, timer);
13616314Skarels 	signal(SIGHUP, hup);
13717570Skarels 	signal(SIGTERM, hup);
1389017Ssam 	timer();
1399017Ssam 
1409017Ssam 	for (;;) {
1419017Ssam 		int ibits;
1429017Ssam 		register int n;
1439017Ssam 
14410245Ssam 		ibits = 1 << s;
14510245Ssam 		n = select(20, &ibits, 0, 0, 0);
1469017Ssam 		if (n < 0)
1479017Ssam 			continue;
1489017Ssam 		if (ibits & (1 << s))
1499017Ssam 			process(s);
15010245Ssam 		/* handle ICMP redirects */
1519017Ssam 	}
1529017Ssam }
1539017Ssam 
1549017Ssam process(fd)
1559017Ssam 	int fd;
1569017Ssam {
1579017Ssam 	struct sockaddr from;
15813036Ssam 	int fromlen = sizeof (from), cc, omask;
1599017Ssam 
16010245Ssam 	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
1619017Ssam 	if (cc <= 0) {
1629017Ssam 		if (cc < 0 && errno != EINTR)
16310245Ssam 			perror("recvfrom");
1649017Ssam 		return;
1659017Ssam 	}
16610245Ssam 	if (fromlen != sizeof (struct sockaddr_in))
16710245Ssam 		return;
16824761Ssklower 	omask = sigblock(sigmask(SIGALRM));
1699017Ssam 	rip_input(&from, cc);
17013036Ssam 	sigsetmask(omask);
1719017Ssam }
17210245Ssam 
17310245Ssam getsocket(domain, type, sin)
17410245Ssam 	int domain, type;
17510245Ssam 	struct sockaddr_in *sin;
17610245Ssam {
17725516Skarels 	int s, on = 1;
17810245Ssam 
17925702Smckusick 	if ((s = socket(domain, type, 0)) < 0) {
18010245Ssam 		perror("socket");
18117570Skarels 		syslog(LOG_ERR, "socket: %m");
18210245Ssam 		return (-1);
18317570Skarels 	}
18417570Skarels 	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
18517570Skarels 		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
18625516Skarels 		close(s);
18725516Skarels 		return (-1);
18817570Skarels 	}
18930927Skarels 	on = 48*1024;
19030927Skarels 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) < 0)
19130927Skarels 		syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
19225516Skarels 	if (bind(s, sin, sizeof (*sin), 0) < 0) {
19310245Ssam 		perror("bind");
19417570Skarels 		syslog(LOG_ERR, "bind: %m");
19525516Skarels 		close(s);
19610245Ssam 		return (-1);
19717570Skarels 	}
19810245Ssam 	return (s);
19910245Ssam }
200