Search code examples
network-programmingwiresharkpcaptcpdump

libpcap read packet size


I started to write an application which will read RTP/H.264 video packets from an existing .pcap file, I need to read the packet size. I tried to use packet->len or header->len, but it never displays the right number of bytes for packets (I'm using wireshark to verify packet size - under Length column). How to do it? This is part of my code:

while (packet = pcap_next(handle,&header)) {

  u_char *pkt_ptr = (u_char *)packet;
  struct ip *ip_hdr = (struct ip *)pkt_ptr; //point to an IP header structure 
  struct pcap_pkthdr  *pkt_hdr =(struct pcap_pkthdr *)packet;

  unsigned int packet_length = pkt_hdr->len;
  unsigned int ip_length = ntohs(ip_hdr->ip_len);
  printf("Packet # %i IP Header length: %d bytes, Packet length: %d bytes\n",pkt_counter,ip_length,packet_length);


Packet # 0 IP Header length: 180 bytes, Packet length: 104857664 bytes
Packet # 1 IP Header length: 52 bytes, Packet length: 104857600 bytes
Packet # 2 IP Header length: 100 bytes, Packet length: 104857600 bytes
Packet # 3 IP Header length: 100 bytes, Packet length: 104857664 bytes
Packet # 4 IP Header length: 52 bytes, Packet length: 104857600 bytes
Packet # 5 IP Header length: 100 bytes, Packet length: 104857600 bytes

Another option I tried is to use: pkt_ptr-> I get:

read_pcapfile.c:67:43: error: request for member ‘len’ in something not a structure or union


Solution

  • while (packet = pcap_next(handle,&header)) {
    
      u_char *pkt_ptr = (u_char *)packet;
    

    Don't do that; you're throwing away the const, and you really should NOT be modifying what the return value of pcap_next() points to.

      struct ip *ip_hdr = (struct ip *)pkt_ptr; //point to an IP header structure
    

    That will point to an IP header structure ONLY if pcap_datalink(handle) returns DLT_RAW, which it probably will NOT do on most devices.

    If, for example, pcap_datalink(handle) returns DLT_EN10MB, packet will point to an Ethernet header (the 10MB is historical - it's used for all Ethernet speeds other than the ancient historical 3MB experimental Ethernet at Xerox, which had a different header type).

    See the list of link-layer header type values for a list of the possible DLT_ types.

      struct pcap_pkthdr  *pkt_hdr =(struct pcap_pkthdr *)packet;
    

    That won't work, either. The struct pcap_pkthdr for the packet is in header.

      unsigned int packet_length = pkt_hdr->len;
    

    As per my earlier comment, that won't work. Use header.len instead.

    (And bear in mind that, if a "snapshot length" shorter than the maximum packet size was specified in the pcap_open_live() call, or specified in a pcap_set_snaplen() call between the pcap_create() and pcap_activate() calls, header.caplen could be less than header.len, and only header.caplen bytes of the packet data will actually be available.)

      unsigned int ip_length = ntohs(ip_hdr->ip_len);
    

    And, as per my earlier comment, that probably won't work, either.