All of lore.kernel.org
 help / color / mirror / Atom feed
* Fwd: Modifying TCP packets with libnetfilter_queue
       [not found] <c97a47b90908262115l1dc29b78q7c02661b64af8cd9@mail.gmail.com>
@ 2009-08-27  4:16 ` Michael Lawson (mshindo)
  2009-08-27  5:34   ` Kuzin Andrey
  2009-08-28 19:53   ` Zhiyun Qian
  0 siblings, 2 replies; 9+ messages in thread
From: Michael Lawson (mshindo) @ 2009-08-27  4:16 UTC (permalink / raw)
  To: netfilter-devel

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

Here is the checksum code at the moment:
struct tcp_pseudo /*the tcp pseudo header*/
{
      __u32 src_addr;
      __u32 dst_addr;
      __u8 zero;
      __u8 proto;
      __u16 length;
}pseudohead;


long checksum(unsigned short *addr, unsigned int count) {
    register long sum = 0;
    while( count > 1 )  {
    /*  This is the inner loop */
        sum += * addr++;
        count -= 2;
    }

    /*  Add left-over byte, if any */
    if( count > 0 )
        sum += * (unsigned char *) addr;

    /*  Fold 32-bit sum to 16 bits */
    while (sum>>16)
        sum = (sum & 0xffff) + (sum >> 16);

    return ~sum;
}

long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
    mytcp->check = 0;

    u16 total_len = ntohs(myip->tot_len);
    int tcpopt_len = mytcp->doff*4 - 20;
    int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);

    /*Setup the pseudo header*/
    pseudohead.src_addr=myip->saddr;
    pseudohead.dst_addr=myip->daddr;
    pseudohead.zero=0;
    pseudohead.proto=IPPROTO_TCP;
    pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);

    /*Calc lengths*/
    int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct
tcphdr) + tcpopt_len + tcpdatalen;
    unsigned short * tcp = new unsigned short[totaltcp_len];

    /*Copy to required mem*/
    memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
    memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned
char *)mytcp,sizeof(struct tcphdr));

    if(tcpopt_len > 0)
        memcpy((unsigned char *)tcp+sizeof(struct
tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
*)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);

    if(tcpdatalen > 0)
        memcpy((unsigned char *)tcp+sizeof(struct
tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
*)mytcp+(mytcp->doff*4), tcpdatalen);

//            memcpy((unsigned char *)tcp+sizeof(struct
tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char
*)mytcp+(mytcp->doff*4), tcpdatalen);

    return checksum(tcp, totaltcp_len);
}

and the whole file, although not much bigger is here:
http://pastebin.com/m2bc636ed

An example of the output values I am getting at the moment is:
 packet size = 529 ip->checksum = 22679 tcp->checksum = 14964 new
ip->checksum = 22679 new tcp->checksum = 8007
 packet size = 52 ip->checksum = 13465 tcp->checksum = 8007 new
ip->checksum = 13465 new tcp->checksum = 31444
 packet size = 52 ip->checksum = 13209 tcp->checksum = 31444 new
ip->checksum = 13209 new tcp->checksum = 50105
 packet size = 52 ip->checksum = 12953 tcp->checksum = 50105 new
ip->checksum = 12953 new tcp->checksum = 12783

Any help or suggestions please? I am at a loss

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: Modifying TCP packets with libnetfilter_queue
  2009-08-27  4:16 ` Fwd: Modifying TCP packets with libnetfilter_queue Michael Lawson (mshindo)
@ 2009-08-27  5:34   ` Kuzin Andrey
       [not found]     ` <c97a47b90908271909l5849517bp729022d4cdd7cb6f@mail.gmail.com>
  2009-08-28 19:53   ` Zhiyun Qian
  1 sibling, 1 reply; 9+ messages in thread
From: Kuzin Andrey @ 2009-08-27  5:34 UTC (permalink / raw)
  To: Michael Lawson (mshindo); +Cc: netfilter-devel

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@yandex.ru
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Fwd: Modifying TCP packets with libnetfilter_queue
       [not found]     ` <c97a47b90908271909l5849517bp729022d4cdd7cb6f@mail.gmail.com>
@ 2009-08-28  2:09       ` Michael Lawson (mshindo)
  2009-08-28 11:26         ` Bruno Moreira Guedes
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Lawson (mshindo) @ 2009-08-28  2:09 UTC (permalink / raw)
  To: netfilter-devel

Thanks for the pointers, am still having problems sadly.

Does it matter where I intercept the packets? As a dev system, I have
been using a rule like: iptables -t filter -I OUTPUT -s ipaddress -j
QUEUE

This rule certainly picks up the packets, interestingly enough the
checksum is equal to zero, which according to the rfc is correct, this
I think is where my problem is coming from. Should I be queuing direct
from the wire? am wondering if the linux tcp/ip stack is playing games
with me ^_^

On Thu, Aug 27, 2009 at 5:34 PM, Kuzin Andrey<kuzinandrey@yandex.ru> wrote:
> 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@yandex.ru
> =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
>
>
>



--
Michael Lawson (mshindo)



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Modifying TCP packets with libnetfilter_queue
  2009-08-28  2:09       ` Michael Lawson (mshindo)
@ 2009-08-28 11:26         ` Bruno Moreira Guedes
  0 siblings, 0 replies; 9+ messages in thread
From: Bruno Moreira Guedes @ 2009-08-28 11:26 UTC (permalink / raw)
  To: netfilter-devel

2009/8/27 Michael Lawson (mshindo) <michael@sphinix.com>
>
> Thanks for the pointers, am still having problems sadly.
>
> Does it matter where I intercept the packets? As a dev system, I have
> been using a rule like: iptables -t filter -I OUTPUT -s ipaddress -j
> QUEUE

If you're using libnetfilter_queue, you'll need to use NFQUEUE target
instead of QUEUE.  And remember, tcpdump is your best friend.
>
> This rule certainly picks up the packets, interestingly enough the
> checksum is equal to zero, which according to the rfc is correct, this
> I think is where my problem is coming from. Should I be queuing direct
> from the wire? am wondering if the linux tcp/ip stack is playing games
> with me ^_^
>
> On Thu, Aug 27, 2009 at 5:34 PM, Kuzin Andrey<kuzinandrey@yandex.ru> wrote:
> > 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@yandex.ru
> > =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> >
> >
> >
> >
>
>
>
> --
> Michael Lawson (mshindo)
>
>
>
> --
> Michael Lawson (mshindo)
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: Modifying TCP packets with libnetfilter_queue
  2009-08-27  4:16 ` Fwd: Modifying TCP packets with libnetfilter_queue Michael Lawson (mshindo)
  2009-08-27  5:34   ` Kuzin Andrey
@ 2009-08-28 19:53   ` Zhiyun Qian
  2009-08-28 20:51     ` Bruno Moreira Guedes
  2009-08-28 22:48     ` Michael Lawson (mshindo)
  1 sibling, 2 replies; 9+ messages in thread
From: Zhiyun Qian @ 2009-08-28 19:53 UTC (permalink / raw)
  To: 'Michael Lawson (mshindo)', netfilter-devel

Have you solved your problem? I've run into the same problem before and then even if I successfully set the TCP checksum. The packet cannot be delivered. 

More specifically, I can queue the packets as expected but after I rewrite the packet and generate the correct checksum at both IP and TCP header, and when I try re-injecting the packets into the network, it just never get sent out according to TCPDUMP. I've posted my question here before but no one answers... I am guess you might also encounter the same problem. If you can let me know if you have made any progress, that'll be great.

-Zhiyun
-----邮件原件-----
发件人: netfilter-devel-owner@vger.kernel.org [mailto:netfilter-devel-owner@vger.kernel.org] 代表 Michael Lawson (mshindo)
发送时间: Thursday, August 27, 2009 12:17 AM
收件人: netfilter-devel@vger.kernel.org
主题: Fwd: Modifying TCP packets with libnetfilter_queue

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

Here is the checksum code at the moment:
struct tcp_pseudo /*the tcp pseudo header*/
{
      __u32 src_addr;
      __u32 dst_addr;
      __u8 zero;
      __u8 proto;
      __u16 length;
}pseudohead;


long checksum(unsigned short *addr, unsigned int count) {
    register long sum = 0;
    while( count > 1 )  {
    /*  This is the inner loop */
        sum += * addr++;
        count -= 2;
    }

    /*  Add left-over byte, if any */
    if( count > 0 )
        sum += * (unsigned char *) addr;

    /*  Fold 32-bit sum to 16 bits */
    while (sum>>16)
        sum = (sum & 0xffff) + (sum >> 16);

    return ~sum;
}

long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
    mytcp->check = 0;

    u16 total_len = ntohs(myip->tot_len);
    int tcpopt_len = mytcp->doff*4 - 20;
    int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);

    /*Setup the pseudo header*/
    pseudohead.src_addr=myip->saddr;
    pseudohead.dst_addr=myip->daddr;
    pseudohead.zero=0;
    pseudohead.proto=IPPROTO_TCP;
    pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);

    /*Calc lengths*/
    int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct
tcphdr) + tcpopt_len + tcpdatalen;
    unsigned short * tcp = new unsigned short[totaltcp_len];

    /*Copy to required mem*/
    memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
    memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned
char *)mytcp,sizeof(struct tcphdr));

    if(tcpopt_len > 0)
        memcpy((unsigned char *)tcp+sizeof(struct
tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
*)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);

    if(tcpdatalen > 0)
        memcpy((unsigned char *)tcp+sizeof(struct
tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
*)mytcp+(mytcp->doff*4), tcpdatalen);

//            memcpy((unsigned char *)tcp+sizeof(struct
tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char
*)mytcp+(mytcp->doff*4), tcpdatalen);

    return checksum(tcp, totaltcp_len);
}

and the whole file, although not much bigger is here:
http://pastebin.com/m2bc636ed

An example of the output values I am getting at the moment is:
 packet size = 529 ip->checksum = 22679 tcp->checksum = 14964 new
ip->checksum = 22679 new tcp->checksum = 8007
 packet size = 52 ip->checksum = 13465 tcp->checksum = 8007 new
ip->checksum = 13465 new tcp->checksum = 31444
 packet size = 52 ip->checksum = 13209 tcp->checksum = 31444 new
ip->checksum = 13209 new tcp->checksum = 50105
 packet size = 52 ip->checksum = 12953 tcp->checksum = 50105 new
ip->checksum = 12953 new tcp->checksum = 12783

Any help or suggestions please? I am at a loss

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



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Modifying TCP packets with libnetfilter_queue
  2009-08-28 19:53   ` Zhiyun Qian
@ 2009-08-28 20:51     ` Bruno Moreira Guedes
  2009-08-28 22:48     ` Michael Lawson (mshindo)
  1 sibling, 0 replies; 9+ messages in thread
From: Bruno Moreira Guedes @ 2009-08-28 20:51 UTC (permalink / raw)
  To: Zhiyun Qian; +Cc: Michael Lawson (mshindo), netfilter-devel

2009/8/28 Zhiyun Qian <zhiyunq@umich.edu>:
> Have you solved your problem? I've run into the same problem before and then even if I successfully set the TCP checksum. The packet cannot be delivered.
>
> More specifically, I can queue the packets as expected but after I rewrite the packet and generate the correct checksum at both IP and TCP header, and when I try re-injecting the packets into the network, it just never get sent out according to TCPDUMP. I've posted my question here before but no one answers... I am guess you might also encounter the same problem. If you can let me know if you have made any progress, that'll be great.

I had the same problem in the past. So it was because I was changing
source/destination information. If you want to do it take a look at
libnetfilter_conntrack. But I don't have ever make it works fine for
me. I don't know why but the connection gets too slow when I do
SNAT/DNAT with libnetfilter_conntrack.

>
> -Zhiyun
> -----邮件原件-----
> 发件人: netfilter-devel-owner@vger.kernel.org [mailto:netfilter-devel-owner@vger.kernel.org] 代表 Michael Lawson (mshindo)
> 发送时间: Thursday, August 27, 2009 12:17 AM
> 收件人: netfilter-devel@vger.kernel.org
> 主题: Fwd: Modifying TCP packets with libnetfilter_queue
>
> Hi,
> I am attempting to adjust contents of tcp packets using the nf queue
> system, the queue part is working as I expected, however I am running
> into problems recalculating the tcp checksum. At the moment, the
> packet isnt being changed, and I am simply reading the checksum, then
> trying to regenerate it, these values arent matching and I am at a
> loss as to where I am going wrong.
>
> Here is the checksum code at the moment:
> struct tcp_pseudo /*the tcp pseudo header*/
> {
>      __u32 src_addr;
>      __u32 dst_addr;
>      __u8 zero;
>      __u8 proto;
>      __u16 length;
> }pseudohead;
>
>
> long checksum(unsigned short *addr, unsigned int count) {
>    register long sum = 0;
>    while( count > 1 )  {
>    /*  This is the inner loop */
>        sum += * addr++;
>        count -= 2;
>    }
>
>    /*  Add left-over byte, if any */
>    if( count > 0 )
>        sum += * (unsigned char *) addr;
>
>    /*  Fold 32-bit sum to 16 bits */
>    while (sum>>16)
>        sum = (sum & 0xffff) + (sum >> 16);
>
>    return ~sum;
> }
>
> long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
>    mytcp->check = 0;
>
>    u16 total_len = ntohs(myip->tot_len);
>    int tcpopt_len = mytcp->doff*4 - 20;
>    int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
>
>    /*Setup the pseudo header*/
>    pseudohead.src_addr=myip->saddr;
>    pseudohead.dst_addr=myip->daddr;
>    pseudohead.zero=0;
>    pseudohead.proto=IPPROTO_TCP;
>    pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
>
>    /*Calc lengths*/
>    int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct
> tcphdr) + tcpopt_len + tcpdatalen;
>    unsigned short * tcp = new unsigned short[totaltcp_len];
>
>    /*Copy to required mem*/
>    memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
>    memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned
> char *)mytcp,sizeof(struct tcphdr));
>
>    if(tcpopt_len > 0)
>        memcpy((unsigned char *)tcp+sizeof(struct
> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
> *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
>
>    if(tcpdatalen > 0)
>        memcpy((unsigned char *)tcp+sizeof(struct
> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
> *)mytcp+(mytcp->doff*4), tcpdatalen);
>
> //            memcpy((unsigned char *)tcp+sizeof(struct
> tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char
> *)mytcp+(mytcp->doff*4), tcpdatalen);
>
>    return checksum(tcp, totaltcp_len);
> }
>
> and the whole file, although not much bigger is here:
> http://pastebin.com/m2bc636ed
>
> An example of the output values I am getting at the moment is:
>  packet size = 529 ip->checksum = 22679 tcp->checksum = 14964 new
> ip->checksum = 22679 new tcp->checksum = 8007
>  packet size = 52 ip->checksum = 13465 tcp->checksum = 8007 new
> ip->checksum = 13465 new tcp->checksum = 31444
>  packet size = 52 ip->checksum = 13209 tcp->checksum = 31444 new
> ip->checksum = 13209 new tcp->checksum = 50105
>  packet size = 52 ip->checksum = 12953 tcp->checksum = 50105 new
> ip->checksum = 12953 new tcp->checksum = 12783
>
> Any help or suggestions please? I am at a loss
>
> --
> Michael Lawson (mshindo)
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Modifying TCP packets with libnetfilter_queue
  2009-08-28 19:53   ` Zhiyun Qian
  2009-08-28 20:51     ` Bruno Moreira Guedes
@ 2009-08-28 22:48     ` Michael Lawson (mshindo)
  2009-09-07  2:52       ` Michael Lawson (mshindo)
  1 sibling, 1 reply; 9+ messages in thread
From: Michael Lawson (mshindo) @ 2009-08-28 22:48 UTC (permalink / raw)
  To: Zhiyun Qian; +Cc: netfilter-devel

I have made some form of progress late last night, basically a core
problem I found was in how I was getting struct tcphdr, once I fixed
this after a bit if fiddling round and some dirty string manipulation
I was able to match the checksums, so the packets get send out onto
the wire.

However this has led to another problem (perhaps the one you are
referring to) that ethereal picks up, but tcpdump does not. Under
SEQ/ACK Analysis, ethereal notes that the packets being transmitted
are duplicate ACK's. This might simply require some dirty hacks to
fix.

The code so far is on: http://pastebin.org/13016

Sadly, I have to jump a 5 hour train shortly, so not much work will be
done this afternoon.

Regards

On Sat, Aug 29, 2009 at 7:53 AM, Zhiyun Qian<zhiyunq@umich.edu> wrote:
> Have you solved your problem? I've run into the same problem before and then even if I successfully set the TCP checksum. The packet cannot be delivered.
>
> More specifically, I can queue the packets as expected but after I rewrite the packet and generate the correct checksum at both IP and TCP header, and when I try re-injecting the packets into the network, it just never get sent out according to TCPDUMP. I've posted my question here before but no one answers... I am guess you might also encounter the same problem. If you can let me know if you have made any progress, that'll be great.
>
> -Zhiyun
> -----邮件原件-----
> 发件人: netfilter-devel-owner@vger.kernel.org [mailto:netfilter-devel-owner@vger.kernel.org] 代表 Michael Lawson (mshindo)
> 发送时间: Thursday, August 27, 2009 12:17 AM
> 收件人: netfilter-devel@vger.kernel.org
> 主题: Fwd: Modifying TCP packets with libnetfilter_queue
>
> Hi,
> I am attempting to adjust contents of tcp packets using the nf queue
> system, the queue part is working as I expected, however I am running
> into problems recalculating the tcp checksum. At the moment, the
> packet isnt being changed, and I am simply reading the checksum, then
> trying to regenerate it, these values arent matching and I am at a
> loss as to where I am going wrong.
>
> Here is the checksum code at the moment:
> struct tcp_pseudo /*the tcp pseudo header*/
> {
>      __u32 src_addr;
>      __u32 dst_addr;
>      __u8 zero;
>      __u8 proto;
>      __u16 length;
> }pseudohead;
>
>
> long checksum(unsigned short *addr, unsigned int count) {
>    register long sum = 0;
>    while( count > 1 )  {
>    /*  This is the inner loop */
>        sum += * addr++;
>        count -= 2;
>    }
>
>    /*  Add left-over byte, if any */
>    if( count > 0 )
>        sum += * (unsigned char *) addr;
>
>    /*  Fold 32-bit sum to 16 bits */
>    while (sum>>16)
>        sum = (sum & 0xffff) + (sum >> 16);
>
>    return ~sum;
> }
>
> long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
>    mytcp->check = 0;
>
>    u16 total_len = ntohs(myip->tot_len);
>    int tcpopt_len = mytcp->doff*4 - 20;
>    int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
>
>    /*Setup the pseudo header*/
>    pseudohead.src_addr=myip->saddr;
>    pseudohead.dst_addr=myip->daddr;
>    pseudohead.zero=0;
>    pseudohead.proto=IPPROTO_TCP;
>    pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
>
>    /*Calc lengths*/
>    int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct
> tcphdr) + tcpopt_len + tcpdatalen;
>    unsigned short * tcp = new unsigned short[totaltcp_len];
>
>    /*Copy to required mem*/
>    memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
>    memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned
> char *)mytcp,sizeof(struct tcphdr));
>
>    if(tcpopt_len > 0)
>        memcpy((unsigned char *)tcp+sizeof(struct
> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
> *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
>
>    if(tcpdatalen > 0)
>        memcpy((unsigned char *)tcp+sizeof(struct
> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
> *)mytcp+(mytcp->doff*4), tcpdatalen);
>
> //            memcpy((unsigned char *)tcp+sizeof(struct
> tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char
> *)mytcp+(mytcp->doff*4), tcpdatalen);
>
>    return checksum(tcp, totaltcp_len);
> }
>
> and the whole file, although not much bigger is here:
> http://pastebin.com/m2bc636ed
>
> An example of the output values I am getting at the moment is:
>  packet size = 529 ip->checksum = 22679 tcp->checksum = 14964 new
> ip->checksum = 22679 new tcp->checksum = 8007
>  packet size = 52 ip->checksum = 13465 tcp->checksum = 8007 new
> ip->checksum = 13465 new tcp->checksum = 31444
>  packet size = 52 ip->checksum = 13209 tcp->checksum = 31444 new
> ip->checksum = 13209 new tcp->checksum = 50105
>  packet size = 52 ip->checksum = 12953 tcp->checksum = 50105 new
> ip->checksum = 12953 new tcp->checksum = 12783
>
> Any help or suggestions please? I am at a loss
>
> --
> Michael Lawson (mshindo)
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>
>



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Modifying TCP packets with libnetfilter_queue
  2009-08-28 22:48     ` Michael Lawson (mshindo)
@ 2009-09-07  2:52       ` Michael Lawson (mshindo)
  2009-09-07  4:45         ` Michael Lawson (mshindo)
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Lawson (mshindo) @ 2009-09-07  2:52 UTC (permalink / raw)
  To: Zhiyun Qian; +Cc: netfilter-devel

Still having problems modifying the packet destination, the packets
appear to be getting out onto the wire, however the host receiving
them sets the RST flag in the TCP payload, can anyone suggest a reason
as to why this might occur once I adjust the destination address?

Regards

On Sat, Aug 29, 2009 at 10:48 AM, Michael Lawson
(mshindo)<michael@sphinix.com> wrote:
> I have made some form of progress late last night, basically a core
> problem I found was in how I was getting struct tcphdr, once I fixed
> this after a bit if fiddling round and some dirty string manipulation
> I was able to match the checksums, so the packets get send out onto
> the wire.
>
> However this has led to another problem (perhaps the one you are
> referring to) that ethereal picks up, but tcpdump does not. Under
> SEQ/ACK Analysis, ethereal notes that the packets being transmitted
> are duplicate ACK's. This might simply require some dirty hacks to
> fix.
>
> The code so far is on: http://pastebin.org/13016
>
> Sadly, I have to jump a 5 hour train shortly, so not much work will be
> done this afternoon.
>
> Regards
>
> On Sat, Aug 29, 2009 at 7:53 AM, Zhiyun Qian<zhiyunq@umich.edu> wrote:
>> Have you solved your problem? I've run into the same problem before and then even if I successfully set the TCP checksum. The packet cannot be delivered.
>>
>> More specifically, I can queue the packets as expected but after I rewrite the packet and generate the correct checksum at both IP and TCP header, and when I try re-injecting the packets into the network, it just never get sent out according to TCPDUMP. I've posted my question here before but no one answers... I am guess you might also encounter the same problem. If you can let me know if you have made any progress, that'll be great.
>>
>> -Zhiyun
>> -----邮件原件-----
>> 发件人: netfilter-devel-owner@vger.kernel.org [mailto:netfilter-devel-owner@vger.kernel.org] 代表 Michael Lawson (mshindo)
>> 发送时间: Thursday, August 27, 2009 12:17 AM
>> 收件人: netfilter-devel@vger.kernel.org
>> 主题: Fwd: Modifying TCP packets with libnetfilter_queue
>>
>> Hi,
>> I am attempting to adjust contents of tcp packets using the nf queue
>> system, the queue part is working as I expected, however I am running
>> into problems recalculating the tcp checksum. At the moment, the
>> packet isnt being changed, and I am simply reading the checksum, then
>> trying to regenerate it, these values arent matching and I am at a
>> loss as to where I am going wrong.
>>
>> Here is the checksum code at the moment:
>> struct tcp_pseudo /*the tcp pseudo header*/
>> {
>>      __u32 src_addr;
>>      __u32 dst_addr;
>>      __u8 zero;
>>      __u8 proto;
>>      __u16 length;
>> }pseudohead;
>>
>>
>> long checksum(unsigned short *addr, unsigned int count) {
>>    register long sum = 0;
>>    while( count > 1 )  {
>>    /*  This is the inner loop */
>>        sum += * addr++;
>>        count -= 2;
>>    }
>>
>>    /*  Add left-over byte, if any */
>>    if( count > 0 )
>>        sum += * (unsigned char *) addr;
>>
>>    /*  Fold 32-bit sum to 16 bits */
>>    while (sum>>16)
>>        sum = (sum & 0xffff) + (sum >> 16);
>>
>>    return ~sum;
>> }
>>
>> long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
>>    mytcp->check = 0;
>>
>>    u16 total_len = ntohs(myip->tot_len);
>>    int tcpopt_len = mytcp->doff*4 - 20;
>>    int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
>>
>>    /*Setup the pseudo header*/
>>    pseudohead.src_addr=myip->saddr;
>>    pseudohead.dst_addr=myip->daddr;
>>    pseudohead.zero=0;
>>    pseudohead.proto=IPPROTO_TCP;
>>    pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
>>
>>    /*Calc lengths*/
>>    int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct
>> tcphdr) + tcpopt_len + tcpdatalen;
>>    unsigned short * tcp = new unsigned short[totaltcp_len];
>>
>>    /*Copy to required mem*/
>>    memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
>>    memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned
>> char *)mytcp,sizeof(struct tcphdr));
>>
>>    if(tcpopt_len > 0)
>>        memcpy((unsigned char *)tcp+sizeof(struct
>> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
>> *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
>>
>>    if(tcpdatalen > 0)
>>        memcpy((unsigned char *)tcp+sizeof(struct
>> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
>> *)mytcp+(mytcp->doff*4), tcpdatalen);
>>
>> //            memcpy((unsigned char *)tcp+sizeof(struct
>> tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char
>> *)mytcp+(mytcp->doff*4), tcpdatalen);
>>
>>    return checksum(tcp, totaltcp_len);
>> }
>>
>> and the whole file, although not much bigger is here:
>> http://pastebin.com/m2bc636ed
>>
>> An example of the output values I am getting at the moment is:
>>  packet size = 529 ip->checksum = 22679 tcp->checksum = 14964 new
>> ip->checksum = 22679 new tcp->checksum = 8007
>>  packet size = 52 ip->checksum = 13465 tcp->checksum = 8007 new
>> ip->checksum = 13465 new tcp->checksum = 31444
>>  packet size = 52 ip->checksum = 13209 tcp->checksum = 31444 new
>> ip->checksum = 13209 new tcp->checksum = 50105
>>  packet size = 52 ip->checksum = 12953 tcp->checksum = 50105 new
>> ip->checksum = 12953 new tcp->checksum = 12783
>>
>> Any help or suggestions please? I am at a loss
>>
>> --
>> Michael Lawson (mshindo)
>> --
>> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>>
>
>
>
> --
> Michael Lawson (mshindo)
>



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Modifying TCP packets with libnetfilter_queue
  2009-09-07  2:52       ` Michael Lawson (mshindo)
@ 2009-09-07  4:45         ` Michael Lawson (mshindo)
  0 siblings, 0 replies; 9+ messages in thread
From: Michael Lawson (mshindo) @ 2009-09-07  4:45 UTC (permalink / raw)
  To: netfilter-devel

This is a relative dump of the packet stream when filtered on wireshark

No.     Time        Source                Destination           Protocol Info
   1808 3010.627337 10.0.0.29             127.0.0.1             TCP
  42479 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=4597297 TSER=0
WS=6

Frame 1808 (76 bytes on wire, 76 bytes captured)
Linux cooked capture
Internet Protocol, Src: 10.0.0.29 (10.0.0.29), Dst: 127.0.0.1 (127.0.0.1)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
    Total Length: 60
    Identification: 0x5c7b (23675)
    Flags: 0x04 (Don't Fragment)
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (0x06)
    Header checksum: 0x5523 [correct]
    Source: 10.0.0.29 (10.0.0.29)
    Destination: 127.0.0.1 (127.0.0.1)
Transmission Control Protocol, Src Port: 42479 (42479), Dst Port: http
(80), Seq: 0, Len: 0
    Source port: 42479 (42479)
    Destination port: http (80)
    Sequence number: 0    (relative sequence number)
    Header length: 40 bytes
    Flags: 0x02 (SYN)
    Window size: 5840
    Checksum: 0x6a0f [correct]
    Options: (20 bytes)

No.     Time        Source                Destination           Protocol Info
   1809 3010.627381 127.0.0.1             10.0.0.29             TCP
  http > 42479 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=16396
TSV=4597297 TSER=4597297 WS=6

Frame 1809 (76 bytes on wire, 76 bytes captured)
Linux cooked capture
Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 10.0.0.29 (10.0.0.29)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
    Total Length: 60
    Identification: 0x0000 (0)
    Flags: 0x04 (Don't Fragment)
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (0x06)
    Header checksum: 0xb19e [correct]
    Source: 127.0.0.1 (127.0.0.1)
    Destination: 10.0.0.29 (10.0.0.29)
Transmission Control Protocol, Src Port: http (80), Dst Port: 42479
(42479), Seq: 0, Ack: 1, Len: 0
    Source port: http (80)
    Destination port: 42479 (42479)
    Sequence number: 0    (relative sequence number)
    Acknowledgement number: 1    (relative ack number)
    Header length: 40 bytes
    Flags: 0x12 (SYN, ACK)
    Window size: 32768
    Checksum: 0xf6d4 [correct]
    Options: (20 bytes)
    [SEQ/ACK analysis]

No.     Time        Source                Destination           Protocol Info
   1810 3010.627403 10.0.0.29             127.0.0.1             TCP
  42479 > http [RST] Seq=1 Win=0 Len=0

Frame 1810 (56 bytes on wire, 56 bytes captured)
Linux cooked capture
Internet Protocol, Src: 10.0.0.29 (10.0.0.29), Dst: 127.0.0.1 (127.0.0.1)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
    Total Length: 40
    Identification: 0x0000 (0)
    Flags: 0x04 (Don't Fragment)
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (0x06)
    Header checksum: 0xb1b2 [correct]
    Source: 10.0.0.29 (10.0.0.29)
    Destination: 127.0.0.1 (127.0.0.1)
Transmission Control Protocol, Src Port: 42479 (42479), Dst Port: http
(80), Seq: 1, Len: 0
    Source port: 42479 (42479)
    Destination port: http (80)
    Sequence number: 1    (relative sequence number)
    Header length: 20 bytes
    Flags: 0x04 (RST)
    Window size: 0
    Checksum: 0x0f35 [correct]

On Mon, Sep 7, 2009 at 2:52 PM, Michael Lawson
(mshindo)<michael@sphinix.com> wrote:
> Still having problems modifying the packet destination, the packets
> appear to be getting out onto the wire, however the host receiving
> them sets the RST flag in the TCP payload, can anyone suggest a reason
> as to why this might occur once I adjust the destination address?
>
> Regards
>
> On Sat, Aug 29, 2009 at 10:48 AM, Michael Lawson
> (mshindo)<michael@sphinix.com> wrote:
>> I have made some form of progress late last night, basically a core
>> problem I found was in how I was getting struct tcphdr, once I fixed
>> this after a bit if fiddling round and some dirty string manipulation
>> I was able to match the checksums, so the packets get send out onto
>> the wire.
>>
>> However this has led to another problem (perhaps the one you are
>> referring to) that ethereal picks up, but tcpdump does not. Under
>> SEQ/ACK Analysis, ethereal notes that the packets being transmitted
>> are duplicate ACK's. This might simply require some dirty hacks to
>> fix.
>>
>> The code so far is on: http://pastebin.org/13016
>>
>> Sadly, I have to jump a 5 hour train shortly, so not much work will be
>> done this afternoon.
>>
>> Regards
>>
>> On Sat, Aug 29, 2009 at 7:53 AM, Zhiyun Qian<zhiyunq@umich.edu> wrote:
>>> Have you solved your problem? I've run into the same problem before and then even if I successfully set the TCP checksum. The packet cannot be delivered.
>>>
>>> More specifically, I can queue the packets as expected but after I rewrite the packet and generate the correct checksum at both IP and TCP header, and when I try re-injecting the packets into the network, it just never get sent out according to TCPDUMP. I've posted my question here before but no one answers... I am guess you might also encounter the same problem. If you can let me know if you have made any progress, that'll be great.
>>>
>>> -Zhiyun
>>> -----邮件原件-----
>>> 发件人: netfilter-devel-owner@vger.kernel.org [mailto:netfilter-devel-owner@vger.kernel.org] 代表 Michael Lawson (mshindo)
>>> 发送时间: Thursday, August 27, 2009 12:17 AM
>>> 收件人: netfilter-devel@vger.kernel.org
>>> 主题: Fwd: Modifying TCP packets with libnetfilter_queue
>>>
>>> Hi,
>>> I am attempting to adjust contents of tcp packets using the nf queue
>>> system, the queue part is working as I expected, however I am running
>>> into problems recalculating the tcp checksum. At the moment, the
>>> packet isnt being changed, and I am simply reading the checksum, then
>>> trying to regenerate it, these values arent matching and I am at a
>>> loss as to where I am going wrong.
>>>
>>> Here is the checksum code at the moment:
>>> struct tcp_pseudo /*the tcp pseudo header*/
>>> {
>>>      __u32 src_addr;
>>>      __u32 dst_addr;
>>>      __u8 zero;
>>>      __u8 proto;
>>>      __u16 length;
>>> }pseudohead;
>>>
>>>
>>> long checksum(unsigned short *addr, unsigned int count) {
>>>    register long sum = 0;
>>>    while( count > 1 )  {
>>>    /*  This is the inner loop */
>>>        sum += * addr++;
>>>        count -= 2;
>>>    }
>>>
>>>    /*  Add left-over byte, if any */
>>>    if( count > 0 )
>>>        sum += * (unsigned char *) addr;
>>>
>>>    /*  Fold 32-bit sum to 16 bits */
>>>    while (sum>>16)
>>>        sum = (sum & 0xffff) + (sum >> 16);
>>>
>>>    return ~sum;
>>> }
>>>
>>> long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
>>>    mytcp->check = 0;
>>>
>>>    u16 total_len = ntohs(myip->tot_len);
>>>    int tcpopt_len = mytcp->doff*4 - 20;
>>>    int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
>>>
>>>    /*Setup the pseudo header*/
>>>    pseudohead.src_addr=myip->saddr;
>>>    pseudohead.dst_addr=myip->daddr;
>>>    pseudohead.zero=0;
>>>    pseudohead.proto=IPPROTO_TCP;
>>>    pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
>>>
>>>    /*Calc lengths*/
>>>    int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct
>>> tcphdr) + tcpopt_len + tcpdatalen;
>>>    unsigned short * tcp = new unsigned short[totaltcp_len];
>>>
>>>    /*Copy to required mem*/
>>>    memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
>>>    memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned
>>> char *)mytcp,sizeof(struct tcphdr));
>>>
>>>    if(tcpopt_len > 0)
>>>        memcpy((unsigned char *)tcp+sizeof(struct
>>> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
>>> *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
>>>
>>>    if(tcpdatalen > 0)
>>>        memcpy((unsigned char *)tcp+sizeof(struct
>>> tcp_pseudo)+sizeof(struct tcphdr), (unsigned char
>>> *)mytcp+(mytcp->doff*4), tcpdatalen);
>>>
>>> //            memcpy((unsigned char *)tcp+sizeof(struct
>>> tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char
>>> *)mytcp+(mytcp->doff*4), tcpdatalen);
>>>
>>>    return checksum(tcp, totaltcp_len);
>>> }
>>>
>>> and the whole file, although not much bigger is here:
>>> http://pastebin.com/m2bc636ed
>>>
>>> An example of the output values I am getting at the moment is:
>>>  packet size = 529 ip->checksum = 22679 tcp->checksum = 14964 new
>>> ip->checksum = 22679 new tcp->checksum = 8007
>>>  packet size = 52 ip->checksum = 13465 tcp->checksum = 8007 new
>>> ip->checksum = 13465 new tcp->checksum = 31444
>>>  packet size = 52 ip->checksum = 13209 tcp->checksum = 31444 new
>>> ip->checksum = 13209 new tcp->checksum = 50105
>>>  packet size = 52 ip->checksum = 12953 tcp->checksum = 50105 new
>>> ip->checksum = 12953 new tcp->checksum = 12783
>>>
>>> Any help or suggestions please? I am at a loss
>>>
>>> --
>>> Michael Lawson (mshindo)
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>>
>>>
>>
>>
>>
>> --
>> Michael Lawson (mshindo)
>>
>
>
>
> --
> Michael Lawson (mshindo)
>



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-09-07  4:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <c97a47b90908262115l1dc29b78q7c02661b64af8cd9@mail.gmail.com>
2009-08-27  4:16 ` Fwd: Modifying TCP packets with libnetfilter_queue Michael Lawson (mshindo)
2009-08-27  5:34   ` Kuzin Andrey
     [not found]     ` <c97a47b90908271909l5849517bp729022d4cdd7cb6f@mail.gmail.com>
2009-08-28  2:09       ` Michael Lawson (mshindo)
2009-08-28 11:26         ` Bruno Moreira Guedes
2009-08-28 19:53   ` Zhiyun Qian
2009-08-28 20:51     ` Bruno Moreira Guedes
2009-08-28 22:48     ` Michael Lawson (mshindo)
2009-09-07  2:52       ` Michael Lawson (mshindo)
2009-09-07  4:45         ` Michael Lawson (mshindo)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.