xref: /csrg-svn/sbin/routed/main.c (revision 34845)
121996Sdist /*
234566Skarels  * Copyright (c) 1983, 1988 Regents of the University of California.
333489Sbostic  * All rights reserved.
433489Sbostic  *
533489Sbostic  * Redistribution and use in source and binary forms are permitted
634771Sbostic  * provided that the above copyright notice and this paragraph are
734771Sbostic  * duplicated in all such forms and that any documentation,
834771Sbostic  * advertising materials, and other materials related to such
934771Sbostic  * distribution and use acknowledge that the software was developed
1034771Sbostic  * by the University of California, Berkeley.  The name of the
1134771Sbostic  * University may not be used to endorse or promote products derived
1234771Sbostic  * from this software without specific prior written permission.
1334771Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434771Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534771Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621996Sdist  */
1721996Sdist 
189017Ssam #ifndef lint
1921996Sdist char copyright[] =
2034566Skarels "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
2121996Sdist  All rights reserved.\n";
2233489Sbostic #endif /* not lint */
239017Ssam 
2421996Sdist #ifndef lint
25*34845Skarels static char sccsid[] = "@(#)main.c	5.15 (Berkeley) 06/27/88";
2633489Sbostic #endif /* not lint */
2721996Sdist 
289017Ssam /*
299017Ssam  * Routing Table Management Daemon
309017Ssam  */
3110245Ssam #include "defs.h"
329017Ssam #include <sys/ioctl.h>
3313602Ssam #include <sys/time.h>
3413602Ssam 
359017Ssam #include <net/if.h>
3613602Ssam 
3734566Skarels #include <sys/errno.h>
3834566Skarels #include <sys/signal.h>
3934566Skarels #include <sys/syslog.h>
409017Ssam 
419017Ssam int	supplier = -1;		/* process should supply updates */
4221847Skarels int	gateway = 0;		/* 1 if we are a gateway to parts beyond */
4331220Skarels int	debug = 0;
449017Ssam 
459017Ssam struct	rip *msg = (struct rip *)packet;
4634566Skarels int	hup(), rtdeleteall(), sigtrace();
479017Ssam 
489017Ssam main(argc, argv)
499017Ssam 	int argc;
509017Ssam 	char *argv[];
519017Ssam {
529017Ssam 	int cc;
539017Ssam 	struct sockaddr from;
5410245Ssam 	u_char retry;
559017Ssam 
569017Ssam 	argv0 = argv;
57*34845Skarels #if BSD >= 43
5824848Seric 	openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
5930930Skarels 	setlogmask(LOG_UPTO(LOG_WARNING));
60*34845Skarels #else
61*34845Skarels 	openlog("routed", LOG_PID);
62*34845Skarels #define LOG_UPTO(x) (x)
63*34845Skarels #define setlogmask(x) (x)
64*34845Skarels #endif
659017Ssam 	sp = getservbyname("router", "udp");
6610245Ssam 	if (sp == NULL) {
6710245Ssam 		fprintf(stderr, "routed: router/udp: unknown service\n");
689017Ssam 		exit(1);
699017Ssam 	}
7010245Ssam 	addr.sin_family = AF_INET;
7110245Ssam 	addr.sin_port = sp->s_port;
7210245Ssam 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
7310245Ssam 	if (s < 0)
7410245Ssam 		exit(1);
759017Ssam 	argv++, argc--;
769017Ssam 	while (argc > 0 && **argv == '-') {
7710636Ssam 		if (strcmp(*argv, "-s") == 0) {
789017Ssam 			supplier = 1;
799017Ssam 			argv++, argc--;
809017Ssam 			continue;
819017Ssam 		}
8210636Ssam 		if (strcmp(*argv, "-q") == 0) {
839017Ssam 			supplier = 0;
849017Ssam 			argv++, argc--;
859017Ssam 			continue;
869017Ssam 		}
8710636Ssam 		if (strcmp(*argv, "-t") == 0) {
8834566Skarels 			if (tracehistory == 0)
8934566Skarels 				tracehistory++;
9034566Skarels 			else {
9134566Skarels 				tracehistory = 0;
9234566Skarels 				tracepackets++;
9334566Skarels 			}
9430930Skarels 			setlogmask(LOG_UPTO(LOG_DEBUG));
9510636Ssam 			argv++, argc--;
9610636Ssam 			continue;
9710636Ssam 		}
9826341Skarels 		if (strcmp(*argv, "-d") == 0) {
9931220Skarels 			debug++;
10030930Skarels 			setlogmask(LOG_UPTO(LOG_DEBUG));
10126341Skarels 			argv++, argc--;
10226341Skarels 			continue;
10326341Skarels 		}
10416326Skarels 		if (strcmp(*argv, "-g") == 0) {
10516326Skarels 			gateway = 1;
10616326Skarels 			argv++, argc--;
10716326Skarels 			continue;
10816326Skarels 		}
10916326Skarels 		fprintf(stderr,
11021847Skarels 			"usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
1119017Ssam 		exit(1);
1129017Ssam 	}
11331220Skarels 	if (tracepackets == 0 && debug == 0) {
11410636Ssam 		int t;
11510636Ssam 
11610636Ssam 		if (fork())
11710636Ssam 			exit(0);
11810637Ssam 		for (t = 0; t < 20; t++)
11910637Ssam 			if (t != s)
12024761Ssklower 				(void) close(t);
12110636Ssam 		(void) open("/", 0);
12210636Ssam 		(void) dup2(0, 1);
12310636Ssam 		(void) dup2(0, 2);
12410636Ssam 		t = open("/dev/tty", 2);
12510636Ssam 		if (t >= 0) {
12610636Ssam 			ioctl(t, TIOCNOTTY, (char *)0);
12710636Ssam 			(void) close(t);
12810636Ssam 		}
12910636Ssam 	}
1309017Ssam 	/*
13110245Ssam 	 * Any extra argument is considered
13210245Ssam 	 * a tracing log file.
13310245Ssam 	 */
13410245Ssam 	if (argc > 0)
13510245Ssam 		traceon(*argv);
13610245Ssam 	/*
1379017Ssam 	 * Collect an initial view of the world by
13821847Skarels 	 * checking the interface configuration and the gateway kludge
1399017Ssam 	 * file.  Then, send a request packet on all
1409017Ssam 	 * directly connected networks to find out what
1419017Ssam 	 * everyone else thinks.
1429017Ssam 	 */
1439017Ssam 	rtinit();
14430927Skarels 	ifinit();
1459017Ssam 	gwkludge();
14621847Skarels 	if (gateway > 0)
14721847Skarels 		rtdefault();
1489017Ssam 	if (supplier < 0)
1499017Ssam 		supplier = 0;
1509017Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
15112726Ssam 	msg->rip_vers = RIPVERSION;
1529017Ssam 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
1539017Ssam 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
15412726Ssam 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
15512726Ssam 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
1569017Ssam 	toall(sendmsg);
15713036Ssam 	signal(SIGALRM, timer);
15816314Skarels 	signal(SIGHUP, hup);
15917570Skarels 	signal(SIGTERM, hup);
16031220Skarels 	signal(SIGINT, rtdeleteall);
16134566Skarels 	signal(SIGUSR1, sigtrace);
16234566Skarels 	signal(SIGUSR2, sigtrace);
1639017Ssam 	timer();
1649017Ssam 
1659017Ssam 	for (;;) {
1669017Ssam 		int ibits;
1679017Ssam 		register int n;
1689017Ssam 
16910245Ssam 		ibits = 1 << s;
17010245Ssam 		n = select(20, &ibits, 0, 0, 0);
1719017Ssam 		if (n < 0)
1729017Ssam 			continue;
1739017Ssam 		if (ibits & (1 << s))
1749017Ssam 			process(s);
17510245Ssam 		/* handle ICMP redirects */
1769017Ssam 	}
1779017Ssam }
1789017Ssam 
1799017Ssam process(fd)
1809017Ssam 	int fd;
1819017Ssam {
1829017Ssam 	struct sockaddr from;
18313036Ssam 	int fromlen = sizeof (from), cc, omask;
18434566Skarels 	time_t now;
1859017Ssam 
18610245Ssam 	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
1879017Ssam 	if (cc <= 0) {
1889017Ssam 		if (cc < 0 && errno != EINTR)
18910245Ssam 			perror("recvfrom");
1909017Ssam 		return;
1919017Ssam 	}
19210245Ssam 	if (fromlen != sizeof (struct sockaddr_in))
19310245Ssam 		return;
19434566Skarels 	if (traceactions && !tracepackets) {
19534566Skarels 		(void) time(&now);
19634566Skarels 		curtime = ctime(&now);
19734566Skarels 	}
19824761Ssklower 	omask = sigblock(sigmask(SIGALRM));
1999017Ssam 	rip_input(&from, cc);
20013036Ssam 	sigsetmask(omask);
2019017Ssam }
20210245Ssam 
20310245Ssam getsocket(domain, type, sin)
20410245Ssam 	int domain, type;
20510245Ssam 	struct sockaddr_in *sin;
20610245Ssam {
20725516Skarels 	int s, on = 1;
20810245Ssam 
20925702Smckusick 	if ((s = socket(domain, type, 0)) < 0) {
21010245Ssam 		perror("socket");
21117570Skarels 		syslog(LOG_ERR, "socket: %m");
21210245Ssam 		return (-1);
21317570Skarels 	}
214*34845Skarels #ifdef SO_BROADCAST
21517570Skarels 	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
21617570Skarels 		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
21725516Skarels 		close(s);
21825516Skarels 		return (-1);
21917570Skarels 	}
220*34845Skarels #endif
221*34845Skarels #ifdef SO_RCVBUF
22230927Skarels 	on = 48*1024;
22330927Skarels 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) < 0)
22430927Skarels 		syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
225*34845Skarels #endif
22625516Skarels 	if (bind(s, sin, sizeof (*sin), 0) < 0) {
22710245Ssam 		perror("bind");
22817570Skarels 		syslog(LOG_ERR, "bind: %m");
22925516Skarels 		close(s);
23010245Ssam 		return (-1);
23117570Skarels 	}
23210245Ssam 	return (s);
23310245Ssam }
234