Find the answer to your Linux question:
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 ...
  1. #1
    Just 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

  2. #2
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    As far as I can see, there can be only three causes of error:
    1. You're actually computing the correct checksum and don't know it.
    2. You're using an incorrect checksum algorithm.
    3. You're computing the checksum on the (perhaps only slightly) wrong data.
    4. 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:
    1. the IP header;
    2. the UDP header; and
    3. the payload.

    I think that's the way it should be. But the first time you fill the buffer, it contains:
    1. the source address from the IP header;
    2. the destination address from the IP header;
    3. the IP header, including the source and destination address;
    4. a single byte (quite mysterious);
    5. the UDP packet size, from the UDP header;
    6. the UDP header, including the packet size; and
    7. 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.

  3. #3
    Just 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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...