Reputation: 179
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.
Upvotes: 1
Views: 2324
Reputation: 2054
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
Upvotes: 1