IPv4Packet.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above
  10. * copyright notice, this list of conditions and the following
  11. * disclaimer in the documentation and/or other materials provided
  12. * with the distribution.
  13. * * Neither the name of The Linux Foundation nor the names of its
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  21. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  24. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  25. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  26. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  27. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include "TestsUtils.h"
  30. #include "IPv4Packet.h"
  31. #include "memory.h"
  32. using namespace IPA;
  33. static const unsigned char TCP_IP_PACKET_DUMP[] = { 0x45, // IPv4, IHL = 5
  34. 0x00, // ToS = 0
  35. 0x00, 0x28, // Total length
  36. 0x11, 0xc2, // ID
  37. 0x40, 0x00, //ID + Fragment Offset
  38. 0x80, // TTL
  39. 0x06, // Protocol = TCP
  40. 0x70, 0x3a, //Checksum
  41. 0x0a, 0x05, 0x07, 0x46, // Source IP 10.5.7.70
  42. 0x81, 0x2e, 0xe6, 0x5a, // Destination IP 129.46.230.90
  43. 0xf3, 0xa2, // Source Port 62370
  44. 0x01, 0xbd, // Destination Port 445
  45. 0x26, 0x26, 0x1d, 0x7d, // Seq Number
  46. 0x15, 0xaa, 0xbc, 0xdb, // Ack Num
  47. 0x50, 0x10, 0x80, 0xd4, // TCP Params
  48. 0xaa, 0xa3, // TCP Checksum
  49. 0x00, 0x00 // Urgent PTR
  50. };
  51. static const unsigned char UDP_IP_PACKET_DUMP[] = {
  52. 0x45, // IPv4, IHL = 5
  53. 0x00, // ToS = 0
  54. 0x00,
  55. 0x34, // Total Length
  56. 0x12,
  57. 0xa2, // ID
  58. 0x00,
  59. 0x00, //ID + fragment offset
  60. 0x80, // TTL
  61. 0x11, // Protocol = UDP
  62. 0xe4,
  63. 0x92, // Checksum
  64. 0x0a, 0x05, 0x07,
  65. 0x46, // Source IP 10.5.7.70
  66. 0x0a, 0x2b, 0x28,
  67. 0x0f, // Destination IP 10.43.40.15
  68. 0x03,
  69. 0x4a, // Source port 842
  70. 0x1b,
  71. 0x4f, // Destination Port 6991
  72. 0x00,
  73. 0x20, // UDP length
  74. 0x36,
  75. 0xac, // UDP checksum
  76. 0x00, 0x05, 0x20,
  77. 0x6d, // Data
  78. 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  79. 0x00, 0x00, 0x00, 0x01, 0x13, 0x05, 0x20, 0x6c };
  80. static unsigned char ICMP_IP_PACKET_DUMP[] = {
  81. //IP
  82. 0x45, 0x00, 0x00, 0xdc, 0x03, 0xfe, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
  83. 0x81, 0x2e, 0xe4, 0xf6, 0x81, 0x2e, 0xe6, 0xd4,
  84. //ICMP
  85. 0x00, 0x00, 0xa9, 0xcd, 0x28, 0xa3, 0x01, 0x00,
  86. //DATA
  87. 0xee, 0x7c, 0xf7, 0x90, 0x39, 0x06, 0xd4, 0x41, 0x51, 0x51, 0x51, 0x51,
  88. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  89. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  90. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  91. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  92. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  93. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  94. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  95. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  96. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  97. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  98. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  99. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  100. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  101. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
  102. 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51 };
  103. static void LittleToBigEndianUint32(unsigned char *pBigEndianBuffer,
  104. unsigned int nUint32LittleEndianValue) {
  105. unsigned char nLsb = nUint32LittleEndianValue & 0xff;
  106. unsigned char nLsbMsbLow = (nUint32LittleEndianValue >> 8) & 0xff;
  107. unsigned char nLsbMsbHigh = (nUint32LittleEndianValue >> 16) & 0xff;
  108. unsigned char nMsb = (nUint32LittleEndianValue >> 24) & 0xff;
  109. pBigEndianBuffer[0] = nMsb;
  110. pBigEndianBuffer[1] = nLsbMsbHigh;
  111. pBigEndianBuffer[2] = nLsbMsbLow;
  112. pBigEndianBuffer[3] = nLsb;
  113. }
  114. static unsigned short BigToLittleEndianUint16(unsigned char *pBigEndianStart) {
  115. unsigned char nMsb = pBigEndianStart[0];
  116. unsigned char nLsb = pBigEndianStart[1];
  117. return (nMsb << 8 | nLsb << 0);
  118. }
  119. static unsigned int BigToLittleEndianUint32(unsigned char *pBigEndianStart) {
  120. unsigned char nMsb = pBigEndianStart[0];
  121. unsigned char nMsbLsbHigh = pBigEndianStart[1];
  122. unsigned char nMsbLsbLow = pBigEndianStart[2];
  123. unsigned char nLsb = pBigEndianStart[3];
  124. return (nMsb << 24 | nMsbLsbHigh << 16 | nMsbLsbLow << 8 | nLsb << 0);
  125. }
  126. static void LittleToBigEndianUint16(unsigned char *pBigEndianBuffer,
  127. unsigned int nUint16LittleEndianValue) {
  128. unsigned char nLsb = nUint16LittleEndianValue & 0xff;
  129. unsigned char nMsb = (nUint16LittleEndianValue >> 8) & 0xff;
  130. pBigEndianBuffer[0] = nMsb;
  131. pBigEndianBuffer[1] = nLsb;
  132. }
  133. static unsigned short Get2BBIGEndian(const unsigned char *pBuff, int offset) {
  134. unsigned char upperByte = 0;
  135. unsigned char lowerByte = 0;
  136. memcpy(&upperByte, pBuff + offset, 1);
  137. memcpy(&lowerByte, pBuff + offset + 1, 1);
  138. return (upperByte << 8 | lowerByte);
  139. }
  140. IPv4Packet::IPv4Packet(unsigned int size) :
  141. m_PacketSize(size) {
  142. }
  143. IPv4Packet::~IPv4Packet(void) {
  144. if (0 != m_Packet) {
  145. delete[] m_Packet;
  146. m_Packet = 0;
  147. }
  148. }
  149. void IPv4Packet::ToNetworkByteStream(unsigned char *buffer) {
  150. if (0 == buffer) {
  151. LOG_MSG_ERROR("IPv4Packet::ToNetworkByteStream : NULL arguments");
  152. return;
  153. }
  154. memcpy(buffer, m_Packet, GetSize());
  155. }
  156. unsigned int IPv4Packet::GetSrcAddr(void) {
  157. return BigToLittleEndianUint32(m_Packet + 12);
  158. }
  159. void IPv4Packet::SetSrcAddr(unsigned int addr) {
  160. LittleToBigEndianUint32(m_Packet + 12, addr);
  161. RecalculateChecksum();
  162. }
  163. unsigned int IPv4Packet::GetDstAddr(void) {
  164. return BigToLittleEndianUint32(m_Packet + 16);
  165. }
  166. void IPv4Packet::SetDstAddr(unsigned int addr) {
  167. LittleToBigEndianUint32(m_Packet + 16, addr);
  168. RecalculateChecksum();
  169. }
  170. unsigned char IPv4Packet::GetProtocol(void) {
  171. unsigned char retVal = 0;
  172. memcpy(&retVal, m_Packet + 9, sizeof(unsigned char));
  173. return retVal;
  174. }
  175. unsigned short IPv4Packet::GetSrcPort(void) {
  176. return BigToLittleEndianUint16(m_Packet + 20);
  177. }
  178. unsigned short IPv4Packet::GetDstPort(void) {
  179. return BigToLittleEndianUint16(m_Packet + 22);
  180. }
  181. void IPv4Packet::SetDstPort(unsigned short port) {
  182. LittleToBigEndianUint16(m_Packet + 22, port);
  183. RecalculateChecksum();
  184. }
  185. void IPv4Packet::SetSrcPort(unsigned short port) {
  186. LittleToBigEndianUint16(m_Packet + 20, port);
  187. RecalculateChecksum();
  188. }
  189. ///////////////////////////////////////////////////////////////////////////////
  190. //Set the third MSB bit of the IPV4_FLAGS_BYTE_OFFSET's byte
  191. void IPv4Packet::SetMF(bool bValue) {
  192. Byte * pFlags = m_Packet + IPV4_FLAGS_BYTE_OFFSET;
  193. //clear the bit
  194. if (true == bValue) {
  195. *pFlags |= (0x20);
  196. } else {
  197. *pFlags &= (~0x20);
  198. }
  199. }
  200. ///////////////////////////////////////////////////////////////////////////////
  201. void IPv4Packet::RecalculateChecksum(void) {
  202. RecalculateIPChecksum();
  203. RecalculateTCPChecksum();
  204. RecalculateUDPChecksum();
  205. }
  206. void IPv4Packet::RecalculateIPChecksum(void) {
  207. unsigned short pUint16[100];
  208. int headerLen = (m_Packet[0] & 0x0F) * 2;
  209. int checksum = 0;
  210. unsigned short result = 0;
  211. memset(&pUint16, 0, 100 * sizeof(unsigned short));
  212. //clear the IP checksum field first
  213. memset(m_Packet + 10, 0, sizeof(unsigned short));
  214. memcpy(&pUint16, m_Packet, headerLen * sizeof(unsigned short));
  215. for (int i = 0; i < headerLen; i++) {
  216. checksum += pUint16[i];
  217. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  218. }
  219. result = (~checksum & 0xFFFF);
  220. memcpy(m_Packet + 10, &result, sizeof(unsigned short));
  221. return;
  222. }
  223. void TCPPacket::RecalculateTCPChecksum(void) {
  224. unsigned short *pUint16 = new unsigned short[100];
  225. int checksum = 0;
  226. int headerLen = 0;
  227. unsigned short *pTemp = 0;
  228. unsigned short result = 0;
  229. headerLen = Get2BBIGEndian(m_Packet, 2) - (m_Packet[0] & 0x0F) * 4;
  230. memset(pUint16, 0, 100);
  231. //clear the TCP checksum field first
  232. memset(m_Packet + 36, 0, sizeof(unsigned short));
  233. memcpy(pUint16, m_Packet, headerLen * sizeof(unsigned short));
  234. pTemp = pUint16;
  235. // Pseudo Header
  236. pUint16 += 6; // Source IP
  237. for (int i = 0; i < 4; i++) {
  238. checksum += pUint16[i];
  239. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  240. }
  241. checksum += 0x0600; // TCP Protocol
  242. checksum += Get2BBIGEndian((unsigned char*) &headerLen, 0);
  243. pUint16 = pTemp + (m_Packet[0] & 0x0F) * 2;
  244. headerLen /= 2;
  245. for (int i = 0; i < headerLen; i++) {
  246. checksum += pUint16[i];
  247. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  248. }
  249. result = (~checksum & 0xFFFF);
  250. memcpy(m_Packet + 36, &result, sizeof(unsigned short));
  251. delete[] pTemp;
  252. return;
  253. }
  254. void UDPPacket::RecalculateUDPChecksum(void) {
  255. unsigned short *pUint16 = new unsigned short[100];
  256. int checksum = 0;
  257. int headerLen = 0;
  258. unsigned short *pTemp = 0;
  259. unsigned short result = 0;
  260. headerLen = Get2BBIGEndian(m_Packet, (m_Packet[0] & 0x0F) * 4 + 4);
  261. memset(pUint16, 0, 100);
  262. //clear the UDP checksum field first
  263. memset(m_Packet + 26, 0, sizeof(unsigned short));
  264. memcpy(pUint16, m_Packet, headerLen * sizeof(unsigned short));
  265. pTemp = pUint16;
  266. // Pseudo Header
  267. pUint16 += 6; // Source IP
  268. for (int i = 0; i < 4; i++) {
  269. checksum += pUint16[i];
  270. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  271. }
  272. checksum += 0x1100; // UDP Protocol
  273. checksum += Get2BBIGEndian((unsigned char*) &headerLen, 0);
  274. pUint16 = pTemp + (m_Packet[0] & 0x0F) * 2;
  275. headerLen /= 2;
  276. for (int i = 0; i < headerLen; i++) {
  277. checksum += pUint16[i];
  278. checksum = (checksum & 0xFFFF) + (checksum >> 16);
  279. }
  280. result = (~checksum & 0xFFFF);
  281. memcpy(m_Packet + 26, &result, sizeof(unsigned short));
  282. delete[] pTemp;
  283. return;
  284. }
  285. TCPPacket::TCPPacket(void) :
  286. IPv4Packet(sizeof(TCP_IP_PACKET_DUMP)) {
  287. size_t length = GetSize();
  288. m_Packet = new unsigned char[length];
  289. if (0 == m_Packet) {
  290. LOG_MSG_ERROR("TCPPacket : packet allocation failed");
  291. return;
  292. }
  293. memcpy(m_Packet, TCP_IP_PACKET_DUMP, length);
  294. }
  295. UDPPacket::UDPPacket(void) :
  296. IPv4Packet(sizeof(UDP_IP_PACKET_DUMP)) {
  297. size_t length = GetSize();
  298. m_Packet = new unsigned char[length];
  299. if (0 == m_Packet) {
  300. LOG_MSG_ERROR("UDPPacket : packet allocation failed");
  301. return;
  302. }
  303. memcpy(m_Packet, UDP_IP_PACKET_DUMP, length);
  304. }
  305. ICMPPacket::ICMPPacket(void) :
  306. IPv4Packet(sizeof(ICMP_IP_PACKET_DUMP)) {
  307. size_t length = GetSize();
  308. m_Packet = new unsigned char[length];
  309. if (0 == m_Packet) {
  310. LOG_MSG_ERROR("ICMPPacket : packet allocation failed");
  311. return;
  312. }
  313. memcpy(m_Packet, ICMP_IP_PACKET_DUMP, length);
  314. }
  315. unsigned short ICMPPacket::GetSrcPort(void) {
  316. return 0;
  317. }
  318. unsigned short ICMPPacket::GetDstPort(void) {
  319. return 0;
  320. }
  321. void ICMPPacket::SetDstPort(unsigned short port) {
  322. (void) port;
  323. return;
  324. }
  325. void ICMPPacket::SetSrcPort(unsigned short port) {
  326. (void) port;
  327. return;
  328. }