void makeTrie(void) { map<int, hostConf>::iterator j; string::iterator stringit; char* temp = new char[16]; string prestring; char* size = new char[2]; struct cidrprefix tempFix; for(j = routerEnd.begin(); j != routerEnd.end(); j++) { prestring = (j->second).overlayPrefix; for(stringit = prestring.begin(); stringit != prestring.end(); stringit++) { if(*stringit == '/') { strcpy(temp, prestring.substr(0, distance(prestring.begin(),stringit)).c_str()); cout << "Temp: " << temp << endl; inet_pton(AF_INET, temp, (void *)&tempFix.prefix); stringit++; size[0] = *stringit; stringit++; size[1] = *stringit; break; } } tempFix.size = (char)atoi(size); #ifdef DEBUG cout << "Prefix: " << tempFix.prefix << "/" << (int)tempFix.size << " for router: " << routerIPs[j->first] << endl; #endif hosts.insert(tempFix, routerIPs[j->first]); #ifdef DEBUG cout << "Testing trie." << endl; int testaddr; inet_pton(AF_INET, "1.2.3.1", (void *)&testaddr); cout << testaddr << hosts.search(testaddr) << endl; #endif } }
int main(int argc, char** argv) { #ifdef SANDWICH printf("I'm a sandwich!\n"); #endif int o; string configPath; char isRouter = IP_NOT_FOUND; while((o = getopt(argc, argv, "rh")) != -1) { switch(o) { case 'r': //enter router mode isRouter = TRUE; break; case 'h': //enter host mode isRouter = FALSE; break; case '?': fprintf(stderr, "Unknown option -%c.\n", optopt); cout << "Specify host with -h or router with -r" << endl; exit(0); break; } } configPath = (string)argv[optind]; if(configPath.empty()) { printf("Please, you must provide a filename.\n"); printf("Usage: overlay [-r -h] config.conf\n"); exit(1); } readConfig(configPath); makeTrie(); struct ifaddrs *demAddrs; if(getifaddrs(&demAddrs)) { fprintf(stderr, "Couldn't get real IP address. Aborting.\n"); exit(1); } struct in_addr *myAddr; char* addrBuf = new char[INET_ADDRSTRLEN]; struct sockaddr *mysockaddr = (demAddrs->ifa_addr); while((strcmp(demAddrs->ifa_name, "eth0") && strcmp(demAddrs->ifa_name, "eth1") && strcmp(demAddrs->ifa_name, "eth2") && strcmp(demAddrs->ifa_name, "eth3") && strcmp(demAddrs->ifa_name, "wlan0"))||(mysockaddr->sa_family!=AF_INET)) { #ifdef DEBUG cout << "Interface: " << demAddrs->ifa_name << ". NOPE!" << endl; #endif demAddrs = demAddrs->ifa_next; if(demAddrs==NULL) { fprintf(stderr, "Couldn't find the specified interface. Aborting. Sorry! Make sure your computer is set up properly.\n"); exit(1); } mysockaddr = (demAddrs->ifa_addr); } #ifdef DEBUG cout << "Interface: " << demAddrs->ifa_name << endl; #endif myAddr = &(((struct sockaddr_in*)mysockaddr)->sin_addr); inet_ntop(AF_INET, (void *)myAddr, addrBuf, INET_ADDRSTRLEN); #ifdef DEBUG printf("My real IP address is: %s\n", addrBuf); #endif map<int, string>::iterator routeit;; for(routeit = routerIPs.begin(); routeit != routerIPs.end(); routeit++) { #ifdef DEBUG cout << "Testing: " << (*routeit).second << endl; #endif if(!(*routeit).second.compare((string)addrBuf)) { isRouter = TRUE; hostID = (*routeit).first; break; } } if(isRouter == IP_NOT_FOUND) { map<int, hostIP>::iterator endit; for(endit = endIPs.begin(); endit != endIPs.end(); endit++) { #ifdef DEBUG cout << "Testing: " << (*endit).second.real << endl; #endif if(!(*endit).second.real.compare((string)addrBuf)) { isRouter = FALSE; hostID = (*endit).first; break; } } } if(isRouter == IP_NOT_FOUND) { fprintf(stderr, "I couldn't find your IP address in my memory banks. Please check to make sure your configuration file is correct."); exit(1); } if(isRouter) router(); else { uint32_t myIP = 0; inet_pton(AF_INET, endIPs[hostID].overlay.c_str(), (void *)&myIP); string myRouter = hosts.search(myIP); #ifdef DEBUG cout << "My router is: " << myRouter << endl; #endif unsigned long myRouterInt; inet_pton(AF_INET, myRouter.c_str(), (void *)&myRouterInt); host(myRouterInt); } return 0; }
void router(void) { #ifdef DEBUG cout << "I am router #" << hostID << "!" << endl; #endif //bind socket int sockfd = create_cs3516_socket(); //initialize for select() call fd_set readfds; FD_ZERO(&readfds); FD_SET(sockfd, &readfds); //We want a truly nonblocking call so... struct timeval timeoutval; timeoutval.tv_sec = 10; timeoutval.tv_usec = 0; map<string, deque<struct message *> > outputbuffers; map<int, hostIP>::iterator it; struct cidrprefix tempFix; for(it = endIPs.begin(); it != endIPs.end(); it++) { inet_pton(AF_INET, (*it).second.overlay.c_str(), (void *)&tempFix.prefix); tempFix.size = 32; hosts.insert(tempFix, (*it).second.real); outputbuffers[(*it).second.real] = *(new deque<struct message *>); //Try to access the output buffer for this IP, but since it won't exist, create one. #ifdef DEBUG cout << "I just inserted " << hosts.search(tempFix.prefix) << endl; #endif } while(TRUE){ //check if we have anything to read FD_ZERO(&readfds); FD_SET(sockfd, &readfds); select(sockfd+1, &readfds, NULL, NULL, &timeoutval); //while we have a packet to receive, handle it if(FD_ISSET(sockfd, &readfds)){ #ifdef DEBUG cout << "Received a packet!" << endl; #endif struct message *receivemessage = new struct message(); receivemessage->buffer = (char*)malloc(MAX_PACKET_SIZE); cs3516_recv(sockfd, receivemessage->buffer, MAX_PACKET_SIZE); time(&(receivemessage->recvtime)); iphdr *ip = (iphdr*)(receivemessage->buffer); //get the real ip address of the destination string interface = hosts.search((uint32_t)(ip->daddr)); cout << "Going to router: " << interface << endl; deque<struct message *> outputqueue; //Get some info from the packet for logging purposes char srcstr[INET_ADDRSTRLEN], dststr[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(ip->saddr), srcstr, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(ip->daddr), dststr, INET_ADDRSTRLEN); cout << "This fella is going to " << dststr << endl; short id = ntohs(ip->id); //get the output queue cout << "Interface: " << interface << endl; if(outputbuffers.find(interface)!=outputbuffers.end()){ outputqueue = outputbuffers.find(interface)->second; } else { //we don't know who this is! Log it and drop that packet like it's hot writetolog(srcstr, dststr, id, "NO_ROUTE_TO_HOST", ""); continue; } //decrement the ttl value (ip->ttl)--; if((ip->ttl)>0){ if(outputqueue.size()<=configuration.queueLength){ outputbuffers[interface].push_back(receivemessage); writetolog(srcstr, dststr, id, "SENT_OK", interface); } else { //drop the packet and log writetolog(srcstr, dststr, id, "MAX_SENDQ_EXCEEDED", ""); } } else { //drop the packet and log writetolog(srcstr, dststr, id, "TTL_EXPIRED", ""); } } //look at queues to see if any send delays have elapsed //TODO per-queue send delay as specified by the assignment for(map<string, deque<struct message *> >::iterator i = outputbuffers.begin(); i != outputbuffers.end(); i++) { string interface = (*i).first; double delay = 0; bool isRouter = false; int hostToSend = lookupHost(interface, &isRouter); if(isRouter) delay = routerRouter[hostToSend].sendDelay; else delay = routerEnd[hostToSend].sendDelay; deque<struct message *> buffer = (*i).second; if(buffer.size()>0){ struct message* currentmsg = buffer.front(); time_t currenttime; time(¤ttime); double waited = difftime(currenttime, currentmsg->recvtime); if(waited>(delay/1000)){ unsigned int interfacebytes; //convert address to bytes inet_pton(AF_INET, (char*)interface.c_str(), (void *)&interfacebytes); #ifdef DEBUG cout << "Down to the nitty-gritty: sending the packet." << endl; #endif int status = cs3516_send(sockfd, currentmsg->buffer, MAX_PACKET_SIZE, interfacebytes); //if(status) sent = TRUE; if(!status) fprintf(stderr, "There was an error sending the file. No bytes were sent."); //free(currentmsg->buffer); delete currentmsg; outputbuffers[interface].pop_front(); } } } } }