Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > UDP checksumm


Автор: hawk3500 22.12.2011, 10:03
Здравствуйте.
Я формирую UDP пакет, и хочу подсчитать чексумму для него.
Сниффер говорит что расчитанная мной чексумма не верна.
Подскажите пожалуйста что я делаю не так.
Заранее благодарен.
С уважением,
hawk3500.
Код

#include <Winsock2.h>
#include <Windows.h>

struct UDP_HEADER
{
    unsigned short Source_Port;
    unsigned short Destanation_Port;
    unsigned short Message_Lenght;
    unsigned short Checksumm;
};
unsigned short rs_crc (unsigned short * buffer, int length)
{ 
    unsigned long crc = 0; 
    while (length > 1)
    { 
        crc += *buffer++; 
        length -= sizeof (unsigned short); 
    } 
    if (length) crc += *(unsigned char*) buffer;
    crc = (crc >> 16) + (crc & 0xffff);
    crc += (crc >> 16);
    if (1) crc = crc << 1; 
    return (unsigned short)(~crc); 
} 
int _tmain(int argc, _TCHAR* argv[])
{
    int pos=0;
    unsigned short check_summ=0;
    unsigned short *HEADER_FOR_CRC;
    UDP_HEADER UDP_H;
    unsigned long SOURCE_IP,DESTANATION_IP;
    unsigned char Protocol_Type_with_Zero[]="\x00\x11";
    char Message[]="\xFF\xFF";
    unsigned short Message_Lenght=2;
    SOURCE_IP=inet_addr("192.168.100.66");
    DESTANATION_IP=inet_addr("192.168.100.213");
    memset(&UDP_H,0,sizeof(UDP_HEADER));
    UDP_H.Destanation_Port=80;
    UDP_H.Source_Port=1105;
    UDP_H.Message_Lenght=Message_Lenght+sizeof(UDP_HEADER);
    HEADER_FOR_CRC=new unsigned short[2*sizeof(unsigned long)+2+sizeof(UDP_HEADER)+Message_Lenght];
    memcpy(&HEADER_FOR_CRC[pos/2],&SOURCE_IP,sizeof(unsigned long));
    pos+=sizeof(unsigned long);
    memcpy(&HEADER_FOR_CRC[pos/2],&DESTANATION_IP,sizeof(unsigned long));
    pos+=sizeof(unsigned long);
    memcpy(&HEADER_FOR_CRC[pos/2],&Protocol_Type_with_Zero,2);
    pos+=2;
    memcpy(&HEADER_FOR_CRC[pos/2],&UDP_H,sizeof(UDP_HEADER));
    pos+=sizeof(UDP_HEADER);
    memcpy(&HEADER_FOR_CRC[pos/2],&Message,Message_Lenght);
    pos+=Message_Lenght;
    check_summ=rs_crc(HEADER_FOR_CRC,pos);

    return 0;
}



Автор: boostcoder 22.12.2011, 10:09
во первых, необходимо знать, какой из http://en.wikipedia.org/wiki/Crc16 алгоритмов используется UDP стеком (снифером?) для подсчета crc. ибо их несколько.
как узнать - не знаю. не задавался этим вопросом.

Автор: hawk3500 22.12.2011, 10:36
Контрольная сумма в UDP пакете рассчитывается не по алгоритму crc16. Там сообщение дополняется нулями для выравнивания по границе слова. И рассчет производится путем последовательного суммирования слов сообщения с поразрядным дополнением, вычисленным на прошлой итерации и вычисления поразрядного дополнения к этой сумме.

Добавлено через 53 секунды
RFC-1071

Автор: newbee 22.12.2011, 10:56
Голова не варит и исходники не переваривает, но сверься с RFC на предмет: 1. алгоритма CRC 2. какие части пакета эта CRC должна считать. Ну и сравни с исходником.

Помнится, поле CRC в заголовке UDP никто никогда не проверяет...

Автор: hawk3500 22.12.2011, 11:07
проверял.Да можно выставить значение контрольной суммы в ноль и программа его пропустит,но если надо всё таки следить за инфой то она нужна.Мне по крайней мере нужна.
И не CRC, а контрольная сумма!

Автор: boostcoder 22.12.2011, 11:10
Цитата(hawk3500 @  22.12.2011,  10:36 Найти цитируемый пост)
Контрольная сумма в UDP пакете рассчитывается не по алгоритму crc16.

ну хз.. навскидку, твоя реализация напоминает crc16.

Добавлено через 59 секунд
да и зачем UDP превращать в TCP?

Автор: hawk3500 22.12.2011, 13:40
Спасибо всем кто отозвался на призыв о помощи.
Сделал.
Код

#include <Winsock2.h>
#include <Windows.h>

struct UDP_HEADER
{
    unsigned short Source_Port;
    unsigned short Destanation_Port;
    unsigned short Message_Lenght;
    unsigned short Checksumm;
};

unsigned short ROLL(unsigned short P)
{
    BYTE *A,*B;
    unsigned short Y;
    A=(BYTE *)&P;
    B=(BYTE *)&Y;
    B[0]=A[1];
    B[1]=A[0];
    return Y;
}
unsigned short ip_cksum(unsigned int sumk, unsigned short *buf1, int len)
{
    register long sum = 0;
    while( len > 1 )  
    {
        sum += * (unsigned short*) buf1++;
        len -= 2;
    }
    if( len > 0 )sum += * (unsigned char *) buf1;
    while (sum>>16)sum = (sum & 0xffff) + (sum >> 16); 
    return ~sum;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int pos=0;
    unsigned short check_summ=0;
    unsigned short *HEADER_FOR_CRC;
    UDP_HEADER UDP_H;
    unsigned long SOURCE_IP,DESTANATION_IP;
    unsigned char Protocol_Type_with_Zero[]="\x00\x11";
    char Message[]="\xFF\xFF";
    unsigned short Message_Lenght=2;
    SOURCE_IP=inet_addr("192.168.100.66");
    DESTANATION_IP=inet_addr("192.168.100.213");
    memset(&UDP_H,0,sizeof(UDP_HEADER));
    UDP_H.Destanation_Port=ROLL(80);
    UDP_H.Source_Port=ROLL(1260);
    UDP_H.Message_Lenght=ROLL(Message_Lenght+sizeof(UDP_HEADER));
    HEADER_FOR_CRC=new unsigned short[2*sizeof(unsigned long)+2+sizeof(UDP_HEADER)+Message_Lenght];
    
    unsigned short Y=ROLL(Message_Lenght+sizeof(UDP_HEADER));
    memcpy(&HEADER_FOR_CRC[pos/2],&DESTANATION_IP,sizeof(unsigned long));
    pos+=sizeof(unsigned long);
    memcpy(&HEADER_FOR_CRC[pos/2],&SOURCE_IP,sizeof(unsigned long));
    pos+=sizeof(unsigned long);
    memcpy(&HEADER_FOR_CRC[pos/2],&Protocol_Type_with_Zero,2);
    pos+=2;
    memcpy(&HEADER_FOR_CRC[pos/2],&Y,2);
    pos+=2;
    memcpy(&HEADER_FOR_CRC[pos/2],&UDP_H,sizeof(UDP_HEADER));
    pos+=sizeof(UDP_HEADER);
    memcpy(&HEADER_FOR_CRC[pos/2],&Message,Message_Lenght);
    pos+=Message_Lenght;
    check_summ=ROLL(ip_cksum(0,HEADER_FOR_CRC,pos));
    delete(HEADER_FOR_CRC);
    return 0;
}


Автор: Олег2005 23.12.2011, 16:45
Псевдозаголовок подключали?
Что то в коде я его не разглядел smile 

Автор: SVN74 24.12.2011, 13:22
"Adler32"  по моему будет лучше....

Код

//================= ADLER 32 =========================

 uint32_t adler32(unsigned char* buf, unsigned int buflength)
  {
     uint32_t s1 = 1;
     uint32_t s2 = 0;
 
     for (unsigned int n=0; n<buflength; n++)
     {
        s1 = (s1 + buf[n]) % 65521;
        s2 = (s2 + s1)     % 65521;
     }
     return (s2 << 16) + s1;
  }

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)