mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
Upgrade to mrouted version 3.6. This includes a substantial clean-up
and ANSIfication of much of the source base. Thanks, Bill! Submitted by: patch from Bill Fenner <fenner@parc.xerox.com>
This commit is contained in:
parent
5575abefeb
commit
e93ad7be43
24 changed files with 1306 additions and 794 deletions
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: callout.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: callout.c,v 3.6 1995/06/25 18:47:29 fenner Exp $
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
|
@ -18,19 +18,22 @@ static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
|
|||
|
||||
static int in_callout= 0;
|
||||
|
||||
typedef void (* cfunc_t)();
|
||||
|
||||
struct timeout_q {
|
||||
struct timeout_q *next; /* next event */
|
||||
int id;
|
||||
cfunc_t func ; /* function to call */
|
||||
cfunc_t func; /* function to call */
|
||||
char *data; /* func's data */
|
||||
int time; /* time offset to next event*/
|
||||
};
|
||||
|
||||
static void print_Q();
|
||||
#ifdef IGMP_DEBUG
|
||||
static void print_Q __P((void));
|
||||
#else
|
||||
#define print_Q()
|
||||
#endif
|
||||
|
||||
void callout_init()
|
||||
void
|
||||
callout_init()
|
||||
{
|
||||
Q = (struct timeout_q *) 0;
|
||||
}
|
||||
|
|
@ -39,7 +42,8 @@ void callout_init()
|
|||
/*
|
||||
* signal handler for SIGALARM that is called once every second
|
||||
*/
|
||||
void age_callout_queue()
|
||||
void
|
||||
age_callout_queue()
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
|
||||
|
|
@ -52,7 +56,7 @@ void age_callout_queue()
|
|||
while (ptr){
|
||||
if (!ptr->time ) {
|
||||
/* timeout has happened */
|
||||
if(ptr->func)
|
||||
if (ptr->func)
|
||||
ptr->func(ptr->data);
|
||||
Q = Q->next;
|
||||
|
||||
|
|
@ -63,7 +67,7 @@ void age_callout_queue()
|
|||
ptr->time --;
|
||||
#ifdef IGMP_DEBUG
|
||||
log(LOG_DEBUG,0,"[callout, age_callout_queue] -- time (%d)", ptr->time);
|
||||
#endif IGMP_DEBUG
|
||||
#endif /* IGMP_DEBUG */
|
||||
in_callout = 0; return;
|
||||
}
|
||||
}
|
||||
|
|
@ -75,7 +79,8 @@ void age_callout_queue()
|
|||
/*
|
||||
* sets the timer
|
||||
*/
|
||||
int timer_setTimer(delay, action, data)
|
||||
int
|
||||
timer_setTimer(delay, action, data)
|
||||
int delay; /* number of units for timeout */
|
||||
cfunc_t action; /* function to be called on timeout */
|
||||
char *data; /* what to call the timeout function with */
|
||||
|
|
@ -88,7 +93,7 @@ int timer_setTimer(delay, action, data)
|
|||
in_callout = 1;
|
||||
|
||||
/* create a node */
|
||||
node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
|
||||
node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
|
||||
if (node == 0) {
|
||||
log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
|
||||
in_callout = 0;
|
||||
|
|
@ -109,9 +114,9 @@ int timer_setTimer(delay, action, data)
|
|||
Q = node;
|
||||
else {
|
||||
/* chase the pointer looking for the right place */
|
||||
while (ptr){
|
||||
while (ptr) {
|
||||
|
||||
if (delay < ptr->time){
|
||||
if (delay < ptr->time) {
|
||||
/* right place */
|
||||
|
||||
node->next = ptr;
|
||||
|
|
@ -123,8 +128,7 @@ int timer_setTimer(delay, action, data)
|
|||
print_Q();
|
||||
in_callout = 0;
|
||||
return node->id;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* keep moving */
|
||||
|
||||
delay -= ptr->time; node->time = delay;
|
||||
|
|
@ -141,17 +145,19 @@ int timer_setTimer(delay, action, data)
|
|||
|
||||
|
||||
/* clears the associated timer */
|
||||
void timer_clearTimer( timer_id)
|
||||
void
|
||||
timer_clearTimer(timer_id)
|
||||
int timer_id;
|
||||
{
|
||||
struct timeout_q *ptr, *prev;
|
||||
|
||||
if (in_callout) return;
|
||||
if (in_callout)
|
||||
return;
|
||||
if (!timer_id)
|
||||
return;
|
||||
|
||||
in_callout = 1;
|
||||
|
||||
|
||||
if ( !timer_id ) {in_callout = 0; return;}
|
||||
|
||||
prev = ptr = Q;
|
||||
|
||||
/*
|
||||
|
|
@ -160,12 +166,12 @@ void timer_clearTimer( timer_id)
|
|||
*/
|
||||
|
||||
print_Q();
|
||||
while (ptr){
|
||||
if (ptr->id == timer_id){
|
||||
while (ptr) {
|
||||
if (ptr->id == timer_id) {
|
||||
/* got the right node */
|
||||
|
||||
/* unlink it from the queue */
|
||||
if ( ptr == Q)
|
||||
if (ptr == Q)
|
||||
Q = Q->next;
|
||||
else
|
||||
prev->next = ptr->next;
|
||||
|
|
@ -187,16 +193,16 @@ void timer_clearTimer( timer_id)
|
|||
in_callout = 0;
|
||||
}
|
||||
|
||||
#ifdef IGMP_DEBUG
|
||||
/*
|
||||
* debugging utility
|
||||
*/
|
||||
static void print_Q()
|
||||
static void
|
||||
print_Q()
|
||||
{
|
||||
#ifdef IGMP_DEBUG
|
||||
struct timeout_q *ptr;
|
||||
|
||||
for(ptr = Q; ptr; ptr = ptr->next)
|
||||
log(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time);
|
||||
#endif IGMP_DEBUG
|
||||
}
|
||||
|
||||
#endif /* IGMP_DEBUG */
|
||||
|
|
|
|||
|
|
@ -4,12 +4,28 @@
|
|||
*
|
||||
* Written by Bill Fenner, NRL, 1994
|
||||
*
|
||||
* $Id: cfparse.y,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: cfparse.y,v 3.6 1995/06/25 18:49:46 fenner Exp $
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
* Local function declarations
|
||||
*/
|
||||
static void fatal __P((char *fmt, ...));
|
||||
static void warn __P((char *fmt, ...));
|
||||
static void yyerror __P((char *s));
|
||||
static char * next_word __P((void));
|
||||
static int yylex __P((void));
|
||||
static u_int32 valid_if __P((char *s));
|
||||
static struct ifreq * ifconfaddr __P((struct ifconf *ifcp, u_int32 a));
|
||||
int yyparse __P((void));
|
||||
|
||||
static FILE *f;
|
||||
|
||||
extern int udp_socket;
|
||||
|
|
@ -195,7 +211,17 @@ ifmods : /* empty */
|
|||
|
||||
ifmod : mod
|
||||
| DISABLE { v->uv_flags |= VIFF_DISABLED; }
|
||||
| NETMASK ADDR { v->uv_subnetmask = $2; }
|
||||
| NETMASK ADDR {
|
||||
u_int32 subnet, mask;
|
||||
|
||||
mask = $2;
|
||||
subnet = v->uv_lcl_addr & mask;
|
||||
if (!inet_valid_subnet(subnet, mask))
|
||||
fatal("Invalid netmask");
|
||||
v->uv_subnet = subnet;
|
||||
v->uv_subnetmask = mask;
|
||||
v->uv_subnetbcast = subnet | ~mask;
|
||||
}
|
||||
| ALTNET addrmask {
|
||||
|
||||
struct phaddr *ph;
|
||||
|
|
@ -204,12 +230,13 @@ ifmod : mod
|
|||
if (ph == NULL)
|
||||
fatal("out of memory");
|
||||
if ($2.mask) {
|
||||
VAL_TO_MASK(ph->pa_mask, $2.mask);
|
||||
VAL_TO_MASK(ph->pa_subnetmask, $2.mask);
|
||||
} else
|
||||
ph->pa_mask = v->uv_subnetmask;
|
||||
ph->pa_addr = $2.addr & ph->pa_mask;
|
||||
if ($2.addr & ~ph->pa_mask)
|
||||
warn("Extra addr %s/%d has host bits set",
|
||||
ph->pa_subnetmask = v->uv_subnetmask;
|
||||
ph->pa_subnet = $2.addr & ph->pa_subnetmask;
|
||||
ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask;
|
||||
if ($2.addr & ~ph->pa_subnetmask)
|
||||
warn("Extra subnet %s/%d has host bits set",
|
||||
inet_fmt($2.addr,s1), $2.mask);
|
||||
ph->pa_next = v->uv_addrs;
|
||||
v->uv_addrs = ph;
|
||||
|
|
@ -305,8 +332,18 @@ addrmask : ADDRMASK { $$ = $1; }
|
|||
| ADDR { $$.addr = $1; $$.mask = 0; }
|
||||
;
|
||||
%%
|
||||
#ifdef __STDC__
|
||||
static void
|
||||
fatal(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[200];
|
||||
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
/*VARARGS1*/
|
||||
static void fatal(fmt, va_alist)
|
||||
static void
|
||||
fatal(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
{
|
||||
|
|
@ -314,14 +351,25 @@ va_dcl
|
|||
char buf[200];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log(LOG_ERR,0,"%s: %s near line %d", configfilename, buf, lineno);
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
static void
|
||||
warn(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[200];
|
||||
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
/*VARARGS1*/
|
||||
static void warn(fmt, va_alist)
|
||||
static void
|
||||
warn(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
{
|
||||
|
|
@ -329,19 +377,22 @@ va_dcl
|
|||
char buf[200];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log(LOG_WARNING,0,"%s: %s near line %d", configfilename, buf, lineno);
|
||||
}
|
||||
|
||||
void yyerror(s)
|
||||
static void
|
||||
yyerror(s)
|
||||
char *s;
|
||||
{
|
||||
log(LOG_ERR, 0, "%s: %s near line %d", configfilename, s, lineno);
|
||||
}
|
||||
|
||||
char *next_word()
|
||||
static char *
|
||||
next_word()
|
||||
{
|
||||
static char buf[1024];
|
||||
static char *p=NULL;
|
||||
|
|
@ -375,7 +426,8 @@ char *next_word()
|
|||
}
|
||||
}
|
||||
|
||||
int yylex()
|
||||
static int
|
||||
yylex()
|
||||
{
|
||||
int n;
|
||||
u_int32 addr;
|
||||
|
|
@ -446,7 +498,8 @@ int yylex()
|
|||
return STRING;
|
||||
}
|
||||
|
||||
void config_vifs_from_file()
|
||||
void
|
||||
config_vifs_from_file()
|
||||
{
|
||||
extern FILE *f;
|
||||
|
||||
|
|
@ -467,7 +520,7 @@ void config_vifs_from_file()
|
|||
|
||||
yyparse();
|
||||
|
||||
close(f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static u_int32
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: config.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: config.c,v 3.6 1995/06/25 18:50:37 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -18,7 +18,8 @@
|
|||
* Query the kernel to find network interfaces that are multicast-capable
|
||||
* and install them in the uvifs array.
|
||||
*/
|
||||
void config_vifs_from_kernel()
|
||||
void
|
||||
config_vifs_from_kernel()
|
||||
{
|
||||
struct ifreq ifbuf[32];
|
||||
struct ifreq *ifrp, *ifend;
|
||||
|
|
|
|||
|
|
@ -7,15 +7,18 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: defs.h,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: defs.h,v 3.6.1.1 1995/06/26 00:18:18 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
@ -34,6 +37,17 @@
|
|||
/*XXX*/
|
||||
typedef u_int u_int32;
|
||||
|
||||
#ifndef __P
|
||||
#ifdef __STDC__
|
||||
#define __P(x) x
|
||||
#else
|
||||
#define __P(x) ()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef void (*cfunc_t) __P((void *));
|
||||
typedef void (*ihfunc_t) __P((fd_set *));
|
||||
|
||||
#include "dvmrp.h"
|
||||
#include "vif.h"
|
||||
#include "route.h"
|
||||
|
|
@ -56,7 +70,7 @@ typedef u_int u_int32;
|
|||
|
||||
#define PROTOCOL_VERSION 3 /* increment when packet format/content changes */
|
||||
|
||||
#define MROUTED_VERSION 5 /* increment on local changes or bug fixes, */
|
||||
#define MROUTED_VERSION 6 /* increment on local changes or bug fixes, */
|
||||
/* reset to 0 whever PROTOCOL_VERSION increments */
|
||||
|
||||
#define MROUTED_LEVEL ( (MROUTED_VERSION << 8) | PROTOCOL_VERSION | \
|
||||
|
|
@ -74,6 +88,7 @@ typedef u_int u_int32;
|
|||
#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
|
||||
#else
|
||||
#define JAN_1970 2208988800L /* 1970 - 1900 in seconds */
|
||||
#define const /**/
|
||||
#endif
|
||||
|
||||
#ifdef RSRR
|
||||
|
|
@ -124,119 +139,154 @@ extern int sys_nerr;
|
|||
extern char * sys_errlist[];
|
||||
#endif
|
||||
|
||||
extern void log();
|
||||
/* main.c */
|
||||
extern void log __P((int, int, char *, ...));
|
||||
extern int register_input_handler __P((int fd, ihfunc_t func));
|
||||
|
||||
extern void init_igmp();
|
||||
extern void accept_igmp();
|
||||
extern void send_igmp();
|
||||
/* igmp.c */
|
||||
extern void init_igmp __P((void));
|
||||
extern void accept_igmp __P((int recvlen));
|
||||
extern void send_igmp __P((u_int32 src, u_int32 dst, int type,
|
||||
int code, u_int32 group,
|
||||
int datalen));
|
||||
|
||||
extern void init_routes();
|
||||
extern void start_route_updates();
|
||||
extern void update_route();
|
||||
extern void age_routes();
|
||||
extern void expire_all_routes();
|
||||
extern void free_all_routes();
|
||||
/* callout.c */
|
||||
extern void callout_init __P((void));
|
||||
extern void age_callout_queue __P((void));
|
||||
extern int timer_setTimer __P((int delay, cfunc_t action,
|
||||
char *data));
|
||||
extern void timer_clearTimer __P((int timer_id));
|
||||
|
||||
extern void accept_probe();
|
||||
extern void accept_report();
|
||||
extern void report();
|
||||
extern void report_to_all_neighbors();
|
||||
extern int report_next_chunk();
|
||||
extern void add_vif_to_routes();
|
||||
extern void delete_vif_from_routes();
|
||||
extern void delete_neighbor_from_routes();
|
||||
extern void dump_routes();
|
||||
/* route.c */
|
||||
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,
|
||||
vifi_t vifi));
|
||||
extern void age_routes __P((void));
|
||||
extern void expire_all_routes __P((void));
|
||||
extern void free_all_routes __P((void));
|
||||
extern void accept_probe __P((u_int32 src, u_int32 dst,
|
||||
char *p, int datalen,
|
||||
u_int32 level));
|
||||
extern void accept_report __P((u_int32 src, u_int32 dst,
|
||||
char *p, int datalen,
|
||||
u_int32 level));
|
||||
extern struct rtentry * determine_route __P((u_int32 src));
|
||||
extern void report __P((int which_routes, vifi_t vifi,
|
||||
u_int32 dst));
|
||||
extern void report_to_all_neighbors __P((int which_routes));
|
||||
extern int report_next_chunk __P((void));
|
||||
extern void add_vif_to_routes __P((vifi_t vifi));
|
||||
extern void delete_vif_from_routes __P((vifi_t vifi));
|
||||
extern void delete_neighbor_from_routes __P((u_int32 addr,
|
||||
vifi_t vifi));
|
||||
extern void dump_routes __P((FILE *fp));
|
||||
extern void start_route_updates __P((void));
|
||||
|
||||
extern void init_vifs();
|
||||
extern void check_vif_state();
|
||||
extern vifi_t find_vif();
|
||||
extern void age_vifs();
|
||||
extern void dump_vifs();
|
||||
extern void stop_all_vifs();
|
||||
extern struct listaddr *neighbor_info();
|
||||
/* vif.c */
|
||||
extern void init_vifs __P((void));
|
||||
extern void check_vif_state __P((void));
|
||||
extern vifi_t find_vif __P((u_int32 src, u_int32 dst));
|
||||
extern void age_vifs __P((void));
|
||||
extern void dump_vifs __P((FILE *fp));
|
||||
extern void stop_all_vifs __P((void));
|
||||
extern struct listaddr *neighbor_info __P((vifi_t vifi, u_int32 addr));
|
||||
extern void accept_group_report __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group, int r_type));
|
||||
extern void query_groups __P((void));
|
||||
extern void probe_for_neighbors __P((void));
|
||||
extern int update_neighbor __P((vifi_t vifi, u_int32 addr,
|
||||
int msgtype, char *p, int datalen,
|
||||
u_int32 level));
|
||||
extern void accept_neighbor_request __P((u_int32 src, u_int32 dst));
|
||||
extern void accept_neighbor_request2 __P((u_int32 src,
|
||||
u_int32 dst));
|
||||
extern void accept_neighbors __P((u_int32 src, u_int32 dst,
|
||||
u_char *p, int datalen, u_int32 level));
|
||||
extern void accept_neighbors2 __P((u_int32 src, u_int32 dst,
|
||||
u_char *p, int datalen, u_int32 level));
|
||||
extern void accept_leave_message __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group));
|
||||
extern void accept_membership_query __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group, int tmo));
|
||||
|
||||
extern void accept_group_report();
|
||||
extern void query_groups();
|
||||
extern void probe_for_neighbors();
|
||||
extern int update_neighbor();
|
||||
extern void accept_neighbor_request();
|
||||
extern void accept_neighbor_request2();
|
||||
extern void accept_neighbors();
|
||||
extern void accept_neighbors2();
|
||||
/* config.c */
|
||||
extern void config_vifs_from_kernel __P((void));
|
||||
|
||||
extern void config_vifs_from_kernel();
|
||||
extern void config_vifs_from_file();
|
||||
/* cfparse.y */
|
||||
extern void config_vifs_from_file __P((void));
|
||||
|
||||
extern int inet_valid_host();
|
||||
extern int inet_valid_subnet();
|
||||
extern char * inet_fmt();
|
||||
extern char * inet_fmts();
|
||||
extern u_int32 inet_parse();
|
||||
extern int inet_cksum();
|
||||
|
||||
extern struct rtentry * determine_route();
|
||||
|
||||
extern void init_ktable();
|
||||
extern void add_table_entry();
|
||||
extern void del_table_entry();
|
||||
extern void update_table_entry();
|
||||
extern void update_lclgrp();
|
||||
extern void delete_lclgrp();
|
||||
/* inet.c */
|
||||
extern int inet_valid_host __P((u_int32 naddr));
|
||||
extern int inet_valid_subnet __P((u_int32 nsubnet, u_int32 nmask));
|
||||
extern char * inet_fmt __P((u_int32 addr, char *s));
|
||||
extern char * inet_fmts __P((u_int32 addr, u_int32 mask, char *s));
|
||||
extern u_int32 inet_parse __P((char *s));
|
||||
extern int inet_cksum __P((u_short *addr, u_int len));
|
||||
|
||||
/* prune.c */
|
||||
extern unsigned kroutes;
|
||||
extern void accept_prune();
|
||||
extern int no_entry_exists();
|
||||
extern int rtr_cnt();
|
||||
extern void free_all_prunes();
|
||||
extern void age_table_entry();
|
||||
extern void dump_cache();
|
||||
extern void add_table_entry __P((u_int32 origin, u_int32 mcastgrp));
|
||||
extern void del_table_entry __P((struct rtentry *r,
|
||||
u_int32 mcastgrp, u_int del_flag));
|
||||
extern void update_table_entry __P((struct rtentry *r));
|
||||
extern void init_ktable __P((void));
|
||||
extern void accept_prune __P((u_int32 src, u_int32 dst, char *p,
|
||||
int datalen));
|
||||
extern void steal_sources __P((struct rtentry *rt));
|
||||
extern void reset_neighbor_state __P((vifi_t vifi, u_int32 addr));
|
||||
extern int grplst_mem __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern int scoped_addr __P((vifi_t vifi, u_int32 addr));
|
||||
extern void free_all_prunes __P((void));
|
||||
extern void age_table_entry __P((void));
|
||||
extern void dump_cache __P((FILE *fp2));
|
||||
extern void update_lclgrp __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern void delete_lclgrp __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern void chkgrp_graft __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern void accept_graft __P((u_int32 src, u_int32 dst, char *p,
|
||||
int datalen));
|
||||
extern void accept_g_ack __P((u_int32 src, u_int32 dst, char *p,
|
||||
int datalen));
|
||||
/* u_int is promoted u_char */
|
||||
extern void accept_mtrace __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group, char *data, u_int no,
|
||||
int datalen));
|
||||
|
||||
/* kern.c */
|
||||
extern void k_set_rcvbuf __P((int bufsize));
|
||||
extern void k_hdr_include __P((int bool));
|
||||
extern void k_set_ttl __P((int t));
|
||||
extern void k_set_loop __P((int l));
|
||||
extern void k_set_if __P((u_int32 ifa));
|
||||
extern void k_join __P((u_int32 grp, u_int32 ifa));
|
||||
extern void k_leave __P((u_int32 grp, u_int32 ifa));
|
||||
extern void k_init_dvmrp __P((void));
|
||||
extern void k_stop_dvmrp __P((void));
|
||||
extern void k_add_vif __P((vifi_t vifi, struct uvif *v));
|
||||
extern void k_del_vif __P((vifi_t vifi));
|
||||
extern void k_add_rg __P((u_int32 origin, struct gtable *g));
|
||||
extern int k_del_rg __P((u_int32 origin, struct gtable *g));
|
||||
extern int k_get_version __P((void));
|
||||
|
||||
#ifdef SNMP
|
||||
extern struct rtentry * snmp_find_route();
|
||||
extern struct gtable * find_grp();
|
||||
extern struct stable * find_grp_src();
|
||||
/* prune.c */
|
||||
extern struct rtentry * snmp_find_route __P(());
|
||||
extern struct gtable * find_grp __P(());
|
||||
extern struct stable * find_grp_src __P(());
|
||||
#endif
|
||||
|
||||
extern void chkgrp_graft();
|
||||
extern void accept_graft();
|
||||
extern void send_graft_ack();
|
||||
extern void accept_g_ack();
|
||||
extern void accept_mtrace();
|
||||
extern void accept_leave_message();
|
||||
extern void accept_membership_query();
|
||||
#ifdef RSRR
|
||||
/* prune.c */
|
||||
extern struct gtable *kernel_table;
|
||||
extern struct gtable *gtp;
|
||||
extern int find_src_grp();
|
||||
extern int grplst_mem();
|
||||
extern int scoped_addr();
|
||||
#endif /* RSRR */
|
||||
|
||||
extern void k_set_rcvbuf();
|
||||
extern void k_hdr_include();
|
||||
extern void k_set_ttl();
|
||||
extern void k_set_loop();
|
||||
extern void k_set_if();
|
||||
extern void k_join();
|
||||
extern void k_leave();
|
||||
extern void k_init_dvmrp();
|
||||
extern void k_stop_dvmrp();
|
||||
extern void k_add_vif();
|
||||
extern void k_del_vif();
|
||||
extern void k_add_rg();
|
||||
extern int k_del_rg();
|
||||
extern int k_get_version();
|
||||
|
||||
extern char * malloc();
|
||||
extern char * fgets();
|
||||
extern FILE * fopen();
|
||||
|
||||
#if !defined(htonl) && !defined(__osf__)
|
||||
extern u_long htonl();
|
||||
extern u_long ntohl();
|
||||
#endif
|
||||
|
||||
#ifdef RSRR
|
||||
extern void rsrr_init();
|
||||
extern void rsrr_read();
|
||||
extern int find_src_grp __P((u_int32 src, u_int32 mask,
|
||||
u_int32 grp));
|
||||
|
||||
/* rsrr.c */
|
||||
extern void rsrr_init __P((void));
|
||||
extern void rsrr_read __P((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));
|
||||
#endif /* RSRR */
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: dvmrp.h,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: dvmrp.h,v 3.6 1995/06/25 18:52:10 fenner Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
* Various protocol constants (all times in seconds)
|
||||
*/
|
||||
/* address for multicast DVMRP msgs */
|
||||
#define INADDR_DVMRP_GROUP (u_int32)0xe0000004 /* 224.0.0.4 */
|
||||
#define INADDR_DVMRP_GROUP (u_int32)0xe0000004 /* 224.0.0.4 */
|
||||
/* address for multicast mtrace msg */
|
||||
#define INADDR_ALLRTRS_GROUP (u_int32)0xe0000002 /* 224.0.0.2 */
|
||||
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
#define DEFAULT_METRIC 1 /* default subnet/tunnel metric */
|
||||
#define DEFAULT_THRESHOLD 1 /* default subnet/tunnel threshold */
|
||||
|
||||
#define MAX_RATE_LIMIT 100000 /* max rate limit */
|
||||
#define MAX_RATE_LIMIT 100000 /* max rate limit */
|
||||
#define DEFAULT_PHY_RATE_LIMIT 0 /* default phyint rate limit */
|
||||
#define DEFAULT_TUN_RATE_LIMIT 500 /* default tunnel rate limit */
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: igmp.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: igmp.c,v 3.6 1995/06/25 18:52:55 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -17,19 +17,27 @@
|
|||
/*
|
||||
* Exported variables.
|
||||
*/
|
||||
char *recv_buf; /* input packet buffer */
|
||||
char *send_buf; /* output packet buffer */
|
||||
char *recv_buf; /* input packet buffer */
|
||||
char *send_buf; /* output packet buffer */
|
||||
int igmp_socket; /* socket for all network I/O */
|
||||
u_int32 allhosts_group; /* All hosts addr in net order */
|
||||
u_int32 allrtrs_group; /* All-Routers " in net order */
|
||||
u_int32 dvmrp_group; /* DVMRP grp addr in net order */
|
||||
u_int32 dvmrp_genid; /* IGMP generation id */
|
||||
|
||||
/*
|
||||
* Local function definitions.
|
||||
*/
|
||||
/* u_char promoted to u_int */
|
||||
static char * packet_kind __P((u_int type, u_int code));
|
||||
static int igmp_log_level __P((u_int type, u_int code));
|
||||
|
||||
/*
|
||||
* Open and initialize the igmp socket, and fill in the non-changing
|
||||
* IP header fields in the output packet buffer.
|
||||
*/
|
||||
void init_igmp()
|
||||
void
|
||||
init_igmp()
|
||||
{
|
||||
struct ip *ip;
|
||||
|
||||
|
|
@ -66,8 +74,9 @@ void init_igmp()
|
|||
#define PIM_GRAFT 6
|
||||
#define PIM_GRAFT_ACK 7
|
||||
|
||||
static char *packet_kind(type, code)
|
||||
u_char type, code;
|
||||
static char *
|
||||
packet_kind(type, code)
|
||||
u_int type, code;
|
||||
{
|
||||
switch (type) {
|
||||
case IGMP_HOST_MEMBERSHIP_QUERY: return "membership query ";
|
||||
|
|
@ -109,7 +118,8 @@ static char *packet_kind(type, code)
|
|||
* Process a newly received IGMP packet that is sitting in the input
|
||||
* packet buffer.
|
||||
*/
|
||||
void accept_igmp(recvlen)
|
||||
void
|
||||
accept_igmp(recvlen)
|
||||
int recvlen;
|
||||
{
|
||||
register u_int32 src, dst, group;
|
||||
|
|
@ -201,12 +211,12 @@ void accept_igmp(recvlen)
|
|||
return;
|
||||
|
||||
case DVMRP_NEIGHBORS:
|
||||
accept_neighbors(src, dst, (char *)(igmp+1), igmpdatalen,
|
||||
accept_neighbors(src, dst, (u_char *)(igmp+1), igmpdatalen,
|
||||
group);
|
||||
return;
|
||||
|
||||
case DVMRP_NEIGHBORS2:
|
||||
accept_neighbors2(src, dst, (char *)(igmp+1), igmpdatalen,
|
||||
accept_neighbors2(src, dst, (u_char *)(igmp+1), igmpdatalen,
|
||||
group);
|
||||
return;
|
||||
|
||||
|
|
@ -250,6 +260,29 @@ void accept_igmp(recvlen)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some IGMP messages are more important than others. This routine
|
||||
* determines the logging level at which to log a send error (often
|
||||
* "No route to host"). This is important when there is asymmetric
|
||||
* reachability and someone is trying to, i.e., mrinfo me periodically.
|
||||
*/
|
||||
static int
|
||||
igmp_log_level(type, code)
|
||||
u_int type, code;
|
||||
{
|
||||
switch (type) {
|
||||
case IGMP_MTRACE_RESP:
|
||||
return LOG_INFO;
|
||||
|
||||
case IGMP_DVMRP:
|
||||
switch (code) {
|
||||
case DVMRP_NEIGHBORS:
|
||||
case DVMRP_NEIGHBORS2:
|
||||
return LOG_INFO;
|
||||
}
|
||||
}
|
||||
return LOG_WARNING;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct an IGMP message in the output packet buffer. The caller may
|
||||
|
|
@ -294,7 +327,7 @@ send_igmp(src, dst, type, code, group, datalen)
|
|||
if (errno == ENETDOWN)
|
||||
check_vif_state();
|
||||
else
|
||||
log(LOG_WARNING, errno,
|
||||
log(igmp_log_level(type, code), errno,
|
||||
"sendto to %s on %s",
|
||||
inet_fmt(dst, s1), inet_fmt(src, s2));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: inet.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: inet.c,v 3.6 1995/06/25 18:54:45 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -28,7 +28,8 @@ char s4[19];
|
|||
* (Without a mask, cannot detect addresses of the form {subnet,0} or
|
||||
* {subnet,-1}.)
|
||||
*/
|
||||
int inet_valid_host(naddr)
|
||||
int
|
||||
inet_valid_host(naddr)
|
||||
u_int32 naddr;
|
||||
{
|
||||
register u_int32 addr;
|
||||
|
|
@ -50,7 +51,8 @@ int inet_valid_host(naddr)
|
|||
* within the [ABC] range and that the host bits of the subnet
|
||||
* are all 0.
|
||||
*/
|
||||
int inet_valid_subnet(nsubnet, nmask)
|
||||
int
|
||||
inet_valid_subnet(nsubnet, nmask)
|
||||
u_int32 nsubnet, nmask;
|
||||
{
|
||||
register u_int32 subnet, mask;
|
||||
|
|
@ -83,7 +85,8 @@ int inet_valid_subnet(nsubnet, nmask)
|
|||
/*
|
||||
* Convert an IP address in u_long (network) format into a printable string.
|
||||
*/
|
||||
char *inet_fmt(addr, s)
|
||||
char *
|
||||
inet_fmt(addr, s)
|
||||
u_int32 addr;
|
||||
char *s;
|
||||
{
|
||||
|
|
@ -99,7 +102,8 @@ char *inet_fmt(addr, s)
|
|||
* Convert an IP subnet number in u_long (network) format into a printable
|
||||
* string including the netmask as a number of bits.
|
||||
*/
|
||||
char *inet_fmts(addr, mask, s)
|
||||
char *
|
||||
inet_fmts(addr, mask, s)
|
||||
u_int32 addr, mask;
|
||||
char *s;
|
||||
{
|
||||
|
|
@ -129,7 +133,8 @@ char *inet_fmts(addr, mask, s)
|
|||
* legal address with that value, you must explicitly compare the string
|
||||
* with "255.255.255.255".)
|
||||
*/
|
||||
u_int32 inet_parse(s)
|
||||
u_int32
|
||||
inet_parse(s)
|
||||
char *s;
|
||||
{
|
||||
u_int32 a = 0;
|
||||
|
|
@ -167,7 +172,8 @@ u_int32 inet_parse(s)
|
|||
* Checksum routine for Internet Protocol family headers (C Version)
|
||||
*
|
||||
*/
|
||||
int inet_cksum(addr, len)
|
||||
int
|
||||
inet_cksum(addr, len)
|
||||
u_short *addr;
|
||||
u_int len;
|
||||
{
|
||||
|
|
@ -182,13 +188,13 @@ int inet_cksum(addr, len)
|
|||
* back all the carry bits from the top 16 bits into the lower
|
||||
* 16 bits.
|
||||
*/
|
||||
while( nleft > 1 ) {
|
||||
while (nleft > 1) {
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
/* mop up an odd byte, if necessary */
|
||||
if( nleft == 1 ) {
|
||||
if (nleft == 1) {
|
||||
*(u_char *) (&answer) = *(u_char *)w ;
|
||||
sum += answer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: kern.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: kern.c,v 3.6 1995/06/25 18:57:38 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ void k_del_vif(vifi)
|
|||
* Adds a (source, mcastgrp) entry to the kernel
|
||||
*/
|
||||
void k_add_rg(origin, g)
|
||||
u_long origin;
|
||||
u_int32 origin;
|
||||
struct gtable *g;
|
||||
{
|
||||
struct mfcctl mc;
|
||||
|
|
@ -185,11 +185,11 @@ void k_add_rg(origin, g)
|
|||
* Deletes a (source, mcastgrp) entry from the kernel
|
||||
*/
|
||||
int k_del_rg(origin, g)
|
||||
u_long origin;
|
||||
u_int32 origin;
|
||||
struct gtable *g;
|
||||
{
|
||||
struct mfcctl mc;
|
||||
int retval, i;
|
||||
int retval;
|
||||
|
||||
/* copy table values so that setsockopt can process it */
|
||||
mc.mfcc_origin.s_addr = origin;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: main.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: main.c,v 3.6 1995/06/25 18:58:06 fenner Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -21,10 +21,14 @@
|
|||
|
||||
|
||||
#include "defs.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef SNMP
|
||||
#include <string.h>
|
||||
#include "snmp.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -45,26 +49,29 @@ u_char pruning = 1; /* Enable pruning by default */
|
|||
|
||||
static struct ihandler {
|
||||
int fd; /* File descriptor */
|
||||
void (*func)(); /* Function to call with &fd_set */
|
||||
ihfunc_t func; /* Function to call with &fd_set */
|
||||
} ihandlers[NHANDLERS];
|
||||
static int nhandlers = 0;
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
static void fasttimer();
|
||||
static void timer();
|
||||
static void cleanup();
|
||||
static void done();
|
||||
static void dump();
|
||||
static void fdump();
|
||||
static void cdump();
|
||||
static void restart();
|
||||
static void fasttimer __P((int));
|
||||
static void done __P((int));
|
||||
static void dump __P((int));
|
||||
static void fdump __P((int));
|
||||
static void cdump __P((int));
|
||||
static void restart __P((int));
|
||||
static void timer __P((void));
|
||||
static void cleanup __P((void));
|
||||
|
||||
/* To shut up gcc -Wstrict-prototypes */
|
||||
int main __P((int argc, char **argv));
|
||||
|
||||
int
|
||||
register_input_handler(fd, func)
|
||||
int fd;
|
||||
void (*func)();
|
||||
ihfunc_t func;
|
||||
{
|
||||
if (nhandlers >= NHANDLERS)
|
||||
return -1;
|
||||
|
|
@ -75,7 +82,8 @@ register_input_handler(fd, func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int main(argc, argv)
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
|
|
@ -83,9 +91,8 @@ int main(argc, argv)
|
|||
register int omask;
|
||||
int dummy;
|
||||
FILE *fp;
|
||||
extern uid_t geteuid();
|
||||
struct timeval tv;
|
||||
u_long prev_genid;
|
||||
u_int32 prev_genid;
|
||||
int vers;
|
||||
fd_set rfds, readers;
|
||||
int nfds, n, i;
|
||||
|
|
@ -212,8 +219,11 @@ usage: fprintf(stderr,
|
|||
|
||||
#ifndef OLD_KERNEL
|
||||
vers = k_get_version();
|
||||
if ((((vers >> 8) & 0xff) != PROTOCOL_VERSION) ||
|
||||
((vers & 0xff) != MROUTED_VERSION))
|
||||
/*XXX
|
||||
* This function must change whenever the kernel version changes
|
||||
*/
|
||||
if ((((vers >> 8) & 0xff) != 3) ||
|
||||
((vers & 0xff) != 5))
|
||||
log(LOG_ERR, 0, "kernel (v%d.%d)/mrouted (v%d.%d) version mismatch",
|
||||
(vers >> 8) & 0xff, vers & 0xff,
|
||||
PROTOCOL_VERSION, MROUTED_VERSION);
|
||||
|
|
@ -239,11 +249,11 @@ usage: fprintf(stderr,
|
|||
|
||||
fp = fopen(pidfilename, "w");
|
||||
if (fp != NULL) {
|
||||
fprintf(fp, "%d\n", getpid());
|
||||
fprintf(fp, "%d\n", (int)getpid());
|
||||
(void) fclose(fp);
|
||||
}
|
||||
|
||||
if (debug >= 2) dump();
|
||||
if (debug >= 2) dump(0);
|
||||
|
||||
(void)signal(SIGALRM, fasttimer);
|
||||
|
||||
|
|
@ -294,16 +304,16 @@ usage: fprintf(stderr,
|
|||
}
|
||||
|
||||
if (FD_ISSET(igmp_socket, &rfds)) {
|
||||
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
|
||||
0, NULL, &dummy);
|
||||
if (recvlen < 0) {
|
||||
if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
|
||||
continue;
|
||||
}
|
||||
omask = sigblock(sigmask(SIGALRM));
|
||||
accept_igmp(recvlen);
|
||||
(void)sigsetmask(omask);
|
||||
}
|
||||
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
|
||||
0, NULL, &dummy);
|
||||
if (recvlen < 0) {
|
||||
if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
|
||||
continue;
|
||||
}
|
||||
omask = sigblock(sigmask(SIGALRM));
|
||||
accept_igmp(recvlen);
|
||||
(void)sigsetmask(omask);
|
||||
}
|
||||
|
||||
for (i = 0; i < nhandlers; i++) {
|
||||
if (FD_ISSET(ihandlers[i].fd, &rfds)) {
|
||||
|
|
@ -332,7 +342,8 @@ usage: fprintf(stderr,
|
|||
* do all the other time-based processing.
|
||||
*/
|
||||
static void
|
||||
fasttimer()
|
||||
fasttimer(i)
|
||||
int i;
|
||||
{
|
||||
static unsigned int tlast;
|
||||
static unsigned int nsent;
|
||||
|
|
@ -453,7 +464,8 @@ timer()
|
|||
* On termination, let everyone know we're going away.
|
||||
*/
|
||||
static void
|
||||
done()
|
||||
done(i)
|
||||
int i;
|
||||
{
|
||||
log(LOG_NOTICE, 0, "mrouted version %d.%d exiting",
|
||||
PROTOCOL_VERSION, MROUTED_VERSION);
|
||||
|
|
@ -471,8 +483,8 @@ cleanup()
|
|||
#ifdef RSRR
|
||||
rsrr_clean();
|
||||
#endif /* RSRR */
|
||||
expire_all_routes();
|
||||
report_to_all_neighbors(ALL_ROUTES);
|
||||
expire_all_routes();
|
||||
report_to_all_neighbors(ALL_ROUTES);
|
||||
k_stop_dvmrp();
|
||||
}
|
||||
}
|
||||
|
|
@ -482,7 +494,8 @@ cleanup()
|
|||
* Dump internal data structures to stderr.
|
||||
*/
|
||||
static void
|
||||
dump()
|
||||
dump(i)
|
||||
int i;
|
||||
{
|
||||
dump_vifs(stderr);
|
||||
dump_routes(stderr);
|
||||
|
|
@ -493,7 +506,8 @@ dump()
|
|||
* Dump internal data structures to a file.
|
||||
*/
|
||||
static void
|
||||
fdump()
|
||||
fdump(i)
|
||||
int i;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
|
|
@ -510,7 +524,8 @@ fdump()
|
|||
* Dump local cache contents to a file.
|
||||
*/
|
||||
static void
|
||||
cdump()
|
||||
cdump(i)
|
||||
int i;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
|
|
@ -526,7 +541,8 @@ cdump()
|
|||
* Restart mrouted
|
||||
*/
|
||||
static void
|
||||
restart()
|
||||
restart(i)
|
||||
int i;
|
||||
{
|
||||
register int omask;
|
||||
|
||||
|
|
@ -565,6 +581,19 @@ restart()
|
|||
* according to the severity of the message and the current debug level.
|
||||
* For errors of severity LOG_ERR or worse, terminate the program.
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
void
|
||||
log(int severity, int syserr, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
static char fmt[211] = "warning - ";
|
||||
char *msg;
|
||||
char tbuf[20];
|
||||
struct timeval now;
|
||||
struct tm *thyme;
|
||||
|
||||
va_start(ap, format);
|
||||
#else
|
||||
/*VARARGS3*/
|
||||
void
|
||||
log(severity, syserr, format, va_alist)
|
||||
|
|
@ -580,6 +609,7 @@ log(severity, syserr, format, va_alist)
|
|||
struct tm *thyme;
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsprintf(&fmt[10], format, ap);
|
||||
va_end(ap);
|
||||
msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* Mapper for connections between MRouteD multicast routers.
|
||||
* Written by Pavel Curtis <Pavel@PARC.Xerox.Com>
|
||||
*
|
||||
* $Id: mapper.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: mapper.c,v 3.6 1995/06/25 18:59:02 fenner Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -25,6 +25,12 @@
|
|||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include "defs.h"
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEOUT 2 /* How long to wait before retrying requests */
|
||||
#define DEFAULT_RETRIES 1 /* How many times to ask each router */
|
||||
|
|
@ -68,6 +74,23 @@ int show_names = TRUE;
|
|||
vifi_t numvifs; /* to keep loader happy */
|
||||
/* (see COPY_TABLES macro called in kern.c) */
|
||||
|
||||
Node * find_node __P((u_int32 addr, Node **ptr));
|
||||
Interface * find_interface __P((u_int32 addr, Node *node));
|
||||
Neighbor * find_neighbor __P((u_int32 addr, Node *node));
|
||||
int main __P((int argc, char *argv[]));
|
||||
void ask __P((u_int32 dst));
|
||||
void ask2 __P((u_int32 dst));
|
||||
int retry_requests __P((Node *node));
|
||||
char * inet_name __P((u_int32 addr));
|
||||
void print_map __P((Node *node));
|
||||
char * graph_name __P((u_int32 addr, char *buf));
|
||||
void graph_edges __P((Node *node));
|
||||
void elide_aliases __P((Node *node));
|
||||
void graph_map __P((void));
|
||||
int get_number __P((int *var, int deflt, char ***pargv,
|
||||
int *pargc));
|
||||
u_int32 host_addr __P((char *name));
|
||||
|
||||
|
||||
Node *find_node(addr, ptr)
|
||||
u_int32 addr;
|
||||
|
|
@ -135,12 +158,27 @@ Neighbor *find_neighbor(addr, node)
|
|||
* message and the current debug level. For errors of severity LOG_ERR or
|
||||
* worse, terminate the program.
|
||||
*/
|
||||
void log(severity, syserr, format, a, b, c, d, e)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
int a, b, c, d, e;
|
||||
#ifdef __STDC__
|
||||
void
|
||||
log(int severity, int syserr, char *format, ...)
|
||||
{
|
||||
char fmt[100];
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap, format);
|
||||
#else
|
||||
/*VARARGS3*/
|
||||
void
|
||||
log(severity, syserr, format, va_alist)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
|
||||
switch (debug) {
|
||||
case 0: if (severity > LOG_WARNING) return;
|
||||
|
|
@ -151,7 +189,7 @@ void log(severity, syserr, format, a, b, c, d, e)
|
|||
if (severity == LOG_WARNING)
|
||||
strcat(fmt, "warning - ");
|
||||
strncat(fmt, format, 80);
|
||||
fprintf(stderr, fmt, a, b, c, d, e);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (syserr == 0)
|
||||
fprintf(stderr, "\n");
|
||||
else if (syserr < sys_nerr)
|
||||
|
|
@ -186,8 +224,9 @@ void ask2(dst)
|
|||
/*
|
||||
* Process an incoming group membership report.
|
||||
*/
|
||||
void accept_group_report(src, dst, group)
|
||||
void accept_group_report(src, dst, group, r_type)
|
||||
u_int32 src, dst, group;
|
||||
int r_type;
|
||||
{
|
||||
log(LOG_INFO, 0, "ignoring IGMP group membership report from %s to %s",
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
|
|
@ -197,8 +236,10 @@ void accept_group_report(src, dst, group)
|
|||
/*
|
||||
* Process an incoming neighbor probe message.
|
||||
*/
|
||||
void accept_probe(src, dst)
|
||||
u_int32 src, dst;
|
||||
void accept_probe(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
log(LOG_INFO, 0, "ignoring DVMRP probe from %s to %s",
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
|
|
@ -208,8 +249,8 @@ void accept_probe(src, dst)
|
|||
/*
|
||||
* Process an incoming route report message.
|
||||
*/
|
||||
void accept_report(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
void accept_report(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
|
|
@ -260,7 +301,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 = ntohl(level);
|
||||
node->version = level;
|
||||
node->tries = 0;
|
||||
ask2(src);
|
||||
return;
|
||||
|
|
@ -404,8 +445,8 @@ void accept_neighbors(src, dst, p, datalen, level)
|
|||
}
|
||||
}
|
||||
|
||||
void accept_neighbors2(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
void accept_neighbors2(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
|
|
@ -496,7 +537,7 @@ void accept_neighbors2(src, dst, p, datalen)
|
|||
old_neighbors = ifc->neighbors;
|
||||
|
||||
/* Add the neighbors for this interface */
|
||||
while (ncount--) {
|
||||
while (ncount-- && datalen > 0) {
|
||||
u_int32 neighbor;
|
||||
Neighbor *nb;
|
||||
Node *n_node;
|
||||
|
|
@ -937,24 +978,42 @@ int main(argc, argv)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
void accept_prune()
|
||||
/* dummies */
|
||||
void accept_prune(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_graft()
|
||||
void accept_graft(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_g_ack()
|
||||
void accept_g_ack(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void add_table_entry()
|
||||
void add_table_entry(origin, mcastgrp)
|
||||
u_int32 origin, mcastgrp;
|
||||
{
|
||||
}
|
||||
void accept_leave_message()
|
||||
void accept_leave_message(src, dst, group)
|
||||
u_int32 src, dst, group;
|
||||
{
|
||||
}
|
||||
void accept_mtrace()
|
||||
void accept_mtrace(src, dst, group, data, no, datalen)
|
||||
u_int32 src, dst, group;
|
||||
char *data;
|
||||
u_int no;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_membership_query()
|
||||
void accept_membership_query(src, dst, group, tmo)
|
||||
u_int32 src, dst, group;
|
||||
int tmo;
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Id: mrinfo.c,v 3.5.1.1 1995/05/09 22:58:05 fenner Exp $";
|
||||
"@(#) $Id: mrinfo.c,v 3.6 1995/06/25 19:05:34 fenner Exp $";
|
||||
/* original rcsid:
|
||||
"@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)";
|
||||
*/
|
||||
|
|
@ -71,6 +71,11 @@ static char rcsid[] =
|
|||
#include <sys/time.h>
|
||||
#include "defs.h"
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEOUT 4 /* How long to wait before retrying requests */
|
||||
#define DEFAULT_RETRIES 3 /* How many times to ask each router */
|
||||
|
|
@ -80,10 +85,22 @@ int debug = 0;
|
|||
int nflag = 0;
|
||||
int retries = DEFAULT_RETRIES;
|
||||
int timeout = DEFAULT_TIMEOUT;
|
||||
int target_level;
|
||||
int target_level = 0;
|
||||
vifi_t numvifs; /* to keep loader happy */
|
||||
/* (see COPY_TABLES macro called in kern.c) */
|
||||
|
||||
char * inet_name __P((u_int32 addr));
|
||||
void ask __P((u_int32 dst));
|
||||
void ask2 __P((u_int32 dst));
|
||||
int get_number __P((int *var, int deflt, char ***pargv,
|
||||
int *pargc));
|
||||
u_int32 host_addr __P((char *name));
|
||||
void usage __P((void));
|
||||
|
||||
/* to shut up -Wstrict-prototypes */
|
||||
int main __P((int argc, char *argv[]));
|
||||
|
||||
|
||||
char *
|
||||
inet_name(addr)
|
||||
u_int32 addr;
|
||||
|
|
@ -107,14 +124,26 @@ inet_name(addr)
|
|||
* message and the current debug level. For errors of severity LOG_ERR or
|
||||
* worse, terminate the program.
|
||||
*/
|
||||
void
|
||||
log(severity, syserr, format, a, b, c, d, e)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
int a, b, c, d, e;
|
||||
#ifdef __STDC__
|
||||
void
|
||||
log(int severity, int syserr, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap, format);
|
||||
#else
|
||||
void
|
||||
log(severity, syserr, format, va_alist)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
switch (debug) {
|
||||
case 0:
|
||||
if (severity > LOG_WARNING)
|
||||
|
|
@ -130,7 +159,7 @@ log(severity, syserr, format, a, b, c, d, e)
|
|||
if (severity == LOG_WARNING)
|
||||
strcat(fmt, "warning - ");
|
||||
strncat(fmt, format, 80);
|
||||
fprintf(stderr, fmt, a, b, c, d, e);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (syserr == 0)
|
||||
fprintf(stderr, "\n");
|
||||
else if (syserr < sys_nerr)
|
||||
|
|
@ -166,9 +195,9 @@ ask2(dst)
|
|||
* Process an incoming neighbor-list message.
|
||||
*/
|
||||
void
|
||||
accept_neighbors(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
u_char *p;
|
||||
accept_neighbors(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
u_char *ep = p + datalen;
|
||||
|
|
@ -199,17 +228,17 @@ accept_neighbors(src, dst, p, datalen)
|
|||
}
|
||||
|
||||
void
|
||||
accept_neighbors2(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
u_char *p;
|
||||
accept_neighbors2(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
u_char *ep = p + datalen;
|
||||
u_int broken_cisco = ((target_level & 0xffff) == 0x020a); /* 10.2 */
|
||||
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),
|
||||
target_level & 0xff, (target_level >> 8) & 0xff);
|
||||
level & 0xff, (level >> 8) & 0xff);
|
||||
|
||||
while (p < ep) {
|
||||
register u_char metric;
|
||||
|
|
@ -308,6 +337,10 @@ main(argc, argv)
|
|||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int tries = 0;
|
||||
int trynew = 1;
|
||||
struct timeval et;
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
if (geteuid() != 0) {
|
||||
|
|
@ -375,12 +408,20 @@ main(argc, argv)
|
|||
our_addr = addr.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
ask(target_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 (;;) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
struct timeval tv, now;
|
||||
int count, recvlen, dummy = 0;
|
||||
register u_int32 src, dst, group;
|
||||
struct ip *ip;
|
||||
|
|
@ -390,8 +431,16 @@ main(argc, argv)
|
|||
FD_ZERO(&fds);
|
||||
FD_SET(igmp_socket, &fds);
|
||||
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
gettimeofday(&now, 0);
|
||||
tv.tv_sec = et.tv_sec - now.tv_sec;
|
||||
tv.tv_usec = et.tv_usec - now.tv_usec;
|
||||
|
||||
if (tv.tv_usec < 0) {
|
||||
tv.tv_usec += 1000000L;
|
||||
--tv.tv_sec;
|
||||
}
|
||||
if (tv.tv_sec < 0)
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
|
||||
count = select(igmp_socket + 1, &fds, 0, 0, &tv);
|
||||
|
||||
|
|
@ -401,9 +450,14 @@ main(argc, argv)
|
|||
continue;
|
||||
} else if (count == 0) {
|
||||
log(LOG_DEBUG, 0, "Timed out receiving neighbor lists");
|
||||
if (--retries < 0)
|
||||
if (++tries > retries)
|
||||
exit(1);
|
||||
if (target_level == 0)
|
||||
/* If we've tried ASK_NEIGHBORS2 twice with
|
||||
* no response, fall back to ASK_NEIGHBORS
|
||||
*/
|
||||
if (tries == 2 && target_level == 0)
|
||||
trynew = 0;
|
||||
if (target_level == 0 && trynew == 0)
|
||||
ask(target_addr);
|
||||
else
|
||||
ask2(target_addr);
|
||||
|
|
@ -473,57 +527,84 @@ main(argc, argv)
|
|||
ask2(target_addr);
|
||||
}
|
||||
} else {
|
||||
accept_neighbors(src, dst, (char *)(igmp + 1),
|
||||
igmpdatalen);
|
||||
accept_neighbors(src, dst, (u_char *)(igmp + 1),
|
||||
igmpdatalen, ntohl(group));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case DVMRP_NEIGHBORS2:
|
||||
accept_neighbors2(src, dst, (char *)(igmp + 1),
|
||||
igmpdatalen);
|
||||
accept_neighbors2(src, dst, (u_char *)(igmp + 1),
|
||||
igmpdatalen, ntohl(group));
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* dummies */
|
||||
void accept_probe()
|
||||
void accept_probe(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_group_report()
|
||||
void accept_group_report(src, dst, group, r_type)
|
||||
u_int32 src, dst, group;
|
||||
int r_type;
|
||||
{
|
||||
}
|
||||
void accept_neighbor_request2()
|
||||
void accept_neighbor_request2(src, dst)
|
||||
u_int32 src, dst;
|
||||
{
|
||||
}
|
||||
void accept_report()
|
||||
void accept_report(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_neighbor_request()
|
||||
void accept_neighbor_request(src, dst)
|
||||
u_int32 src, dst;
|
||||
{
|
||||
}
|
||||
void accept_prune()
|
||||
void accept_prune(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_graft()
|
||||
void accept_graft(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_g_ack()
|
||||
void accept_g_ack(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void add_table_entry()
|
||||
void add_table_entry(origin, mcastgrp)
|
||||
u_int32 origin, mcastgrp;
|
||||
{
|
||||
}
|
||||
void check_vif_state()
|
||||
{
|
||||
}
|
||||
void accept_leave_message()
|
||||
void accept_leave_message(src, dst, group)
|
||||
u_int32 src, dst, group;
|
||||
{
|
||||
}
|
||||
void accept_mtrace()
|
||||
void accept_mtrace(src, dst, group, data, no, datalen)
|
||||
u_int32 src, dst, group;
|
||||
char *data;
|
||||
u_int no;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_membership_query()
|
||||
void accept_membership_query(src, dst, group, tmo)
|
||||
u_int32 src, dst, group;
|
||||
int tmo;
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
'\"COPYRIGHT 1989 by The Board of Trustees of Leland Stanford Junior University.
|
||||
'\"$Id: mrouted.8,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
'\"$Id: mrouted.8,v 3.6 1995/06/25 19:10:58 fenner Exp $
|
||||
.TH MROUTED 8
|
||||
.UC 5
|
||||
.SH NAME
|
||||
|
|
@ -118,7 +118,7 @@ There are four types of configuration commands:
|
|||
[altnet <network>/<mask-len>]
|
||||
|
||||
tunnel <local-addr> <remote-addr> [metric <m>]
|
||||
[threshold <t>] [srcrt] [rate_limit <b>]
|
||||
[threshold <t>] [rate_limit <b>]
|
||||
[boundary (<boundary-name>|<scoped-addr>/<mask-len>)]
|
||||
|
||||
cache_lifetime <ct>
|
||||
|
|
@ -327,7 +327,7 @@ shown at each interface.
|
|||
Associated with each subnet from which a multicast datagram can originate
|
||||
is the address of the previous hop router (unless the subnet is directly-
|
||||
connected), the metric of the path back to the origin, the amount of time
|
||||
since we last recieved an update for this subnet, the incoming vif for
|
||||
since we last received an update for this subnet, the incoming vif for
|
||||
multicasts from that origin, and a list of outgoing vifs. "*" means that
|
||||
the outgoing vif is connected to a leaf of the broadcast tree rooted at the
|
||||
origin, and a multicast datagram from that origin will be forwarded on that
|
||||
|
|
@ -365,7 +365,7 @@ The 'Ptmr' field is simply a dash if no prune was sent upstream, or the
|
|||
amount of time until the upstream prune will time out.
|
||||
The 'Ivif' field indicates the
|
||||
incoming vif for multicast packets from that origin. Each router also
|
||||
maintains a record of the number of prunes received from neighbouring
|
||||
maintains a record of the number of prunes received from neighboring
|
||||
routers for a particular source and group. If there are no members of
|
||||
a multicast group on any downward link of the multicast tree for a
|
||||
subnet, a prune message is sent to the upstream router. They are
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: mrouted.conf,v 3.5.1.1 1995/05/09 05:48:48 fenner Exp $
|
||||
# $Id: mrouted.conf,v 3.6 1995/06/25 19:11:55 fenner Exp $
|
||||
#
|
||||
# This is the configuration file for "mrouted", an IP multicast router.
|
||||
# mrouted looks for it in "/etc/mrouted.conf".
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
.\" Copyright (c) 1988 The Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" $Id: mtrace.8,v 3.5 1995/05/09 01:23:58 fenner Exp $
|
||||
.\" $Id: mtrace.8,v 3.6 1995/06/25 19:14:07 fenner Exp $
|
||||
.\"
|
||||
.TH MTRACE 8 "May 8, 1995"
|
||||
.UC 6
|
||||
|
|
@ -62,7 +62,6 @@ mtrace \- print multicast path from a source to a receiver
|
|||
.I resp_dest
|
||||
] [
|
||||
.B \-s
|
||||
.I src_addr
|
||||
] [
|
||||
.B \-t
|
||||
.I ttl
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
* have been derived from mrouted programs sources covered by the
|
||||
* license in the accompanying file named "LICENSE".
|
||||
*
|
||||
* $Id: mtrace.c,v 3.5 1995/05/09 01:24:19 fenner Exp $
|
||||
* $Id: mtrace.c,v 3.6 1995/06/25 19:17:14 fenner Exp $
|
||||
*/
|
||||
|
||||
#include <netdb.h>
|
||||
|
|
@ -55,8 +55,14 @@
|
|||
#include <sys/filio.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "defs.h"
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEOUT 3 /* How long to wait before retrying requests */
|
||||
#define DEFAULT_RETRIES 3 /* How many times to try */
|
||||
|
|
@ -104,26 +110,51 @@ u_int32 dst_netmask; /* netmask to go with qdst */
|
|||
* Query/response parameters, all initialized to zero and set later
|
||||
* to default values or from options.
|
||||
*/
|
||||
u_int32 qsrc = 0;
|
||||
u_int32 qgrp = 0;
|
||||
u_int32 qdst = 0;
|
||||
u_char qno = 0;
|
||||
u_int32 raddr = 0;
|
||||
int qttl = 0;
|
||||
u_char rttl = 0;
|
||||
u_int32 gwy = 0;
|
||||
u_int32 qsrc = 0; /* Source address in the query */
|
||||
u_int32 qgrp = 0; /* Group address in the query */
|
||||
u_int32 qdst = 0; /* Destination (receiver) address in query */
|
||||
u_char qno = 0; /* Max number of hops to query */
|
||||
u_int32 raddr = 0; /* Address where response should be sent */
|
||||
int qttl = 0; /* TTL for the query packet */
|
||||
u_char rttl = 0; /* TTL for the response packet */
|
||||
u_int32 gwy = 0; /* User-supplied last-hop router address */
|
||||
u_int32 tdst = 0; /* Address where trace is sent (last-hop) */
|
||||
|
||||
vifi_t numvifs; /* to keep loader happy */
|
||||
/* (see kern.c) */
|
||||
extern void k_join();
|
||||
extern void k_leave();
|
||||
extern void k_set_ttl();
|
||||
extern void exit();
|
||||
#ifndef SYSV
|
||||
extern long random();
|
||||
#endif
|
||||
extern int errno;
|
||||
|
||||
char * inet_name __P((u_int32 addr));
|
||||
u_int32 host_addr __P((char *name));
|
||||
/* u_int is promoted u_char */
|
||||
char * proto_type __P((u_int type));
|
||||
char * flag_type __P((u_int type));
|
||||
|
||||
u_int32 get_netmask __P((int s, u_int32 dst));
|
||||
int get_ttl __P((struct resp_buf *buf));
|
||||
int t_diff __P((u_long a, u_long b));
|
||||
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));
|
||||
void print_trace __P((int index, struct resp_buf *buf));
|
||||
int what_kind __P((struct resp_buf *buf));
|
||||
char * scale __P((int *hop));
|
||||
void stat_line __P((struct tr_resp *r, struct tr_resp *s,
|
||||
int have_next));
|
||||
void fixup_stats __P((struct resp_buf *base,
|
||||
struct resp_buf *new));
|
||||
int print_stats __P((struct resp_buf *base,
|
||||
struct resp_buf *prev,
|
||||
struct resp_buf *new));
|
||||
void check_vif_state __P((void));
|
||||
|
||||
int main __P((int argc, char *argv[]));
|
||||
|
||||
|
||||
|
||||
char *
|
||||
inet_name(addr)
|
||||
|
|
@ -141,28 +172,32 @@ u_int32
|
|||
host_addr(name)
|
||||
char *name;
|
||||
{
|
||||
struct hostent *e = gethostbyname(name);
|
||||
struct hostent *e = (struct hostent *)0;
|
||||
u_int32 addr;
|
||||
int i, dots = 3;
|
||||
char buf[40];
|
||||
char *ip = name;
|
||||
char *op = buf;
|
||||
|
||||
/*
|
||||
* Undo BSD's favor -- take fewer than 4 octets as net/subnet address
|
||||
* if the name is all numeric.
|
||||
*/
|
||||
for (i = sizeof(buf) - 7; i > 0; --i) {
|
||||
if (*ip == '.') --dots;
|
||||
else if (*ip == '\0') break;
|
||||
else if (!isdigit(*ip)) dots = 0; /* Not numeric, don't add zeroes */
|
||||
*op++ = *ip++;
|
||||
}
|
||||
for (i = 0; i < dots; ++i) {
|
||||
*op++ = '.';
|
||||
*op++ = '0';
|
||||
}
|
||||
*op = '\0';
|
||||
|
||||
if (dots <= 0) e = gethostbyname(name);
|
||||
if (e) memcpy((char *)&addr, e->h_addr_list[0], e->h_length);
|
||||
else {
|
||||
/*
|
||||
* Undo BSD's favor -- take fewer than 4 octets as net/subnet address.
|
||||
*/
|
||||
for (i = sizeof(buf) - 7; i > 0; --i) {
|
||||
if (*ip == '.') --dots;
|
||||
if (*ip == '\0') break;
|
||||
*op++ = *ip++;
|
||||
}
|
||||
for (i = 0; i < dots; ++i) {
|
||||
*op++ = '.';
|
||||
*op++ = '0';
|
||||
}
|
||||
*op = '\0';
|
||||
addr = inet_addr(buf);
|
||||
if (addr == -1) {
|
||||
addr = 0;
|
||||
|
|
@ -175,7 +210,7 @@ host_addr(name)
|
|||
|
||||
char *
|
||||
proto_type(type)
|
||||
u_char type;
|
||||
u_int type;
|
||||
{
|
||||
static char buf[80];
|
||||
|
||||
|
|
@ -197,7 +232,7 @@ proto_type(type)
|
|||
|
||||
char *
|
||||
flag_type(type)
|
||||
u_char type;
|
||||
u_int type;
|
||||
{
|
||||
static char buf[80];
|
||||
|
||||
|
|
@ -342,7 +377,7 @@ send_recv(dst, type, code, tries, save)
|
|||
int datalen;
|
||||
int count, recvlen, dummy = 0;
|
||||
int len;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
if (type == IGMP_MTRACE) {
|
||||
group = qgrp;
|
||||
|
|
@ -366,6 +401,8 @@ send_recv(dst, type, code, tries, save)
|
|||
query->tr_raddr = raddr ? raddr : multicast ? resp_cast : lcl_addr;
|
||||
query->tr_rttl = rttl ? rttl :
|
||||
IN_MULTICAST(ntohl(query->tr_raddr)) ? get_ttl(save) : UNICAST_TTL;
|
||||
query->tr_src = qsrc;
|
||||
query->tr_dst = qdst;
|
||||
|
||||
for (i = tries ; i > 0; --i) {
|
||||
if (tries == nqueries && raddr == 0) {
|
||||
|
|
@ -460,8 +497,26 @@ send_recv(dst, type, code, tries, save)
|
|||
|
||||
case IGMP_DVMRP:
|
||||
if (igmp->igmp_code != DVMRP_NEIGHBORS2) continue;
|
||||
if (ip->ip_src.s_addr != dst) continue;
|
||||
len = igmpdatalen;
|
||||
/*
|
||||
* Accept DVMRP_NEIGHBORS2 response if it comes from the
|
||||
* address queried or if that address is one of the local
|
||||
* 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);
|
||||
while (p < ep) {
|
||||
register u_int32 laddr = *p++;
|
||||
register int n = ntohl(*p++) & 0xFF;
|
||||
if (laddr == dst) {
|
||||
ep = p + 1; /* ensure p < ep after loop */
|
||||
break;
|
||||
}
|
||||
p += n;
|
||||
}
|
||||
if (p >= ep) continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case IGMP_MTRACE: /* For backward compatibility with 3.3 */
|
||||
|
|
@ -576,44 +631,61 @@ print_trace(index, buf)
|
|||
/*
|
||||
* See what kind of router is the next hop
|
||||
*/
|
||||
void
|
||||
int
|
||||
what_kind(buf)
|
||||
struct resp_buf *buf;
|
||||
{
|
||||
u_int32 smask;
|
||||
int recvlen;
|
||||
int retval;
|
||||
int hops = buf->len;
|
||||
struct tr_resp *r = buf->resps + hops - 1;
|
||||
u_int32 next = r->tr_rmtaddr;
|
||||
|
||||
recvlen = send_recv(next, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0]);
|
||||
retval = send_recv(next, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0]);
|
||||
print_host(next);
|
||||
if (recvlen) {
|
||||
if (retval) {
|
||||
u_int32 version = ntohl(incr[0].igmp.igmp_group.s_addr);
|
||||
u_int32 *p = (u_int32 *)incr[0].ndata;
|
||||
u_int32 *ep = p + (incr[0].len >> 2);
|
||||
char *type = "";
|
||||
retval = 0;
|
||||
switch (version & 0xFF) {
|
||||
case 1:
|
||||
type = "proteon/mrouted ";
|
||||
retval = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
if (((version >> 8) & 0xFF) < 3) retval = 1;
|
||||
/* Fall through */
|
||||
case 4:
|
||||
type = "mrouted ";
|
||||
break;
|
||||
|
||||
case 10:
|
||||
type = "cisco ";
|
||||
}
|
||||
printf(" [%s%d.%d] didn't respond\n",
|
||||
(version == 1) ? "proteon/mrouted " :
|
||||
((version & 0xff) == 2) ? "mrouted " :
|
||||
((version & 0xff) == 3) ? "mrouted " :
|
||||
((version & 0xff) == 4) ? "mrouted " :
|
||||
((version & 0xff) == 10) ? "cisco " : "",
|
||||
version & 0xff, (version >> 8) & 0xff);
|
||||
type, version & 0xFF, (version >> 8) & 0xFF);
|
||||
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;
|
||||
if ((laddr & smask) == (qsrc & smask)) {
|
||||
if (!(flags & (DVMRP_NF_DOWN | DVMRP_NF_DISABLED)) &&
|
||||
(laddr & smask) == (qsrc & smask)) {
|
||||
printf("%3d ", -(hops+2));
|
||||
print_host(qsrc);
|
||||
printf("\n");
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
p += n;
|
||||
}
|
||||
return;
|
||||
return retval;
|
||||
}
|
||||
printf(" didn't respond\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -738,7 +810,7 @@ fixup_stats(base, new)
|
|||
/*
|
||||
* Print responses with statistics for forward path (from src to dst)
|
||||
*/
|
||||
void
|
||||
int
|
||||
print_stats(base, prev, new)
|
||||
struct resp_buf *base, *prev, *new;
|
||||
{
|
||||
|
|
@ -780,10 +852,9 @@ print_stats(base, prev, new)
|
|||
}
|
||||
|
||||
while (TRUE) {
|
||||
if ((n->tr_inaddr != b->tr_inaddr) || (n->tr_inaddr != b->tr_inaddr)) {
|
||||
printf("Route changed, start again.\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((n->tr_inaddr != b->tr_inaddr) || (n->tr_inaddr != b->tr_inaddr))
|
||||
return 1; /* Route changed */
|
||||
|
||||
if ((n->tr_inaddr != n->tr_outaddr))
|
||||
printf("%-15s\n", inet_fmt(n->tr_inaddr, s1));
|
||||
printf("%-15s %-14s %s\n", inet_fmt(n->tr_outaddr, s1), names[rno],
|
||||
|
|
@ -815,6 +886,7 @@ print_stats(base, prev, new)
|
|||
stat_line(b, n, FALSE);
|
||||
printf("%-15s %s\n", inet_fmt(qdst, s1), inet_fmt(lcl_addr, s2));
|
||||
printf(" Receiver Query Source\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -833,11 +905,11 @@ char *argv[];
|
|||
int recvlen;
|
||||
struct timeval tv;
|
||||
struct resp_buf *prev, *new;
|
||||
struct tr_query *query;
|
||||
struct tr_resp *r;
|
||||
u_int32 smask;
|
||||
int rno;
|
||||
int hops, tries;
|
||||
int hops, nexthop, tries;
|
||||
u_int32 lastout = 0;
|
||||
int numstats = 1;
|
||||
int waittime;
|
||||
int seed;
|
||||
|
|
@ -999,31 +1071,33 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
|
|||
* Default destination for path to be queried is the local host.
|
||||
*/
|
||||
if (qdst == 0) qdst = lcl_addr ? lcl_addr : addr.sin_addr.s_addr;
|
||||
|
||||
/*
|
||||
* If the destination is on the local net, the last-hop router can
|
||||
* be found by multicast to the all-routers multicast group.
|
||||
* Otherwise, use the group address that is the subject of the
|
||||
* query since by definition the last hop router will be a member.
|
||||
* Set default TTLs for local remote multicasts.
|
||||
*/
|
||||
dst_netmask = get_netmask(udp, qdst);
|
||||
close(udp);
|
||||
if (lcl_addr == 0) lcl_addr = addr.sin_addr.s_addr;
|
||||
if (gwy == 0)
|
||||
if ((qdst & dst_netmask) == (lcl_addr & dst_netmask)) gwy = query_cast;
|
||||
else gwy = qgrp;
|
||||
|
||||
if (IN_MULTICAST(ntohl(gwy))) {
|
||||
k_set_loop(1); /* If I am running on a router, I need to hear this */
|
||||
if (gwy == query_cast) k_set_ttl(qttl ? qttl : 1);
|
||||
else k_set_ttl(qttl ? qttl : MULTICAST_TTL1);
|
||||
} else
|
||||
if (send_recv(gwy, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0]))
|
||||
if (ntohl(incr[0].igmp.igmp_group.s_addr) == 0x0303) {
|
||||
printf("Don't use -g to address an mrouted 3.3, it might crash\n");
|
||||
/*
|
||||
* Initialize the seed for random query identifiers.
|
||||
*/
|
||||
gettimeofday(&tv, 0);
|
||||
seed = tv.tv_usec ^ lcl_addr;
|
||||
#ifdef SYSV
|
||||
srand48(seed);
|
||||
#else
|
||||
srandom(seed);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Protect against unicast queries to mrouted versions that might crash.
|
||||
*/
|
||||
if (gwy && !IN_MULTICAST(ntohl(gwy)))
|
||||
if (send_recv(gwy, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0])) {
|
||||
int version = ntohl(incr[0].igmp.igmp_group.s_addr) & 0xFFFF;
|
||||
if (version == 0x0303 || version == 0x0503) {
|
||||
printf("Don't use -g to address an mrouted 3.%d, it might crash\n",
|
||||
(version >> 8) & 0xFF);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Mtrace from %s to %s via group %s\n",
|
||||
inet_fmt(qsrc, s1), inet_fmt(qdst, s2), inet_fmt(qgrp, s3));
|
||||
|
|
@ -1033,29 +1107,33 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
|
|||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make up the IGMP_MTRACE query packet to send (some parameters
|
||||
* are set later), including initializing the seed for random
|
||||
* query identifiers.
|
||||
*/
|
||||
query = (struct tr_query *)(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
|
||||
query->tr_src = qsrc;
|
||||
query->tr_dst = qdst;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
seed = tv.tv_usec ^ lcl_addr;
|
||||
#ifdef SYSV
|
||||
srand48(seed);
|
||||
#else
|
||||
srandom(seed);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the response is to be a multicast address, make sure we
|
||||
* are listening on that multicast address.
|
||||
*/
|
||||
if (raddr && IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr);
|
||||
else k_join(resp_cast, lcl_addr);
|
||||
if (raddr) {
|
||||
if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr);
|
||||
} else k_join(resp_cast, lcl_addr);
|
||||
|
||||
/*
|
||||
* If the destination is on the local net, the last-hop router can
|
||||
* be found by multicast to the all-routers multicast group.
|
||||
* Otherwise, use the group address that is the subject of the
|
||||
* query since by definition the last-hop router will be a member.
|
||||
* Set default TTLs for local remote multicasts.
|
||||
*/
|
||||
restart:
|
||||
|
||||
if (gwy == 0)
|
||||
if ((qdst & dst_netmask) == (lcl_addr & dst_netmask)) tdst = query_cast;
|
||||
else tdst = qgrp;
|
||||
else tdst = gwy;
|
||||
|
||||
if (IN_MULTICAST(ntohl(tdst))) {
|
||||
k_set_loop(1); /* If I am running on a router, I need to hear this */
|
||||
if (tdst == query_cast) k_set_ttl(qttl ? qttl : 1);
|
||||
else k_set_ttl(qttl ? qttl : MULTICAST_TTL1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try a query at the requested number of hops or MAXOPS if unspecified.
|
||||
|
|
@ -1074,12 +1152,14 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
|
|||
base.rtime = 0;
|
||||
base.len = 0;
|
||||
|
||||
recvlen = send_recv(gwy, IGMP_MTRACE, hops, tries, &base);
|
||||
recvlen = send_recv(tdst, IGMP_MTRACE, hops, tries, &base);
|
||||
|
||||
/*
|
||||
* If the initial query was successful, print it. Otherwise, if
|
||||
* the query max hop count is the default of zero, loop starting
|
||||
* from one until a timeout occurs.
|
||||
* from one until there is no response for four hops. The extra
|
||||
* hops allow getting past an mtrace-capable mrouter that can't
|
||||
* send multicast packets because all phyints are disabled.
|
||||
*/
|
||||
if (recvlen) {
|
||||
printf("\n 0 ");
|
||||
|
|
@ -1089,7 +1169,6 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
|
|||
r = base.resps + base.len - 1;
|
||||
if (r->tr_rflags == TR_OLD_ROUTER) {
|
||||
printf("%3d ", -(base.len+1));
|
||||
fflush(stdout);
|
||||
what_kind(&base);
|
||||
} else {
|
||||
VAL_TO_MASK(smask, r->tr_smask);
|
||||
|
|
@ -1104,36 +1183,75 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
|
|||
print_host(qdst);
|
||||
printf("\n");
|
||||
|
||||
for (hops = 1; hops <= MAXHOPS; ++hops) {
|
||||
for (hops = 1, nexthop = 1; hops <= MAXHOPS; ++hops) {
|
||||
printf("%3d ", -hops);
|
||||
fflush(stdout);
|
||||
|
||||
recvlen = send_recv(gwy, IGMP_MTRACE, hops, nqueries, &base);
|
||||
/*
|
||||
* After a successful first hop, try switching to the unicast
|
||||
* address of the last-hop router instead of multicasting the
|
||||
* trace query. This should be safe for mrouted versions 3.3
|
||||
* and 3.5 because there is a long route timeout with metric
|
||||
* infinity before a route disappears. Switching to unicast
|
||||
* reduces the amount of multicast traffic and avoids a bug
|
||||
* with duplicate suppression in mrouted 3.5.
|
||||
*/
|
||||
if (hops == 2 && gwy == 0 &&
|
||||
(recvlen = send_recv(lastout, IGMP_MTRACE, hops, 1, &base)))
|
||||
tdst = lastout;
|
||||
else recvlen = send_recv(tdst, IGMP_MTRACE, hops, nqueries, &base);
|
||||
|
||||
if (recvlen == 0) {
|
||||
if (--hops == 0) break;
|
||||
what_kind(&base);
|
||||
break;
|
||||
if (hops == 1) break;
|
||||
if (hops == nexthop) {
|
||||
if (what_kind(&base)) {
|
||||
/* the ask_neighbors determined that the
|
||||
* not-responding router is the first-hop. */
|
||||
break;
|
||||
}
|
||||
} else if (hops < nexthop + 3) {
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("...giving up\n");
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
r = base.resps + base.len - 1;
|
||||
if (base.len == hops) print_trace(-hops, &base);
|
||||
else {
|
||||
hops = base.len;
|
||||
if (base.len == hops &&
|
||||
(hops == 1 || (base.resps+nexthop-2)->tr_outaddr == lastout)) {
|
||||
if (hops == nexthop) {
|
||||
print_trace(-hops, &base);
|
||||
} else {
|
||||
printf("\nResuming...\n");
|
||||
print_trace(nexthop, &base);
|
||||
}
|
||||
} else {
|
||||
if (base.len == hops - 1) {
|
||||
if (nexthop <= base.len) {
|
||||
printf("\nResuming...\n");
|
||||
print_trace(nexthop, &base);
|
||||
}
|
||||
} else {
|
||||
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 further hops\n");
|
||||
printf("No space left in trace packet for more hops\n");
|
||||
break; /* XXX could do segmented trace */
|
||||
}
|
||||
printf("Route must have changed...\n\n");
|
||||
print_trace(1, &base);
|
||||
}
|
||||
lastout = r->tr_outaddr;
|
||||
nexthop = hops + 1;
|
||||
|
||||
VAL_TO_MASK(smask, r->tr_smask);
|
||||
if ((r->tr_inaddr & smask) == (qsrc & smask)) {
|
||||
printf("%3d ", -(hops+1));
|
||||
printf("%3d ", -nexthop);
|
||||
print_host(qsrc);
|
||||
printf("\n");
|
||||
break;
|
||||
|
|
@ -1144,8 +1262,8 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\
|
|||
|
||||
if (base.rtime == 0) {
|
||||
printf("Timed out receiving responses\n");
|
||||
if (IN_MULTICAST(ntohl(gwy)))
|
||||
if (gwy == query_cast)
|
||||
if (IN_MULTICAST(ntohl(tdst)))
|
||||
if (tdst == query_cast)
|
||||
printf("Perhaps no local router has a route for source %s\n",
|
||||
inet_fmt(qsrc, s1));
|
||||
else
|
||||
|
|
@ -1177,7 +1295,7 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
|
|||
sleep((unsigned)waittime);
|
||||
}
|
||||
rno = base.len;
|
||||
recvlen = send_recv(gwy, IGMP_MTRACE, rno, nqueries, new);
|
||||
recvlen = send_recv(tdst, IGMP_MTRACE, rno, nqueries, new);
|
||||
|
||||
if (recvlen == 0) {
|
||||
printf("Timed out.\n");
|
||||
|
|
@ -1185,14 +1303,21 @@ 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");
|
||||
exit(1);
|
||||
printf("Trace length doesn't match:\n");
|
||||
print_trace(1, new);
|
||||
printf("Restarting.\n\n");
|
||||
goto restart;
|
||||
}
|
||||
|
||||
printf("Results after %d seconds:\n\n",
|
||||
(new->qtime - base.qtime) >> 16);
|
||||
(int)((new->qtime - base.qtime) >> 16));
|
||||
fixup_stats(&base, new);
|
||||
print_stats(&base, prev, new);
|
||||
if (print_stats(&base, prev, new)) {
|
||||
printf("Route changed:\n");
|
||||
print_trace(1, new);
|
||||
printf("Restarting.\n\n");
|
||||
goto restart;
|
||||
}
|
||||
prev = new;
|
||||
new = &incr[numstats&1];
|
||||
waittime = 10;
|
||||
|
|
@ -1201,8 +1326,9 @@ or multicast at ttl %d doesn't reach its last-hop router for that source\n",
|
|||
/*
|
||||
* If the response was multicast back, leave the group
|
||||
*/
|
||||
if (raddr && IN_MULTICAST(ntohl(raddr))) k_leave(raddr, lcl_addr);
|
||||
else k_leave(resp_cast, lcl_addr);
|
||||
if (raddr) {
|
||||
if (IN_MULTICAST(ntohl(raddr))) k_leave(raddr, lcl_addr);
|
||||
} else k_leave(resp_cast, lcl_addr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -1218,14 +1344,27 @@ check_vif_state()
|
|||
* of the message and the current debug level. For errors of severity
|
||||
* LOG_ERR or worse, terminate the program.
|
||||
*/
|
||||
/*VARARGS3*/
|
||||
#ifdef __STDC__
|
||||
void
|
||||
log(severity, syserr, format, a, b, c, d, e)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
int a, b, c, d, e;
|
||||
log(int severity, int syserr, char *format, ...)
|
||||
{
|
||||
char fmt[100];
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap, format);
|
||||
#else
|
||||
/*VARARGS3*/
|
||||
void
|
||||
log(severity, syserr, format, va_alist)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
|
||||
switch (debug) {
|
||||
case 0: if (severity > LOG_WARNING) return;
|
||||
|
|
@ -1235,7 +1374,7 @@ log(severity, syserr, format, a, b, c, d, e)
|
|||
fmt[0] = '\0';
|
||||
if (severity == LOG_WARNING) strcat(fmt, "warning - ");
|
||||
strncat(fmt, format, 80);
|
||||
fprintf(stderr, fmt, a, b, c, d, e);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (syserr == 0)
|
||||
fprintf(stderr, "\n");
|
||||
else if(syserr < sys_nerr)
|
||||
|
|
@ -1247,19 +1386,78 @@ log(severity, syserr, format, a, b, c, d, e)
|
|||
}
|
||||
|
||||
/* dummies */
|
||||
|
||||
/*VARARGS*/
|
||||
void accept_probe() {} /*VARARGS*/
|
||||
void accept_group_report() {} /*VARARGS*/
|
||||
void accept_neighbors() {} /*VARARGS*/
|
||||
void accept_neighbors2() {} /*VARARGS*/
|
||||
void accept_neighbor_request() {} /*VARARGS*/
|
||||
void accept_neighbor_request2() {} /*VARARGS*/
|
||||
void accept_report() {} /*VARARGS*/
|
||||
void accept_prune() {} /*VARARGS*/
|
||||
void accept_graft() {} /*VARARGS*/
|
||||
void accept_g_ack() {} /*VARARGS*/
|
||||
void add_table_entry() {} /*VARARGS*/
|
||||
void accept_mtrace() {} /*VARARGS*/
|
||||
void accept_leave_message() {} /*VARARGS*/
|
||||
void accept_membership_query() {} /*VARARGS*/
|
||||
void accept_probe(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_group_report(src, dst, group, r_type)
|
||||
u_int32 src, dst, group;
|
||||
int r_type;
|
||||
{
|
||||
}
|
||||
void accept_neighbor_request2(src, dst)
|
||||
u_int32 src, dst;
|
||||
{
|
||||
}
|
||||
void accept_report(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_neighbor_request(src, dst)
|
||||
u_int32 src, dst;
|
||||
{
|
||||
}
|
||||
void accept_prune(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_graft(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_g_ack(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void add_table_entry(origin, mcastgrp)
|
||||
u_int32 origin, mcastgrp;
|
||||
{
|
||||
}
|
||||
void accept_leave_message(src, dst, group)
|
||||
u_int32 src, dst, group;
|
||||
{
|
||||
}
|
||||
void accept_mtrace(src, dst, group, data, no, datalen)
|
||||
u_int32 src, dst, group;
|
||||
char *data;
|
||||
u_int no;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_membership_query(src, dst, group, tmo)
|
||||
u_int32 src, dst, group;
|
||||
int tmo;
|
||||
{
|
||||
}
|
||||
void accept_neighbors(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_neighbors2(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: pathnames.h,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: pathnames.h,v 3.6 1995/06/25 19:17:45 fenner Exp $
|
||||
*/
|
||||
|
||||
#define _PATH_MROUTED_CONF "/etc/mrouted.conf"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: prune.c,v 1.6 1995/06/13 18:04:57 wollman Exp $
|
||||
* $Id: prune.c,v 3.6 1995/06/25 19:18:43 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -17,6 +17,8 @@ extern int cache_lifetime;
|
|||
extern int max_prune_lifetime;
|
||||
extern struct rtentry *routing_table;
|
||||
|
||||
extern int phys_vif;
|
||||
|
||||
/*
|
||||
* dither cache lifetime to obtain a value between x and 2*x
|
||||
*/
|
||||
|
|
@ -49,6 +51,16 @@ unsigned int kroutes; /* current number of cache entries */
|
|||
/****************************************************************************
|
||||
Functions that are local to prune.c
|
||||
****************************************************************************/
|
||||
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 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,
|
||||
u_int32 origin, u_int32 grp));
|
||||
static void update_kernel __P((struct gtable *g));
|
||||
static char * scaletime __P((u_long t));
|
||||
|
||||
/*
|
||||
* Updates the ttl values for each vif.
|
||||
|
|
@ -163,7 +175,7 @@ pruning_neighbor(vifi, addr)
|
|||
{
|
||||
struct listaddr *n = neighbor_info(vifi, addr);
|
||||
int vers;
|
||||
|
||||
|
||||
if (n == NULL)
|
||||
return 0;
|
||||
|
||||
|
|
@ -183,8 +195,8 @@ pruning_neighbor(vifi, addr)
|
|||
*/
|
||||
static int
|
||||
can_mtrace(vifi, addr)
|
||||
vifi_t vifi;
|
||||
u_int32 addr;
|
||||
vifi_t vifi;
|
||||
u_int32 addr;
|
||||
{
|
||||
struct listaddr *n = neighbor_info(vifi, addr);
|
||||
int vers;
|
||||
|
|
@ -337,7 +349,7 @@ send_graft(gt)
|
|||
/*
|
||||
* Send an ack that a graft was received
|
||||
*/
|
||||
void
|
||||
static void
|
||||
send_graft_ack(src, dst, origin, grp)
|
||||
u_int32 src;
|
||||
u_int32 dst;
|
||||
|
|
@ -347,7 +359,7 @@ send_graft_ack(src, dst, origin, grp)
|
|||
register char *p;
|
||||
register int i;
|
||||
int datalen;
|
||||
|
||||
|
||||
p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
|
||||
datalen = 0;
|
||||
|
||||
|
|
@ -359,7 +371,7 @@ send_graft_ack(src, dst, origin, grp)
|
|||
|
||||
send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT_ACK,
|
||||
htonl(MROUTED_LEVEL), datalen);
|
||||
|
||||
|
||||
log(LOG_DEBUG, 0, "sent graft ack for (%s, %s) to %s",
|
||||
inet_fmt(origin, s1), inet_fmt(grp, s2), inet_fmt(dst, s3));
|
||||
}
|
||||
|
|
@ -638,8 +650,8 @@ add_table_entry(origin, mcastgrp)
|
|||
} else {
|
||||
gtnp = &r->rt_groups;
|
||||
while ((gt = *gtnp) != NULL) {
|
||||
if (gt->gt_mcastgrp >= mcastgrp)
|
||||
break;
|
||||
if (gt->gt_mcastgrp >= mcastgrp)
|
||||
break;
|
||||
gtnp = >->gt_next;
|
||||
prev_gt = gt;
|
||||
}
|
||||
|
|
@ -660,22 +672,24 @@ add_table_entry(origin, mcastgrp)
|
|||
gt->gt_srctbl = NULL;
|
||||
gt->gt_pruntbl = NULL;
|
||||
gt->gt_route = r;
|
||||
#ifdef RSRR
|
||||
gt->gt_rsrr_cache = NULL;
|
||||
#endif
|
||||
|
||||
if (r != NULL) {
|
||||
/* obtain the multicast group membership list */
|
||||
for (i = 0; i < numvifs; i++) {
|
||||
if (VIFM_ISSET(i, r->rt_children) &&
|
||||
!(VIFM_ISSET(i, r->rt_leaves)))
|
||||
VIFM_SET(i, gt->gt_grpmems);
|
||||
/* obtain the multicast group membership list */
|
||||
for (i = 0; i < numvifs; i++) {
|
||||
if (VIFM_ISSET(i, r->rt_children) &&
|
||||
!(VIFM_ISSET(i, r->rt_leaves)))
|
||||
VIFM_SET(i, gt->gt_grpmems);
|
||||
|
||||
if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
|
||||
VIFM_SET(i, gt->gt_grpmems);
|
||||
}
|
||||
GET_SCOPE(gt);
|
||||
if (VIFM_ISSET(r->rt_parent, gt->gt_scope))
|
||||
gt->gt_scope = -1;
|
||||
gt->gt_grpmems &= ~gt->gt_scope;
|
||||
if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
|
||||
VIFM_SET(i, gt->gt_grpmems);
|
||||
}
|
||||
GET_SCOPE(gt);
|
||||
if (VIFM_ISSET(r->rt_parent, gt->gt_scope))
|
||||
gt->gt_scope = -1;
|
||||
gt->gt_grpmems &= ~gt->gt_scope;
|
||||
} else {
|
||||
gt->gt_scope = -1;
|
||||
gt->gt_grpmems = 0;
|
||||
|
|
@ -688,30 +702,30 @@ add_table_entry(origin, mcastgrp)
|
|||
*gtnp = gt;
|
||||
if (gt->gt_next)
|
||||
gt->gt_next->gt_prev = gt;
|
||||
gt->gt_prev = prev_gt;
|
||||
gt->gt_prev = prev_gt;
|
||||
|
||||
if (r) {
|
||||
if (find_src_grp(r->rt_origin, r->rt_originmask, gt->gt_mcastgrp)) {
|
||||
struct gtable *g;
|
||||
if (find_src_grp(r->rt_origin, r->rt_originmask, gt->gt_mcastgrp)) {
|
||||
struct gtable *g;
|
||||
|
||||
g = gtp ? gtp->gt_gnext : kernel_table;
|
||||
log(LOG_WARNING, 0, "Entry for (%s %s) (rt:%x) exists (rt:%x)",
|
||||
inet_fmts(r->rt_origin, r->rt_originmask, s1),
|
||||
inet_fmt(g->gt_mcastgrp, s2),
|
||||
r, g->gt_route);
|
||||
} else {
|
||||
if (gtp) {
|
||||
gt->gt_gnext = gtp->gt_gnext;
|
||||
gt->gt_gprev = gtp;
|
||||
gtp->gt_gnext = gt;
|
||||
g = gtp ? gtp->gt_gnext : kernel_table;
|
||||
log(LOG_WARNING, 0, "Entry for (%s %s) (rt:%x) exists (rt:%x)",
|
||||
inet_fmts(r->rt_origin, r->rt_originmask, s1),
|
||||
inet_fmt(g->gt_mcastgrp, s2),
|
||||
r, g->gt_route);
|
||||
} else {
|
||||
gt->gt_gnext = kernel_table;
|
||||
gt->gt_gprev = NULL;
|
||||
kernel_table = gt;
|
||||
if (gtp) {
|
||||
gt->gt_gnext = gtp->gt_gnext;
|
||||
gt->gt_gprev = gtp;
|
||||
gtp->gt_gnext = gt;
|
||||
} else {
|
||||
gt->gt_gnext = kernel_table;
|
||||
gt->gt_gprev = NULL;
|
||||
kernel_table = gt;
|
||||
}
|
||||
if (gt->gt_gnext)
|
||||
gt->gt_gnext->gt_gprev = gt;
|
||||
}
|
||||
if (gt->gt_gnext)
|
||||
gt->gt_gnext->gt_gprev = gt;
|
||||
}
|
||||
} else {
|
||||
gt->gt_gnext = gt->gt_prev = NULL;
|
||||
}
|
||||
|
|
@ -1005,7 +1019,7 @@ update_table_entry(r)
|
|||
struct gtable *g;
|
||||
struct ptable *pt, *prev_pt;
|
||||
int i;
|
||||
|
||||
|
||||
for (g = r->rt_groups; g; g = g->gt_next) {
|
||||
pt = g->gt_pruntbl;
|
||||
while (pt) {
|
||||
|
|
@ -1016,7 +1030,7 @@ update_table_entry(r)
|
|||
g->gt_pruntbl = NULL;
|
||||
|
||||
g->gt_grpmems = 0;
|
||||
|
||||
|
||||
/* obtain the multicast group membership list */
|
||||
for (i = 0; i < numvifs; i++) {
|
||||
if (VIFM_ISSET(i, r->rt_children) &&
|
||||
|
|
@ -1029,12 +1043,12 @@ update_table_entry(r)
|
|||
if (VIFM_ISSET(r->rt_parent, g->gt_scope))
|
||||
g->gt_scope = -1;
|
||||
g->gt_grpmems &= ~g->gt_scope;
|
||||
|
||||
|
||||
log(LOG_DEBUG, 0, "updating cache entries (%s %s) gm:%x",
|
||||
inet_fmts(r->rt_origin, r->rt_originmask, s1),
|
||||
inet_fmt(g->gt_mcastgrp, s2),
|
||||
g->gt_grpmems);
|
||||
|
||||
|
||||
if (g->gt_grpmems && g->gt_prsent_timer) {
|
||||
g->gt_grftsnt = 1;
|
||||
send_graft(g);
|
||||
|
|
@ -1048,12 +1062,12 @@ update_table_entry(r)
|
|||
/* Send route change notification to reservation protocol. */
|
||||
rsrr_cache_send(g,1);
|
||||
#endif /* RSRR */
|
||||
|
||||
|
||||
/* Check if we want to prune this group */
|
||||
if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) {
|
||||
g->gt_timer = CACHE_LIFETIME(cache_lifetime);
|
||||
send_prune(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1135,28 +1149,28 @@ delete_lclgrp(vifi, mcastgrp)
|
|||
}
|
||||
|
||||
if (stop_sending) {
|
||||
VIFM_CLR(vifi, g->gt_grpmems);
|
||||
log(LOG_DEBUG, 0, "delete lclgrp (%s %s) gm:%x",
|
||||
inet_fmts(r->rt_origin, r->rt_originmask, s1),
|
||||
inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
|
||||
VIFM_CLR(vifi, g->gt_grpmems);
|
||||
log(LOG_DEBUG, 0, "delete lclgrp (%s %s) gm:%x",
|
||||
inet_fmts(r->rt_origin, r->rt_originmask, s1),
|
||||
inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
|
||||
|
||||
prun_add_ttls(g);
|
||||
update_kernel(g);
|
||||
prun_add_ttls(g);
|
||||
update_kernel(g);
|
||||
#ifdef RSRR
|
||||
/* Send route change notification to reservation protocol. */
|
||||
rsrr_cache_send(g,1);
|
||||
#endif /* RSRR */
|
||||
|
||||
/*
|
||||
* If there are no more members of this particular group,
|
||||
* send prune upstream
|
||||
*/
|
||||
if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway)
|
||||
send_prune(g);
|
||||
/*
|
||||
* If there are no more members of this particular group,
|
||||
* send prune upstream
|
||||
*/
|
||||
if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway)
|
||||
send_prune(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes the prune message received and then strips it to
|
||||
|
|
@ -1644,7 +1658,7 @@ steal_sources(rt)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gtnp = &kernel_no_route;
|
||||
while ((gt = *gtnp) != NULL) {
|
||||
|
|
@ -1736,7 +1750,7 @@ age_table_entry()
|
|||
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;
|
||||
gt->gt_prsent_timer = 0;
|
||||
}
|
||||
|
||||
/* modify the kernel entry to forward packets */
|
||||
|
|
@ -1765,13 +1779,13 @@ 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 (gt->gt_timer <= 0) {
|
||||
if (gt->gt_pruntbl) {
|
||||
if (gt->gt_prsent_timer == -1)
|
||||
|
|
@ -1832,7 +1846,7 @@ age_table_entry()
|
|||
inet_fmt(gt->gt_mcastgrp, s2));
|
||||
|
||||
/* free all the source entries */
|
||||
while (st = gt->gt_srctbl) {
|
||||
while ((st = gt->gt_srctbl) != NULL) {
|
||||
log(LOG_DEBUG, 0,
|
||||
"age_table_entry (P) deleting (%s %s)",
|
||||
inet_fmt(st->st_origin, s1),
|
||||
|
|
@ -1849,7 +1863,7 @@ age_table_entry()
|
|||
}
|
||||
|
||||
/* free all the prune list entries */
|
||||
while (gt->gt_pruntbl) {
|
||||
while ((pt = gt->gt_pruntbl) != NULL) {
|
||||
gt->gt_pruntbl = pt->pt_next;
|
||||
free(pt);
|
||||
}
|
||||
|
|
@ -1914,7 +1928,7 @@ age_table_entry()
|
|||
}
|
||||
}
|
||||
|
||||
char *
|
||||
static char *
|
||||
scaletime(t)
|
||||
u_long t;
|
||||
{
|
||||
|
|
@ -1948,7 +1962,7 @@ scaletime(t)
|
|||
if (t > 999)
|
||||
return "*** ";
|
||||
|
||||
sprintf(p,"%3d%c", t, s);
|
||||
sprintf(p,"%3d%c", (int)t, s);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
@ -1980,7 +1994,7 @@ dump_cache(fp2)
|
|||
fprintf(fp2, ">%s\n", inet_fmt(gt->gt_srctbl->st_origin, s1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (gt = kernel_table; gt; gt = gt->gt_gnext) {
|
||||
r = gt->gt_route;
|
||||
fprintf(fp2, " %-18s %-15s",
|
||||
|
|
@ -2013,9 +2027,9 @@ dump_cache(fp2)
|
|||
for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) {
|
||||
fprintf(fp2, "<r:%s v:%d t:%d\n", inet_fmt(pt->pt_router, s1),
|
||||
pt->pt_vifi, pt->pt_timer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2028,7 +2042,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
|
|||
u_int32 dst;
|
||||
u_int32 group;
|
||||
char *data;
|
||||
u_char no;
|
||||
u_int no; /* promoted u_char */
|
||||
int datalen;
|
||||
{
|
||||
u_char type;
|
||||
|
|
@ -2056,21 +2070,21 @@ accept_mtrace(src, dst, group, data, no, datalen)
|
|||
*/
|
||||
if (datalen == QLEN) {
|
||||
type = QUERY;
|
||||
log(LOG_DEBUG, 0, "Traceroute query rcvd from %s to %s",
|
||||
log(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s",
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
}
|
||||
else if ((datalen - QLEN) % RLEN == 0) {
|
||||
type = RESP;
|
||||
log(LOG_DEBUG, 0, "Traceroute response rcvd from %s to %s",
|
||||
log(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s",
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
if IN_MULTICAST(ntohl(dst)) {
|
||||
if (IN_MULTICAST(ntohl(dst))) {
|
||||
log(LOG_DEBUG, 0, "Dropping multicast response");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log(LOG_WARNING, 0, "%s from %s to %s",
|
||||
"Non decipherable tracer request recieved",
|
||||
"Non decipherable traceroute request recieved",
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
return;
|
||||
}
|
||||
|
|
@ -2090,8 +2104,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
|
|||
*/
|
||||
log(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
|
||||
return;
|
||||
} else
|
||||
oqid = qry->tr_qid;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it is a packet with all reports filled, drop it
|
||||
|
|
@ -2105,7 +2118,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
|
|||
inet_fmt(group, s2), inet_fmt(qry->tr_dst, s3));
|
||||
log(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl,
|
||||
inet_fmt(qry->tr_raddr, s1));
|
||||
log(LOG_DEBUG, 0, "rcount:%d", rcount);
|
||||
log(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid);
|
||||
|
||||
/* determine the routing table entry for this traceroute */
|
||||
rt = determine_route(qry->tr_src);
|
||||
|
|
@ -2158,6 +2171,9 @@ accept_mtrace(src, dst, group, data, no, datalen)
|
|||
}
|
||||
}
|
||||
|
||||
/* Now that we've decided to send a response, save the qid */
|
||||
oqid = qry->tr_qid;
|
||||
|
||||
log(LOG_DEBUG, 0, "Sending traceroute response");
|
||||
|
||||
/* copy the packet to the sending buffer */
|
||||
|
|
@ -2235,7 +2251,7 @@ accept_mtrace(src, dst, group, data, no, datalen)
|
|||
} else {
|
||||
if (scoped_addr(vifi, group))
|
||||
resp->tr_rflags = TR_SCOPED;
|
||||
else if (!VIFM_ISSET(vifi, rt->rt_children))
|
||||
else if (rt && !VIFM_ISSET(vifi, rt->rt_children))
|
||||
resp->tr_rflags = TR_NO_FWD;
|
||||
}
|
||||
|
||||
|
|
@ -2290,22 +2306,30 @@ sendit:
|
|||
resptype = IGMP_MTRACE;
|
||||
}
|
||||
|
||||
log(LOG_DEBUG, 0, "Sending %s to %s from %s",
|
||||
resptype == IGMP_MTRACE_RESP ? "response" : "request on",
|
||||
inet_fmt(dst, s1), inet_fmt(src, s2));
|
||||
|
||||
if (IN_MULTICAST(ntohl(dst))) {
|
||||
k_set_ttl(qry->tr_rttl);
|
||||
/* Let the kernel pick the source address, since we might have picked
|
||||
* a disabled phyint to multicast on.
|
||||
/*
|
||||
* Send the reply on a known multicast capable vif.
|
||||
* If we don't have one, we can't source any multicasts anyway.
|
||||
*/
|
||||
send_igmp(INADDR_ANY, dst,
|
||||
resptype, no, group,
|
||||
datalen);
|
||||
k_set_ttl(1);
|
||||
} else
|
||||
if (phys_vif != -1) {
|
||||
log(LOG_DEBUG, 0, "Sending reply to %s from %s",
|
||||
inet_fmt(dst, s1), inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2));
|
||||
k_set_ttl(qry->tr_rttl);
|
||||
send_igmp(uvifs[phys_vif].uv_lcl_addr, dst,
|
||||
resptype, no, group,
|
||||
datalen);
|
||||
k_set_ttl(1);
|
||||
} else
|
||||
log(LOG_INFO, 0, "No enabled phyints -- %s",
|
||||
"dropping traceroute reply");
|
||||
} else {
|
||||
log(LOG_DEBUG, 0, "Sending %s to %s from %s",
|
||||
resptype == IGMP_MTRACE_RESP ? "reply" : "request on",
|
||||
inet_fmt(dst, s1), inet_fmt(src, s2));
|
||||
|
||||
send_igmp(src, dst,
|
||||
resptype, no, group,
|
||||
datalen);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: prune.h,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: prune.h,v 3.6 1995/06/25 19:19:04 fenner Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -131,8 +131,8 @@ struct tr_resp {
|
|||
|
||||
#define MASK_TO_VAL(x, i) { \
|
||||
u_int32 _x = ntohl(x); \
|
||||
(i) = 0; \
|
||||
while ((_x) << (i)) \
|
||||
(i) = 1; \
|
||||
while ((_x) <<= 1) \
|
||||
(i)++; \
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: route.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: route.c,v 3.6 1995/06/25 19:20:19 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -38,6 +38,18 @@ static struct rtentry *rtp; /* pointer to a route entry */
|
|||
static struct rtentry *rt_end; /* pointer to last route entry */
|
||||
unsigned int nroutes; /* current number of route entries */
|
||||
|
||||
/*
|
||||
* Private functions.
|
||||
*/
|
||||
static int init_children_and_leaves __P((struct rtentry *r,
|
||||
vifi_t parent));
|
||||
static int find_route __P((u_int32 origin, u_int32 mask));
|
||||
static void create_route __P((u_int32 origin, u_int32 mask));
|
||||
static void discard_route __P((struct rtentry *prev_r));
|
||||
static int compare_rts __P((const void *rt1, const void *rt2));
|
||||
static int report_chunk __P((struct rtentry *start_rt, vifi_t vifi,
|
||||
u_int32 dst));
|
||||
|
||||
/*
|
||||
* Initialize the routing table and associated variables.
|
||||
*/
|
||||
|
|
@ -45,6 +57,7 @@ void
|
|||
init_routes()
|
||||
{
|
||||
routing_table = NULL;
|
||||
rt_end = RT_ADDR;
|
||||
nroutes = 0;
|
||||
routes_changed = FALSE;
|
||||
delay_change_reports = FALSE;
|
||||
|
|
@ -284,7 +297,7 @@ create_route(origin, mask)
|
|||
|
||||
if ((r = (struct rtentry *) malloc(sizeof(struct rtentry) +
|
||||
(2 * numvifs * sizeof(u_int32)) +
|
||||
(numvifs * sizeof(u_long)))) == NULL) {
|
||||
(numvifs * sizeof(u_int)))) == NULL) {
|
||||
log(LOG_ERR, 0, "ran out of memory"); /* fatal */
|
||||
}
|
||||
r->rt_origin = origin;
|
||||
|
|
@ -296,7 +309,7 @@ create_route(origin, mask)
|
|||
r->rt_flags = 0;
|
||||
r->rt_dominants = (u_int32 *)(r + 1);
|
||||
r->rt_subordinates = (u_int32 *)(r->rt_dominants + numvifs);
|
||||
r->rt_leaf_timers = (u_long *)(r->rt_subordinates + numvifs);
|
||||
r->rt_leaf_timers = (u_int *)(r->rt_subordinates + numvifs);
|
||||
r->rt_groups = NULL;
|
||||
|
||||
r->rt_next = rtp->rt_next;
|
||||
|
|
@ -345,7 +358,6 @@ update_route(origin, mask, metric, src, vifi)
|
|||
vifi_t vifi;
|
||||
{
|
||||
register struct rtentry *r;
|
||||
struct rtentry *prev_r;
|
||||
int adj_metric;
|
||||
|
||||
/*
|
||||
|
|
@ -366,10 +378,6 @@ update_route(origin, mask, metric, src, vifi)
|
|||
* Look up the reported origin in the routing table.
|
||||
*/
|
||||
if (!find_route(origin, mask)) {
|
||||
register struct rtentry *rp;
|
||||
register struct gtable *gt;
|
||||
register struct stable *st, **stnp;
|
||||
|
||||
/*
|
||||
* Not found.
|
||||
* Don't create a new entry if the report says it's unreachable,
|
||||
|
|
@ -697,10 +705,7 @@ accept_probe(src, dst, p, datalen, level)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!update_neighbor(vifi, src, DVMRP_PROBE, p, datalen, level))
|
||||
return;
|
||||
|
||||
report(ALL_ROUTES, vifi, src);
|
||||
update_neighbor(vifi, src, DVMRP_PROBE, p, datalen, level);
|
||||
}
|
||||
|
||||
struct newrt {
|
||||
|
|
@ -710,11 +715,13 @@ struct newrt {
|
|||
int pad;
|
||||
};
|
||||
|
||||
int
|
||||
compare_rts(r1, r2)
|
||||
register struct newrt *r1;
|
||||
register struct newrt *r2;
|
||||
static int
|
||||
compare_rts(rt1, rt2)
|
||||
const void *rt1;
|
||||
const void *rt2;
|
||||
{
|
||||
register struct newrt *r1 = (struct newrt *)rt1;
|
||||
register struct newrt *r2 = (struct newrt *)rt2;
|
||||
register u_int32 m1 = ntohl(r1->mask);
|
||||
register u_int32 m2 = ntohl(r2->mask);
|
||||
register u_int32 o1, o2;
|
||||
|
|
@ -830,17 +837,15 @@ report(which_routes, vifi, dst)
|
|||
register struct rtentry *r;
|
||||
register char *p;
|
||||
register int i;
|
||||
int datalen;
|
||||
int width;
|
||||
u_int32 mask;
|
||||
int datalen = 0;
|
||||
int width = 0;
|
||||
u_int32 mask = 0;
|
||||
u_int32 src;
|
||||
u_int32 nflags;
|
||||
|
||||
src = uvifs[vifi].uv_lcl_addr;
|
||||
|
||||
p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
|
||||
datalen = 0;
|
||||
mask = 0;
|
||||
|
||||
#ifdef NOTYET
|
||||
/* If I'm not a leaf, but the neighbor is a leaf, only advertise default */
|
||||
|
|
@ -880,7 +885,7 @@ report(which_routes, vifi, dst)
|
|||
mask = 0;
|
||||
}
|
||||
|
||||
if(r->rt_originmask != mask) {
|
||||
if (r->rt_originmask != mask || datalen == 0) {
|
||||
mask = r->rt_originmask;
|
||||
width = r->rt_originwidth;
|
||||
if (datalen != 0) *(p-1) |= 0x80;
|
||||
|
|
@ -961,7 +966,7 @@ report_to_all_neighbors(which_routes)
|
|||
* Send a route report message to destination 'dst', via virtual interface
|
||||
* 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
report_chunk(start_rt, vifi, dst)
|
||||
register struct rtentry *start_rt;
|
||||
vifi_t vifi;
|
||||
|
|
@ -971,16 +976,14 @@ report_chunk(start_rt, vifi, dst)
|
|||
register char *p;
|
||||
register int i;
|
||||
register int nrt = 0;
|
||||
int datalen;
|
||||
int width;
|
||||
u_int32 mask;
|
||||
int datalen = 0;
|
||||
int width = 0;
|
||||
u_int32 mask = 0;
|
||||
u_int32 src;
|
||||
u_int32 nflags;
|
||||
|
||||
src = uvifs[vifi].uv_lcl_addr;
|
||||
p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
|
||||
datalen = 0;
|
||||
mask = 0;
|
||||
|
||||
nflags = (uvifs[vifi].uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS;
|
||||
|
||||
|
|
@ -1007,7 +1010,7 @@ report_chunk(start_rt, vifi, dst)
|
|||
htonl(MROUTED_LEVEL | nflags), datalen);
|
||||
return (nrt);
|
||||
}
|
||||
if(r->rt_originmask != mask) {
|
||||
if (r->rt_originmask != mask || datalen == 0) {
|
||||
mask = r->rt_originmask;
|
||||
width = r->rt_originwidth;
|
||||
if (datalen != 0) *(p-1) |= 0x80;
|
||||
|
|
@ -1096,13 +1099,12 @@ dump_routes(fp)
|
|||
{
|
||||
register struct rtentry *r;
|
||||
register int i;
|
||||
register time_t thyme = time(0);
|
||||
|
||||
|
||||
fprintf(fp,
|
||||
"Multicast Routing Table (%u %s)\n%s\n",
|
||||
nroutes, (nroutes == 1) ? "entry" : "entries",
|
||||
" Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs");
|
||||
" Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs");
|
||||
|
||||
for (r = routing_table; r != NULL; r = r->rt_next) {
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: route.h,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: route.h,v 3.6 1995/06/25 19:21:05 fenner Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -38,8 +38,8 @@ struct rtentry {
|
|||
vifbitmap_t rt_leaves; /* subset of outgoing children vifs */
|
||||
u_int32 *rt_dominants; /* per vif dominant gateways */
|
||||
u_int32 *rt_subordinates; /* per vif subordinate gateways */
|
||||
u_long *rt_leaf_timers; /* per vif leaf confirmation timers */
|
||||
u_long rt_timer; /* for timing out the route entry */
|
||||
u_int *rt_leaf_timers; /* per vif leaf confirmation timers */
|
||||
u_int rt_timer; /* for timing out the route entry */
|
||||
struct rtentry *rt_prev; /* link to previous entry */
|
||||
struct gtable *rt_groups; /* link to active groups */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@
|
|||
|
||||
#include "defs.h"
|
||||
#include <sys/param.h>
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
/* Taken from prune.c */
|
||||
/*
|
||||
|
|
@ -66,11 +68,13 @@ int client_length = sizeof(client_addr);
|
|||
/*
|
||||
* Procedure definitions needed internally.
|
||||
*/
|
||||
void rsrr_accept();
|
||||
void rsrr_accept_iq();
|
||||
int rsrr_accept_rq();
|
||||
int rsrr_send();
|
||||
void rsrr_cache();
|
||||
static void rsrr_accept __P((int recvlen));
|
||||
static void rsrr_accept_iq __P((void));
|
||||
static int rsrr_accept_rq __P((struct rsrr_rq *route_query, int flags,
|
||||
struct gtable *gt_notify));
|
||||
static int rsrr_send __P((int sendlen));
|
||||
static void rsrr_cache __P((struct gtable *gt,
|
||||
struct rsrr_rq *route_query));
|
||||
|
||||
/* Initialize RSRR socket */
|
||||
void
|
||||
|
|
@ -86,9 +90,9 @@ rsrr_init()
|
|||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
serv_addr.sun_family = AF_UNIX;
|
||||
strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
|
||||
#if BSD >= 199103
|
||||
servlen = offsetof(struct sockaddr_un, sun_path)
|
||||
+ strlen(serv_addr.sun_path);
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
servlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
strlen(serv_addr.sun_path);
|
||||
serv_addr.sun_len = servlen;
|
||||
#else
|
||||
servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
|
||||
|
|
@ -103,14 +107,15 @@ rsrr_init()
|
|||
|
||||
/* Read a message from the RSRR socket */
|
||||
void
|
||||
rsrr_read()
|
||||
rsrr_read(rfd)
|
||||
fd_set *rfd;
|
||||
{
|
||||
register int rsrr_recvlen;
|
||||
register int omask;
|
||||
|
||||
bzero((char *) &client_addr, sizeof(client_addr));
|
||||
rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
|
||||
0, (struct sockaddr *)&client_addr,&client_length);
|
||||
0, (struct sockaddr *)&client_addr, &client_length);
|
||||
if (rsrr_recvlen < 0) {
|
||||
if (errno != EINTR)
|
||||
log(LOG_ERR, errno, "RSRR recvfrom");
|
||||
|
|
@ -125,7 +130,7 @@ rsrr_read()
|
|||
/* Accept a message from the reservation protocol and take
|
||||
* appropriate action.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
rsrr_accept(recvlen)
|
||||
int recvlen;
|
||||
{
|
||||
|
|
@ -191,7 +196,7 @@ rsrr_accept(recvlen)
|
|||
}
|
||||
|
||||
/* Send an Initial Reply to the reservation protocol. */
|
||||
void
|
||||
static void
|
||||
rsrr_accept_iq()
|
||||
{
|
||||
struct rsrr_header *rsrr;
|
||||
|
|
@ -243,7 +248,7 @@ rsrr_accept_iq()
|
|||
* kernel table entry contains the routing info to use for a route
|
||||
* change notification.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
rsrr_accept_rq(route_query,flags,gt_notify)
|
||||
struct rsrr_rq *route_query;
|
||||
int flags;
|
||||
|
|
@ -363,7 +368,7 @@ rsrr_accept_rq(route_query,flags,gt_notify)
|
|||
}
|
||||
|
||||
/* Send an RSRR message. */
|
||||
int
|
||||
static int
|
||||
rsrr_send(sendlen)
|
||||
int sendlen;
|
||||
{
|
||||
|
|
@ -376,30 +381,28 @@ rsrr_send(sendlen)
|
|||
/* Check for errors. */
|
||||
if (error < 0) {
|
||||
log(LOG_WARNING, errno, "Failed send on RSRR socket");
|
||||
return error;
|
||||
}
|
||||
if (error != sendlen) {
|
||||
} else if (error != sendlen) {
|
||||
log(LOG_WARNING, 0,
|
||||
"Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
|
||||
return error;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Cache a message being sent to a client. Currently only used for
|
||||
* caching Route Reply messages for route change notification.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
rsrr_cache(gt,route_query)
|
||||
struct gtable *gt;
|
||||
struct rsrr_rq *route_query;
|
||||
{
|
||||
struct rsrr_cache *rc,*rc_prev;
|
||||
struct rsrr_cache *rc, **rcnp;
|
||||
struct rsrr_header *rsrr;
|
||||
|
||||
rsrr = (struct rsrr_header *) rsrr_send_buf;
|
||||
|
||||
rc = gt->gt_rsrr_cache;
|
||||
while (rc) {
|
||||
rcnp = >->gt_rsrr_cache;
|
||||
while ((rc = *rcnp) != NULL) {
|
||||
if ((rc->route_query.source_addr.s_addr ==
|
||||
route_query->source_addr.s_addr) &&
|
||||
(rc->route_query.dest_addr.s_addr ==
|
||||
|
|
@ -410,22 +413,18 @@ rsrr_cache(gt,route_query)
|
|||
*/
|
||||
if (!BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)) {
|
||||
/* Delete cache entry. */
|
||||
if (rc == gt->gt_rsrr_cache)
|
||||
/* Deleting first entry. */
|
||||
gt->gt_rsrr_cache = rc->next;
|
||||
else
|
||||
rc_prev->next = rc->next;
|
||||
*rcnp = rc->next;
|
||||
free(rc);
|
||||
} else {
|
||||
/* Update */
|
||||
rc->route_query.query_id = route_query->query_id;
|
||||
printf("Update cached query id %d from client %s\n",
|
||||
rc->route_query.query_id,rc->client_addr.sun_path);
|
||||
log(LOG_DEBUG, 0,
|
||||
"Update cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id, rc->client_addr.sun_path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rc_prev = rc;
|
||||
rc = rc->next;
|
||||
rcnp = &rc->next;
|
||||
}
|
||||
|
||||
/* Cache entry doesn't already exist. Create one and insert at
|
||||
|
|
@ -441,7 +440,7 @@ rsrr_cache(gt,route_query)
|
|||
rc->client_length = client_length;
|
||||
rc->next = gt->gt_rsrr_cache;
|
||||
gt->gt_rsrr_cache = rc;
|
||||
printf("Cached query id %d from client %s\n",
|
||||
log(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id,rc->client_addr.sun_path);
|
||||
}
|
||||
|
||||
|
|
@ -453,30 +452,23 @@ rsrr_cache_send(gt,notify)
|
|||
struct gtable *gt;
|
||||
int notify;
|
||||
{
|
||||
struct rsrr_cache *rc,*rc_next,*rc_prev;
|
||||
struct rsrr_cache *rc, **rcnp;
|
||||
int flags = 0;
|
||||
|
||||
rc = gt->gt_rsrr_cache;
|
||||
while (rc) {
|
||||
rc_next = rc->next;
|
||||
|
||||
if (notify)
|
||||
BIT_SET(flags,RSRR_NOTIFICATION_BIT);
|
||||
if (notify)
|
||||
BIT_SET(flags,RSRR_NOTIFICATION_BIT);
|
||||
|
||||
rcnp = >->gt_rsrr_cache;
|
||||
while ((rc = *rcnp) != NULL) {
|
||||
if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) {
|
||||
printf("Deleting cached query id %d from client %s\n",
|
||||
log(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id,rc->client_addr.sun_path);
|
||||
/* Delete cache entry. */
|
||||
if (rc == gt->gt_rsrr_cache)
|
||||
/* Deleting first entry. */
|
||||
gt->gt_rsrr_cache = rc_next;
|
||||
else
|
||||
rc_prev->next = rc_next;
|
||||
*rcnp = rc->next;
|
||||
free(rc);
|
||||
} else {
|
||||
rc_prev = rc;
|
||||
rcnp = &rc->next;
|
||||
}
|
||||
rc = rc_next;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#define RSRR_ROUTE_QUERY 3
|
||||
#define RSRR_ROUTE_REPLY 4
|
||||
|
||||
/* RSRR Initial Reply (Vif) Status bits.
|
||||
/* RSRR Initial Reply (Vif) Status bits
|
||||
* Each definition represents the position of the bit from right to left.
|
||||
*
|
||||
* Right-most bit is the disabled bit, set if the vif is administratively
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
#define RSRR_DISABLED_BIT 0
|
||||
/* All other bits are zeroes */
|
||||
|
||||
/* RSRR Route Query/Reply flag bits.
|
||||
/* RSRR Route Query/Reply flag bits
|
||||
* Each definition represents the position of the bit from right to left.
|
||||
*
|
||||
* Right-most bit is the Route Change Notification bit, set if the
|
||||
|
|
|
|||
|
|
@ -7,31 +7,48 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: vif.c,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: vif.c,v 3.6 1995/06/25 19:53:01 fenner Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
*/
|
||||
struct uvif uvifs[MAXVIFS]; /* array of virtual interfaces */
|
||||
vifi_t numvifs; /* number of vifs in use */
|
||||
int vifs_down; /* 1=>some interfaces are down */
|
||||
struct uvif uvifs[MAXVIFS]; /* array of virtual interfaces */
|
||||
vifi_t numvifs; /* number of vifs in use */
|
||||
int vifs_down; /* 1=>some interfaces are down */
|
||||
int phys_vif; /* An enabled vif */
|
||||
int udp_socket; /* Since the honkin' kernel doesn't support */
|
||||
/* ioctls on raw IP sockets, we need a UDP */
|
||||
/* socket as well as our IGMP (raw) socket. */
|
||||
/* How dumb. */
|
||||
int vifs_with_neighbors; /* == 1 if I am a leaf */
|
||||
|
||||
typedef struct {
|
||||
vifi_t vifi;
|
||||
struct listaddr *g;
|
||||
int q_time;
|
||||
} cbk_t;
|
||||
|
||||
static cbk_t *cbk;
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
static void start_vif();
|
||||
static void stop_vif();
|
||||
static void age_old_hosts();
|
||||
static void start_vif __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 SetTimer __P((int vifi, struct listaddr *g));
|
||||
static int DeleteTimer __P((int id));
|
||||
static void SendQuery __P((cbk_t *cbk));
|
||||
static int SetQueryTimer __P((struct listaddr *g, vifi_t vifi, int to_expire,
|
||||
int q_time));
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the virtual interfaces.
|
||||
|
|
@ -45,6 +62,7 @@ init_vifs()
|
|||
extern char *configfilename;
|
||||
|
||||
numvifs = 0;
|
||||
vifs_with_neighbors = 0;
|
||||
vifs_down = FALSE;
|
||||
|
||||
/*
|
||||
|
|
@ -64,11 +82,15 @@ init_vifs()
|
|||
*/
|
||||
enabled_vifs = 0;
|
||||
enabled_phyints = 0;
|
||||
phys_vif = -1;
|
||||
for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
|
||||
if (!(v->uv_flags & VIFF_DISABLED)) {
|
||||
++enabled_vifs;
|
||||
if (!(v->uv_flags & VIFF_TUNNEL))
|
||||
if (!(v->uv_flags & VIFF_TUNNEL)) {
|
||||
if (phys_vif == -1)
|
||||
phys_vif = vifi;
|
||||
++enabled_phyints;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enabled_vifs < 2)
|
||||
|
|
@ -83,17 +105,17 @@ init_vifs()
|
|||
* 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 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));
|
||||
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));
|
||||
log(LOG_INFO, 0, "vif #%d, phyint %s", vifi,
|
||||
inet_fmt(v->uv_lcl_addr, s1));
|
||||
start_vif(vifi);
|
||||
} else log(LOG_INFO, 0,
|
||||
"%s is not yet up; vif #%u not in service",
|
||||
|
|
@ -152,7 +174,7 @@ check_vif_state()
|
|||
/*
|
||||
* Send a probe message on vif v
|
||||
*/
|
||||
void
|
||||
static void
|
||||
send_probe_on_vif(v)
|
||||
register struct uvif *v;
|
||||
{
|
||||
|
|
@ -237,7 +259,7 @@ start_vif(vifi)
|
|||
update_route(v->uv_subnet, v->uv_subnetmask, 0, 0, vifi);
|
||||
for (p = v->uv_addrs; p; p = p->pa_next) {
|
||||
start_route_updates();
|
||||
update_route(p->pa_addr, p->pa_mask, 0, 0, vifi);
|
||||
update_route(p->pa_subnet, p->pa_subnetmask, 0, 0, vifi);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -292,7 +314,7 @@ stop_vif(vifi)
|
|||
update_route(v->uv_subnet, v->uv_subnetmask, UNREACHABLE, 0, vifi);
|
||||
for (p = v->uv_addrs; p; p = p->pa_next) {
|
||||
start_route_updates();
|
||||
update_route(p->pa_addr, p->pa_mask, UNREACHABLE, 0, vifi);
|
||||
update_route(p->pa_subnet, p->pa_subnetmask, UNREACHABLE, 0, vifi);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -385,11 +407,13 @@ find_vif(src, dst)
|
|||
}
|
||||
else {
|
||||
if ((src & v->uv_subnetmask) == v->uv_subnet &&
|
||||
src != v->uv_subnetbcast)
|
||||
((v->uv_subnetmask == 0xffffffff) ||
|
||||
(src != v->uv_subnetbcast)))
|
||||
return(vifi);
|
||||
for (p=v->uv_addrs; p; p=p->pa_next) {
|
||||
if ((src & p->pa_mask) == p->pa_addr &&
|
||||
src != p->pa_addr)
|
||||
if ((src & p->pa_subnetmask) == p->pa_subnet &&
|
||||
((p->pa_subnetmask == 0xffffffff) ||
|
||||
(src != p->pa_subnetbcast)))
|
||||
return(vifi);
|
||||
}
|
||||
}
|
||||
|
|
@ -527,7 +551,7 @@ 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){
|
||||
if (r_type == IGMP_HOST_NEW_MEMBERSHIP_REPORT) {
|
||||
g->al_last = OLD_AGE_THRESHOLD;
|
||||
g->al_old = 0;
|
||||
}
|
||||
|
|
@ -555,7 +579,7 @@ accept_group_report(src, dst, group, r_type)
|
|||
|
||||
|
||||
void
|
||||
accept_leave_message( src, dst, group)
|
||||
accept_leave_message(src, dst, group)
|
||||
u_int32 src, dst, group;
|
||||
{
|
||||
register vifi_t vifi;
|
||||
|
|
@ -840,7 +864,7 @@ accept_neighbor_request2(src, dst)
|
|||
void
|
||||
accept_neighbors(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
log(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list from %s to %s",
|
||||
|
|
@ -854,7 +878,7 @@ accept_neighbors(src, dst, p, datalen, level)
|
|||
void
|
||||
accept_neighbors2(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
log(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list2 from %s to %s",
|
||||
|
|
@ -880,7 +904,8 @@ update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
|||
register struct listaddr *n;
|
||||
u_int32 genid = 0;
|
||||
u_int32 router;
|
||||
int he_hears_me = TRUE;
|
||||
u_int32 send_tables = 0;
|
||||
int do_reset = FALSE;
|
||||
int nflags;
|
||||
|
||||
v = &uvifs[vifi];
|
||||
|
|
@ -907,18 +932,83 @@ update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
|||
}
|
||||
|
||||
/*
|
||||
* If we have received a route report from a neighbor, and we believed
|
||||
* that we had no neighbors on this vif, send a full route report to
|
||||
* all neighbors on the vif.
|
||||
* Look for addr in list of neighbors.
|
||||
*/
|
||||
|
||||
if (msgtype == DVMRP_REPORT && v->uv_neighbors == NULL)
|
||||
report(ALL_ROUTES, vifi,
|
||||
(v->uv_flags & VIFF_TUNNEL) ? addr : dvmrp_group);
|
||||
for (n = v->uv_neighbors; n != NULL; n = n->al_next) {
|
||||
if (addr == n->al_addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the router gen-ids are the same (only if vers > 3.2)
|
||||
* Found it. Reset its timer, and check for a version change
|
||||
*/
|
||||
if (n) {
|
||||
n->al_timer = 0;
|
||||
|
||||
/*
|
||||
* 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))) {
|
||||
|
||||
do_reset = TRUE;
|
||||
log(LOG_DEBUG, 0,
|
||||
"version change 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;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If not found, add it to the list. If the neighbor has a lower
|
||||
* IP address than me, yield querier duties to it.
|
||||
*/
|
||||
log(LOG_DEBUG, 0, "New neighbor %s on vif %d v%d.%d nf 0x%02x",
|
||||
inet_fmt(addr, s1), vifi, level & 0xff, (level >> 8) & 0xff,
|
||||
(level >> 16) & 0xff);
|
||||
|
||||
n = (struct listaddr *)malloc(sizeof(struct listaddr));
|
||||
if (n == NULL)
|
||||
log(LOG_ERR, 0, "ran out of memory"); /* fatal */
|
||||
|
||||
n->al_addr = addr;
|
||||
n->al_pv = level & 0xff;
|
||||
n->al_mv = (level >> 8) & 0xff;
|
||||
n->al_genid = 0;
|
||||
|
||||
time(&n->al_ctime);
|
||||
n->al_timer = 0;
|
||||
n->al_next = v->uv_neighbors;
|
||||
|
||||
/*
|
||||
* If we thought that we had no neighbors on this vif, send a route
|
||||
* report to the vif. If this is just a new neighbor on the same
|
||||
* vif, send the route report just to the new neighbor.
|
||||
*/
|
||||
if (v->uv_neighbors == NULL) {
|
||||
send_tables = (v->uv_flags & VIFF_TUNNEL) ? addr : dvmrp_group;
|
||||
vifs_with_neighbors++;
|
||||
} else {
|
||||
send_tables = addr;
|
||||
}
|
||||
|
||||
v->uv_neighbors = n;
|
||||
|
||||
if (!(v->uv_flags & VIFF_TUNNEL) &&
|
||||
ntohl(addr) < ntohl(v->uv_lcl_addr))
|
||||
v->uv_flags &= ~VIFF_QUERIER;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the router gen-ids are the same.
|
||||
* Need to reset the prune state of the router if not.
|
||||
* Also check for one-way interfaces by seeing if we are in our
|
||||
* neighbor's list of known routers.
|
||||
*/
|
||||
if (msgtype == DVMRP_PROBE) {
|
||||
|
||||
|
|
@ -938,13 +1028,24 @@ update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
|||
|
||||
for (i = 0; i < 4; i++)
|
||||
((char *)&genid)[i] = *p++;
|
||||
datalen -=4;
|
||||
datalen -= 4;
|
||||
|
||||
if (n->al_genid == 0)
|
||||
n->al_genid = genid;
|
||||
else if (n->al_genid != genid) {
|
||||
log(LOG_DEBUG, 0,
|
||||
"new genid neigbor %s on vif %d [old:%x, new:%x]",
|
||||
inet_fmt(addr, s1), vifi, n->al_genid, genid);
|
||||
|
||||
n->al_genid = genid;
|
||||
do_reset = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* loop through router list and check for one-way ifs.
|
||||
*/
|
||||
|
||||
he_hears_me = FALSE;
|
||||
v->uv_flags |= VIFF_ONEWAY;
|
||||
|
||||
while (datalen > 0) {
|
||||
if (datalen < 4) {
|
||||
|
|
@ -957,139 +1058,37 @@ update_neighbor(vifi, addr, msgtype, p, datalen, level)
|
|||
((char *)&router)[i] = *p++;
|
||||
datalen -= 4;
|
||||
if (router == v->uv_lcl_addr) {
|
||||
he_hears_me = TRUE;
|
||||
v->uv_flags &= ~VIFF_ONEWAY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Look for addr in list of neighbors; if found, reset its timer.
|
||||
*/
|
||||
for (n = v->uv_neighbors; n != NULL; n = n->al_next) {
|
||||
if (addr == n->al_addr) {
|
||||
n->al_timer = 0;
|
||||
if (n->al_flags != nflags) {
|
||||
n->al_flags = nflags;
|
||||
|
||||
/*
|
||||
* If probe message and version no >= 3.3 check genid
|
||||
*/
|
||||
if (msgtype == DVMRP_PROBE &&
|
||||
((n->al_pv >= 3 && n->al_mv > 2) || n->al_pv > 3)) {
|
||||
if (he_hears_me == TRUE && v->uv_flags & VIFF_ONEWAY)
|
||||
v->uv_flags &= ~VIFF_ONEWAY;
|
||||
|
||||
if (he_hears_me == FALSE)
|
||||
v->uv_flags |= VIFF_ONEWAY;
|
||||
|
||||
if (n->al_genid == 0)
|
||||
n->al_genid = genid;
|
||||
else if (n->al_genid != genid) {
|
||||
log(LOG_DEBUG, 0,
|
||||
"reset neighbor %s on vif %d [old genid:%x, new:%x]",
|
||||
inet_fmt(addr, s1), vifi, n->al_genid, genid);
|
||||
|
||||
n->al_genid = genid;
|
||||
n->al_pv = level & 0xff;
|
||||
n->al_mv = (level >> 8) & 0xff;
|
||||
n->al_flags = 0; /*XXX*/
|
||||
reset_neighbor_state(vifi, addr);
|
||||
|
||||
/*
|
||||
* need to do a full route report here
|
||||
* it gets done by accept_probe()
|
||||
*/
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*XXX nflags shouldn't be dealt with in 2 places in the same
|
||||
*XXX routine...*/
|
||||
if (n->al_flags != nflags) {
|
||||
n->al_flags = nflags;
|
||||
if (nflags & NF_LEAF) {
|
||||
if (!v->uv_leaf_timer)
|
||||
v->uv_leaf_timer = LEAF_CONFIRMATION_TIME;
|
||||
} else {
|
||||
v->uv_flags &= ~VIFF_LEAF;
|
||||
v->uv_leaf_timer = 0;
|
||||
}
|
||||
/* Neighbor flags changed, do a full report */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (n->al_flags & NF_LEAF) {
|
||||
/*XXX If we have non-leaf neighbors then we know we shouldn't
|
||||
* mark this vif as a leaf. For now we just count on other
|
||||
* probes and/or reports resetting the timer. */
|
||||
if (!v->uv_leaf_timer)
|
||||
v->uv_leaf_timer = LEAF_CONFIRMATION_TIME;
|
||||
} else {
|
||||
/* If we get a leaf to non-leaf transition, we *must* update
|
||||
* the routing table. */
|
||||
if (v->uv_flags & VIFF_LEAF && send_tables == 0)
|
||||
send_tables = addr;
|
||||
v->uv_flags &= ~VIFF_LEAF;
|
||||
v->uv_leaf_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not found, add it to the list. If the neighbor has a lower
|
||||
* IP address than me, yield querier duties to it.
|
||||
*/
|
||||
if (n == NULL) {
|
||||
log(LOG_DEBUG, 0, "New neighbor %s on vif %d v%d.%d nf 0x%02x",
|
||||
inet_fmt(addr, s1), vifi, level & 0xff, (level >> 8) & 0xff,
|
||||
(level >> 16) & 0xff);
|
||||
|
||||
n = (struct listaddr *)malloc(sizeof(struct listaddr));
|
||||
if (n == NULL)
|
||||
log(LOG_ERR, 0, "ran out of memory"); /* fatal */
|
||||
|
||||
n->al_addr = addr;
|
||||
n->al_pv = level & 0xff;
|
||||
n->al_mv = (level >> 8) & 0xff;
|
||||
if (msgtype == DVMRP_PROBE)
|
||||
n->al_genid = genid;
|
||||
else
|
||||
n->al_genid = 0;
|
||||
|
||||
time(&n->al_ctime);
|
||||
n->al_timer = 0;
|
||||
n->al_next = v->uv_neighbors;
|
||||
|
||||
if (v->uv_neighbors == NULL)
|
||||
vifs_with_neighbors++;
|
||||
|
||||
v->uv_neighbors = n;
|
||||
|
||||
if (!(v->uv_flags & VIFF_TUNNEL) &&
|
||||
ntohl(addr) < ntohl(v->uv_lcl_addr))
|
||||
v->uv_flags &= ~VIFF_QUERIER;
|
||||
}
|
||||
|
||||
n->al_flags = nflags;
|
||||
if (!(n->al_flags & NF_LEAF)) {
|
||||
v->uv_flags &= ~VIFF_LEAF;
|
||||
v->uv_leaf_timer = 0;
|
||||
} else {
|
||||
/*XXX If we have non-leaf neighbors then we know we shouldn't
|
||||
* mark this vif as a leaf. For now we just count on other
|
||||
* probes and/or reports resetting the timer. */
|
||||
if (!v->uv_leaf_timer)
|
||||
v->uv_leaf_timer = LEAF_CONFIRMATION_TIME;
|
||||
if (do_reset) {
|
||||
reset_neighbor_state(vifi, addr);
|
||||
if (!send_tables)
|
||||
send_tables = addr;
|
||||
}
|
||||
if (send_tables)
|
||||
report(ALL_ROUTES, vifi, send_tables);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
|
@ -1170,20 +1169,6 @@ neighbor_info(vifi, addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the neighbor's version number
|
||||
* returns (protocol_version << 8 + mrouted_version) of neighbor
|
||||
*/
|
||||
int
|
||||
nbr_vers(vifi, addr)
|
||||
vifi_t vifi;
|
||||
u_int32 addr;
|
||||
{
|
||||
struct listaddr *u = neighbor_info(vifi, addr);
|
||||
|
||||
return u ? NBR_VERS(u) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the contents of the uvifs array on file 'fp'.
|
||||
*/
|
||||
|
|
@ -1234,10 +1219,10 @@ dump_vifs(fp)
|
|||
|
||||
if (v->uv_addrs != NULL) {
|
||||
fprintf(fp, " alternate subnets: %s\n",
|
||||
inet_fmts(v->uv_addrs->pa_addr, v->uv_addrs->pa_mask, s1));
|
||||
inet_fmts(v->uv_addrs->pa_subnet, v->uv_addrs->pa_subnetmask, s1));
|
||||
for (p = v->uv_addrs->pa_next; p; p = p->pa_next) {
|
||||
fprintf(fp, " %s\n",
|
||||
inet_fmts(p->pa_addr, p->pa_mask, s1));
|
||||
inet_fmts(p->pa_subnet, p->pa_subnetmask, s1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1277,9 +1262,9 @@ dump_vifs(fp)
|
|||
"SIOCGETVIFCNT fails");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, " pkts in : %d\n",
|
||||
fprintf(fp, " pkts in : %ld\n",
|
||||
v_req.icount);
|
||||
fprintf(fp, " pkts out: %d\n",
|
||||
fprintf(fp, " pkts out: %ld\n",
|
||||
v_req.ocount);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
|
@ -1290,15 +1275,7 @@ dump_vifs(fp)
|
|||
|
||||
/**** the timeout routines ********/
|
||||
|
||||
typedef struct {
|
||||
vifi_t vifi;
|
||||
struct listaddr *g;
|
||||
int q_time;
|
||||
} cbk_t;
|
||||
|
||||
static cbk_t *cbk;
|
||||
|
||||
void
|
||||
static void
|
||||
DelVif(cbk)
|
||||
cbk_t *cbk;
|
||||
{
|
||||
|
|
@ -1320,7 +1297,7 @@ cbk_t *cbk;
|
|||
* Group has expired
|
||||
* delete all kernel cache entries with this group
|
||||
*/
|
||||
if( g->al_query) DeleteTimer(g->al_query);
|
||||
if (g->al_query) DeleteTimer(g->al_query);
|
||||
delete_lclgrp(vifi, a->al_addr);
|
||||
|
||||
prev_a->al_next = a->al_next;
|
||||
|
|
@ -1331,38 +1308,38 @@ cbk_t *cbk;
|
|||
free(cbk);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SetTimer( vifi, g)
|
||||
static int
|
||||
SetTimer(vifi, 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,DelVif,cbk);
|
||||
return timer_setTimer(g->al_timer, (cfunc_t)DelVif, (void *)cbk);
|
||||
}
|
||||
|
||||
int
|
||||
DeleteTimer( id)
|
||||
static int
|
||||
DeleteTimer(id)
|
||||
int id;
|
||||
{
|
||||
timer_clearTimer(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
SendQuery(cbk)
|
||||
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, 0, 0);
|
||||
cbk->g->al_query = 0;
|
||||
free(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, 0, 0);
|
||||
cbk->g->al_query = 0;
|
||||
free(cbk);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
SetQueryTimer(g , vifi, to_expire, q_time)
|
||||
struct listaddr *g; vifi_t vifi;
|
||||
int to_expire, q_time;
|
||||
|
|
@ -1370,5 +1347,5 @@ SetQueryTimer(g , vifi, 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,SendQuery,cbk);
|
||||
return timer_setTimer(to_expire, (cfunc_t)SendQuery, (void *)cbk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: vif.h,v 3.5 1995/05/09 01:00:39 fenner Exp $
|
||||
* $Id: vif.h,v 3.6 1995/06/25 19:53:22 fenner Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -44,8 +44,9 @@ struct uvif {
|
|||
|
||||
struct phaddr {
|
||||
struct phaddr *pa_next;
|
||||
u_long pa_addr;
|
||||
u_long pa_mask;
|
||||
u_int32 pa_subnet; /* extra subnet */
|
||||
u_int32 pa_subnetmask; /* netmask of extra subnet */
|
||||
u_int32 pa_subnetbcast; /* broadcast of extra subnet */
|
||||
};
|
||||
|
||||
struct vif_acl {
|
||||
|
|
|
|||
Loading…
Reference in a new issue