Symulacja NAT na przedmiot Symulacje Komputerowe
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

222 lines
4.9 KiB

/*
* 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
}
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;
}
/*
* 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");
this->delay(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());
this->delay();
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());
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;
}
/*
* 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;
}