Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.05.2015, 00:18   #1
BigDa
Пользователь
 
Регистрация: 23.10.2011
Сообщений: 16
Стрелка UDP: проблемы с контрольной суммой

Использую сырые сокеты, поэтому полностью сам задаю заголовки IP и UDP. Скопировал код с другого сайта, и всё работало. Контрольная сумма IP не считается, а в UDP считается по псевдозаголовку. И всё работало, пока мне не понадобилось добавить опции в пакет IP... Я добавил одну опцию (её присутствие учитывается в длине заголовка IP), которая занимает 4 байта. И почему-то когда эта опция равна нулю, то пакеты доходят до места назначения, а когда не равна нулю - не доходят (во второй программе принимаются все пакеты и выводятся на экран, да и там всегда всё принималось до этого). Такое ощущение, как будто опции в заголовке IP влияют на подсчёт контрольной суммы в заголовке UDP, но ведь такого не должно быть! Или что-то где-то делается не так. Подскажите, в чём проблема?

Вот как это всё происходит:

Код:
USHORT checksum(USHORT *br, int size)
{
    unsigned long cksum=0;
    while (size > 1){
        cksum += *br++;
        size  -= sizeof(USHORT);   
    }
    if (size){
        cksum += *(UCHAR*)br;   
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
    return (USHORT)(~cksum);
}
/*****************************************************************/
typedef struct ip_hdr
{
        unsigned char    ip_verlen;
        unsigned char    ip_tos;
        unsigned short   ip_total_len;
        unsigned short   ip_id;
        unsigned short   ip_offset;
        unsigned char    ip_ttl;
        unsigned char    ip_protocol;
        unsigned short   ip_checksum;
        unsigned int     sourceIP;
        unsigned int     destIP;
        unsigned int     option;
}IP_HDR;

typedef struct udp_hdr
{
        unsigned short   source_port;
        unsigned short   dest_port;
        unsigned short   udp_len;
        unsigned short   udp_sum;
}UDP_HDR;

/*****************************************************************/

void MakePacket(char* addrrr,int tos,char* MSG,unsigned long opt)
{
    iTotalSize = sizeof(ipHdr)+sizeof(udpHdr)+strlen(MSG);
    iIPSize    = (sizeof(ipHdr))/sizeof(unsigned long);
    ver = 4;
    ipHdr.ip_verlen    = (ver<<4) | iIPSize;
    ipHdr.ip_tos       = tos;
    ipHdr.ip_total_len = htons(iTotalSize);
    ipHdr.ip_id        = 0;
    ipHdr.ip_offset    = 0;
    ipHdr.ip_ttl       = 128;
    ipHdr.ip_protocol  = IPPROTO_UDP;
    ipHdr.ip_checksum  = 0;
    ipHdr.sourceIP     = inet_addr(MyAdr);
    ipHdr.destIP       = inet_addr(addrrr);
    ipHdr.option       = opt;
    //-------------------------------------------//
    iUdpSize = sizeof(udpHdr)+strlen(MSG);
    udpHdr.source_port = htons(5150);
    udpHdr.dest_port   = htons(5150);
    udpHdr.udp_len     = htons(iUdpSize);
    udpHdr.udp_sum     = 0;
    //-------------------------------------------//
    iUdpChecksumSize = 0;
    ptrSnd = SendBuf; ZeroMemory(SendBuf,4096);

    memcpy(ptrSnd,&ipHdr.sourceIP, sizeof(ipHdr.sourceIP));  
    ptrSnd              += sizeof(ipHdr.sourceIP);
    iUdpChecksumSize += sizeof(ipHdr.sourceIP);

    memcpy(ptrSnd,&ipHdr.destIP,sizeof(ipHdr.destIP));
    ptrSnd              += sizeof(ipHdr.destIP);
    iUdpChecksumSize += sizeof(ipHdr.destIP);


    ptrSnd++;iUdpChecksumSize += 1;



    memcpy(ptrSnd,&ipHdr.ip_protocol,sizeof(ipHdr.ip_protocol));
    ptrSnd              += sizeof(ipHdr.ip_protocol);
    iUdpChecksumSize += sizeof(ipHdr.ip_protocol);


    memcpy(ptrSnd,&udpHdr.udp_len,sizeof(udpHdr.udp_len));
    ptrSnd              += sizeof(udpHdr.udp_len);
    iUdpChecksumSize += sizeof(udpHdr.udp_len);

    memcpy(ptrSnd,&udpHdr,sizeof(udpHdr));
    ptrSnd              += sizeof(udpHdr);
    iUdpChecksumSize += sizeof(udpHdr);

    for(unsigned int i = 0; i < strlen(MSG); i++, ptrSnd++)
            *ptrSnd = MSG[i];

    iUdpChecksumSize += strlen(MSG);
    udpHdr.udp_sum = checksum((USHORT *)SendBuf, iUdpChecksumSize);

    ZeroMemory(SendBuf,4096);
    ptrSnd = SendBuf;

    memcpy(ptrSnd,&ipHdr, sizeof(ipHdr)); ptrSnd += sizeof(ipHdr);
    memcpy(ptrSnd,&udpHdr,sizeof(udpHdr));ptrSnd += sizeof(udpHdr);
    memcpy(ptrSnd,MSG,strlen(MSG));
}
BigDa вне форума Ответить с цитированием
Старый 16.05.2015, 09:13   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Здесь описано как надо считать cheksum для UDP
http://www.faqs.org/rfcs/rfc768.html
Обратите внимание на то, что входит в сумму до UDP заголовка.
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как вывести на экран номер строки с максимальной суммой элементов и номер столбца с минимальной суммой? Vetal888888 C# (си шарп) 4 20.12.2011 13:46
В квадратной матрице найти столбец с максимальной суммой и строку с максимальной суммой (Pascal) Alexey355 Помощь студентам 1 26.03.2011 14:06
проблема с фильтрами и суммой: dimmor Microsoft Office Excel 5 25.06.2009 15:10
Помогите с контрольной суммой!! tvaplus002 Софт 7 23.03.2009 13:57