0

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!

Fabian
  • 24
  • 4
  • I don't know why your checksum is 0 or how to use the functions in csum.h, but I do know that the checksum is computed over the TCP "pseudo header" rather than the actual TCP header. Maybe try csum_tcpudp_magic. – JimD. May 17 '23 at 02:53
  • Here is how the linux tcp stack uses them: https://elixir.bootlin.com/linux/v4.0/source/net/ipv4/tcp_ipv4.c#L540 https://elixir.bootlin.com/linux/v4.0/source/include/net/tcp.h#L1064 – JimD. May 17 '23 at 03:01

0 Answers0