Browse Source

zaimplementowanie funkcjonalnosci sieci lokalnej: NATRouter moze miec polaczenia do komputerow (a'la switch) i przekazywac pakiety

implementacja liczenia adresu podsieci
master
Piotr Dergun 7 years ago
parent
commit
37a2ce3ccb
7 changed files with 161 additions and 14 deletions
  1. +53
    -4
      Main.cpp
  2. +0
    -1
      NATItem.h
  3. +32
    -4
      NATRouter.cpp
  4. +6
    -2
      NATRouter.h
  5. +58
    -0
      Node.cpp
  6. +10
    -2
      Node.h
  7. +2
    -1
      common.h

+ 53
- 4
Main.cpp View File

@ -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;
}

+ 0
- 1
NATItem.h View File

@ -18,7 +18,6 @@ class NATItem
public:
NATItem();
NATItem();
bool isFree();

+ 32
- 4
NATRouter.cpp View File

@ -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

+ 6
- 2
NATRouter.h View File

@ -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();

+ 58
- 0
Node.cpp View File

@ -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<NATRouter*>(*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;
}

+ 10
- 2
Node.h View File

@ -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:
queue<Packet>rcvBuffer; // kolejka z pakietami do przetworzenia
vector<Node*> 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ę

+ 2
- 1
common.h View File

@ -15,8 +15,9 @@
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <sstream>
#include <cstdio>
using namespace std;
#endif /* COMMON_H_ */

Loading…
Cancel
Save