Home | History | Annotate | Line # | Download | only in map-mbone
mapper.c revision 1.25
      1  1.25    perry /*	$NetBSD: mapper.c,v 1.25 2007/12/15 16:32:07 perry 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.25    perry #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