mapper.c revision 1.8.2.1 1 1.8.2.1 lukem /* $NetBSD: mapper.c,v 1.8.2.1 2002/06/04 11:56:40 lukem Exp $ */
2 1.2 thorpej
3 1.1 mycroft /* Mapper for connections between MRouteD multicast routers.
4 1.1 mycroft * Written by Pavel Curtis <Pavel (at) PARC.Xerox.Com>
5 1.1 mycroft */
6 1.1 mycroft
7 1.1 mycroft /*
8 1.7 itojun * Copyright (c) 1992, 2001 Xerox Corporation. All rights reserved.
9 1.7 itojun *
10 1.7 itojun * Redistribution and use in source and binary forms, with or without modification,
11 1.7 itojun * are permitted provided that the following conditions are met:
12 1.7 itojun *
13 1.7 itojun * Redistributions of source code must retain the above copyright notice,
14 1.7 itojun * this list of conditions and the following disclaimer.
15 1.7 itojun *
16 1.7 itojun * Redistributions in binary form must reproduce the above copyright notice,
17 1.7 itojun * this list of conditions and the following disclaimer in the documentation
18 1.7 itojun * and/or other materials provided with the distribution.
19 1.7 itojun *
20 1.7 itojun * Neither name of the Xerox, PARC, nor the names of its contributors may be used
21 1.7 itojun * to endorse or promote products derived from this software
22 1.7 itojun * without specific prior written permission.
23 1.7 itojun *
24 1.7 itojun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
25 1.7 itojun * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 1.7 itojun * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 1.7 itojun * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE XEROX CORPORATION OR CONTRIBUTORS
28 1.7 itojun * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 1.7 itojun * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 1.7 itojun * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31 1.7 itojun * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 1.7 itojun * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 1.7 itojun * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
34 1.7 itojun * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 1.1 mycroft */
36 1.1 mycroft
37 1.1 mycroft #include <string.h>
38 1.1 mycroft #include <netdb.h>
39 1.1 mycroft #include <sys/time.h>
40 1.1 mycroft #include "defs.h"
41 1.3 mycroft #include <arpa/inet.h>
42 1.3 mycroft #ifdef __STDC__
43 1.3 mycroft #include <stdarg.h>
44 1.3 mycroft #else
45 1.3 mycroft #include <varargs.h>
46 1.3 mycroft #endif
47 1.1 mycroft
48 1.1 mycroft #define DEFAULT_TIMEOUT 2 /* How long to wait before retrying requests */
49 1.1 mycroft #define DEFAULT_RETRIES 1 /* How many times to ask each router */
50 1.1 mycroft
51 1.1 mycroft
52 1.1 mycroft /* All IP addresses are stored in the data structure in NET order. */
53 1.1 mycroft
54 1.1 mycroft typedef struct neighbor {
55 1.1 mycroft struct neighbor *next;
56 1.1 mycroft u_int32_t addr; /* IP address in NET order */
57 1.1 mycroft u_char metric; /* TTL cost of forwarding */
58 1.1 mycroft u_char threshold; /* TTL threshold to forward */
59 1.1 mycroft u_short flags; /* flags on connection */
60 1.1 mycroft #define NF_PRESENT 0x8000 /* True if flags are meaningful */
61 1.1 mycroft } Neighbor;
62 1.1 mycroft
63 1.1 mycroft typedef struct interface {
64 1.1 mycroft struct interface *next;
65 1.1 mycroft u_int32_t addr; /* IP address of the interface in NET order */
66 1.1 mycroft Neighbor *neighbors; /* List of neighbors' IP addresses */
67 1.1 mycroft } Interface;
68 1.1 mycroft
69 1.1 mycroft typedef struct node {
70 1.1 mycroft u_int32_t addr; /* IP address of this entry in NET order */
71 1.1 mycroft u_int32_t version; /* which mrouted version is running */
72 1.1 mycroft int tries; /* How many requests sent? -1 for aliases */
73 1.1 mycroft union {
74 1.1 mycroft struct node *alias; /* If alias, to what? */
75 1.1 mycroft struct interface *interfaces; /* Else, neighbor data */
76 1.1 mycroft } u;
77 1.1 mycroft struct node *left, *right;
78 1.1 mycroft } Node;
79 1.1 mycroft
80 1.1 mycroft
81 1.1 mycroft Node *routers = 0;
82 1.1 mycroft u_int32_t our_addr, target_addr = 0; /* in NET order */
83 1.1 mycroft int debug = 0;
84 1.1 mycroft int retries = DEFAULT_RETRIES;
85 1.1 mycroft int timeout = DEFAULT_TIMEOUT;
86 1.1 mycroft int show_names = TRUE;
87 1.1 mycroft vifi_t numvifs; /* to keep loader happy */
88 1.1 mycroft /* (see COPY_TABLES macro called in kern.c) */
89 1.1 mycroft
90 1.3 mycroft Node * find_node __P((u_int32_t addr, Node **ptr));
91 1.3 mycroft Interface * find_interface __P((u_int32_t addr, Node *node));
92 1.3 mycroft Neighbor * find_neighbor __P((u_int32_t addr, Node *node));
93 1.3 mycroft int main __P((int argc, char *argv[]));
94 1.3 mycroft void ask __P((u_int32_t dst));
95 1.3 mycroft void ask2 __P((u_int32_t dst));
96 1.3 mycroft int retry_requests __P((Node *node));
97 1.3 mycroft char * inet_name __P((u_int32_t addr));
98 1.3 mycroft void print_map __P((Node *node));
99 1.3 mycroft char * graph_name __P((u_int32_t addr, char *buf));
100 1.3 mycroft void graph_edges __P((Node *node));
101 1.3 mycroft void elide_aliases __P((Node *node));
102 1.3 mycroft void graph_map __P((void));
103 1.3 mycroft int get_number __P((int *var, int deflt, char ***pargv,
104 1.3 mycroft int *pargc));
105 1.3 mycroft u_int32_t host_addr __P((char *name));
106 1.3 mycroft
107 1.5 is #ifdef __STDC__
108 1.5 is void log(int severity, int syserr, const char *format, ...)
109 1.5 is __attribute__((__format__(__printf__, 3, 4)));
110 1.5 is #endif
111 1.1 mycroft
112 1.1 mycroft Node *find_node(addr, ptr)
113 1.1 mycroft u_int32_t addr;
114 1.1 mycroft Node **ptr;
115 1.1 mycroft {
116 1.1 mycroft Node *n = *ptr;
117 1.1 mycroft
118 1.1 mycroft if (!n) {
119 1.1 mycroft *ptr = n = (Node *) malloc(sizeof(Node));
120 1.1 mycroft n->addr = addr;
121 1.1 mycroft n->version = 0;
122 1.1 mycroft n->tries = 0;
123 1.1 mycroft n->u.interfaces = 0;
124 1.1 mycroft n->left = n->right = 0;
125 1.1 mycroft return n;
126 1.1 mycroft } else if (addr == n->addr)
127 1.1 mycroft return n;
128 1.1 mycroft else if (addr < n->addr)
129 1.1 mycroft return find_node(addr, &(n->left));
130 1.1 mycroft else
131 1.1 mycroft return find_node(addr, &(n->right));
132 1.1 mycroft }
133 1.1 mycroft
134 1.1 mycroft
135 1.1 mycroft Interface *find_interface(addr, node)
136 1.1 mycroft u_int32_t addr;
137 1.1 mycroft Node *node;
138 1.1 mycroft {
139 1.1 mycroft Interface *ifc;
140 1.1 mycroft
141 1.1 mycroft for (ifc = node->u.interfaces; ifc; ifc = ifc->next)
142 1.1 mycroft if (ifc->addr == addr)
143 1.1 mycroft return ifc;
144 1.1 mycroft
145 1.1 mycroft ifc = (Interface *) malloc(sizeof(Interface));
146 1.1 mycroft ifc->addr = addr;
147 1.1 mycroft ifc->next = node->u.interfaces;
148 1.1 mycroft node->u.interfaces = ifc;
149 1.1 mycroft ifc->neighbors = 0;
150 1.1 mycroft
151 1.1 mycroft return ifc;
152 1.1 mycroft }
153 1.1 mycroft
154 1.1 mycroft
155 1.1 mycroft Neighbor *find_neighbor(addr, node)
156 1.1 mycroft u_int32_t addr;
157 1.1 mycroft Node *node;
158 1.1 mycroft {
159 1.1 mycroft Interface *ifc;
160 1.1 mycroft
161 1.1 mycroft for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
162 1.1 mycroft Neighbor *nb;
163 1.1 mycroft
164 1.1 mycroft for (nb = ifc->neighbors; nb; nb = nb->next)
165 1.1 mycroft if (nb->addr == addr)
166 1.1 mycroft return nb;
167 1.1 mycroft }
168 1.1 mycroft
169 1.1 mycroft return 0;
170 1.1 mycroft }
171 1.1 mycroft
172 1.1 mycroft
173 1.1 mycroft /*
174 1.1 mycroft * Log errors and other messages to stderr, according to the severity of the
175 1.1 mycroft * message and the current debug level. For errors of severity LOG_ERR or
176 1.1 mycroft * worse, terminate the program.
177 1.1 mycroft */
178 1.3 mycroft #ifdef __STDC__
179 1.3 mycroft void
180 1.5 is log(int severity, int syserr, const char *format, ...)
181 1.3 mycroft #else
182 1.3 mycroft /*VARARGS3*/
183 1.3 mycroft void
184 1.3 mycroft log(severity, syserr, format, va_alist)
185 1.3 mycroft int severity, syserr;
186 1.3 mycroft char *format;
187 1.3 mycroft va_dcl
188 1.8 wiz #endif
189 1.3 mycroft {
190 1.8 wiz va_list ap;
191 1.8 wiz char fmt[100];
192 1.1 mycroft
193 1.1 mycroft switch (debug) {
194 1.1 mycroft case 0: if (severity > LOG_WARNING) return;
195 1.1 mycroft case 1: if (severity > LOG_NOTICE ) return;
196 1.1 mycroft case 2: if (severity > LOG_INFO ) return;
197 1.1 mycroft default:
198 1.1 mycroft fmt[0] = '\0';
199 1.1 mycroft if (severity == LOG_WARNING)
200 1.1 mycroft strcat(fmt, "warning - ");
201 1.1 mycroft strncat(fmt, format, 80);
202 1.5 is format = fmt;
203 1.8 wiz #ifdef __STDC__
204 1.8 wiz va_start(ap, format);
205 1.8 wiz #else
206 1.8 wiz va_start(ap);
207 1.8 wiz #endif
208 1.5 is vfprintf(stderr, format, ap);
209 1.8 wiz va_end(ap);
210 1.1 mycroft if (syserr == 0)
211 1.1 mycroft fprintf(stderr, "\n");
212 1.1 mycroft else
213 1.4 kleink fprintf(stderr, ": %s\n", strerror(syserr));
214 1.1 mycroft }
215 1.1 mycroft
216 1.1 mycroft if (severity <= LOG_ERR)
217 1.6 wiz exit(1);
218 1.1 mycroft }
219 1.1 mycroft
220 1.1 mycroft
221 1.1 mycroft /*
222 1.1 mycroft * Send a neighbors-list request.
223 1.1 mycroft */
224 1.1 mycroft void ask(dst)
225 1.1 mycroft u_int32_t dst;
226 1.1 mycroft {
227 1.1 mycroft send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS,
228 1.1 mycroft htonl(MROUTED_LEVEL), 0);
229 1.1 mycroft }
230 1.1 mycroft
231 1.1 mycroft void ask2(dst)
232 1.1 mycroft u_int32_t dst;
233 1.1 mycroft {
234 1.1 mycroft send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2,
235 1.1 mycroft htonl(MROUTED_LEVEL), 0);
236 1.1 mycroft }
237 1.1 mycroft
238 1.1 mycroft
239 1.1 mycroft /*
240 1.1 mycroft * Process an incoming group membership report.
241 1.1 mycroft */
242 1.3 mycroft void accept_group_report(src, dst, group, r_type)
243 1.1 mycroft u_int32_t src, dst, group;
244 1.3 mycroft int r_type;
245 1.1 mycroft {
246 1.1 mycroft log(LOG_INFO, 0, "ignoring IGMP group membership report from %s to %s",
247 1.1 mycroft inet_fmt(src, s1), inet_fmt(dst, s2));
248 1.1 mycroft }
249 1.1 mycroft
250 1.1 mycroft
251 1.1 mycroft /*
252 1.1 mycroft * Process an incoming neighbor probe message.
253 1.1 mycroft */
254 1.3 mycroft void accept_probe(src, dst, p, datalen, level)
255 1.3 mycroft u_int32_t src, dst, level;
256 1.3 mycroft char *p;
257 1.3 mycroft int datalen;
258 1.1 mycroft {
259 1.1 mycroft log(LOG_INFO, 0, "ignoring DVMRP probe from %s to %s",
260 1.1 mycroft inet_fmt(src, s1), inet_fmt(dst, s2));
261 1.1 mycroft }
262 1.1 mycroft
263 1.1 mycroft
264 1.1 mycroft /*
265 1.1 mycroft * Process an incoming route report message.
266 1.1 mycroft */
267 1.3 mycroft void accept_report(src, dst, p, datalen, level)
268 1.3 mycroft u_int32_t src, dst, level;
269 1.1 mycroft char *p;
270 1.1 mycroft int datalen;
271 1.1 mycroft {
272 1.1 mycroft log(LOG_INFO, 0, "ignoring DVMRP routing report from %s to %s",
273 1.1 mycroft inet_fmt(src, s1), inet_fmt(dst, s2));
274 1.1 mycroft }
275 1.1 mycroft
276 1.1 mycroft
277 1.1 mycroft /*
278 1.1 mycroft * Process an incoming neighbor-list request message.
279 1.1 mycroft */
280 1.1 mycroft void accept_neighbor_request(src, dst)
281 1.1 mycroft u_int32_t src, dst;
282 1.1 mycroft {
283 1.1 mycroft if (src != our_addr)
284 1.1 mycroft log(LOG_INFO, 0,
285 1.1 mycroft "ignoring spurious DVMRP neighbor request from %s to %s",
286 1.1 mycroft inet_fmt(src, s1), inet_fmt(dst, s2));
287 1.1 mycroft }
288 1.1 mycroft
289 1.1 mycroft void accept_neighbor_request2(src, dst)
290 1.1 mycroft u_int32_t src, dst;
291 1.1 mycroft {
292 1.1 mycroft if (src != our_addr)
293 1.1 mycroft log(LOG_INFO, 0,
294 1.1 mycroft "ignoring spurious DVMRP neighbor request2 from %s to %s",
295 1.1 mycroft inet_fmt(src, s1), inet_fmt(dst, s2));
296 1.1 mycroft }
297 1.1 mycroft
298 1.1 mycroft
299 1.1 mycroft /*
300 1.1 mycroft * Process an incoming neighbor-list message.
301 1.1 mycroft */
302 1.1 mycroft void accept_neighbors(src, dst, p, datalen, level)
303 1.1 mycroft u_int32_t src, dst, level;
304 1.1 mycroft u_char *p;
305 1.1 mycroft int datalen;
306 1.1 mycroft {
307 1.1 mycroft Node *node = find_node(src, &routers);
308 1.1 mycroft
309 1.1 mycroft if (node->tries == 0) /* Never heard of 'em; must have hit them at */
310 1.1 mycroft node->tries = 1; /* least once, though...*/
311 1.1 mycroft else if (node->tries == -1) /* follow alias link */
312 1.1 mycroft node = node->u.alias;
313 1.1 mycroft
314 1.1 mycroft #define GET_ADDR(a) (a = ((u_int32_t)*p++ << 24), a += ((u_int32_t)*p++ << 16),\
315 1.1 mycroft a += ((u_int32_t)*p++ << 8), a += *p++)
316 1.1 mycroft
317 1.1 mycroft /* if node is running a recent mrouted, ask for additional info */
318 1.1 mycroft if (level != 0) {
319 1.3 mycroft node->version = level;
320 1.3 mycroft node->tries = 1;
321 1.1 mycroft ask2(src);
322 1.1 mycroft return;
323 1.1 mycroft }
324 1.1 mycroft
325 1.1 mycroft if (debug > 3) {
326 1.1 mycroft int i;
327 1.1 mycroft
328 1.1 mycroft fprintf(stderr, " datalen = %d\n", datalen);
329 1.1 mycroft for (i = 0; i < datalen; i++) {
330 1.1 mycroft if ((i & 0xF) == 0)
331 1.1 mycroft fprintf(stderr, " ");
332 1.1 mycroft fprintf(stderr, " %02x", p[i]);
333 1.1 mycroft if ((i & 0xF) == 0xF)
334 1.1 mycroft fprintf(stderr, "\n");
335 1.1 mycroft }
336 1.1 mycroft if ((datalen & 0xF) != 0xF)
337 1.1 mycroft fprintf(stderr, "\n");
338 1.1 mycroft }
339 1.1 mycroft
340 1.1 mycroft while (datalen > 0) { /* loop through interfaces */
341 1.1 mycroft u_int32_t ifc_addr;
342 1.1 mycroft u_char metric, threshold, ncount;
343 1.1 mycroft Node *ifc_node;
344 1.1 mycroft Interface *ifc;
345 1.1 mycroft Neighbor *old_neighbors;
346 1.1 mycroft
347 1.1 mycroft if (datalen < 4 + 3) {
348 1.1 mycroft log(LOG_WARNING, 0, "received truncated interface record from %s",
349 1.1 mycroft inet_fmt(src, s1));
350 1.1 mycroft return;
351 1.1 mycroft }
352 1.1 mycroft
353 1.1 mycroft GET_ADDR(ifc_addr);
354 1.1 mycroft ifc_addr = htonl(ifc_addr);
355 1.1 mycroft metric = *p++;
356 1.1 mycroft threshold = *p++;
357 1.1 mycroft ncount = *p++;
358 1.1 mycroft datalen -= 4 + 3;
359 1.1 mycroft
360 1.1 mycroft /* Fix up any alias information */
361 1.1 mycroft ifc_node = find_node(ifc_addr, &routers);
362 1.1 mycroft if (ifc_node->tries == 0) { /* new node */
363 1.1 mycroft ifc_node->tries = -1;
364 1.1 mycroft ifc_node->u.alias = node;
365 1.1 mycroft } else if (ifc_node != node
366 1.1 mycroft && (ifc_node->tries > 0 || ifc_node->u.alias != node)) {
367 1.1 mycroft /* must merge two hosts' nodes */
368 1.1 mycroft Interface *ifc_i, *next_ifc_i;
369 1.1 mycroft
370 1.1 mycroft if (ifc_node->tries == -1) {
371 1.1 mycroft Node *tmp = ifc_node->u.alias;
372 1.1 mycroft
373 1.1 mycroft ifc_node->u.alias = node;
374 1.1 mycroft ifc_node = tmp;
375 1.1 mycroft }
376 1.1 mycroft
377 1.1 mycroft /* Merge ifc_node (foo_i) into node (foo_n) */
378 1.1 mycroft
379 1.1 mycroft if (ifc_node->tries > node->tries)
380 1.1 mycroft node->tries = ifc_node->tries;
381 1.1 mycroft
382 1.1 mycroft for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) {
383 1.1 mycroft Neighbor *nb_i, *next_nb_i, *nb_n;
384 1.1 mycroft Interface *ifc_n = find_interface(ifc_i->addr, node);
385 1.1 mycroft
386 1.1 mycroft old_neighbors = ifc_n->neighbors;
387 1.1 mycroft for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) {
388 1.1 mycroft next_nb_i = nb_i->next;
389 1.1 mycroft for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next)
390 1.1 mycroft if (nb_i->addr == nb_n->addr) {
391 1.1 mycroft if (nb_i->metric != nb_n->metric
392 1.3 mycroft || nb_i->threshold != nb_n->threshold)
393 1.1 mycroft log(LOG_WARNING, 0,
394 1.1 mycroft "inconsistent %s for neighbor %s of %s",
395 1.1 mycroft "metric/threshold",
396 1.1 mycroft inet_fmt(nb_i->addr, s1),
397 1.1 mycroft inet_fmt(node->addr, s2));
398 1.1 mycroft free(nb_i);
399 1.1 mycroft break;
400 1.1 mycroft }
401 1.1 mycroft if (!nb_n) { /* no match for this neighbor yet */
402 1.1 mycroft nb_i->next = ifc_n->neighbors;
403 1.1 mycroft ifc_n->neighbors = nb_i;
404 1.1 mycroft }
405 1.1 mycroft }
406 1.1 mycroft
407 1.1 mycroft next_ifc_i = ifc_i->next;
408 1.1 mycroft free(ifc_i);
409 1.1 mycroft }
410 1.1 mycroft
411 1.1 mycroft ifc_node->tries = -1;
412 1.1 mycroft ifc_node->u.alias = node;
413 1.1 mycroft }
414 1.1 mycroft
415 1.1 mycroft ifc = find_interface(ifc_addr, node);
416 1.1 mycroft old_neighbors = ifc->neighbors;
417 1.1 mycroft
418 1.1 mycroft /* Add the neighbors for this interface */
419 1.1 mycroft while (ncount--) {
420 1.1 mycroft u_int32_t neighbor;
421 1.1 mycroft Neighbor *nb;
422 1.1 mycroft Node *n_node;
423 1.1 mycroft
424 1.1 mycroft if (datalen < 4) {
425 1.1 mycroft log(LOG_WARNING, 0, "received truncated neighbor list from %s",
426 1.1 mycroft inet_fmt(src, s1));
427 1.1 mycroft return;
428 1.1 mycroft }
429 1.1 mycroft
430 1.1 mycroft GET_ADDR(neighbor);
431 1.1 mycroft neighbor = htonl(neighbor);
432 1.1 mycroft datalen -= 4;
433 1.1 mycroft
434 1.1 mycroft for (nb = old_neighbors; nb; nb = nb->next)
435 1.1 mycroft if (nb->addr == neighbor) {
436 1.1 mycroft if (metric != nb->metric || threshold != nb->threshold)
437 1.1 mycroft log(LOG_WARNING, 0,
438 1.1 mycroft "inconsistent %s for neighbor %s of %s",
439 1.1 mycroft "metric/threshold",
440 1.1 mycroft inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2));
441 1.1 mycroft goto next_neighbor;
442 1.1 mycroft }
443 1.1 mycroft
444 1.1 mycroft nb = (Neighbor *) malloc(sizeof(Neighbor));
445 1.1 mycroft nb->next = ifc->neighbors;
446 1.1 mycroft ifc->neighbors = nb;
447 1.1 mycroft nb->addr = neighbor;
448 1.1 mycroft nb->metric = metric;
449 1.1 mycroft nb->threshold = threshold;
450 1.1 mycroft nb->flags = 0;
451 1.1 mycroft
452 1.1 mycroft n_node = find_node(neighbor, &routers);
453 1.1 mycroft if (n_node->tries == 0 && !target_addr) { /* it's a new router */
454 1.1 mycroft ask(neighbor);
455 1.1 mycroft n_node->tries = 1;
456 1.1 mycroft }
457 1.1 mycroft
458 1.1 mycroft next_neighbor: ;
459 1.1 mycroft }
460 1.1 mycroft }
461 1.1 mycroft }
462 1.1 mycroft
463 1.3 mycroft void accept_neighbors2(src, dst, p, datalen, level)
464 1.3 mycroft u_int32_t src, dst, level;
465 1.1 mycroft u_char *p;
466 1.1 mycroft int datalen;
467 1.1 mycroft {
468 1.1 mycroft Node *node = find_node(src, &routers);
469 1.3 mycroft u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */
470 1.3 mycroft /* well, only possibly_broken_cisco, but that's too long to type. */
471 1.1 mycroft
472 1.1 mycroft if (node->tries == 0) /* Never heard of 'em; must have hit them at */
473 1.1 mycroft node->tries = 1; /* least once, though...*/
474 1.1 mycroft else if (node->tries == -1) /* follow alias link */
475 1.1 mycroft node = node->u.alias;
476 1.1 mycroft
477 1.1 mycroft while (datalen > 0) { /* loop through interfaces */
478 1.1 mycroft u_int32_t ifc_addr;
479 1.1 mycroft u_char metric, threshold, ncount, flags;
480 1.1 mycroft Node *ifc_node;
481 1.1 mycroft Interface *ifc;
482 1.1 mycroft Neighbor *old_neighbors;
483 1.1 mycroft
484 1.1 mycroft if (datalen < 4 + 4) {
485 1.1 mycroft log(LOG_WARNING, 0, "received truncated interface record from %s",
486 1.1 mycroft inet_fmt(src, s1));
487 1.1 mycroft return;
488 1.1 mycroft }
489 1.1 mycroft
490 1.1 mycroft ifc_addr = *(u_int32_t*)p;
491 1.1 mycroft p += 4;
492 1.1 mycroft metric = *p++;
493 1.1 mycroft threshold = *p++;
494 1.1 mycroft flags = *p++;
495 1.1 mycroft ncount = *p++;
496 1.1 mycroft datalen -= 4 + 4;
497 1.1 mycroft
498 1.3 mycroft if (broken_cisco && ncount == 0) /* dumb Ciscos */
499 1.3 mycroft ncount = 1;
500 1.3 mycroft if (broken_cisco && ncount > 15) /* dumb Ciscos */
501 1.3 mycroft ncount = ncount & 0xf;
502 1.3 mycroft
503 1.1 mycroft /* Fix up any alias information */
504 1.1 mycroft ifc_node = find_node(ifc_addr, &routers);
505 1.1 mycroft if (ifc_node->tries == 0) { /* new node */
506 1.1 mycroft ifc_node->tries = -1;
507 1.1 mycroft ifc_node->u.alias = node;
508 1.1 mycroft } else if (ifc_node != node
509 1.1 mycroft && (ifc_node->tries > 0 || ifc_node->u.alias != node)) {
510 1.1 mycroft /* must merge two hosts' nodes */
511 1.1 mycroft Interface *ifc_i, *next_ifc_i;
512 1.1 mycroft
513 1.1 mycroft if (ifc_node->tries == -1) {
514 1.1 mycroft Node *tmp = ifc_node->u.alias;
515 1.1 mycroft
516 1.1 mycroft ifc_node->u.alias = node;
517 1.1 mycroft ifc_node = tmp;
518 1.1 mycroft }
519 1.1 mycroft
520 1.1 mycroft /* Merge ifc_node (foo_i) into node (foo_n) */
521 1.1 mycroft
522 1.1 mycroft if (ifc_node->tries > node->tries)
523 1.1 mycroft node->tries = ifc_node->tries;
524 1.1 mycroft
525 1.1 mycroft for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) {
526 1.1 mycroft Neighbor *nb_i, *next_nb_i, *nb_n;
527 1.1 mycroft Interface *ifc_n = find_interface(ifc_i->addr, node);
528 1.1 mycroft
529 1.1 mycroft old_neighbors = ifc_n->neighbors;
530 1.1 mycroft for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) {
531 1.1 mycroft next_nb_i = nb_i->next;
532 1.1 mycroft for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next)
533 1.1 mycroft if (nb_i->addr == nb_n->addr) {
534 1.1 mycroft if (nb_i->metric != nb_n->metric
535 1.1 mycroft || nb_i->threshold != nb_i->threshold)
536 1.1 mycroft log(LOG_WARNING, 0,
537 1.1 mycroft "inconsistent %s for neighbor %s of %s",
538 1.1 mycroft "metric/threshold",
539 1.1 mycroft inet_fmt(nb_i->addr, s1),
540 1.1 mycroft inet_fmt(node->addr, s2));
541 1.1 mycroft free(nb_i);
542 1.1 mycroft break;
543 1.1 mycroft }
544 1.1 mycroft if (!nb_n) { /* no match for this neighbor yet */
545 1.1 mycroft nb_i->next = ifc_n->neighbors;
546 1.1 mycroft ifc_n->neighbors = nb_i;
547 1.1 mycroft }
548 1.1 mycroft }
549 1.1 mycroft
550 1.1 mycroft next_ifc_i = ifc_i->next;
551 1.1 mycroft free(ifc_i);
552 1.1 mycroft }
553 1.1 mycroft
554 1.1 mycroft ifc_node->tries = -1;
555 1.1 mycroft ifc_node->u.alias = node;
556 1.1 mycroft }
557 1.1 mycroft
558 1.1 mycroft ifc = find_interface(ifc_addr, node);
559 1.1 mycroft old_neighbors = ifc->neighbors;
560 1.1 mycroft
561 1.1 mycroft /* Add the neighbors for this interface */
562 1.3 mycroft while (ncount-- && datalen > 0) {
563 1.1 mycroft u_int32_t neighbor;
564 1.1 mycroft Neighbor *nb;
565 1.1 mycroft Node *n_node;
566 1.1 mycroft
567 1.1 mycroft if (datalen < 4) {
568 1.1 mycroft log(LOG_WARNING, 0, "received truncated neighbor list from %s",
569 1.1 mycroft inet_fmt(src, s1));
570 1.1 mycroft return;
571 1.1 mycroft }
572 1.1 mycroft
573 1.1 mycroft neighbor = *(u_int32_t*)p;
574 1.1 mycroft p += 4;
575 1.1 mycroft datalen -= 4;
576 1.1 mycroft if (neighbor == 0)
577 1.1 mycroft /* make leaf nets point to themselves */
578 1.1 mycroft neighbor = ifc_addr;
579 1.1 mycroft
580 1.1 mycroft for (nb = old_neighbors; nb; nb = nb->next)
581 1.1 mycroft if (nb->addr == neighbor) {
582 1.1 mycroft if (metric != nb->metric || threshold != nb->threshold)
583 1.1 mycroft log(LOG_WARNING, 0,
584 1.1 mycroft "inconsistent %s for neighbor %s of %s",
585 1.1 mycroft "metric/threshold",
586 1.1 mycroft inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2));
587 1.1 mycroft goto next_neighbor;
588 1.1 mycroft }
589 1.1 mycroft
590 1.1 mycroft nb = (Neighbor *) malloc(sizeof(Neighbor));
591 1.1 mycroft nb->next = ifc->neighbors;
592 1.1 mycroft ifc->neighbors = nb;
593 1.1 mycroft nb->addr = neighbor;
594 1.1 mycroft nb->metric = metric;
595 1.1 mycroft nb->threshold = threshold;
596 1.1 mycroft nb->flags = flags | NF_PRESENT;
597 1.1 mycroft
598 1.1 mycroft n_node = find_node(neighbor, &routers);
599 1.1 mycroft if (n_node->tries == 0 && !target_addr) { /* it's a new router */
600 1.1 mycroft ask(neighbor);
601 1.1 mycroft n_node->tries = 1;
602 1.1 mycroft }
603 1.1 mycroft
604 1.1 mycroft next_neighbor: ;
605 1.1 mycroft }
606 1.1 mycroft }
607 1.1 mycroft }
608 1.1 mycroft
609 1.1 mycroft
610 1.1 mycroft void check_vif_state()
611 1.1 mycroft {
612 1.1 mycroft log(LOG_NOTICE, 0, "network marked down...");
613 1.1 mycroft }
614 1.1 mycroft
615 1.1 mycroft
616 1.1 mycroft int retry_requests(node)
617 1.1 mycroft Node *node;
618 1.1 mycroft {
619 1.1 mycroft int result;
620 1.1 mycroft
621 1.1 mycroft if (node) {
622 1.1 mycroft result = retry_requests(node->left);
623 1.1 mycroft if (node->tries > 0 && node->tries < retries) {
624 1.1 mycroft if (node->version)
625 1.1 mycroft ask2(node->addr);
626 1.1 mycroft else
627 1.1 mycroft ask(node->addr);
628 1.1 mycroft node->tries++;
629 1.1 mycroft result = 1;
630 1.1 mycroft }
631 1.1 mycroft return retry_requests(node->right) || result;
632 1.1 mycroft } else
633 1.1 mycroft return 0;
634 1.1 mycroft }
635 1.1 mycroft
636 1.1 mycroft
637 1.1 mycroft char *inet_name(addr)
638 1.1 mycroft u_int32_t addr;
639 1.1 mycroft {
640 1.1 mycroft struct hostent *e;
641 1.1 mycroft
642 1.1 mycroft e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
643 1.1 mycroft
644 1.1 mycroft return e ? e->h_name : 0;
645 1.1 mycroft }
646 1.1 mycroft
647 1.1 mycroft
648 1.1 mycroft void print_map(node)
649 1.1 mycroft Node *node;
650 1.1 mycroft {
651 1.1 mycroft if (node) {
652 1.1 mycroft char *name, *addr;
653 1.1 mycroft
654 1.1 mycroft print_map(node->left);
655 1.1 mycroft
656 1.1 mycroft addr = inet_fmt(node->addr, s1);
657 1.1 mycroft if (!target_addr
658 1.1 mycroft || (node->tries >= 0 && node->u.interfaces)
659 1.1 mycroft || (node->tries == -1
660 1.1 mycroft && node->u.alias->tries >= 0
661 1.1 mycroft && node->u.alias->u.interfaces)) {
662 1.1 mycroft if (show_names && (name = inet_name(node->addr)))
663 1.1 mycroft printf("%s (%s):", addr, name);
664 1.1 mycroft else
665 1.1 mycroft printf("%s:", addr);
666 1.1 mycroft if (node->tries < 0)
667 1.1 mycroft printf(" alias for %s\n\n", inet_fmt(node->u.alias->addr, s1));
668 1.1 mycroft else if (!node->u.interfaces)
669 1.1 mycroft printf(" no response to query\n\n");
670 1.1 mycroft else {
671 1.1 mycroft Interface *ifc;
672 1.1 mycroft
673 1.1 mycroft if (node->version)
674 1.1 mycroft printf(" <v%d.%d>", node->version & 0xff,
675 1.1 mycroft (node->version >> 8) & 0xff);
676 1.1 mycroft printf("\n");
677 1.1 mycroft for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
678 1.1 mycroft Neighbor *nb;
679 1.1 mycroft char *ifc_name = inet_fmt(ifc->addr, s1);
680 1.1 mycroft int ifc_len = strlen(ifc_name);
681 1.1 mycroft int count = 0;
682 1.1 mycroft
683 1.1 mycroft printf(" %s:", ifc_name);
684 1.1 mycroft for (nb = ifc->neighbors; nb; nb = nb->next) {
685 1.1 mycroft if (count > 0)
686 1.1 mycroft printf("%*s", ifc_len + 5, "");
687 1.1 mycroft printf(" %s", inet_fmt(nb->addr, s1));
688 1.1 mycroft if (show_names && (name = inet_name(nb->addr)))
689 1.1 mycroft printf(" (%s)", name);
690 1.1 mycroft printf(" [%d/%d", nb->metric, nb->threshold);
691 1.1 mycroft if (nb->flags) {
692 1.1 mycroft u_short flags = nb->flags;
693 1.1 mycroft if (flags & DVMRP_NF_TUNNEL)
694 1.1 mycroft printf("/tunnel");
695 1.1 mycroft if (flags & DVMRP_NF_SRCRT)
696 1.1 mycroft printf("/srcrt");
697 1.1 mycroft if (flags & DVMRP_NF_QUERIER)
698 1.1 mycroft printf("/querier");
699 1.1 mycroft if (flags & DVMRP_NF_DISABLED)
700 1.1 mycroft printf("/disabled");
701 1.1 mycroft if (flags & DVMRP_NF_DOWN)
702 1.1 mycroft printf("/down");
703 1.1 mycroft }
704 1.1 mycroft printf("]\n");
705 1.1 mycroft count++;
706 1.1 mycroft }
707 1.1 mycroft }
708 1.1 mycroft printf("\n");
709 1.1 mycroft }
710 1.1 mycroft }
711 1.1 mycroft print_map(node->right);
712 1.1 mycroft }
713 1.1 mycroft }
714 1.1 mycroft
715 1.1 mycroft
716 1.1 mycroft char *graph_name(addr, buf)
717 1.1 mycroft u_int32_t addr;
718 1.1 mycroft char *buf;
719 1.1 mycroft {
720 1.1 mycroft char *name;
721 1.1 mycroft
722 1.1 mycroft if (show_names && (name = inet_name(addr)))
723 1.1 mycroft strcpy(buf, name);
724 1.1 mycroft else
725 1.1 mycroft inet_fmt(addr, buf);
726 1.1 mycroft
727 1.1 mycroft return buf;
728 1.1 mycroft }
729 1.1 mycroft
730 1.1 mycroft
731 1.1 mycroft void graph_edges(node)
732 1.1 mycroft Node *node;
733 1.1 mycroft {
734 1.1 mycroft Interface *ifc;
735 1.1 mycroft Neighbor *nb;
736 1.1 mycroft char name[100];
737 1.1 mycroft
738 1.1 mycroft if (node) {
739 1.1 mycroft graph_edges(node->left);
740 1.1 mycroft if (node->tries >= 0) {
741 1.1 mycroft printf(" %d {$ NP %d0 %d0 $} \"%s%s\" \n",
742 1.1 mycroft (int) node->addr,
743 1.1 mycroft node->addr & 0xFF, (node->addr >> 8) & 0xFF,
744 1.1 mycroft graph_name(node->addr, name),
745 1.1 mycroft node->u.interfaces ? "" : "*");
746 1.1 mycroft for (ifc = node->u.interfaces; ifc; ifc = ifc->next)
747 1.1 mycroft for (nb = ifc->neighbors; nb; nb = nb->next) {
748 1.1 mycroft Node *nb_node = find_node(nb->addr, &routers);
749 1.1 mycroft Neighbor *nb2;
750 1.1 mycroft
751 1.1 mycroft if (nb_node->tries < 0)
752 1.1 mycroft nb_node = nb_node->u.alias;
753 1.1 mycroft
754 1.1 mycroft if (node != nb_node &&
755 1.1 mycroft (!(nb2 = find_neighbor(node->addr, nb_node))
756 1.1 mycroft || node->addr < nb_node->addr)) {
757 1.1 mycroft printf(" %d \"%d/%d",
758 1.1 mycroft nb_node->addr, nb->metric, nb->threshold);
759 1.1 mycroft if (nb2 && (nb2->metric != nb->metric
760 1.1 mycroft || nb2->threshold != nb->threshold))
761 1.1 mycroft printf(",%d/%d", nb2->metric, nb2->threshold);
762 1.1 mycroft if (nb->flags & NF_PRESENT)
763 1.1 mycroft printf("%s%s",
764 1.1 mycroft nb->flags & DVMRP_NF_SRCRT ? "" :
765 1.1 mycroft nb->flags & DVMRP_NF_TUNNEL ? "E" : "P",
766 1.1 mycroft nb->flags & DVMRP_NF_DOWN ? "D" : "");
767 1.1 mycroft printf("\"\n");
768 1.1 mycroft }
769 1.1 mycroft }
770 1.1 mycroft printf(" ;\n");
771 1.1 mycroft }
772 1.1 mycroft graph_edges(node->right);
773 1.1 mycroft }
774 1.1 mycroft }
775 1.1 mycroft
776 1.1 mycroft void elide_aliases(node)
777 1.1 mycroft Node *node;
778 1.1 mycroft {
779 1.1 mycroft if (node) {
780 1.1 mycroft elide_aliases(node->left);
781 1.1 mycroft if (node->tries >= 0) {
782 1.1 mycroft Interface *ifc;
783 1.1 mycroft
784 1.1 mycroft for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
785 1.1 mycroft Neighbor *nb;
786 1.1 mycroft
787 1.1 mycroft for (nb = ifc->neighbors; nb; nb = nb->next) {
788 1.1 mycroft Node *nb_node = find_node(nb->addr, &routers);
789 1.1 mycroft
790 1.1 mycroft if (nb_node->tries < 0)
791 1.1 mycroft nb->addr = nb_node->u.alias->addr;
792 1.1 mycroft }
793 1.1 mycroft }
794 1.1 mycroft }
795 1.1 mycroft elide_aliases(node->right);
796 1.1 mycroft }
797 1.1 mycroft }
798 1.1 mycroft
799 1.1 mycroft void graph_map()
800 1.1 mycroft {
801 1.1 mycroft time_t now = time(0);
802 1.1 mycroft char *nowstr = ctime(&now);
803 1.1 mycroft
804 1.1 mycroft nowstr[24] = '\0'; /* Kill the newline at the end */
805 1.1 mycroft elide_aliases(routers);
806 1.1 mycroft printf("GRAPH \"Multicast Router Connectivity: %s\" = UNDIRECTED\n",
807 1.1 mycroft nowstr);
808 1.1 mycroft graph_edges(routers);
809 1.1 mycroft printf("END\n");
810 1.1 mycroft }
811 1.1 mycroft
812 1.1 mycroft
813 1.1 mycroft int get_number(var, deflt, pargv, pargc)
814 1.1 mycroft int *var, *pargc, deflt;
815 1.1 mycroft char ***pargv;
816 1.1 mycroft {
817 1.1 mycroft if ((*pargv)[0][2] == '\0') { /* Get the value from the next argument */
818 1.1 mycroft if (*pargc > 1 && isdigit((*pargv)[1][0])) {
819 1.1 mycroft (*pargv)++, (*pargc)--;
820 1.1 mycroft *var = atoi((*pargv)[0]);
821 1.1 mycroft return 1;
822 1.1 mycroft } else if (deflt >= 0) {
823 1.1 mycroft *var = deflt;
824 1.1 mycroft return 1;
825 1.1 mycroft } else
826 1.1 mycroft return 0;
827 1.1 mycroft } else { /* Get value from the rest of this argument */
828 1.1 mycroft if (isdigit((*pargv)[0][2])) {
829 1.1 mycroft *var = atoi((*pargv)[0] + 2);
830 1.1 mycroft return 1;
831 1.1 mycroft } else {
832 1.1 mycroft return 0;
833 1.1 mycroft }
834 1.1 mycroft }
835 1.1 mycroft }
836 1.1 mycroft
837 1.1 mycroft
838 1.1 mycroft u_int32_t host_addr(name)
839 1.1 mycroft char *name;
840 1.1 mycroft {
841 1.1 mycroft struct hostent *e = gethostbyname(name);
842 1.1 mycroft int addr;
843 1.1 mycroft
844 1.1 mycroft if (e)
845 1.1 mycroft memcpy(&addr, e->h_addr_list[0], e->h_length);
846 1.1 mycroft else {
847 1.1 mycroft addr = inet_addr(name);
848 1.1 mycroft if (addr == -1)
849 1.1 mycroft addr = 0;
850 1.1 mycroft }
851 1.1 mycroft
852 1.1 mycroft return addr;
853 1.1 mycroft }
854 1.1 mycroft
855 1.1 mycroft
856 1.1 mycroft int main(argc, argv)
857 1.1 mycroft int argc;
858 1.1 mycroft char *argv[];
859 1.1 mycroft {
860 1.1 mycroft int flood = FALSE, graph = FALSE;
861 1.1 mycroft
862 1.1 mycroft setlinebuf(stderr);
863 1.1 mycroft
864 1.1 mycroft if (geteuid() != 0) {
865 1.1 mycroft fprintf(stderr, "must be root\n");
866 1.1 mycroft exit(1);
867 1.1 mycroft }
868 1.1 mycroft
869 1.1 mycroft argv++, argc--;
870 1.1 mycroft while (argc > 0 && argv[0][0] == '-') {
871 1.1 mycroft switch (argv[0][1]) {
872 1.1 mycroft case 'd':
873 1.1 mycroft if (!get_number(&debug, DEFAULT_DEBUG, &argv, &argc))
874 1.1 mycroft goto usage;
875 1.1 mycroft break;
876 1.1 mycroft case 'f':
877 1.1 mycroft flood = TRUE;
878 1.1 mycroft break;
879 1.1 mycroft case 'g':
880 1.1 mycroft graph = TRUE;
881 1.1 mycroft break;
882 1.1 mycroft case 'n':
883 1.1 mycroft show_names = FALSE;
884 1.1 mycroft break;
885 1.1 mycroft case 'r':
886 1.1 mycroft if (!get_number(&retries, -1, &argv, &argc))
887 1.1 mycroft goto usage;
888 1.1 mycroft break;
889 1.1 mycroft case 't':
890 1.1 mycroft if (!get_number(&timeout, -1, &argv, &argc))
891 1.1 mycroft goto usage;
892 1.1 mycroft break;
893 1.1 mycroft default:
894 1.1 mycroft goto usage;
895 1.1 mycroft }
896 1.1 mycroft argv++, argc--;
897 1.1 mycroft }
898 1.1 mycroft
899 1.1 mycroft if (argc > 1) {
900 1.1 mycroft usage:
901 1.1 mycroft fprintf(stderr,
902 1.1 mycroft "Usage: map-mbone [-f] [-g] [-n] [-t timeout] %s\n\n",
903 1.1 mycroft "[-r retries] [-d [debug-level]] [router]");
904 1.1 mycroft fprintf(stderr, "\t-f Flood the routing graph with queries\n");
905 1.1 mycroft fprintf(stderr, "\t (True by default unless `router' is given)\n");
906 1.1 mycroft fprintf(stderr, "\t-g Generate output in GraphEd format\n");
907 1.1 mycroft fprintf(stderr, "\t-n Don't look up DNS names for routers\n");
908 1.1 mycroft exit(1);
909 1.1 mycroft } else if (argc == 1 && !(target_addr = host_addr(argv[0]))) {
910 1.1 mycroft fprintf(stderr, "Unknown host: %s\n", argv[0]);
911 1.1 mycroft exit(2);
912 1.1 mycroft }
913 1.1 mycroft
914 1.1 mycroft if (debug)
915 1.1 mycroft fprintf(stderr, "Debug level %u\n", debug);
916 1.1 mycroft
917 1.1 mycroft init_igmp();
918 1.1 mycroft
919 1.1 mycroft { /* Find a good local address for us. */
920 1.1 mycroft int udp;
921 1.1 mycroft struct sockaddr_in addr;
922 1.1 mycroft int addrlen = sizeof(addr);
923 1.1 mycroft
924 1.8.2.1 lukem memset(&addr, 0, sizeof(addr));
925 1.1 mycroft addr.sin_family = AF_INET;
926 1.1 mycroft #if (defined(BSD) && (BSD >= 199103))
927 1.1 mycroft addr.sin_len = sizeof addr;
928 1.1 mycroft #endif
929 1.1 mycroft addr.sin_addr.s_addr = dvmrp_group;
930 1.1 mycroft addr.sin_port = htons(2000); /* any port over 1024 will do... */
931 1.1 mycroft if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0
932 1.1 mycroft || connect(udp, (struct sockaddr *) &addr, sizeof(addr)) < 0
933 1.1 mycroft || getsockname(udp, (struct sockaddr *) &addr, &addrlen) < 0) {
934 1.1 mycroft perror("Determining local address");
935 1.6 wiz exit(1);
936 1.1 mycroft }
937 1.1 mycroft close(udp);
938 1.1 mycroft our_addr = addr.sin_addr.s_addr;
939 1.1 mycroft }
940 1.1 mycroft
941 1.1 mycroft /* Send initial seed message to all local routers */
942 1.1 mycroft ask(target_addr ? target_addr : allhosts_group);
943 1.1 mycroft
944 1.1 mycroft if (target_addr) {
945 1.1 mycroft Node *n = find_node(target_addr, &routers);
946 1.1 mycroft
947 1.1 mycroft n->tries = 1;
948 1.1 mycroft
949 1.1 mycroft if (flood)
950 1.1 mycroft target_addr = 0;
951 1.1 mycroft }
952 1.1 mycroft
953 1.1 mycroft /* Main receive loop */
954 1.1 mycroft for(;;) {
955 1.1 mycroft fd_set fds;
956 1.1 mycroft struct timeval tv;
957 1.1 mycroft int count, recvlen, dummy = 0;
958 1.1 mycroft
959 1.1 mycroft FD_ZERO(&fds);
960 1.1 mycroft FD_SET(igmp_socket, &fds);
961 1.1 mycroft
962 1.1 mycroft tv.tv_sec = timeout;
963 1.1 mycroft tv.tv_usec = 0;
964 1.1 mycroft
965 1.1 mycroft count = select(igmp_socket + 1, &fds, 0, 0, &tv);
966 1.1 mycroft
967 1.1 mycroft if (count < 0) {
968 1.1 mycroft if (errno != EINTR)
969 1.1 mycroft perror("select");
970 1.1 mycroft continue;
971 1.1 mycroft } else if (count == 0) {
972 1.1 mycroft log(LOG_DEBUG, 0, "Timed out receiving neighbor lists");
973 1.1 mycroft if (retry_requests(routers))
974 1.1 mycroft continue;
975 1.1 mycroft else
976 1.1 mycroft break;
977 1.1 mycroft }
978 1.1 mycroft
979 1.1 mycroft recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
980 1.1 mycroft 0, NULL, &dummy);
981 1.1 mycroft if (recvlen >= 0)
982 1.1 mycroft accept_igmp(recvlen);
983 1.1 mycroft else if (errno != EINTR)
984 1.1 mycroft perror("recvfrom");
985 1.1 mycroft }
986 1.1 mycroft
987 1.1 mycroft printf("\n");
988 1.1 mycroft
989 1.1 mycroft if (graph)
990 1.1 mycroft graph_map();
991 1.1 mycroft else {
992 1.1 mycroft if (!target_addr)
993 1.1 mycroft printf("Multicast Router Connectivity:\n\n");
994 1.1 mycroft print_map(routers);
995 1.1 mycroft }
996 1.1 mycroft
997 1.1 mycroft exit(0);
998 1.1 mycroft }
999 1.1 mycroft
1000 1.3 mycroft /* dummies */
1001 1.3 mycroft void accept_prune(src, dst, p, datalen)
1002 1.3 mycroft u_int32_t src, dst;
1003 1.3 mycroft char *p;
1004 1.3 mycroft int datalen;
1005 1.3 mycroft {
1006 1.3 mycroft }
1007 1.3 mycroft void accept_graft(src, dst, p, datalen)
1008 1.3 mycroft u_int32_t src, dst;
1009 1.3 mycroft char *p;
1010 1.3 mycroft int datalen;
1011 1.3 mycroft {
1012 1.3 mycroft }
1013 1.3 mycroft void accept_g_ack(src, dst, p, datalen)
1014 1.3 mycroft u_int32_t src, dst;
1015 1.3 mycroft char *p;
1016 1.3 mycroft int datalen;
1017 1.1 mycroft {
1018 1.1 mycroft }
1019 1.3 mycroft void add_table_entry(origin, mcastgrp)
1020 1.3 mycroft u_int32_t origin, mcastgrp;
1021 1.1 mycroft {
1022 1.1 mycroft }
1023 1.3 mycroft void accept_leave_message(src, dst, group)
1024 1.3 mycroft u_int32_t src, dst, group;
1025 1.1 mycroft {
1026 1.1 mycroft }
1027 1.3 mycroft void accept_mtrace(src, dst, group, data, no, datalen)
1028 1.3 mycroft u_int32_t src, dst, group;
1029 1.3 mycroft char *data;
1030 1.3 mycroft u_int no;
1031 1.3 mycroft int datalen;
1032 1.1 mycroft {
1033 1.1 mycroft }
1034 1.3 mycroft void accept_membership_query(src, dst, group, tmo)
1035 1.3 mycroft u_int32_t src, dst, group;
1036 1.3 mycroft int tmo;
1037 1.1 mycroft {
1038 1.1 mycroft }
1039 1.3 mycroft void accept_info_request(src, dst, p, datalen)
1040 1.3 mycroft u_int32_t src, dst;
1041 1.3 mycroft u_char *p;
1042 1.3 mycroft int datalen;
1043 1.1 mycroft {
1044 1.1 mycroft }
1045 1.3 mycroft void accept_info_reply(src, dst, p, datalen)
1046 1.3 mycroft u_int32_t src, dst;
1047 1.3 mycroft u_char *p;
1048 1.3 mycroft int datalen;
1049 1.1 mycroft {
1050 1.1 mycroft }
1051