aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/mrouted
diff options
context:
space:
mode:
authorBill Fenner <fenner@FreeBSD.org>1996-11-11 03:50:15 +0000
committerBill Fenner <fenner@FreeBSD.org>1996-11-11 03:50:15 +0000
commitf014b7e69bbd6737e73d43099fdb4ba32e99b5ad (patch)
tree165f9cfd99d55b06f466b5dad237613485ce8624 /usr.sbin/mrouted
parentf29c770b37549c04aba8981e60954c3878a59bd8 (diff)
downloadsrc-f014b7e69bbd6737e73d43099fdb4ba32e99b5ad.tar.gz
src-f014b7e69bbd6737e73d43099fdb4ba32e99b5ad.zip
Update to the unreleased mrouted 3.8a . This includes a minor
endian-ness fix, Router Alert options on IGMP messages, and a new keyword, "advert_metric", for fine-tuning tunnel metrics. This also includes a new mtrace, which is also unreleased but builds significantly on the experiences of users' troubles with using and understanding mtrace in release 3.8 . (unreleased does not, of course, mean untested!) This is a candidate for both 2.2 and 2.1.6 .
Notes
Notes: svn path=/head/; revision=19620
Diffstat (limited to 'usr.sbin/mrouted')
-rw-r--r--usr.sbin/mrouted/cfparse.y25
-rw-r--r--usr.sbin/mrouted/config.c3
-rw-r--r--usr.sbin/mrouted/defs.h14
-rw-r--r--usr.sbin/mrouted/igmp.c122
-rw-r--r--usr.sbin/mrouted/inet.c12
-rw-r--r--usr.sbin/mrouted/kern.c4
-rw-r--r--usr.sbin/mrouted/main.c6
-rw-r--r--usr.sbin/mrouted/mrinfo.82
-rw-r--r--usr.sbin/mrouted/mrouted.825
-rw-r--r--usr.sbin/mrouted/mtrace.879
-rw-r--r--usr.sbin/mrouted/mtrace.c368
-rw-r--r--usr.sbin/mrouted/prune.c39
-rw-r--r--usr.sbin/mrouted/route.c24
-rw-r--r--usr.sbin/mrouted/rsrr.c15
-rw-r--r--usr.sbin/mrouted/vif.c95
-rw-r--r--usr.sbin/mrouted/vif.h3
16 files changed, 602 insertions, 234 deletions
diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y
index ab5b89f30ea8..54f80bcb82af 100644
--- a/usr.sbin/mrouted/cfparse.y
+++ b/usr.sbin/mrouted/cfparse.y
@@ -4,7 +4,7 @@
*
* Written by Bill Fenner, NRL, 1994
*
- * $Id: cfparse.y,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: cfparse.y,v 3.8.1.2 1996/08/09 22:46:18 fenner Exp $
*/
#include <stdio.h>
#ifdef __STDC__
@@ -71,7 +71,7 @@ int numbounds = 0; /* Number of named boundaries */
%token CACHE_LIFETIME PRUNING
%token PHYINT TUNNEL NAME
%token DISABLE IGMPV1 SRCRT
-%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET
+%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET ADVERT_METRIC
%token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION
%token <num> BOOLEAN
%token <num> NUMBER
@@ -157,6 +157,7 @@ stmt : error
v = &uvifs[numvifs];
v->uv_flags = VIFF_TUNNEL;
v->uv_metric = DEFAULT_METRIC;
+ v->uv_admetric = 0;
v->uv_rate_limit= DEFAULT_TUN_RATE_LIMIT;
v->uv_threshold = DEFAULT_THRESHOLD;
v->uv_lcl_addr = $2;
@@ -294,6 +295,15 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
warn("Expected number after metric keyword, ignored");
}
+ | ADVERT_METRIC NUMBER { if ($2 < 0 || $2 > UNREACHABLE - 1)
+ fatal("Invalid advert_metric %d", $2);
+ v->uv_admetric = $2;
+ }
+ | ADVERT_METRIC {
+
+ warn("Expected number after advert_metric keyword, ignored");
+
+ }
| RATE_LIMIT NUMBER { if ($2 > MAX_RATE_LIMIT)
fatal("Invalid rate_limit %d",$2);
v->uv_rate_limit = $2;
@@ -504,6 +514,8 @@ yylex()
return DISABLE;
if (!strcmp(q,"metric"))
return METRIC;
+ if (!strcmp(q,"advert_metric"))
+ return ADVERT_METRIC;
if (!strcmp(q,"threshold"))
return THRESHOLD;
if (!strcmp(q,"rate_limit"))
@@ -528,8 +540,13 @@ yylex()
yylval.num = 0;
return BOOLEAN;
}
+ if (!strcmp(q,"default")) {
+ yylval.addrmask.mask = 0;
+ yylval.addrmask.addr = 0;
+ return ADDRMASK;
+ }
if (sscanf(q,"%[.0-9]/%d%c",s1,&n,s2) == 2) {
- if ((addr = inet_parse(s1)) != 0xffffffff) {
+ if ((addr = inet_parse(s1,1)) != 0xffffffff) {
yylval.addrmask.mask = n;
yylval.addrmask.addr = addr;
return ADDRMASK;
@@ -537,7 +554,7 @@ yylex()
/* fall through to returning STRING */
}
if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) {
- if ((addr = inet_parse(s1)) != 0xffffffff &&
+ if ((addr = inet_parse(s1,4)) != 0xffffffff &&
inet_valid_host(addr)) {
yylval.addr = addr;
return ADDR;
diff --git a/usr.sbin/mrouted/config.c b/usr.sbin/mrouted/config.c
index 1147412b904e..64cf3f60a11e 100644
--- a/usr.sbin/mrouted/config.c
+++ b/usr.sbin/mrouted/config.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: config.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: config.c,v 3.8.1.1 1996/08/09 22:46:16 fenner Exp $
*/
@@ -116,6 +116,7 @@ config_vifs_from_kernel()
v = &uvifs[numvifs];
v->uv_flags = 0;
v->uv_metric = DEFAULT_METRIC;
+ v->uv_admetric = 0;
v->uv_rate_limit = DEFAULT_PHY_RATE_LIMIT;
v->uv_threshold = DEFAULT_THRESHOLD;
v->uv_lcl_addr = addr;
diff --git a/usr.sbin/mrouted/defs.h b/usr.sbin/mrouted/defs.h
index 63aef773e77c..4e19349ff061 100644
--- a/usr.sbin/mrouted/defs.h
+++ b/usr.sbin/mrouted/defs.h
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: defs.h,v 3.8 1995/11/29 22:36:34 fenner Rel $
+ * $Id: defs.h,v 3.8.1.2 1996/09/05 19:00:20 fenner Exp $
*/
@@ -160,10 +160,20 @@ extern char * sys_errlist[];
#define MRT_DEL_VIF DVMRP_DEL_VIF
#define MRT_ADD_MFC DVMRP_ADD_MFC
#define MRT_DEL_MFC DVMRP_DEL_MFC
+#endif
+#ifndef IGMP_PIM
#define IGMP_PIM 0x14
#endif
+#ifndef IGMP_MEMBERSHIP_QUERY
+#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
+#define IGMP_V1_MEMBERSHIP_REPORT IGMP_HOST_MEMBERSHIP_REPORT
+#define IGMP_V2_MEMBERSHIP_REPORT IGMP_HOST_NEW_MEMBERSHIP_REPORT
+#define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE
+#endif
+
+
/* main.c */
extern void log __P((int, int, char *, ...));
extern int register_input_handler __P((int fd, ihfunc_t func));
@@ -247,7 +257,7 @@ extern int inet_valid_host __P((u_int32 naddr));
extern int inet_valid_subnet __P((u_int32 nsubnet, u_int32 nmask));
extern char * inet_fmt __P((u_int32 addr, char *s));
extern char * inet_fmts __P((u_int32 addr, u_int32 mask, char *s));
-extern u_int32 inet_parse __P((char *s));
+extern u_int32 inet_parse __P((char *s, int n));
extern int inet_cksum __P((u_short *addr, u_int len));
/* prune.c */
diff --git a/usr.sbin/mrouted/igmp.c b/usr.sbin/mrouted/igmp.c
index bbcd707c3971..f1ded9afe495 100644
--- a/usr.sbin/mrouted/igmp.c
+++ b/usr.sbin/mrouted/igmp.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: igmp.c,v 1.9 1996/01/06 21:09:44 peter Exp $
+ * $Id: igmp.c,v 3.8.1.1 1996/08/09 22:49:12 fenner Exp $
*/
@@ -26,6 +26,23 @@ u_int32 dvmrp_group; /* DVMRP grp addr in net order */
u_int32 dvmrp_genid; /* IGMP generation id */
/*
+ * Private variables
+ */
+static char router_alert[4]; /* Router Alert IP Option */
+#ifndef IPOPT_RA
+#define IPOPT_RA 148
+#endif
+#ifdef SUNOS5
+static char no_op[4]; /* Null IP Option */
+static int ip_addlen = 0; /* Workaround for Option bug #2*/
+#endif
+#define SEND_RA(x) (((x) == IGMP_MEMBERSHIP_QUERY) || \
+ ((x) == IGMP_V1_MEMBERSHIP_REPORT) || \
+ ((x) == IGMP_V2_MEMBERSHIP_REPORT) || \
+ ((x) == IGMP_V2_LEAVE_GROUP) || \
+ ((x) == IGMP_MTRACE))
+
+/*
* Local function definitions.
*/
/* u_char promoted to u_int */
@@ -40,6 +57,9 @@ void
init_igmp()
{
struct ip *ip;
+#ifdef SUNOS5
+ u_int32 localhost = htonl(0x7f000001);
+#endif
recv_buf = malloc(RECV_BUF_SIZE);
send_buf = malloc(RECV_BUF_SIZE);
@@ -63,6 +83,67 @@ init_igmp()
allhosts_group = htonl(INADDR_ALLHOSTS_GROUP);
dvmrp_group = htonl(INADDR_DVMRP_GROUP);
allrtrs_group = htonl(INADDR_ALLRTRS_GROUP);
+
+ router_alert[0] = IPOPT_RA; /* Router Alert */
+ router_alert[1] = 4; /* 4 bytes */
+ router_alert[2] = 0;
+ router_alert[3] = 0;
+
+#ifdef SUNOS5
+ no_op[0] = IPOPT_NOP;
+ no_op[1] = IPOPT_NOP;
+ no_op[2] = IPOPT_NOP;
+ no_op[3] = IPOPT_NOP;
+
+ setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS, no_op, sizeof(no_op));
+ /*
+ * Check if the kernel adds the options length to the packet
+ * length. Send myself an IGMP packet of type 0 (illegal),
+ * with 4 IPOPT_NOP options, my PID (for collision detection)
+ * and 4 bytes of zero (so that the checksum works whether
+ * the 4 bytes of zero get truncated or not).
+ */
+ bzero(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN, 8);
+ *(int *)(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN) = getpid();
+ send_igmp(localhost, localhost, 0, 0, 0, 8);
+ while (1) {
+ int recvlen, dummy = 0;
+
+ recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
+ 0, NULL, &dummy);
+ /* 8 == 4 bytes of options and 4 bytes of PID */
+ if (recvlen >= MIN_IP_HEADER_LEN + IGMP_MINLEN + 8) {
+ struct ip *ip = (struct ip *)recv_buf;
+ struct igmp *igmp;
+ int *p;
+
+ if (ip->ip_hl != 6 ||
+ ip->ip_p != IPPROTO_IGMP ||
+ ip->ip_src.s_addr != localhost ||
+ ip->ip_dst.s_addr != localhost)
+ continue;
+
+ igmp = (struct igmp *)(recv_buf + (ip->ip_hl << 2));
+ if (igmp->igmp_group.s_addr != 0)
+ continue;
+ if (igmp->igmp_type != 0 || igmp->igmp_code != 0)
+ continue;
+
+ p = (int *)((char *)igmp + IGMP_MINLEN);
+ if (*p != getpid())
+ continue;
+
+ if (ip->ip_len == IGMP_MINLEN + 4)
+ ip_addlen = 4;
+ else if (ip->ip_len == IGMP_MINLEN + 8)
+ ip_addlen = 0;
+ else
+ log(LOG_ERR, 0, "while checking for Solaris bug: Sent %d bytes and got back %d!", IGMP_MINLEN + 8, ip->ip_len);
+
+ break;
+ }
+ }
+#endif
}
#define PIM_QUERY 0
@@ -80,8 +161,8 @@ packet_kind(type, code)
{
switch (type) {
case IGMP_HOST_MEMBERSHIP_QUERY: return "membership query ";
- case IGMP_HOST_MEMBERSHIP_REPORT: return "membership report ";
- case IGMP_HOST_NEW_MEMBERSHIP_REPORT: return "new member report ";
+ case IGMP_HOST_MEMBERSHIP_REPORT: return "V1 member report ";
+ case IGMP_HOST_NEW_MEMBERSHIP_REPORT: return "V2 member report ";
case IGMP_HOST_LEAVE_MESSAGE: return "leave message ";
case IGMP_DVMRP:
switch (code) {
@@ -310,12 +391,19 @@ send_igmp(src, dst, type, code, group, datalen)
struct sockaddr_in sdst;
struct ip *ip;
struct igmp *igmp;
- int setloop;
+ int setloop = 0;
+ static int raset = 0;
+ int sendra = 0;
+ int sendlen;
ip = (struct ip *)send_buf;
ip->ip_src.s_addr = src;
ip->ip_dst.s_addr = dst;
ip->ip_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;
+ sendlen = ip->ip_len;
+#ifdef SUNOS5
+ ip->ip_len += ip_addlen;
+#endif
igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN);
igmp->igmp_type = type;
@@ -331,6 +419,27 @@ send_igmp(src, dst, type, code, group, datalen)
setloop = 1;
k_set_loop(TRUE);
}
+ if (SEND_RA(type))
+ sendra = 1;
+ }
+
+ if (sendra && !raset) {
+ setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,
+ router_alert, sizeof(router_alert));
+ raset = 1;
+ } else if (!sendra && raset) {
+#ifdef SUNOS5
+ /*
+ * SunOS5 < 5.6 cannot properly reset the IP_OPTIONS "socket"
+ * option. Instead, set up a string of 4 no-op's.
+ */
+ setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,
+ no_op, sizeof(no_op));
+#else
+ setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,
+ NULL, 0);
+#endif
+ raset = 0;
}
bzero(&sdst, sizeof(sdst));
@@ -339,7 +448,7 @@ send_igmp(src, dst, type, code, group, datalen)
sdst.sin_len = sizeof(sdst);
#endif
sdst.sin_addr.s_addr = dst;
- if (sendto(igmp_socket, send_buf, ip->ip_len, 0,
+ if (sendto(igmp_socket, send_buf, sendlen, 0,
(struct sockaddr *)&sdst, sizeof(sdst)) < 0) {
if (errno == ENETDOWN)
check_vif_state();
@@ -353,5 +462,6 @@ send_igmp(src, dst, type, code, group, datalen)
k_set_loop(FALSE);
log(LOG_DEBUG, 0, "SENT %s from %-15s to %s",
- packet_kind(type, code), inet_fmt(src, s1), inet_fmt(dst, s2));
+ packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" :
+ inet_fmt(src, s1), inet_fmt(dst, s2));
}
diff --git a/usr.sbin/mrouted/inet.c b/usr.sbin/mrouted/inet.c
index b60e3854da35..e0ce09e15201 100644
--- a/usr.sbin/mrouted/inet.c
+++ b/usr.sbin/mrouted/inet.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: inet.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: inet.c,v 3.8.1.1 1995/12/01 22:20:26 fenner Exp $
*/
@@ -155,15 +155,17 @@ inet_fmts(addr, mask, s)
* with "255.255.255.255".)
*/
u_int32
-inet_parse(s)
+inet_parse(s,n)
char *s;
+ int n;
{
u_int32 a = 0;
- u_int a0, a1, a2, a3;
+ u_int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
+ int i;
char c;
- if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 ||
- a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
+ i = sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c);
+ if (i < n || i > 4 || a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
return (0xffffffff);
((u_char *)&a)[0] = a0;
diff --git a/usr.sbin/mrouted/kern.c b/usr.sbin/mrouted/kern.c
index 2a64e5c13916..b8b88dc1cd39 100644
--- a/usr.sbin/mrouted/kern.c
+++ b/usr.sbin/mrouted/kern.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: kern.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: kern.c,v 3.8.1.1 1995/12/07 18:17:58 fenner Exp $
*/
@@ -150,7 +150,7 @@ void k_del_vif(vifi)
{
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF,
(char *)&vifi, sizeof(vifi)) < 0)
- log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF");
+ log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
}
diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c
index 21ae32150a50..40f75633e090 100644
--- a/usr.sbin/mrouted/main.c
+++ b/usr.sbin/mrouted/main.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: main.c,v 1.7 1996/01/06 21:09:51 peter Exp $
+ * $Id: main.c,v 3.8.1.3 1996/09/06 18:30:00 fenner Exp $
*/
/*
@@ -34,7 +34,7 @@
#ifndef lint
static char rcsid[] =
- "@(#) $Id: main.c,v 1.7 1996/01/06 21:09:51 peter Exp $";
+ "@(#) $Id: main.c,v 3.8.1.3 1996/09/06 18:30:00 fenner Exp $";
#endif
extern char *configfilename;
@@ -192,7 +192,7 @@ usage: fprintf(stderr,
#else
(void)openlog("mrouted", LOG_PID);
#endif
- sprintf(versionstring, "mrouted version %d.%d",
+ sprintf(versionstring, "mrouted version %d.%da",
PROTOCOL_VERSION, MROUTED_VERSION);
log(LOG_NOTICE, 0, "%s", versionstring);
diff --git a/usr.sbin/mrouted/mrinfo.8 b/usr.sbin/mrouted/mrinfo.8
index 8001b2bde841..1e7f9a91159a 100644
--- a/usr.sbin/mrouted/mrinfo.8
+++ b/usr.sbin/mrouted/mrinfo.8
@@ -66,7 +66,7 @@ reply. Default timeout is 4 seconds.
.PP
For each neighbor of the queried multicast router, the IP of the queried router
is displayed, followed by the IP and name of the neighbor. In square brackets
-the metric (cost of connection), the threshold (multicast ttl) is displayed. If
+the metric (cost of connection), the treashold (multicast ttl) is displayed. If
the queried multicast router has a newer version number, the type (tunnel,
srcrt) and status (disabled, down) of the connection is displayed.
.PP
diff --git a/usr.sbin/mrouted/mrouted.8 b/usr.sbin/mrouted/mrouted.8
index 6c4c7bd98616..246139c06fc0 100644
--- a/usr.sbin/mrouted/mrouted.8
+++ b/usr.sbin/mrouted/mrouted.8
@@ -1,5 +1,5 @@
'\"COPYRIGHT 1989 by The Board of Trustees of Leland Stanford Junior University.
-'\"$Id: mrouted.8,v 3.8 1995/11/29 22:37:21 fenner Rel $
+'\"$Id: mrouted.8,v 3.8.1.1 1996/11/10 22:16:52 fenner Exp $
.TH MROUTED 8
.UC 5
.SH NAME
@@ -112,19 +112,17 @@ configuration commands may be placed in
There are four types of configuration commands:
.nf
- phyint <local-addr> [disable] [metric <m>]
+ phyint <local-addr> [disable] [metric <m>] [advert_metric <m>]
[threshold <t>] [rate_limit <b>]
[boundary (<boundary-name>|<scoped-addr>/<mask-len>)]
[altnet <network>/<mask-len>]
- tunnel <local-addr> <remote-addr> [metric <m>]
+ tunnel <local-addr> <remote-addr> [metric <m>] [advert_metric <m>]
[threshold <t>] [rate_limit <b>]
[boundary (<boundary-name>|<scoped-addr>/<mask-len>)]
cache_lifetime <ct>
- pruning <off/on>
-
name <boundary-name> <scoped-addr>/<mask-len>
.fi
@@ -155,23 +153,11 @@ be replaced by a host name, if and only if the host name has a single
IP address associated with it.
The tunnel must be set
up in the mrouted.conf files of both routers before it can be used.
-'\"For backwards compatibility with older
-'\".IR mrouted s,
-'\"the srcrt keyword specifies
-'\"encapsulation using IP source routing.
.PP
The cache_lifetime is a value that determines the amount of time that a
cached multicast route stays in kernel before timing out. The value of this
entry should lie between 300 (5 min) and 86400 (1 day). It defaults to 300.
.PP
-The pruning <off/on> option is provided for
-.IR mrouted
-to act as a non-pruning router. It is also possible to start
-.IR mrouted
-in a non-pruning mode using the "-p" option on the command line. It is
-expected that a router would be configured in this manner for test
-purposes only. The default mode is pruning enabled.
-.PP
You may assign names to boundaries to make configuration easier with
the name keyword. The boundary option on phyint or tunnel commands
can accept either a name or a boundary.
@@ -183,6 +169,11 @@ because
.I mrouted
cannot route along paths with a sum of metrics greater
than 31.
+.PP
+The advert_metric is the "cost" associated with receiving a datagram
+on the given interface or tunnel; it may be used to influence the choice
+of routes. The advert_metric defaults to 0. Note that the effective
+metric of a link is one end's metric plus the other end's advert_metric.
.LP
The threshold is the minimum IP time-to-live required for a multicast datagram
to be forwarded to the given interface or tunnel. It is used to control the
diff --git a/usr.sbin/mrouted/mtrace.8 b/usr.sbin/mrouted/mtrace.8
index 5c8e1fe13465..11bffe1c054d 100644
--- a/usr.sbin/mrouted/mtrace.8
+++ b/usr.sbin/mrouted/mtrace.8
@@ -29,7 +29,7 @@
.\" Copyright (c) 1988 The Regents of the University of California.
.\" All rights reserved.
.\"
-.\" $Id: mtrace.8,v 3.8 1995/11/29 22:37:21 fenner Rel $
+.\" $Id: mtrace.8,v 3.8.1.1 1996/11/10 22:24:15 fenner Exp $
.\"
.TH MTRACE 8 "May 8, 1995"
.UC 6
@@ -48,6 +48,8 @@ mtrace \- print multicast path from a source to a receiver
] [
.B \-M
] [
+.B \-T
+] [
.B \-m
.I max_hops
] [
@@ -110,6 +112,13 @@ detailed below. The two parameters can be distinguished because the
is a unicast address and the
.I group
is a multicast address.
+If the
+.B \-g
+flag is specified, the source address defaults to the host running
+mtrace, and the receiver defaults to the router being addressed with
+the
+.B \-g
+flag. In this case, there are no required parameters.
.PP
NOTE: For Solaris 2.4/2.5, if the multicast interface is not the default
interface, the -i option must be used to set the local address.
@@ -202,11 +211,16 @@ seconds (default 10 seconds).
Set the
.I ttl
(time-to-live, or number of hops) for multicast trace queries and
-responses. The default is 64, except for local queries to the "all
+responses. The default is 127, except for local queries to the "all
routers" multicast group which use ttl 1.
.TP 8 8
+.B \-T
+"Tunnel statistics" mode; show loss rates for overall traffic.
+These statistics can be extremely misleading.
+.TP 8 8
.B \-v
Verbose mode; show hop times on the initial trace and statistics display.
+Also show the route that was used to forward the initial trace.
.TP 8 8
.BI \-w\ n
Set the time to wait for a trace response to
@@ -273,7 +287,7 @@ trace query is multicast to the
address since the last hop router will be a member of that group if
the receiver is. Therefore it is necessary to specify a group that
the intended receiver has joined. This multicast is sent with a
-default ttl of 64, which may not be sufficient for all cases (changed
+default ttl of 127, which may not be sufficient for all cases (changed
with the
.B \-t
option).
@@ -316,7 +330,7 @@ multicast to mtrace.mcast.net (224.0.1.32) with the ttl set to 32 more
than what's needed to pass the thresholds seen so far along the path
to the receiver. For the last quarter of the attempts (default is
one), the ttl is increased by another 32 each time up to a maximum of
-192. Alternatively, the ttl may be set explicity with the
+192. Alternatively, the ttl may be set explicitly with the
.B \-t
option and/or the initial unicast attempts can be forced to use
multicast instead with the
@@ -346,7 +360,8 @@ up-arrow character); and the cumulative delay for the query to reach
that hop (valid only if the clocks are synchronized). This first
section ends with a line showing the round-trip time which measures
the interval from when the query is issued until the response is
-received, both derived from the local system clock. A sample use and
+received, both derived from the local system clock, and the total
+ttl required for a packet to travel along this path. A sample use and
output might be:
.PP
.nf
@@ -361,18 +376,29 @@ Querying full reverse path...
-4 bbn.dart.net (140.173.32.1) DVMRP thresh^ 1 63 ms
-5 mit.dart.net (140.173.48.2) DVMRP thresh^ 1 71 ms
-6 caraway.lcs.mit.edu (18.26.0.170)
-Round trip time 124 ms
+Round trip time 124 ms; total ttl of 6 required.
.fi
.PP
+If a hop reports that it is using the default route to forward packets,
+the word
+.B [default]
+is printed after that hop. If the
+.B \-v
+flag is supplied, the route being used to forward packets is printed
+in the form
+.B [18.26.0/24] .
+.PP
The second section provides a pictorial view of the path in the
forward direction with data flow indicated by arrows pointing downward
and the query path indicated by arrows pointing upward. For each hop,
both the entry and exit addresses of the router are shown if
different, along with the initial ttl required on the packet in order
to be forwarded at this hop and the propagation delay across the hop
-assuming that the routers at both ends have synchronized clocks. The
-right half of this section is composed of several columns of
-statistics in two groups. Within each group, the columns are the
+assuming that the routers at both ends have synchronized clocks.
+The right half of this section is composed of two sets of statistics.
+The first column contains the average packet rate for all traffic at
+each hop.
+The remaining columns are the
number of packets lost, the number of packets sent, the percentage
lost, and the average packet rate at each hop. These statistics are
calculated from differences between traces and from hop to hop as
@@ -383,6 +409,11 @@ from the specified
.I source
to the specified
.IR group .
+The first group of statistics may be expanded to include loss rates
+using the
+.B \-T
+option. However, these numbers can be extremely misleading and require
+detailed knowledge of the routers involved to be interpreted properly.
.PP
These statistics are shown on one or two lines for each hop. Without
any options, this second section of the output is printed only once,
@@ -397,7 +428,7 @@ statistics over the period since the initial trace, which is 101
seconds in the example below. The second section of the output is
omitted if the
.B \-s
-option is set.
+option is set or if no multicast group is specified.
.ie t \{\
.ft C
. ie \w'i'<>\w'm' \{\" looks like this is not proper Courier font
@@ -411,30 +442,30 @@ and try again.)
.nf
Waiting to accumulate statistics... Results after 101 seconds:
- Source Response Dest Packet Statistics For Only For Traffic
-18.26.0.170 128.9.160.100 All Multicast Traffic From 18.26.0.170
- | __/ rtt 125 ms Lost/Sent = Pct Rate To 224.2.0.3
- v / hop 65 ms --------------------- ------------------
+ Source Response Dest Overall Packet Statistics For Traffic From
+18.26.0.170 128.9.160.100 Packet 18.26.0.170 To 224.2.0.3
+ | __/ rtt 125 ms Rate Lost/Sent = Pct Rate
+ v / hop 65 ms ------- ---------------------
18.26.0.144
140.173.48.2 mit.dart.net
- | ^ ttl 1 0/6 = --% 0 pps 0/2 = --% 0 pps
- v | hop 8 ms 1/52 = 2% 0 pps 0/18 = 0% 0 pps
+ | ^ ttl 1 0 pps 0/2 = --% 0 pps
+ v | hop 8 ms 0 pps 0/18 = 0% 0 pps
140.173.48.1
140.173.32.1 bbn.dart.net
- | ^ ttl 2 0/6 = --% 0 pps 0/2 = --% 0 pps
- v | hop 12 ms 1/52 = 2% 0 pps 0/18 = 0% 0 pps
+ | ^ ttl 2 0 pps 0/2 = --% 0 pps
+ v | hop 12 ms 0 pps 0/18 = 0% 0 pps
140.173.32.2
140.173.64.1 dc.dart.net
- | ^ ttl 3 0/271 = 0% 27 pps 0/2 = --% 0 pps
- v | hop 34 ms -1/2652 = 0% 26 pps 0/18 = 0% 0 pps
+ | ^ ttl 3 27 pps 0/2 = --% 0 pps
+ v | hop 34 ms 26 pps 0/18 = 0% 0 pps
140.173.64.2
140.173.128.1 la.dart.net
- | ^ ttl 4 -2/831 = 0% 83 pps 0/2 = --% 0 pps
- v | hop 11 ms -3/8072 = 0% 79 pps 0/18 = 0% 0 pps
+ | ^ ttl 4 83 pps 0/2 = --% 0 pps
+ v | hop 11 ms 79 pps 0/18 = 0% 0 pps
140.173.128.2
128.9.160.153 cub.isi.edu
- | \\__ ttl 5 833 83 pps 2 0 pps
- v \\ hop -8 ms 8075 79 pps 18 0 pps
+ | \\__ ttl 5 83 pps ?/2 0 pps
+ v \\ hop -8 ms 79 pps ?/18 0 pps
128.9.160.100 128.9.160.100
Receiver Query Source
.fi
diff --git a/usr.sbin/mrouted/mtrace.c b/usr.sbin/mrouted/mtrace.c
index e84d9e5f2ffa..8fe0c48ed811 100644
--- a/usr.sbin/mrouted/mtrace.c
+++ b/usr.sbin/mrouted/mtrace.c
@@ -50,7 +50,7 @@
#ifndef lint
static char rcsid[] =
- "@(#) $Id: mtrace.c,v 1.7 1996/01/06 21:10:05 peter Exp $";
+ "@(#) $Id: mtrace.c,v 3.8.1.12 1996/11/10 22:23:46 fenner Exp $";
#endif
#include <netdb.h>
@@ -74,7 +74,7 @@ static char rcsid[] =
#define DEFAULT_RETRIES 3 /* How many times to try */
#define MAXHOPS UNREACHABLE /* Don't need more hops than max metric */
#define UNICAST_TTL 255 /* TTL for unicast response */
-#define MULTICAST_TTL1 64 /* Default TTL for multicast query/response */
+#define MULTICAST_TTL1 127 /* Default TTL for multicast query/response */
#define MULTICAST_TTL_INC 32 /* TTL increment for increase after timeout */
#define MULTICAST_TTL_MAX 192 /* Maximum TTL allowed (protect low-BW links */
@@ -99,6 +99,7 @@ struct resp_buf {
char names[MAXHOPS][40];
int reset[MAXHOPS]; /* To get around 3.4 bug, ... */
int swaps[MAXHOPS]; /* To get around 3.6 bug, ... */
+int bogustime[MAXHOPS]; /* To get around 3.5 bug, ... */
int timeout = DEFAULT_TIMEOUT;
int nqueries = DEFAULT_RETRIES;
@@ -106,8 +107,11 @@ int numeric = FALSE;
int debug = 0;
int passive = FALSE;
int multicast = FALSE;
+int unicast = FALSE;
int statint = 10;
-int verbose = 0;
+int verbose = FALSE;
+int tunstats = FALSE;
+int weak = FALSE;
u_int32 defgrp; /* Default group if not specified */
u_int32 query_cast; /* All routers multicast addr */
@@ -132,11 +136,17 @@ u_int32 tdst = 0; /* Address where trace is sent (last-hop) */
vifi_t numvifs; /* to keep loader happy */
/* (see kern.c) */
+
#ifndef SYSV
extern long random();
#endif
extern int errno;
+/*
+ * max macro, with weird case to avoid conflicts
+ */
+#define MaX(a,b) (a) > (b) ? (a) : (b)
+
char * inet_name __P((u_int32 addr));
u_int32 host_addr __P((char *name));
/* u_int is promoted u_char */
@@ -211,7 +221,7 @@ host_addr(name)
if (e) memcpy((char *)&addr, e->h_addr_list[0], e->h_length);
else {
addr = inet_addr(buf);
- if (addr == -1) {
+ if (addr == -1 || (IN_MULTICAST(addr) && dots)) {
addr = 0;
printf("Could not parse %s as host name or address\n", name);
}
@@ -395,10 +405,12 @@ send_recv(dst, type, code, tries, save)
struct ip *ip;
struct igmp *igmp;
struct tr_query *query, *rquery;
- int ipdatalen, iphdrlen, igmpdatalen;
+ struct tr_resp *r;
+ struct sockaddr_in recvaddr;
u_int32 local, group;
+ int ipdatalen, iphdrlen, igmpdatalen;
int datalen;
- int count, recvlen, dummy = 0;
+ int count, recvlen, socklen = sizeof(recvaddr);
int len;
int i;
@@ -482,7 +494,7 @@ send_recv(dst, type, code, tries, save)
gettimeofday(&tr, 0);
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, (struct sockaddr *)0, &dummy);
+ 0, (struct sockaddr *)&recvaddr, &socklen);
if (recvlen <= 0) {
if (recvlen && errno != EINTR) perror("recvfrom");
@@ -519,6 +531,8 @@ send_recv(dst, type, code, tries, save)
switch (igmp->igmp_type) {
case IGMP_DVMRP:
+ if (type != IGMP_DVMRP || code != DVMRP_ASK_NEIGHBORS2)
+ continue;
if (igmp->igmp_code != DVMRP_NEIGHBORS2) continue;
len = igmpdatalen;
/*
@@ -544,6 +558,7 @@ send_recv(dst, type, code, tries, save)
case IGMP_MTRACE: /* For backward compatibility with 3.3 */
case IGMP_MTRACE_RESP:
+ if (type != IGMP_MTRACE) continue;
if (igmpdatalen <= QLEN) continue;
if ((igmpdatalen - QLEN)%RLEN) {
printf("packet with incorrect datalen\n");
@@ -558,6 +573,7 @@ send_recv(dst, type, code, tries, save)
if (rquery->tr_src != qsrc) continue;
if (rquery->tr_dst != qdst) continue;
len = (igmpdatalen - QLEN)/RLEN;
+ r = (struct tr_resp *)(rquery+1) + len - 1;
/*
* Ignore trace queries passing through this node when
@@ -566,7 +582,6 @@ send_recv(dst, type, code, tries, save)
* for backward compatibility with multicast release 3.3).
*/
if (igmp->igmp_type == IGMP_MTRACE) {
- struct tr_resp *r = (struct tr_resp *)(rquery+1) + len - 1;
u_int32 smask;
VAL_TO_MASK(smask, r->tr_smask);
@@ -574,6 +589,13 @@ send_recv(dst, type, code, tries, save)
&& r->tr_rmtaddr != 0 && !(r->tr_rflags & 0x80))
continue;
}
+ /*
+ * Some routers will return error messages without
+ * filling in their addresses. We fill in the address
+ * for them.
+ */
+ if (r->tr_outaddr == 0)
+ r->tr_outaddr = recvaddr.sin_addr.s_addr;
/*
* A match, we'll keep this one.
@@ -625,6 +647,10 @@ passive_mode()
struct ip *ip;
struct igmp *igmp;
struct tr_resp *r;
+ struct sockaddr_in recvaddr;
+ struct tm *now;
+ char timebuf[32];
+ int socklen;
int ipdatalen, iphdrlen, igmpdatalen;
int len, recvlen, dummy = 0;
u_int32 smask;
@@ -634,8 +660,9 @@ passive_mode()
} else k_join(htonl(0xE0000120), INADDR_ANY);
while (1) {
+ socklen = sizeof(recvaddr);
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, (struct sockaddr *)0, &dummy);
+ 0, (struct sockaddr *)&recvaddr, &socklen);
gettimeofday(&tr,0);
if (recvlen <= 0) {
@@ -704,16 +731,41 @@ passive_mode()
(qgrp != 0 && qgrp != igmp->igmp_group.s_addr))
continue;
- printf("Mtrace from %s to %s via group %s (mxhop=%d)\n",
+ now = localtime(&tr.tv_sec);
+ strftime(timebuf, sizeof(timebuf) - 1, "%b %e %k:%M:%S", now);
+ printf("Mtrace %s at %s",
+ len == 0 ? "query" :
+ igmp->igmp_type == IGMP_MTRACE_RESP ? "response" :
+ "in transit",
+ timebuf);
+ if (len == 0)
+ printf(" by %s", inet_fmt(recvaddr.sin_addr.s_addr, s1));
+ if (!IN_MULTICAST(base.qhdr.tr_raddr))
+ printf(", resp to %s", (len == 0 && recvaddr.sin_addr.s_addr == base.qhdr.tr_raddr) ? "same" : inet_fmt(base.qhdr.tr_raddr, s1));
+ else
+ printf(", respttl %d", base.qhdr.tr_rttl);
+ printf(", qid %06x\n", base.qhdr.tr_qid);
+ printf("packet from %s to %s\n",
+ inet_fmt(ip->ip_src.s_addr, s1),
+ inet_fmt(ip->ip_dst.s_addr, s2));
+
+ printf("from %s to %s via group %s (mxhop=%d)\n",
inet_fmt(base.qhdr.tr_dst, s1), inet_fmt(base.qhdr.tr_src, s2),
inet_fmt(igmp->igmp_group.s_addr, s3), igmp->igmp_code);
if (len == 0)
continue;
+ r = base.resps + base.len - 1;
+ /*
+ * Some routers will return error messages without
+ * filling in their addresses. We fill in the address
+ * for them.
+ */
+ if (r->tr_outaddr == 0)
+ r->tr_outaddr = recvaddr.sin_addr.s_addr;
printf(" 0 ");
print_host(base.qhdr.tr_dst);
printf("\n");
print_trace(1, &base);
- r = base.resps + base.len - 1;
VAL_TO_MASK(smask, r->tr_smask);
if ((r->tr_inaddr & smask) == (base.qhdr.tr_src & smask)) {
printf("%3d ", -(base.len+1));
@@ -785,7 +837,20 @@ print_trace(index, buf)
ms = scale(&hop);
printf(" %d%s", hop, ms);
}
- printf(" %s\n", flag_type(r->tr_rflags));
+ printf(" %s", flag_type(r->tr_rflags));
+ if (i > 1 && r->tr_outaddr != (r-1)->tr_rmtaddr) {
+ printf(" !RPF!");
+ print_host((r-1)->tr_rmtaddr);
+ }
+ if (r->tr_smask <= 1) /* Buggy MASK_TO_VAL() returns 1 for default */
+ printf(" [default]");
+ else if (verbose) {
+ u_int32 smask;
+
+ VAL_TO_MASK(smask, r->tr_smask);
+ printf(" [%s]", inet_fmts(buf->qhdr.tr_src & smask, smask, s1));
+ }
+ printf("\n");
memcpy(names[i-1], name, sizeof(names[0]) - 1);
names[i-1][sizeof(names[0])-1] = '\0';
}
@@ -886,27 +951,33 @@ stat_line(r, s, have_next, rst)
int g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
int v_pps, g_pps;
char v_str[8], g_str[8];
- int have = NEITHER;
- int res = *rst;
+ int vhave = NEITHER;
+ int ghave = NEITHER;
+ char whochar;
if (timediff == 0) timediff = 1;
v_pps = v_out / timediff;
g_pps = g_out / timediff;
if (v_out && (s->tr_vifout != 0xFFFFFFFF && s->tr_vifout != 0) ||
- (r->tr_vifout != 0xFFFFFFFF && r->tr_vifout != 0))
- have |= OUTS;
+ (r->tr_vifout != 0xFFFFFFFF && r->tr_vifout != 0)) {
+ vhave |= OUTS;
+ if (!*rst)
+ ghave |= OUTS;
+ }
if (have_next) {
--r, --s, --rst;
if ((s->tr_vifin != 0xFFFFFFFF && s->tr_vifin != 0) ||
- (r->tr_vifin != 0xFFFFFFFF && r->tr_vifin != 0))
- have |= INS;
- if (*rst)
- res = 1;
+ (r->tr_vifin != 0xFFFFFFFF && r->tr_vifin != 0)) {
+ vhave |= INS;
+ if (!*rst)
+ ghave |= INS;
+ }
}
- switch (have) {
+ whochar = have_next ? '^' : ' ';
+ switch (vhave) {
case BOTH:
v_lost = v_out - (ntohl(s->tr_vifin) - ntohl(r->tr_vifin));
if (v_out) v_pct = (v_lost * 100 + (v_out >> 1)) / v_out;
@@ -915,6 +986,42 @@ stat_line(r, s, have_next, rst)
sprintf(v_str, "%3d", v_pct);
else memcpy(v_str, " --", 4);
+ if (tunstats)
+ printf("%6d/%-5d=%s%%", v_lost, v_out, v_str);
+ else
+ printf(" ");
+ printf("%4d pps", v_pps);
+
+ break;
+
+ case INS:
+ v_out = ntohl(s->tr_vifin) - ntohl(r->tr_vifin);
+ v_pps = v_out / timediff;
+ whochar = 'v';
+ /* Fall through */
+
+ case OUTS:
+ if (tunstats)
+ printf(" %c%-5d ", whochar, v_out);
+ else
+ printf(" %c", whochar);
+ printf("%4d pps", v_pps);
+
+ break;
+
+ case NEITHER:
+ if (vhave != NEITHER)
+ if (tunstats)
+ printf(" ");
+ else
+ printf(" ");
+
+ break;
+ }
+
+ whochar = have_next ? '^' : ' ';
+ switch (ghave) {
+ case BOTH:
g_lost = g_out - (ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt));
if (g_out) g_pct = (g_lost * 100 + (g_out >> 1))/ g_out;
else g_pct = 0;
@@ -922,35 +1029,35 @@ stat_line(r, s, have_next, rst)
sprintf(g_str, "%3d", g_pct);
else memcpy(g_str, " --", 4);
- printf("%6d/%-5d=%s%%%4d pps",
- v_lost, v_out, v_str, v_pps);
- if (res)
- printf("\n");
- else
- printf("%6d/%-5d=%s%%%4d pps\n",
- g_lost, g_out, g_str, g_pps);
+ if (!tunstats)
+ printf(" ");
+ printf("%6d/%-5d=%s%%%4d pps\n",
+ g_lost, g_out, g_str, g_pps);
break;
+#if 0
case INS:
- v_out = ntohl(s->tr_vifin) - ntohl(r->tr_vifin);
- v_pps = v_out / timediff;
+ g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
+ g_pps = g_out / timediff;
+ whochar = 'v';
/* Fall through */
+#endif
case OUTS:
- printf(" %-5d %4d pps",
- v_out, v_pps);
- if (res)
- printf("\n");
- else
- printf(" %-5d %4d pps\n",
- g_out, g_pps);
+ if (!tunstats)
+ printf(" ");
+
+ printf(" ?/%-5d %4d pps\n",
+ g_out, g_pps);
break;
+ case INS:
case NEITHER:
printf("\n");
break;
}
+
if (debug > 2) {
printf("\t\t\t\tv_in: %ld ", ntohl(s->tr_vifin));
printf("v_out: %ld ", ntohl(s->tr_vifout));
@@ -962,7 +1069,6 @@ stat_line(r, s, have_next, rst)
printf("v_out: %ld ", ntohl(s->tr_vifout) - ntohl(r->tr_vifout));
printf("pkts: %ld ", ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt));
printf("time: %d\n", timediff);
- printf("\t\t\t\tres: %d\n", res);
}
}
@@ -980,11 +1086,12 @@ fixup_stats(base, prev, new)
struct tr_resp *n = new->resps + rno;
int *r = reset + rno;
int *s = swaps + rno;
+ int *t = bogustime + rno;
int res;
/* Check for byte-swappers */
while (--rno >= 0) {
- --n; --p; --b; --s;
+ --n; --p; --b; --s; --t;
if (*s || abs(ntohl(n->tr_vifout) - ntohl(p->tr_vifout)) > 100000) {
/* This host sends byteswapped reports; swap 'em */
if (!*s) {
@@ -1000,6 +1107,26 @@ fixup_stats(base, prev, new)
n->tr_vifout = byteswap(n->tr_vifout);
n->tr_pktcnt = byteswap(n->tr_pktcnt);
}
+ /*
+ * A missing parenthesis in mrouted 3.5-3.8's prune.c
+ * causes extremely bogus time diff's.
+ * One half of the time calculation was
+ * inside an htonl() and one half wasn't. Therefore, on
+ * a little-endian machine, both halves of the calculation
+ * would get added together in the little end. Thus, the
+ * low-order 2 bytes are either 0000 (no overflow) or
+ * 0100 (overflow from the addition).
+ *
+ * Odds are against these particular bit patterns
+ * happening in both prev and new for actual time values.
+ */
+ if (*t || ((ntohl(n->tr_qarr) & 0xfeff) == 0x0000) &&
+ ((ntohl(p->tr_qarr) & 0xfeff) == 0x0000)) {
+ *t = 1;
+ n->tr_qarr = new->rtime;
+ p->tr_qarr = prev->rtime;
+ b->tr_qarr = base->rtime;
+ }
}
rno = base->len;
@@ -1064,24 +1191,39 @@ print_stats(base, prev, new)
int *r = reset + rno;
u_long resptime = new->rtime;
u_long qarrtime = fixtime(ntohl(n->tr_qarr));
- u_int ttl = n->tr_fttl;
+ u_int ttl = n->tr_fttl + 1;
int first = (base == prev);
VAL_TO_MASK(smask, b->tr_smask);
- printf(" Source Response Dest");
- printf(" Packet Statistics For Only For Traffic\n");
- printf("%-15s %-15s All Multicast Traffic From %s\n",
+ printf(" Source Response Dest ");
+ if (tunstats)
+ printf("Packet Statistics For Only For Traffic\n");
+ else
+ printf("Overall Packet Statistics For Traffic From\n");
+ (void)inet_fmt(qsrc, s1);
+ printf("%-15s %-15s ",
((b->tr_inaddr & smask) == (qsrc & smask)) ? s1 : " * * * ",
- inet_fmt(base->qhdr.tr_raddr, s2), inet_fmt(qsrc, s1));
+ inet_fmt(base->qhdr.tr_raddr, s2));
+ if (tunstats)
+ printf("All Multicast Traffic From %s\n", s1);
+ else
+ printf("Packet %s To %s\n", s1, inet_fmt(qgrp, s2));
rtt = t_diff(resptime, new->qtime);
ms = scale(&rtt);
- printf(" %c __/ rtt%5d%s Lost/Sent = Pct Rate To %s\n",
- first ? 'v' : '|', rtt, ms, inet_fmt(qgrp, s2));
- if (!first) {
+ printf(" %c __/ rtt%5d%s ",
+ (first && !verbose) ? 'v' : '|', rtt, ms);
+ if (tunstats)
+ printf("Lost/Sent = Pct Rate To %s\n",inet_fmt(qgrp, s2));
+ else
+ printf(" Rate Lost/Sent = Pct Rate\n");
+ if (!first || verbose) {
hop = t_diff(resptime, qarrtime);
ms = scale(&hop);
- printf(" v / hop%5d%s", hop, ms);
- printf(" --------------------- --------------------\n");
+ printf(" v / hop%5d%s ", hop, ms);
+ if (tunstats)
+ printf("--------------------- --------------------\n");
+ else
+ printf("------- ---------------------\n");
}
if (debug > 2) {
printf("\t\t\t\tv_in: %ld ", ntohl(n->tr_vifin));
@@ -1097,39 +1239,46 @@ print_stats(base, prev, new)
}
while (TRUE) {
- if ((n->tr_inaddr != b->tr_inaddr) || (n->tr_inaddr != b->tr_inaddr))
+ if ((n->tr_inaddr != b->tr_inaddr) || (n->tr_outaddr != b->tr_outaddr))
return 1; /* Route changed */
- if ((n->tr_inaddr != n->tr_outaddr))
+ if ((n->tr_inaddr != n->tr_outaddr) && n->tr_inaddr)
printf("%-15s\n", inet_fmt(n->tr_inaddr, s1));
- printf("%-15s %-14s %s\n", inet_fmt(n->tr_outaddr, s1), names[rno],
- flag_type(n->tr_rflags));
+ printf("%-15s %-14s %s%s\n", inet_fmt(n->tr_outaddr, s1), names[rno],
+ flag_type(n->tr_rflags), *r ? " [reset counters]" : "");
if (rno-- < 1) break;
- printf(" %c ^ ttl%5d ", first ? 'v' : '|', ttl);
+ printf(" %c ^ ttl%5d ", (first && !verbose) ? 'v' : '|',
+ ttl);
stat_line(p, n, TRUE, r);
- if (!first) {
+ if (!first || verbose) {
resptime = qarrtime;
qarrtime = fixtime(ntohl((n-1)->tr_qarr));
hop = t_diff(resptime, qarrtime);
ms = scale(&hop);
printf(" v | hop%5d%s", hop, ms);
- stat_line(b, n, TRUE, r);
+ if (first)
+ printf("\n");
+ else
+ stat_line(b, n, TRUE, r);
}
--b, --p, --n, --r;
- if (ttl < n->tr_fttl) ttl = n->tr_fttl;
- else ++ttl;
+ ttl = MaX(ttl, n->tr_fttl + base->len - rno);
}
- printf(" %c \\__ ttl%5d ", first ? 'v' : '|', ttl);
+ printf(" %c \\__ ttl%5d ", (first && !verbose) ? 'v' : '|',
+ ttl);
stat_line(p, n, FALSE, r);
- if (!first) {
+ if (!first || verbose) {
hop = t_diff(qarrtime, new->qtime);
ms = scale(&hop);
printf(" v \\ hop%5d%s", hop, ms);
- stat_line(b, n, FALSE, r);
+ if (first)
+ printf("\n");
+ else
+ stat_line(b, n, FALSE, r);
}
printf("%-15s %s\n", inet_fmt(qdst, s1), inet_fmt(lcl_addr, s2));
printf(" Receiver Query Source\n\n");
@@ -1195,6 +1344,15 @@ char *argv[];
case 'M': /* Use multicast for reponse */
multicast = TRUE;
break;
+ case 'U': /* Use unicast for response */
+ unicast = TRUE;
+ break;
+ case 'T': /* Print confusing tunnel stats */
+ tunstats = TRUE;
+ break;
+ case 'W': /* Cisco's "weak" mtrace */
+ weak = TRUE;
+ break;
case 'l': /* Loop updating stats indefinitely */
numstats = 3153600;
break;
@@ -1277,7 +1435,16 @@ char *argv[];
}
if (argc > 0 && (qsrc = host_addr(argv[0]))) { /* Source of path */
- if (IN_MULTICAST(ntohl(qsrc))) goto usage;
+ if (IN_MULTICAST(ntohl(qsrc))) {
+ if (gwy) {
+ /* Should probably rewrite arg parsing at some point, as
+ * this makes "mtrace -g foo 224.1.2.3 224.2.3.4" valid!... */
+ qgrp = qsrc;
+ qsrc = 0;
+ } else {
+ goto usage;
+ }
+ }
argv++, argc--;
if (argc > 0 && (qdst = host_addr(argv[0]))) { /* Dest of path */
argv++, argc--;
@@ -1298,7 +1465,7 @@ char *argv[];
return(0);
}
- if (argc > 0 || qsrc == 0) {
+ if (argc > 0) {
usage: printf("\
Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
[-S statint] [-t ttl] [-r resp_dest] [-i if_addr] source [receiver] [group]\n");
@@ -1312,7 +1479,16 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
defgrp = htonl(0xE0020001); /* MBone Audio (224.2.0.1) */
query_cast = htonl(0xE0000002); /* All routers multicast addr */
resp_cast = htonl(0xE0000120); /* Mtrace response multicast addr */
- if (qgrp == 0) qgrp = defgrp;
+ if (qgrp == 0) {
+ if (!weak)
+ qgrp = defgrp;
+ /* Stats are useless without a group */
+ fprintf(stderr, "mtrace: WARNING: no multicast group specified, so no statistics printed\n");
+ numstats = 0;
+ } else {
+ if (weak)
+ fprintf(stderr, "mtrace: WARNING: group was specified so not performing \"weak\" mtrace\n");
+ }
/*
* Get default local address for multicasts to use in setting defaults.
@@ -1321,7 +1497,7 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
#if (defined(BSD) && (BSD >= 199103))
addr.sin_len = sizeof(addr);
#endif
- addr.sin_addr.s_addr = qgrp;
+ addr.sin_addr.s_addr = qgrp ? qgrp : query_cast;
addr.sin_port = htons(2000); /* Any port above 1024 will do */
if (((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0) ||
@@ -1363,8 +1539,15 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
/*
* Default destination for path to be queried is the local host.
+ * When gateway specified, default destination is that gateway
+ * and default source is local host.
*/
- if (qdst == 0) qdst = lcl_addr ? lcl_addr : addr.sin_addr.s_addr;
+ if (qdst == 0)
+ qdst = gwy ? gwy : (lcl_addr ? lcl_addr : addr.sin_addr.s_addr);
+ if (qsrc == 0 && gwy)
+ qsrc = lcl_addr ? lcl_addr : addr.sin_addr.s_addr;
+ if (qsrc == 0)
+ goto usage;
dst_netmask = get_netmask(udp, qdst);
close(udp);
if (lcl_addr == 0) lcl_addr = addr.sin_addr.s_addr;
@@ -1382,15 +1565,25 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
/*
* Protect against unicast queries to mrouted versions that might crash.
+ * Also use the obsolete "can mtrace" neighbor bit to warn about
+ * older implementations.
*/
if (gwy && !IN_MULTICAST(ntohl(gwy)))
if (send_recv(gwy, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0])) {
- int version = ntohl(incr[0].igmp.igmp_group.s_addr) & 0xFFFF;
- if (version == 0x0303 || version == 0x0503) {
+ int flags = ntohl(incr[0].igmp.igmp_group.s_addr);
+ int version = flags & 0xFFFF;
+ int info = (flags & 0xFF0000) >> 16;
+
+ if (version == 0x0303 || version == 0x0503) {
printf("Don't use -g to address an mrouted 3.%d, it might crash\n",
(version >> 8) & 0xFF);
exit(0);
}
+ if ((info & 0x08) == 0) {
+ printf("mtrace: ");
+ print_host(gwy);
+ printf(" probably doesn't support mtrace, trying anyway...\n");
+ }
}
printf("Mtrace from %s to %s via group %s\n",
@@ -1409,6 +1602,17 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr);
} else k_join(resp_cast, lcl_addr);
+ restart:
+
+ /*
+ * Zero out bug-avoidance counters
+ */
+ memset(reset, 0, sizeof(reset));
+ memset(swaps, 0, sizeof(swaps));
+ memset(bogustime, 0, sizeof(bogustime));
+
+ memset(&base, 0, sizeof(base));
+
/*
* If the destination is on the local net, the last-hop router can
* be found by multicast to the all-routers multicast group.
@@ -1416,12 +1620,14 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
* query since by definition the last-hop router will be a member.
* Set default TTLs for local remote multicasts.
*/
- restart:
-
if (gwy == 0)
if ((qdst & dst_netmask) == (lcl_addr & dst_netmask)) tdst = query_cast;
else tdst = qgrp;
else tdst = gwy;
+ if (tdst == 0 && weak) {
+ fprintf(stderr, "mtrace: -W requires -g if destination is not local.\n");
+ exit(1);
+ }
if (IN_MULTICAST(ntohl(tdst))) {
k_set_loop(1); /* If I am running on a router, I need to hear this */
@@ -1462,7 +1668,7 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
print_trace(1, &base);
r = base.resps + base.len - 1;
if (r->tr_rflags == TR_OLD_ROUTER || r->tr_rflags == TR_NO_SPACE ||
- qno != 0) {
+ (qno != 0 && r->tr_rmtaddr != 0)) {
printf("%3d ", -(base.len+1));
what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ?
"doesn't support mtrace"
@@ -1598,7 +1804,18 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
exit(1);
}
- printf("Round trip time %d ms\n\n", t_diff(base.rtime, base.qtime));
+ printf("Round trip time %d ms; ", t_diff(base.rtime, base.qtime));
+ {
+ struct tr_resp *n = base.resps + base.len - 1;
+ u_int ttl = n->tr_fttl + 1;
+
+ rno = base.len - 1;
+ while (--rno > 0) {
+ --n;
+ ttl = MaX(ttl, n->tr_fttl + base.len - rno);
+ }
+ printf("total ttl of %d required.\n\n",ttl);
+ }
/*
* Use the saved response which was the longest one received,
@@ -1623,7 +1840,11 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
if (recvlen == 0) {
printf("Timed out.\n");
- exit(1);
+ if (numstats) {
+ numstats++;
+ continue;
+ } else
+ exit(1);
}
if (rno != new->len) {
@@ -1649,6 +1870,7 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
printf("Route changed:\n");
print_trace(1, new);
printf("Restarting.\n\n");
+ numstats++;
goto restart;
}
prev = new;
diff --git a/usr.sbin/mrouted/prune.c b/usr.sbin/mrouted/prune.c
index fe3cdd5b4e14..ff4e0b9dcbcb 100644
--- a/usr.sbin/mrouted/prune.c
+++ b/usr.sbin/mrouted/prune.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: prune.c,v 3.8 1995/11/29 22:36:34 fenner Rel $
+ * $Id: prune.c,v 3.8.1.4 1996/09/06 18:26:29 fenner Exp $
*/
@@ -1234,17 +1234,11 @@ accept_prune(src, dst, p, datalen)
return;
}
if ((pt = find_prune_entry(src, g->gt_pruntbl)) != NULL) {
- /*
- * If it's about to expire, then it's only still around because
- * of timer granularity, so don't warn about it.
- */
- if (pt->pt_timer > 10) {
- log(LOG_WARNING, 0, "%s %d from %s for (%s %s)/%d %s %d %s %x",
- "duplicate prune received on vif",
- vifi, inet_fmt(src, s1), inet_fmt(prun_src, s2),
- inet_fmt(prun_grp, s3), prun_tmr,
- "old timer:", pt->pt_timer, "cur gm:", g->gt_grpmems);
- }
+ log(LOG_DEBUG, 0, "%s %d from %s for (%s %s)/%d %s %d %s %x",
+ "duplicate prune received on vif",
+ vifi, inet_fmt(src, s1), inet_fmt(prun_src, s2),
+ inet_fmt(prun_grp, s3), prun_tmr,
+ "old timer:", pt->pt_timer, "cur gm:", g->gt_grpmems);
pt->pt_timer = prun_tmr;
} else {
/* allocate space for the prune structure */
@@ -1947,6 +1941,7 @@ dump_cache(fp2)
register struct stable *st;
register struct ptable *pt;
register vifi_t i;
+ char c;
register time_t thyme = time(0);
fprintf(fp2,
@@ -1988,15 +1983,19 @@ dump_cache(fp2)
VIFM_ISSET(i, gt->gt_scope) ? 'b' : 'p');
}
fprintf(fp2, "\n");
+ if (gt->gt_pruntbl) {
+ fprintf(fp2, "<");
+ c = '(';
+ for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) {
+ fprintf(fp2, "%c%s:%d/%d", c, inet_fmt(pt->pt_router, s1),
+ pt->pt_vifi, pt->pt_timer);
+ c = ',';
+ }
+ fprintf(fp2, ")\n");
+ }
for (st = gt->gt_srctbl; st; st = st->st_next) {
fprintf(fp2, ">%s\n", inet_fmt(st->st_origin, s1));
}
-#ifdef DEBUG_PRUNES
- for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) {
- fprintf(fp2, "<r:%s v:%d t:%d\n", inet_fmt(pt->pt_router, s1),
- pt->pt_vifi, pt->pt_timer);
- }
-#endif
}
}
@@ -2169,8 +2168,8 @@ accept_mtrace(src, dst, group, data, no, datalen)
bzero(resp, sizeof(struct tr_resp));
datalen += RLEN;
- resp->tr_qarr = htonl((tp.tv_sec + JAN_1970) << 16) +
- ((tp.tv_usec >> 4) & 0xffff);
+ resp->tr_qarr = htonl(((tp.tv_sec + JAN_1970) << 16) +
+ ((tp.tv_usec << 10) / 15625));
resp->tr_rproto = PROTO_DVMRP;
if (errcode != TR_NO_ERR) {
diff --git a/usr.sbin/mrouted/route.c b/usr.sbin/mrouted/route.c
index c2b6b9e8b932..c12d7fd25f90 100644
--- a/usr.sbin/mrouted/route.c
+++ b/usr.sbin/mrouted/route.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: route.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: route.c,v 3.8.1.1 1996/08/09 22:46:20 fenner Exp $
*/
@@ -862,6 +862,8 @@ report(which_routes, vifi, dst)
u_int32 mask = 0;
u_int32 src;
u_int32 nflags;
+ int metric;
+ int admetric = uvifs[vifi].uv_admetric;
src = uvifs[vifi].uv_lcl_addr;
@@ -918,9 +920,12 @@ report(which_routes, vifi, dst)
for (i = 0; i < width; ++i)
*p++ = ((char *)&(r->rt_origin))[i];
- *p++ = (r->rt_parent == vifi && r->rt_metric != UNREACHABLE) ?
- (char)(r->rt_metric + UNREACHABLE) : /* "poisoned reverse" */
- (char)(r->rt_metric);
+ metric = r->rt_metric + admetric;
+ if (metric > UNREACHABLE)
+ metric = UNREACHABLE;
+ *p++ = (r->rt_parent == vifi && metric != UNREACHABLE) ?
+ (char)(metric + UNREACHABLE) : /* "poisoned reverse" */
+ (char)(metric);
datalen += width + 1;
}
@@ -1001,6 +1006,8 @@ report_chunk(start_rt, vifi, dst)
u_int32 mask = 0;
u_int32 src;
u_int32 nflags;
+ int admetric = uvifs[vifi].uv_admetric;
+ int metric;
src = uvifs[vifi].uv_lcl_addr;
p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
@@ -1042,9 +1049,12 @@ report_chunk(start_rt, vifi, dst)
for (i = 0; i < width; ++i)
*p++ = ((char *)&(r->rt_origin))[i];
- *p++ = (r->rt_parent == vifi && r->rt_metric != UNREACHABLE) ?
- (char)(r->rt_metric + UNREACHABLE) : /* "poisoned reverse" */
- (char)(r->rt_metric);
+ metric = r->rt_metric + admetric;
+ if (metric > UNREACHABLE)
+ metric = UNREACHABLE;
+ *p++ = (r->rt_parent == vifi && metric != UNREACHABLE) ?
+ (char)(metric + UNREACHABLE) : /* "poisoned reverse" */
+ (char)(metric);
++nrt;
datalen += width + 1;
}
diff --git a/usr.sbin/mrouted/rsrr.c b/usr.sbin/mrouted/rsrr.c
index ea9628f55aea..b447f1a0b8fe 100644
--- a/usr.sbin/mrouted/rsrr.c
+++ b/usr.sbin/mrouted/rsrr.c
@@ -112,7 +112,11 @@ rsrr_read(f, rfd)
fd_set *rfd;
{
register int rsrr_recvlen;
+#ifdef SYSV
+ sigset_t block, oblock;
+#else
register int omask;
+#endif
bzero((char *) &client_addr, sizeof(client_addr));
rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
@@ -122,10 +126,21 @@ rsrr_read(f, rfd)
log(LOG_ERR, errno, "RSRR recvfrom");
return;
}
+#ifdef SYSV
+ (void)sigemptyset(&block);
+ (void)sigaddset(&block, SIGALRM);
+ if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
+ log(LOG_ERR, errno, "sigprocmask");
+#else
/* Use of omask taken from main() */
omask = sigblock(sigmask(SIGALRM));
+#endif
rsrr_accept(rsrr_recvlen);
+#ifdef SYSV
+ (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
+#else
(void)sigsetmask(omask);
+#endif
}
/* Accept a message from the reservation protocol and take
diff --git a/usr.sbin/mrouted/vif.c b/usr.sbin/mrouted/vif.c
index 3716292d1cab..8211ab0b49a2 100644
--- a/usr.sbin/mrouted/vif.c
+++ b/usr.sbin/mrouted/vif.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: vif.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: vif.c,v 3.8.1.2 1996/08/09 22:42:13 fenner Exp $
*/
@@ -163,8 +163,18 @@ check_vif_state()
register vifi_t vifi;
register struct uvif *v;
struct ifreq ifr;
+ static int checking_vifs = 0;
+
+ /*
+ * If we get an error while checking, (e.g. two interfaces go down
+ * at once, and we decide to send a prune out one of the failed ones)
+ * then don't go into an infinite loop!
+ */
+ if (checking_vifs)
+ return;
vifs_down = FALSE;
+ checking_vifs = 1;
for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
if (v->uv_flags & VIFF_DISABLED) continue;
@@ -176,25 +186,26 @@ check_vif_state()
if (v->uv_flags & VIFF_DOWN) {
if (ifr.ifr_flags & IFF_UP) {
- v->uv_flags &= ~VIFF_DOWN;
- start_vif(vifi);
- log(LOG_INFO, 0,
+ log(LOG_NOTICE, 0,
"%s has come up; vif #%u now in service",
v->uv_name, vifi);
+ v->uv_flags &= ~VIFF_DOWN;
+ start_vif(vifi);
}
else vifs_down = TRUE;
}
else {
if (!(ifr.ifr_flags & IFF_UP)) {
- stop_vif(vifi);
- v->uv_flags |= VIFF_DOWN;
- log(LOG_INFO, 0,
+ log(LOG_NOTICE, 0,
"%s has gone down; vif #%u taken out of service",
v->uv_name, vifi);
+ stop_vif(vifi);
+ v->uv_flags |= VIFF_DOWN;
vifs_down = TRUE;
}
}
}
+ checking_vifs = 0;
}
/*
@@ -704,33 +715,7 @@ accept_neighbor_request(src, dst)
u_char *p, *ncount;
struct listaddr *la;
int datalen;
- u_int32 temp_addr, us, them = src;
-
- /* Determine which of our addresses to use as the source of our response
- * to this query.
- */
- if (IN_MULTICAST(ntohl(dst))) { /* query sent to a multicast group */
- int udp; /* find best interface to reply on */
- struct sockaddr_in addr;
- int addrlen = sizeof(addr);
-
- addr.sin_family = AF_INET;
-#if (defined(BSD) && (BSD >= 199103))
- addr.sin_len = sizeof addr;
-#endif
- addr.sin_addr.s_addr = dst;
- addr.sin_port = htons(2000); /* any port over 1024 will do... */
- if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0
- || connect(udp, (struct sockaddr *) &addr, sizeof(addr)) < 0
- || getsockname(udp, (struct sockaddr *) &addr, &addrlen) < 0) {
- log(LOG_WARNING, errno, "Determining local address");
- close(udp);
- return;
- }
- close(udp);
- us = addr.sin_addr.s_addr;
- } else /* query sent to us alone */
- us = dst;
+ u_int32 temp_addr, them = src;
#define PUT_ADDR(a) temp_addr = ntohl(a); \
*p++ = temp_addr >> 24; \
@@ -751,7 +736,7 @@ accept_neighbor_request(src, dst)
/* Make sure that there's room for this neighbor... */
if (datalen + (ncount == 0 ? 4 + 3 + 4 : 4) > MAX_DVMRP_DATA_LEN) {
- send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS,
+ send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS,
htonl(MROUTED_LEVEL), datalen);
p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
datalen = 0;
@@ -775,8 +760,8 @@ accept_neighbor_request(src, dst)
}
if (datalen != 0)
- send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS, htonl(MROUTED_LEVEL),
- datalen);
+ send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS,
+ htonl(MROUTED_LEVEL), datalen);
}
/*
@@ -791,33 +776,7 @@ accept_neighbor_request2(src, dst)
u_char *p, *ncount;
struct listaddr *la;
int datalen;
- u_int32 us, them = src;
-
- /* Determine which of our addresses to use as the source of our response
- * to this query.
- */
- if (IN_MULTICAST(ntohl(dst))) { /* query sent to a multicast group */
- int udp; /* find best interface to reply on */
- struct sockaddr_in addr;
- int addrlen = sizeof(addr);
-
- addr.sin_family = AF_INET;
-#if (defined(BSD) && (BSD >= 199103))
- addr.sin_len = sizeof addr;
-#endif
- addr.sin_addr.s_addr = dst;
- addr.sin_port = htons(2000); /* any port over 1024 will do... */
- if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0
- || connect(udp, (struct sockaddr *) &addr, sizeof(addr)) < 0
- || getsockname(udp, (struct sockaddr *) &addr, &addrlen) < 0) {
- log(LOG_WARNING, errno, "Determining local address");
- close(udp);
- return;
- }
- close(udp);
- us = addr.sin_addr.s_addr;
- } else /* query sent to us alone */
- us = dst;
+ u_int32 them = src;
p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
datalen = 0;
@@ -847,7 +806,7 @@ accept_neighbor_request2(src, dst)
if (rflags & DVMRP_NF_TUNNEL)
rflags |= DVMRP_NF_DOWN;
if (datalen > MAX_DVMRP_DATA_LEN - 12) {
- send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
+ send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
htonl(MROUTED_LEVEL), datalen);
p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
datalen = 0;
@@ -865,7 +824,7 @@ accept_neighbor_request2(src, dst)
for ( ; la; la = la->al_next) {
/* Make sure that there's room for this neighbor... */
if (datalen + (ncount == 0 ? 4+4+4 : 4) > MAX_DVMRP_DATA_LEN) {
- send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
+ send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
htonl(MROUTED_LEVEL), datalen);
p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
datalen = 0;
@@ -890,8 +849,8 @@ accept_neighbor_request2(src, dst)
}
}
if (datalen != 0)
- send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, htonl(MROUTED_LEVEL),
- datalen);
+ send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
+ htonl(MROUTED_LEVEL), datalen);
}
void
diff --git a/usr.sbin/mrouted/vif.h b/usr.sbin/mrouted/vif.h
index 94f5f7a9ee7b..65c1da05758d 100644
--- a/usr.sbin/mrouted/vif.h
+++ b/usr.sbin/mrouted/vif.h
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: vif.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
+ * $Id: vif.h,v 3.8.1.1 1996/08/09 22:46:19 fenner Exp $
*/
/*
@@ -20,6 +20,7 @@
struct uvif {
u_short uv_flags; /* VIFF_ flags defined below */
u_char uv_metric; /* cost of this vif */
+ u_char uv_admetric; /* advertised cost of this vif */
u_int uv_rate_limit; /* rate limit on this vif */
u_char uv_threshold; /* min ttl required to forward on vif */
u_int32 uv_lcl_addr; /* local address of this vif */