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