utilities.cpp 6.1 KB

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