date and time created 83/01/11 14:35:34 by sam
[unix-history] / usr / src / sbin / routed / main.c
#ifndef lint
static char sccsid[] = "@(#)main.c 4.1 %G%";
#endif
/*
* Routing Table Management Daemon
*/
#include "router.h"
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <nlist.h>
#include <signal.h>
#include <time.h>
int supplier = -1; /* process should supply updates */
struct rip *msg = (struct rip *)packet;
main(argc, argv)
int argc;
char *argv[];
{
int cc;
struct sockaddr from;
argv0 = argv;
#ifndef DEBUG
if (fork())
exit(0);
for (cc = 0; cc < 10; cc++)
(void) close(cc);
(void) open("/", 0);
(void) dup2(0, 1);
(void) dup2(0, 2);
{ int t = open("/dev/tty", 2);
if (t >= 0) {
ioctl(t, TIOCNOTTY, (char *)0);
(void) close(t);
}
}
#endif
if (tracing)
traceon("/etc/routerlog");
/*
* We use two sockets. One for which outgoing
* packets are routed and for which they're not.
* The latter allows us to delete routing table
* entries in the kernel for network interfaces
* attached to our host which we believe are down
* while still polling it to see when/if it comes
* back up. With the new ipc interface we'll be
* able to specify ``don't route'' as an option
* to send, but until then we utilize a second port.
*/
sp = getservbyname("router", "udp");
if (sp == 0) {
fprintf(stderr, "routed: udp/router: unknown service\n");
exit(1);
}
routingaddr.sin_family = AF_INET;
routingaddr.sin_port = htons(sp->s_port);
noroutingaddr.sin_family = AF_INET;
noroutingaddr.sin_port = htons(sp->s_port + 1);
again:
s = socket(SOCK_DGRAM, 0, &routingaddr, 0);
if (s < 0) {
perror("socket");
sleep(30);
goto again;
}
again2:
snoroute = socket(SOCK_DGRAM, 0, &noroutingaddr, SO_DONTROUTE);
if (snoroute < 0) {
perror("socket");
sleep(30);
goto again2;
}
argv++, argc--;
while (argc > 0 && **argv == '-') {
if (!strcmp(*argv, "-s") == 0) {
supplier = 1;
argv++, argc--;
continue;
}
if (!strcmp(*argv, "-q") == 0) {
supplier = 0;
argv++, argc--;
continue;
}
goto usage;
}
if (argc > 0) {
usage:
fprintf(stderr, "usage: routed [ -s ] [ -q ]\n");
exit(1);
}
/*
* Collect an initial view of the world by
* snooping in the kernel and the gateway kludge
* file. Then, send a request packet on all
* directly connected networks to find out what
* everyone else thinks.
*/
rtinit();
gwkludge();
ifinit();
if (supplier < 0)
supplier = 0;
msg->rip_cmd = RIPCMD_REQUEST;
msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
toall(sendmsg);
sigset(SIGALRM, timer);
timer();
#define INFINITY 1000000
for (;;) {
int ibits;
register int n;
ibits = (1 << s) | (1 << snoroute);
n = select(32, &ibits, 0, INFINITY);
if (n < 0)
continue;
if (ibits & (1 << s))
process(s);
if (ibits & (1 << snoroute))
process(snoroute);
}
}
process(fd)
int fd;
{
register int cc;
struct sockaddr from;
cc = receive(fd, &from, packet, sizeof (packet));
if (cc <= 0) {
if (cc < 0 && errno != EINTR)
perror("receive");
return;
}
sighold(SIGALRM);
rip_input(&from, cc);
sigrelse(SIGALRM);
}