I am trying to send a SYN ACK packet back to the client when they sent a SYN packet. I have this code:
static inline void swap_mac_addresses(struct ethhdr *eth)
{
unsigned char tmp[ETH_ALEN];
memcpy(tmp, eth->h_source, ETH_ALEN);
memcpy(eth->h_source, eth->h_dest, ETH_ALEN);
memcpy(eth->h_dest, tmp, ETH_ALEN);
}
static inline void swap_ipv4_addresses(struct __sk_buff *skb, struct iphdr *iph)
{
uint32_t tmps = iph->saddr;
iph->saddr = iph->daddr;
iph->daddr = tmps;
iph->check = 0;
update_iph_checksum(iph);
}
unsigned short calculateChecksum(unsigned short *ptr, int nbytes) {
unsigned long sum;
unsigned short oddbyte;
unsigned short checksum;
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((unsigned char*)&oddbyte) = *(unsigned char*)ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
checksum = ~sum;
return checksum;
}
static inline void create_syn_ack_packet(struct __sk_buff *skb, struct ethhdr *eth, struct iphdr *iph, struct tcphdr *tcph)
{
swap_mac_addresses(eth);
swap_ipv4_addresses(skb, iph);
uint16_t old_sport = tcph->source;
uint16_t old_dport = tcph->dest;
tcph->syn = 1;
tcph->ack = 1;
tcph->ack_seq = htonl(ntohl(tcph->seq) + 1);
tcph->seq = 0;
tcph->dest = old_sport;
tcph->source = old_dport;
tcph->check = 0;
tcph->check = csum_diff4(old_sport, tcph->source, tcph->check);
tcph->check = csum_diff4(old_dport, tcph->dest, tcph->check);
}
The functions I use for the checksum are: https://github.com/gamemann/XDP-Forwarding/blob/7f11d69b1ec21b3670ee375339cdea43dd9144f1/src/csum.h
Why is my checksum invalid when sending the packet;
16:57:33.407099 eth0 In IP (tos 0x0, ttl 53, id 43174, offset 0, flags [DF], proto TCP (6), length 60)
x.x.x.x.51896 > x.x.x.x.24: Flags [S], cksum 0xa061 (correct), seq 2634206384, win 64860, options [mss 1380,sackOK,TS val 1124381365 ecr 0,nop,wscale 7], length 0
16:57:33.407190 eth0 Out IP (tos 0x0, ttl 52, id 43174, offset 0, flags [DF], proto TCP (6), length 60)
x.x.x.x.24 > x.x.x.x.51896: Flags [S.], cksum 0x0000 (incorrect -> 0xa050), seq 0, ack 2634206385, win 64860, options [mss 1380,sackOK,TS val 1124381365 ecr 0,nop,wscale 7], length 0
Thanks!