Re: IP cheksum and libnet_pblock_coalesce
Wu Yongwei <[email protected]> Thu, 30 Sep 2004 09:23:13 +0800
| Newsgroups | gmane.comp.security.libnet |
|---|---|
| Organization | Kingnet Security, Inc. |
| Message-ID | <[email protected]> |
Unless the checksumming is not intended upon the raw packet content, you
have the wrong test case. I think it should be like:
main()
{
char i[] = "\x01\x02\x03";
unsigned short last = 0, sum, *s = (unsigned short*)i;
unsigned char *sum_p = (unsigned char*)∑
*(unsigned char*)&last = *(unsigned char*)s;
printf("last=0x%04x\n", last);
sum_p[0] = 0x44;
sum_p[1] = 0x55;
sum += last;
printf("sum=0x%.2x%.2x\n", sum_p[0], sum_p[1]);
sum_p[0] = 0x44;
sum_p[1] = 0x55;
sum += (*(unsigned char*)s & 0xff)<<8;
printf("sum=0x%.2x%.2x\n", sum_p[0], sum_p[1]);
}
This will not change the result on big-endian machines, but will give
last=0x0001
sum=0x4555
sum=0x4456
on little-endian machines.
I did my test on a real packet. I chose a captured odd-sized UDP packet
and calculated its UDP checksum, and verified that the result should be
zero. My method passed the test but David's one failed it.
Best regards,
Yongwei
--- Original Message from Frédéric Raynal ---
> >Hi,
> >
> >That is a known (but tricky) bug reported some times ago. David
> >Baroso proposed something like :
> >
> >sum += ((*(u_int8_t *)addr & 0xFF)<<8);
> >
> >The difficulty is to find something working on both big and little
> >endian systems.
>
> The expression above seems to work only on big-endian machines and
> proves wrong in my test on x86 (contrary to Mr David Barroso's
> statement). The third edition of UNIX Network Programming has
> something like this (adapted):
>
> u_int16_t last_byte = 0;
> ...
> if (nleft == 1) {
> *(u_int8_t*)&last_byte = *(u_int8_t*)addr;
> sum += last_byte;
> }
>
> I feel this is good.
>
Hi,
I like it ... but I feel there is a problem. Thus, I coded this small
example:
main()
{
char i[] = "\x01\x02\x03";
unsigned short last = 0, sum = 0x4455, *s = (unsigned
short*)i;
*(unsigned char*)&last = *(unsigned char*)s;
printf("last=0x%04x\n", last);
sum += last;
printf("sum=0x%04x\n", sum);
sum = 0x4455;
sum += (*(unsigned char*)s & 0xff)<<8;
printf("sum=0x%04x\n", sum);
}
And here are the results:
On Mac OS X (big endian) :
last=0x0100
sum=0x4555
sum=0x4555
On x86 (little endian):
last=0x0001
sum=0x4456
sum=0x4555
And checksm must be big endian (network ordered) ...
I am not in position to perform tests here, so if some people could do
it, that will be very helpful.
Fred Raynal