0

I'm using libtins in C++ project on Linux to create a pcap dump. The pcap dump that I am getting from my code does not appear to be readable by Wireshark, tcp dump, or the example that I used to try and read the code with libtins.

I need my program to produce output which is readable by wireshark, as well as being readable in a way that I can read it via code in my project as well.

Edit:

relevant code:

bool packetHandler(const PDU &pdu) {
    const IP &ip = pdu.rfind_pdu<IP>();
    return true;
    cout << ip.src_addr() << " -> " << ip.dst_addr() << endl;
    return true;
} 

int main(int argc, char** argv)
{
      if(getuid() != 0)
      {
      printf("You must run this program as root!\n");
      exit(1);
      }
      try
      {
        std::string pcap_path = "/tmp/test.pcap";
        std::string device = "eth0";
        printf("Filepath: %s\n", pcap_path.c_str());
        PacketWriter writer(pcap_path, DataLinkType<EthernetII>());
        std::vector<EthernetII> vec(1000, EthernetII(hwaddr(device)));
        writer.write(vec.begin(), vec.end());
        writer.write(vec[0]);
      } catch(Tins::unknown_link_type e)
      {
    printf("ERROR:\t%s\n", e.what());
      } catch(std::runtime_error e)
      {
      printf("ERROR:\t%s\n", e.what());
      }
}

I have also tried this code to read the pcap but it doesn't output anything:

#include <tins/tins.h>
using namespace Tins;
using namespace std;
bool packetHandler(PDU &pdu)
{
    // Find the IP layer
    const IP &ip = pdu.rfind_pdu<IP>(); 
    cout << ip.src_addr() << " -> " << ip.dst_addr() << endl;
    return true;
}
int main() {
    FileSniffer sniffer("/tmp/test.pcap");
    sniffer.sniff_loop(packetHandler);
}

edit.. again

As you can see from wireshark I'm getting the incorrect values for each field and data which is all 0s. https://i.stack.imgur.com/KTtq7.png (sry I couldn't embed the image because I don't have 10 reputation points on here). I need to be able to see the IP addresses, data, etc in the correct fields on wireshark but I'm not getting the correct data.

  • a [mcve] must be posted inline (not as a link) as part of your question in order to make sure it is useful in the future for other people with a similar question. Also, the current and desired behaviors must be specified. – xaxxon Jul 30 '18 at 02:00
  • Thank you @xaxxon. I have gone ahead and updated my post with the code and more details as to what is wrong and what I need. – Robert Whitney Jul 30 '18 at 02:09
  • That second code is much more minimal than the first. But "with no such luck" doesn't really help. What did it output? What did you expect? Do you have a minimal pcap file you could paste as well - perhaps the problem is with that. – dave Jul 30 '18 at 04:10
  • Thx @dave, I have made updates to my post to clarify what I need and provided an image of how the pcap dump looks in Wireshark. I can't post a pcap dump though because it's binary data and wouldn't go into the post well. ;) I hope the image will suffice. – Robert Whitney Jul 30 '18 at 07:24
  • Can you post the pcap dump on pastebin? – oxr463 Aug 01 '18 at 13:01
  • You can find a example of writing pcap files on https://stackoverflow.com/questions/11150245/pcap-library-capabilities-writing-new-pcap-files/59759181#59759181 – camp0 Feb 11 '20 at 09:03

1 Answers1

0

I've just started to study libtins. I've got how to capture packets, based in this tutorial here: https://libtins.github.io/tutorial/sniffing/

#include <tins/tins.h>
#include <iostream>
#include <typeinfo>

using namespace Tins;
using namespace std;

/*
Compile

g++ loop_sniffing_simple.cpp -o loop_sniffing_simple.o -O3 -std=c++11 -lpthread -ltins


Run

sudo ./loop_sniffing_simple.o


From other machine (192.168.72.57) send something
*/

void test() {
    SnifferConfiguration config;
    config.set_promisc_mode(true);
    config.set_filter("ip host 192.168.72.57");
    Sniffer sniffer("wlp2s0", config);
    // sniffer.sniff_loop(doo);

    PacketWriter writer = PacketWriter("sniffer.pcap", DataLinkType<IP>());

    int n_packet = 0;
    const int totalPackets = 4;
    for (auto &packet : sniffer) {
        auto pdu = packet.release_pdu();
        IP ip = pdu->rfind_pdu<IP>();

        cout << "Destination IP: " << ip.dst_addr()
            << " source IP: " << ip.src_addr() << endl;
        // cout << typeid(ip).name() << endl;

        // writer.write(pdu->rfind_pdu<IP>());
        writer.write(ip);

        ++n_packet;
        
        if (n_packet == totalPackets) {
            break;
        }
    }

}

int main() {

    test();

    return 0;
}

In the end you will have a correct pcap file

Other example, I guess it is better:

#include <vector>
#include <tins/tins.h>
#include <iostream>

using namespace Tins;
using namespace std;

/*
Compile

g++ packet_objects.cpp -o packet_objects.o -O3 -std=c++11 -lpthread -ltins
*/

int main() {
    vector<Packet> vt;
    PacketWriter writer = PacketWriter("sniffer_obj.pcap", DataLinkType<IP>());

    Sniffer sniffer("wlp2s0");
    while (vt.size() != 10) {
        // next_packet returns a PtrPacket, which can be implicitly converted to Packet.
        vt.push_back(sniffer.next_packet());
    }
    // Done, now let's cehck the packets
    for (const auto& packet : vt) {
        // Is there an IP PDU somewhere?
        if(packet.pdu()->find_pdu<IP>()) {
            // Just print timestamp's seconds and IP source address
            cout << "At: " << packet.timestamp().seconds()
                << " - " << packet.pdu()->rfind_pdu<IP>().src_addr() 
                << std::endl;
            
            IP ip = packet.pdu()->rfind_pdu<IP>();

            writer.write(ip);
        }
    }

    return 0;
}