0

I am working on a network application where I send and receive TCP packets. However, I’m encountering an issue where the data received does not match the data sent. I’m using raw sockets and constructing the packet manually, and I suspect there might be an issue with either the packet construction or the reception process.

Here’s what I send:

45 00 00 35 00 00 00 00 FF 06 3C C2 00 00 00 00 7F 00 00 01 31 D4 39 30 29 00 00 00 00 00 00 00 50 18 FF FF A5 71 00 00 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21

And here’s what I receive:

45 00 00 3C F8 A9 00 00 80 FF 00 00 7F 00 00 01 7F 00 00 01 45 00 00 28 00 00 00 00 FF 06 BD CD 7F 00 00 01 7F 00 00 01 31 D4 39 30 29 00 00 00 00 00 00 2A 50 12 FF FF 1B BF 00 00

Problem:

  • The received packet does not match the sent packet. Specifically

  • The IP header length (45 00 00 ...) differs.

  • The TCP header length and flags seem inconsistent.

  • The payload data (which should be "Hello, World!") is different.

Steps Taken:

Packet Construction: I am manually constructing the IP and TCP headers, setting fields such as source and destination IP addresses, ports, sequence numbers, etc.

Checksum Calculation: I compute the checksums for both IP and TCP headers, but the received packet data does not align with what is expected. Packet Reception: I use recv to receive the packet data. Questions:

What might cause the discrepancy between the sent and received packet data? Are there any common issues with packet construction or reception that could lead to such differences?

How can I debug this issue effectively to ensure that the packet sent matches what is received?

receiver code :

recv_len = receive_packet(sock, packet);
if (recv_len < 0) {
    std::cerr << "Failed to receive packet: " << WSAGetLastError() << std::endl;
    return false;
}

// Output for debugging
std::cout << "Raw packet data (hex): ";
for (int i = 0; i < recv_len; ++i) {
    printf("%02X ", static_cast<unsigned char>(packet[i]));
}

sender code:

// Create the data packet
create_data_packet(saddr, daddr, seq, ack, data, data_len, packet, packet_len);

// Send the data packet to the destination address
if (sendto(sock, packet.get(), packet_len, 0, reinterpret_cast<sockaddr*>(&daddr), sizeof(daddr)) == SOCKET_ERROR) {
    std::cerr << "Failed to send data packet: " << WSAGetLastError() << std::endl;
    closesocket(sock); // Close the socket before exiting
    WSACleanup();      // Clean up Winsock before exiting
    return 1; // Exit with an error code if sending the packet fails
}
std::cout << "Data packet sent successfully." << std::endl;

I manually constructed and sent a TCP packet using raw sockets. The packet included both IP and TCP headers, as well as a payload. I computed and set the checksums for both the IP and TCP headers correctly. After sending the packet, I attempted to receive the same packet on the other end using raw sockets as well.

What I Expected:

I expected that the received packet would exactly match the sent packet, including the headers and payload. Specifically, the IP and TCP headers should align with what was sent, and the payload should be identical to what was transmitted.

4
  • 1
    "How can I debug this issue effectively ..." - do a packet capture so that you compare the packet on the wire with what you've send and received. This way you can narrow down if the problem is in your client side or server side code. If there are middleboxes (like firewalls) in between do a packet capture both at the sender and receiver and to ensure that data did not get changed in the middlebox. Commented Aug 24, 2024 at 14:31
  • Apart from that the TCP checksum in the generated packet seem to be incorrect. Commented Aug 24, 2024 at 14:43
  • "The IP header length (45 00 00 ...) differs." No, the IP Header Length value, 5 (five 32-bit words, or 20 octets), is exactly the same in both the sent and received IP Packets. Commented Aug 24, 2024 at 19:51
  • "I’m using raw sockets and constructing the packet manually" - why? What's wrong with letting the OS handle that for you? What are you doing manually that the OS can't do for you? Commented Aug 25, 2024 at 5:18

1 Answer 1

-1

Sorry... but you shouldn't be analyzing the packet like that.

If the ~data is not correct, you need to explain where you see a failure by decapsulating the raw data one layer at a time.

And you need to do all the work for each layer by hand. If you don't have code that does this, you should at least leverage an available networking API to compare.

For example, if your packet could be fragmented in transit. That ensures that the raw data would look very different. (One packet becoming two packets can have that effect :) ... ) but inside it, proper handling and reassembly would deliver the correct data-stream.

Sign up to request clarification or add additional context in comments.

1 Comment

Since I'm already commenting, and example fast(er) ethernet-based IP routers that used "cut-thru" packet routing. Basically, they just assumed ethernet and IP header lengths were fixed, and then would immediately start composing the encapsulation of the forwarded packet header, and dump the next byte of the inbound datagram into the outbound datagram... Which would work, until it didn't work. But, hey! At least when it passed the wrong info into the packets, it did so at an extremely performant rate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.