Bug Summary

File:src/usr.sbin/map-mbone/mapper.c
Warning:line 808, column 5
The return value from the call to 'setuid' is not checked. If an error occurs in 'setuid', the following code may execute with unexpected privileges

Annotated Source Code

Press '?' to see keyboard shortcuts

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