I am manipulating TCP packets using netfilter, so I have to recalculate the TCP and IP checksums which is working as expected.
Wireshark reports the checksums are correct on the way out of the server (which matches what the client thinks they should be as well), but when they reach the client the checksum is always replaced with 0xAA6A.
In the post routing hook, I am calculating the TCP checksum as follows... after manipulating the addresses/ports.
tcp_header->check = 0;
tcp_header->check = tcp_v4_check(tcp_len,
ip_header->saddr,
ip_header->daddr,
csum_partial((char *)tcp_header, tcp_len, 0));
The IP checksum is fine using
ip_send_check(ip_header);
The server does not have TCP offloading enabled for RX or TX and also does not even support it, I get an unsupported error when attempting to enable or disable.
Offload parameters for eth0:
rx-checksumming: off
tx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: off
tx-vlan-offload: off
ntuple-filters: off
receive-hashing: off
Another related point that I am not to sure on... I also manipulate packets/ports in a pre-routing hook on the server, and they are accepted by the transport layer and are definitely getting to my application no matter what I seem to do to the TCP checksum, I was under the assumption that they would be dropped if the TCP checksum wasn't updated after a change of IP Address/ and Port.
Is there any obvious reason for this behaviour or am I misunderstanding part of the network stack?
Update:
Setting ip_summed to CHECKSUM_NONE is stopping the checksum being recalculated once it leaves my code. What I'm not sure about is why it is being re-calculated to an incorrect fixed value? If I don't set it, it is set to CHECKSUM_PARTIAL.
If the value is always the same on the other side, I see 2 main possibilities: 1) you overwrite the checksum later after this code 2) tcp_len is wrong
You should also check if NETIF_F_V4_CSUM is set in the sockbuff dev->features because the kernel does something different in this case
Related
I'm working on a Win32 application and have noticed I am getting checksum issues in Wireshark (checking is not enabled by default). The IP header checksum is being set to 0 (this is not a massive issue but it would be preferable to sort it) and the UDP checksum is being set to the value that is expected for the IP header checksum.
I am not doing anything to set the IP header checksum since it is out of scope for my project, but I have tried the steps here (also for the UDP checksum) to disable checksum offloading but that has not made a difference. No idea how to get it to set a value for the IP header checksum.
Regarding the UDP checksum, something I think I can affect, I have been experimenting with setsockopt, mainly setsockopt(UdpSocket, SOL_SOCKET, UDP_CHECKSUM_COVERAGE, (const char*)&t, sizeof(t)), where t is a bool/DWORD set to true, and the setsockopts line is after socket() and bind(), before sendTo(). I have also tried changing SOL_SOCKET to IPPROTO_UDP. I know the socket is set up correctly since it has all been working fine before looking at the checksums. Does anyone know any other things I can try? I feel like I am out of options.
Thanks for any help you can give!
I am having raw socket server but when it respond to client I am getting following flags set
Reserved
Nonce
Congestion Window Reduced CWR
I believe it Nonce flag has to do with checksum. For tcp checksum I viewed from other sources that checksum
]does not include flags and some other fields and I am creating checksum on every field before calculating
checksum by just passing entire tcphdr pointer to memory to checksum function before checksum. If that's the
reason or any other reason of having these flags to be set to 1 then please explain
Also what these flags are for also please explain
I am sorry if the question is too naive, but I am confused. I want to send IPv6 jumbograms (to be able to multicast packets of size > 64 KB). I have been able to multicast normal IPv6 UDP packets successfully.
For sending jumbograms, from RFC 2675, I get that I have to make the following changes :
set payload length to 0
set next header to hop-by-hop
But, I don't get how to implement these in c socket programming (which function calls to make etc.). Do I have to create a custom header or are there functions like sendto available to send jumbograms?
You could use raw sockets if you are making your own headers. For more information, type man -s7 raw or look here. Note you will effectively need to implement your own IP stack that way.
However, my understanding is that linux itself supports IPv6 jumbograms natively so you don't need to bother. Try ifconfig lo mtu 100000 and do some tests over the loopback device to check.
I suspect the issue might be that your network adaptor and everything on the path (end to end) needs to support the jumbograms too.
I'm trying to dissect certain protocol that runs on top of TCP. The messages are sometimes split into different packets - unfortunately I do not have a way of determining the expected length of the message (protocol does not announce this). The only way to determine that the message transmission is complete is to wait for a TCP/IP packet with FIN,ACK flags set.
The issue is that my dissector is not even aware of TCP/IP protocol (nor it should in concern itself with it in reality). Is there any way to reassemble all packets until FIN,ACK is seen?
So the entire TCP connection contains only a single message? You can specify DESEGMENT_UNTIL_FIN in pinfo->desegment_len. See epan/packet_info.h for details.
I have a divert socket. I am trying to change the port on packets as I see them. When I do this - do I need to recalculate the TCP checksum, and the IP checksum?
I am trying to do this, but I am seeing reset packets in tcpdump. I dont know if this is because I am calculating the tcp checksum wrong, or if its something else going on.
I used the cksum methods from this site:
http://www.enderunix.org/docs/en/rawipspoof/
I thought with using a divert socket, if I change one thing, it should be fairly straightforward, but doesnt seem to be. is there a TCP checksum calculator out there I can use to verify I am getting the right value?
You do need to recompute the checksum. Here is a description of the calculation: TCP/IP Checksum calculation
See Section 3.3 of RFC 1631 for the checksum adjustments that a NAT/PAT must make. You don't have to go through the entire packet, you just need to adjust the checksum based on the bytes that you modify.