many cleanups; avoid interface timing out; put it back asap
[unix-history] / usr / src / sbin / routed / main.c
CommitLineData
fdd0ed12 1#ifndef lint
b7e4f8be 2static char sccsid[] = "@(#)main.c 4.9 (Berkeley) %G%";
fdd0ed12
SL
3#endif
4
5/*
6 * Routing Table Management Daemon
7 */
7fe7fe74 8#include "defs.h"
fdd0ed12 9#include <sys/ioctl.h>
e2feeea9
SL
10#include <sys/time.h>
11
fdd0ed12 12#include <net/if.h>
e2feeea9 13
fdd0ed12
SL
14#include <errno.h>
15#include <nlist.h>
16#include <signal.h>
fdd0ed12
SL
17
18int supplier = -1; /* process should supply updates */
19
20struct rip *msg = (struct rip *)packet;
b7e4f8be 21int hup();
fdd0ed12
SL
22
23main(argc, argv)
24 int argc;
25 char *argv[];
26{
27 int cc;
28 struct sockaddr from;
7fe7fe74
SL
29 u_char retry;
30#ifdef COMPAT
31 int snoroute;
32#endif
fdd0ed12
SL
33
34 argv0 = argv;
fdd0ed12 35 sp = getservbyname("router", "udp");
7fe7fe74
SL
36 if (sp == NULL) {
37 fprintf(stderr, "routed: router/udp: unknown service\n");
fdd0ed12
SL
38 exit(1);
39 }
7fe7fe74
SL
40 addr.sin_family = AF_INET;
41 addr.sin_port = sp->s_port;
42 s = getsocket(AF_INET, SOCK_DGRAM, &addr);
43 if (s < 0)
44 exit(1);
45#ifdef COMPAT
46 bzero(&addr, sizeof (addr));
47 addr.sin_family = AF_INET;
48 addr.sin_port = htons(ntohs(sp->s_port) + 1);
49 snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr);
50 if (snoroute < 0)
51 exit(1);
52#endif
fdd0ed12
SL
53 argv++, argc--;
54 while (argc > 0 && **argv == '-') {
d4b6a849 55 if (strcmp(*argv, "-s") == 0) {
fdd0ed12
SL
56 supplier = 1;
57 argv++, argc--;
58 continue;
59 }
d4b6a849 60 if (strcmp(*argv, "-q") == 0) {
fdd0ed12
SL
61 supplier = 0;
62 argv++, argc--;
63 continue;
64 }
d4b6a849
SL
65 if (strcmp(*argv, "-t") == 0) {
66 tracepackets++;
67 argv++, argc--;
68 continue;
69 }
70 fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n");
fdd0ed12
SL
71 exit(1);
72 }
d4b6a849
SL
73#ifndef DEBUG
74 if (!tracepackets) {
75 int t;
76
77 if (fork())
78 exit(0);
7620381d
SL
79 for (t = 0; t < 20; t++)
80 if (t != s)
81#ifdef COMPAT
55d340a4 82 if (t != snoroute)
7620381d
SL
83#endif
84 (void) close(cc);
d4b6a849
SL
85 (void) open("/", 0);
86 (void) dup2(0, 1);
87 (void) dup2(0, 2);
88 t = open("/dev/tty", 2);
89 if (t >= 0) {
90 ioctl(t, TIOCNOTTY, (char *)0);
91 (void) close(t);
92 }
93 }
94#endif
7fe7fe74
SL
95 /*
96 * Any extra argument is considered
97 * a tracing log file.
98 */
99 if (argc > 0)
100 traceon(*argv);
fdd0ed12
SL
101 /*
102 * Collect an initial view of the world by
103 * snooping in the kernel and the gateway kludge
104 * file. Then, send a request packet on all
105 * directly connected networks to find out what
106 * everyone else thinks.
107 */
108 rtinit();
109 gwkludge();
110 ifinit();
111 if (supplier < 0)
112 supplier = 0;
113 msg->rip_cmd = RIPCMD_REQUEST;
55d340a4 114 msg->rip_vers = RIPVERSION;
fdd0ed12
SL
115 msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
116 msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
55d340a4
SL
117 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
118 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
fdd0ed12 119 toall(sendmsg);
ce5e9df4 120 signal(SIGALRM, timer);
b7e4f8be 121 signal(SIGHUP, hup);
fdd0ed12
SL
122 timer();
123
fdd0ed12
SL
124 for (;;) {
125 int ibits;
126 register int n;
127
7fe7fe74
SL
128 ibits = 1 << s;
129#ifdef COMPAT
130 ibits |= 1 << snoroute;
131#endif
132 n = select(20, &ibits, 0, 0, 0);
fdd0ed12
SL
133 if (n < 0)
134 continue;
135 if (ibits & (1 << s))
136 process(s);
7fe7fe74 137#ifdef COMPAT
fdd0ed12
SL
138 if (ibits & (1 << snoroute))
139 process(snoroute);
7fe7fe74
SL
140#endif
141 /* handle ICMP redirects */
fdd0ed12
SL
142 }
143}
144
145process(fd)
146 int fd;
147{
fdd0ed12 148 struct sockaddr from;
ce5e9df4 149 int fromlen = sizeof (from), cc, omask;
fdd0ed12 150
7fe7fe74 151 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
fdd0ed12
SL
152 if (cc <= 0) {
153 if (cc < 0 && errno != EINTR)
7fe7fe74 154 perror("recvfrom");
fdd0ed12
SL
155 return;
156 }
7fe7fe74
SL
157 if (fromlen != sizeof (struct sockaddr_in))
158 return;
ce5e9df4
SL
159#define mask(s) (1<<((s)-1))
160 omask = sigblock(mask(SIGALRM));
fdd0ed12 161 rip_input(&from, cc);
ce5e9df4 162 sigsetmask(omask);
fdd0ed12 163}
7fe7fe74
SL
164
165getsocket(domain, type, sin)
166 int domain, type;
167 struct sockaddr_in *sin;
168{
169 int retry, s;
170
171 retry = 1;
172 while ((s = socket(domain, type, 0, 0)) < 0 && retry) {
173 perror("socket");
174 sleep(5 * retry);
175 retry <<= 1;
176 }
177 if (retry == 0)
178 return (-1);
179 while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) {
180 perror("bind");
181 sleep(5 * retry);
182 retry <<= 1;
183 }
184 if (retry == 0)
185 return (-1);
186 return (s);
187}