home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
mrdebug.tar.Z
/
mrdebug.tar
/
mrdebug.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-29
|
11KB
|
357 lines
/************************************************************************
PURPOSE: M-Bone debugger.
DESCRIPTION:
This program reads a description of the M-Bone and it's
subnets and is able to predict multicast routes given
a source.
METHODOLOGY:
Once the network has been read in and stored in an
adjacency list, then a distance vector routing table
is built and the multicast routes are predicted assuming
the use of Steve Deering's truncated-broadcast algorithm.
PROGRAMMER: Deb Agarwal 6/1993
***********************************************************************/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include "types.h"
#include "mrhash.h"
#include "data_struct_proto.h"
#include "build_adj_proto.h"
#include "dist_vect_proto.h"
#include "user_proto.h"
/********EXTERNAL REFERENCES *************/
extern int getopt(int, char**, const char*);
extern char *optarg;
extern int optind;
/********GLOBALS **********/
Network mbone;
Ifc_list invisib_ifcs;
Ifc_list all_subnets;
Path_stack cur_path_stack;
int verbose;
int reverse_path; /* use reverse or forward metrics */
/*********Private Functions ****************/
void usage( char *exename );
void
main( int argc, char *argv[] )
{
char opt;
int done = FALSE, indent = 3, batch = FALSE, print_act_tree,
arg_cnt = 0, action = NO_ACTION;
long source = INVALID_NODE, last_source = INVALID_NODE,
destination = INVALID_NODE, max_thresh, extra_nodes = 0;
NAME src_name, dest_name, new_src_name, new_dest_name;
HENTRY_t *ht_entry_p;
char subnet_fl[MAXLINE],
network_fl[MAXLINE];
FILE *output;
Interface *temp_ifc;
verbose = FALSE;
reverse_path = FALSE;
/*
** Parse the input arguments supplied on the command line and
** set the appropriate variables.
*/
output = stdout;
strcpy( src_name, "\0");
strcpy( dest_name, "\0");
strcpy( new_src_name, "\0");
strcpy( new_dest_name, "\0");
source = INVALID_NODE;
destination = INVALID_NODE;
while ( ( opt = getopt( argc, argv, "m:o:s:d:i:a:pltv" )) != -1)
{
switch( opt )
{
case 'm':
/*
** The next argument specifies the name of the file containing
** the list of ip subnets.
*/
/*printf( "The subnets will be read from: %s\n", (char *) optarg );*/
strcpy(subnet_fl, optarg);
arg_cnt++;
break;
case 'o':
/*
** The next argument specifies the file to print the program
** output to. If not supplied, the output will go to stdout.
*/
printf( "Output will be printed to: %s\n", (char *)optarg);
if( !(output = fopen( (char *)optarg, "w" )))
{
printf( "ERROR: Unable to open output file named %s\n",(char *)optarg );
exit(-1);
}
break;
case 's':
/*
** The next argument specifies the ip number of the interface to
** be the source of the multicast.
*/
strcpy(new_src_name, optarg);
break;
case 'd':
/*
** The next argument is assumed to be the destination of the
** multicast from the source specified by ip number. If no
** argument is provided, the entire source tree will be printed.
*/
strcpy(new_dest_name, optarg);
break;
case 'i':
/*
** The next argument is the number of spaces to indent for each
** new level of the tree. If this argument is omitted it defaults
** to 3.
*/
sscanf((char *)optarg, "%d", &indent );
break;
case 'a':
/*
** The next argument allows the user to specified the number of
** extra nodes to allocate for specifying new routers and subnets
** while working with the program.
*/
sscanf((char *)optarg, "%ld", &extra_nodes );
break;
case 'p':
/*
** Run in batch mode and only print out the path from the
** specified source to the destination.
*/
batch = TRUE;
action = PRINT_PATH;
break;
case 'l':
/*
** Use forward instead of reverse edge metrics in
** determining routing.
*/
reverse_path = TRUE;
break;
case 't':
/*
** Run in batch mode and just print out the tree from the given
** source.
*/
batch = TRUE;
action = PRINT_TREE;
break;
case 'v':
/*
** Turn on verbose mode. If specified on the input line, then
** informative messages will be printed to the output.
*/
verbose = TRUE;
break;
default:
usage( argv[0] );
exit( EX_USAGE );
}
}
/*
** The next argument specifies the name of the file containing
** the description of the m-bone topology.
*/
if(optind >= argc)
{
printf("Missing topology description file\n");
usage( argv[0] );
exit(EX_USAGE);
}
strcpy(network_fl, argv[optind]);
/*
** The program requires at least the m and f command line
** arguments be used. If they are not supplied, the program
** will exit.
*/
if (subnet_fl[0] == 0)
{
sprintf(subnet_fl, "%s.subnets", network_fl);
if (access(subnet_fl, R_OK|F_OK) != 0)
{
sprintf(subnet_fl, "%s.sn", network_fl);
if (access(subnet_fl, R_OK|F_OK) != 0)
{
printf( "Missing subnet description file (-m flag)\n" );
usage( argv[0] );
exit( EX_USAGE );
}
}
}
if( verbose )
{
fprintf( output, "Subnet file: %s\n", subnet_fl );
fprintf( output, "Network description file: %s\n", network_fl );
if( reverse_path )
fprintf( output, "Using forward direction edge metrics\n");
}
/*
** Read the list of subnets and then the network description
** file to build the adjacency list of the network.
*/
read_subnets( subnet_fl, &all_subnets );
read_file( network_fl, &mbone, &all_subnets, extra_nodes );
build_adj( network_fl, &mbone, stdout );
/*Print_adj( &mbone, stdout );*/
/*
** Loop on user input
*/
last_source = 0;
while( !done )
{
if( !batch )
action = parse_user_input( &mbone, new_src_name, new_dest_name, &max_thresh,
&all_subnets, &output );
else
done = TRUE;
if( action == DONE )
{/*
** Exit the while loop
*/
done = TRUE;
continue;
}
ht_entry_p = find_actual_name( &mbone, new_src_name, &all_subnets );
if( ht_entry_p != NULL )
{/*
** Check that the specified source is valid and if so,
** determine the corresponding node number.
*/
strcpy( src_name, ht_entry_p->key_p );
source = ht_entry_p->index;
}
ht_entry_p = find_actual_name( &mbone, new_dest_name, &all_subnets );
if( ht_entry_p != NULL )
{/*
** Check that the specified destination is valid and if so,
** determine the corresponding node number.
*/
strcpy( dest_name, ht_entry_p->key_p );
destination = ht_entry_p->index;
}
strcpy( new_src_name, src_name );
strcpy( new_dest_name, dest_name );
if( source == INVALID_NODE )
/*
** If no source or an invalid source was specified, return to the
** beginning of the while loop.
*/
continue;
if( action == FIND_TREE || source != last_source)
{/*
** If the source or the network has changed, then reget the source
** multicast tree.
*/
if( verbose )
printf( "\nBuilding source tree . . . . \n");
dijkstra_tree( &mbone, source );
last_source = source;
/*Print_adj( &mbone, output );*/
}
if( action == PRINT_PATH )
{/*
** If a valid destination has been specified, print the path
** from the source interface to the destination interface.
*/
if( destination != INVALID_NODE &&
mbone.adj_list[destination].dist_vects.next_hop_subnet != NULL )
{
cur_path_stack.number = 0;
cur_path_stack.first = NULL;
if( mbone.adj_list[destination].type & SUBNET )
push_path_elem( &cur_path_stack, dest_name,
mbone.adj_list[destination].dist_vects.distance,
0, FALSE, FALSE, TRUE, 0 );
if( verbose )
fprintf( output, "Output key: interface, tree level/metric to here/ttl to reach\n\n");
print_path( output, &mbone, indent, src_name, dest_name,
destination, &cur_path_stack );
}
else if( verbose )
printf( "\nNo destination or invalid destination specified\n");
}
if( action == PRINT_TREE || action == PRINT_UNREACH )
{/*
** Print the source multicast tree or the unreachable interfaces
** from the tree.
*/
if( action == PRINT_TREE )
{
print_act_tree = TRUE;
if( verbose )
{
fprintf( output, "\nPrinting the source tree for %s\n", src_name );
fprintf( output, "Output key: interface, tree level/metric to here/ttl to reach\n\n");
}
}
else
print_act_tree = FALSE;
temp_ifc = find_name( &(mbone.adj_list[source].interfaces), src_name );
if( mbone.adj_list[source].type & SUBNET )
{
fprintf(output, "%s, 0/0/0\n", src_name );
if( max_thresh < 0 || max_thresh > 1 )
print_tree( output, indent, &mbone, source, temp_ifc, 1, -1, 0, FALSE,
max_thresh, print_act_tree );
}
else
print_tree( output, indent, &mbone, source, temp_ifc, 0, -1, 0, FALSE,
max_thresh, print_act_tree );
print_unreach( output, &mbone, !print_act_tree );
}
}/* endwhile */
fclose( output );
exit(0);
}
/************************************************************************
FUNCTION: usage( char *exename )
DESCRIPTION:
This function prints out a usage message to the user
indicating correct command line arguments to the
program.
**************************************************************/
void usage( char *exename )
{
printf("usage: %s -m <subnet mask file> <topology file>\n", exename );
printf(" Optional arguments:\n" );
printf("\t[-s <source interface>]\n");
printf("\t[-o <output file for results>]\n");
printf("\t[-d <destination interface>]\n");
printf("\t[-i <indentation>]\n");
printf("\t[-t] (print tree batch mode)\n");
printf("\t[-p] (print path batch mode)\n");
printf("\t[-l] (use forward instead of reverse edge metrics)\n");
printf("\t[-v] (turn on verbose mode)\n");
printf("\t[-a <number of nodes allowed to add>]\n");
}