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