|
|
- /**
- * @file NATRouter.cpp
- *
- * Created on: 11-01-2017
- * @author Piotr Dergun
- */
-
- #include "NATRouter.h"
-
- void NATRouter::initalizeNatTable()
- {
- try
- {
- natTable = new NATItem[NAT_TABLE_LEN];
- }
- catch (bad_alloc &ba)
- {
- cerr << "Nie mozna zaalokowac pamieci dla tablicy NAT!" << endl;
- exit(1);
- }
- }
-
- NATRouter::NATRouter()
- {
- this->lastUsedPort = 0;
- this->initalizeNatTable();
- }
-
- NATRouter::NATRouter(string hostname) : Node(hostname)
- {
- this->lastUsedPort = 0;
- this->initalizeNatTable();
- }
-
- NATRouter::NATRouter(string hostname, string ip, string mask) : Node(hostname, ip, mask)
- {
- this->lastUsedPort = 0;
- this->initalizeNatTable();
- }
-
- NATRouter::NATRouter(string hostname, string ip, string mask, string gatewayIp) : Node(hostname, ip, mask, gatewayIp)
- {
- this->lastUsedPort = 0;
- this->initalizeNatTable();
- }
-
- int NATRouter::getFreePort()
- {
- if (this->lastUsedPort == NAT_TABLE_LEN-1)
- this->lastUsedPort = 0;
-
- for (int i = this->lastUsedPort+1; i<NAT_TABLE_LEN; ++i)
- if (this->natTable[i].isFree())
- {
- this->lastUsedPort = i;
- return i;
- }
-
- for (int i = 1; i<this->lastUsedPort; ++i)
- if (this->natTable[i].isFree())
- {
- this->lastUsedPort = i;
- 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 (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
- }
- this->delay();
- }
- else
- {
- #ifndef DEBUG
-
- this->print("onRecv() sleeping...");
- #endif
- }
- this->delay();
-
- }
- }
-
- 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;
- }
-
- void NATRouter::sNAT(Packet *packet)
- {
- int port;
- NATItem *natItem;
- bool allocated = false;
- stringstream ss;
-
- // mozliwe, ze juz port zostal zaalokowany, to trzeba wykorzystac
- port = this->getAllocatedPort(packet->getSrcIp(), packet->getSrcPort());
- if (port == -1)
- while ((port = this->getFreePort()) == -1)
- {
- this->print("NAT table full, waiting 1s", true);
- this->delay(1);
- }
- else
- allocated = true;
-
- // wstawiam do tablicy NAT info ze port zarezerowany na odbior
- natItem = &this->natTable[port];
- natItem->setIp(packet->getSrcIp());
- natItem->setPort(packet->getSrcPort());
-
- if (allocated)
- natItem->increaseTimeout(15);
- else
- natItem->setTimeout(15);
-
- ss << packet->getSrcIp() << ":" << packet->getSrcPort();
-
- if (!allocated)
- this->natHelper.insert(pair<string, int>(ss.str(), port));
-
- ss.str("");
- 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(), true);
- this->delay();
- this->send(*packet, true); // wysylam dalej
- natItem = NULL;
- }
-
- 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->increaseTimeout(5); // podbijam o kolejne 5 sekund skoro transmisja trwa
-
- this->print(ss.str());
- this->delay();
- 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;
- }
-
- int NATRouter::getAllocatedPort(string srcIp, int srcPort)
- {
- map<string, int>::iterator it;
- int pos = -1;
-
- stringstream ss;
- ss << srcIp << ":" << srcPort;
-
- it = this->natHelper.find(ss.str());
- if (it != this->natHelper.end())
- {
- // sprawdz czy wpis o podanym IP z nat nie zostal napisany (referencja nieaktualna)
- if (this->natTable[it->second].getIp() != srcIp || this->natTable[it->second].getPort() != srcPort)
- this->natHelper.erase(it);
- else
- pos = it->second;
- }
-
- return pos;
- }
-
- void NATRouter::freePorts()
- {
- stringstream ss;
- int i, ports, peak=NAT_TABLE_LEN-1;
-
- Log portsLog;
- string name = "NAT";
- portsLog.setLogParams(3, GREEN, "\t\t");
- portsLog.setObjectName(&name);
- portsLog.setDelay(100000);
-
- while(true)
- {
- ports = 0;
- ss.str("");
-
- for (i=1; i<NAT_TABLE_LEN; ++i)
- if (this->natTable[i].isFree())
- ++ports;
-
- if (ports < peak)
- peak = ports;
-
- ss << "Free/Reserved:\t" << ports << " (" << peak << ")/" << (NAT_TABLE_LEN-ports-1) << " (" << (NAT_TABLE_LEN-peak-1) << ")"; // poprawka na nieuzywany port 0
-
- portsLog.print(ss.str());
- portsLog.printProgressBar(4, 4, "Utilization", (float)(NAT_TABLE_LEN-ports-1)/(NAT_TABLE_LEN-1));
- portsLog.delay();
- }
-
- }
-
- string NATRouter::getWanGatewayIp()
- {
- return this->netWanConf.gatewayIp;
- }
|