1 |
|
|
/* $NetBSD: mrinfo.c,v 1.4 1995/12/10 11:00:51 mycroft Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* This tool requests configuration info from a multicast router |
5 |
|
|
* and prints the reply (if any). Invoke it as: |
6 |
|
|
* |
7 |
|
|
* mrinfo router-name-or-address |
8 |
|
|
* |
9 |
|
|
* Written Wed Mar 24 1993 by Van Jacobson (adapted from the |
10 |
|
|
* multicast mapper written by Pavel Curtis). |
11 |
|
|
* |
12 |
|
|
* The lawyers insist we include the following UC copyright notice. |
13 |
|
|
* The mapper from which this is derived contained a Xerox copyright |
14 |
|
|
* notice which follows the UC one. Try not to get depressed noting |
15 |
|
|
* that the legal gibberish is larger than the program. |
16 |
|
|
* |
17 |
|
|
* Copyright (c) 1993 Regents of the University of California. |
18 |
|
|
* All rights reserved. |
19 |
|
|
* |
20 |
|
|
* Redistribution and use in source and binary forms, with or without |
21 |
|
|
* modification, are permitted provided that the following conditions |
22 |
|
|
* are met: |
23 |
|
|
* 1. Redistributions of source code must retain the above copyright |
24 |
|
|
* notice, this list of conditions and the following disclaimer. |
25 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
26 |
|
|
* notice, this list of conditions and the following disclaimer in the |
27 |
|
|
* documentation and/or other materials provided with the distribution. |
28 |
|
|
* 3. All advertising materials mentioning features or use of this software |
29 |
|
|
* must display the following acknowledgement: |
30 |
|
|
* This product includes software developed by the Computer Systems |
31 |
|
|
* Engineering Group at Lawrence Berkeley Laboratory. |
32 |
|
|
* 4. Neither the name of the University nor of the Laboratory may be used |
33 |
|
|
* to endorse or promote products derived from this software without |
34 |
|
|
* specific prior written permission. |
35 |
|
|
* |
36 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
37 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
38 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
39 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
40 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
41 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
42 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
43 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
44 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
45 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
46 |
|
|
* SUCH DAMAGE. |
47 |
|
|
* --------------------------------- |
48 |
|
|
* Copyright (c) 1992, 2001 Xerox Corporation. All rights reserved. |
49 |
|
|
* |
50 |
|
|
* Redistribution and use in source and binary forms, with or without modification, |
51 |
|
|
* are permitted provided that the following conditions are met: |
52 |
|
|
* |
53 |
|
|
* Redistributions of source code must retain the above copyright notice, |
54 |
|
|
* this list of conditions and the following disclaimer. |
55 |
|
|
* |
56 |
|
|
* Redistributions in binary form must reproduce the above copyright notice, |
57 |
|
|
* this list of conditions and the following disclaimer in the documentation |
58 |
|
|
* and/or other materials provided with the distribution. |
59 |
|
|
|
60 |
|
|
* Neither name of the Xerox, PARC, nor the names of its contributors may be used |
61 |
|
|
* to endorse or promote products derived from this software |
62 |
|
|
* without specific prior written permission. |
63 |
|
|
* |
64 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' |
65 |
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
66 |
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
67 |
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE XEROX CORPORATION OR CONTRIBUTORS |
68 |
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
69 |
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
70 |
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
71 |
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
72 |
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
73 |
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
74 |
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
75 |
|
|
*/ |
76 |
|
|
|
77 |
|
|
#include <string.h> |
78 |
|
|
#include <netdb.h> |
79 |
|
|
#include <sys/time.h> |
80 |
|
|
#include "defs.h" |
81 |
|
|
#include <arpa/inet.h> |
82 |
|
|
#include <stdarg.h> |
83 |
|
|
#include <poll.h> |
84 |
|
|
#include <limits.h> |
85 |
|
|
#include <err.h> |
86 |
|
|
|
87 |
|
|
#define DEFAULT_TIMEOUT 4 /* How long to wait before retrying requests */ |
88 |
|
|
#define DEFAULT_RETRIES 3 /* How many times to ask each router */ |
89 |
|
|
|
90 |
|
|
u_int32_t our_addr, target_addr = 0; /* in NET order */ |
91 |
|
|
int debug = 0; |
92 |
|
|
int nflag = 0; |
93 |
|
|
int retries = DEFAULT_RETRIES; |
94 |
|
|
int timeout = DEFAULT_TIMEOUT; |
95 |
|
|
int target_level = 0; |
96 |
|
|
vifi_t numvifs; /* to keep loader happy */ |
97 |
|
|
/* (see COPY_TABLES macro called in kern.c) */ |
98 |
|
|
|
99 |
|
|
char *inet_name(u_int32_t addr); |
100 |
|
|
void ask(u_int32_t dst); |
101 |
|
|
void ask2(u_int32_t dst); |
102 |
|
|
u_int32_t host_addr(char *name); |
103 |
|
|
void usage(void); |
104 |
|
|
|
105 |
|
|
char * |
106 |
|
|
inet_name(u_int32_t addr) |
107 |
|
|
{ |
108 |
|
|
struct hostent *e; |
109 |
|
|
struct in_addr in; |
110 |
|
|
|
111 |
|
|
if (addr == 0) |
112 |
|
|
return "local"; |
113 |
|
|
|
114 |
|
|
if (nflag || |
115 |
|
|
(e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == NULL) { |
116 |
|
|
in.s_addr = addr; |
117 |
|
|
return (inet_ntoa(in)); |
118 |
|
|
} |
119 |
|
|
return (e->h_name); |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
/* |
123 |
|
|
* Log errors and other messages to stderr, according to the severity of the |
124 |
|
|
* message and the current debug level. For errors of severity LOG_ERR or |
125 |
|
|
* worse, terminate the program. |
126 |
|
|
*/ |
127 |
|
|
void |
128 |
|
|
logit(int severity, int syserr, char *format, ...) |
129 |
|
|
{ |
130 |
|
|
va_list ap; |
131 |
|
|
|
132 |
|
|
switch (debug) { |
133 |
|
|
case 0: |
134 |
|
|
if (severity > LOG_WARNING) |
135 |
|
|
return; |
136 |
|
|
case 1: |
137 |
|
|
if (severity > LOG_NOTICE) |
138 |
|
|
return; |
139 |
|
|
case 2: |
140 |
|
|
if (severity > LOG_INFO) |
141 |
|
|
return; |
142 |
|
|
default: |
143 |
|
|
if (severity == LOG_WARNING) |
144 |
|
|
fprintf(stderr, "warning - "); |
145 |
|
|
va_start(ap, format); |
146 |
|
|
vfprintf(stderr, format, ap); |
147 |
|
|
va_end(ap); |
148 |
|
|
if (syserr == 0) |
149 |
|
|
fputc('\n', stderr); |
150 |
|
|
else if (syserr < sys_nerr) |
151 |
|
|
fprintf(stderr, ": %s\n", sys_errlist[syserr]); |
152 |
|
|
else |
153 |
|
|
fprintf(stderr, ": errno %d\n", syserr); |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
if (severity <= LOG_ERR) |
157 |
|
|
exit(1); |
158 |
|
|
} |
159 |
|
|
|
160 |
|
|
/* |
161 |
|
|
* Send a neighbors-list request. |
162 |
|
|
*/ |
163 |
|
|
void |
164 |
|
|
ask(u_int32_t dst) |
165 |
|
|
{ |
166 |
|
|
send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS, |
167 |
|
|
htonl(MROUTED_LEVEL), 0); |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
void |
171 |
|
|
ask2(u_int32_t dst) |
172 |
|
|
{ |
173 |
|
|
send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, |
174 |
|
|
htonl(MROUTED_LEVEL), 0); |
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
/* |
178 |
|
|
* Process an incoming neighbor-list message. |
179 |
|
|
*/ |
180 |
|
|
void |
181 |
|
|
accept_neighbors(u_int32_t src, u_int32_t dst, u_char *p, int datalen, |
182 |
|
|
u_int32_t level) |
183 |
|
|
{ |
184 |
|
|
u_char *ep = p + datalen; |
185 |
|
|
|
186 |
|
|
#define GET_ADDR(a) (a = ((u_int32_t)*p++ << 24), a += ((u_int32_t)*p++ << 16),\ |
187 |
|
|
a += ((u_int32_t)*p++ << 8), a += *p++) |
188 |
|
|
|
189 |
|
|
printf("%s (%s):\n", inet_fmt(src, s1), inet_name(src)); |
190 |
|
|
while (p < ep) { |
191 |
|
|
u_char metric, thresh; |
192 |
|
|
u_int32_t laddr; |
193 |
|
|
int ncount; |
194 |
|
|
|
195 |
|
|
GET_ADDR(laddr); |
196 |
|
|
laddr = htonl(laddr); |
197 |
|
|
metric = *p++; |
198 |
|
|
thresh = *p++; |
199 |
|
|
ncount = *p++; |
200 |
|
|
while (--ncount >= 0) { |
201 |
|
|
u_int32_t neighbor; |
202 |
|
|
|
203 |
|
|
GET_ADDR(neighbor); |
204 |
|
|
neighbor = htonl(neighbor); |
205 |
|
|
printf(" %s -> ", inet_fmt(laddr, s1)); |
206 |
|
|
printf("%s (%s) [%d/%d]\n", inet_fmt(neighbor, s1), |
207 |
|
|
inet_name(neighbor), metric, thresh); |
208 |
|
|
} |
209 |
|
|
} |
210 |
|
|
} |
211 |
|
|
|
212 |
|
|
void |
213 |
|
|
accept_neighbors2(u_int32_t src, u_int32_t dst, u_char *p, int datalen, |
214 |
|
|
u_int32_t level) |
215 |
|
|
{ |
216 |
|
|
u_char *ep = p + datalen; |
217 |
|
|
u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */ |
218 |
|
|
/* well, only possibly_broken_cisco, but that's too long to type. */ |
219 |
|
|
|
220 |
|
|
printf("%s (%s) [version %d.%d", inet_fmt(src, s1), inet_name(src), |
221 |
|
|
level & 0xff, (level >> 8) & 0xff); |
222 |
|
|
if ((level >> 16) & NF_LEAF) |
223 |
|
|
printf (",leaf"); |
224 |
|
|
if ((level >> 16) & NF_PRUNE) |
225 |
|
|
printf (",prune"); |
226 |
|
|
if ((level >> 16) & NF_GENID) |
227 |
|
|
printf (",genid"); |
228 |
|
|
if ((level >> 16) & NF_MTRACE) |
229 |
|
|
printf (",mtrace"); |
230 |
|
|
printf ("]:\n"); |
231 |
|
|
|
232 |
|
|
while (p < ep) { |
233 |
|
|
u_char metric, thresh, flags; |
234 |
|
|
u_int32_t laddr = *(u_int32_t*)p; |
235 |
|
|
int ncount; |
236 |
|
|
|
237 |
|
|
p += 4; |
238 |
|
|
metric = *p++; |
239 |
|
|
thresh = *p++; |
240 |
|
|
flags = *p++; |
241 |
|
|
ncount = *p++; |
242 |
|
|
if (broken_cisco && ncount == 0) /* dumb Ciscos */ |
243 |
|
|
ncount = 1; |
244 |
|
|
if (broken_cisco && ncount > 15) /* dumb Ciscos */ |
245 |
|
|
ncount = ncount & 0xf; |
246 |
|
|
while (--ncount >= 0 && p < ep) { |
247 |
|
|
u_int32_t neighbor = *(u_int32_t*)p; |
248 |
|
|
p += 4; |
249 |
|
|
printf(" %s -> ", inet_fmt(laddr, s1)); |
250 |
|
|
printf("%s (%s) [%d/%d", inet_fmt(neighbor, s1), |
251 |
|
|
inet_name(neighbor), metric, thresh); |
252 |
|
|
if (flags & DVMRP_NF_TUNNEL) |
253 |
|
|
printf("/tunnel"); |
254 |
|
|
if (flags & DVMRP_NF_SRCRT) |
255 |
|
|
printf("/srcrt"); |
256 |
|
|
if (flags & DVMRP_NF_PIM) |
257 |
|
|
printf("/pim"); |
258 |
|
|
if (flags & DVMRP_NF_QUERIER) |
259 |
|
|
printf("/querier"); |
260 |
|
|
if (flags & DVMRP_NF_DISABLED) |
261 |
|
|
printf("/disabled"); |
262 |
|
|
if (flags & DVMRP_NF_DOWN) |
263 |
|
|
printf("/down"); |
264 |
|
|
if (flags & DVMRP_NF_LEAF) |
265 |
|
|
printf("/leaf"); |
266 |
|
|
printf("]\n"); |
267 |
|
|
} |
268 |
|
|
} |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
void |
272 |
|
|
usage() |
273 |
|
|
{ |
274 |
|
|
fprintf(stderr, |
275 |
|
|
"Usage: mrinfo [-d [debug_level]] [-n] [-t timeout] [-r retries] [router]\n"); |
276 |
|
|
exit(1); |
277 |
|
|
} |
278 |
|
|
|
279 |
|
|
int |
280 |
|
|
main(int argc, char *argv[]) |
281 |
|
|
{ |
282 |
|
|
int tries, trynew, curaddr, udp, ch; |
283 |
|
|
struct hostent *hp, bogus; |
284 |
|
|
struct sockaddr_in addr; |
285 |
|
|
socklen_t addrlen; |
286 |
|
|
struct timeval et; |
287 |
|
|
char *host; |
288 |
|
|
uid_t uid; |
289 |
|
|
const char *errstr; |
290 |
|
|
|
291 |
|
|
if (geteuid() != 0) { |
292 |
|
|
fprintf(stderr, "mrinfo: must be root\n"); |
293 |
|
|
exit(1); |
294 |
|
|
} |
295 |
|
|
|
296 |
|
|
init_igmp(); |
297 |
|
|
|
298 |
|
|
uid = getuid(); |
299 |
|
|
if (setresuid(uid, uid, uid) == -1) |
300 |
|
|
err(1, "setresuid"); |
301 |
|
|
|
302 |
|
|
setvbuf(stderr, NULL, _IOLBF, 0); |
303 |
|
|
|
304 |
|
|
while ((ch = getopt(argc, argv, "d::nr:t:")) != -1) { |
305 |
|
|
switch (ch) { |
306 |
|
|
case 'd': |
307 |
|
|
if (!optarg) |
308 |
|
|
debug = DEFAULT_DEBUG; |
309 |
|
|
else { |
310 |
|
|
debug = strtonum(optarg, 0, 3, &errstr); |
311 |
|
|
if (errstr) { |
312 |
|
|
warnx("debug level %s", errstr); |
313 |
|
|
debug = DEFAULT_DEBUG; |
314 |
|
|
} |
315 |
|
|
} |
316 |
|
|
break; |
317 |
|
|
case 'n': |
318 |
|
|
++nflag; |
319 |
|
|
break; |
320 |
|
|
case 'r': |
321 |
|
|
retries = strtonum(optarg, 0, INT_MAX, &errstr); |
322 |
|
|
if (errstr) { |
323 |
|
|
warnx("retries %s", errstr); |
324 |
|
|
usage(); |
325 |
|
|
} |
326 |
|
|
break; |
327 |
|
|
case 't': |
328 |
|
|
timeout = strtonum(optarg, 0, INT_MAX, &errstr); |
329 |
|
|
if (errstr) { |
330 |
|
|
warnx("timeout %s", errstr); |
331 |
|
|
usage(); |
332 |
|
|
} |
333 |
|
|
break; |
334 |
|
|
default: |
335 |
|
|
usage(); |
336 |
|
|
} |
337 |
|
|
} |
338 |
|
|
argc -= optind; |
339 |
|
|
argv += optind; |
340 |
|
|
|
341 |
|
|
if (argc > 1) |
342 |
|
|
usage(); |
343 |
|
|
if (argc == 1) |
344 |
|
|
host = argv[0]; |
345 |
|
|
else |
346 |
|
|
host = "127.0.0.1"; |
347 |
|
|
|
348 |
|
|
if ((target_addr = inet_addr(host)) != -1) { |
349 |
|
|
hp = &bogus; |
350 |
|
|
hp->h_length = sizeof(target_addr); |
351 |
|
|
if (!(hp->h_addr_list = calloc(2, sizeof(char *)))) |
352 |
|
|
err(1, "can't allocate memory"); |
353 |
|
|
if (!(hp->h_addr_list[0] = malloc(hp->h_length))) |
354 |
|
|
err(1, "can't allocate memory"); |
355 |
|
|
memcpy(hp->h_addr_list[0], &target_addr, hp->h_length); |
356 |
|
|
hp->h_addr_list[1] = 0; |
357 |
|
|
} else |
358 |
|
|
hp = gethostbyname(host); |
359 |
|
|
|
360 |
|
|
if (hp == NULL || hp->h_length != sizeof(target_addr)) { |
361 |
|
|
fprintf(stderr, "mrinfo: %s: no such host\n", argv[0]); |
362 |
|
|
exit(1); |
363 |
|
|
} |
364 |
|
|
if (debug) |
365 |
|
|
fprintf(stderr, "Debug level %u\n", debug); |
366 |
|
|
|
367 |
|
|
/* Check all addresses; mrouters often have unreachable interfaces */ |
368 |
|
|
for (curaddr = 0; hp->h_addr_list[curaddr] != NULL; curaddr++) { |
369 |
|
|
memcpy(&target_addr, hp->h_addr_list[curaddr], hp->h_length); |
370 |
|
|
/* Find a good local address for us. */ |
371 |
|
|
addrlen = sizeof(addr); |
372 |
|
|
memset(&addr, 0, sizeof addr); |
373 |
|
|
addr.sin_family = AF_INET; |
374 |
|
|
addr.sin_len = sizeof addr; |
375 |
|
|
addr.sin_addr.s_addr = target_addr; |
376 |
|
|
addr.sin_port = htons(2000); /* any port over 1024 will |
377 |
|
|
* do... */ |
378 |
|
|
if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || |
379 |
|
|
connect(udp, (struct sockaddr *) & addr, sizeof(addr)) < 0 || |
380 |
|
|
getsockname(udp, (struct sockaddr *) & addr, &addrlen) < 0) { |
381 |
|
|
perror("Determining local address"); |
382 |
|
|
exit(1); |
383 |
|
|
} |
384 |
|
|
close(udp); |
385 |
|
|
our_addr = addr.sin_addr.s_addr; |
386 |
|
|
|
387 |
|
|
tries = 0; |
388 |
|
|
trynew = 1; |
389 |
|
|
/* |
390 |
|
|
* New strategy: send 'ask2' for two timeouts, then fall back |
391 |
|
|
* to 'ask', since it's not very likely that we are going to |
392 |
|
|
* find someone who only responds to 'ask' these days |
393 |
|
|
*/ |
394 |
|
|
ask2(target_addr); |
395 |
|
|
|
396 |
|
|
gettimeofday(&et, 0); |
397 |
|
|
et.tv_sec += timeout; |
398 |
|
|
|
399 |
|
|
/* Main receive loop */ |
400 |
|
|
for (;;) { |
401 |
|
|
int count, recvlen, ipdatalen, iphdrlen, igmpdatalen; |
402 |
|
|
u_int32_t src, dst, group; |
403 |
|
|
struct timeval tv, now; |
404 |
|
|
socklen_t dummy = 0; |
405 |
|
|
struct igmp *igmp; |
406 |
|
|
struct ip *ip; |
407 |
|
|
struct pollfd pfd[1]; |
408 |
|
|
|
409 |
|
|
pfd[0].fd = igmp_socket; |
410 |
|
|
pfd[0].events = POLLIN; |
411 |
|
|
|
412 |
|
|
gettimeofday(&now, 0); |
413 |
|
|
tv.tv_sec = et.tv_sec - now.tv_sec; |
414 |
|
|
tv.tv_usec = et.tv_usec - now.tv_usec; |
415 |
|
|
|
416 |
|
|
if (tv.tv_usec < 0) { |
417 |
|
|
tv.tv_usec += 1000000L; |
418 |
|
|
--tv.tv_sec; |
419 |
|
|
} |
420 |
|
|
if (tv.tv_sec < 0) |
421 |
|
|
timerclear(&tv); |
422 |
|
|
|
423 |
|
|
count = poll(pfd, 1, tv.tv_sec * 1000); |
424 |
|
|
|
425 |
|
|
if (count < 0) { |
426 |
|
|
if (errno != EINTR) |
427 |
|
|
perror("select"); |
428 |
|
|
continue; |
429 |
|
|
} else if (count == 0) { |
430 |
|
|
logit(LOG_DEBUG, 0, |
431 |
|
|
"Timed out receiving neighbor lists"); |
432 |
|
|
if (++tries > retries) |
433 |
|
|
break; |
434 |
|
|
/* If we've tried ASK_NEIGHBORS2 twice with |
435 |
|
|
* no response, fall back to ASK_NEIGHBORS |
436 |
|
|
*/ |
437 |
|
|
if (tries == 2 && target_level == 0) |
438 |
|
|
trynew = 0; |
439 |
|
|
if (target_level == 0 && trynew == 0) |
440 |
|
|
ask(target_addr); |
441 |
|
|
else |
442 |
|
|
ask2(target_addr); |
443 |
|
|
gettimeofday(&et, 0); |
444 |
|
|
et.tv_sec += timeout; |
445 |
|
|
continue; |
446 |
|
|
} |
447 |
|
|
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, |
448 |
|
|
0, NULL, &dummy); |
449 |
|
|
if (recvlen <= 0) { |
450 |
|
|
if (recvlen && errno != EINTR) |
451 |
|
|
perror("recvfrom"); |
452 |
|
|
continue; |
453 |
|
|
} |
454 |
|
|
|
455 |
|
|
if (recvlen < sizeof(struct ip)) { |
456 |
|
|
logit(LOG_WARNING, 0, |
457 |
|
|
"packet too short (%u bytes) for IP header", |
458 |
|
|
recvlen); |
459 |
|
|
continue; |
460 |
|
|
} |
461 |
|
|
ip = (struct ip *) recv_buf; |
462 |
|
|
if (ip->ip_p == 0) |
463 |
|
|
continue; /* Request to install cache entry */ |
464 |
|
|
src = ip->ip_src.s_addr; |
465 |
|
|
dst = ip->ip_dst.s_addr; |
466 |
|
|
iphdrlen = ip->ip_hl << 2; |
467 |
|
|
ipdatalen = ntohs(ip->ip_len) - iphdrlen; |
468 |
|
|
if (iphdrlen + ipdatalen != recvlen) { |
469 |
|
|
logit(LOG_WARNING, 0, |
470 |
|
|
"packet shorter (%u bytes) than " |
471 |
|
|
"hdr+data length (%u+%u)", |
472 |
|
|
recvlen, iphdrlen, ipdatalen); |
473 |
|
|
continue; |
474 |
|
|
} |
475 |
|
|
igmp = (struct igmp *) (recv_buf + iphdrlen); |
476 |
|
|
group = igmp->igmp_group.s_addr; |
477 |
|
|
igmpdatalen = ipdatalen - IGMP_MINLEN; |
478 |
|
|
if (igmpdatalen < 0) { |
479 |
|
|
logit(LOG_WARNING, 0, |
480 |
|
|
"IP data field too short (%u bytes) " |
481 |
|
|
"for IGMP, from %s", |
482 |
|
|
ipdatalen, inet_fmt(src, s1)); |
483 |
|
|
continue; |
484 |
|
|
} |
485 |
|
|
if (igmp->igmp_type != IGMP_DVMRP) |
486 |
|
|
continue; |
487 |
|
|
|
488 |
|
|
switch (igmp->igmp_code) { |
489 |
|
|
case DVMRP_NEIGHBORS: |
490 |
|
|
case DVMRP_NEIGHBORS2: |
491 |
|
|
if (src != target_addr) { |
492 |
|
|
fprintf(stderr, "mrinfo: got reply from %s", |
493 |
|
|
inet_fmt(src, s1)); |
494 |
|
|
fprintf(stderr, " instead of %s\n", |
495 |
|
|
inet_fmt(target_addr, s1)); |
496 |
|
|
/*continue;*/ |
497 |
|
|
} |
498 |
|
|
break; |
499 |
|
|
default: |
500 |
|
|
continue; /* ignore all other DVMRP messages */ |
501 |
|
|
} |
502 |
|
|
|
503 |
|
|
switch (igmp->igmp_code) { |
504 |
|
|
case DVMRP_NEIGHBORS: |
505 |
|
|
if (group) { |
506 |
|
|
/* knows about DVMRP_NEIGHBORS2 msg */ |
507 |
|
|
if (target_level == 0) { |
508 |
|
|
target_level = ntohl(group); |
509 |
|
|
ask2(target_addr); |
510 |
|
|
} |
511 |
|
|
} else { |
512 |
|
|
accept_neighbors(src, dst, (u_char *)(igmp + 1), |
513 |
|
|
igmpdatalen, ntohl(group)); |
514 |
|
|
exit(0); |
515 |
|
|
} |
516 |
|
|
break; |
517 |
|
|
case DVMRP_NEIGHBORS2: |
518 |
|
|
accept_neighbors2(src, dst, (u_char *)(igmp + 1), |
519 |
|
|
igmpdatalen, ntohl(group)); |
520 |
|
|
exit(0); |
521 |
|
|
} |
522 |
|
|
} |
523 |
|
|
} |
524 |
|
|
exit(1); |
525 |
|
|
} |
526 |
|
|
|
527 |
|
|
/* dummies */ |
528 |
|
|
void |
529 |
|
|
accept_probe(u_int32_t src, u_int32_t dst, char *p, int datalen, |
530 |
|
|
u_int32_t level) |
531 |
|
|
{ |
532 |
|
|
} |
533 |
|
|
|
534 |
|
|
void |
535 |
|
|
accept_group_report(u_int32_t src, u_int32_t dst, u_int32_t group, int r_type) |
536 |
|
|
{ |
537 |
|
|
} |
538 |
|
|
|
539 |
|
|
void |
540 |
|
|
accept_neighbor_request2(u_int32_t src, u_int32_t dst) |
541 |
|
|
{ |
542 |
|
|
} |
543 |
|
|
|
544 |
|
|
void |
545 |
|
|
accept_report(u_int32_t src, u_int32_t dst, char *p, int datalen, |
546 |
|
|
u_int32_t level) |
547 |
|
|
{ |
548 |
|
|
} |
549 |
|
|
|
550 |
|
|
void |
551 |
|
|
accept_neighbor_request(u_int32_t src, u_int32_t dst) |
552 |
|
|
{ |
553 |
|
|
} |
554 |
|
|
|
555 |
|
|
void |
556 |
|
|
accept_prune(u_int32_t src, u_int32_t dst, char *p, int datalen) |
557 |
|
|
{ |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
void |
561 |
|
|
accept_graft(u_int32_t src, u_int32_t dst, char *p, int datalen) |
562 |
|
|
{ |
563 |
|
|
} |
564 |
|
|
|
565 |
|
|
void |
566 |
|
|
accept_g_ack(u_int32_t src, u_int32_t dst, char *p, int datalen) |
567 |
|
|
{ |
568 |
|
|
} |
569 |
|
|
|
570 |
|
|
void |
571 |
|
|
add_table_entry(u_int32_t origin, u_int32_t mcastgrp) |
572 |
|
|
{ |
573 |
|
|
} |
574 |
|
|
|
575 |
|
|
void |
576 |
|
|
check_vif_state(void) |
577 |
|
|
{ |
578 |
|
|
} |
579 |
|
|
|
580 |
|
|
void |
581 |
|
|
accept_leave_message(u_int32_t src, u_int32_t dst, u_int32_t group) |
582 |
|
|
{ |
583 |
|
|
} |
584 |
|
|
|
585 |
|
|
void |
586 |
|
|
accept_mtrace(u_int32_t src, u_int32_t dst, u_int32_t group, char *data, |
587 |
|
|
u_int no, int datalen) |
588 |
|
|
{ |
589 |
|
|
} |
590 |
|
|
|
591 |
|
|
void |
592 |
|
|
accept_membership_query(u_int32_t src, u_int32_t dst, u_int32_t group, int tmo) |
593 |
|
|
{ |
594 |
|
|
} |
595 |
|
|
|
596 |
|
|
void |
597 |
|
|
accept_info_request(u_int32_t src, u_int32_t dst, u_char *p, int datalen) |
598 |
|
|
{ |
599 |
|
|
} |
600 |
|
|
|
601 |
|
|
void |
602 |
|
|
accept_info_reply(u_int32_t src, u_int32_t dst, u_char *p, int datalen) |
603 |
|
|
{ |
604 |
|
|
} |