/* * NATItem.cpp * * Created on: 11-01-2017 * Author: Piotr Dergun */ #include "NATRouter.h" void NATRouter::initalizeNatTable() { try { natTable = new NATItem[65536]; } catch (bad_alloc &ba) { cerr << "Nie mozna zaalokowac pamieci dla tablicy NAT!" << endl; exit(1); } } NATRouter::NATRouter() { this->initalizeNatTable(); } NATRouter::NATRouter(string hostname) : Node(hostname) { this->initalizeNatTable(); } NATRouter::NATRouter(string hostname, string ip, string mask) : Node(hostname, ip, mask) { this->initalizeNatTable(); } NATRouter::NATRouter(string hostname, string ip, string mask, string gatewayIp) : Node(hostname, ip, mask, gatewayIp) { this->initalizeNatTable(); } int NATRouter::getFreePort() { for (int i=1; i<65536; ++i) if (this->natTable[i].isFree()) return i; return -1; // nie ma żadnego wolnego portu } NATRouter::~NATRouter() { if (natTable) delete [] natTable; } void NATRouter::onRecv() { while (true) { Packet p = this->recv(); stringstream s; /*if (this->getHostname() == "Router 2") { s << "src: " << p.getSrcIp() << ":" << p.getSrcPort() << "dst: " << p.getDstIp() << ":" << p.getDstPort(); this->print(s.str()); }*/ if (p.getSrcPort() != 0) { // jezeli pakiet idzie z jednego wezla do drugiego w danej possieci to odeslij mu "jak switch" if (this->calculateNetwork(p.getDstIp(), this->getMask()) == this->getNetwork() && p.getDstIp() != this->getIp()) { this->send(p, true); } else if (p.getDstIp() != this->getIp() && p.getDstIp() != this->getWanIp()) { this->sNAT(&p); } else if (p.getDstIp() == this->getWanIp() && !this->natTable[p.getDstPort()].isFree()) { this->dNAT(&p); } else { // TUTAJ ew. implementacja obslugi pakietu adresowanego do routera } //usleep(500000); sleep(1); } else { #ifndef DEBUG this->print("onRecv() sleeping..."); #endif } sleep(1); } } void NATRouter::setWanIp(string wanIp) { this->netWanConf.ip = wanIp; this->setWanNetwork(); } void NATRouter::setWanMask(string wanMask) { this->netWanConf.mask = wanMask; this->setWanNetwork(); } void NATRouter::setWanGatewayIp(string wanGatewayIp) { this->netWanConf.gatewayIp = wanGatewayIp; } string NATRouter::getWanIp() { return this->netWanConf.ip; } string NATRouter::getWanMask() { return this->netWanConf.mask; } /* * funkcja SNAT zapisuje w tablicy NAT * numer portu zrodlowego komputera z LAN * oraz jego IP i przeksztalca pakiet, zmieniajac * zrodlowy IP na IP zewn. routera oraz wolny * port z tablicy NAT. Jezeli portu nie ma to funkcja * czeka, az sie zwolni */ void NATRouter::sNAT(Packet *packet) { int port; NATItem *natItem; // mozliwe, ze juz port zostal zaalokowany, to trzeba wykorzystac port = this->getAllocatedPort(packet->getSrcIp(), packet->getSrcPort()); if (port == -1) while ((port = this->getFreePort()) == -1) { //TESTOWO this->print("NAT table full, waiting 1s"); sleep(1); } // wstawiam do tablicy NAT info ze port zarezerowany na odbior natItem = &this->natTable[port]; natItem->setIp(packet->getSrcIp()); natItem->setPort(packet->getSrcPort()); natItem->setTimeout(/*5*/15); stringstream ss; ss << "SNAT " << packet->getSrcIp() << ":" << packet->getSrcPort() << " --> " << this->getWanIp() << ":" << port; packet->setSrcIp(this->getWanIp()); // zamieniam IP lokalne na WAN'owe packet->setSrcPort(port); // zamieniam port lokalny na WAN'owy - z tablicy NAT this->print(ss.str()); sleep(1); this->send(*packet, true); // wysylam dalej natItem = NULL; } /* * funkcja DNAT ma za zadanie znalezc w tablicy NAT * port i adres IP wezla na ktory ma wrocic odpowiedz * z sieci Internet (z zewnatrz), a takze przedluzyc * czas zycia tego portu */ void NATRouter::dNAT(Packet* packet) { NATItem *natItem = &this->natTable[packet->getDstPort()]; stringstream ss; ss << "DNAT " << packet->getDstIp() << ":" << packet->getDstPort() << " --> " << natItem->getIp() << ":" << natItem->getPort(); packet->setDstIp(natItem->getIp()); // zamieniam IP lokalne na WAN'owe packet->setDstPort(natItem->getPort()); // zamieniam port NAT na lokalny wezla //natItem->free(); // zwalniam port w routerze natItem->increaseTimeout(5); // podbijam o kolejne 5 sekund skoro transmisja trwa this->print(ss.str()); sleep(1); this->send(*packet, true); // wysylam dalej natItem = NULL; } void NATRouter::setWanNetwork() { this->netWanConf.network = this->calculateNetwork(this->getWanIp(), this->getWanMask()); } string NATRouter::getWanNetwork() { return this->netWanConf.network; } /* * funkcja szuka aktywnego zaalokowanego portu (aktywna * transmisja) w tablicy NAT dla pary (srcIp:srcPort) */ int NATRouter::getAllocatedPort(string srcIp, int srcPort) { for (int i=1; i<65536; ++i) if (this->natTable[i].getIp() == srcIp && this->natTable[i].getPort() == srcPort) return i; return -1; // nic nie znaleziono } string NATRouter::getWanGatewayIp() { return this->netWanConf.gatewayIp; }