many cleanups; avoid interface timing out; put it back asap
[unix-history] / usr / src / sbin / routed / main.c
... / ...
CommitLineData
1#ifndef lint
2static char sccsid[] = "@(#)main.c 4.9 (Berkeley) %G%";
3#endif
4
5/*
6 * Routing Table Management Daemon
7 */
8#include "defs.h"
9#include <sys/ioctl.h>
10#include <sys/time.h>
11
12#include <net/if.h>
13
14#include <errno.h>
15#include <nlist.h>
16#include <signal.h>
17
18int supplier = -1; /* process should supply updates */
19
20struct rip *msg = (struct rip *)packet;
21int hup();
22
23main(argc, argv)
24 int argc;
25 char *argv[];
26{
27 int cc;
28 struct sockaddr from;
29 u_char retry;
30#ifdef COMPAT
31 int snoroute;
32#endif
33
34 argv0 = argv;
35 sp = getservbyname("router", "udp");
36 if (sp == NULL) {
37 fprintf(stderr, "routed: router/udp: unknown service\n");
38 exit(1);
39 }
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
53 argv++, argc--;
54 while (argc > 0 && **argv == '-') {
55 if (strcmp(*argv, "-s") == 0) {
56 supplier = 1;
57 argv++, argc--;
58 continue;
59 }
60 if (strcmp(*argv, "-q") == 0) {
61 supplier = 0;
62 argv++, argc--;
63 continue;
64 }
65 if (strcmp(*argv, "-t") == 0) {
66 tracepackets++;
67 argv++, argc--;
68 continue;
69 }
70 fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n");
71 exit(1);
72 }
73#ifndef DEBUG
74 if (!tracepackets) {
75 int t;
76
77 if (fork())
78 exit(0);
79 for (t = 0; t < 20; t++)
80 if (t != s)
81#ifdef COMPAT
82 if (t != snoroute)
83#endif
84 (void) close(cc);
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
95 /*
96 * Any extra argument is considered
97 * a tracing log file.
98 */
99 if (argc > 0)
100 traceon(*argv);
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;
114 msg->rip_vers = RIPVERSION;
115 msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
116 msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
117 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
118 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
119 toall(sendmsg);
120 signal(SIGALRM, timer);
121 signal(SIGHUP, hup);
122 timer();
123
124 for (;;) {
125 int ibits;
126 register int n;
127
128 ibits = 1 << s;
129#ifdef COMPAT
130 ibits |= 1 << snoroute;
131#endif
132 n = select(20, &ibits, 0, 0, 0);
133 if (n < 0)
134 continue;
135 if (ibits & (1 << s))
136 process(s);
137#ifdef COMPAT
138 if (ibits & (1 << snoroute))
139 process(snoroute);
140#endif
141 /* handle ICMP redirects */
142 }
143}
144
145process(fd)
146 int fd;
147{
148 struct sockaddr from;
149 int fromlen = sizeof (from), cc, omask;
150
151 cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
152 if (cc <= 0) {
153 if (cc < 0 && errno != EINTR)
154 perror("recvfrom");
155 return;
156 }
157 if (fromlen != sizeof (struct sockaddr_in))
158 return;
159#define mask(s) (1<<((s)-1))
160 omask = sigblock(mask(SIGALRM));
161 rip_input(&from, cc);
162 sigsetmask(omask);
163}
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}