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 >
C/C++ Source or Header  |  1993-10-29  |  11KB  |  357 lines

  1. /************************************************************************
  2.  
  3.     PURPOSE:  M-Bone debugger.
  4.  
  5.     DESCRIPTION:
  6.         This program reads a description of the M-Bone and it's
  7.         subnets and is able to predict multicast routes given
  8.         a source.
  9.  
  10.     METHODOLOGY:
  11.         Once the network has been read in and stored in an
  12.         adjacency list, then a distance vector routing table
  13.         is built and the multicast routes are predicted assuming
  14.         the use of Steve Deering's truncated-broadcast algorithm.
  15.  
  16.     PROGRAMMER:  Deb Agarwal    6/1993
  17.  
  18. ***********************************************************************/
  19.  
  20. #include    <unistd.h>
  21. #include    <stdio.h>
  22. #include    <string.h>
  23. #include        <sysexits.h>
  24.  
  25. #include       "types.h"
  26. #include       "mrhash.h"
  27. #include       "data_struct_proto.h"
  28. #include       "build_adj_proto.h"
  29. #include       "dist_vect_proto.h"
  30. #include       "user_proto.h"
  31.  
  32. /********EXTERNAL REFERENCES *************/
  33. extern int getopt(int, char**, const char*);
  34. extern char *optarg;
  35. extern int  optind;
  36.  
  37. /********GLOBALS **********/
  38. Network         mbone;
  39. Ifc_list        invisib_ifcs;
  40. Ifc_list        all_subnets;
  41. Path_stack      cur_path_stack;
  42. int             verbose;
  43. int        reverse_path;  /* use reverse or forward metrics */
  44.  
  45. /*********Private Functions ****************/
  46. void usage( char *exename );
  47.  
  48. void
  49. main( int argc, char *argv[] )
  50. {
  51.         char   opt;
  52.         int    done = FALSE, indent = 3, batch = FALSE, print_act_tree,
  53.            arg_cnt = 0, action = NO_ACTION;
  54.     long   source = INVALID_NODE, last_source = INVALID_NODE,
  55.            destination = INVALID_NODE, max_thresh, extra_nodes = 0;
  56.     NAME   src_name, dest_name, new_src_name, new_dest_name;
  57.     HENTRY_t  *ht_entry_p;
  58.     char   subnet_fl[MAXLINE],
  59.            network_fl[MAXLINE];
  60.     FILE   *output;
  61.     Interface *temp_ifc;
  62.  
  63.  
  64.     verbose = FALSE;
  65.     reverse_path = FALSE;
  66.     /*
  67.     **   Parse the input arguments supplied on the command line and
  68.     **   set the appropriate variables.
  69.     */
  70.     output = stdout;
  71.     strcpy( src_name, "\0");
  72.     strcpy( dest_name, "\0");
  73.     strcpy( new_src_name, "\0");
  74.     strcpy( new_dest_name, "\0");
  75.     source = INVALID_NODE;
  76.     destination = INVALID_NODE;
  77.     
  78.     while ( ( opt = getopt( argc, argv, "m:o:s:d:i:a:pltv" )) != -1)
  79.        {
  80.        switch( opt )
  81.           {
  82.            case 'm':
  83.          /*
  84.          **   The next argument specifies the name of the file containing
  85.          **   the list of ip subnets.
  86.          */
  87.          /*printf( "The subnets will be read from: %s\n", (char *) optarg );*/
  88.          strcpy(subnet_fl, optarg);
  89.          arg_cnt++;
  90.          break;
  91.            case 'o':
  92.          /*
  93.          **   The next argument specifies the file to print the program
  94.          **   output to.  If not supplied, the output will go to stdout.
  95.          */
  96.          printf( "Output will be printed to: %s\n", (char *)optarg);
  97.          if( !(output = fopen( (char *)optarg, "w" )))
  98.             {
  99.             printf( "ERROR: Unable to open output file named %s\n",(char *)optarg );
  100.             exit(-1);
  101.             }
  102.          break;
  103.            case 's':
  104.          /*
  105.          **   The next argument specifies the ip number of the interface to
  106.          **   be the source of the multicast.
  107.          */
  108.          strcpy(new_src_name, optarg);
  109.          break;
  110.            case 'd':
  111.          /*
  112.          **   The next argument is assumed to be the destination of the
  113.          **   multicast from the source specified by ip number.  If no
  114.          **   argument is provided, the entire source tree will be printed.
  115.          */
  116.          strcpy(new_dest_name, optarg);
  117.          break;
  118.            case 'i':
  119.          /*
  120.          **   The next argument is the number of spaces to indent for each
  121.          **   new level of the tree.  If this argument is omitted it defaults
  122.          **   to 3.
  123.          */
  124.          sscanf((char *)optarg, "%d", &indent );
  125.          break;
  126.            case 'a':
  127.          /*
  128.          **    The next argument allows the user to specified the number of
  129.          **    extra nodes to allocate for specifying new routers and subnets
  130.          **    while working with the program.
  131.          */
  132.          sscanf((char *)optarg, "%ld", &extra_nodes );
  133.          break;
  134.            case 'p':
  135.          /*
  136.          **    Run in batch mode and only print out the path from the
  137.          **    specified source to the destination.
  138.          */
  139.          batch = TRUE;
  140.          action = PRINT_PATH;
  141.          break;
  142.            case 'l':
  143.          /*
  144.          **   Use forward instead of reverse edge metrics in
  145.          **   determining routing.
  146.          */
  147.          reverse_path = TRUE;
  148.          break;
  149.            case 't':
  150.          /*
  151.          **    Run in batch mode and just print out the tree from the given
  152.          **    source.
  153.          */
  154.          batch = TRUE;
  155.          action = PRINT_TREE;
  156.          break;
  157.            case 'v':
  158.          /*
  159.          **    Turn on verbose mode.  If specified on the input line, then
  160.          **    informative messages will be printed to the output.
  161.          */
  162.          verbose = TRUE;
  163.          break;
  164.            default:
  165.          usage( argv[0] );
  166.          exit( EX_USAGE );
  167.           }
  168.        }
  169.  
  170.     /*
  171.     **   The next argument specifies the name of the file containing
  172.     **   the description of the m-bone topology.
  173.     */
  174.     if(optind >= argc)
  175.        {
  176.        printf("Missing topology description file\n");
  177.        usage( argv[0] );
  178.        exit(EX_USAGE);
  179.        }
  180.     strcpy(network_fl, argv[optind]);
  181.  
  182.     /*
  183.     **     The program requires at least the m and f command line
  184.     **     arguments be used.  If they are not supplied, the program
  185.     **     will exit.
  186.     */
  187.     if (subnet_fl[0] == 0)
  188.        {
  189.        sprintf(subnet_fl, "%s.subnets", network_fl);
  190.        if (access(subnet_fl, R_OK|F_OK) != 0)
  191.           {
  192.           sprintf(subnet_fl, "%s.sn", network_fl);
  193.           if (access(subnet_fl, R_OK|F_OK) != 0)
  194.              {
  195.              printf( "Missing subnet description file (-m flag)\n" );
  196.              usage( argv[0] );
  197.              exit( EX_USAGE );
  198.          }
  199.           }
  200.        }
  201.     if( verbose )
  202.        {
  203.        fprintf( output, "Subnet file:              %s\n", subnet_fl );
  204.        fprintf( output, "Network description file: %s\n", network_fl );
  205.        if( reverse_path )
  206.         fprintf( output, "Using forward direction edge metrics\n");
  207.        }
  208.  
  209.     /*
  210.     **   Read the list of subnets and then the network description
  211.     **   file to build the adjacency list of the network.
  212.     */
  213.     read_subnets( subnet_fl, &all_subnets );
  214.     read_file( network_fl, &mbone, &all_subnets, extra_nodes );
  215.     build_adj( network_fl, &mbone, stdout );
  216.     /*Print_adj( &mbone, stdout );*/
  217.     /*
  218.     **   Loop on user input
  219.     */
  220.     last_source = 0;
  221.     while( !done )
  222.        {
  223.        if( !batch )
  224.           action = parse_user_input( &mbone, new_src_name, new_dest_name, &max_thresh,
  225.                      &all_subnets, &output );
  226.        else
  227.           done = TRUE;
  228.        if( action == DONE )
  229.           {/*
  230.            **    Exit the while loop
  231.            */
  232.           done = TRUE;
  233.           continue;
  234.           }
  235.        ht_entry_p = find_actual_name( &mbone, new_src_name, &all_subnets );
  236.        if( ht_entry_p != NULL )
  237.           {/*
  238.            **     Check that the specified source is valid and if so,
  239.            **     determine the corresponding node number.
  240.            */
  241.           strcpy( src_name, ht_entry_p->key_p );
  242.           source = ht_entry_p->index;
  243.           }
  244.        ht_entry_p = find_actual_name( &mbone, new_dest_name,  &all_subnets );
  245.        if( ht_entry_p != NULL ) 
  246.           {/*
  247.            **     Check that the specified destination is valid and if so,
  248.            **     determine the corresponding node number.
  249.            */
  250.           strcpy( dest_name, ht_entry_p->key_p );
  251.           destination = ht_entry_p->index;
  252.           }
  253.        strcpy( new_src_name, src_name );
  254.        strcpy( new_dest_name, dest_name );
  255.        if( source == INVALID_NODE )
  256.           /*
  257.           **    If no source or an invalid source was specified, return to the
  258.           **    beginning of the while loop.
  259.           */
  260.           continue;
  261.        if( action == FIND_TREE || source != last_source)
  262.           {/*
  263.            **      If the source or the network has changed, then reget the source
  264.            **      multicast tree.
  265.            */
  266.           if( verbose )
  267.          printf( "\nBuilding source tree . . .  . \n");
  268.           dijkstra_tree( &mbone, source );
  269.           last_source = source;
  270.           /*Print_adj( &mbone, output );*/
  271.           }
  272.        if( action == PRINT_PATH )
  273.           {/*
  274.            **      If a valid destination has been specified, print the path
  275.            **      from the source interface to the destination interface.
  276.            */
  277.           if( destination != INVALID_NODE  &&
  278.           mbone.adj_list[destination].dist_vects.next_hop_subnet != NULL )
  279.          {
  280.          cur_path_stack.number = 0;
  281.          cur_path_stack.first = NULL;
  282.          if( mbone.adj_list[destination].type & SUBNET )
  283.             push_path_elem( &cur_path_stack, dest_name, 
  284.                     mbone.adj_list[destination].dist_vects.distance,
  285.                     0, FALSE, FALSE, TRUE, 0 );
  286.          if( verbose )
  287.             fprintf( output, "Output key: interface, tree level/metric to here/ttl to reach\n\n");
  288.          print_path( output, &mbone, indent, src_name, dest_name,
  289.                  destination, &cur_path_stack );
  290.              }
  291.           else if( verbose )
  292.          printf( "\nNo destination or invalid destination specified\n");
  293.           }
  294.        if( action == PRINT_TREE || action == PRINT_UNREACH )
  295.           {/*
  296.            **      Print the source multicast tree or the unreachable interfaces
  297.            **      from the tree.
  298.            */
  299.           if( action == PRINT_TREE )
  300.          {
  301.          print_act_tree = TRUE;
  302.          if( verbose )
  303.             {
  304.                 fprintf( output, "\nPrinting the source tree for %s\n", src_name );
  305.             fprintf( output, "Output key: interface, tree level/metric to here/ttl to reach\n\n");
  306.                 }
  307.              }
  308.           else
  309.          print_act_tree = FALSE;
  310.           temp_ifc = find_name( &(mbone.adj_list[source].interfaces), src_name );
  311.           if( mbone.adj_list[source].type & SUBNET )
  312.          {
  313.          fprintf(output, "%s, 0/0/0\n", src_name );
  314.          if( max_thresh < 0 || max_thresh > 1 )
  315.          print_tree( output, indent, &mbone, source, temp_ifc, 1, -1, 0, FALSE,
  316.                  max_thresh, print_act_tree );
  317.          }
  318.           else
  319.          print_tree( output, indent, &mbone, source, temp_ifc, 0, -1, 0, FALSE,
  320.                  max_thresh, print_act_tree );
  321.           print_unreach( output, &mbone, !print_act_tree );
  322.           }
  323.        }/* endwhile */
  324.     fclose( output );
  325.     exit(0);
  326. }
  327.  
  328.  
  329. /************************************************************************
  330.  
  331.   FUNCTION: usage( char *exename )
  332.  
  333.   DESCRIPTION:
  334.         This function prints out a usage message to the user
  335.     indicating correct command line arguments to the
  336.     program.
  337.  
  338. **************************************************************/
  339. void usage( char *exename )
  340. {
  341.     printf("usage: %s -m <subnet mask file> <topology file>\n", exename );
  342.     printf("  Optional arguments:\n" );
  343.     printf("\t[-s <source interface>]\n");
  344.     printf("\t[-o <output file for results>]\n");
  345.     printf("\t[-d <destination interface>]\n");
  346.     printf("\t[-i <indentation>]\n");
  347.     printf("\t[-t] (print tree batch mode)\n");
  348.     printf("\t[-p] (print path batch mode)\n");
  349.     printf("\t[-l] (use forward instead of reverse edge metrics)\n");
  350.     printf("\t[-v] (turn on verbose mode)\n");
  351.     printf("\t[-a <number of nodes allowed to add>]\n");
  352.  }
  353.  
  354.  
  355.  
  356.  
  357.