A number of bug fixes to mrouted (no functionality enhancements from 3.5, just
the fixes!): o Scoped addresses might let traffic in o IGMP queries sent with wrong timeouts o Possible core dump in mtrace if we get a request for which we have no route o If a member on a transit network left a group, mrouted would stop forwarding even if there was a downstream router o Various code cleanups and logging changes Reviewed by: wollman Submitted by: Bill Fenner <fenner@parc.xerox.com>
This commit is contained in:
parent
e472db9bf5
commit
87a603cb4d
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: callout.c,v 1.1 1994/08/24 23:52:49 thyagara Exp $
|
||||
* $Id: callout.c,v 1.2 1994/09/08 02:51:11 wollman Exp $
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
@ -29,7 +29,9 @@ struct timeout_q {
|
||||
};
|
||||
|
||||
|
||||
callout_init()
|
||||
static void print_Q();
|
||||
|
||||
void callout_init()
|
||||
{
|
||||
Q = (struct timeout_q *) 0;
|
||||
}
|
||||
@ -38,7 +40,7 @@ callout_init()
|
||||
/*
|
||||
* signal handler for SIGALARM that is called once every second
|
||||
*/
|
||||
age_callout_queue()
|
||||
void age_callout_queue()
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
|
||||
@ -82,7 +84,7 @@ int timer_setTimer(delay, action, data)
|
||||
struct timeout_q *ptr, *node, *prev;
|
||||
|
||||
if (in_callout)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
in_callout = 1;
|
||||
|
||||
@ -189,11 +191,11 @@ void timer_clearTimer( id)
|
||||
/*
|
||||
* debugging utility
|
||||
*/
|
||||
print_Q()
|
||||
static void print_Q()
|
||||
{
|
||||
#ifdef IGMP_DEBUG
|
||||
struct timeout_q *ptr;
|
||||
|
||||
#ifdef IGMP_DEBUG
|
||||
for(ptr = Q; ptr; ptr = ptr->next)
|
||||
log(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time);
|
||||
#endif IGMP_DEBUG
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: defs.h,v 1.8 1994/08/24 23:53:23 thyagara Exp $
|
||||
* $Id: defs.h,v 1.2 1994/09/08 02:51:13 wollman Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
#define PROTOCOL_VERSION 3 /* increment when packet format/content changes */
|
||||
|
||||
#define MROUTED_VERSION 3 /* increment on local changes or bug fixes, */
|
||||
#define MROUTED_VERSION 4 /* increment on local changes or bug fixes, */
|
||||
/* reset to 0 whever PROTOCOL_VERSION increments */
|
||||
|
||||
#define MROUTED_LEVEL ( (MROUTED_VERSION << 8) | PROTOCOL_VERSION )
|
||||
|
@ -109,7 +109,6 @@ static char *packet_kind(type, code)
|
||||
void accept_igmp(recvlen)
|
||||
int recvlen;
|
||||
{
|
||||
register vifi_t vifi;
|
||||
register u_long src, dst, group;
|
||||
struct ip *ip;
|
||||
struct igmp *igmp;
|
||||
@ -131,7 +130,7 @@ void accept_igmp(recvlen)
|
||||
* necessary to install a route into the kernel for this.
|
||||
*/
|
||||
if (ip->ip_p == 0) {
|
||||
if (src == NULL || dst == NULL)
|
||||
if (src == 0 || dst == 0)
|
||||
log(LOG_WARNING, 0, "kernel request not accurate");
|
||||
else
|
||||
add_table_entry(src, dst);
|
||||
@ -280,8 +279,12 @@ void send_igmp(src, dst, type, code, group, datalen)
|
||||
sdst.sin_addr.s_addr = dst;
|
||||
if (sendto(igmp_socket, send_buf, ip->ip_len, 0,
|
||||
(struct sockaddr *)&sdst, sizeof(sdst)) < 0) {
|
||||
if (errno == ENETDOWN) check_vif_state();
|
||||
else log(LOG_WARNING, errno, "sendto on %s", inet_fmt(src, s1));
|
||||
if (errno == ENETDOWN)
|
||||
check_vif_state();
|
||||
else
|
||||
log(LOG_WARNING, errno,
|
||||
"sendto to %s on %s",
|
||||
inet_fmt(dst, s1), inet_fmt(src, s2));
|
||||
}
|
||||
|
||||
if (dst == allhosts_group) k_set_loop(FALSE);
|
||||
|
@ -61,7 +61,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Id: mrinfo.c,v 1.7 1994/08/24 23:54:04 thyagara Exp $";
|
||||
"@(#) $Id: mrinfo.c,v 1.2 1994/09/08 02:51:20 wollman Exp $";
|
||||
/* original rcsid:
|
||||
"@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)";
|
||||
*/
|
||||
@ -277,7 +277,7 @@ host_addr(name)
|
||||
}
|
||||
|
||||
|
||||
main(argc, argv)
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
@ -389,6 +389,8 @@ usage: fprintf(stderr,
|
||||
continue;
|
||||
}
|
||||
ip = (struct ip *) recv_buf;
|
||||
if (ip->ip_p == 0)
|
||||
continue; /* Request to install cache entry */
|
||||
src = ip->ip_src.s_addr;
|
||||
if (src != target_addr) {
|
||||
fprintf(stderr, "mrinfo: got reply from %s",
|
||||
@ -418,6 +420,21 @@ usage: fprintf(stderr,
|
||||
if (igmp->igmp_type != IGMP_DVMRP)
|
||||
continue;
|
||||
|
||||
switch (igmp->igmp_code) {
|
||||
case DVMRP_NEIGHBORS:
|
||||
case DVMRP_NEIGHBORS2:
|
||||
if (src != target_addr) {
|
||||
fprintf(stderr, "mrinfo: got reply from %s",
|
||||
inet_fmt(src, s1));
|
||||
fprintf(stderr, " instead of %s\n",
|
||||
inet_fmt(target_addr, s1));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
continue; /* ignore all other DVMRP messages */
|
||||
}
|
||||
|
||||
switch (igmp->igmp_code) {
|
||||
|
||||
case DVMRP_NEIGHBORS:
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "defs.h"
|
||||
|
||||
#define DEFAULT_TIMEOUT 10 /* How long to wait before retrying requests */
|
||||
#define JAN_1970 2208988800 /* 1970 - 1900 in seconds */
|
||||
|
||||
int timeout = DEFAULT_TIMEOUT;
|
||||
|
||||
@ -77,30 +78,12 @@ flag_type(type)
|
||||
}
|
||||
|
||||
int
|
||||
t_diff(a_sec, a_usec, b_sec, b_usec)
|
||||
u_long a_sec, a_usec, b_sec, b_usec;
|
||||
t_diff(a, b)
|
||||
u_long a, b;
|
||||
{
|
||||
int d = a_sec - b_sec;
|
||||
int ms = a_usec - b_usec;
|
||||
int d = a - b;
|
||||
|
||||
if ((d < 0) ||
|
||||
((d == 0) && (ms < 0))) {
|
||||
d = b_sec - a_sec;
|
||||
ms = b_usec - a_usec;
|
||||
}
|
||||
|
||||
switch (d) {
|
||||
case 0:
|
||||
break;
|
||||
case 2:
|
||||
ms += 1000000;
|
||||
case 1:
|
||||
ms += 1000000;
|
||||
break;
|
||||
default:
|
||||
ms += (1000000) * d;
|
||||
}
|
||||
return (ms/1000);
|
||||
return ((d * 125) >> 13);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
@ -109,7 +92,7 @@ char *argv[];
|
||||
{
|
||||
struct timeval tq;
|
||||
struct timezone tzp;
|
||||
u_long resptime;
|
||||
u_long querytime, resptime;
|
||||
|
||||
int udp;
|
||||
struct sockaddr_in addr;
|
||||
@ -136,8 +119,15 @@ char *argv[];
|
||||
int i;
|
||||
int done = 0;
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "must be root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
argv++, argc--;
|
||||
|
||||
if (argc == 0) goto usage;
|
||||
|
||||
while (argc > 0 && *argv[0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
case 's':
|
||||
@ -260,6 +250,7 @@ usage: printf("usage: mtrace -s <src> -g <grp> -d <dst> -n <# reports> \n");
|
||||
* set timer to calculate delays & send query
|
||||
*/
|
||||
gettimeofday(&tq, &tzp);
|
||||
querytime = ((tq.tv_sec + JAN_1970) << 16) + (tq.tv_usec << 10) / 15625;
|
||||
|
||||
send_igmp(lcl_addr, dst, IGMP_MTRACE, qno,
|
||||
qgrp, datalen);
|
||||
@ -278,7 +269,7 @@ usage: printf("usage: mtrace -s <src> -g <grp> -d <dst> -n <# reports> \n");
|
||||
struct timezone tzp;
|
||||
|
||||
int count, recvlen, dummy = 0;
|
||||
register u_long src, dst, group, smask;
|
||||
register u_long src, group, smask;
|
||||
struct ip *ip;
|
||||
struct igmp *igmp;
|
||||
struct tr_resp *resp;
|
||||
@ -303,6 +294,9 @@ usage: printf("usage: mtrace -s <src> -g <grp> -d <dst> -n <# reports> \n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gettimeofday(&tq, &tzp);
|
||||
resptime = ((tq.tv_sec + JAN_1970) << 16) + (tq.tv_usec << 10) / 15625;
|
||||
|
||||
recvlen = recvfrom(igmp_socket, recv_buf, sizeof(recv_buf),
|
||||
0, NULL, &dummy);
|
||||
|
||||
@ -366,8 +360,9 @@ usage: printf("usage: mtrace -s <src> -g <grp> -d <dst> -n <# reports> \n");
|
||||
/*
|
||||
* print the responses out in reverse order (from src to dst)
|
||||
*/
|
||||
printf("src: <%s> grp: <%s> dst: <%s>\n\n", inet_fmt(qsrc, s1),
|
||||
inet_fmt(qgrp, s2), inet_fmt(qdst, s3));
|
||||
printf("src: <%s> grp: <%s> dst: <%s> rtt: %d ms\n\n",
|
||||
inet_fmt(qsrc, s1), inet_fmt(qgrp, s2), inet_fmt(qdst, s3),
|
||||
t_diff(resptime, querytime));
|
||||
|
||||
VAL_TO_MASK(smask, (resp+rno-1)->tr_smask);
|
||||
|
||||
@ -376,19 +371,14 @@ usage: printf("usage: mtrace -s <src> -g <grp> -d <dst> -n <# reports> \n");
|
||||
else
|
||||
printf(" * * *\n");
|
||||
|
||||
resptime = 0;
|
||||
while (rno--) {
|
||||
struct tr_resp *r = resp + rno;
|
||||
|
||||
printf(" | \n");
|
||||
printf(" %-15s ", inet_fmt(r->tr_inaddr, s1));
|
||||
printf("ttl %d ", r->tr_fttl);
|
||||
printf("cum: %d ms ",
|
||||
t_diff(r->tr_qarr >> 16, (r->tr_qarr & 0xffff) << 4,
|
||||
tq.tv_sec & 0xffff, tq.tv_usec));
|
||||
printf("hop: %d ms ",
|
||||
t_diff(resptime >> 16, (resptime & 0xffff) << 4,
|
||||
r->tr_qarr >> 16, (r->tr_qarr & 0xffff) << 4));
|
||||
printf("cum: %d ms ", t_diff(r->tr_qarr, querytime));
|
||||
printf("hop: %d ms ", t_diff(resptime, r->tr_qarr));
|
||||
printf("%s ", proto_type(r->tr_rproto));
|
||||
printf("%s\n", flag_type(r->tr_rflags));
|
||||
|
||||
|
@ -7,12 +7,14 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: prune.c,v 1.2 1994/09/08 02:51:23 wollman Exp $
|
||||
* $Id: prune.c,v 1.3 1995/03/16 16:25:55 wollman Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#define JAN_1970 2208988800 /* 1970 - 1900 in seconds */
|
||||
|
||||
extern int cache_lifetime;
|
||||
extern int max_prune_lifetime;
|
||||
|
||||
@ -81,7 +83,7 @@ void prun_add_ttls(kt)
|
||||
if (VIFM_ISSET(vifi, kt->kt_grpmems))
|
||||
kt->kt_ttls[vifi] = v->uv_threshold;
|
||||
else
|
||||
kt->kt_ttls[vifi] = NULL;
|
||||
kt->kt_ttls[vifi] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,8 +181,10 @@ void add_table_entry(origin, mcastgrp)
|
||||
VIFM_SET(i, kt->kt_grpmems);
|
||||
}
|
||||
GET_SCOPE(kt);
|
||||
if (VIFM_ISSET(kt->kt_parent, kt->kt_scope))
|
||||
kt->kt_grpmems = NULL;
|
||||
if (VIFM_ISSET(kt->kt_parent, kt->kt_scope)) {
|
||||
kt->kt_grpmems = 0;
|
||||
kt->kt_scope = -1; /* make sure we don't forward */
|
||||
}
|
||||
else
|
||||
kt->kt_grpmems &= ~kt->kt_scope;
|
||||
}
|
||||
@ -193,8 +197,10 @@ void add_table_entry(origin, mcastgrp)
|
||||
prun_add_ttls(kt);
|
||||
k_add_rg(kt);
|
||||
|
||||
log(LOG_DEBUG, 0, "add entry s:%x g:%x gm:%x",
|
||||
kt->kt_origin, kt->kt_mcastgrp, kt->kt_grpmems);
|
||||
log(LOG_DEBUG, 0, "add entry (%s %s) vif-list:%x",
|
||||
inet_fmt(kt->kt_origin, s1),
|
||||
inet_fmt(kt->kt_mcastgrp, s2),
|
||||
kt->kt_grpmems);
|
||||
|
||||
/* If there are no leaf vifs
|
||||
* which have this group, then
|
||||
@ -285,7 +291,6 @@ void del_table_entry(r, mcastgrp, del_flag)
|
||||
u_long mcastgrp;
|
||||
u_int del_flag;
|
||||
{
|
||||
struct mfcctl mc;
|
||||
struct ktable *kt, *prev_kt;
|
||||
struct prunlst *krl;
|
||||
|
||||
@ -294,8 +299,8 @@ void del_table_entry(r, mcastgrp, del_flag)
|
||||
kt = prev_kt->kt_next;
|
||||
prev_kt = kt) {
|
||||
if ((kt->kt_origin & r->rt_originmask) == r->rt_origin) {
|
||||
log(LOG_DEBUG, 0, "delete all rtes %x grp %x",
|
||||
kt->kt_origin, mcastgrp);
|
||||
log(LOG_DEBUG, 0, "delete all rtes %s",
|
||||
inet_fmt(kt->kt_origin, s1));
|
||||
|
||||
k_del_rg(kt);
|
||||
|
||||
@ -321,8 +326,8 @@ void del_table_entry(r, mcastgrp, del_flag)
|
||||
prev_kt = kt) {
|
||||
if ((kt->kt_origin & r->rt_originmask) == r->rt_origin &&
|
||||
kt->kt_mcastgrp == mcastgrp) {
|
||||
log(LOG_DEBUG, 0, "delete src %x grp %x",
|
||||
kt->kt_origin, mcastgrp);
|
||||
log(LOG_DEBUG, 0, "delete (%s, %s)",
|
||||
inet_fmt(kt->kt_origin, s1), inet_fmt(mcastgrp, s2));
|
||||
|
||||
k_del_rg(kt);
|
||||
|
||||
@ -359,17 +364,18 @@ void update_table_entry(r)
|
||||
changed = 0;
|
||||
|
||||
if (kt->kt_leaves != r->rt_leaves)
|
||||
changed++;
|
||||
changed |= 0x1;
|
||||
if (kt->kt_children != r->rt_children)
|
||||
changed++;
|
||||
changed |= 0x2;
|
||||
if (kt->kt_parent != r->rt_parent)
|
||||
changed++;
|
||||
changed |= 0x4;
|
||||
|
||||
if (!changed)
|
||||
continue;
|
||||
|
||||
log(LOG_DEBUG, 0, "update entry: s %-15s g %-15s",
|
||||
inet_fmt(kt->kt_origin, s1), inet_fmt(kt->kt_mcastgrp, s2));
|
||||
log(LOG_DEBUG, 0, "updating entry: (%s %s) code:%x",
|
||||
inet_fmt(kt->kt_origin, s1),
|
||||
inet_fmt(kt->kt_mcastgrp, s2), changed);
|
||||
|
||||
/* free prun list entries */
|
||||
while (kt->kt_rlist) {
|
||||
@ -394,8 +400,10 @@ void update_table_entry(r)
|
||||
if (VIFM_ISSET(i, kt->kt_leaves) && grplst_mem(i, kt->kt_mcastgrp))
|
||||
VIFM_SET(i, kt->kt_grpmems);
|
||||
}
|
||||
if (VIFM_ISSET(kt->kt_parent, kt->kt_scope))
|
||||
kt->kt_grpmems = NULL;
|
||||
if (VIFM_ISSET(kt->kt_parent, kt->kt_scope)) {
|
||||
kt->kt_grpmems = 0;
|
||||
kt->kt_scope = -1;
|
||||
}
|
||||
else
|
||||
kt->kt_grpmems &= ~kt->kt_scope;
|
||||
|
||||
@ -427,13 +435,14 @@ void update_lclgrp(vifi, mcastgrp)
|
||||
{
|
||||
struct ktable *kt;
|
||||
|
||||
log(LOG_DEBUG, 0, "group %x joined at vif %d", mcastgrp, vifi);
|
||||
log(LOG_DEBUG, 0, "group %s joined at vif %d",
|
||||
inet_fmt(mcastgrp, s1), vifi);
|
||||
|
||||
for (kt = kernel_rtable; kt; kt = kt->kt_next)
|
||||
if (kt->kt_mcastgrp == mcastgrp && VIFM_ISSET(vifi, kt->kt_children)) {
|
||||
VIFM_SET(vifi, kt->kt_grpmems);
|
||||
kt->kt_grpmems &= ~kt->kt_scope;
|
||||
if (kt->kt_grpmems == NULL)
|
||||
if (kt->kt_grpmems == 0)
|
||||
continue;
|
||||
prun_add_ttls(kt);
|
||||
k_add_rg(kt);
|
||||
@ -447,23 +456,34 @@ void delete_lclgrp(vifi, mcastgrp)
|
||||
vifi_t vifi;
|
||||
u_long mcastgrp;
|
||||
{
|
||||
|
||||
struct ktable *kt;
|
||||
|
||||
log(LOG_DEBUG, 0, "group %x left at vif %d", mcastgrp, vifi);
|
||||
log(LOG_DEBUG, 0, "group %s left at vif %d",
|
||||
inet_fmt(mcastgrp, s1), vifi);
|
||||
|
||||
for (kt = kernel_rtable; kt; kt = kt->kt_next)
|
||||
if (kt->kt_mcastgrp == mcastgrp) {
|
||||
VIFM_CLR(vifi, kt->kt_grpmems);
|
||||
prun_add_ttls(kt);
|
||||
k_add_rg(kt);
|
||||
|
||||
/*
|
||||
* If there are no more members of this particular group,
|
||||
* send prune upstream
|
||||
*/
|
||||
if (kt->kt_grpmems == NULL && kt->kt_gateway)
|
||||
send_prune(kt);
|
||||
struct listaddr *vr;
|
||||
int stop_sending = 1;
|
||||
|
||||
for (vr = uvifs[vifi].uv_neighbors; vr; vr = vr->al_next)
|
||||
if (no_entry_exists(vr->al_addr, kt)) {
|
||||
stop_sending = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stop_sending) {
|
||||
VIFM_CLR(vifi, kt->kt_grpmems);
|
||||
prun_add_ttls(kt);
|
||||
k_add_rg(kt);
|
||||
|
||||
/*
|
||||
* If there are no more members of this particular group,
|
||||
* send prune upstream
|
||||
*/
|
||||
if (kt->kt_grpmems == NULL && kt->kt_gateway)
|
||||
send_prune(kt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,7 +590,6 @@ void accept_prune(src, dst, p, datalen)
|
||||
int stop_sending;
|
||||
struct ktable *kt;
|
||||
struct prunlst *pr_recv;
|
||||
struct prunlst *krl;
|
||||
struct listaddr *vr;
|
||||
|
||||
/* Don't process any prunes if router is not pruning */
|
||||
@ -579,16 +598,18 @@ void accept_prune(src, dst, p, datalen)
|
||||
|
||||
if ((vifi = find_vif(src, dst)) == NO_VIF) {
|
||||
log(LOG_INFO, 0,
|
||||
"ignoring prune report from non-neighbor %s", inet_fmt(src, s1));
|
||||
"ignoring prune report from non-neighbor %s",
|
||||
inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (datalen < 0 || datalen > 12)
|
||||
{
|
||||
log(LOG_WARNING, 0,
|
||||
"received non-decipherable prune report from %s", inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
/* Check if enough data is present */
|
||||
if (datalen < 12) {
|
||||
log(LOG_WARNING, 0,
|
||||
"non-decipherable prune from %s",
|
||||
inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i< 4; i++)
|
||||
((char *)&prun_src)[i] = *p++;
|
||||
@ -755,7 +776,7 @@ void chkgrp_graft(vifi, mcastgrp)
|
||||
* ignore it ; don't graft back
|
||||
*/
|
||||
kt->kt_grpmems &= ~kt->kt_scope;
|
||||
if (kt->kt_grpmems == NULL)
|
||||
if (kt->kt_grpmems == 0)
|
||||
continue;
|
||||
|
||||
/* set the flag for graft retransmission */
|
||||
@ -805,13 +826,15 @@ void accept_graft(src, dst, p, datalen)
|
||||
|
||||
if ((vifi = find_vif(src, dst)) == NO_VIF) {
|
||||
log(LOG_INFO, 0,
|
||||
"ignoring graft report from non-neighbor %s", inet_fmt(src, s1));
|
||||
"ignoring graft from non-neighbor %s",
|
||||
inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (datalen < 0 || datalen > 8) {
|
||||
if (datalen < 8) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received non-decipherable graft report from %s", inet_fmt(src, s1));
|
||||
"received non-decipherable graft from %s",
|
||||
inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -898,8 +921,10 @@ void send_graft_ack(kt, to)
|
||||
send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT_ACK,
|
||||
htonl(MROUTED_LEVEL), datalen);
|
||||
|
||||
log(LOG_DEBUG, 0, "send graft ack for src:%x, grp:%x to %x",
|
||||
kt->kt_origin, kt->kt_mcastgrp, dst);
|
||||
log(LOG_DEBUG, 0, "sent graft ack (%s, %s) to %s",
|
||||
inet_fmt(kt->kt_origin, s1), inet_fmt(kt->kt_mcastgrp, s2),
|
||||
inet_fmt(dst, s3));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -934,8 +959,9 @@ void send_graft(kt)
|
||||
send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT,
|
||||
htonl(MROUTED_LEVEL), datalen);
|
||||
}
|
||||
log(LOG_DEBUG, 0, "send graft for src:%x, grp:%x up to %x",
|
||||
kt->kt_origin, kt->kt_mcastgrp, kt->kt_gateway);
|
||||
log(LOG_DEBUG, 0, "sent graft (%s, %s) to %s",
|
||||
inet_fmt(kt->kt_origin, s1), inet_fmt(kt->kt_mcastgrp, s2),
|
||||
inet_fmt(kt->kt_gateway, s3));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -960,13 +986,15 @@ void accept_g_ack(src, dst, p, datalen)
|
||||
|
||||
if ((vifi = find_vif(src, dst)) == NO_VIF) {
|
||||
log(LOG_INFO, 0,
|
||||
"ignoring graft ack report from non-neighbor %s", inet_fmt(src, s1));
|
||||
"ignoring graft ack report from non-neighbor %s",
|
||||
inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (datalen < 0 || datalen > 8) {
|
||||
if (datalen < 8) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received non-decipherable graft ack report from %s", inet_fmt(src, s1));
|
||||
"received non-decipherable graft ack report from %s",
|
||||
inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1036,10 +1064,6 @@ void age_table_entry()
|
||||
/* advance the timer for the kernel entry */
|
||||
kt->kt_timer -= ROUTE_MAX_REPORT_DELAY;
|
||||
|
||||
/* decrement prune timer if need be */
|
||||
if (kt->kt_prsent_timer)
|
||||
kt->kt_prsent_timer -= ROUTE_MAX_REPORT_DELAY;
|
||||
|
||||
/* retransmit graft if graft sent flag is still set */
|
||||
if (kt->kt_grftsnt) {
|
||||
register int y;
|
||||
@ -1052,24 +1076,35 @@ void age_table_entry()
|
||||
routers
|
||||
|
||||
Now, if there are subordinate routers, then, what we
|
||||
have to do is to decrement each and every router's
|
||||
have to do is to decrement each and every router's prune
|
||||
time entry too and decide if we want to forward on
|
||||
that link basically
|
||||
*/
|
||||
for (prev_krl = (struct prunlst *)&kt->kt_rlist,
|
||||
krl = prev_krl->rl_next;
|
||||
krl;
|
||||
krl = prev_krl->rl_next; krl;
|
||||
prev_krl = krl, krl = krl->rl_next) {
|
||||
|
||||
/* decrement prune timer received from downstream routers */
|
||||
if ((krl->rl_timer -= ROUTE_MAX_REPORT_DELAY) <= 0) {
|
||||
log(LOG_DEBUG, 0, "forw again s %x g %x on vif %d",
|
||||
kt->kt_origin, kt->kt_mcastgrp, krl->rl_vifi);
|
||||
log(LOG_DEBUG, 0, "forw again (%s, %s) on vif %d",
|
||||
inet_fmt(kt->kt_origin, s1),
|
||||
inet_fmt(kt->kt_mcastgrp, s2),
|
||||
krl->rl_vifi);
|
||||
|
||||
/*
|
||||
* forwarding now, so entry is not pruned anymore
|
||||
* reset the cache timer to a largish value also
|
||||
*/
|
||||
kt->kt_prsent_timer = 0;
|
||||
|
||||
/* modify the kernel entry to forward packets */
|
||||
if (!VIFM_ISSET(krl->rl_vifi, kt->kt_grpmems)) {
|
||||
VIFM_SET(krl->rl_vifi, kt->kt_grpmems);
|
||||
prun_add_ttls(kt);
|
||||
k_add_rg(kt);
|
||||
}
|
||||
|
||||
/* remove the router's prune entry and await new one */
|
||||
kt->kt_prun_count--;
|
||||
prev_krl->rl_next = krl->rl_next;
|
||||
free((char *)krl);
|
||||
@ -1089,8 +1124,9 @@ void age_table_entry()
|
||||
kt->kt_timer = CACHE_LIFETIME(cache_lifetime);
|
||||
}
|
||||
else {
|
||||
log(LOG_DEBUG, 0, "age route s %x g %x",
|
||||
kt->kt_origin, kt->kt_mcastgrp);
|
||||
log(LOG_DEBUG, 0, "aging entry (%s, %s)",
|
||||
inet_fmt(kt->kt_origin, s1),
|
||||
inet_fmt(kt->kt_mcastgrp, s2));
|
||||
|
||||
k_del_rg(kt);
|
||||
prev_kt->kt_next = kt->kt_next;
|
||||
@ -1293,8 +1329,8 @@ void mtrace(src, dst, group, data, no, datalen)
|
||||
* fill in initial response fields
|
||||
*/
|
||||
resp = (struct tr_resp *)p;
|
||||
resp->tr_qarr = ((tp.tv_sec & 0xffff) << 16) +
|
||||
((tp.tv_usec >> 4) & 0xffff);
|
||||
resp->tr_qarr = ((tp.tv_sec + JAN_1970) << 16) +
|
||||
((tp.tv_usec << 10) / 15625);
|
||||
|
||||
resp->tr_vifin = 0; /* default values */
|
||||
resp->tr_pktcnt = 0; /* default values */
|
||||
@ -1333,9 +1369,9 @@ void mtrace(src, dst, group, data, no, datalen)
|
||||
*/
|
||||
if (rt == NULL) {
|
||||
src = dst; /* the dst address of resp. pkt */
|
||||
resp->tr_inaddr = NULL;
|
||||
resp->tr_inaddr = 0;
|
||||
resp->tr_rflags = TR_NO_RTE;
|
||||
resp->tr_rmtaddr = NULL;
|
||||
resp->tr_rmtaddr = 0;
|
||||
}
|
||||
else {
|
||||
/* get # of packets in on interface */
|
||||
@ -1360,14 +1396,14 @@ void mtrace(src, dst, group, data, no, datalen)
|
||||
*/
|
||||
printf("rcount:%d, no:%d\n", rcount, no);
|
||||
|
||||
if ((rcount + 1 == no) || (rt->rt_metric == 1))
|
||||
if ((rcount + 1 == no) || (rt == NULL) || (rt->rt_metric == 1))
|
||||
dst = qry->tr_raddr;
|
||||
else
|
||||
dst = rt->rt_gateway;
|
||||
|
||||
if (IN_MULTICAST(ntohl(dst))) {
|
||||
k_set_ttl(qry->tr_rttl);
|
||||
send_igmp(src, dst,
|
||||
send_igmp(INADDR_ANY, dst,
|
||||
IGMP_MTRACE_RESP, no, group,
|
||||
datalen + RLEN);
|
||||
k_set_ttl(1);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: vif.c,v 1.8 1994/08/24 23:54:45 thyagara Exp $
|
||||
* $Id: vif.c,v 1.2 1994/09/08 02:51:27 wollman Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ int udp_socket; /* Since the honkin' kernel doesn't support */
|
||||
*/
|
||||
static void start_vif();
|
||||
static void stop_vif();
|
||||
static void age_old_hosts();
|
||||
|
||||
/*
|
||||
* Initialize the virtual interfaces.
|
||||
@ -155,6 +156,7 @@ static void start_vif(vifi)
|
||||
/*
|
||||
* Install the interface in the kernel's vif structure.
|
||||
*/
|
||||
log(LOG_DEBUG, 0, "Installing vif %d in kernel\n", vifi);
|
||||
k_add_vif(vifi, &uvifs[vifi]);
|
||||
|
||||
/*
|
||||
@ -186,7 +188,7 @@ static void start_vif(vifi)
|
||||
*/
|
||||
v->uv_flags |= VIFF_QUERIER;
|
||||
send_igmp(src, allhosts_group, IGMP_HOST_MEMBERSHIP_QUERY,
|
||||
GROUP_EXPIRE_TIME * 10 / ROUTE_MAX_REPORT_DELAY, 0, 0);
|
||||
IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0);
|
||||
age_old_hosts();
|
||||
}
|
||||
|
||||
@ -335,7 +337,7 @@ vifi_t find_vif(src, dst)
|
||||
}
|
||||
|
||||
|
||||
age_old_hosts()
|
||||
static void age_old_hosts()
|
||||
{
|
||||
register vifi_t vifi;
|
||||
register struct uvif *v;
|
||||
@ -365,7 +367,7 @@ void query_groups()
|
||||
if (v->uv_flags & VIFF_QUERIER) {
|
||||
send_igmp(v->uv_lcl_addr, allhosts_group,
|
||||
IGMP_HOST_MEMBERSHIP_QUERY,
|
||||
GROUP_EXPIRE_TIME * 10 / ROUTE_MAX_REPORT_DELAY, 0, 0);
|
||||
IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0);
|
||||
}
|
||||
}
|
||||
age_old_hosts();
|
||||
@ -492,10 +494,10 @@ void leave_group_message( src, dst, group)
|
||||
g->al_timer = GROUP_EXPIRE_TIME / 10;
|
||||
send_igmp(v->uv_lcl_addr, g->al_addr,
|
||||
IGMP_HOST_MEMBERSHIP_QUERY,
|
||||
IGMP_MAX_HOST_REPORT_DELAY * 10 / (2*TIMER_INTERVAL),
|
||||
0, 0);
|
||||
GROUP_EXPIRE_TIME / 30 * IGMP_TIMER_SCALE,
|
||||
g->al_addr, 0);
|
||||
g->al_query = SetQueryTimer(g, vifi, g->al_timer / 3 ,
|
||||
IGMP_MAX_HOST_REPORT_DELAY / 2);
|
||||
GROUP_EXPIRE_TIME / 30 * IGMP_TIMER_SCALE);
|
||||
g->al_timerid = SetTimer(vifi, g);
|
||||
break;
|
||||
}
|
||||
@ -642,7 +644,7 @@ void accept_neighbor_request2(src, dst)
|
||||
u_char *p, *ncount;
|
||||
struct listaddr *la;
|
||||
int datalen;
|
||||
u_long temp_addr, us, them = src;
|
||||
u_long us, them = src;
|
||||
|
||||
/* Determine which of our addresses to use as the source of our response
|
||||
* to this query.
|
||||
@ -783,7 +785,7 @@ int update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
||||
{
|
||||
register struct uvif *v;
|
||||
register struct listaddr *n;
|
||||
u_long genid;
|
||||
u_long genid = 0;
|
||||
u_long router;
|
||||
int he_hears_me = TRUE;
|
||||
|
||||
@ -824,41 +826,48 @@ int update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
||||
* Need to reset the prune state of the router if not.
|
||||
*/
|
||||
if (msgtype == DVMRP_PROBE) {
|
||||
int i;
|
||||
|
||||
if (datalen < 4) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received truncated probe message from %s",
|
||||
inet_fmt(addr, s1));
|
||||
return;
|
||||
}
|
||||
/* if mrouted level > 3.2, analyze further */
|
||||
if ((level&0xff) > 3 ||
|
||||
(((level&0xff) == 3) && (((level>>8)&0xff) > 2))) {
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
((char *)&genid)[i] = *p++;
|
||||
datalen -=4;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* loop through router list and check for one-way ifs.
|
||||
*/
|
||||
|
||||
he_hears_me = FALSE;
|
||||
|
||||
while (datalen > 0) {
|
||||
if (datalen < 4) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received truncated probe message from %s",
|
||||
inet_fmt(addr, s1));
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
((char *)&router)[i] = *p++;
|
||||
datalen -= 4;
|
||||
if (router == v->uv_lcl_addr) {
|
||||
he_hears_me = TRUE;
|
||||
break;
|
||||
((char *)&genid)[i] = *p++;
|
||||
datalen -=4;
|
||||
|
||||
/*
|
||||
* loop through router list and check for one-way ifs.
|
||||
*/
|
||||
|
||||
he_hears_me = FALSE;
|
||||
|
||||
while (datalen > 0) {
|
||||
if (datalen < 4) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received truncated probe message from %s",
|
||||
inet_fmt(addr, s1));
|
||||
return (FALSE);
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
((char *)&router)[i] = *p++;
|
||||
datalen -= 4;
|
||||
if (router == v->uv_lcl_addr) {
|
||||
he_hears_me = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for addr in list of neighbors; if found, reset its timer.
|
||||
*/
|
||||
@ -882,14 +891,39 @@ int update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
||||
|
||||
reset_neighbor_state(vifi, addr);
|
||||
n->al_genid = genid;
|
||||
/* need to do a full route report here */
|
||||
break;
|
||||
}
|
||||
n->al_pv = level & 0xff;
|
||||
n->al_mv = (level >> 8) & 0xff;
|
||||
|
||||
/* recurring probe - so no need to do a route report */
|
||||
return FALSE;
|
||||
/*
|
||||
* need to do a full route report here
|
||||
* it gets done by accept_probe()
|
||||
*/
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* update the neighbors version and protocol number
|
||||
* if changed => router went down and came up,
|
||||
* so take action immediately.
|
||||
*/
|
||||
if ((n->al_pv != (level & 0xff)) ||
|
||||
((n->al_mv != (level >> 8)) & 0xff)) {
|
||||
log(LOG_DEBUG, 0,
|
||||
"resetting neighbor %s [old:%d.%d, new:%d.%d]",
|
||||
inet_fmt(addr, s1),
|
||||
n->al_pv, n->al_mv, level&0xff, (level>>8)&0xff);
|
||||
|
||||
n->al_pv = level & 0xff;
|
||||
n->al_mv = (level >> 8) & 0xff;
|
||||
|
||||
reset_neighbor_state(vifi, addr);
|
||||
}
|
||||
/* recurring probe - so no need to do a route report */
|
||||
if (msgtype == DVMRP_PROBE)
|
||||
return (FALSE);
|
||||
else
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1121,7 +1155,7 @@ cbk_t *cbk;
|
||||
register struct uvif *v = &uvifs[cbk->vifi];
|
||||
send_igmp(v->uv_lcl_addr, cbk->g->al_addr,
|
||||
IGMP_HOST_MEMBERSHIP_QUERY,
|
||||
cbk->q_time * 10 / TIMER_INTERVAL, 0, 0);
|
||||
cbk->q_time, 0, 0);
|
||||
cbk->g->al_query = 0;
|
||||
free(cbk);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user