From: "Michael Lawson (mshindo)" <michael@sphinix.com>
To: netfilter-devel@vger.kernel.org
Subject: Fwd: Modifying TCP packets with libnetfilter_queue
Date: Fri, 28 Aug 2009 14:09:46 +1200 [thread overview]
Message-ID: <c97a47b90908271909s74161405ib542aa1080a9c833@mail.gmail.com> (raw)
In-Reply-To: <c97a47b90908271909l5849517bp729022d4cdd7cb6f@mail.gmail.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
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
next prev parent reply other threads:[~2009-08-28 2:10 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[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) [this message]
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)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c97a47b90908271909s74161405ib542aa1080a9c833@mail.gmail.com \
--to=michael@sphinix.com \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).