aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1996-01-06 21:04:38 +0000
committerPeter Wemm <peter@FreeBSD.org>1996-01-06 21:04:38 +0000
commit73950bd7a6d01b29d656a59c00de1ff876c44de1 (patch)
tree096b18bdaa7ddb050ea46e9135793f638e841ef6
parent29a6d69cc3ace06013586242876d971734f09820 (diff)
downloadsrc-73950bd7a6d01b29d656a59c00de1ff876c44de1.tar.gz
src-73950bd7a6d01b29d656a59c00de1ff876c44de1.zip
This is a 'for reference' import of mrouted release 3.8.
I'm using these to try to resync our tree with the vendor branch..
Notes
Notes: svn path=/cvs2svn/branches/XEROX/; revision=13280
-rw-r--r--usr.sbin/mrouted/callout.c28
-rw-r--r--usr.sbin/mrouted/cfparse.y103
-rw-r--r--usr.sbin/mrouted/config.c2
-rw-r--r--usr.sbin/mrouted/defs.h41
-rw-r--r--usr.sbin/mrouted/dvmrp.h19
-rw-r--r--usr.sbin/mrouted/igmp.c32
-rw-r--r--usr.sbin/mrouted/inet.c31
-rw-r--r--usr.sbin/mrouted/kern.c26
-rw-r--r--usr.sbin/mrouted/main.c239
-rw-r--r--usr.sbin/mrouted/mapper.c29
-rw-r--r--usr.sbin/mrouted/mrinfo.c121
-rw-r--r--usr.sbin/mrouted/mrouted.811
-rw-r--r--usr.sbin/mrouted/mrouted.conf8
-rw-r--r--usr.sbin/mrouted/mtrace.828
-rw-r--r--usr.sbin/mrouted/mtrace.c600
-rw-r--r--usr.sbin/mrouted/pathnames.h2
-rw-r--r--usr.sbin/mrouted/prune.c362
-rw-r--r--usr.sbin/mrouted/prune.h2
-rw-r--r--usr.sbin/mrouted/route.c34
-rw-r--r--usr.sbin/mrouted/route.h2
-rw-r--r--usr.sbin/mrouted/rsrr.c3
-rw-r--r--usr.sbin/mrouted/vif.c337
-rw-r--r--usr.sbin/mrouted/vif.h6
23 files changed, 1449 insertions, 617 deletions
diff --git a/usr.sbin/mrouted/callout.c b/usr.sbin/mrouted/callout.c
index 29e44eccfbdc..358c7ae86a21 100644
--- a/usr.sbin/mrouted/callout.c
+++ b/usr.sbin/mrouted/callout.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: callout.c,v 3.6 1995/06/25 18:47:29 fenner Exp $
+ * $Id: callout.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
#include "defs.h"
@@ -16,7 +16,7 @@
static int id = 0;
static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
-static int in_callout= 0;
+static int in_callout = 0;
struct timeout_q {
struct timeout_q *next; /* next event */
@@ -53,12 +53,15 @@ age_callout_queue()
in_callout = 1;
ptr = Q;
- while (ptr){
- if (!ptr->time ) {
+ while (ptr) {
+ if (!ptr->time) {
/* timeout has happened */
+ Q = Q->next;
+
+ in_callout = 0;
if (ptr->func)
ptr->func(ptr->data);
- Q = Q->next;
+ in_callout = 1;
free(ptr);
ptr = Q;
@@ -206,3 +209,18 @@ print_Q()
log(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time);
}
#endif /* IGMP_DEBUG */
+int
+secs_remaining( timer_id)
+ int timer_id;
+{
+ struct timeout_q *ptr;
+ int left=0;
+
+ for (ptr = Q; ptr && ptr->id != timer_id; ptr = ptr->next)
+ left += ptr->time;
+
+ if (!ptr) /* not found */
+ return 0;
+
+ return left + ptr->time;
+}
diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y
index c08938d4a47a..ab5b89f30ea8 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.6 1995/06/25 18:49:46 fenner Exp $
+ * $Id: cfparse.y,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
#include <stdio.h>
#ifdef __STDC__
@@ -13,6 +13,7 @@
#include <varargs.h>
#endif
#include "defs.h"
+#include <netdb.h>
/*
* Local function declarations
@@ -69,14 +70,16 @@ int numbounds = 0; /* Number of named boundaries */
%token CACHE_LIFETIME PRUNING
%token PHYINT TUNNEL NAME
-%token DISABLE METRIC THRESHOLD RATE_LIMIT SRCRT BOUNDARY NETMASK ALTNET
+%token DISABLE IGMPV1 SRCRT
+%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET
+%token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION
%token <num> BOOLEAN
%token <num> NUMBER
%token <ptr> STRING
%token <addrmask> ADDRMASK
%token <addr> ADDR
-%type <addr> interface
+%type <addr> interface addrname
%type <addrmask> bound boundary addrmask
%start conf
@@ -109,10 +112,9 @@ stmt : error
fatal("%s is not a configured interface",
inet_fmt($2,s1));
- /*log(LOG_INFO, 0, "phyint: %x\n", v);*/
}
ifmods
- | TUNNEL interface ADDR {
+ | TUNNEL interface addrname {
struct ifreq *ifr;
struct ifreq ffr;
@@ -172,7 +174,6 @@ stmt : error
v->uv_flags |= VIFF_DOWN;
vifs_down = TRUE;
}
- /*log(LOG_INFO, 0, "tunnel: %x\n", v);*/
}
tunnelmods
{
@@ -195,10 +196,30 @@ stmt : error
strcpy(boundlist[numbounds].name, $2);
boundlist[numbounds++].bound = $3;
}
+ | SYSNAM STRING {
+#ifdef SNMP
+ set_sysName($2);
+#endif /* SNMP */
+ }
+ | SYSCONTACT STRING {
+#ifdef SNMP
+ set_sysContact($2);
+#endif /* SNMP */
+ }
+ | SYSVERSION STRING {
+#ifdef SNMP
+ set_sysVersion($2);
+#endif /* SNMP */
+ }
+ | SYSLOCATION STRING {
+#ifdef SNMP
+ set_sysLocation($2);
+#endif /* SNMP */
+ }
;
tunnelmods : /* empty */
- | tunnelmods /*{ log(LOG_INFO, 0, "tunnelmod: %x", v); }*/ tunnelmod
+ | tunnelmods tunnelmod
;
tunnelmod : mod
@@ -206,12 +227,13 @@ tunnelmod : mod
;
ifmods : /* empty */
- | ifmods /*{ log(LOG_INFO, 0, "ifmod: %x", v); }*/ ifmod
+ | ifmods ifmod
;
ifmod : mod
| DISABLE { v->uv_flags |= VIFF_DISABLED; }
- | NETMASK ADDR {
+ | IGMPV1 { v->uv_flags |= VIFF_IGMPV1; }
+ | NETMASK addrname {
u_int32 subnet, mask;
mask = $2;
@@ -222,6 +244,11 @@ ifmod : mod
v->uv_subnetmask = mask;
v->uv_subnetbcast = subnet | ~mask;
}
+ | NETMASK {
+
+ warn("Expected address after netmask keyword, ignored");
+
+ }
| ALTNET addrmask {
struct phaddr *ph;
@@ -242,6 +269,11 @@ ifmod : mod
v->uv_addrs = ph;
}
+ | ALTNET {
+
+ warn("Expected address after altnet keyword, ignored");
+
+ }
;
mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
@@ -250,7 +282,7 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
}
| THRESHOLD {
- warn("Expected number after threshold keyword");
+ warn("Expected number after threshold keyword, ignored");
}
| METRIC NUMBER { if ($2 < 1 || $2 > UNREACHABLE)
@@ -259,7 +291,7 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
}
| METRIC {
- warn("Expected number after metric keyword");
+ warn("Expected number after metric keyword, ignored");
}
| RATE_LIMIT NUMBER { if ($2 > MAX_RATE_LIMIT)
@@ -268,7 +300,7 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
}
| RATE_LIMIT {
- warn("Expected number after rate_limit keyword");
+ warn("Expected number after rate_limit keyword, ignored");
}
| BOUNDARY bound {
@@ -289,7 +321,7 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
}
| BOUNDARY {
- warn("Expected boundary spec after boundary keyword");
+ warn("Expected boundary spec after boundary keyword, ignored");
}
;
@@ -302,6 +334,20 @@ interface : ADDR { $$ = $1; }
}
;
+addrname : ADDR { $$ = $1; }
+ | STRING { struct hostent *hp;
+
+ if ((hp = gethostbyname($1)) == NULL)
+ fatal("No such host %s", $1);
+
+ if (hp->h_addr_list[1])
+ fatal("Hostname %s does not %s",
+ $1, "map to a unique address");
+
+ bcopy(hp->h_addr_list[0], &$$,
+ hp->h_length);
+ }
+
bound : boundary { $$ = $1; }
| STRING { int i;
@@ -413,6 +459,15 @@ next_word()
continue;
}
q = p;
+#ifdef SNMP
+ if (*p == '"') {
+ p++;
+ while (*p && *p != '"' && *p != '\n')
+ p++; /* find next whitespace */
+ if (*p == '"')
+ p++;
+ } else
+#endif
while (*p && *p != ' ' && *p != '\t' && *p != '\n')
p++; /* find next whitespace */
*p++ = '\0'; /* null-terminate string */
@@ -459,10 +514,12 @@ yylex()
return BOUNDARY;
if (!strcmp(q,"netmask"))
return NETMASK;
- if (!strcmp(q,"name"))
- return NAME;
+ if (!strcmp(q,"igmpv1"))
+ return IGMPV1;
if (!strcmp(q,"altnet"))
return ALTNET;
+ if (!strcmp(q,"name"))
+ return NAME;
if (!strcmp(q,"on") || !strcmp(q,"yes")) {
yylval.num = 1;
return BOOLEAN;
@@ -494,6 +551,22 @@ yylex()
yylval.num = n;
return NUMBER;
}
+#ifdef SNMP
+ if (!strcmp(q,"sysName"))
+ return SYSNAM;
+ if (!strcmp(q,"sysContact"))
+ return SYSCONTACT;
+ if (!strcmp(q,"sysVersion"))
+ return SYSVERSION;
+ if (!strcmp(q,"sysLocation"))
+ return SYSLOCATION;
+ if (*q=='"') {
+ if (q[ strlen(q)-1 ]=='"')
+ q[ strlen(q)-1 ]='\0'; /* trash trailing quote */
+ yylval.ptr = q+1;
+ return STRING;
+ }
+#endif
yylval.ptr = q;
return STRING;
}
diff --git a/usr.sbin/mrouted/config.c b/usr.sbin/mrouted/config.c
index 56fdccb991e2..1147412b904e 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.6 1995/06/25 18:50:37 fenner Exp $
+ * $Id: config.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
diff --git a/usr.sbin/mrouted/defs.h b/usr.sbin/mrouted/defs.h
index 5829314ce500..63aef773e77c 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.6.1.1 1995/06/26 00:18:18 fenner Exp $
+ * $Id: defs.h,v 3.8 1995/11/29 22:36:34 fenner Rel $
*/
@@ -23,6 +23,9 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
+#ifdef SYSV
+#include <sys/sockio.h>
+#endif
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -46,7 +49,7 @@ typedef u_int u_int32;
#endif
typedef void (*cfunc_t) __P((void *));
-typedef void (*ihfunc_t) __P((fd_set *));
+typedef void (*ihfunc_t) __P((int, fd_set *));
#include "dvmrp.h"
#include "vif.h"
@@ -68,13 +71,17 @@ typedef void (*ihfunc_t) __P((fd_set *));
#define TIMER_INTERVAL ROUTE_MAX_REPORT_DELAY
+#define VENDOR_CODE 1 /* Get a new vendor code if you make significant
+ * changes to mrouted. */
+
#define PROTOCOL_VERSION 3 /* increment when packet format/content changes */
-#define MROUTED_VERSION 6 /* increment on local changes or bug fixes, */
+#define MROUTED_VERSION 8 /* increment on local changes or bug fixes, */
/* reset to 0 whever PROTOCOL_VERSION increments */
-#define MROUTED_LEVEL ( (MROUTED_VERSION << 8) | PROTOCOL_VERSION | \
- ((NF_PRUNE | NF_GENID | NF_MTRACE) << 16))
+#define MROUTED_LEVEL ((MROUTED_VERSION << 8) | PROTOCOL_VERSION | \
+ ((NF_PRUNE | NF_GENID | NF_MTRACE) << 16) | \
+ (VENDOR_CODE << 24))
/* for IGMP 'group' field of DVMRP messages */
#define LEAF_FLAGS (( vifs_with_neighbors == 1 ) ? 0x010000 : 0)
@@ -98,10 +105,17 @@ typedef void (*ihfunc_t) __P((fd_set *));
#define BIT_TST(X,n) ((X) & 1 << (n))
#endif /* RSRR */
+#ifdef SYSV
+#define bcopy(a, b, c) memcpy(b, a, c)
+#define bzero(s, n) memset((s), 0, (n))
+#define setlinebuf(s) setvbuf(s, NULL, _IOLBF, 0)
+#define signal(s,f) sigset(s,f)
+#endif
+
/*
* External declarations for global variables and functions.
*/
-#define RECV_BUF_SIZE MAX_IP_PACKET_LEN
+#define RECV_BUF_SIZE 8192
extern char *recv_buf;
extern char *send_buf;
extern int igmp_socket;
@@ -139,6 +153,17 @@ extern int sys_nerr;
extern char * sys_errlist[];
#endif
+#ifdef OLD_KERNEL
+#define MRT_INIT DVMRP_INIT
+#define MRT_DONE DVMRP_DONE
+#define MRT_ADD_VIF DVMRP_ADD_VIF
+#define MRT_DEL_VIF DVMRP_DEL_VIF
+#define MRT_ADD_MFC DVMRP_ADD_MFC
+#define MRT_DEL_MFC DVMRP_DEL_MFC
+
+#define IGMP_PIM 0x14
+#endif
+
/* main.c */
extern void log __P((int, int, char *, ...));
extern int register_input_handler __P((int fd, ihfunc_t func));
@@ -161,7 +186,7 @@ extern void timer_clearTimer __P((int timer_id));
extern void init_routes __P((void));
extern void start_route_updates __P((void));
extern void update_route __P((u_int32 origin, u_int32 mask,
- int metric, u_int32 src,
+ u_int metric, u_int32 src,
vifi_t vifi));
extern void age_routes __P((void));
extern void expire_all_routes __P((void));
@@ -285,7 +310,7 @@ extern int find_src_grp __P((u_int32 src, u_int32 mask,
/* rsrr.c */
extern void rsrr_init __P((void));
-extern void rsrr_read __P((fd_set *rfd));
+extern void rsrr_read __P((int f, fd_set *rfd));
extern void rsrr_clean __P((void));
extern void rsrr_cache_send __P((struct gtable *gt, int notify));
extern void rsrr_cache_clean __P((struct gtable *gt));
diff --git a/usr.sbin/mrouted/dvmrp.h b/usr.sbin/mrouted/dvmrp.h
index 5553dc34910e..e471800588dc 100644
--- a/usr.sbin/mrouted/dvmrp.h
+++ b/usr.sbin/mrouted/dvmrp.h
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: dvmrp.h,v 3.6 1995/06/25 18:52:10 fenner Exp $
+ * $Id: dvmrp.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
/*
@@ -96,6 +96,8 @@
#define DVMRP_PRUNE 7 /* prune message */
#define DVMRP_GRAFT 8 /* graft message */
#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */
+#define DVMRP_INFO_REQUEST 10 /* information request */
+#define DVMRP_INFO_REPLY 11 /* information reply */
/*
* 'flags' byte values in DVMRP_NEIGHBORS2 reply.
@@ -109,6 +111,12 @@
#define DVMRP_NF_LEAF 0x80 /* Neighbor reports that it is a leaf */
/*
+ * Request/reply types for info queries/replies
+ */
+#define DVMRP_INFO_VERSION 1 /* version string */
+#define DVMRP_INFO_NEIGHBORS 2 /* neighbors2 data */
+
+/*
* Limit on length of route data
*/
#define MAX_IP_PACKET_LEN 576
@@ -122,8 +130,14 @@
*/
/* address for multicast DVMRP msgs */
#define INADDR_DVMRP_GROUP (u_int32)0xe0000004 /* 224.0.0.4 */
+/*
+ * The IGMPv2 <netinet/in.h> defines INADDR_ALLRTRS_GROUP, but earlier
+ * ones don't, so we define it conditionally here.
+ */
+#ifndef INADDR_ALLRTRS_GROUP
/* address for multicast mtrace msg */
#define INADDR_ALLRTRS_GROUP (u_int32)0xe0000002 /* 224.0.0.2 */
+#endif
#define ROUTE_MAX_REPORT_DELAY 5 /* max delay for reporting changes */
/* (This is the timer interrupt */
@@ -144,8 +158,7 @@
#define GROUP_EXPIRE_TIME 270 /* time to consider group gone */
#define LEAVE_EXPIRE_TIME 3 /* " " after receiving a leave */
/* Note: LEAVE_EXPIRE_TIME should ideally be shorter, but the resolution of
- * the timer in mrouted doesn't allow us to follow the spec and make it any
- * shorter. */
+ * the timer in mrouted doesn't allow us to make it any shorter. */
#define UNREACHABLE 32 /* "infinity" metric, must be <= 64 */
#define DEFAULT_METRIC 1 /* default subnet/tunnel metric */
diff --git a/usr.sbin/mrouted/igmp.c b/usr.sbin/mrouted/igmp.c
index 00eeff56500b..3c27e6d38d26 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 3.6 1995/06/25 18:52:55 fenner Exp $
+ * $Id: igmp.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
@@ -94,6 +94,8 @@ packet_kind(type, code)
case DVMRP_PRUNE: return "prune message ";
case DVMRP_GRAFT: return "graft message ";
case DVMRP_GRAFT_ACK: return "graft message ack ";
+ case DVMRP_INFO_REQUEST: return "info request ";
+ case DVMRP_INFO_REPLY: return "info reply ";
default: return "unknown DVMRP msg ";
}
case IGMP_PIM:
@@ -154,8 +156,8 @@ accept_igmp(recvlen)
ipdatalen = ip->ip_len;
if (iphdrlen + ipdatalen != recvlen) {
log(LOG_WARNING, 0,
- "received packet shorter (%u bytes) than hdr+data length (%u+%u)",
- recvlen, iphdrlen, ipdatalen);
+ "received packet from %s shorter (%u bytes) than hdr+data length (%u+%u)",
+ inet_fmt(src, s1), recvlen, iphdrlen, ipdatalen);
return;
}
@@ -232,6 +234,15 @@ accept_igmp(recvlen)
accept_g_ack(src, dst, (char *)(igmp+1), igmpdatalen);
return;
+ case DVMRP_INFO_REQUEST:
+ accept_info_request(src, dst, (char *)(igmp+1),
+ igmpdatalen);
+ return;
+
+ case DVMRP_INFO_REPLY:
+ accept_info_reply(src, dst, (char *)(igmp+1), igmpdatalen);
+ return;
+
default:
log(LOG_INFO, 0,
"ignoring unknown DVMRP message code %u from %s to %s",
@@ -296,9 +307,10 @@ send_igmp(src, dst, type, code, group, datalen)
u_int32 group;
int datalen;
{
- static struct sockaddr_in sdst;
+ struct sockaddr_in sdst;
struct ip *ip;
struct igmp *igmp;
+ int setloop;
ip = (struct ip *)send_buf;
ip->ip_src.s_addr = src;
@@ -313,8 +325,13 @@ send_igmp(src, dst, type, code, group, datalen)
igmp->igmp_cksum = inet_cksum((u_short *)igmp,
IGMP_MINLEN + datalen);
- if (IN_MULTICAST(ntohl(dst))) k_set_if(src);
- if (dst == allhosts_group) k_set_loop(TRUE);
+ if (IN_MULTICAST(ntohl(dst))) {
+ k_set_if(src);
+ if (type != IGMP_DVMRP) {
+ setloop = 1;
+ k_set_loop(TRUE);
+ }
+ }
bzero(&sdst, sizeof(sdst));
sdst.sin_family = AF_INET;
@@ -332,7 +349,8 @@ send_igmp(src, dst, type, code, group, datalen)
inet_fmt(dst, s1), inet_fmt(src, s2));
}
- if (dst == allhosts_group) k_set_loop(FALSE);
+ if (setloop)
+ 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));
diff --git a/usr.sbin/mrouted/inet.c b/usr.sbin/mrouted/inet.c
index e8d5ab6f23f8..b60e3854da35 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.6 1995/06/25 18:54:45 fenner Exp $
+ * $Id: inet.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
@@ -41,6 +41,22 @@ inet_valid_host(naddr)
(addr & 0xff000000) == 0));
}
+/*
+ * Verify that a given netmask is plausible;
+ * make sure that it is a series of 1's followed by
+ * a series of 0's with no discontiguous 1's.
+ */
+int
+inet_valid_mask(mask)
+ u_int32 mask;
+{
+ if (~(((mask & -mask) - 1) | mask) != 0) {
+ /* Mask is not contiguous */
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
/*
* Verify that a given subnet number and mask pair are credible.
@@ -62,21 +78,26 @@ inet_valid_subnet(nsubnet, nmask)
if ((subnet & mask) != subnet) return (FALSE);
- if (subnet == 0 && mask == 0)
- return (TRUE);
+ if (subnet == 0)
+ return (mask == 0);
if (IN_CLASSA(subnet)) {
if (mask < 0xff000000 ||
- (subnet & 0xff000000) == 0x7f000000) return (FALSE);
+ (subnet & 0xff000000) == 0x7f000000 ||
+ (subnet & 0xff000000) == 0x00000000) return (FALSE);
}
else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) {
/* Above Class C address space */
return (FALSE);
}
- else if (subnet & ~mask) {
+ if (subnet & ~mask) {
/* Host bits are set in the subnet */
return (FALSE);
}
+ if (!inet_valid_mask(mask)) {
+ /* Netmask is not contiguous */
+ return (FALSE);
+ }
return (TRUE);
}
diff --git a/usr.sbin/mrouted/kern.c b/usr.sbin/mrouted/kern.c
index a4030c831bb2..2a64e5c13916 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.6 1995/06/25 18:57:38 fenner Exp $
+ * $Id: kern.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
@@ -162,8 +162,11 @@ void k_add_rg(origin, g)
struct gtable *g;
{
struct mfcctl mc;
- int i;
+ vifi_t i;
+#ifdef DEBUG_MFC
+ md_log(MD_ADD, origin, g->gt_mcastgrp);
+#endif
/* copy table values so that setsockopt can process it */
mc.mfcc_origin.s_addr = origin;
#ifdef OLD_KERNEL
@@ -176,8 +179,12 @@ void k_add_rg(origin, g)
/* write to kernel space */
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC,
- (char *)&mc, sizeof(mc)) < 0)
+ (char *)&mc, sizeof(mc)) < 0) {
+#ifdef DEBUG_MFC
+ md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
+#endif
log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC");
+ }
}
@@ -191,6 +198,9 @@ int k_del_rg(origin, g)
struct mfcctl mc;
int retval;
+#ifdef DEBUG_MFC
+ md_log(MD_DEL, origin, g->gt_mcastgrp);
+#endif
/* copy table values so that setsockopt can process it */
mc.mfcc_origin.s_addr = origin;
#ifdef OLD_KERNEL
@@ -200,8 +210,12 @@ int k_del_rg(origin, g)
/* write to kernel space */
if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC,
- (char *)&mc, sizeof(mc))) < 0)
+ (char *)&mc, sizeof(mc))) < 0) {
+#ifdef DEBUG_MFC
+ md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
+#endif
log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC");
+ }
return retval;
}
@@ -211,6 +225,9 @@ int k_del_rg(origin, g)
*/
int k_get_version()
{
+#ifdef OLD_KERNEL
+ return -1;
+#else
int vers;
int len = sizeof(vers);
@@ -220,4 +237,5 @@ int k_get_version()
"getsockopt MRT_VERSION: perhaps your kernel is too old");
return vers;
+#endif
}
diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c
index f66ce7193f2f..b5ef723bcb73 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 3.6 1995/06/25 18:58:06 fenner Exp $
+ * $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $
*/
/*
@@ -32,7 +32,13 @@
#include "snmp.h"
#endif
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $";
+#endif
+
extern char *configfilename;
+char versionstring[100];
static char pidfilename[] = _PATH_MROUTED_PID;
static char dumpfilename[] = _PATH_MROUTED_DUMP;
@@ -45,7 +51,11 @@ int max_prune_lifetime = DEFAULT_CACHE_LIFETIME * 2;
int debug = 0;
u_char pruning = 1; /* Enable pruning by default */
+#ifdef SNMP
+#define NHANDLERS 34
+#else
#define NHANDLERS 2
+#endif
static struct ihandler {
int fd; /* File descriptor */
@@ -64,6 +74,7 @@ static void cdump __P((int));
static void restart __P((int));
static void timer __P((void));
static void cleanup __P((void));
+static void resetlogging __P((void *));
/* To shut up gcc -Wstrict-prototypes */
int main __P((int argc, char **argv));
@@ -97,22 +108,12 @@ main(argc, argv)
fd_set rfds, readers;
int nfds, n, i;
#ifdef SNMP
- char *myname;
- fd_set wfds;
-
-
- if (myname = strrchr(argv[0], '/'))
- myname++;
- if (myname == NULL || *myname == 0)
- myname = argv[0];
- isodetailor (myname, 0);
+ struct timeval timeout, *tvp = &timeout;
+ struct timeval sched, *svp = &sched, now, *nvp = &now;
+ int index, block;
#endif
-#ifdef SYSV
- setvbuf(stderr, NULL, _IOLBF, 0);
-#else
setlinebuf(stderr);
-#endif
if (geteuid() != 0) {
fprintf(stderr, "must be root\n");
@@ -135,6 +136,14 @@ main(argc, argv)
goto usage;
} else if (strcmp(*argv, "-p") == 0) {
pruning = 0;
+#ifdef SNMP
+ } else if (strcmp(*argv, "-P") == 0) {
+ if (argc > 1 && isdigit(*(argv + 1)[0])) {
+ argv++, argc--;
+ dest_port = atoi(*argv);
+ } else
+ dest_port = DEFAULT_PORT;
+#endif
} else
goto usage;
argv++, argc--;
@@ -159,6 +168,9 @@ usage: fprintf(stderr,
(void)open("/", 0);
(void)dup2(0, 1);
(void)dup2(0, 2);
+#ifdef SYSV
+ (void)setpgrp();
+#else
#ifdef TIOCNOTTY
t = open("/dev/tty", 2);
if (t >= 0) {
@@ -169,6 +181,7 @@ usage: fprintf(stderr,
if (setsid() < 0)
perror("setsid");
#endif
+#endif
}
else
fprintf(stderr, "debug level %u\n", debug);
@@ -179,9 +192,11 @@ usage: fprintf(stderr,
#else
(void)openlog("mrouted", LOG_PID);
#endif
- log(LOG_NOTICE, 0, "mrouted version %d.%d",
+ sprintf(versionstring, "mrouted version %d.%d",
PROTOCOL_VERSION, MROUTED_VERSION);
+ log(LOG_NOTICE, 0, "%s", versionstring);
+
#ifdef SYSV
srand48(time(NULL));
#else
@@ -209,12 +224,9 @@ usage: fprintf(stderr,
}
callout_init();
-
-#ifdef SNMP
- snmp_init();
-#endif
-
init_igmp();
+ init_routes();
+ init_ktable();
k_init_dvmrp(); /* enable DVMRP routing in kernel */
#ifndef OLD_KERNEL
@@ -229,15 +241,29 @@ usage: fprintf(stderr,
PROTOCOL_VERSION, MROUTED_VERSION);
#endif
- init_routes();
- init_ktable();
+#ifdef SNMP
+ if (i = snmp_init())
+ return i;
+
+ gettimeofday(nvp, 0);
+ if (nvp->tv_usec < 500000L){
+ svp->tv_usec = nvp->tv_usec + 500000L;
+ svp->tv_sec = nvp->tv_sec;
+ } else {
+ svp->tv_usec = nvp->tv_usec - 500000L;
+ svp->tv_sec = nvp->tv_sec + 1;
+ }
+#endif /* SNMP */
+
init_vifs();
+
#ifdef RSRR
rsrr_init();
#endif /* RSRR */
#if defined(__STDC__) || defined(__GNUC__)
- /* Allow cleanup if unexpected exit. Apparently some architectures
+ /*
+ * Allow cleanup if unexpected exit. Apparently some architectures
* have a kernel bug where closing the socket doesn't do an
* ip_mrouter_done(), so we attempt to do it on exit.
*/
@@ -253,8 +279,6 @@ usage: fprintf(stderr,
(void) fclose(fp);
}
- if (debug >= 2) dump(0);
-
(void)signal(SIGALRM, fasttimer);
(void)signal(SIGHUP, restart);
@@ -274,6 +298,17 @@ usage: fprintf(stderr,
nfds = ihandlers[i].fd + 1;
}
+ /*
+ * Install the vifs in the kernel as late as possible in the
+ * initialization sequence.
+ */
+ init_installvifs();
+
+ if (debug >= 2) dump(0);
+
+ /* Start up the log rate-limiter */
+ resetlogging(NULL);
+
(void)alarm(1); /* schedule first timer interrupt */
/*
@@ -281,23 +316,38 @@ usage: fprintf(stderr,
*/
dummy = 0;
for(;;) {
+#ifdef SYSV
+ sigset_t block, oblock;
+#endif
bcopy((char *)&readers, (char *)&rfds, sizeof(rfds));
#ifdef SNMP
- FD_ZERO(&wfds);
-
- if (smux_fd != NOTOK) {
- if (rock_and_roll)
- FD_SET(smux_fd, &rfds);
- else
- FD_SET(smux_fd, &wfds);
- if (smux_fd >= nfds)
- nfds = smux_fd + 1;
- }
-
- if ((n = xselect(nfds, &rfds, &wfds, NULLFD, NOTOK))==NOTOK) {
+ gettimeofday(nvp, 0);
+ if (nvp->tv_sec > svp->tv_sec
+ || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
+ alarmTimer(nvp);
+ eventTimer(nvp);
+ if (nvp->tv_usec < 500000L){
+ svp->tv_usec = nvp->tv_usec + 500000L;
+ svp->tv_sec = nvp->tv_sec;
+ } else {
+ svp->tv_usec = nvp->tv_usec - 500000L;
+ svp->tv_sec = nvp->tv_sec + 1;
+ }
+ }
+
+ tvp = &timeout;
+ tvp->tv_sec = 0;
+ tvp->tv_usec = 500000L;
+
+ block = 0;
+ snmp_select_info(&nfds, &rfds, tvp, &block);
+ if (block == 1)
+ tvp = NULL; /* block without timeout */
+ if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0)
#else
- if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0) {
+ if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0)
#endif
+ {
if (errno != EINTR) /* SIGALRM is expected */
log(LOG_WARNING, errno, "select failed");
continue;
@@ -310,25 +360,31 @@ usage: fprintf(stderr,
if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
continue;
}
+#ifdef SYSV
+ (void)sigemptyset(&block);
+ (void)sigaddset(&block, SIGALRM);
+ if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
+ log(LOG_ERR, errno, "sigprocmask");
+#else
omask = sigblock(sigmask(SIGALRM));
+#endif
accept_igmp(recvlen);
+#ifdef SYSV
+ (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
+#else
(void)sigsetmask(omask);
+#endif
}
for (i = 0; i < nhandlers; i++) {
if (FD_ISSET(ihandlers[i].fd, &rfds)) {
- (*ihandlers[i].func)(&rfds);
+ (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
}
}
#ifdef SNMP
- if (smux_fd != NOTOK) {
- if (rock_and_roll) {
- if (FD_ISSET(smux_fd, &rfds))
- doit_smux();
- } else if (FD_ISSET(smux_fd, &wfds))
- start_smux();
- }
+ snmp_read(&rfds);
+ snmp_timeout(); /* poll */
#endif
}
}
@@ -444,13 +500,7 @@ timer()
}
#ifdef SNMP
- if (smux_fd == NOTOK && !dont_bother_anymore
- && virtual_time % SNMPD_RETRY_INTERVAL == 0) {
- /*
- * Time to check for snmpd running.
- */
- try_smux_init();
- }
+ sync_timer();
#endif
/*
@@ -467,8 +517,7 @@ static void
done(i)
int i;
{
- log(LOG_NOTICE, 0, "mrouted version %d.%d exiting",
- PROTOCOL_VERSION, MROUTED_VERSION);
+ log(LOG_NOTICE, 0, "%s exiting", versionstring);
cleanup();
_exit(1);
}
@@ -545,14 +594,23 @@ restart(i)
int i;
{
register int omask;
+#ifdef SYSV
+ sigset_t block, oblock;
+#endif
- log(LOG_NOTICE, 0, "mrouted version %d.%d restart",
- PROTOCOL_VERSION, MROUTED_VERSION);
+ log(LOG_NOTICE, 0, "%s restart", versionstring);
/*
* reset all the entries
*/
+#ifdef SYSV
+ (void)sigemptyset(&block);
+ (void)sigaddset(&block, SIGALRM);
+ if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
+ log(LOG_ERR, errno, "sigprocmask");
+#else
omask = sigblock(sigmask(SIGALRM));
+#endif
free_all_prunes();
free_all_routes();
stop_all_vifs();
@@ -567,14 +625,41 @@ restart(i)
pruning = 1;
init_igmp();
- k_init_dvmrp(); /* enable DVMRP routing in kernel */
init_routes();
init_ktable();
init_vifs();
+ k_init_dvmrp(); /* enable DVMRP routing in kernel */
+ init_installvifs();
+#ifdef SYSV
+ (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
+#else
(void)sigsetmask(omask);
+#endif
}
+#define LOG_MAX_MSGS 20 /* if > 20/minute then shut up for a while */
+#define LOG_SHUT_UP 600 /* shut up for 10 minutes */
+static int log_nmsgs = 0;
+
+static void
+resetlogging(arg)
+ void *arg;
+{
+ int nxttime = 60;
+ void *narg = NULL;
+
+ if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) {
+ nxttime = LOG_SHUT_UP;
+ narg = (void *)&log_nmsgs; /* just need some valid void * */
+ syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes",
+ LOG_SHUT_UP / 60);
+ } else {
+ log_nmsgs = 0;
+ }
+
+ timer_setTimer(nxttime, resetlogging, narg);
+}
/*
* Log errors and other messages to the system log daemon and to stderr,
@@ -633,12 +718,40 @@ log(severity, syserr, format, va_alist)
}
if (severity <= LOG_NOTICE) {
- if (syserr != 0) {
- errno = syserr;
- syslog(severity, "%s: %m", msg);
- } else
- syslog(severity, "%s", msg);
+ if (log_nmsgs++ < LOG_MAX_MSGS) {
+ if (syserr != 0) {
+ errno = syserr;
+ syslog(severity, "%s: %m", msg);
+ } else
+ syslog(severity, "%s", msg);
+ }
if (severity <= LOG_ERR) exit(-1);
}
}
+
+#ifdef DEBUG_MFC
+void
+md_log(what, origin, mcastgrp)
+ int what;
+ u_int32 origin, mcastgrp;
+{
+ static FILE *f = NULL;
+ struct timeval tv;
+ u_int32 buf[4];
+
+ if (!f) {
+ if ((f = fopen("/tmp/mrouted.clog", "w")) == NULL) {
+ log(LOG_ERR, errno, "open /tmp/mrouted.clog");
+ }
+ }
+
+ gettimeofday(&tv, NULL);
+ buf[0] = tv.tv_sec;
+ buf[1] = what;
+ buf[2] = origin;
+ buf[3] = mcastgrp;
+
+ fwrite(buf, sizeof(u_int32), 4, f);
+}
+#endif
diff --git a/usr.sbin/mrouted/mapper.c b/usr.sbin/mrouted/mapper.c
index 8c1c5fd7e6ff..1eacd04bb61d 100644
--- a/usr.sbin/mrouted/mapper.c
+++ b/usr.sbin/mrouted/mapper.c
@@ -1,7 +1,7 @@
/* Mapper for connections between MRouteD multicast routers.
* Written by Pavel Curtis <Pavel@PARC.Xerox.Com>
*
- * $Id: mapper.c,v 3.6 1995/06/25 18:59:02 fenner Exp $
+ * $Id: mapper.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
/*
@@ -302,7 +302,7 @@ void accept_neighbors(src, dst, p, datalen, level)
/* if node is running a recent mrouted, ask for additional info */
if (level != 0) {
node->version = level;
- node->tries = 0;
+ node->tries = 1;
ask2(src);
return;
}
@@ -374,7 +374,7 @@ void accept_neighbors(src, dst, p, datalen, level)
for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next)
if (nb_i->addr == nb_n->addr) {
if (nb_i->metric != nb_n->metric
- || nb_i->threshold != nb_i->threshold)
+ || nb_i->threshold != nb_n->threshold)
log(LOG_WARNING, 0,
"inconsistent %s for neighbor %s of %s",
"metric/threshold",
@@ -451,6 +451,8 @@ void accept_neighbors2(src, dst, p, datalen, level)
int datalen;
{
Node *node = find_node(src, &routers);
+ u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */
+ /* well, only possibly_broken_cisco, but that's too long to type. */
if (node->tries == 0) /* Never heard of 'em; must have hit them at */
node->tries = 1; /* least once, though...*/
@@ -478,6 +480,11 @@ void accept_neighbors2(src, dst, p, datalen, level)
ncount = *p++;
datalen -= 4 + 4;
+ if (broken_cisco && ncount == 0) /* dumb Ciscos */
+ ncount = 1;
+ if (broken_cisco && ncount > 15) /* dumb Ciscos */
+ ncount = ncount & 0xf;
+
/* Fix up any alias information */
ifc_node = find_node(ifc_addr, &routers);
if (ifc_node->tries == 0) { /* new node */
@@ -837,11 +844,7 @@ int main(argc, argv)
{
int flood = FALSE, graph = FALSE;
-#ifdef SYSV
- setvbuf(stderr, NULL, _IOLBF, 0);
-#else
setlinebuf(stderr);
-#endif
if (geteuid() != 0) {
fprintf(stderr, "must be root\n");
@@ -1017,3 +1020,15 @@ void accept_membership_query(src, dst, group, tmo)
int tmo;
{
}
+void accept_info_request(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+}
+void accept_info_reply(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+}
diff --git a/usr.sbin/mrouted/mrinfo.c b/usr.sbin/mrouted/mrinfo.c
index f4ccc86eb6d8..7335aba95cf9 100644
--- a/usr.sbin/mrouted/mrinfo.c
+++ b/usr.sbin/mrouted/mrinfo.c
@@ -61,7 +61,7 @@
#ifndef lint
static char rcsid[] =
- "@(#) $Id: mrinfo.c,v 3.6 1995/06/25 19:05:34 fenner Exp $";
+ "@(#) $Id: mrinfo.c,v 3.8 1995/11/29 22:36:34 fenner Rel $";
/* original rcsid:
"@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)";
*/
@@ -237,8 +237,13 @@ accept_neighbors2(src, dst, p, datalen, level)
u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */
/* well, only possibly_broken_cisco, but that's too long to type. */
- printf("%s (%s) [version %d.%d]:\n", inet_fmt(src, s1), inet_name(src),
+ printf("%s (%s) [version %d.%d", inet_fmt(src, s1), inet_name(src),
level & 0xff, (level >> 8) & 0xff);
+ if ((level >> 16) & NF_LEAF) { printf (",leaf"); }
+ if ((level >> 16) & NF_PRUNE) { printf (",prune"); }
+ if ((level >> 16) & NF_GENID) { printf (",genid"); }
+ if ((level >> 16) & NF_MTRACE) { printf (",mtrace"); }
+ printf ("]:\n");
while (p < ep) {
register u_char metric;
@@ -307,23 +312,6 @@ get_number(var, deflt, pargv, pargc)
}
}
-u_int32
-host_addr(name)
- char *name;
-{
- struct hostent *e;
- u_int32 addr;
-
- addr = inet_addr(name);
- if ((int)addr == -1) {
- e = gethostbyname(name);
- if (e == NULL || e->h_length != sizeof(addr))
- return (0);
- memcpy(&addr, e->h_addr_list[0], e->h_length);
- }
- return(addr);
-}
-
void
usage()
{
@@ -337,9 +325,13 @@ main(argc, argv)
int argc;
char *argv[];
{
- int tries = 0;
- int trynew = 1;
+ int tries;
+ int trynew;
struct timeval et;
+ struct hostent *hp;
+ struct hostent bogus;
+ char *host;
+ int curaddr;
setlinebuf(stderr);
@@ -373,11 +365,21 @@ main(argc, argv)
if (argc > 1)
usage();
if (argc == 1)
- target_addr = host_addr(argv[0]);
+ host = argv[0];
else
- target_addr = host_addr("127.0.0.1");
-
- if (target_addr == 0) {
+ host = "127.0.0.1";
+
+ if ((target_addr = inet_addr(host)) != -1) {
+ hp = &bogus;
+ hp->h_length = sizeof(target_addr);
+ hp->h_addr_list = (char **)malloc(2 * sizeof(char *));
+ hp->h_addr_list[0] = malloc(hp->h_length);
+ memcpy(hp->h_addr_list[0], &target_addr, hp->h_length);
+ hp->h_addr_list[1] = 0;
+ } else
+ hp = gethostbyname(host);
+
+ if (hp == NULL) {
fprintf(stderr, "mrinfo: %s: no such host\n", argv[0]);
exit(1);
}
@@ -386,7 +388,10 @@ main(argc, argv)
init_igmp();
- { /* Find a good local address for us. */
+ /* Check all addresses; mrouters often have unreachable interfaces */
+ for (curaddr = 0; hp->h_addr_list[curaddr] != NULL; curaddr++) {
+ memcpy(&target_addr, hp->h_addr_list[curaddr], hp->h_length);
+ { /* Find a good local address for us. */
int udp;
struct sockaddr_in addr;
int addrlen = sizeof(addr);
@@ -406,20 +411,22 @@ main(argc, argv)
}
close(udp);
our_addr = addr.sin_addr.s_addr;
- }
-
- /*
- * New strategy: send 'ask2' for two timeouts, then fall back
- * to 'ask', since it's not very likely that we are going to
- * find someone who only responds to 'ask' these days
- */
- ask2(target_addr);
-
- gettimeofday(&et, 0);
- et.tv_sec += timeout;
-
- /* Main receive loop */
- for (;;) {
+ }
+
+ tries = 0;
+ trynew = 1;
+ /*
+ * New strategy: send 'ask2' for two timeouts, then fall back
+ * to 'ask', since it's not very likely that we are going to
+ * find someone who only responds to 'ask' these days
+ */
+ ask2(target_addr);
+
+ gettimeofday(&et, 0);
+ et.tv_sec += timeout;
+
+ /* Main receive loop */
+ for (;;) {
fd_set fds;
struct timeval tv, now;
int count, recvlen, dummy = 0;
@@ -451,7 +458,7 @@ main(argc, argv)
} else if (count == 0) {
log(LOG_DEBUG, 0, "Timed out receiving neighbor lists");
if (++tries > retries)
- exit(1);
+ break;
/* If we've tried ASK_NEIGHBORS2 twice with
* no response, fall back to ASK_NEIGHBORS
*/
@@ -461,6 +468,8 @@ main(argc, argv)
ask(target_addr);
else
ask2(target_addr);
+ gettimeofday(&et, 0);
+ et.tv_sec += timeout;
continue;
}
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
@@ -485,19 +494,19 @@ main(argc, argv)
iphdrlen = ip->ip_hl << 2;
ipdatalen = ip->ip_len;
if (iphdrlen + ipdatalen != recvlen) {
- log(LOG_WARNING, 0,
- "packet shorter (%u bytes) than hdr+data length (%u+%u)",
- recvlen, iphdrlen, ipdatalen);
- continue;
+ log(LOG_WARNING, 0,
+ "packet shorter (%u bytes) than hdr+data length (%u+%u)",
+ recvlen, iphdrlen, ipdatalen);
+ continue;
}
igmp = (struct igmp *) (recv_buf + iphdrlen);
group = igmp->igmp_group.s_addr;
igmpdatalen = ipdatalen - IGMP_MINLEN;
if (igmpdatalen < 0) {
- log(LOG_WARNING, 0,
- "IP data field too short (%u bytes) for IGMP, from %s",
- ipdatalen, inet_fmt(src, s1));
- continue;
+ log(LOG_WARNING, 0,
+ "IP data field too short (%u bytes) for IGMP, from %s",
+ ipdatalen, inet_fmt(src, s1));
+ continue;
}
if (igmp->igmp_type != IGMP_DVMRP)
continue;
@@ -538,7 +547,9 @@ main(argc, argv)
igmpdatalen, ntohl(group));
exit(0);
}
+ }
}
+ exit(1);
}
/* dummies */
@@ -608,3 +619,15 @@ void accept_membership_query(src, dst, group, tmo)
int tmo;
{
}
+void accept_info_request(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+}
+void accept_info_reply(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+}
diff --git a/usr.sbin/mrouted/mrouted.8 b/usr.sbin/mrouted/mrouted.8
index 7dae5e38b2c6..6c4c7bd98616 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.6 1995/06/25 19:10:58 fenner Exp $
+'\"$Id: mrouted.8,v 3.8 1995/11/29 22:37:21 fenner Rel $
.TH MROUTED 8
.UC 5
.SH NAME
@@ -140,7 +140,7 @@ options may be specified as many times as necessary.
The phyint command can be used to disable multicast routing on the physical
interface identified by local IP address <local-addr>, or to associate a
non-default metric or threshold with the specified physical interface.
-The local IP address <local-addr> may be alternatively replaced by the
+The local IP address <local-addr> may be replaced by the
interface name (e.g le0).
If a phyint is attached to multiple IP subnets, describe each additional subnet
with the altnet keyword.
@@ -148,7 +148,12 @@ Phyint commands must precede tunnel commands.
.PP
The tunnel command can be used to establish a tunnel link between local
IP address <local-addr> and remote IP address <remote-addr>, and to associate
-a non-default metric or threshold with that tunnel. The tunnel must be set
+a non-default metric or threshold with that tunnel.
+The local IP address <local-addr> may be replaced by the
+interface name (e.g. le0). The remote IP address <remote-addr> may
+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,
diff --git a/usr.sbin/mrouted/mrouted.conf b/usr.sbin/mrouted/mrouted.conf
index 4962d68e71f8..eb3bad3f4995 100644
--- a/usr.sbin/mrouted/mrouted.conf
+++ b/usr.sbin/mrouted/mrouted.conf
@@ -1,4 +1,4 @@
-# $Id: mrouted.conf,v 3.6 1995/06/25 19:11:55 fenner Exp $
+# $Id: mrouted.conf,v 3.8 1995/11/29 22:40:47 fenner Rel $
#
# This is the configuration file for "mrouted", an IP multicast router.
# mrouted looks for it in "/etc/mrouted.conf".
@@ -35,3 +35,9 @@ tunnel 128.4.0.77 128.4.0.8 metric 1 threshold 64 rate_limit 500 # <-- REPLACE
#
# You might want to specify a boundary on your tunnel to the outside world,
# as above.
+#
+# NOTE: ONLY uncomment the following if you are running mrouted.snmp!
+#sysName "mymrouter"
+#sysContact "Me <me@me.com> +x.yyy.zzz-zzzz"
+#sysVersion "MyOS 4.1.3 and mrouted"
+#sysLocation "The MBONE"
diff --git a/usr.sbin/mrouted/mtrace.8 b/usr.sbin/mrouted/mtrace.8
index c4ac21866af7..5c8e1fe13465 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.6 1995/06/25 19:14:07 fenner Exp $
+.\" $Id: mtrace.8,v 3.8 1995/11/29 22:37:21 fenner Rel $
.\"
.TH MTRACE 8 "May 8, 1995"
.UC 6
@@ -63,9 +63,14 @@ mtrace \- print multicast path from a source to a receiver
] [
.B \-s
] [
+.B \-S
+.I stat_int
+] [
.B \-t
.I ttl
] [
+.B \-v
+] [
.B \-w
.I waittime
]
@@ -105,6 +110,9 @@ detailed below. The two parameters can be distinguished because the
is a unicast address and the
.I group
is a multicast address.
+.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.
.SH OPTIONS
.TP 8 8
.BI \-g\ gwy
@@ -118,7 +126,7 @@ to the
.RS 8
.TP 12 12
.I CAUTION!!
-Version 3.3 of
+Versions 3.3 and 3.5 of
.B mrouted
will crash if a trace query is received via a
unicast packet and
@@ -129,7 +137,7 @@ address. Therefore, do not use the
.B \-g
option unless the target
.B mrouted
-has been verified to be newer than 3.3.
+has been verified to be 3.4 or newer than 3.5.
.RE
.TP 8 8
.BI \-i\ addr
@@ -142,7 +150,9 @@ and the response destination.
.TP 8 8
.B \-l
Loop indefinitely printing packet rate and loss statistics for the
-multicast path every 10 seconds.
+multicast path every 10 seconds (see
+.B \-S
+.IR stat_int ).
.TP 8 8
.B \-M
Always send the response using multicast rather than attempting
@@ -169,7 +179,7 @@ The default is 3.
.TP 8 8
.B \-p
Listen passively for multicast responses from traces initiated by
-others (not implemented yet).
+others. This works best when run on a multicast router.
.TP 8 8
.BI \-r\ host
Send the trace response to
@@ -183,6 +193,11 @@ for this purpose (224.0.1.32).
Print a short form output including only the multicast path and not
the packet rate and loss statistics.
.TP 8 8
+.BI \-S\ n
+Change the interval between statistics gathering traces to
+.I n
+seconds (default 10 seconds).
+.TP 8 8
.BI \-t\ ttl
Set the
.I ttl
@@ -190,6 +205,9 @@ Set the
responses. The default is 64, except for local queries to the "all
routers" multicast group which use ttl 1.
.TP 8 8
+.B \-v
+Verbose mode; show hop times on the initial trace and statistics display.
+.TP 8 8
.BI \-w\ n
Set the time to wait for a trace response to
.I n
diff --git a/usr.sbin/mrouted/mtrace.c b/usr.sbin/mrouted/mtrace.c
index 321b2693092d..389084ae2416 100644
--- a/usr.sbin/mrouted/mtrace.c
+++ b/usr.sbin/mrouted/mtrace.c
@@ -46,16 +46,19 @@
* In particular, parts of the prototype version of this program may
* have been derived from mrouted programs sources covered by the
* license in the accompanying file named "LICENSE".
- *
- * $Id: mtrace.c,v 3.6 1995/06/25 19:17:14 fenner Exp $
*/
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Id: mtrace.c,v 3.8 1995/11/29 22:36:34 fenner Rel $";
+#endif
+
#include <netdb.h>
#include <sys/time.h>
-#include <sys/filio.h>
#include <memory.h>
#include <string.h>
#include <ctype.h>
+#include <sys/ioctl.h>
#include "defs.h"
#include <arpa/inet.h>
#ifdef __STDC__
@@ -63,6 +66,9 @@
#else
#include <varargs.h>
#endif
+#ifdef SUNOS5
+#include <sys/systeminfo.h>
+#endif
#define DEFAULT_TIMEOUT 3 /* How long to wait before retrying requests */
#define DEFAULT_RETRIES 3 /* How many times to try */
@@ -91,6 +97,8 @@ struct resp_buf {
#define ndata u.d
char names[MAXHOPS][40];
+int reset[MAXHOPS]; /* To get around 3.4 bug, ... */
+int swaps[MAXHOPS]; /* To get around 3.6 bug, ... */
int timeout = DEFAULT_TIMEOUT;
int nqueries = DEFAULT_RETRIES;
@@ -98,6 +106,8 @@ int numeric = FALSE;
int debug = 0;
int passive = FALSE;
int multicast = FALSE;
+int statint = 10;
+int verbose = 0;
u_int32 defgrp; /* Default group if not specified */
u_int32 query_cast; /* All routers multicast addr */
@@ -140,12 +150,14 @@ u_long fixtime __P((u_long time));
int send_recv __P((u_int32 dst, int type, int code,
int tries, struct resp_buf *save));
char * print_host __P((u_int32 addr));
+char * print_host2 __P((u_int32 addr1, u_int32 addr2));
void print_trace __P((int index, struct resp_buf *buf));
-int what_kind __P((struct resp_buf *buf));
+int what_kind __P((struct resp_buf *buf, char *why));
char * scale __P((int *hop));
void stat_line __P((struct tr_resp *r, struct tr_resp *s,
- int have_next));
+ int have_next, int *res));
void fixup_stats __P((struct resp_buf *base,
+ struct resp_buf *prev,
struct resp_buf *new));
int print_stats __P((struct resp_buf *base,
struct resp_buf *prev,
@@ -313,9 +325,9 @@ int
get_ttl(buf)
struct resp_buf *buf;
{
- register rno;
- register struct tr_resp *b;
- register ttl;
+ int rno;
+ struct tr_resp *b;
+ u_int ttl;
if (buf && (rno = buf->len) > 0) {
b = buf->resps + rno - 1;
@@ -361,6 +373,17 @@ fixtime(time)
return (time);
}
+/*
+ * Swap bytes for poor little-endian machines that don't byte-swap
+ */
+u_long
+byteswap(v)
+ u_long v;
+{
+ return ((v << 24) | ((v & 0xff00) << 8) |
+ ((v >> 8) & 0xff00) | (v >> 24));
+}
+
int
send_recv(dst, type, code, tries, save)
u_int32 dst;
@@ -504,11 +527,11 @@ send_recv(dst, type, code, tries, save)
* addresses in the response.
*/
if (ip->ip_src.s_addr != dst) {
- register u_int32 *p = (u_int32 *)(igmp + 1);
- register u_int32 *ep = p + (len >> 2);
+ u_int32 *p = (u_int32 *)(igmp + 1);
+ u_int32 *ep = p + (len >> 2);
while (p < ep) {
- register u_int32 laddr = *p++;
- register int n = ntohl(*p++) & 0xFF;
+ u_int32 laddr = *p++;
+ int n = ntohl(*p++) & 0xFF;
if (laddr == dst) {
ep = p + 1; /* ensure p < ep after loop */
break;
@@ -586,19 +609,155 @@ send_recv(dst, type, code, tries, save)
return (0);
}
+/*
+ * Most of this code is duplicated elsewhere. I'm not sure if
+ * the duplication is absolutely required or not.
+ *
+ * Ideally, this would keep track of ongoing statistics
+ * collection and print out statistics. (& keep track
+ * of h-b-h traces and only print the longest) For now,
+ * it just snoops on what traces it can.
+ */
+void
+passive_mode()
+{
+ struct timeval tr;
+ struct ip *ip;
+ struct igmp *igmp;
+ struct tr_resp *r;
+ int ipdatalen, iphdrlen, igmpdatalen;
+ int len, recvlen, dummy = 0;
+ u_int32 smask;
+
+ init_igmp();
+
+ if (raddr) {
+ if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, INADDR_ANY);
+ } else k_join(htonl(0xE0000120), INADDR_ANY);
+
+ while (1) {
+ recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
+ 0, (struct sockaddr *)0, &dummy);
+ gettimeofday(&tr,0);
+
+ if (recvlen <= 0) {
+ if (recvlen && errno != EINTR) perror("recvfrom");
+ continue;
+ }
+
+ if (recvlen < sizeof(struct ip)) {
+ fprintf(stderr,
+ "packet too short (%u bytes) for IP header", recvlen);
+ continue;
+ }
+ ip = (struct ip *) recv_buf;
+ if (ip->ip_p == 0) /* ignore cache creation requests */
+ continue;
+
+ iphdrlen = ip->ip_hl << 2;
+ ipdatalen = ip->ip_len;
+ if (iphdrlen + ipdatalen != recvlen) {
+ fprintf(stderr,
+ "packet shorter (%u bytes) than hdr+data len (%u+%u)\n",
+ recvlen, iphdrlen, ipdatalen);
+ continue;
+ }
+
+ igmp = (struct igmp *) (recv_buf + iphdrlen);
+ igmpdatalen = ipdatalen - IGMP_MINLEN;
+ if (igmpdatalen < 0) {
+ fprintf(stderr,
+ "IP data field too short (%u bytes) for IGMP from %s\n",
+ ipdatalen, inet_fmt(ip->ip_src.s_addr, s1));
+ continue;
+ }
+
+ switch (igmp->igmp_type) {
+
+ case IGMP_MTRACE: /* For backward compatibility with 3.3 */
+ case IGMP_MTRACE_RESP:
+ if (igmpdatalen < QLEN) continue;
+ if ((igmpdatalen - QLEN)%RLEN) {
+ printf("packet with incorrect datalen\n");
+ continue;
+ }
+
+ len = (igmpdatalen - QLEN)/RLEN;
+
+ break;
+
+ default:
+ continue;
+ }
+
+ base.qtime = ((tr.tv_sec + JAN_1970) << 16) +
+ (tr.tv_usec << 10) / 15625;
+ base.rtime = ((tr.tv_sec + JAN_1970) << 16) +
+ (tr.tv_usec << 10) / 15625;
+ base.len = len;
+ bcopy((char *)igmp, (char *)&base.igmp, ipdatalen);
+ /*
+ * If the user specified which traces to monitor,
+ * only accept traces that correspond to the
+ * request
+ */
+ if ((qsrc != 0 && qsrc != base.qhdr.tr_src) ||
+ (qdst != 0 && qdst != base.qhdr.tr_dst) ||
+ (qgrp != 0 && qgrp != igmp->igmp_group.s_addr))
+ continue;
+
+ printf("Mtrace 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;
+ 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));
+ print_host(base.qhdr.tr_src);
+ printf("\n");
+ } else if (r->tr_rmtaddr != 0) {
+ printf("%3d ", -(base.len+1));
+ what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ?
+ "doesn't support mtrace"
+ : "is the next hop");
+ }
+ printf("\n");
+ }
+}
char *
print_host(addr)
u_int32 addr;
{
+ return print_host2(addr, 0);
+}
+
+/*
+ * On some routers, one interface has a name and the other doesn't.
+ * We always print the address of the outgoing interface, but can
+ * sometimes get the name from the incoming interface. This might be
+ * confusing but should be slightly more helpful than just a "?".
+ */
+char *
+print_host2(addr1, addr2)
+ u_int32 addr1, addr2;
+{
char *name;
if (numeric) {
- printf("%s", inet_fmt(addr, s1));
+ printf("%s", inet_fmt(addr1, s1));
return ("");
}
- name = inet_name(addr);
- printf("%s (%s)", name, inet_fmt(addr, s1));
+ name = inet_name(addr1);
+ if (*name == '?' && *(name + 1) == '\0' && addr2 != 0)
+ name = inet_name(addr2);
+ printf("%s (%s)", name, inet_fmt(addr1, s1));
return (name);
}
@@ -613,16 +772,22 @@ print_trace(index, buf)
struct tr_resp *r;
char *name;
int i;
+ int hop;
+ char *ms;
i = abs(index);
r = buf->resps + i - 1;
for (; i <= buf->len; ++i, ++r) {
if (index > 0) printf("%3d ", -i);
- name = print_host(r->tr_outaddr);
- printf(" %s thresh^ %d %d ms %s\n", proto_type(r->tr_rproto),
- r->tr_fttl, t_diff(fixtime(ntohl(r->tr_qarr)), buf->qtime),
- flag_type(r->tr_rflags));
+ name = print_host2(r->tr_outaddr, r->tr_inaddr);
+ printf(" %s thresh^ %d", proto_type(r->tr_rproto), r->tr_fttl);
+ if (verbose) {
+ hop = t_diff(fixtime(ntohl(r->tr_qarr)), buf->qtime);
+ ms = scale(&hop);
+ printf(" %d%s", hop, ms);
+ }
+ printf(" %s\n", flag_type(r->tr_rflags));
memcpy(names[i-1], name, sizeof(names[0]) - 1);
names[i-1][sizeof(names[0])-1] = '\0';
}
@@ -632,8 +797,9 @@ print_trace(index, buf)
* See what kind of router is the next hop
*/
int
-what_kind(buf)
+what_kind(buf, why)
struct resp_buf *buf;
+ char *why;
{
u_int32 smask;
int retval;
@@ -666,13 +832,14 @@ what_kind(buf)
case 10:
type = "cisco ";
}
- printf(" [%s%d.%d] didn't respond\n",
- type, version & 0xFF, (version >> 8) & 0xFF);
+ printf(" [%s%d.%d] %s\n",
+ type, version & 0xFF, (version >> 8) & 0xFF,
+ why);
VAL_TO_MASK(smask, r->tr_smask);
while (p < ep) {
- register u_int32 laddr = *p++;
- register int flags = (ntohl(*p) & 0xFF00) >> 8;
- register int n = ntohl(*p++) & 0xFF;
+ u_int32 laddr = *p++;
+ int flags = (ntohl(*p) & 0xFF00) >> 8;
+ int n = ntohl(*p++) & 0xFF;
if (!(flags & (DVMRP_NF_DOWN | DVMRP_NF_DISABLED)) &&
(laddr & smask) == (qsrc & smask)) {
printf("%3d ", -(hops+2));
@@ -684,7 +851,7 @@ what_kind(buf)
}
return retval;
}
- printf(" didn't respond\n");
+ printf(" %s\n", why);
return 0;
}
@@ -708,30 +875,37 @@ scale(hop)
#define OUTS 2
#define BOTH 3
void
-stat_line(r, s, have_next)
+stat_line(r, s, have_next, rst)
struct tr_resp *r, *s;
int have_next;
+ int *rst;
{
- register timediff = (fixtime(ntohl(s->tr_qarr)) -
+ int timediff = (fixtime(ntohl(s->tr_qarr)) -
fixtime(ntohl(r->tr_qarr))) >> 16;
- register v_lost, v_pct;
- register g_lost, g_pct;
- register v_out = ntohl(s->tr_vifout) - ntohl(r->tr_vifout);
- register g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
- register v_pps, g_pps;
+ int v_lost, v_pct;
+ int g_lost, g_pct;
+ int v_out = ntohl(s->tr_vifout) - ntohl(r->tr_vifout);
+ int g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
+ int v_pps, g_pps;
char v_str[8], g_str[8];
- register have = NEITHER;
+ int have = NEITHER;
+ int res = *rst;
if (timediff == 0) timediff = 1;
v_pps = v_out / timediff;
g_pps = g_out / timediff;
- if (v_out || s->tr_vifout != 0xFFFFFFFF) have |= OUTS;
+ if (v_out && (s->tr_vifout != 0xFFFFFFFF && s->tr_vifout != 0) ||
+ (r->tr_vifout != 0xFFFFFFFF && r->tr_vifout != 0))
+ have |= OUTS;
if (have_next) {
- --r, --s;
- if (s->tr_vifin != 0xFFFFFFFF || r->tr_vifin != 0xFFFFFFFF)
+ --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;
}
switch (have) {
@@ -750,61 +924,129 @@ stat_line(r, s, have_next)
sprintf(g_str, "%3d", g_pct);
else memcpy(g_str, " --", 4);
- printf("%6d/%-5d=%s%%%4d pps%6d/%-5d=%s%%%4d pps\n",
- v_lost, v_out, v_str, v_pps, g_lost, g_out, g_str, g_pps);
- if (debug > 2) {
- printf("\t\t\t\tv_in: %ld ", ntohl(s->tr_vifin));
- printf("v_out: %ld ", ntohl(s->tr_vifout));
- printf("pkts: %ld\n", ntohl(s->tr_pktcnt));
- printf("\t\t\t\tv_in: %ld ", ntohl(r->tr_vifin));
- printf("v_out: %ld ", ntohl(r->tr_vifout));
- printf("pkts: %ld\n", ntohl(r->tr_pktcnt));
- printf("\t\t\t\tv_in: %ld ",ntohl(s->tr_vifin)-ntohl(r->tr_vifin));
- 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("%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);
break;
case INS:
- v_out = (ntohl(s->tr_vifin) - ntohl(r->tr_vifin));
- g_out = (ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt));
+ v_out = ntohl(s->tr_vifin) - ntohl(r->tr_vifin);
v_pps = v_out / timediff;
- g_pps = g_out / timediff;
/* Fall through */
case OUTS:
- printf(" %-5d %4d pps %-5d %4d pps\n",
- v_out, v_pps, g_out, g_pps);
+ 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));
+ printf("pkts: %ld\n", ntohl(s->tr_pktcnt));
+ printf("\t\t\t\tv_in: %ld ", ntohl(r->tr_vifin));
+ printf("v_out: %ld ", ntohl(r->tr_vifout));
+ printf("pkts: %ld\n", ntohl(r->tr_pktcnt));
+ printf("\t\t\t\tv_in: %ld ",ntohl(s->tr_vifin)-ntohl(r->tr_vifin));
+ 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);
+ }
}
/*
- * A fixup to check if any pktcnt has been reset.
+ * A fixup to check if any pktcnt has been reset, and to fix the
+ * byteorder bugs in mrouted 3.6 on little-endian machines.
*/
void
-fixup_stats(base, new)
- struct resp_buf *base, *new;
+fixup_stats(base, prev, new)
+ struct resp_buf *base, *prev, *new;
{
- register rno = base->len;
- register struct tr_resp *b = base->resps + rno;
- register struct tr_resp *n = new->resps + rno;
+ int rno = base->len;
+ struct tr_resp *b = base->resps + rno;
+ struct tr_resp *p = prev->resps + rno;
+ struct tr_resp *n = new->resps + rno;
+ int *r = reset + rno;
+ int *s = swaps + rno;
+ int res;
+
+ /* Check for byte-swappers */
+ while (--rno >= 0) {
+ --n; --p; --b; --s;
+ if (*s || abs(ntohl(n->tr_vifout) - ntohl(p->tr_vifout)) > 100000) {
+ /* This host sends byteswapped reports; swap 'em */
+ if (!*s) {
+ *s = 1;
+ b->tr_qarr = byteswap(b->tr_qarr);
+ b->tr_vifin = byteswap(b->tr_vifin);
+ b->tr_vifout = byteswap(b->tr_vifout);
+ b->tr_pktcnt = byteswap(b->tr_pktcnt);
+ }
- while (--rno >= 0)
- if (ntohl((--n)->tr_pktcnt) < ntohl((--b)->tr_pktcnt)) break;
+ n->tr_qarr = byteswap(n->tr_qarr);
+ n->tr_vifin = byteswap(n->tr_vifin);
+ n->tr_vifout = byteswap(n->tr_vifout);
+ n->tr_pktcnt = byteswap(n->tr_pktcnt);
+ }
+ }
+
+ rno = base->len;
+ b = base->resps + rno;
+ p = prev->resps + rno;
+ n = new->resps + rno;
+
+ while (--rno >= 0) {
+ --n; --p; --b; --r;
+ res = ((ntohl(n->tr_pktcnt) < ntohl(b->tr_pktcnt)) ||
+ (ntohl(n->tr_pktcnt) < ntohl(p->tr_pktcnt)));
+ if (debug > 2)
+ printf("\t\tr=%d, res=%d\n", *r, res);
+ if (*r) {
+ if (res || *r > 1) {
+ /*
+ * This router appears to be a 3.4 with that nasty ol'
+ * neighbor version bug, which causes it to constantly
+ * reset. Just nuke the statistics for this node, and
+ * don't even bother giving it the benefit of the
+ * doubt from now on.
+ */
+ p->tr_pktcnt = b->tr_pktcnt = n->tr_pktcnt;
+ *r++;
+ } else {
+ /*
+ * This is simply the situation that the original
+ * fixup_stats was meant to deal with -- that a
+ * 3.3 or 3.4 router deleted a cache entry while
+ * traffic was still active.
+ */
+ *r = 0;
+ break;
+ }
+ } else
+ *r = res;
+ }
if (rno < 0) return;
rno = base->len;
b = base->resps + rno;
- n = new->resps + rno;
+ p = prev->resps + rno;
- while (--rno >= 0) (--b)->tr_pktcnt = (--n)->tr_pktcnt;
+ while (--rno >= 0) (--b)->tr_pktcnt = (--p)->tr_pktcnt;
}
/*
@@ -815,15 +1057,17 @@ print_stats(base, prev, new)
struct resp_buf *base, *prev, *new;
{
int rtt, hop;
- register char *ms;
- register u_int32 smask;
- register rno = base->len - 1;
- register struct tr_resp *b = base->resps + rno;
- register struct tr_resp *p = prev->resps + rno;
- register struct tr_resp *n = new->resps + rno;
- register u_long resptime = new->rtime;
- register u_long qarrtime = fixtime(ntohl(n->tr_qarr));
- register ttl = n->tr_fttl;
+ char *ms;
+ u_int32 smask;
+ int rno = base->len - 1;
+ struct tr_resp *b = base->resps + rno;
+ struct tr_resp *p = prev->resps + rno;
+ struct tr_resp *n = new->resps + rno;
+ int *r = reset + rno;
+ u_long resptime = new->rtime;
+ u_long qarrtime = fixtime(ntohl(n->tr_qarr));
+ u_int ttl = n->tr_fttl;
+ int first = (base == prev);
VAL_TO_MASK(smask, b->tr_smask);
printf(" Source Response Dest");
@@ -833,12 +1077,14 @@ print_stats(base, prev, new)
inet_fmt(base->qhdr.tr_raddr, s2), inet_fmt(qsrc, s1));
rtt = t_diff(resptime, new->qtime);
ms = scale(&rtt);
- printf(" | __/ rtt%5d%s Lost/Sent = Pct Rate To %s\n",
- rtt, ms, inet_fmt(qgrp, s2));
- hop = t_diff(resptime, qarrtime);
- ms = scale(&hop);
- printf(" v / hop%5d%s", hop, ms);
- printf(" --------------------- --------------------\n");
+ printf(" %c __/ rtt%5d%s Lost/Sent = Pct Rate To %s\n",
+ first ? 'v' : '|', rtt, ms, inet_fmt(qgrp, s2));
+ if (!first) {
+ hop = t_diff(resptime, qarrtime);
+ ms = scale(&hop);
+ printf(" v / hop%5d%s", hop, ms);
+ printf(" --------------------- --------------------\n");
+ }
if (debug > 2) {
printf("\t\t\t\tv_in: %ld ", ntohl(n->tr_vifin));
printf("v_out: %ld ", ntohl(n->tr_vifout));
@@ -849,6 +1095,7 @@ print_stats(base, prev, new)
printf("\t\t\t\tv_in: %ld ", ntohl(n->tr_vifin) - ntohl(b->tr_vifin));
printf("v_out: %ld ", ntohl(n->tr_vifout) - ntohl(b->tr_vifout));
printf("pkts: %ld\n", ntohl(n->tr_pktcnt) - ntohl(b->tr_pktcnt));
+ printf("\t\t\t\treset: %d\n", *r);
}
while (TRUE) {
@@ -862,28 +1109,30 @@ print_stats(base, prev, new)
if (rno-- < 1) break;
- printf(" | ^ ttl%5d ", ttl);
- if (prev == new) printf("\n");
- else stat_line(p, n, TRUE);
- 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);
+ printf(" %c ^ ttl%5d ", first ? 'v' : '|', ttl);
+ stat_line(p, n, TRUE, r);
+ if (!first) {
+ 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);
+ }
- --b, --p, --n;
+ --b, --p, --n, --r;
if (ttl < n->tr_fttl) ttl = n->tr_fttl;
else ++ttl;
}
- printf(" | \\__ ttl%5d ", ttl);
- if (prev == new) printf("\n");
- else stat_line(p, n, FALSE);
- hop = t_diff(qarrtime, new->qtime);
- ms = scale(&hop);
- printf(" v \\ hop%5d%s", hop, ms);
- stat_line(b, n, FALSE);
+ printf(" %c \\__ ttl%5d ", first ? 'v' : '|', ttl);
+ stat_line(p, n, FALSE, r);
+ if (!first) {
+ hop = t_diff(qarrtime, new->qtime);
+ ms = scale(&hop);
+ printf(" v \\ hop%5d%s", hop, ms);
+ 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");
return 0;
@@ -923,11 +1172,11 @@ char *argv[];
if (argc == 0) goto usage;
while (argc > 0 && *argv[0] == '-') {
- register char *p = *argv++; argc--;
+ char *p = *argv++; argc--;
p++;
do {
- register char c = *p++;
- register char *arg = (char *) 0;
+ char c = *p++;
+ char *arg = (char *) 0;
if (isdigit(*p)) {
arg = p;
p = "";
@@ -954,6 +1203,9 @@ char *argv[];
case 'p': /* Passive listen for traces */
passive = TRUE;
break;
+ case 'v': /* Verbosity */
+ verbose = TRUE;
+ break;
case 's': /* Short form, don't wait for stats */
numstats = 0;
break;
@@ -1009,6 +1261,14 @@ char *argv[];
break;
} else
goto usage;
+ case 'S': /* Stat accumulation interval */
+ if (arg && isdigit(*arg)) {
+ statint = atoi(arg);
+ if (statint < 1) statint = 1;
+ if (arg == argv[0]) argv++, argc--;
+ break;
+ } else
+ goto usage;
default:
goto usage;
}
@@ -1032,10 +1292,15 @@ char *argv[];
}
}
+ if (passive) {
+ passive_mode();
+ return(0);
+ }
+
if (argc > 0 || qsrc == 0) {
usage: printf("\
Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
- [-t ttl] [-r resp_dest] [-i if_addr] source [receiver] [group]\n");
+ [-S statint] [-t ttl] [-r resp_dest] [-i if_addr] source [receiver] [group]\n");
exit(1);
}
@@ -1067,6 +1332,36 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
exit(-1);
}
+#ifdef SUNOS5
+ /*
+ * SunOS 5.X prior to SunOS 2.6, getsockname returns 0 for udp socket.
+ * This call to sysinfo will return the hostname.
+ * If the default multicast interfface (set with the route
+ * for 224.0.0.0) is not the same as the hostname,
+ * mtrace -i [if_addr] will have to be used.
+ */
+ if (addr.sin_addr.s_addr == 0) {
+ char myhostname[MAXHOSTNAMELEN];
+ struct hostent *hp;
+ int error;
+
+ error = sysinfo(SI_HOSTNAME, myhostname, sizeof(myhostname));
+ if (error == -1) {
+ perror("Getting my hostname");
+ exit(-1);
+ }
+
+ hp = gethostbyname(myhostname);
+ if (hp == NULL || hp->h_addrtype != AF_INET ||
+ hp->h_length != sizeof(addr.sin_addr)) {
+ perror("Finding IP address for my hostname");
+ exit(-1);
+ }
+
+ memcpy((char *)&addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
+ }
+#endif
+
/*
* Default destination for path to be queried is the local host.
*/
@@ -1136,7 +1431,7 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
}
/*
- * Try a query at the requested number of hops or MAXOPS if unspecified.
+ * Try a query at the requested number of hops or MAXHOPS if unspecified.
*/
if (qno == 0) {
hops = MAXHOPS;
@@ -1148,7 +1443,7 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
tries = nqueries;
printf("Querying reverse path, maximum %d hops... ", qno);
fflush(stdout);
- }
+ }
base.rtime = 0;
base.len = 0;
@@ -1167,9 +1462,12 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
printf("\n");
print_trace(1, &base);
r = base.resps + base.len - 1;
- if (r->tr_rflags == TR_OLD_ROUTER) {
+ if (r->tr_rflags == TR_OLD_ROUTER || r->tr_rflags == TR_NO_SPACE ||
+ qno != 0) {
printf("%3d ", -(base.len+1));
- what_kind(&base);
+ what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ?
+ "doesn't support mtrace"
+ : "is the next hop");
} else {
VAL_TO_MASK(smask, r->tr_smask);
if ((r->tr_inaddr & smask) == (qsrc & smask)) {
@@ -1204,7 +1502,7 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
if (recvlen == 0) {
if (hops == 1) break;
if (hops == nexthop) {
- if (what_kind(&base)) {
+ if (what_kind(&base, "didn't respond")) {
/* the ask_neighbors determined that the
* not-responding router is the first-hop. */
break;
@@ -1227,36 +1525,62 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
print_trace(nexthop, &base);
}
} else {
- if (base.len == hops - 1) {
+ if (base.len < hops) {
+ /*
+ * A shorter trace than requested means a fatal error
+ * occurred along the path, or that the route changed
+ * to a shorter one.
+ *
+ * If the trace is longer than the last one we received,
+ * then we are resuming from a skipped router (but there
+ * is still probably a problem).
+ *
+ * If the trace is shorter than the last one we
+ * received, then the route must have changed (and
+ * there is still probably a problem).
+ */
if (nexthop <= base.len) {
printf("\nResuming...\n");
print_trace(nexthop, &base);
+ } else if (nexthop > base.len + 1) {
+ hops = base.len;
+ printf("\nRoute must have changed...\n");
+ print_trace(1, &base);
}
} else {
+ /*
+ * The last hop address is not the same as it was;
+ * the route probably changed underneath us.
+ */
hops = base.len;
printf("\nRoute must have changed...\n");
print_trace(1, &base);
}
- if (r->tr_rflags == TR_OLD_ROUTER) {
- what_kind(&base);
- break;
- }
- if (r->tr_rflags == TR_NO_SPACE) {
- printf("No space left in trace packet for more hops\n");
- break; /* XXX could do segmented trace */
- }
}
lastout = r->tr_outaddr;
- nexthop = hops + 1;
- VAL_TO_MASK(smask, r->tr_smask);
- if ((r->tr_inaddr & smask) == (qsrc & smask)) {
- printf("%3d ", -nexthop);
- print_host(qsrc);
- printf("\n");
+ if (base.len < hops ||
+ r->tr_rmtaddr == 0 ||
+ (r->tr_rflags & 0x80)) {
+ VAL_TO_MASK(smask, r->tr_smask);
+ if (r->tr_rmtaddr) {
+ if (hops != nexthop) {
+ printf("\n%3d ", -(base.len+1));
+ }
+ what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ?
+ "doesn't support mtrace" :
+ "would be the next hop");
+ /* XXX could do segmented trace if TR_NO_SPACE */
+ } else if (r->tr_rflags == TR_NO_ERR &&
+ (r->tr_inaddr & smask) == (qsrc & smask)) {
+ printf("%3d ", -(hops + 1));
+ print_host(qsrc);
+ printf("\n");
+ }
break;
}
- if (r->tr_rmtaddr == 0 || (r->tr_rflags & 0x80)) break;
+
+ nexthop = hops + 1;
}
}
@@ -1284,8 +1608,9 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
raddr = base.qhdr.tr_raddr;
rttl = base.qhdr.tr_rttl;
gettimeofday(&tv, 0);
- waittime = 10 - (((tv.tv_sec + JAN_1970) & 0xFFFF) - (base.qtime >> 16));
- prev = new = &incr[numstats&1];
+ waittime = statint - (((tv.tv_sec + JAN_1970) & 0xFFFF) - (base.qtime >> 16));
+ prev = &base;
+ new = &incr[numstats&1];
while (numstats--) {
if (waittime < 1) printf("\n");
@@ -1304,14 +1629,23 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
if (rno != new->len) {
printf("Trace length doesn't match:\n");
+ /*
+ * XXX Should this trace result be printed, or is that
+ * too verbose? Perhaps it should just say restarting.
+ * But if the path is changing quickly, this may be the
+ * only snapshot of the current path. But, if the path
+ * is changing that quickly, does the current path really
+ * matter?
+ */
print_trace(1, new);
printf("Restarting.\n\n");
+ numstats++;
goto restart;
}
printf("Results after %d seconds:\n\n",
(int)((new->qtime - base.qtime) >> 16));
- fixup_stats(&base, new);
+ fixup_stats(&base, prev, new);
if (print_stats(&base, prev, new)) {
printf("Route changed:\n");
print_trace(1, new);
@@ -1320,7 +1654,7 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
}
prev = new;
new = &incr[numstats&1];
- waittime = 10;
+ waittime = statint;
}
/*
@@ -1461,3 +1795,15 @@ void accept_neighbors2(src, dst, p, datalen, level)
int datalen;
{
}
+void accept_info_request(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+}
+void accept_info_reply(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+}
diff --git a/usr.sbin/mrouted/pathnames.h b/usr.sbin/mrouted/pathnames.h
index 22b0019f089d..b3e3c88f8988 100644
--- a/usr.sbin/mrouted/pathnames.h
+++ b/usr.sbin/mrouted/pathnames.h
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: pathnames.h,v 3.6 1995/06/25 19:17:45 fenner Exp $
+ * $Id: pathnames.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
#define _PATH_MROUTED_CONF "/etc/mrouted.conf"
diff --git a/usr.sbin/mrouted/prune.c b/usr.sbin/mrouted/prune.c
index f30b056d1fb1..fe3cdd5b4e14 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.6 1995/06/25 19:18:43 fenner Exp $
+ * $Id: prune.c,v 3.8 1995/11/29 22:36:34 fenner Rel $
*/
@@ -55,6 +55,7 @@ static void prun_add_ttls __P((struct gtable *gt));
static int pruning_neighbor __P((vifi_t vifi, u_int32 addr));
static int can_mtrace __P((vifi_t vifi, u_int32 addr));
static struct ptable * find_prune_entry __P((u_int32 vr, struct ptable *pt));
+static void expire_prune __P((vifi_t vifi, struct gtable *gt));
static void send_prune __P((struct gtable *gt));
static void send_graft __P((struct gtable *gt));
static void send_graft_ack __P((u_int32 src, u_int32 dst,
@@ -84,7 +85,7 @@ prun_add_ttls(gt)
* checks for scoped multicast addresses
*/
#define GET_SCOPE(gt) { \
- register int _i; \
+ register vifi_t _i; \
if ((ntohl((gt)->gt_mcastgrp) & 0xff000000) == 0xef000000) \
for (_i = 0; _i < numvifs; _i++) \
if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
@@ -633,7 +634,11 @@ add_table_entry(origin, mcastgrp)
struct rtentry *r;
struct gtable *gt,**gtnp,*prev_gt;
struct stable *st,**stnp;
- int i;
+ vifi_t i;
+
+#ifdef DEBUG_MFC
+ md_log(MD_MISS, origin, mcastgrp);
+#endif
r = determine_route(origin);
prev_gt = NULL;
@@ -727,7 +732,7 @@ add_table_entry(origin, mcastgrp)
gt->gt_gnext->gt_gprev = gt;
}
} else {
- gt->gt_gnext = gt->gt_prev = NULL;
+ gt->gt_gnext = gt->gt_gprev = NULL;
}
}
@@ -748,8 +753,14 @@ add_table_entry(origin, mcastgrp)
st->st_next = *stnp;
*stnp = st;
} else {
+#ifdef DEBUG_MFC
+ md_log(MD_DUPE, origin, mcastgrp);
+#endif
log(LOG_WARNING, 0, "kernel entry already exists for (%s %s)",
inet_fmt(origin, s1), inet_fmt(mcastgrp, s2));
+ /* XXX Doing this should cause no harm, and may ensure
+ * kernel<>mrouted synchronization */
+ k_add_rg(origin, gt);
return;
}
@@ -780,60 +791,31 @@ reset_neighbor_state(vifi, addr)
{
struct rtentry *r;
struct gtable *g;
- struct ptable *pt, *prev_pt;
- struct stable *st, *prev_st;
+ struct ptable *pt, **ptnp;
+ struct stable *st;
for (g = kernel_table; g; g = g->gt_gnext) {
r = g->gt_route;
/*
* If neighbor was the parent, remove the prune sent state
- * Don't send any grafts upstream.
+ * and all of the source cache info so that prunes get
+ * regenerated.
*/
if (vifi == r->rt_parent) {
if (addr == r->rt_gateway) {
- log(LOG_DEBUG, 0, "reset_neighbor_state del prunes (%s %s)",
+ log(LOG_DEBUG, 0, "reset_neighbor_state parent reset (%s %s)",
inet_fmts(r->rt_origin, r->rt_originmask, s1),
inet_fmt(g->gt_mcastgrp, s2));
- pt = g->gt_pruntbl;
- while (pt) {
- /*
- * Expire prune, send again on this vif.
- */
- VIFM_SET(pt->pt_vifi, g->gt_grpmems);
- prev_pt = pt;
- pt = prev_pt->pt_next;
- free(prev_pt);
- }
- g->gt_pruntbl = NULL;
-
- st = g->gt_srctbl;
- while (st) {
- log(LOG_DEBUG, 0, "reset_neighbor_state del sg (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(g->gt_mcastgrp, s2));
-
- if (k_del_rg(st->st_origin, g) < 0) {
- log(LOG_WARNING, errno,
- "reset_neighbor_state trying to delete (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(g->gt_mcastgrp, s2));
- }
- kroutes--;
- prev_st = st;
- st = prev_st->st_next;
- free(prev_st);
- }
- g->gt_srctbl = NULL;
- /*
- * Keep the group entries themselves around since the
- * state will likely just come right back, and if not,
- * the group entries will time out with no kernel entries
- * and no prune state.
- */
g->gt_prsent_timer = 0;
g->gt_grftsnt = 0;
+ while (st = g->gt_srctbl) {
+ g->gt_srctbl = st->st_next;
+ k_del_rg(st->st_origin, g);
+ kroutes--;
+ free(st);
+ }
}
} else {
/*
@@ -848,13 +830,13 @@ reset_neighbor_state(vifi, addr)
/*
* Remove any prunes that this router has sent us.
*/
- prev_pt = (struct ptable *)&g->gt_pruntbl;
- for (pt = g->gt_pruntbl; pt; pt = pt->pt_next) {
+ ptnp = &g->gt_pruntbl;
+ while ((pt = *ptnp) != NULL) {
if (pt->pt_vifi == vifi && pt->pt_router == addr) {
- prev_pt->pt_next = pt->pt_next;
+ *ptnp = pt->pt_next;
free(pt);
} else
- prev_pt = pt;
+ ptnp = &pt->pt_next;
}
/*
@@ -924,9 +906,9 @@ del_table_entry(r, mcastgrp, del_flag)
pt = g->gt_pruntbl;
while (pt) {
- prev_pt = pt->pt_next;
- free(pt);
- pt = prev_pt;
+ prev_pt = pt;
+ pt = pt->pt_next;
+ free(prev_pt);
}
g->gt_pruntbl = NULL;
@@ -937,14 +919,14 @@ del_table_entry(r, mcastgrp, del_flag)
else
kernel_table = g->gt_gnext;
- prev_g = g->gt_next;
#ifdef RSRR
/* Send route change notification to reservation protocol. */
rsrr_cache_send(g,0);
rsrr_cache_clean(g);
#endif /* RSRR */
- free(g);
- g = prev_g;
+ prev_g = g;
+ g = g->gt_next;
+ free(prev_g);
}
r->rt_groups = NULL;
}
@@ -968,17 +950,17 @@ del_table_entry(r, mcastgrp, del_flag)
inet_fmt(g->gt_mcastgrp, s2));
}
kroutes--;
- prev_st = st->st_next;
- free(st);
- st = prev_st;
+ prev_st = st;
+ st = st->st_next;
+ free(prev_st);
}
g->gt_srctbl = NULL;
pt = g->gt_pruntbl;
while (pt) {
- prev_pt = pt->pt_next;
- free(pt);
- pt = prev_pt;
+ prev_pt = pt;
+ pt = pt->pt_next;
+ free(prev_pt);
}
g->gt_pruntbl = NULL;
@@ -1018,7 +1000,7 @@ update_table_entry(r)
{
struct gtable *g;
struct ptable *pt, *prev_pt;
- int i;
+ vifi_t i;
for (g = r->rt_groups; g; g = g->gt_next) {
pt = g->gt_pruntbl;
@@ -1282,7 +1264,7 @@ accept_prune(src, dst, p, datalen)
g->gt_timer = CACHE_LIFETIME(cache_lifetime);
if (g->gt_timer < prun_tmr)
g->gt_timer = prun_tmr;
-
+
/*
* check if any more packets need to be sent on the
* vif which sent this message
@@ -1580,21 +1562,21 @@ free_all_prunes()
while (g) {
s = g->gt_srctbl;
while (s) {
- prev_s = s->st_next;
- free(s);
- s = prev_s;
+ prev_s = s;
+ s = s->st_next;
+ free(prev_s);
}
p = g->gt_pruntbl;
while (p) {
- prev_p = p->pt_next;
- free(p);
- p = prev_p;
+ prev_p = p;
+ p = p->pt_next;
+ free(prev_p);
}
- prev_g = g->gt_next;
- free(g);
- g = prev_g;
+ prev_g = g;
+ g = g->gt_next;
+ free(prev_g);
}
r->rt_groups = NULL;
}
@@ -1605,9 +1587,9 @@ free_all_prunes()
if (g->gt_srctbl)
free(g->gt_srctbl);
- prev_g = g->gt_next;
- free(g);
- g = prev_g;
+ prev_g = g;
+ g = g->gt_next;
+ free(prev_g);
}
kernel_no_route = NULL;
}
@@ -1742,34 +1724,8 @@ age_table_entry()
inet_fmt(gt->gt_mcastgrp, s2),
inet_fmt(pt->pt_router, s3),
pt->pt_vifi);
-
- /*
- * No need to send a graft, any prunes that we sent
- * will expire before any prunes that we have received.
- */
- if (gt->gt_prsent_timer > 0) {
- log(LOG_DEBUG, 0, "prune expired with %d left on %s",
- gt->gt_prsent_timer, "prsent_timer");
- gt->gt_prsent_timer = 0;
- }
- /* modify the kernel entry to forward packets */
- if (!VIFM_ISSET(pt->pt_vifi, gt->gt_grpmems)) {
- VIFM_SET(pt->pt_vifi, gt->gt_grpmems);
- log(LOG_DEBUG, 0, "forw again (%s %s) gm:%x vif:%d",
- inet_fmts(r->rt_origin, r->rt_originmask, s1),
- inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems,
- pt->pt_vifi);
-
- prun_add_ttls(gt);
- update_kernel(gt);
-#ifdef RSRR
- /* Send route change notification to reservation
- * protocol.
- */
- rsrr_cache_send(gt,1);
-#endif /* RSRR */
- }
+ expire_prune(pt->pt_vifi, gt);
/* remove the router's prune entry and await new one */
*ptnp = pt->pt_next;
@@ -1780,94 +1736,65 @@ age_table_entry()
}
/*
- * If the cache entry has expired, check for downstream prunes.
- *
- * If there are downstream prunes, refresh the cache entry's timer.
- * Otherwise, check for traffic. If no traffic, delete this
- * entry.
+ * If the cache entry has expired, delete source table entries for
+ * silent sources. If there are no source entries left, and there
+ * are no downstream prunes, then the entry is deleted.
+ * Otherwise, the cache entry's timer is refreshed.
*/
if (gt->gt_timer <= 0) {
- if (gt->gt_pruntbl) {
- if (gt->gt_prsent_timer == -1)
- gt->gt_prsent_timer = 0;
- gt->gt_timer = CACHE_LIFETIME(cache_lifetime);
- gtnptr = &gt->gt_gnext;
- continue;
- }
-
- /*
- * If this entry was pruned, but all downstream prunes
- * have expired, then it is safe to simply delete it.
- * Otherwise, check for traffic before deleting.
- */
- if (gt->gt_prsent_timer == 0) {
- sg_req.grp.s_addr = gt->gt_mcastgrp;
- stnp = &gt->gt_srctbl;
- while ((st = *stnp) != NULL) {
- sg_req.src.s_addr = st->st_origin;
- if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req)
- < 0) {
- log(LOG_WARNING, errno, "%s (%s %s)",
- "age_table_entry: SIOCGETSGCNT failing for",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- /* Make sure it gets deleted below */
- sg_req.pktcnt = st->st_pktcnt;
- }
- if (sg_req.pktcnt == st->st_pktcnt) {
- *stnp = st->st_next;
- log(LOG_DEBUG, 0,
- "age_table_entry deleting (%s %s)",
+ /* Check for traffic before deleting source entries */
+ sg_req.grp.s_addr = gt->gt_mcastgrp;
+ stnp = &gt->gt_srctbl;
+ while ((st = *stnp) != NULL) {
+ sg_req.src.s_addr = st->st_origin;
+ if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) < 0) {
+ log(LOG_WARNING, errno, "%s (%s %s)",
+ "age_table_entry: SIOCGETSGCNT failing for",
+ inet_fmt(st->st_origin, s1),
+ inet_fmt(gt->gt_mcastgrp, s2));
+ /* Make sure it gets deleted below */
+ sg_req.pktcnt = st->st_pktcnt;
+ }
+ if (sg_req.pktcnt == st->st_pktcnt) {
+ *stnp = st->st_next;
+ log(LOG_DEBUG, 0, "age_table_entry deleting (%s %s)",
+ inet_fmt(st->st_origin, s1),
+ inet_fmt(gt->gt_mcastgrp, s2));
+ if (k_del_rg(st->st_origin, gt) < 0) {
+ log(LOG_WARNING, errno,
+ "age_table_entry trying to delete (%s %s)",
inet_fmt(st->st_origin, s1),
inet_fmt(gt->gt_mcastgrp, s2));
- if (k_del_rg(st->st_origin, gt) < 0) {
- log(LOG_WARNING, errno,
- "age_table_entry trying to delete (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- }
- kroutes--;
- free(st);
- } else {
- stnp = &st->st_next;
}
+ kroutes--;
+ free(st);
+ } else {
+ st->st_pktcnt = sg_req.pktcnt;
+ stnp = &st->st_next;
}
+ }
- if (gt->gt_srctbl) {
- /* At least one source in the list still has traffic */
- gt->gt_timer = CACHE_LIFETIME(cache_lifetime);
- gtnptr = &gt->gt_gnext;
- continue;
- }
+ /*
+ * Retain the group entry if we have downstream prunes or if
+ * there is at least one source in the list that still has
+ * traffic, or if our upstream prune timer is running.
+ */
+ if (gt->gt_pruntbl != NULL || gt->gt_srctbl != NULL ||
+ gt->gt_prsent_timer > 0) {
+ gt->gt_timer = CACHE_LIFETIME(cache_lifetime);
+ if (gt->gt_prsent_timer == -1)
+ if (gt->gt_grpmems == 0)
+ send_prune(gt);
+ else
+ gt->gt_prsent_timer = 0;
+ gtnptr = &gt->gt_gnext;
+ continue;
}
log(LOG_DEBUG, 0, "timeout cache entry (%s, %s)",
inet_fmts(r->rt_origin, r->rt_originmask, s1),
inet_fmt(gt->gt_mcastgrp, s2));
- /* free all the source entries */
- while ((st = gt->gt_srctbl) != NULL) {
- log(LOG_DEBUG, 0,
- "age_table_entry (P) deleting (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- if (k_del_rg(st->st_origin, gt) < 0) {
- log(LOG_WARNING, errno,
- "age_table_entry (P) trying to delete (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- }
- kroutes--;
- gt->gt_srctbl = st->st_next;
- free(st);
- }
-
- /* free all the prune list entries */
- while ((pt = gt->gt_pruntbl) != NULL) {
- gt->gt_pruntbl = pt->pt_next;
- free(pt);
- }
-
if (gt->gt_prev)
gt->gt_prev->gt_next = gt->gt_next;
else
@@ -1893,7 +1820,10 @@ age_table_entry()
free((char *)gt);
} else {
if (gt->gt_prsent_timer == -1)
- gt->gt_prsent_timer = 0;
+ if (gt->gt_grpmems == 0)
+ send_prune(gt);
+ else
+ gt->gt_prsent_timer = 0;
gtnptr = &gt->gt_gnext;
}
}
@@ -1928,6 +1858,44 @@ age_table_entry()
}
}
+/*
+ * Modify the kernel to forward packets when one or multiple prunes that
+ * were received on the vif given by vifi, for the group given by gt,
+ * have expired.
+ */
+static void
+expire_prune(vifi, gt)
+ vifi_t vifi;
+ struct gtable *gt;
+{
+ /*
+ * No need to send a graft, any prunes that we sent
+ * will expire before any prunes that we have received.
+ */
+ if (gt->gt_prsent_timer > 0) {
+ log(LOG_DEBUG, 0, "prune expired with %d left on %s",
+ gt->gt_prsent_timer, "prsent_timer");
+ gt->gt_prsent_timer = 0;
+ }
+
+ /* modify the kernel entry to forward packets */
+ if (!VIFM_ISSET(vifi, gt->gt_grpmems)) {
+ struct rtentry *rt = gt->gt_route;
+ VIFM_SET(vifi, gt->gt_grpmems);
+ log(LOG_DEBUG, 0, "forw again (%s %s) gm:%x vif:%d",
+ inet_fmts(rt->rt_origin, rt->rt_originmask, s1),
+ inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems, vifi);
+
+ prun_add_ttls(gt);
+ update_kernel(gt);
+#ifdef RSRR
+ /* Send route change notification to reservation protocol. */
+ rsrr_cache_send(gt,1);
+#endif /* RSRR */
+ }
+}
+
+
static char *
scaletime(t)
u_long t;
@@ -1978,7 +1946,7 @@ dump_cache(fp2)
register struct gtable *gt;
register struct stable *st;
register struct ptable *pt;
- register int i;
+ register vifi_t i;
register time_t thyme = time(0);
fprintf(fp2,
@@ -2091,21 +2059,6 @@ accept_mtrace(src, dst, group, data, no, datalen)
qry = (struct tr_query *)data;
- if (oqid == qry->tr_qid) {
- /*
- * If the multicast router is a member of the group being
- * queried, and the query is multicasted, then the router can
- * recieve multiple copies of the same query. If we have already
- * replied to this traceroute, just ignore it this time.
- *
- * This is not a total solution, but since if this fails you
- * only get N copies, N <= the number of interfaces on the router,
- * it is not fatal.
- */
- log(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
- return;
- }
-
/*
* if it is a packet with all reports filled, drop it
*/
@@ -2136,6 +2089,21 @@ accept_mtrace(src, dst, group, data, no, datalen)
* and if so, whether I should start response back
*/
if (type == QUERY) {
+ if (oqid == qry->tr_qid) {
+ /*
+ * If the multicast router is a member of the group being
+ * queried, and the query is multicasted, then the router can
+ * recieve multiple copies of the same query. If we have already
+ * replied to this traceroute, just ignore it this time.
+ *
+ * This is not a total solution, but since if this fails you
+ * only get N copies, N <= the number of interfaces on the router,
+ * it is not fatal.
+ */
+ log(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
+ return;
+ }
+
if (rt == NULL) {
log(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s",
inet_fmt(qry->tr_src, s1));
@@ -2201,7 +2169,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
bzero(resp, sizeof(struct tr_resp));
datalen += RLEN;
- resp->tr_qarr = ((tp.tv_sec + JAN_1970) << 16) +
+ resp->tr_qarr = htonl((tp.tv_sec + JAN_1970) << 16) +
((tp.tv_usec >> 4) & 0xffff);
resp->tr_rproto = PROTO_DVMRP;
@@ -2219,7 +2187,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
*/
v_req.vifi = vifi;
if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
- resp->tr_vifout = v_req.ocount;
+ resp->tr_vifout = htonl(v_req.ocount);
/*
* fill in scoping & pruning information
@@ -2236,7 +2204,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
sg_req.src.s_addr = qry->tr_src;
sg_req.grp.s_addr = group;
if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0)
- resp->tr_pktcnt = sg_req.pktcnt;
+ resp->tr_pktcnt = htonl(sg_req.pktcnt);
if (VIFM_ISSET(vifi, gt->gt_scope))
resp->tr_rflags = TR_SCOPED;
@@ -2267,7 +2235,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
/* get # of packets in on interface */
v_req.vifi = rt->rt_parent;
if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
- resp->tr_vifin = v_req.icount;
+ resp->tr_vifin = htonl(v_req.icount);
MASK_TO_VAL(rt->rt_originmask, resp->tr_smask);
src = uvifs[rt->rt_parent].uv_lcl_addr;
diff --git a/usr.sbin/mrouted/prune.h b/usr.sbin/mrouted/prune.h
index eef9d2842331..57ae067ce74f 100644
--- a/usr.sbin/mrouted/prune.h
+++ b/usr.sbin/mrouted/prune.h
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: prune.h,v 3.6 1995/06/25 19:19:04 fenner Exp $
+ * $Id: prune.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
/*
diff --git a/usr.sbin/mrouted/route.c b/usr.sbin/mrouted/route.c
index 38b9002982f0..c2b6b9e8b932 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.6 1995/06/25 19:20:19 fenner Exp $
+ * $Id: route.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
@@ -353,12 +353,12 @@ discard_route(prev_r)
void
update_route(origin, mask, metric, src, vifi)
u_int32 origin, mask;
- int metric;
+ u_int metric;
u_int32 src;
vifi_t vifi;
{
register struct rtentry *r;
- int adj_metric;
+ u_int adj_metric;
/*
* Compute an adjusted metric, taking into account the cost of the
@@ -462,7 +462,8 @@ update_route(origin, mask, metric, src, vifi)
(r->rt_gateway != 0 &&
(adj_metric < r->rt_metric ||
(adj_metric == r->rt_metric &&
- r->rt_timer >= ROUTE_SWITCH_TIME)))) {
+ (ntohl(src) < ntohl(r->rt_gateway) ||
+ r->rt_timer >= ROUTE_SWITCH_TIME))))) {
/*
* The report is for an origin we consider reachable; the report
* comes either from one of our own interfaces or from a gateway
@@ -473,10 +474,15 @@ update_route(origin, mask, metric, src, vifi)
* what our routing entry says, update the entry to use the new
* gateway and metric. We also switch gateways if the reported
* metric is the same as the one in the route entry and the gateway
- * associated with the route entry has not been heard from recently.
+ * associated with the route entry has not been heard from recently,
+ * or if the metric is the same but the reporting gateway has a lower
+ * IP address than the gateway associated with the route entry.
* Did you get all that?
*/
if (r->rt_parent != vifi || adj_metric < r->rt_metric) {
+ /*
+ * XXX Why do we do this if we are just changing the metric?
+ */
r->rt_parent = vifi;
if (init_children_and_leaves(r, vifi)) {
update_table_entry(r);
@@ -785,6 +791,12 @@ accept_report(src, dst, p, datalen, level)
if ((((u_char *)&mask)[1] = *p++) != 0) width = 2;
if ((((u_char *)&mask)[2] = *p++) != 0) width = 3;
if ((((u_char *)&mask)[3] = *p++) != 0) width = 4;
+ if (!inet_valid_mask(ntohl(mask))) {
+ log(LOG_WARNING, 0,
+ "%s reports bogus netmask 0x%08x (%s)",
+ inet_fmt(src, s1), ntohl(mask), inet_fmt(mask, s2));
+ return;
+ }
datalen -= 3;
do { /* Loop through (origin, metric) pairs */
@@ -805,6 +817,7 @@ accept_report(src, dst, p, datalen, level)
++nrt;
} while (!(metric & 0x80));
}
+
qsort((char*)rt, nrt, sizeof(rt[0]), compare_rts);
start_route_updates();
/*
@@ -815,9 +828,16 @@ accept_report(src, dst, p, datalen, level)
log(LOG_DEBUG, 0, "Updating %d routes from %s to %s", nrt,
inet_fmt(src, s1), inet_fmt(dst, s2));
- for (i = 0; i < nrt; ++i)
+ for (i = 0; i < nrt; ++i) {
+ if (i != 0 && rt[i].origin == rt[i-1].origin &&
+ rt[i].mask == rt[i-1].mask) {
+ log(LOG_WARNING, 0, "%s reports duplicate route for %s",
+ inet_fmt(src, s1), inet_fmts(rt[i].origin, rt[i].mask, s2));
+ continue;
+ }
update_route(rt[i].origin, rt[i].mask, rt[i].metric,
src, vifi);
+ }
if (routes_changed && !delay_change_reports)
report_to_all_neighbors(CHANGED_ROUTES);
@@ -1098,7 +1118,7 @@ dump_routes(fp)
FILE *fp;
{
register struct rtentry *r;
- register int i;
+ register vifi_t i;
fprintf(fp,
diff --git a/usr.sbin/mrouted/route.h b/usr.sbin/mrouted/route.h
index c947dd2da62a..73159d50261e 100644
--- a/usr.sbin/mrouted/route.h
+++ b/usr.sbin/mrouted/route.h
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: route.h,v 3.6 1995/06/25 19:21:05 fenner Exp $
+ * $Id: route.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
/*
diff --git a/usr.sbin/mrouted/rsrr.c b/usr.sbin/mrouted/rsrr.c
index c7bbc892379f..ea9628f55aea 100644
--- a/usr.sbin/mrouted/rsrr.c
+++ b/usr.sbin/mrouted/rsrr.c
@@ -107,7 +107,8 @@ rsrr_init()
/* Read a message from the RSRR socket */
void
-rsrr_read(rfd)
+rsrr_read(f, rfd)
+ int f;
fd_set *rfd;
{
register int rsrr_recvlen;
diff --git a/usr.sbin/mrouted/vif.c b/usr.sbin/mrouted/vif.c
index 98915aa5ac9c..3716292d1cab 100644
--- a/usr.sbin/mrouted/vif.c
+++ b/usr.sbin/mrouted/vif.c
@@ -7,14 +7,13 @@
* Leland Stanford Junior University.
*
*
- * $Id: vif.c,v 3.6 1995/06/25 19:53:01 fenner Exp $
+ * $Id: vif.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
#include "defs.h"
#include <fcntl.h>
-
/*
* Exported variables.
*/
@@ -34,24 +33,27 @@ typedef struct {
int q_time;
} cbk_t;
-static cbk_t *cbk;
/*
* Forward declarations.
*/
static void start_vif __P((vifi_t vifi));
+static void start_vif2 __P((vifi_t vifi));
static void stop_vif __P((vifi_t vifi));
static void age_old_hosts __P((void));
static void send_probe_on_vif __P((struct uvif *v));
-static void DelVif __P((cbk_t *cbk));
+static int info_version __P((char *p));
+static void DelVif __P((void *arg));
static int SetTimer __P((int vifi, struct listaddr *g));
static int DeleteTimer __P((int id));
-static void SendQuery __P((cbk_t *cbk));
+static void SendQuery __P((void *arg));
static int SetQueryTimer __P((struct listaddr *g, vifi_t vifi, int to_expire,
int q_time));
/*
- * Initialize the virtual interfaces.
+ * Initialize the virtual interfaces, but do not install
+ * them in the kernel. Start routing on all vifs that are
+ * not down or disabled.
*/
void
init_vifs()
@@ -101,11 +103,7 @@ init_vifs()
log(LOG_WARNING, 0,
"no enabled interfaces, forwarding via tunnels only");
- /*
- * Start routing on all virtual interfaces that are not down or
- * administratively disabled.
- */
- log(LOG_INFO, 0, "Installing vifs in kernel...");
+ log(LOG_INFO, 0, "Installing vifs in mrouted...");
for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
if (!(v->uv_flags & VIFF_DISABLED)) {
if (!(v->uv_flags & VIFF_DOWN)) {
@@ -116,7 +114,7 @@ init_vifs()
else
log(LOG_INFO, 0, "vif #%d, phyint %s", vifi,
inet_fmt(v->uv_lcl_addr, s1));
- start_vif(vifi);
+ start_vif2(vifi);
} else log(LOG_INFO, 0,
"%s is not yet up; vif #%u not in service",
v->uv_name, vifi);
@@ -124,6 +122,34 @@ init_vifs()
}
}
+/*
+ * Start routing on all virtual interfaces that are not down or
+ * administratively disabled.
+ */
+void
+init_installvifs()
+{
+ vifi_t vifi;
+ struct uvif *v;
+
+ log(LOG_INFO, 0, "Installing vifs in kernel...");
+ for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
+ if (!(v->uv_flags & VIFF_DISABLED)) {
+ if (!(v->uv_flags & VIFF_DOWN)) {
+ if (v->uv_flags & VIFF_TUNNEL)
+ log(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi,
+ inet_fmt(v->uv_lcl_addr, s1),
+ inet_fmt(v->uv_rmt_addr, s2));
+ else
+ log(LOG_INFO, 0, "vif #%d, phyint %s", vifi,
+ inet_fmt(v->uv_lcl_addr, s1));
+ k_add_vif(vifi, &uvifs[vifi]);
+ } else log(LOG_INFO, 0,
+ "%s is not yet up; vif #%u not in service",
+ v->uv_name, vifi);
+ }
+ }
+}
/*
* See if any interfaces have changed from up state to down, or vice versa,
@@ -211,12 +237,28 @@ send_probe_on_vif(v)
}
/*
- * Start routing on the specified virtual interface.
+ * Add a vifi to the kernel and start routing on it.
*/
static void
start_vif(vifi)
vifi_t vifi;
{
+ /*
+ * Install the interface in the kernel's vif structure.
+ */
+ k_add_vif(vifi, &uvifs[vifi]);
+
+ start_vif2(vifi);
+}
+
+/*
+ * Add a vifi to all the user-level data structures but don't add
+ * it to the kernel yet.
+ */
+static void
+start_vif2(vifi)
+ vifi_t vifi;
+{
struct uvif *v;
u_int32 src;
struct phaddr *p;
@@ -225,11 +267,6 @@ start_vif(vifi)
src = v->uv_lcl_addr;
/*
- * Install the interface in the kernel's vif structure.
- */
- k_add_vif(vifi, &uvifs[vifi]);
-
- /*
* Update the existing route entries to take into account the new vif.
*/
add_vif_to_routes(vifi);
@@ -269,7 +306,8 @@ start_vif(vifi)
*/
v->uv_flags |= VIFF_QUERIER;
send_igmp(src, allhosts_group, IGMP_HOST_MEMBERSHIP_QUERY,
- IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0);
+ (v->uv_flags & VIFF_IGMPV1) ? 0 :
+ IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0);
age_old_hosts();
}
@@ -428,16 +466,15 @@ age_old_hosts()
register vifi_t vifi;
register struct uvif *v;
register struct listaddr *g;
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
- /* -*- increment the time since an old report was heard */
- for (g = v->uv_groups; g != NULL; g = g->al_next) {
- g->al_last ++;
- if (g->al_last >= OLD_AGE_THRESHOLD){
- g->al_old = 0;
- g->al_last = OLD_AGE_THRESHOLD;
- }
- }
- }
+
+ /*
+ * Decrement the old-hosts-present timer for each
+ * active group on each vif.
+ */
+ for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++)
+ for (g = v->uv_groups; g != NULL; g = g->al_next)
+ if (g->al_old)
+ g->al_old--;
}
@@ -454,6 +491,7 @@ query_groups()
if (v->uv_flags & VIFF_QUERIER) {
send_igmp(v->uv_lcl_addr, allhosts_group,
IGMP_HOST_MEMBERSHIP_QUERY,
+ (v->uv_flags & VIFF_IGMPV1) ? 0 :
IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0);
}
}
@@ -481,16 +519,19 @@ accept_membership_query(src, dst, group, tmo)
v = &uvifs[vifi];
- /* If we consider ourselves the querier for this vif, but hear a
+ /*
+ * If we consider ourselves the querier for this vif, but hear a
* query from a router with a lower IP address, yield to them.
*
* This is done here as well as in the neighbor discovery in case
* there is a querier that doesn't speak DVMRP.
+ *
+ * XXX If this neighbor doesn't speak DVMRP, then we need to create
+ * some neighbor state for him so that we can time him out!
*/
if ((v->uv_flags & VIFF_QUERIER) &&
(ntohl(src) < ntohl(v->uv_lcl_addr))) {
-
- v->uv_flags &= ~VIFF_QUERIER;
+ v->uv_flags &= ~VIFF_QUERIER;
}
}
@@ -522,17 +563,14 @@ accept_group_report(src, dst, group, r_type)
*/
for (g = v->uv_groups; g != NULL; g = g->al_next) {
if (group == g->al_addr) {
- if (r_type == IGMP_HOST_NEW_MEMBERSHIP_REPORT) {
- g->al_last = OLD_AGE_THRESHOLD;
- g->al_old = 0;
- }
- else {
- g->al_last = 0;
- g->al_old = 1;
- }
-
- /** delete old timer set a timer for expiration **/
- g->al_timer= GROUP_EXPIRE_TIME;
+ if (r_type == IGMP_HOST_MEMBERSHIP_REPORT)
+ g->al_old = OLD_AGE_THRESHOLD;
+#ifdef SNMP
+ g->al_genid = src;
+#endif /* SNMP */
+
+ /** delete old timers, set a timer for expiration **/
+ g->al_timer = GROUP_EXPIRE_TIME;
if (g->al_query)
g->al_query = DeleteTimer(g->al_query);
if (g->al_timerid)
@@ -551,14 +589,13 @@ accept_group_report(src, dst, group, r_type)
log(LOG_ERR, 0, "ran out of memory"); /* fatal */
g->al_addr = group;
- if (r_type == IGMP_HOST_NEW_MEMBERSHIP_REPORT) {
- g->al_last = OLD_AGE_THRESHOLD;
+ if (r_type == IGMP_HOST_NEW_MEMBERSHIP_REPORT)
g->al_old = 0;
- }
- else {
- g->al_last = 0;
- g->al_old = 1;
- }
+ else
+ g->al_old = OLD_AGE_THRESHOLD;
+#ifdef SNMP
+ g->al_genid = src;
+#endif
/** set a timer for expiration **/
g->al_query = 0;
@@ -596,7 +633,7 @@ accept_leave_message(src, dst, group)
v = &uvifs[vifi];
- if (!(v->uv_flags & VIFF_QUERIER))
+ if (!(v->uv_flags & VIFF_QUERIER) || (v->uv_flags & VIFF_IGMPV1))
return;
/*
@@ -857,6 +894,68 @@ accept_neighbor_request2(src, dst)
datalen);
}
+void
+accept_info_request(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+ u_char *q;
+ int len;
+ int outlen = 0;
+
+ q = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
+
+ /* To be general, this must deal properly with breaking up over-sized
+ * packets. That implies passing a length to each function, and
+ * allowing each function to request to be called again. Right now,
+ * we're only implementing the one thing we are positive will fit into
+ * a single packet, so we wimp out.
+ */
+ while (datalen > 0) {
+ len = 0;
+ switch (*p) {
+ case DVMRP_INFO_VERSION:
+ len = info_version(q);
+ break;
+
+ case DVMRP_INFO_NEIGHBORS:
+ default:
+ log(LOG_INFO, 0, "ignoring unknown info type %d", *p);
+ break;
+ }
+ *(q+1) = len++;
+ outlen += len * 4;
+ q += len * 4;
+ len = (*(p+1) + 1) * 4;
+ p += len;
+ datalen -= len;
+ }
+
+ if (outlen != 0)
+ send_igmp(INADDR_ANY, src, IGMP_DVMRP, DVMRP_INFO_REPLY,
+ htonl(MROUTED_LEVEL), outlen);
+}
+
+/*
+ * Information response -- return version string
+ */
+static int
+info_version(p)
+ char *p;
+{
+ int len;
+ extern char versionstring[];
+
+ *p++ = DVMRP_INFO_VERSION;
+ p++; /* skip over length */
+ *p++ = 0; /* zero out */
+ *p++ = 0; /* reserved fields */
+ strcpy(p, versionstring); /* XXX strncpy!!! */
+
+ len = strlen(versionstring);
+ return ((len + 3) / 4);
+}
/*
* Process an incoming neighbor-list message.
@@ -885,6 +984,19 @@ accept_neighbors2(src, dst, p, datalen, level)
inet_fmt(src, s1), inet_fmt(dst, s2));
}
+/*
+ * Process an incoming info reply message.
+ */
+void
+accept_info_reply(src, dst, p, datalen)
+ u_int32 src, dst;
+ u_char *p;
+ int datalen;
+{
+ log(LOG_INFO, 0, "ignoring spurious DVMRP info reply from %s to %s",
+ inet_fmt(src, s1), inet_fmt(dst, s2));
+}
+
/*
* Update the neighbor entry for neighbor 'addr' on vif 'vifi'.
@@ -1215,6 +1327,7 @@ dump_vifs(fp)
if (v->uv_flags & VIFF_QUERIER) fprintf(fp, " querier");
if (v->uv_flags & VIFF_SRCRT) fprintf(fp, " src-rt");
if (v->uv_flags & VIFF_LEAF) fprintf(fp, " leaf");
+ if (v->uv_flags & VIFF_IGMPV1) fprintf(fp, " IGMPv1");
fprintf(fp, "\n");
if (v->uv_addrs != NULL) {
@@ -1272,80 +1385,98 @@ dump_vifs(fp)
fprintf(fp, "\n");
}
-
-/**** the timeout routines ********/
-
+/*
+ * Time out record of a group membership on a vif
+ */
static void
-DelVif(cbk)
-cbk_t *cbk;
+DelVif(arg)
+ void *arg;
{
- /* -*- make the list consistent */
- register vifi_t vifi = cbk->vifi;
- register struct uvif *v;
- register struct listaddr *a, *prev_a, *g = cbk->g;
-
- v = &uvifs[vifi];
+ cbk_t *cbk = (cbk_t *)arg;
+ vifi_t vifi = cbk->vifi;
+ struct uvif *v = &uvifs[vifi];
+ struct listaddr *a, **anp, *g = cbk->g;
- for (prev_a = (struct listaddr *)&(v->uv_groups),
- a = v->uv_groups;
- a != NULL;
- prev_a = a, a = a->al_next) {
-
- if (a != g) continue;
+ /*
+ * Group has expired
+ * delete all kernel cache entries with this group
+ */
+ if (g->al_query)
+ DeleteTimer(g->al_query);
- /*
- * Group has expired
- * delete all kernel cache entries with this group
- */
- if (g->al_query) DeleteTimer(g->al_query);
- delete_lclgrp(vifi, a->al_addr);
+ delete_lclgrp(vifi, g->al_addr);
- prev_a->al_next = a->al_next;
- free((char *)a);
- a = prev_a;
- }
+ anp = &(v->uv_groups);
+ while ((a = *anp) != NULL) {
+ if (a == g) {
+ *anp = a->al_next;
+ free((char *)a);
+ } else {
+ anp = &a->al_next;
+ }
+ }
- free(cbk);
+ free(cbk);
}
+/*
+ * Set a timer to delete the record of a group membership on a vif.
+ */
static int
SetTimer(vifi, g)
- vifi_t vifi; struct listaddr *g;
+ vifi_t vifi;
+ struct listaddr *g;
{
- cbk = (cbk_t *) malloc(sizeof(cbk_t));
- cbk->g = g;
- cbk->vifi = vifi;
- return timer_setTimer(g->al_timer, (cfunc_t)DelVif, (void *)cbk);
+ cbk_t *cbk;
+
+ cbk = (cbk_t *) malloc(sizeof(cbk_t));
+ cbk->g = g;
+ cbk->vifi = vifi;
+ return timer_setTimer(g->al_timer, (cfunc_t)DelVif, (void *)cbk);
}
+/*
+ * Delete a timer that was set above.
+ */
static int
DeleteTimer(id)
-int id;
+ int id;
{
- timer_clearTimer(id);
- return 0;
+ timer_clearTimer(id);
+ return 0;
}
+/*
+ * Send a group-specific query.
+ */
static void
-SendQuery(cbk)
-cbk_t *cbk;
+SendQuery(arg)
+ void *arg;
{
- register struct uvif *v = &uvifs[cbk->vifi];
-
- send_igmp(v->uv_lcl_addr, cbk->g->al_addr,
- IGMP_HOST_MEMBERSHIP_QUERY,
- cbk->q_time, 0, 0);
- cbk->g->al_query = 0;
- free(cbk);
+ cbk_t *cbk = (cbk_t *)arg;
+ register struct uvif *v = &uvifs[cbk->vifi];
+
+ send_igmp(v->uv_lcl_addr, cbk->g->al_addr,
+ IGMP_HOST_MEMBERSHIP_QUERY,
+ cbk->q_time, cbk->g->al_addr, 0);
+ cbk->g->al_query = 0;
+ free(cbk);
}
+/*
+ * Set a timer to send a group-specific query.
+ */
static int
-SetQueryTimer(g , vifi, to_expire, q_time)
- struct listaddr *g; vifi_t vifi;
- int to_expire, q_time;
+SetQueryTimer(g, vifi, to_expire, q_time)
+ struct listaddr *g;
+ vifi_t vifi;
+ int to_expire, q_time;
{
- cbk = (cbk_t *) malloc(sizeof(cbk_t));
- cbk->g = g;
- cbk->q_time = q_time; cbk-> vifi = vifi;
- return timer_setTimer(to_expire, (cfunc_t)SendQuery, (void *)cbk);
+ cbk_t *cbk;
+
+ cbk = (cbk_t *) malloc(sizeof(cbk_t));
+ cbk->g = g;
+ cbk->q_time = q_time;
+ cbk->vifi = vifi;
+ return timer_setTimer(to_expire, (cfunc_t)SendQuery, (void *)cbk);
}
diff --git a/usr.sbin/mrouted/vif.h b/usr.sbin/mrouted/vif.h
index 57c1c8f14526..94f5f7a9ee7b 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.6 1995/06/25 19:53:22 fenner Exp $
+ * $Id: vif.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
*/
/*
@@ -41,6 +41,7 @@ struct uvif {
#define VIFF_QUERIER 0x0400 /* I am the subnet's querier */
#define VIFF_ONEWAY 0x0800 /* Maybe one way interface */
#define VIFF_LEAF 0x1000 /* all neighbors are leaves */
+#define VIFF_IGMPV1 0x2000 /* Act as an IGMPv1 Router */
struct phaddr {
struct phaddr *pa_next;
@@ -65,8 +66,7 @@ struct listaddr {
u_char al_mv; /* router mrouted version */
u_long al_timerid; /* returned by set timer */
u_long al_query; /* second query in case of leave */
- u_short al_old; /* if old memberships are present */
- u_short al_last; /* # of query's since last old rep */
+ u_short al_old; /* time since heard old report */
u_char al_flags; /* flags related to this neighbor */
};