0
votes

I have relatively limited network programming experience and was hoping someone could help me with perhaps a n00bish question, thanks in advance for any help! :)

I have two C++ programs running separately. One is a simple packet sniffer written with the libpcap library that is filtering such that it only listens to packets received on a specific port, and then parses the packet such that it writes out the payload length and payload content to a binary file.

The other program is a simple bsd socket server program that is set to receives messages on that specific port with the recv() function, and then similarly writes the received message length and message content out to a binary file.

Everything appears to be running fine, so when I check the binary output files I expect the content to be the same... but unfortunately, I am finding they are only somewhat similar. It seems that the packet sniffer is catching the same data that the server is catching, but it is also recording extra packets with 6-byte long payloads, that apparently aren't being received by the server program.

So, either the packet sniffer is picking up packets that the server isn't supposed to know about, or the server program is missing packets that it's supposed to be receiving. However, I feel somewhat confident that the server program is functioning properly and is receiving the right messages, so these extra packets being detected by the packet sniffer baffle me. Does anyone know what these extra packets may be, and how I might filter them out?

Notes:

The client that is sending data to the ports I'm listening on is an old Windows NT machine in a small network, it's basically passing binary data to the server program for processing.

Unfortunately, I can't upload the code thanks to workplace policies. However, examples of what my code is like may be found here: http://www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

Thanks again!

2

2 Answers

0
votes

One is a simple packet sniffer written with the libpcap library that is filtering such that it only listens to packets received on a specific port, and then parses the packet such that it writes out the payload length and payload content to a binary file.

TCP port or UDP port?

If it's a TCP port, your program might receive the 3-way handshake packets and ACK-only packets.

How are you calculating the payload length? You should do it by taking the IP packet's total length, subtracting from it the IP header length (not 20 bytes, but the length from the version/header length field, so that you handle IP options; if that length is < 5, i.e. < 20 bytes, just discard the packet, it's bogus), to get the total TCP packet length, and then subtract from that the TCP header length (not 20 bytes, but the "Data Offset" field, so you handle TCP options; if that length is < 5, i.e. < 20 bytes, just discard the packet, it's bogus) to get the TCP payload length.

That should handle the options to which mfontanini refers, as well as the IP options.

If it's a UDP port, you should still handle IP options and get the total UDP packet length, and then:

  • if that's less than the length in the UDP header, discard the packet, it's bogus;
  • if the length in the UDP header is < 8, discard the packet, it's bogus;
  • otherwise, use the length in the UDP header, minus 8, as the payload length.

The other program is a simple bsd socket server program that is set to receives messages on that specific port with the recv() function, and then similarly writes the received message length and message content out to a binary file.

That won't see the initial handshake or ACK-only packets.

0
votes

My magic ball indicates those 6 bytes long payloads might be just TCP options. You should skip those options if you only want to work with the payload. Note that some packets might contain both a payload and some options.

The data offset field in the TCP packet indicates at which point the payload starts. You can have a look at that here in section 3.1.

I'd anyway recommend you using some higher level library which deals with that stuff internally. Using libtins you could do that task using some short snippet such as:

#include <tins/tins.h>

using namespace Tins;

bool callback(const PDU &pdu) {
    const RawPDU &raw = pdu.rfind_pdu<RawPDU>();
    // raw.payload() returns a std::vector<uint8_t>
    process_payload(raw.payload());
    return true;
}

int main() {
    Sniffer some_sniffer(
        "eth0", 
        Sniffer::NON_PROMISC,
        "some pcap filter"
    );
    some_sniffer.sniff_loop(callback);
}