diff --git a/Main.cpp b/Main.cpp index e2c3e65..a842f37 100644 --- a/Main.cpp +++ b/Main.cpp @@ -7,32 +7,81 @@ #include "common.h" #include "Node.h" +#include "NATRouter.h" int main(int argc, char *argv[]) { cout << "Obiekt PC1" << endl; - Node pc1("PC1", "10.0.0.2", "255.0.0.0"); + Node pc1("PC1", "10.0.0.2", "255.0.0.0", "10.0.0.1"); cout << "Obiekt PC2" << endl; - Node pc2("PC2", "10.0.0.3", "255.0.0.0"); + Node pc2("PC2", "10.0.0.3", "255.0.0.0", "10.0.0.1"); + + cout << "Obiekt R1" << endl; + NATRouter r1("R1", "10.0.0.1", "255.255.255.0"); + r1.setWanIp("83.11.254.254"); + r1.setWanMask("255.255.255.255"); + + cout << "Podlaczam PC1, PC2 z R1" << endl; + cout << r1.connectNode(&pc1) << endl; + cout << r1.connectNode(&pc2) << endl; + + cout << "Obiekt S" << endl; + Node s("Serwer", "8.8.8.8", "255.255.255.255"); + s.connectNode(&r1); + + /* + * zastapilem to polaczenie bezposrednie + * polaczeniem przez router (a'la switch) cout << "Lacze PC1 z PC2" << endl; cout << pc1.connectNode(&pc2) << endl; cout << "Lacze PC1 z PC2 (ponownie)" << endl; cout << pc1.connectNode(&pc2) << endl; - + */ cout << "Tworze pakiet i adresuje go do PC2" << endl; Packet p("piekna wiadomosc"); p.setDstIp("10.0.0.3"); p.setDstPort(80); - cout << "Wysylam wiadomosc: "; + cout << "Wysylam wiadomosc z PC1: "; cout << pc1.send(p) << endl; + cout << "Wywoluje onRecv() na R1 <-- pelni funkcje switcha" << endl; + r1.onRecv(); + cout << "Wywoluje onRecv() na PC2" << endl; pc2.onRecv(); + cout << "Adresuje pakiet do serwera" << endl; + p.setDstIp("8.8.8.8"); + p.setDstPort(80); + p.setMsg("to wiadomosc do serwera!"); + + cout << "Wysylam wiadomosc z PC1: "; + cout << pc1.send(p) << endl; + + cout << "Wywoluje onRecv() na R1 <-- pelni funkcje SNAT" << endl; + r1.onRecv(); + + cout << "Wywoluje onRecv() na serwerze" << endl; + s.onRecv(); + + cout << "Serwer generuje odpowiedz (tymczasowo, poki nie ma swojej klasy)" << endl; + Packet rp("Odpowiedz z serwera do PC1"); + rp.setDstIp("83.11.254.254"); + rp.setDstPort(1); + + cout << "Wysylam wiadomosc z serwera: "; + cout << s.send(rp) << endl; + + cout << "Wywoluje onRecv() na R1 <-- pelni funkcje DNAT" << endl; + r1.onRecv(); + + cout << "Wywoluje onRecv() na PC1" << endl; + pc1.onRecv(); + return 0; } diff --git a/NATItem.h b/NATItem.h index c11e285..e0fb37d 100644 --- a/NATItem.h +++ b/NATItem.h @@ -18,7 +18,6 @@ class NATItem public: NATItem(); - NATItem(); bool isFree(); diff --git a/NATRouter.cpp b/NATRouter.cpp index 5c6dbd5..822c63c 100644 --- a/NATRouter.cpp +++ b/NATRouter.cpp @@ -7,22 +7,42 @@ #include "NATRouter.h" -NATRouter::NATRouter() +void NATRouter::initalizeNatTable() { try { natTable = new NATItem[65536]; } - catch(bad_alloc &ba) + 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=0; i<65536; ++i) + for (int i=1; i<65536; ++i) if (this->natTable[i].isFree()) return i; @@ -39,9 +59,15 @@ void NATRouter::onRecv() { Packet p = this->recv(); + // TODO: jako ze router jest tez switchem, zaimplementowac wysylanie wiadomosci po sieci lokalnej if (p.getSrcPort() != 0) { - if (p.getDstIp() != this->getIp() && p.getDstIp() != this->getWanIp()) + // 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()) + { + this->send(p, true); + } + else if (p.getDstIp() != this->getIp() && p.getDstIp() != this->getWanIp()) { this->sNAT(&p); } @@ -97,6 +123,8 @@ void NATRouter::sNAT(Packet *packet) natItem = &this->natTable[port]; natItem->setIp(packet->getSrcIp()); natItem->setPort(packet->getSrcPort()); + natItem->setTimeout(5); + packet->setSrcIp(this->getWanIp()); // zamieniam IP lokalne na WAN'owe packet->setSrcPort(port); // zamieniam port lokalny na WAN'owy - z tablicy NAT diff --git a/NATRouter.h b/NATRouter.h index 6fcc77d..66be364 100644 --- a/NATRouter.h +++ b/NATRouter.h @@ -14,14 +14,18 @@ class NATRouter : public Node { - NATItem *natTable; // tablica z zaalokowanymi portami na zewnątrz - NetConf netWanConf; // konfiguracja sieciowa na zewnątrz + NATItem *natTable = NULL; // tablica z zaalokowanymi portami na zewnątrz + NetConf netWanConf; // konfiguracja sieciowa na zewnątrz + void initalizeNatTable(); int getFreePort(); void sNAT(Packet *packet); void dNAT(Packet *packet); public: NATRouter(); + NATRouter(string hostname); + NATRouter(string hostname, string ip, string mask); + NATRouter(string hostname, string ip, string mask, string gatewayIp); ~NATRouter(); virtual void onRecv(); diff --git a/Node.cpp b/Node.cpp index a2b9b72..bbf84dc 100644 --- a/Node.cpp +++ b/Node.cpp @@ -6,9 +6,11 @@ */ #include "Node.h" +#include "NATRouter.h" Node * Node::findConnection(string ip) { + NATRouter *ptr; if (ip == "0.0.0.0") return NULL; @@ -17,6 +19,17 @@ Node * Node::findConnection(string ip) { if ((*it)->getIp() == ip) return *it; + + /* + * jezeli wezel ma polaczenie do NAT-routera + * (i istnieje jego interfejs WAN to sprawdz + * czy nie ma z nim bezposredniego polaczenia) + */ + ptr = dynamic_cast(*it); + + if (ptr != NULL) + if (ptr->getWanIp() == ip) + return *it; } return NULL; @@ -35,6 +48,32 @@ Packet Node::recv() return packet; } +string Node::ipToString(unsigned int ip) +{ + ostringstream ss; + ss << ((ip>>24)&0xFF) << "." << ((ip>>16)&0xFF) << "." << ((ip>>8)&0xFF) << "." << (ip&0xFF); + + return ss.str(); +} + +unsigned int Node::stringToIp(string ip) +{ + istringstream iss(ip); + int offset = 24; + unsigned int res=0; + + std::string token; + while (getline(iss, token, '.')) { + if (!token.empty()) + { + res |= atoi(token.c_str()) << offset; + offset -= 8; + } + } + + return res; +} + Node::Node() { this->setHostname(""); @@ -143,15 +182,19 @@ void Node::setHostname(string hostname) void Node::setIp(string ip) { this->netConf.ip = ip; + + this->setNetwork(); } void Node::setMask(string mask) { this->netConf.mask = mask; + this->setNetwork(); } void Node::setGatewayIp(string gatewayIp) { + // TODO mozna ewentualnie zrobic sprawdzenie czy gateway jest w podsieci this->netConf.gatewayIp = gatewayIp; } @@ -175,6 +218,11 @@ string Node::getGatewayIp() return this->netConf.gatewayIp; } +string Node::calculateNetwork(string ip, string mask) +{ + return ipToString(stringToIp(ip) & stringToIp(mask)); +} + void Node::onRecv() { // TESTOWO @@ -189,3 +237,13 @@ void Node::onRecv() } } + +void Node::setNetwork() +{ + this->netConf.network = this->calculateNetwork(this->netConf.ip, this->netConf.mask); +} + +string Node::getNetwork() +{ + return this->netConf.network; +} diff --git a/Node.h b/Node.h index c543e1d..0569f20 100644 --- a/Node.h +++ b/Node.h @@ -10,22 +10,29 @@ #include "common.h" #include "Packet.h" - typedef struct { string ip; string mask; + string network; string gatewayIp; } NetConf; class Node { -protected: +private: queuercvBuffer; // kolejka z pakietami do przetworzenia vector connectedNodes; // referencje do węzłów, z którymi jest podłączony NetConf netConf; // konfiguracja sieciowa string hostname; // nazwa węzła + void setNetwork(); +protected: Node * findConnection(string ip); Packet recv(); + string ipToString(unsigned int ip); + unsigned int stringToIp(string ip); +public: + string calculateNetwork(string ip, string mask); + public: Node(); Node(string hostname); @@ -47,6 +54,7 @@ public: string getHostname(); string getIp(); string getMask(); + string getNetwork(); string getGatewayIp(); virtual void onRecv(); // wirtualna metoda na odbiór i dalszą akcję diff --git a/common.h b/common.h index c8df114..035fe28 100644 --- a/common.h +++ b/common.h @@ -15,8 +15,9 @@ #include #include #include +#include +#include using namespace std; - #endif /* COMMON_H_ */