utilities.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "utilities.h"
  2. using namespace Tins;
  3. template<class T>
  4. std::string integral_to_binary_string(T byte)
  5. {
  6. std::bitset<sizeof(T) * CHAR_BIT> bs(byte);
  7. return bs.to_string();
  8. }
  9. /**
  10. * Split a string.
  11. * @param str string to be splitted.
  12. * @param delimiter delimiter to use in splitting.
  13. * @return vector of substrings.
  14. */
  15. void split_str(const std::string& s, char delim,std::vector<std::string>& v) {
  16. auto i = 0;
  17. auto pos = s.find(delim);
  18. while (pos != std::string::npos) {
  19. v.push_back(s.substr(i, pos-i));
  20. i = ++pos;
  21. pos = s.find(delim, pos);
  22. if (pos == std::string::npos)
  23. v.push_back(s.substr(i, s.length()));
  24. }
  25. }
  26. /**
  27. * Get the class (A,B,C,D,E) of IP address.
  28. * @param ipAddress IP that we get its class.
  29. */
  30. std::string getIPv4Class(const std::string &ipAddress){
  31. std::string ipClass="Unknown";
  32. std::vector<std::string> ipBytes;
  33. split_str(ipAddress, '.',ipBytes);
  34. //std::cout<< ipAddress << "\n";
  35. if(ipBytes.size()>1){
  36. int b1 = std::stoi(ipBytes[0]);
  37. int b2 = std::stoi(ipBytes[1]);
  38. if(b1 >= 1 && b1 <= 126){
  39. if(b1 == 10)
  40. ipClass = "A-private";
  41. else
  42. ipClass = "A";
  43. }
  44. else if(b1 == 127){
  45. ipClass = "A-unused"; // cannot be used and is reserved for loopback and diagnostic functions.
  46. }
  47. else if (b1 >= 128 && b1 <= 191){
  48. if(b1 == 172 && b2 >= 16 && b2 <= 31)
  49. ipClass = "B-private";
  50. else
  51. ipClass = "B";
  52. }
  53. else if (b1 >= 192 && b1 <= 223){
  54. if(b1 == 192 && b2 == 168)
  55. ipClass = "C-private";
  56. else
  57. ipClass = "C";
  58. }
  59. else if (b1 >= 224 && b1 <= 239)
  60. ipClass = "D"; // Reserved for Multicasting
  61. else if (b1 >= 240 && b1 <= 254)
  62. ipClass = "E"; // Experimental; used for research
  63. }
  64. return ipClass;
  65. }
  66. /**
  67. * Convert IP address from string to array of bytes.
  68. * @param IP to convert.
  69. * @param IP_bytes to be filled and retrieved.
  70. */
  71. void convertIPv4toArray(const std::string &IP, unsigned short IP_bytes[]){
  72. std::vector<std::string> temp_v;
  73. split_str(IP,'.',temp_v);
  74. IP_bytes[0] = std::stoi(temp_v[0]);
  75. IP_bytes[1] = std::stoi(temp_v[1]);
  76. IP_bytes[2] = std::stoi(temp_v[2]);
  77. IP_bytes[3] = std::stoi(temp_v[3]);
  78. }
  79. /**
  80. * Calculate TCP checksum.
  81. * @param len_tcp TCP packet length
  82. * @param src_addr source IP address
  83. * @param dest_addr destination IP address
  84. * @param padding
  85. * @param buff
  86. * @return checksum.
  87. */
  88. u16 tcp_sum_calc(u16 len_tcp, u16 src_addr[],u16 dest_addr[], bool padding, u16 buff[])
  89. {
  90. u16 prot_tcp=6;
  91. u16 padd=0;
  92. u16 word16;
  93. u32 sum;
  94. // Find out if the length of data is even or odd number. If odd,
  95. // add a padding byte = 0 at the end of packet
  96. //if ((padding&1)==1){
  97. if(padding){
  98. padd=1;
  99. buff[len_tcp]=0;
  100. }
  101. //initialize sum to zero
  102. sum=0;
  103. // make 16 bit words out of every two adjacent 8 bit words and
  104. // calculate the sum of all 16 vit words
  105. for (int i=0;i<len_tcp+padd;i=i+2){
  106. word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
  107. sum = sum + (unsigned long)word16;
  108. }
  109. // add the TCP pseudo header which contains:
  110. // the IP source and destinationn addresses,
  111. for (int i=0;i<4;i=i+2){
  112. word16 =((src_addr[i]<<8)&0xFF00)+(src_addr[i+1]&0xFF);
  113. sum=sum+word16;
  114. }
  115. for (int i=0;i<4;i=i+2){
  116. word16 =((dest_addr[i]<<8)&0xFF00)+(dest_addr[i+1]&0xFF);
  117. sum=sum+word16;
  118. }
  119. // the protocol number and the length of the TCP packet
  120. sum = sum + prot_tcp + len_tcp;
  121. // keep only the last 16 bits of the 32 bit calculated sum and add the carries
  122. while (sum>>16)
  123. sum = (sum & 0xFFFF)+(sum >> 16);
  124. // Take the one's complement of sum
  125. sum = ~sum;
  126. return ((unsigned short) sum);
  127. }
  128. /**
  129. * Checks the TCP checksum of a given packet.
  130. * @param ipAddressSender The source IP.
  131. * @param ipAddressReceiver The destination IP.
  132. * @param tcpPkt The packet to get checked.
  133. */
  134. bool check_tcpChecksum(const std::string &ipAddressSender, const std::string &ipAddressReceiver, TCP tcpPkt){
  135. uint16_t checksum = tcpPkt.checksum();
  136. unsigned short calculatedChecsum = 0;
  137. int headerSize = tcpPkt.header_size();
  138. std::vector<uint8_t> bufferArray_8;
  139. try {
  140. bufferArray_8 = tcpPkt.serialize();
  141. } catch (serialization_error&) {
  142. std::cerr << "Error: Could not serialize TCP packet with sender: " << ipAddressSender << ", receiver: "
  143. << ipAddressReceiver << ", seq: " << tcpPkt.seq() << std::endl;
  144. return false;
  145. }
  146. std::vector<unsigned short> bufferArray_16;
  147. for(int i=0; (unsigned)i<bufferArray_8.size();i++){
  148. bufferArray_16.push_back(bufferArray_8[i]);
  149. }
  150. unsigned short* buff_16 = &bufferArray_16[0];
  151. unsigned short ipAddressSender_bytes[4];
  152. unsigned short ipAddressReceiver_bytes[4];
  153. convertIPv4toArray(ipAddressSender, ipAddressSender_bytes);
  154. convertIPv4toArray(ipAddressReceiver, ipAddressReceiver_bytes);
  155. bool padding = false;
  156. int dataSize = bufferArray_8.size() - headerSize;
  157. if(dataSize != 0)
  158. if(dataSize % 2 != 0)
  159. padding = true; // padding if the data size is odd
  160. calculatedChecsum = tcp_sum_calc(bufferArray_8.size(), ipAddressSender_bytes, ipAddressReceiver_bytes, padding, buff_16);
  161. return (calculatedChecsum == checksum);
  162. }