Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
11-21-2010, 07:58 AM
|
#1
|
LQ Newbie
Registered: Nov 2010
Posts: 3
Rep:
|
UDP Checksum Algorithm
I am trying to compute a UDP checksum via what the UDF RFC suggests.
From what I have learned the checksum is on a pseudo header and a combined UDP header and data. Essentially the checksum should cover, where all of the fields are in network/bigendian order:
Pseudo Header:
source(32bits) + dest(32bits) + zeros(8bits) + protocol(8bits) + udplength(16bits)
UDP and Data:
source_port(16bits) + dest_port(16bits) + length(16bits) + zeros(16bits)
+ data(384 bits)
To achieve the checsum I copy the pseudo header and the udp+data into one byte array. I then traverse that byte array in blocks of 4 bytes until I reach the end of the array. I compute as follows:
[I]
unsigned short buffer[sizeof(psedudo) + sizeof(udp_and_data)];
/* The data is copied from pseudo and udp_and_data into buffer */
sum = 0;
for (i=0; i<sizeof(buffer); i+=2)
sum += ~(buffer + buffer[i+1]);
return ~sum;
I return the 1's complement. Unfortunately I have yet to get tcpdump to report this as a valid calculation.
I have tried numerous approaches found online, and even some pieces of the Linux kernel to no avail. Any help would be appreciated.
-Matt
|
|
|
11-21-2010, 10:15 PM
|
#2
|
Senior Member
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
|
Code:
traverse that byte array in blocks of 4 bytes until I reach the end of the array
Presumably you mean blocks of 2 bytes, since it is a 16 bit sum.
Code:
sum += ~(buffer + buffer[i+1]);
You should be adding words (big endian), not bytes. And why the complement operator here?
You haven't added back in the carries (the sum is a ones-complement sum; since most languages provide only a twos-complement addition, you have to add the carries back in to emulate a ones-complement sum).
Last edited by neonsignal; 11-21-2010 at 10:16 PM.
|
|
|
11-22-2010, 04:24 PM
|
#3
|
Moderator
Registered: Mar 2008
Posts: 22,239
|
Some nics offload checksum.
|
|
|
11-23-2010, 08:50 AM
|
#4
|
LQ Newbie
Registered: Nov 2010
Posts: 3
Original Poster
Rep:
|
Thanks for all the help. Following is the algorithm I am using on a 64bit x86 machine. I am still not having much luck with it.
Code:
static uint16_t udp_checksum(
const struct iphdr *ip,
const struct udphdr *udp,
const data_pkt *foo)
{
pseudo_hdr ps_hdr = {0};
uint8_t data[sizeof(pseudo_hdr) + sizeof(struct udphdr) + sizeof(data_pkt)] = {0};
ps_hdr.source = ip->saddr;
ps_hdr.dest = ip->daddr;
ps_hdr.protocol = IPPROTO_UDP;
ps_hdr.udp_length = udp->len;
memcpy(data, &ps_hdr, sizeof(pseudo_hdr));
memcpy(data + sizeof(pseudo_hdr), udp, sizeof(struct udphdr));
memcpy(data + sizeof(pseudo_hdr) + sizeof(struct udphdr), ntp, sizeof(data_pkt));
return csum((uint16_t *)data, sizeof(data)/2);
}
/* Not my code */
unsigned short csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
|
|
|
11-23-2010, 06:21 PM
|
#5
|
Senior Member
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
|
The checksum code is now valid.
If you are still having problems with the actual packet, then one possibility is that it is an endian issue (because presumably you are working on a little-endian, and the packets have to be constructed big-endian). The endian direction doesn't affect the checksum; the checksum is the same no matter what order the bytes are in (since it just does additions, which are commutative).
The other possibility, being on a 64 bit machine, is that you have alignment issues. It is worth printing out the sizeof values of your structures, just to make sure they are the size you think they are.
What are your structure definitions? Do you have any sample data to compare with?
|
|
|
11-24-2010, 06:02 AM
|
#6
|
LQ Newbie
Registered: Nov 2010
Posts: 3
Original Poster
Rep:
|
Quote:
Originally Posted by neonsignal
The checksum code is now valid.
If you are still having problems with the actual packet, then one possibility is that it is an endian issue (because presumably you are working on a little-endian, and the packets have to be constructed big-endian). The endian direction doesn't affect the checksum; the checksum is the same no matter what order the bytes are in (since it just does additions, which are commutative).
The other possibility, being on a 64 bit machine, is that you have alignment issues. It is worth printing out the sizeof values of your structures, just to make sure they are the size you think they are.
What are your structure definitions? Do you have any sample data to compare with?
|
neonsignal,
Ok, I'm baffled. It now works. Thanks for the positive vibes. I'm in Melbourne too ;-)
-Matt
|
|
|
All times are GMT -5. The time now is 06:03 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|