mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2025-01-01 00:18:15 +01:00
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 .
This commit is contained in:
parent
f29c770b37
commit
f014b7e69b
@ -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;
|
||||
@ -293,6 +294,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);
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 $
|
||||
*/
|
||||
|
||||
|
||||
@ -25,6 +25,23 @@ u_int32 allrtrs_group; /* All-Routers " in net order */
|
||||
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.
|
||||
*/
|
||||
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
|
||||
g_pps = g_out / timediff;
|
||||
whochar = 'v';
|
||||
/* Fall through */
|
||||
#endif
|
||||
|
||||
case OUTS:
|
||||
if (!tunstats)
|
||||
printf(" ");
|
||||
|
||||
printf(" ?/%-5d %4d pps\n",
|
||||
g_out, g_pps);
|
||||
break;
|
||||
|
||||
case INS:
|
||||
v_out = ntohl(s->tr_vifin) - ntohl(r->tr_vifin);
|
||||
v_pps = v_out / timediff;
|
||||
/* Fall through */
|
||||
|
||||
case OUTS:
|
||||
printf(" %-5d %4d pps",
|
||||
v_out, v_pps);
|
||||
if (res)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" %-5d %4d pps\n",
|
||||
g_out, g_pps);
|
||||
break;
|
||||
|
||||
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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user