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