// Michael Masterson // Greg Greenway // CSE461 // Project 4 // 3-15-2002 #include #include #include "fish.h" #include // uncomment this #define to have the program write the routing table to a text // file named "routedump" in the current directory every time it sends out its // routing tables. Note: it will overwrite any existing file with that name //#define DEBUG_DUMP_ROUTES #define MAX_STRING_LENGTH 1000 #define TRUE 1 #define FALSE 0 // route update period #define UPDATE_PERIOD 10000 #define MAX_ROUTE_AGE 3 // address of an unused node #define UNUSED (MAX_NODE_ADDRESS + 1) // location of a node #define OUTSIDE_LOCAL_SUBNET 1 #define INSIDE_LOCAL_SUBNET 2 // which special packets a node has seen #define NONE -1 #define FIN_ACK -2 // routing table entry: note that destination of UNUSED means the entry is not // used. All the used entries will occur before the first unused entry struct routing_table_entry { int dst; /* final destination */ int via; /* which neighbor to send through */ int cost; /* cost of route */ int age; /* time since last update of the route */ } rt[MAX_ADVERTISEMENTS]; /* create the table */ typedef enum {OPEN, CLOSED} ConnectionState; // a state of closed means the entry is not currently in use struct connection_track_entry { int local_address; /* address of node inside firewall */ int local_port; /* port of this node */ int remote_address; /* address of node outside firewall */ int remote_port; /* should be 20, but we'll keep track of it */ ConnectionState state; /* state of the connection */ long local_seen; /* what packets local node has seen */ long remote_seen; /* what packets remote node has seen */ event timerHandle; /* Handle for timer event */ } ct[MAX_CONNECTIONS]; // Prototypes void PktRcvFunc (int from, void* frame, int frameLength); void KeybRcvFunc (char* lineOfText); struct packet createPkt (int dst, int ttl, int protocol, void* data, int dataSize); void forwardPkt (void* fwdPktPtr, int frameLength); void routeUpdate(void *arg); void recvRoutePkt(int, void*, int); int sendRoutedPkt(int, void*, int); void initRoutingTable(); int getSubnet(int addr); void filterPacket(void* rcvPktPtr, int frameLength); void dropTransportPacket(struct transport_packet* pkt); void allowTransportPacket(struct transport_packet*, int frameLength); int doesConnectionExist(struct transport_packet* tPkt); void initConnectionTable(); void teardownConnection(void *entryPtr); void timeoutConnection(void *entryPtr); int main(int argc, char **argv) { char fishhead_server[MAX_STRING_LENGTH], fishnet_domain[MAX_STRING_LENGTH]; int fishnet_id, i, good_string = FALSE; receive_handler PktRcv = PktRcvFunc; keyboard_handler KeybRcv = KeybRcvFunc; if( argc != 4) { printf("incorrect number of arguments\n"); printf("Usage: ./hw1 headhost:headport domain address\n"); exit(1); } strncpy(fishhead_server, argv[1], MAX_STRING_LENGTH); if(fishhead_server[MAX_STRING_LENGTH - 1] != '\0') { printf("server name too long\n"); exit(1); } /* check that format is server:port */ for(i = 0; i < MAX_STRING_LENGTH; i++) if(fishhead_server[i] == ':') if(fishhead_server[i+1] >= 48 && fishhead_server[i+1] <= 57) good_string = TRUE; if(good_string == FALSE) { printf("bad server name string\n"); exit(1); } strncpy(fishnet_domain, argv[2], MAX_STRING_LENGTH); if(fishnet_domain[MAX_STRING_LENGTH - 1] != '\0') { printf("domain name too long\n"); exit(1); } fishnet_id = atoi(argv[3]); if(fishnet_id > MAX_NODE_ADDRESS) { printf("id too large\n"); exit(1); } initRoutingTable(); initConnectionTable(); // turn down the debugging level fish_setdebuglevel(FISH_DEBUG_APPLICATION); // join the fishnet and initialize fish_joinnetwork(fishhead_server, fishnet_domain, fishnet_id); fish_keybhook(KeybRcv); fish_recvhook(PktRcv); fish_scheduleevent(UPDATE_PERIOD, (event_handler_t)routeUpdate, NULL); fish_main(); return 0; } // Function Pointer to handle keyboard events from fish_recvhook() // Parm: int from, void* frame, int frameLength // Return: void void PktRcvFunc (int from, void* frame, int frameLength) { struct packet* rcvPktPtr = (struct packet*) frame; struct packet sendPkt; // check to see if this is our packet if (rcvPktPtr->hdr.dst == fish_getaddress() || rcvPktPtr->hdr.dst == ALL_NEIGHBORS) { // OUR PACKET - choose action based on protocol if (rcvPktPtr->hdr.protocol == FISH_PROTOCOL_ECHO_REQUEST){ // echo and send response printf("Echo request from %d: %s\n", rcvPktPtr->hdr.src, rcvPktPtr->data); // create the packet to send sendPkt = createPkt(rcvPktPtr->hdr.src, MAX_TTL, FISH_PROTOCOL_ECHO_RESPONSE, rcvPktPtr->data, frameLength - PACKET_HEADER_SIZE); // send the response packet using the API if (sendRoutedPkt(sendPkt.hdr.dst, &sendPkt, frameLength) != 0) printf("Error on fish_send.\n"); } else if (rcvPktPtr->hdr.protocol == FISH_PROTOCOL_ECHO_RESPONSE){ // echo we received a response printf("Echo response from %d: %s\n", rcvPktPtr->hdr.src, rcvPktPtr->data); } else if(rcvPktPtr->hdr.protocol == FISH_PROTOCOL_ROUTING){ // received a routing update recvRoutePkt(from, frame, frameLength); } else { // we have a protocol with an unsupported packet printf("Invalid packet protocol from %d: %s\n", rcvPktPtr->hdr.src, rcvPktPtr->data); } } // end if this is our own packet // else packet is not for us else { if (rcvPktPtr->hdr.ttl > 0) { filterPacket(rcvPktPtr, frameLength); } } } // Function Pointer to handle keyboard events from fish_keybhook() // Parm: char* lineOfText // Return: void void KeybRcvFunc (char* lineOfText) { char* message; int dstAddress, numMatched; struct packet sendPkt; // packet to send // parse lineOfText numMatched = sscanf(lineOfText, "send %d %a[^\n]", &dstAddress, &message); // check to see if input is what we want if (numMatched != 2) { printf ("Commands:\n send \n"); return; } // create a packet // we want to include the null termination of the string, so + 1 sendPkt = createPkt(dstAddress, MAX_TTL,FISH_PROTOCOL_ECHO_REQUEST, message, strlen(message) + 1); // send the packet using the API // we want to include the null termination of the string, so + 1 if (sendRoutedPkt(sendPkt.hdr.dst, &sendPkt, strlen(message) + 1 + PACKET_HEADER_SIZE) != 0) printf("Error on fish_send.\n"); else printf("Successful on fish_send.\n"); // c