Re: Fwd: Modifying TCP packets with libnetfilter_queue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



MLm> Hi,
MLm> I am attempting to adjust contents of tcp packets using the nf queue
MLm> system, the queue part is working as I expected, however I am running
MLm> into problems recalculating the tcp checksum. At the moment, the
MLm> packet isnt being changed, and I am simply reading the checksum, then
MLm> trying to regenerate it, these values arent matching and I am at a
MLm> loss as to where I am going wrong.
MLm> Any help or suggestions please? I am at a loss

Try this code stolen from tcpdump and other cool stuff.

/*
 * IP header checksum.
 * don't modifiy the packet.
 */
u_short
in_cksum(const u_short *addr, register u_int len, int csum)
{
        int nleft = len;
        const u_short *w = addr;
        u_short answer;
        int sum = csum;

        /*
         *  Our algorithm is simple, using a 32 bit accumulator (sum),
         *  we add sequential 16 bit words to it, and at the end, fold
         *  back all the carry bits from the top 16 bits into the lower
         *  16 bits.
         */
        while (nleft > 1)  {
                sum += *w++;
                nleft -= 2;
        }
        if (nleft == 1)
                sum += htons(*(u_char *)w<<8);

        /*
         * add back carry outs from top 16 bits to low 16 bits
         */
        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;                          /* truncate to 16 bits */
        return (answer);
}

static int tcp_cksum(register const struct ip *ip,
                     register const struct tcphdr *tp,
                     register u_int len)
{
        union phu {
                struct phdr {
                        u_int32_t src;
                        u_int32_t dst;
                        u_char mbz;
                        u_char proto;
                        u_int16_t len;
                } ph;
                u_int16_t pa[6];
        } phu;
        const u_int16_t *sp;

        /* pseudo-header.. */
        phu.ph.len = htons((u_int16_t)len);
        phu.ph.mbz = 0;
        phu.ph.proto = IPPROTO_TCP;
        memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
        if ( (ip->ip_hl & 0x0f) == 5)
                memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
        else
                phu.ph.dst = ip_finddst(ip);

        sp = &phu.pa[0];
        return in_cksum((u_short *)tp, len,
                        sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
}


void recalculate_tcp_checksum(unsigned char *packet)
{
    struct ip *ip_packet = NULL;
    struct tcphdr *tcp_packet = NULL;
    u_int16_t word16, padd = 0, i, sum = 0, tcp_len;
    unsigned char *buff;
    if (!packet) return;

    ip_packet = (struct ip *)packet;
    tcp_packet = (struct tcphdr *)(packet + (ip_packet->ip_hl << 2));
    tcp_len = ntohs(ip_packet->ip_len) - (ip_packet->ip_hl << 2);

    sum = tcp_cksum(ip_packet,tcp_packet,tcp_len);
    tcp_packet->check = sum; //ntohs(sum);
}


Use recalculate_tcp_checksum() on your modified payload in this way:


    void *packet;
    struct ip *ip_packet = NULL;
    struct tcphdr *tcp_packet = NULL;
    unsigned char *tcp_packet_content = NULL;

.......
    ip_packet = ((struct ip *)packet);

    if (ip_packet->ip_p == IPPROTO_TCP) {
        tcp_packet = (struct tcphdr *)(packet + sizeof(struct ip));
        tcp_packet_content = (unsigned char *)(packet + sizeof(struct ip) + sizeof(struct tcphdr));
        tcp_packet_content_size = htons(ip_packet->ip_len) - sizeof(struct ip) - sizeof(struct tcphdr);
        .......
        // modify payload...
        .......
        // calculate
        tcp_packet->check = 0;
        recalculate_tcp_checksum(packet);
   }

You also can move some of this code to recalculate_tcp_checksum() and
simply call recalculate_tcp_checksum() without any payload preparations.
   
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Kuzin Andrey  -  kuzinandrey@xxxxxxxxx
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=



--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux