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