Search code examples
c++filterpcap

How to filter by ip with pcap.h c++


I'm trying to select a group of packages of a pcap file with c++. The criteria is the IP. The code of the pcap reader:

readPcap()
{

  //Filter packages with ip = 192.168.15.40
  std::vector<std::string> rmc;
  std::string path = "../../imu10000.pcap";
  char errbuff[PCAP_ERRBUF_SIZE];
  pcap_t *pcap = pcap_open_offline(path.c_str(), errbuff);
  struct pcap_pkthdr *header;
  const unsigned char *data;

  while (int returnValue = pcap_next_ex(pcap, &header, &data) >= 0)
  {
    if (header->len != header->caplen)
        printf("Warning! Capture size different than packet size: %d bytes\n", header->len);

    // We also have a function that does this similarly below: PrintData()
    for (u_int i=0; (i < header->caplen ) ; i++)
    {
        // Start printing on the next after every 16 octets
        if ( (i % 16) == 0) printf("\n");

        // Print each octet as hex (x), make sure there is always two characters (.2).
        printf("%.2x ", data[i]);
    }
  }
}

By the moment, the code is printing all the body of all the packages in hex, but i have 10,000 packages in the file and half of them are from other IP.

Do you know how to filter by IP so I can read only the packages I need?

If you know another way for reading pcap files and filtering them, it will also be welcome.

Thank you


Solution

  • The Data array from the pcap_next_ex() call will contain the raw packet bytes (pcap_next_ex man). You need to find the index of the field that contains the IPAddress you are trying to filter out (most likely the IPv4 source or destination address field.)

    Unless you are dealing with a non-ipv4 case you should have packets where the layers are (generalized): MAC, IPv4, protocol, payload. The MAC layer will consist of 14-bytes, this will be added to any index. And the IPv4 layer should look like this. The last two fields you see are the src and dst IPAddresses. Thus take whichever index value you need, account for the 14-bytes in the MAC, and then extract the necessary bytes (4 for an IP) from this index. Use any Network-to-Host conversions, and now you got yourself an IP that can be compared to your filter value.

    Note: This is a generalized way to filter ipv4 packets. If you want an "all traffic via an ip", including such protocols as ARP or ICMP you will need to take a look at those protocol structures and find the appropriate byte index of the defined IP. It will be similar to the above in concept.