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

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. * NATItem.cpp
  3. *
  4. * Created on: 11-01-2017
  5. * Author: Piotr Dergun
  6. */
  7. #include "NATRouter.h"
  8. void NATRouter::initalizeNatTable()
  9. {
  10. try
  11. {
  12. natTable = new NATItem[65536];
  13. }
  14. catch (bad_alloc &ba)
  15. {
  16. cerr << "Nie mozna zaalokowac pamieci dla tablicy NAT!" << endl;
  17. exit(1);
  18. }
  19. }
  20. NATRouter::NATRouter()
  21. {
  22. this->initalizeNatTable();
  23. }
  24. NATRouter::NATRouter(string hostname) : Node(hostname)
  25. {
  26. this->initalizeNatTable();
  27. }
  28. NATRouter::NATRouter(string hostname, string ip, string mask) : Node(hostname, ip, mask)
  29. {
  30. this->initalizeNatTable();
  31. }
  32. NATRouter::NATRouter(string hostname, string ip, string mask, string gatewayIp) : Node(hostname, ip, mask, gatewayIp)
  33. {
  34. this->initalizeNatTable();
  35. }
  36. int NATRouter::getFreePort()
  37. {
  38. for (int i=1; i<65536; ++i)
  39. if (this->natTable[i].isFree())
  40. return i;
  41. return -1; // nie ma żadnego wolnego portu
  42. }
  43. NATRouter::~NATRouter()
  44. {
  45. if (natTable)
  46. delete [] natTable;
  47. }
  48. void NATRouter::onRecv()
  49. {
  50. while (true)
  51. {
  52. Packet p = this->recv();
  53. stringstream s;
  54. /*if (this->getHostname() == "Router 2") {
  55. s << "src: " << p.getSrcIp() << ":" << p.getSrcPort() << "dst: " << p.getDstIp() << ":" << p.getDstPort();
  56. this->print(s.str());
  57. }*/
  58. if (p.getSrcPort() != 0)
  59. {
  60. // jezeli pakiet idzie z jednego wezla do drugiego w danej possieci to odeslij mu "jak switch"
  61. if (this->calculateNetwork(p.getDstIp(), this->getMask()) == this->getNetwork() && p.getDstIp() != this->getIp())
  62. {
  63. this->send(p, true);
  64. }
  65. else if (p.getDstIp() != this->getIp() && p.getDstIp() != this->getWanIp())
  66. {
  67. this->sNAT(&p);
  68. }
  69. else if (p.getDstIp() == this->getWanIp() && !this->natTable[p.getDstPort()].isFree())
  70. {
  71. this->dNAT(&p);
  72. }
  73. else
  74. {
  75. // TUTAJ ew. implementacja obslugi pakietu adresowanego do routera
  76. }
  77. this->delay();
  78. }
  79. else
  80. {
  81. #ifndef DEBUG
  82. this->print("onRecv() sleeping...");
  83. #endif
  84. }
  85. this->delay();
  86. }
  87. }
  88. void NATRouter::setWanIp(string wanIp)
  89. {
  90. this->netWanConf.ip = wanIp;
  91. this->setWanNetwork();
  92. }
  93. void NATRouter::setWanMask(string wanMask)
  94. {
  95. this->netWanConf.mask = wanMask;
  96. this->setWanNetwork();
  97. }
  98. void NATRouter::setWanGatewayIp(string wanGatewayIp)
  99. {
  100. this->netWanConf.gatewayIp = wanGatewayIp;
  101. }
  102. string NATRouter::getWanIp()
  103. {
  104. return this->netWanConf.ip;
  105. }
  106. string NATRouter::getWanMask()
  107. {
  108. return this->netWanConf.mask;
  109. }
  110. /*
  111. * funkcja SNAT zapisuje w tablicy NAT
  112. * numer portu zrodlowego komputera z LAN
  113. * oraz jego IP i przeksztalca pakiet, zmieniajac
  114. * zrodlowy IP na IP zewn. routera oraz wolny
  115. * port z tablicy NAT. Jezeli portu nie ma to funkcja
  116. * czeka, az sie zwolni
  117. */
  118. void NATRouter::sNAT(Packet *packet)
  119. {
  120. int port;
  121. NATItem *natItem;
  122. // mozliwe, ze juz port zostal zaalokowany, to trzeba wykorzystac
  123. port = this->getAllocatedPort(packet->getSrcIp(), packet->getSrcPort());
  124. if (port == -1)
  125. while ((port = this->getFreePort()) == -1)
  126. {
  127. //TESTOWO
  128. this->print("NAT table full, waiting 1s");
  129. this->delay(1);
  130. }
  131. // wstawiam do tablicy NAT info ze port zarezerowany na odbior
  132. natItem = &this->natTable[port];
  133. natItem->setIp(packet->getSrcIp());
  134. natItem->setPort(packet->getSrcPort());
  135. natItem->setTimeout(/*5*/15);
  136. stringstream ss;
  137. ss << "SNAT " << packet->getSrcIp() << ":" << packet->getSrcPort() << " --> " << this->getWanIp() << ":" << port;
  138. packet->setSrcIp(this->getWanIp()); // zamieniam IP lokalne na WAN'owe
  139. packet->setSrcPort(port); // zamieniam port lokalny na WAN'owy - z tablicy NAT
  140. this->print(ss.str());
  141. this->delay();
  142. this->send(*packet, true); // wysylam dalej
  143. natItem = NULL;
  144. }
  145. /*
  146. * funkcja DNAT ma za zadanie znalezc w tablicy NAT
  147. * port i adres IP wezla na ktory ma wrocic odpowiedz
  148. * z sieci Internet (z zewnatrz), a takze przedluzyc
  149. * czas zycia tego portu
  150. */
  151. void NATRouter::dNAT(Packet* packet)
  152. {
  153. NATItem *natItem = &this->natTable[packet->getDstPort()];
  154. stringstream ss;
  155. ss << "DNAT " << packet->getDstIp() << ":" << packet->getDstPort() << " --> " << natItem->getIp() << ":" << natItem->getPort();
  156. packet->setDstIp(natItem->getIp()); // zamieniam IP lokalne na WAN'owe
  157. packet->setDstPort(natItem->getPort()); // zamieniam port NAT na lokalny wezla
  158. //natItem->free(); // zwalniam port w routerze
  159. natItem->increaseTimeout(5); // podbijam o kolejne 5 sekund skoro transmisja trwa
  160. this->print(ss.str());
  161. this->delay();
  162. this->send(*packet, true); // wysylam dalej
  163. natItem = NULL;
  164. }
  165. void NATRouter::setWanNetwork()
  166. {
  167. this->netWanConf.network = this->calculateNetwork(this->getWanIp(), this->getWanMask());
  168. }
  169. string NATRouter::getWanNetwork()
  170. {
  171. return this->netWanConf.network;
  172. }
  173. /*
  174. * funkcja szuka aktywnego zaalokowanego portu (aktywna
  175. * transmisja) w tablicy NAT dla pary (srcIp:srcPort)
  176. */
  177. int NATRouter::getAllocatedPort(string srcIp, int srcPort)
  178. {
  179. for (int i=1; i<65536; ++i)
  180. if (this->natTable[i].getIp() == srcIp && this->natTable[i].getPort() == srcPort)
  181. return i;
  182. return -1; // nic nie znaleziono
  183. }
  184. string NATRouter::getWanGatewayIp()
  185. {
  186. return this->netWanConf.gatewayIp;
  187. }