// route_sim.c++ by Brett Tjaden #include "route_sim.h" void run_route_sim(); int test_path(string src, string dest); int main(int argc,char **argv) { int status = -1; if (argc > 2) // Error: too many arguments { cout << "Usage: " << argv[0] << " [conf_file]" << endl; exit(-1); } else if (argc == 1) // read conf_file from standard input status=yyparse(); else // read conf_file from file { FILE *yyin; yyin=freopen(argv[1],"r",stdin); if (yyin != NULL) status=yyparse(); // call the parser else { cout << "Error opening input file: " << argv[1] << endl; exit(-1); } } if (status == 0) // Everything worked! Data structures should be full. run_route_sim(); // so go run the simulation else cout << "Error parsing input file." << endl; exit(status); } void print_conf() { cout << "Here is the configuration of the internet:" << endl; for (vector::iterator i=hosts.begin(); i != hosts.end(); i++) { cout << "\t" << (*i).name << ":" << endl; for (vector::iterator j=(*i).interfaces.begin(); j != (*i).interfaces.end(); j++) cout << "\t\t" << (*j).name << "\t" << (*j).ip_address << "\t" << (*j).netmask << endl; } } void print_routing_tables() { cout << "Here are the routing tables:" << endl; for (vector::iterator i=tables.begin(); i != tables.end(); i++) { cout << "\t" << (*i).hostname << ":" << endl; for (vector::iterator j=(*i).table.begin(); j != (*i).table.end(); j++) cout << "\t\t" << (*j).target << "\t" << (*j).netmask << "\t" << (*j).next_hop << endl; } } void print_tests() { cout << "Here are the tests to be run:" << endl; for (vector::iterator i=tests.begin(); i != tests.end(); i++) cout << "\t" << (*i).src << " -> " << (*i).dest << endl; cout << endl; } void run_tests() { // For each path to be tested, call the test_path routine. // Report any of the tested paths that failed (due to a bad routing entry). for (vector::iterator i=tests.begin(); i != tests.end(); i++) { int result=FAIL; result=test_path((*i).src,(*i).dest); if (result==FAIL) cout << "FAILED: " << (*i).src << " -> " << (*i).dest << endl; } } void run_route_sim() { // These routines are provided to give you an example of how you can // access all the information stored in the various data structures. // // print_conf(); // print_routing_tables(); // print_tests(); run_tests(); } int test_path(string src, string dest) { // This routine (and probably several supporting routines) is yours to // write. You will do yourself a big favor if you develop and test // functionality in incremental stages and include lots of diagnostic // code so that you can follow the simulation (especially when things go // wrong). Here is an outline of how you can code this routine: // // let current_host = src and end_host = dest // while (current_host is not the same as end_host) { // Use current_host's routing table to make a routing decision (next_hop) // Check that the routing decision if valid (i.e. current_host and // next_hop's interface are on the same subnet) // If not valid return FAIL // else current_host = next_hop // } // return SUCCESS // That's the end of the pseudocode. Right now this routine is just a stub // that always returns FAIL. return(FAIL); }