Commit | Line | Data |
---|---|---|
f6daefea KS |
1 | #ifndef lint |
2 | static char rcsid[] = "$Header$"; | |
3 | #endif | |
4 | ||
5 | /* | |
6 | * XNS Routing Information Protocol 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 | ||
18 | int supplier = -1; /* process should supply updates */ | |
19 | extern int gateway; | |
20 | ||
21 | struct rip *msg = (struct rip *) &packet[sizeof (struct idp)]; | |
22 | int hup(), fkexit(); | |
23 | ||
24 | main(argc, argv) | |
25 | int argc; | |
26 | char *argv[]; | |
27 | { | |
28 | struct sockaddr from; | |
29 | u_char retry; | |
30 | int selectbits; | |
31 | struct interface *ifp; | |
32 | extern struct interface *ifnet; | |
33 | ||
34 | argv0 = argv; | |
35 | argv++, argc--; | |
36 | while (argc > 0 && **argv == '-') { | |
37 | if (strcmp(*argv, "-s") == 0) { | |
38 | supplier = 1; | |
39 | argv++, argc--; | |
40 | continue; | |
41 | } | |
42 | if (strcmp(*argv, "-q") == 0) { | |
43 | supplier = 0; | |
44 | argv++, argc--; | |
45 | continue; | |
46 | } | |
47 | if (strcmp(*argv, "-t") == 0) { | |
48 | tracepackets++; | |
49 | argv++, argc--; | |
50 | ftrace = stderr; | |
51 | tracing = 1; | |
52 | continue; | |
53 | } | |
54 | if (strcmp(*argv, "-g") == 0) { | |
55 | gateway = 1; | |
56 | argv++, argc--; | |
57 | continue; | |
58 | } | |
59 | if (strcmp(*argv, "-l") == 0) { | |
60 | gateway = -1; | |
61 | argv++, argc--; | |
62 | continue; | |
63 | } | |
64 | fprintf(stderr, | |
65 | "usage: xnsrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); | |
66 | exit(1); | |
67 | } | |
68 | ||
69 | #ifndef DEBUG | |
70 | if (!tracepackets) { | |
71 | int t; | |
72 | ||
73 | if (fork()) | |
74 | exit(0); | |
75 | for (t = 0; t < 20; t++) | |
76 | (void) close(t); | |
77 | (void) open("/", 0); | |
78 | (void) dup2(0, 1); | |
79 | (void) dup2(0, 2); | |
80 | t = open("/dev/tty", 2); | |
81 | if (t >= 0) { | |
82 | ioctl(t, TIOCNOTTY, (char *)0); | |
83 | (void) close(t); | |
84 | } | |
85 | } | |
86 | #endif | |
87 | /* | |
88 | * Any extra argument is considered | |
89 | * a tracing log file. | |
90 | */ | |
91 | if (argc > 0) | |
92 | traceon(*argv); | |
93 | /* | |
94 | * Collect an initial view of the world by | |
95 | * snooping in the kernel. Then, send a request packet on all | |
96 | * directly connected networks to find out what | |
97 | * everyone else thinks. | |
98 | */ | |
99 | rtinit(); | |
100 | ifinit(); | |
101 | if (supplier < 0) | |
102 | supplier = 0; | |
103 | /* request the state of the world */ | |
104 | msg->rip_cmd = htons(RIPCMD_REQUEST); | |
105 | xnnet(msg->rip_nets[0].rip_dst) = htonl(DSTNETS_ALL); | |
106 | msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); | |
107 | toall(sendmsg); | |
108 | signal(SIGALRM, timer); | |
109 | signal(SIGHUP, hup); | |
110 | signal(SIGINT, hup); | |
111 | signal(SIGEMT, fkexit); | |
112 | timer(); | |
113 | ||
114 | /* | |
115 | * Listen for RIF packets on all interfaces | |
116 | */ | |
117 | selectbits = 0; | |
118 | for( ifp = ifnet; ifp!=0; ifp = ifp->int_next) { | |
119 | selectbits |= 1 << ifp->int_ripsock[0]; | |
120 | selectbits |= 1 << ifp->int_ripsock[1]; | |
121 | } | |
122 | ||
123 | for (;;) { | |
124 | int ibits; | |
125 | register int n; | |
126 | ||
127 | ibits = selectbits; | |
128 | n = select(20, &ibits, 0, 0, 0); | |
129 | if (n < 0) { | |
130 | if(errno != EINTR) { | |
131 | perror("main:select"); | |
132 | exit(1); | |
133 | } | |
134 | continue; | |
135 | } | |
136 | for( ifp = ifnet; ifp!=0; ifp = ifp->int_next) { | |
137 | /* take RIF packet off interface */ | |
138 | for(n = 0; n < 2; n++) | |
139 | if(ibits & (1 << ifp->int_ripsock[n])) | |
140 | process(ifp->int_ripsock[n]); | |
141 | } | |
142 | } | |
143 | } | |
144 | ||
145 | process(fd) | |
146 | int fd; | |
147 | { | |
148 | struct sockaddr from; | |
149 | int fromlen = sizeof (from), cc, omask; | |
150 | struct idp *idp = (struct idp *)packet; | |
151 | ||
152 | cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); | |
153 | if (cc <= 0) { | |
154 | if (cc < 0 && errno != EINTR) | |
155 | perror("recvfrom"); | |
156 | return; | |
157 | } | |
158 | /* We get the IDP header in front of the RIF packet*/ | |
159 | if (tracepackets > 1) { | |
160 | fprintf(ftrace,"rcv %d bytes on %s ", | |
161 | cc, xns_ntoa(&idp->idp_dst)); | |
162 | fprintf(ftrace," from %s\n", xns_ntoa(&idp->idp_src)); | |
163 | } | |
164 | ||
165 | if (xnnet(idp->idp_src.xn_net) != xnnet(idp->idp_dst.xn_net)) { | |
166 | fprintf(ftrace, "XNSrouted: net of interface (%d) != net on ether (%d)!\n", | |
167 | ntohl(xnnet(idp->idp_dst.xn_net)), | |
168 | ntohs(xnnet(idp->idp_src.xn_net))); | |
169 | } | |
170 | ||
171 | cc -= sizeof (struct idp); | |
172 | if (fromlen != sizeof (struct sockaddr_xn)) | |
173 | return; | |
174 | #define mask(s) (1<<((s)-1)) | |
175 | omask = sigblock(mask(SIGALRM)); | |
176 | rip_input(&from, cc); | |
177 | sigsetmask(omask); | |
178 | } | |
179 | ||
180 | getsocket(domain, type, proto, sxn) | |
181 | int domain, type, proto; | |
182 | struct sockaddr_xn *sxn; | |
183 | { | |
184 | int retry, s; | |
185 | ||
186 | retry = 1; | |
187 | while ((s = socket(domain, type, proto, 0)) < 0 && retry) { | |
188 | perror("socket"); | |
189 | sleep(5 * retry); | |
190 | retry <<= 1; | |
191 | } | |
192 | if (retry == 0) | |
193 | return (-1); | |
194 | while (bind(s, sxn, sizeof (*sxn), 0) < 0 && retry) { | |
195 | perror("bind"); | |
196 | sleep(5 * retry); | |
197 | retry <<= 1; | |
198 | } | |
199 | if (retry == 0) | |
200 | return (-1); | |
201 | return (s); | |
202 | } | |
203 | ||
204 | /* | |
205 | * Fork and exit on EMT-- for profiling. | |
206 | */ | |
207 | fkexit() | |
208 | { | |
209 | if (fork() == 0) | |
210 | exit(0); | |
211 | } |