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