Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.03 KB | None | 0 0
  1. #undef _BIGENDIAN
  2.  
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #define __FAVOR_BSD   /* To unify tcp and udp headers for both FBSD & Linux */
  6. #include <netinet/in_systm.h>
  7. #include <netinet/in.h>
  8. #include <netinet/ip.h>
  9. #include <netinet/udp.h>
  10. #include <netinet/tcp.h>
  11. #include <net/ethernet.h>
  12. #include <arpa/inet.h>
  13. #include <pcap.h>
  14. #include <fcntl.h>
  15.  
  16. #include <boost/date_time/posix_time/posix_time.hpp>
  17.  
  18. #ifndef MIN
  19. # define MIN(a, b)  ((a)<(b)?(a):(b))
  20. #endif
  21.  
  22. typedef struct rtp_header
  23. {
  24. #ifdef _BIGENDIAN
  25.   uint16_t version:2;
  26.   uint16_t padbit:1;
  27.   uint16_t extbit:1;
  28.   uint16_t cc:4;
  29.   uint16_t markbit:1;
  30.   uint16_t paytype:7;
  31. #else
  32.   uint16_t cc:4;
  33.   uint16_t extbit:1;
  34.   uint16_t padbit:1;
  35.   uint16_t version:2;
  36.   uint16_t paytype:7;
  37.   uint16_t markbit:1;
  38. #endif
  39.   uint16_t seq_number;
  40.   uint32_t timestamp;
  41.   uint32_t ssrc;
  42.   uint32_t csrc[16];
  43. } __attribute__((packed)) rtp_header_t;
  44.  
  45. #define   HASH(a, b, c, d)  (((a)^(b))^(((c)^(d))))
  46.  
  47. typedef struct rtcp_header
  48. {
  49. #ifdef _BIGENDIAN
  50.   uint8_t version:2;
  51.   uint8_t padbit:1;
  52.   uint8_t count:5;
  53. #else
  54.   uint8_t count:5;
  55.   uint8_t padbit:1;
  56.   uint8_t version:2;
  57. #endif
  58.   uint8_t type;
  59.   uint16_t length;
  60. } __attribute__((packed)) rtcp_header_t;
  61.  
  62. #undef VERBOSE
  63. #define LOGUNK
  64.  
  65. enum packet_type_t {
  66.   PT_UNKNOWN, PT_RTP, PT_RTCP, PT_SIP, PT_TCPSIP, PT_UDPFRAGMENT
  67. };
  68.  
  69. bool isSIPPort(unsigned short port) {
  70.   return port == 5060 || port == 15060 || port == 23432;
  71. }
  72.  
  73. packet_type_t detectTcpSip(struct ip *ip, uint32_t *hash) {
  74.   struct tcphdr* tcp;
  75.   tcp = (struct tcphdr*)( (uint8_t*)ip + (ip->ip_hl<<2)); // ip_hl is in units of 4 bytes (32 bits)
  76.   if (ip->ip_p != IPPROTO_TCP) {
  77. #ifdef LOGUNK
  78.     fprintf(stderr, "Invalid IP-level protocol\n");
  79. #endif
  80.     return PT_UNKNOWN;
  81.   }
  82.   if(isSIPPort(ntohs(tcp->th_sport)) || isSIPPort(ntohs(tcp->th_dport))) {
  83.     *hash = HASH(ip->ip_src.s_addr, ip->ip_dst.s_addr, tcp->th_sport, tcp->th_dport);
  84.     return PT_TCPSIP;
  85.   }
  86. #ifdef LOGUNK
  87.   fprintf(stderr, "TCP ports don't match\n");
  88. #endif
  89.   return PT_UNKNOWN;
  90. }
  91.  
  92. packet_type_t detectPacketType(const uint8_t* pdata, struct pcap_pkthdr* phdr, uint32_t *hash)
  93. {
  94.   // ethernet
  95.   struct ether_header* ep;
  96.   struct ip* ip;
  97.   struct udphdr* uh;
  98.  
  99.   ep = (struct ether_header*)pdata;
  100.  
  101.   if (ntohs (ep->ether_type) != ETHERTYPE_IP) {
  102. #ifdef LOGUNK
  103.     fprintf(stderr, "Invalid PHY type protocol\n");
  104. #endif
  105.     return PT_UNKNOWN;
  106.   }
  107.  
  108.   ip = (struct ip*)(pdata + sizeof(struct ether_header));
  109.  
  110. #ifdef VERBOSE
  111.     printf("IP length=%d", ntohs(ip->ip_len));
  112.     printf(" hdr_length=%d", 4*ip->ip_hl);
  113.     printf(" src=%s", inet_ntoa(ip->ip_src));
  114.     printf(" dst=%s", inet_ntoa(ip->ip_dst));
  115.     printf(" proto=%d", ip->ip_p);
  116. #endif
  117.  
  118.   if (phdr->len < sizeof(struct ether_header) + ntohs(ip->ip_len)) {
  119.     fprintf(stderr, "error: IP packet larger than containing ethernet packet \n");
  120. #ifdef LOGUNK
  121.     fprintf(stderr, "Invalid ethernet packet length\n");
  122. #endif
  123.     return PT_UNKNOWN;
  124.   }
  125.   // filter udp packets only
  126.   if (ip->ip_p != IPPROTO_UDP) {
  127.     return detectTcpSip(ip, hash);
  128.   }
  129.  
  130.   //if(ntohs(ip->ip_off)&IP_MF || (ntohs(ip->ip_off )&IP_OFFMASK != 0)) {
  131.   // Ignore IP packet fragments other than first
  132.   if((ntohs(ip->ip_off)&IP_OFFMASK) != 0) {
  133. #ifdef VERBOSE
  134.     printf("\n");
  135. #endif
  136.     fprintf(stderr, "error: fragment of IP packet!\n");
  137.     return PT_UDPFRAGMENT;
  138.   }
  139.  
  140.   // udp
  141.   uh = (struct udphdr*)( (uint8_t*)ip + (ip->ip_hl<<2)); // ip_hl is in units of 4 bytes (32 bits)
  142.   uint32_t len = MIN(ntohs(uh->uh_ulen), htons(ip->ip_len) - (ip->ip_hl << 2));
  143.  
  144. #ifdef VERBOSE
  145.     printf(" sport=%d", ntohs(uh->uh_sport));
  146.     printf(" dport=%d", ntohs(uh->uh_dport));
  147.     printf(" udp_length=%d", ntohs(uh->uh_ulen));
  148.     printf("\n");
  149. #endif
  150.  
  151.   if(ntohs(ip->ip_len) < 4*ip->ip_hl + len) {
  152.     fprintf(stdout, "error: UDP packet smaller than containing IP packet for unknown reason\n");
  153.     return PT_UNKNOWN;
  154.   }
  155.  
  156.   *hash = HASH(ip->ip_src.s_addr, ip->ip_dst.s_addr, uh->uh_sport, uh->uh_dport);
  157.  
  158.   if(isSIPPort(ntohs(uh->uh_sport)) || isSIPPort(ntohs(uh->uh_dport)))
  159.     return PT_SIP;
  160.  
  161.   // rtp
  162.   rtp_header_t* rtp;
  163.   rtcp_header_t* rtcp;
  164.  
  165.   rtp = (rtp_header_t*)((uint8_t*)uh + sizeof(struct udphdr));
  166.   rtcp = (rtcp_header_t*)((uint8_t*)uh + sizeof(struct udphdr));
  167.  
  168.   if(len < sizeof(rtcp_header_t)) {
  169. #ifdef LOGUNK
  170.     fprintf(stderr, "Invalid RTCP header length\n");
  171. #endif
  172.     return PT_UNKNOWN;
  173.   }
  174.  
  175.   if(rtcp->version != 2) { // Version is common for RTP and RTCP
  176. #ifdef LOGUNK
  177.     fprintf(stderr, "Unknown RTP/RTCP version\n");
  178. #endif
  179.     return PT_UNKNOWN;
  180.   }
  181.  
  182.   if(rtcp->type >= 200 && rtcp->type <= 204) {
  183.     return PT_RTCP;
  184.   }
  185.  
  186.   if(len < 12) {
  187. #ifdef LOGUNK
  188.     fprintf(stderr, "Invalid RTP header length\n");
  189. #endif
  190.     return PT_UNKNOWN;
  191.   }
  192.  
  193.   if (rtp->paytype <= 34 || rtp->paytype >= 96) {
  194.     return PT_RTP;
  195.   }
  196.  
  197. #ifdef LOGUNK
  198.   fprintf(stderr, "Invalid RTP payload type\n");
  199. #endif
  200.   return PT_UNKNOWN;
  201. }
  202.  
  203.  
  204. int main(int argc, char * argv[])
  205. {
  206.   using namespace boost::posix_time;
  207.   assert( argc == 2);
  208.  
  209.   bool verbose(false);
  210.   pcap_t* p;
  211.   char errbuf[PCAP_ERRBUF_SIZE];
  212.  
  213.   p = pcap_open_offline(argv[1], errbuf);
  214.   if (p == NULL) {
  215.     fprintf(stderr, "could not open input file %s: %s \n", argv[1], errbuf);
  216.     exit(0);
  217.   }
  218.  
  219.  
  220.   ptime begin = microsec_clock::local_time();
  221.  
  222.   time_duration rtpProcessTime = seconds(0);
  223.   int rtpPackets(0), totalPackets(0), rtcpPackets(0), sipPackets(0), fragPackets(0), unkPackets(0);
  224.   uint32_t hash;
  225.   for (totalPackets = 0; true; ++totalPackets)
  226.   {
  227.     struct pcap_pkthdr hdr;
  228.     struct pcap_pkthdr* phdr = &hdr;
  229.  
  230.     const uint8_t* pdata = pcap_next(p, &hdr);
  231.  
  232.     if (pdata == NULL) {
  233.       break;
  234.     }
  235.  
  236.     packet_type_t pt;
  237.     ptime b = microsec_clock::local_time();
  238.     pt = detectPacketType(pdata, phdr, &hash);
  239.     ptime e = microsec_clock::local_time();
  240.     switch(pt) {
  241.     case PT_UDPFRAGMENT:
  242.       fragPackets ++;
  243.       break;
  244.     case PT_RTP:
  245.       std::cout << "Hash value: " << (hash%3) << std::endl;
  246.       rtpPackets ++;
  247.       break;
  248.     case PT_RTCP:
  249.       rtcpPackets ++;
  250.       break;
  251.     case PT_SIP:
  252.     case PT_TCPSIP:
  253.       sipPackets ++;
  254.       break;
  255.     case PT_UNKNOWN:
  256.       unkPackets ++;
  257.     }
  258.     rtpProcessTime += (e-b);
  259.   }
  260.  
  261.   ptime end = microsec_clock::local_time();
  262.  
  263.   std::cout << "Total Packets: " << totalPackets << std::endl;
  264.   std::cout << "Detected RTP Packets: " << rtpPackets << std::endl;
  265.   std::cout << "Detected RTCP Packets: " << rtcpPackets << std::endl;
  266.   std::cout << "Detected SIP Packets: " << sipPackets << std::endl;
  267.   std::cout << "Detected UDP Fragments: " << fragPackets << std::endl;
  268.   std::cout << "Other (Unknown) Packets: " << unkPackets << std::endl;
  269.   std::cout << "Total Time taken: " << (end-begin) << std::endl;
  270.   std::cout << "Average Total Time Per Packet: " << ((end-begin)/totalPackets) << std::endl;
  271.   std::cout << "Average Time Per RTP Check: " << (rtpProcessTime/totalPackets) << std::endl;
  272.  
  273.   return 0;
  274. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement