netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Recalculate checksums in netfilter queue
@ 2010-04-21  1:02 Justin Yaple
  2010-04-21  2:02 ` Bruno Moreira Guedes
  0 siblings, 1 reply; 7+ messages in thread
From: Justin Yaple @ 2010-04-21  1:02 UTC (permalink / raw)
  To: netfilter-devel

Hello,

I am having some trouble figuring out how to re-calculate the tcp/ip
checksums after pulling a packet into user space with
libnetfilter_queue.  In a netfilter hook I was able to use this:
tcph->check = 0;
tcph->check = tcp_v4_check(tcph, tcplen,
	iph->saddr,
	iph->daddr,
	csum_partial((char *)tcph, tcplen, 0));
	iph->check = 0;
	ip_send_check(iph); //ip checksum

In user space these functions tcp_v4_check(), csum_partial() and
ip_send_check() do not exists.  Are there equivalent functions in user
space so I can recalculate the ip/tcp checksums before passing the new
packet back to the kernel with nfq_set_verdict()?

Thanks.

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

* Re: Recalculate checksums in netfilter queue
  2010-04-21  1:02 Recalculate checksums in netfilter queue Justin Yaple
@ 2010-04-21  2:02 ` Bruno Moreira Guedes
  2010-04-22  3:15   ` Justin Yaple
  0 siblings, 1 reply; 7+ messages in thread
From: Bruno Moreira Guedes @ 2010-04-21  2:02 UTC (permalink / raw)
  To: Justin Yaple; +Cc: netfilter-devel

2010/4/20 Justin Yaple <yaplej@gmail.com>:
> Hello,
>
> I am having some trouble figuring out how to re-calculate the tcp/ip
> checksums after pulling a packet into user space with
> libnetfilter_queue.  In a netfilter hook I was able to use this:
> tcph->check = 0;
> tcph->check = tcp_v4_check(tcph, tcplen,
>        iph->saddr,
>        iph->daddr,
>        csum_partial((char *)tcph, tcplen, 0));
>        iph->check = 0;
>        ip_send_check(iph); //ip checksum
>
> In user space these functions tcp_v4_check(), csum_partial() and
> ip_send_check() do not exists.  Are there equivalent functions in user
> space so I can recalculate the ip/tcp checksums before passing the new
> packet back to the kernel with nfq_set_verdict()?
>
> Thanks.
> --
> 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
>

Hello Justin!

If you solve this problem, I'll be too grateful, because I'm looking
for a solution since the last year in order to do NAT in userspace.
Good luck.
--
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] 7+ messages in thread

* Re: Recalculate checksums in netfilter queue
  2010-04-21  2:02 ` Bruno Moreira Guedes
@ 2010-04-22  3:15   ` Justin Yaple
  2010-04-22 12:43     ` Morgon.J.Kanter
  2010-04-22 19:37     ` James King
  0 siblings, 2 replies; 7+ messages in thread
From: Justin Yaple @ 2010-04-22  3:15 UTC (permalink / raw)
  Cc: netfilter-devel

> If you solve this problem, I'll be too grateful, because I'm looking
> for a solution since the last year in order to do NAT in userspace.
> Good luck.


If I get it figured out I will let you know.  Im kind of supprised
that there isnt a function for this in libnetfilter_queue already.  It
seems like it would be a pretty common requirement to recalculate the
tcp, and ip checksums.  I have spent two days trying to get something
to work without much luck.

My understanding is that the one complement of each 16-bit word is
summed, and then the result of that is bitwise complemented.

So for each word we would do something like this.
for each word{
     sum += ~word;
}

then you would take the bitwise complement of that total.
sum = ~sum;

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

* Re: Recalculate checksums in netfilter queue
  2010-04-22  3:15   ` Justin Yaple
@ 2010-04-22 12:43     ` Morgon.J.Kanter
  2010-04-22 20:19       ` Justin Yaple
  2010-04-22 19:37     ` James King
  1 sibling, 1 reply; 7+ messages in thread
From: Morgon.J.Kanter @ 2010-04-22 12:43 UTC (permalink / raw)
  To: Justin Yaple; +Cc: netfilter-devel


  My understanding is that the one complement of each 16-bit word is
> summed, and then the result of that is bitwise complemented.
>
> So for each word we would do something like this.
> for each word{
>      sum += ~word;
> }
>
> then you would take the bitwise complement of that total.
> sum = ~sum;

The RFC for IP contains C code that you can literally copy and paste  
for this task.

-- Morgon

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

* Re: Recalculate checksums in netfilter queue
  2010-04-22  3:15   ` Justin Yaple
  2010-04-22 12:43     ` Morgon.J.Kanter
@ 2010-04-22 19:37     ` James King
  1 sibling, 0 replies; 7+ messages in thread
From: James King @ 2010-04-22 19:37 UTC (permalink / raw)
  To: Justin Yaple; +Cc: netfilter-devel

On Wed, Apr 21, 2010 at 8:15 PM, Justin Yaple <yaplej@gmail.com> wrote:
> If I get it figured out I will let you know.  Im kind of supprised
> that there isnt a function for this in libnetfilter_queue already.  It
> seems like it would be a pretty common requirement to recalculate the
> tcp, and ip checksums.  I have spent two days trying to get something
> to work without much luck.
>
> My understanding is that the one complement of each 16-bit word is
> summed, and then the result of that is bitwise complemented.
>
> So for each word we would do something like this.
> for each word{
>     sum += ~word;
> }
>
> then you would take the bitwise complement of that total.
> sum = ~sum;

For TCP, it's a bit more complicated, as you need to construct an IP
pseudo header first, calculate the checksum for the pseudo header +
segment containing a zeroed checksum field, and then finally insert
the checksum into the TCP header [1].  You also have to pad the
segment into an even number of octets before doing the calculation,
but not include this padding in the transmitted segment [2].  You may
also need to recalculate the IP checksum, depending on what fields
you're modifying.  The process is also slightly different for TCP over
IPv6.

I found a thread on this list from last year that contains some helper
functions extracted from tcpdump that may help you, titled "Re: Fwd:
Modifying TCP packets with libnetfilter_queue" [3].

If this works for you, perhaps a patch to include them in
libnetfilter_queue is in order.

[1] http://www.tcpipguide.com/free/t_TCPChecksumCalculationandtheTCPPseudoHeader-2.htm
[2] http://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_checksum_for_IPv4
[3] http://markmail.org/message/auqvblfqenhy4hlz


HTH,
James
--
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] 7+ messages in thread

* Re: Recalculate checksums in netfilter queue
  2010-04-22 12:43     ` Morgon.J.Kanter
@ 2010-04-22 20:19       ` Justin Yaple
       [not found]         ` <z2o3fdd6ce01004221432yec6c907bz4124144d403be1b4@mail.gmail.com>
  0 siblings, 1 reply; 7+ messages in thread
From: Justin Yaple @ 2010-04-22 20:19 UTC (permalink / raw)
  To: Morgon.J.Kanter; +Cc: netfilter-devel

> The RFC for IP contains C code that you can literally copy and paste for
> this task.
>
> -- Morgon

Thanks.  I finally have both my tcp checksum, and ip checksum
functions working.  I found where I was doing some calculations in
reverse order than the example given in the RFC.  Would there be any
reason not to add checksum functions to libnetfilter_queue?

unsigned short tcp_sum_calc(unsigned short len_tcp, unsigned short
*src_addr, unsigned short *dest_addr, unsigned short *buff)
{
	unsigned short prot_tcp = 6;
	long sum = 0;
	int i = 0;
	
	/* Check if the tcp length is even or odd.  Add padding if odd. */
	if((len_tcp % 2) == 1){
		buff[len_tcp] = 0;  // Empty space in the ip buffer should be 0 anyway.
      	len_tcp += 1; // increase length to make even.
	}
	
	/* add the pseudo header */	
	sum += ntohs(src_addr[0]);
	sum += ntohs(src_addr[1]);
	sum += ntohs(dest_addr[0]);
	sum += ntohs(dest_addr[1]);
	sum += len_tcp; // already in host format.
	sum += prot_tcp; // already in host format.

	/*
	 * calculate the checksum for the tcp header and payload
	 * len_tcp represents number of 8-bit bytes,
	 * we are working with 16-bit words so divide len_tcp by 2.
	 */
	for(i=0;i<(len_tcp/2);i++){
		sum += ntohs(buff[i]);
	}

	// keep only the last 16 bits of the 32 bit calculated sum and add the carries
	while (sum >> 16){
		sum = (sum & 0xFFFF) + (sum >> 16);
	}
	
	// Take the bitwise complement of sum
	sum = ~sum;

	return htons(((unsigned short) sum));
}

unsigned short ip_sum_calc(unsigned short len_ip_header, unsigned short *buff){
	long sum = 0;
	int i = 0;
	
	for (i=0;i<len_ip_header/2;i++){
		sum += ntohs(buff[i]);
	}
	
	while (sum >> 16){
		sum = (sum & 0xFFFF) + (sum >> 16);
	}
	
	sum = ~sum;
	
	return htons(((unsigned short) sum));
}

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

* Re: Recalculate checksums in netfilter queue
       [not found]         ` <z2o3fdd6ce01004221432yec6c907bz4124144d403be1b4@mail.gmail.com>
@ 2010-04-22 22:12           ` Justin Yaple
  0 siblings, 0 replies; 7+ messages in thread
From: Justin Yaple @ 2010-04-22 22:12 UTC (permalink / raw)
  To: Bruno Moreira Guedes; +Cc: netfilter-devel

> So, talking about the topic - implementing checksum functions on
> netfilter_queue, it would be useful to nfq_set_verdict subcall a
> function which check if the checksums(tcp, ip, udp, anything else) are
> set to 0, and then(if it's 0) it change the ckecksum automatically -
> something like the kernel does when we send a packet through a RAW
> socket.
>
> --Bruno Moreira Guedes

I think thats a great idea.  If the functions were included in the
library you could have nfq_set_verdict call them if any of the
checksums are set to 0.  This would give you the option of either
calling the function yourself, or just setting the checksum to 0 then
let the nfq_set_verdict call the functions to recalculate them.

So maybe it could be implemented like the checksum functions used in
the kernel where the base checksum function is the same, but takes
parameters to determine what protocol the checksum is being calculated
for.  Then a wrapper function is made for each protocol type ip, tcp,
udp...

-Justin.

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

end of thread, other threads:[~2010-04-22 22:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-21  1:02 Recalculate checksums in netfilter queue Justin Yaple
2010-04-21  2:02 ` Bruno Moreira Guedes
2010-04-22  3:15   ` Justin Yaple
2010-04-22 12:43     ` Morgon.J.Kanter
2010-04-22 20:19       ` Justin Yaple
     [not found]         ` <z2o3fdd6ce01004221432yec6c907bz4124144d403be1b4@mail.gmail.com>
2010-04-22 22:12           ` Justin Yaple
2010-04-22 19:37     ` James King

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).