Results 1 to 3 of 3
hello everybody,I am the new kid
I compute the udp checksum with the following code,but when I capture the my packet by ethereal,I got the incorrect checksum
why is the ...
- 02-03-2008 #1Just Joined!
- Join Date
- Feb 2008
- Posts
- 2
UDP checksum problem
hello everybody,I am the new kid
I compute the udp checksum with the following code,but when I capture the my packet by ethereal,I got the incorrect checksum
why is the checksum wrong?
I have searched in google,study the UDP rfc,referenced some code.
I computed the checksum according to the following text
Checksum is the 16-bit one's complement of the one's complement sum of a
pseudo header of information from the IP header, the UDP header, and the
data, padded with zero octets at the end (if necessary) to make a
multiple of two octets.
The pseudo header conceptually prefixed to the UDP header contains the
source address, the destination address, the protocol, and the UDP
length. This information gives protection against misrouted datagrams.
This checksum procedure is the same as is used in TCP.
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| source address |
+--------+--------+--------+--------+
| destination address |
+--------+--------+--------+--------+
| zero |protocol| UDP length |
+--------+--------+--------+--------+
If the computed checksum is zero, it is transmitted as all ones (the
equivalent in one's complement arithmetic). An all zero transmitted
checksum value means that the transmitter generated no checksum (for
debugging or for higher level protocols that don't care).
what's wrong?
thanks lot for you help
//the checksum
static unsigned short checksum(unsigned short *pwbuffer,uint32_t size)
{
unsigned long cksum=0;
while(size > 1){
cksum+=*pwbuffer++;
size-=sizeof(uint16_t);
}
if(size){
cksum+=*(uint8_t*)pwbuffer;
}
cksum=(cksum>>16)+(cksum&0xffff);
cksum+=(cksum >> 16);
return (unsigned short)(~cksum);
}
//create the raw socket
BOOL createNatSocket(uint32_t protocol)
{
BOOL opt=TRUE;
DEBUG_INFO("createNatSocket","Start....");
if((natPacket.natSock=socket(AF_INET,SOCK_RAW,prot ocol))<0){
ERR_INFO("socket failed");
return FALSE;
}
if(setsockopt(natPacket.natSock,IPPROTO_IP,IP_HDRI NCL,(char*)&opt,sizeof(opt))==-1){
close(natPacket.natSock);
natPacket.natSock=-1;
ERR_INFO("setsockopt failed");
return FALSE;
}
DEBUG_INFO("createNatSocket","End....");
return TRUE;
}
//makeup the ip and udp header and sendto
static BOOL sendNatPacket(uint32_t localIP,uint16_t localPort,uint32_t dstIP,uint16_t dstPort,uint8_t *buf,uint32_t bufLen)
{
struct UDPHeader udp_header;
struct IPHeader ip_header;
unsigned char rawBuf[1024];
unsigned char *pRawBuf=rawBuf;
int udpCheckSumSize=0;
unsigned short cksum=0;
uint32_t ip_version=4;
uint32_t ip_header_len=sizeof(struct IPHeader)/sizeof(unsigned long);
uint32_t udp_len=sizeof(struct UDPHeader)+bufLen;
uint32_t total_len=sizeof(struct IPHeader)+sizeof(struct UDPHeader)+bufLen;
struct sockaddr_in addr;
if(natPacket.natSock==-1){
DEBUG_INFO("sendNatPacket","natPacket.natSock is -1");
return FALSE;
}
memset(&udp_header,0,sizeof(struct UDPHeader));
memset(&ip_header,0,sizeof(struct IPHeader));
ip_header.ip_verlen=(ip_version<<4)|ip_header_len;
ip_header.ip_tos=0;
ip_header.ip_totallength=htons(total_len);
ip_header.ip_offset=0;
ip_header.ip_ttl=128;
ip_header.ip_protocol=0x11;
ip_header.ip_checksum=0;
ip_header.ip_srcaddr=localIP;
ip_header.ip_destaddr=dstIP;
udp_header.src_portno=htons(localPort);
udp_header.dst_portno=htons(dstPort);
udp_header.udp_length=htons(udp_len);
udp_header.udp_checksum=0;
memset(pRawBuf,0,sizeof(rawBuf));
//src IP
memcpy(pRawBuf,&ip_header.ip_srcaddr,sizeof(ip_hea der.ip_srcaddr));
pRawBuf+=sizeof(ip_header.ip_srcaddr);
udpCheckSumSize+=sizeof(ip_header.ip_srcaddr);
//dst IP
memcpy(pRawBuf,&ip_header.ip_destaddr,sizeof(ip_he ader.ip_destaddr));
pRawBuf+=sizeof(ip_header.ip_destaddr);
udpCheckSumSize+=sizeof(ip_header.ip_destaddr);
pRawBuf++;
udpCheckSumSize+=1;
//ip protocol
memcpy(pRawBuf,&ip_header.ip_protocol,sizeof(ip_he ader.ip_protocol));
pRawBuf+=sizeof(ip_header.ip_protocol);
udpCheckSumSize+=sizeof(ip_header.ip_protocol);
//udp packet size
memcpy(pRawBuf,&udp_header.udp_length,sizeof(udp_h eader.udp_length));
pRawBuf+=sizeof(udp_header.udp_length);
udpCheckSumSize+=sizeof(udp_header.udp_length);
//udp header
memcpy(pRawBuf,&udp_header,sizeof(udp_header));
pRawBuf+=sizeof(udp_header.udp_length);
udpCheckSumSize+=sizeof(udp_header);
//payload
memcpy(pRawBuf,buf,bufLen);
udpCheckSumSize+=bufLen;
cksum=checksum((unsigned short *)rawBuf,udpCheckSumSize);
udp_header.udp_checksum=cksum;
pRawBuf=rawBuf;
memset(pRawBuf,0,sizeof(rawBuf));
memcpy(pRawBuf,&ip_header,sizeof(ip_header));
pRawBuf+=sizeof(ip_header);
memcpy(pRawBuf,&udp_header,sizeof(udp_header));
pRawBuf+=sizeof(udp_header);
memcpy(pRawBuf,buf,bufLen);
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=dstIP;
addr.sin_port=htons(dstPort);
if(sendto(natPacket.natSock,rawBuf,total_len,0,(st ruct sockaddr*)&addr,sizeof(struct sockaddr_in))<0){
fprintf(stderr,"FILE %s, LINE %d, errno %d, errMsg %s\n",__FILE__,__LINE__,errno,strerror(errno));
return FALSE;
}
return TRUE;
}
//the send
BOOL sendNatDetect(void)
{
char tmpBuf[128]={0};
uint16_t localPort=59000;
m_buf.port=htons(localPort);
memcpy(tmpBuf,&m_buf.ip,4);
memcpy(tmpBuf+4,&m_buf.port,2);
memcpy(tmpBuf+6,m_buf.buf,22);
return sendNatPacket(natPacket.local_ip_addr,localPort,
natPacket.remote_ip_addr,natPacket.remote_port,
tmpBuf,natPacket.data_buf_len);
}Last edited by linux_harmful; 02-03-2008 at 02:23 AM. Reason: somthing mistake
- 02-03-2008 #2
As far as I can see, there can be only three causes of error:
- You're actually computing the correct checksum and don't know it.
- You're using an incorrect checksum algorithm.
- You're computing the checksum on the (perhaps only slightly) wrong data.
- You're storing the computed checksum in the wrong place.
Yeah, that's three items, all right. Just to give you confidence in my competence. (Harrumph.)
You will be overjoyed to know that I compared your checksum function with that in the impossible-to-overrate Addison Wesley book UNIX Network Programming, volume 1, by W. Richard Stevens of happy memory, and it looks ok.
And I have no experience with raw sockets programming, but I'm looking at the code you posted.
You seem to fill the buffer, compute the checksum on the basis of what's in the buffer (including a zero checksum), and then fill the buffer again, this time with the correct checksum. There's a faster way to do this, of course, but you're asking about accuracy, not speed.
The second time you fill the buffer, it contains:
- the IP header;
- the UDP header; and
- the payload.
I think that's the way it should be. But the first time you fill the buffer, it contains:
- the source address from the IP header;
- the destination address from the IP header;
- the IP header, including the source and destination address;
- a single byte (quite mysterious);
- the UDP packet size, from the UDP header;
- the UDP header, including the packet size; and
- the payload.
What are those extra items doing there in the first pass? Won't they throw the checksum out of whack?
Also, during the first pass, when you add the UDP header, you advance pRawbuf not by sizeof(upd_header), but by sizeof(udp_header.udp_length). That can't be right.
Maybe I'm speaking from complete ignorance, but possibly there's something of use here. I hope so.--
Bill
Old age and treachery will overcome youth and skill.
- 02-05-2008 #3Just Joined!
- Join Date
- Feb 2008
- Posts
- 2
oh my god! I take a addlepated mistake and I didn't care it and pay all of the attention to the algorithm.
the following code is wrong
//udp header
memcpy(pRawBuf,&udp_header,sizeof(udp_header));
pRawBuf+=sizeof(udp_header.udp_length);
udpCheckSumSize+=sizeof(udp_header);
and the correct is
//udp header
memcpy(pRawBuf,&udp_header,sizeof(udp_header));
pRawBuf+=sizeof(udp_header);
udpCheckSumSize+=sizeof(udp_header);
I am too reckless
thanks a lot for wje_lf


Reply With Quote