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:
jkh 1995-05-16 00:28:50 +00:00
parent e472db9bf5
commit 87a603cb4d
7 changed files with 236 additions and 154 deletions

View File

@ -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

View File

@ -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 )

View File

@ -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);

View File

@ -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:

View File

@ -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));

View File

@ -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);

View File

@ -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);
}