diff options
author | wollman <wollman@FreeBSD.org> | 1995-06-28 17:58:49 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1995-06-28 17:58:49 +0000 |
commit | d3f63bd3ee5c661b428cd8a799861660da144b7b (patch) | |
tree | 585fe426376ddd559974a1fec24c87c188352816 /usr.sbin/mrouted | |
parent | 6b90340edba96eb6b139fc853617c8e7cbb10e3c (diff) | |
download | FreeBSD-src-d3f63bd3ee5c661b428cd8a799861660da144b7b.zip FreeBSD-src-d3f63bd3ee5c661b428cd8a799861660da144b7b.tar.gz |
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>
Diffstat (limited to 'usr.sbin/mrouted')
-rw-r--r-- | usr.sbin/mrouted/callout.c | 60 | ||||
-rw-r--r-- | usr.sbin/mrouted/cfparse.y | 81 | ||||
-rw-r--r-- | usr.sbin/mrouted/config.c | 5 | ||||
-rw-r--r-- | usr.sbin/mrouted/defs.h | 268 | ||||
-rw-r--r-- | usr.sbin/mrouted/dvmrp.h | 6 | ||||
-rw-r--r-- | usr.sbin/mrouted/igmp.c | 53 | ||||
-rw-r--r-- | usr.sbin/mrouted/inet.c | 24 | ||||
-rw-r--r-- | usr.sbin/mrouted/kern.c | 8 | ||||
-rw-r--r-- | usr.sbin/mrouted/main.c | 104 | ||||
-rw-r--r-- | usr.sbin/mrouted/mapper.c | 105 | ||||
-rw-r--r-- | usr.sbin/mrouted/mrinfo.c | 151 | ||||
-rw-r--r-- | usr.sbin/mrouted/mrouted.8 | 8 | ||||
-rw-r--r-- | usr.sbin/mrouted/mrouted.conf | 2 | ||||
-rw-r--r-- | usr.sbin/mrouted/mtrace.8 | 3 | ||||
-rw-r--r-- | usr.sbin/mrouted/mtrace.c | 468 | ||||
-rw-r--r-- | usr.sbin/mrouted/pathnames.h | 2 | ||||
-rw-r--r-- | usr.sbin/mrouted/prune.c | 208 | ||||
-rw-r--r-- | usr.sbin/mrouted/prune.h | 6 | ||||
-rw-r--r-- | usr.sbin/mrouted/route.c | 64 | ||||
-rw-r--r-- | usr.sbin/mrouted/route.h | 6 | ||||
-rw-r--r-- | usr.sbin/mrouted/rsrr.c | 86 | ||||
-rw-r--r-- | usr.sbin/mrouted/rsrr.h | 4 | ||||
-rw-r--r-- | usr.sbin/mrouted/vif.c | 381 | ||||
-rw-r--r-- | usr.sbin/mrouted/vif.h | 7 |
24 files changed, 1311 insertions, 799 deletions
diff --git a/usr.sbin/mrouted/callout.c b/usr.sbin/mrouted/callout.c index e2e81fb..29e44ec 100644 --- a/usr.sbin/mrouted/callout.c +++ b/usr.sbin/mrouted/callout.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: callout.c,v 3.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 */ diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y index 5c1402f..c08938d 100644 --- a/usr.sbin/mrouted/cfparse.y +++ b/usr.sbin/mrouted/cfparse.y @@ -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 diff --git a/usr.sbin/mrouted/config.c b/usr.sbin/mrouted/config.c index 0113807..56fdccb 100644 --- a/usr.sbin/mrouted/config.c +++ b/usr.sbin/mrouted/config.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: config.c,v 3.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; diff --git a/usr.sbin/mrouted/defs.h b/usr.sbin/mrouted/defs.h index b239557..5829314 100644 --- a/usr.sbin/mrouted/defs.h +++ b/usr.sbin/mrouted/defs.h @@ -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(); - -extern void init_igmp(); -extern void accept_igmp(); -extern void send_igmp(); - -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(); - -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(); - -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(); - -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(); - -extern void config_vifs_from_kernel(); -extern void config_vifs_from_file(); - -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(); - +/* main.c */ +extern void log __P((int, int, char *, ...)); +extern int register_input_handler __P((int fd, ihfunc_t func)); + +/* 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)); + +/* 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)); + +/* 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)); + +/* 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)); + +/* config.c */ +extern void config_vifs_from_kernel __P((void)); + +/* cfparse.y */ +extern void config_vifs_from_file __P((void)); + +/* 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 */ diff --git a/usr.sbin/mrouted/dvmrp.h b/usr.sbin/mrouted/dvmrp.h index 4a0a163..5553dc3 100644 --- a/usr.sbin/mrouted/dvmrp.h +++ b/usr.sbin/mrouted/dvmrp.h @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: dvmrp.h,v 3.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 */ diff --git a/usr.sbin/mrouted/igmp.c b/usr.sbin/mrouted/igmp.c index 5fe08e7..00eeff5 100644 --- a/usr.sbin/mrouted/igmp.c +++ b/usr.sbin/mrouted/igmp.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: igmp.c,v 3.5 1995/05/09 01:00:39 fenner Exp $ + * $Id: igmp.c,v 3.6 1995/06/25 18:52:55 fenner Exp $ */ @@ -17,8 +17,8 @@ /* * 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 */ @@ -26,10 +26,18 @@ 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)); } diff --git a/usr.sbin/mrouted/inet.c b/usr.sbin/mrouted/inet.c index b888bec..e8d5ab6 100644 --- a/usr.sbin/mrouted/inet.c +++ b/usr.sbin/mrouted/inet.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: inet.c,v 3.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; } diff --git a/usr.sbin/mrouted/kern.c b/usr.sbin/mrouted/kern.c index 9c308eb..a4030c8 100644 --- a/usr.sbin/mrouted/kern.c +++ b/usr.sbin/mrouted/kern.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: kern.c,v 3.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; diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c index efb3630..f66ce71 100644 --- a/usr.sbin/mrouted/main.c +++ b/usr.sbin/mrouted/main.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: main.c,v 3.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]; diff --git a/usr.sbin/mrouted/mapper.c b/usr.sbin/mrouted/mapper.c index 526ed9f..8c1c5fd 100644 --- a/usr.sbin/mrouted/mapper.c +++ b/usr.sbin/mrouted/mapper.c @@ -1,7 +1,7 @@ /* Mapper for connections between MRouteD multicast routers. * Written by Pavel Curtis <Pavel@PARC.Xerox.Com> * - * $Id: mapper.c,v 3.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; { } diff --git a/usr.sbin/mrouted/mrinfo.c b/usr.sbin/mrouted/mrinfo.c index 8f137d0..f4ccc86 100644 --- a/usr.sbin/mrouted/mrinfo.c +++ b/usr.sbin/mrouted/mrinfo.c @@ -61,7 +61,7 @@ #ifndef lint static char rcsid[] = - "@(#) $Id: mrinfo.c,v 3.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. */ +#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, a, b, c, d, e) +log(severity, syserr, format, va_alist) int severity, syserr; char *format; - int a, b, c, d, e; + 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; { } diff --git a/usr.sbin/mrouted/mrouted.8 b/usr.sbin/mrouted/mrouted.8 index 53dcec8..7dae5e3 100644 --- a/usr.sbin/mrouted/mrouted.8 +++ b/usr.sbin/mrouted/mrouted.8 @@ -1,5 +1,5 @@ '\"COPYRIGHT 1989 by The Board of Trustees of Leland Stanford Junior University. -'\"$Id: mrouted.8,v 3.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 diff --git a/usr.sbin/mrouted/mrouted.conf b/usr.sbin/mrouted/mrouted.conf index 993fd9e..4962d68 100644 --- a/usr.sbin/mrouted/mrouted.conf +++ b/usr.sbin/mrouted/mrouted.conf @@ -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". diff --git a/usr.sbin/mrouted/mtrace.8 b/usr.sbin/mrouted/mtrace.8 index bfc6dd5..c4ac218 100644 --- a/usr.sbin/mrouted/mtrace.8 +++ b/usr.sbin/mrouted/mtrace.8 @@ -29,7 +29,7 @@ .\" Copyright (c) 1988 The Regents of the University of California. .\" All rights reserved. .\" -.\" $Id: mtrace.8,v 3.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 diff --git a/usr.sbin/mrouted/mtrace.c b/usr.sbin/mrouted/mtrace.c index 42a6084..321b269 100644 --- a/usr.sbin/mrouted/mtrace.c +++ b/usr.sbin/mrouted/mtrace.c @@ -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)); @@ -1034,28 +1108,32 @@ Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\ } /* - * Make up the IGMP_MTRACE query packet to send (some parameters - * are set later), including initializing the seed for random - * query identifiers. + * If the response is to be a multicast address, make sure we + * are listening on that multicast address. */ - 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 (raddr) { + if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr); + } else k_join(resp_cast, lcl_addr); /* - * If the response is to be a multicast address, make sure we - * are listening on that multicast address. + * 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. */ - if (raddr && IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr); - else k_join(resp_cast, lcl_addr); + 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, ...) +{ + 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 { - char fmt[100]; + 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; +{ +} diff --git a/usr.sbin/mrouted/pathnames.h b/usr.sbin/mrouted/pathnames.h index 2022314..22b0019 100644 --- a/usr.sbin/mrouted/pathnames.h +++ b/usr.sbin/mrouted/pathnames.h @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: pathnames.h,v 3.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" diff --git a/usr.sbin/mrouted/prune.c b/usr.sbin/mrouted/prune.c index df4a8e5..f30b056 100644 --- a/usr.sbin/mrouted/prune.c +++ b/usr.sbin/mrouted/prune.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: prune.c,v 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); - - 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; + /* 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; } 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; } diff --git a/usr.sbin/mrouted/prune.h b/usr.sbin/mrouted/prune.h index dadba5d..eef9d28 100644 --- a/usr.sbin/mrouted/prune.h +++ b/usr.sbin/mrouted/prune.h @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: prune.h,v 3.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)++; \ }; diff --git a/usr.sbin/mrouted/route.c b/usr.sbin/mrouted/route.c index 756623f..38b9002 100644 --- a/usr.sbin/mrouted/route.c +++ b/usr.sbin/mrouted/route.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: route.c,v 3.5 1995/05/09 01:00:39 fenner Exp $ + * $Id: route.c,v 3.6 1995/06/25 19:20:19 fenner Exp $ */ @@ -39,12 +39,25 @@ 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. */ 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) { diff --git a/usr.sbin/mrouted/route.h b/usr.sbin/mrouted/route.h index fd84572..c947dd2 100644 --- a/usr.sbin/mrouted/route.h +++ b/usr.sbin/mrouted/route.h @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: route.h,v 3.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 */ }; diff --git a/usr.sbin/mrouted/rsrr.c b/usr.sbin/mrouted/rsrr.c index ceaf4ca..c7bbc89 100644 --- a/usr.sbin/mrouted/rsrr.c +++ b/usr.sbin/mrouted/rsrr.c @@ -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; } } diff --git a/usr.sbin/mrouted/rsrr.h b/usr.sbin/mrouted/rsrr.h index 4099dcd..8bc8c91 100644 --- a/usr.sbin/mrouted/rsrr.h +++ b/usr.sbin/mrouted/rsrr.h @@ -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 diff --git a/usr.sbin/mrouted/vif.c b/usr.sbin/mrouted/vif.c index 07878d8..98915aa 100644 --- a/usr.sbin/mrouted/vif.c +++ b/usr.sbin/mrouted/vif.c @@ -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. */ + for (n = v->uv_neighbors; n != NULL; n = n->al_next) { + if (addr == n->al_addr) { + break; + } + } + + /* + * 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); - if (msgtype == DVMRP_REPORT && v->uv_neighbors == NULL) - report(ALL_ROUTES, vifi, - (v->uv_flags & VIFF_TUNNEL) ? addr : dvmrp_group); + 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 (only if vers > 3.2) + * 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 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 != nflags) { + n->al_flags = nflags; + + 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); } @@ -1171,20 +1170,6 @@ neighbor_info(vifi, addr) } /* - * 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'. */ void @@ -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); } diff --git a/usr.sbin/mrouted/vif.h b/usr.sbin/mrouted/vif.h index 53c309e..57c1c8f 100644 --- a/usr.sbin/mrouted/vif.h +++ b/usr.sbin/mrouted/vif.h @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: vif.h,v 3.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 { |