The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  вход/выход  слежка  RSS
"Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 16-Фев-11, 20:52 
Здравствуйте, дорогие участники форума!

Недвно у меня возникла необходимость работы с низкоуровневыми (сырыми) сокетами в ОС Linux.
Для начала написал парочку простеньких приложений, одним из которых является генератор SYN-пакетов протокола TCP. При тестировании программы заметил, что от машины, на адрес которой высылается пакет, не приходит никакого ответа. Стал разбираться и обнаружил, что монитор сетевого трафика wireShark забраковывает контрольную сумму TCP-заголовка отправляемого пакета, что может говорить о том, что на удаленной машине пакет молча уничтожается вследствие обнаружения неправильной контрольной суммы на приеме.

Ниже привожу кусок кода, относящийся к рассчету КС:

Функция рассчета КС:

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;
}

Проверял следующим образом. Брал массив из четного числа байтов, рассчитывал по нему КС, а затем по тому же массиву с учетом контрольной суммы производил перерассчет. Итоговое значение - 0, то есть функция корректная.

Структура псевдозаголовка:

struct p_header
{
  u_long s_addr;
  u_long d_addr;
  u_char zer0;
  u_char protocol;
  u_int lenght;
};

Буфер для хранения пакета:

char datagram[4096];

/* Создаем указатель на структуру IP-заголовка и инициализируем
его адресом начала буфера datagram */
  struct ip *iph = (struct ip *) datagram;
    
/* Создаем указатель на структуру TCP-заголовка и инициализируем
его адресом ячейки буфера datagram, соответствующей первому байту TCP-заголовка */

  struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));

/*Объявляем и инициализируем указатель на структуру псевдозаголовка TCP-пакета
Она используется для рассчета контрольной суммы TCP-пакета*/

struct p_header *pseudo = (struct p_header *) ( datagram + sizeof( struct ip)
- sizeof( struct p_header ));

/* Инициалзируем псевдозаголовок */

pseudo->s_addr = inet_addr ("1.2.3.4");
pseudo->d_addr = sin.sin_addr.s_addr;
pseudo->protocol = 6;
pseudo->lenght = 5;

/* Транспортный протокол */

tcph->th_sport = htons (1234); // номер порта отправителя

tcph->th_dport = htons (P); // номер порта получателя

tcph->th_seq = htonl(1);//random(); // Определяет порядковый номер TCP пакета внутри сеанса (для SYN-запроса - случайное число)

tcph->th_ack = 0; // Определяет количество принятых данных из входящего по отношению к TCP модулю потока

tcph->th_x2 = 0; // Зарезервированное поле

tcph->th_off = 5;//Смещение начала поля данных относительно TCP-заголовка(в 32-разрядных словах)

tcph->th_flags = TH_SYN; // Флаг SYN (TCP пакет представляет собой запрос на установление логического соединения)

tcph->th_win = htons (32767);// Размер окна (размер приемного буфера TCP-модуля, отправляющего пакет)

tcph->th_sum = 0;

tcph->th_urp = 0; // Указатель на первый байт последовательности "важных" данных в теле TCP-пакета

/* Рассчитываем контрольную сумму TCP-пакета*/
tcph->th_sum = csum ((unsigned short *) datagram, sizeof (struct p_header ) + sizeof (struct tcphdr));

Вот такой вот не хитрый код.
Подскажите пожалуйста, что я делаю не так?

Заранее благодарю!

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 17-Фев-11, 04:14 
> Функция рассчета КС:
> 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;
> }

return (unsigned short)~sum;

> /* Рассчитываем контрольную сумму TCP-пакета*/
> tcph->th_sum = csum ((unsigned short *) datagram, sizeof (struct p_header ) + sizeof(struct tcphdr));

А где struct pseudo c адресами?

> Вот такой вот не хитрый код.

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 17-Фев-11, 11:30 
>[оверквотинг удален]
>> 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;
>> }
> return (unsigned short)~sum;

Явное приведение типа в данном случае не играет никакой роли.

>> /* Рассчитываем контрольную сумму TCP-пакета*/
>> tcph->th_sum = csum ((unsigned short *) datagram, sizeof (struct p_header ) + sizeof(struct tcphdr));
> А где struct pseudo c адресами?

pseudo->s_addr = inet_addr ("1.2.3.4");// Адрес источника
pseudo->d_addr = sin.sin_addr.s_addr;//Адрес получателя (вводится с терминала)
pseudo->protocol = 6;
pseudo->lenght = 5;

>> Вот такой вот не хитрый код.

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от guest email(??) on 17-Фев-11, 12:11 
>   u_int lenght;
> };

А точно int? ЕМНИП там 2 байта

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

4. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 17-Фев-11, 19:17 
>[оверквотинг удален]
> Функция рассчета КС:
> 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;
> }


unsigned short csum(unsigned short *buf, int nwords)
{
   unsigned long sum;

   for (sum = 0; nwords > 1; nwords-2)
         sum += *(buf++);

   if (nwords > 0)
         sum += *(unsigned char *)buf;

   while (sum >> 16)
      sum = (sum >> 16) + (sum & 0xffff);

return (unsigned short)~sum;
}

Кстати, на выходе: сумма байт пакета + КС должны равняться 0xFFFF;

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

5. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 20-Фев-11, 15:39 
Господа, с проблемой я разобрался! Исходников под рукой нет, в чем суть была, напишу позже.
Одно скажу, функция рассчета КС правильная. По-поводу u_int lenght, - здесь действительно ошибка, поскольку вместо 2 байт используется 4, но она не играет никакой роли в процессе вычисления КС, так как лишние 2 байта равны нулю. Кстати, благодарю вас за поддержку!!!

Тут у меня возникла еще одна интереснейшая проблема, которой я хочу с вами поделиться. Может вместе что придумаем. Есть у меня в программе (не в вышеприведенной) структурка. Точное ее содержание сейчас не передам, но суть вопроса состоит в следующем.

struct x
{
......
......
......
u_long a;
u_long b;
u_long c;
char array[50];
......
......
......
};

Когда я создаю объект данного типа, то вижу следующее. Линкер в памяти компьютера между полем "c" и полем "array" вставляет промежуток в 4 байта. Суть в том, что эти четыре байта мне ни как не нужны, поскольку структура, с которой я работаю, описывает заголовок пакета, формируемого по некоторому стандартизованному протоколу. Само собой разумеется, что ничего лишнего там быть не должно.

Слышал я про выравнивание адресов... Но в данном случае с выравниванием не должно быть никаких проблем. Объекты типа u_long распологаются в памяти по адресам, кратным 4, а типа char - по любым. То есть массив он мне должен был положить в память сразу же после поля "с".

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 20-Фев-11, 16:08 
> Само собой разумеется, что ничего лишнего там быть не должно.

Дык


struct x  {
  u_long a;
  u_long b;
  u_long c;
  char array[50];
} __attribute__((packed));

PS.
  На 64 битах, без упаковки массив выравняется до 56, то есть 6 лишних будет.

Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

7. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 20-Фев-11, 16:12 
А можно поподробнее про __attribute__((__packed__))? Шо це таке? =)

Все, нашел про это информацию. Сегодня попробую!!!


Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

8. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 20-Фев-11, 17:06 
>  Шо це таке?

Це ментовоз.

Кстати, эта, аккуратнее с упаковкой, на обратной стороне соединения должно так же паковаться.

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

9. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing (ok) on 20-Фев-11, 21:24 
Не помог атрибут =( Пакует так же

struct dhcp_header
{
    u_int8_t op; /* 0: Message opcode/type */
    u_int8_t htype; /* 1: Hardware addr type (net/if_types.h) */
    u_int8_t hlen; /* 2: Hardware addr length */
    u_int8_t hops; /* 3: Number of relay agent hops from client */
    u_int32_t xid; /* 4: Transaction ID */
    u_int16_t secs; /* 8: Seconds since client started looking */
    u_int16_t flags; /* 10: Flag bits */
    struct in_addr ciaddr; /* 12: Client IP address (if already in use) */
    struct in_addr yiaddr; /* 16: Client IP address */
    struct in_addr siaddr; /* 18: IP address of next server to talk to */
    struct in_addr giaddr; /* 20: DHCP relay agent IP address */
    unsigned char chaddr [16]; /* 24: Client hardware address */
    char sname [64]; /* 40: Server name */
    char file [128]; /* 104: Boot filename */
    unsigned char options [12];
}__attribute__((packed));

Между полями giaddr и chaddr 4 лишних байта

Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

10. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 20-Фев-11, 22:33 
> Не помог атрибут =( Пакует так же
> Между полями giaddr и chaddr 4 лишних байта


#include <inttypes.h>
#include <netinet/in.h>

struct dhcp_header {
        u_int8_t op;
        u_int8_t htype;
        u_int8_t hlen;
        u_int8_t hops;
        u_int32_t xid;
        u_int16_t secs;
        u_int16_t flags;
        struct in_addr ciaddr;
        struct in_addr yiaddr;
        struct in_addr siaddr;
        struct in_addr giaddr;
        unsigned char chaddr[16];
        char sname[64];
        char file[128];
        unsigned char options[12];
} __attribute__((packed));

struct dhcp_header x = {1,2,3,4,5,6,7,
                        1111,
                        2222,
                        3333,
                        4444,
                        {[0 ... 15] = '\xff'},
                        {[0 ... 63] = '\xff'},
                        {[0 ... 127]= '\xff'},
                        {[0 ... 11] = '\xff'},
                      };

# gcc -c main.c -S
# less main.s


        .file   "main.c"
.globl x
        .data
        .align 32
        .type   x, @object
        .size   x, 248           Как видишь 248 байт.
x:
        .byte   1
        .byte   2
        .byte   3
        .byte   4

        .long   5

        .value  6
        .value  7    

        .long   1111  
        .long   2222
        .long   3333
        .long   4444   ; поле giaddr

        .byte   -1     ; поле chaddr (точнее, его начало, там далее 208 раз по -1)
        .... // много раз


Более того, сама структура выровнена как по 4 байтовой границе, так и по 8-ми
То есть, даже без __attribute__((packed)), лишних нулей не должно быть.


Кстати, какой компилятор???

У меня например чтоб догнать размер этой структуры до 256 байт,
надо написать  __attribute__((aligned(16)));
и только тогда В КОНЦЕ появятся 8 нулей.

Почему они у Вас в середине не понятно.

Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

11. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от rezzko (ok) on 21-Фев-11, 01:54 
спс
Ответить | Правка | ^ к родителю #10 | Наверх | Cообщить модератору

12. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 21-Фев-11, 10:10 
Я изначально и писал, что все должно быть нормально и без выравнивания))) Компилятор gcc.
У меня, кстати, возникла идея, как этот момент можно обойти. Если получится, расскажу.


Ответить | Правка | ^ к родителю #10 | Наверх | Cообщить модератору

13. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 21-Фев-11, 18:24 
> Я изначально и писал, что все должно быть нормально и без выравнивания)))

Там правило простое - если делаешь структуру, делай её размер кратный степени 2.
По этой причине в некоторых структурах встречается настораживающие слово Reserved.
А если вложенный массив или структура не влазит в степень 2-ки, как последнее поле
в dhcp_header, то её помещают в конец.

Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

14. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 21-Фев-11, 20:23 
Дружище, все бы хорошо, да вот протокол не мною писан! Не имею я права в нем поля менять местами, иначе машина на удаленном конце меня не "поймет" =)


Ответить | Правка | ^ к родителю #13 | Наверх | Cообщить модератору

15. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 21-Фев-11, 21:06 
> Дружище, все бы хорошо, да вот протокол не мною писан! Не имею
> я права в нем поля менять местами, иначе машина на удаленном
> конце меня не "поймет" =)

http://www.networksorcery.com/enp/protocol/dhcp.htm

Он там как раз 256 байт, так что последний массив скорее должен быть options[16]

Ответить | Правка | ^ к родителю #14 | Наверх | Cообщить модератору

16. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 21-Фев-11, 22:10 
        .file   "DHCP.c"
        .comm   sock,4,4
        .comm   dhcph,248,32
        .section        .rodata

Вот что он пишет про dhcph


Ответить | Правка | ^ к родителю #15 | Наверх | Cообщить модератору

17. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 21-Фев-11, 22:32 
> .comm   dhcph,248,32

Ну и нормально.
Я к тому, что если будет 248 + 8 в конце, то страшного тоже ничего не должно быть.

Ответить | Правка | ^ к родителю #16 | Наверх | Cообщить модератору

18. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 22-Фев-11, 11:34 
Не нормально, поскольку 4 лишних байта он всеравно вставляет, хоть ты тресни!

Ответить | Правка | ^ к родителю #17 | Наверх | Cообщить модератору

19. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 22-Фев-11, 14:29 
> Не нормально, поскольку 4 лишних байта он всеравно вставляет, хоть ты тресни!

Сам же написал 248, откуда лишние?  

Ответить | Правка | ^ к родителю #18 | Наверх | Cообщить модератору

20. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 22-Фев-11, 16:50 
В шарке вижу. Потом нарисую, чтобы понятно было.


Ответить | Правка | ^ к родителю #19 | Наверх | Cообщить модератору

21. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от guest email(??) on 22-Фев-11, 17:20 
> В шарке вижу. Потом нарисую, чтобы понятно было.

unsigned char options [12];
Опять же, для dhcp тут точно не 12 байт должно быть. Не уверен, но вроди там может быть >1200 байт (максMTU - ip - udp - остальная часть DHCP заголовка).
Понимаю, что к вашим проблемам это пока не относиться, но посмотрите внимательно)

Ответить | Правка | ^ к родителю #20 | Наверх | Cообщить модератору

22. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 22-Фев-11, 17:29 
>> В шарке вижу. Потом нарисую, чтобы понятно было.
>  unsigned char options [12];
> Опять же, для dhcp тут точно не 12 байт должно быть. Не
> уверен, но вроде там может быть >1200 байт (максMTU - ip
> - udp - остальная часть DHCP заголовка).
> Понимаю, что к вашим проблемам это пока не относиться, но посмотрите внимательно)

По стандарту там до 255, но минимум 4 байта - 99, 130, 83, 99

BOOTP/DHCP options. Variable length.
The first four bytes contain the (decimal) values 99, 130, 83 and 99. This is the same magic cookie as has been defined for BOOTP. The remainder of the field consists of a list of tagged parameters that are called options. All of the vendor extensions used by BOOTP are also DHCP options.

У него в середине дыра получается :)

Ответить | Правка | ^ к родителю #21 | Наверх | Cообщить модератору

24. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 22-Фев-11, 17:57 
>>> В шарке вижу. Потом нарисую, чтобы понятно было.
>>  unsigned char options [12];
>> Опять же, для dhcp тут точно не 12 байт должно быть. Не
>> уверен, но вроде там может быть >1200 байт (максMTU - ip
>> - udp - остальная часть DHCP заголовка).
>> Понимаю, что к вашим проблемам это пока не относиться, но посмотрите внимательно)
> По стандарту там до 255, но минимум 4 байта - 99, 130,
> 83, 99

Вру, 4 байта и 0xff - конец опций.

Ответить | Правка | ^ к родителю #22 | Наверх | Cообщить модератору

25. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от guest (??) on 22-Фев-11, 18:16 
> По стандарту там до 255, но минимум 4 байта - 99, 130,

Куда-то не туда смотрите. В RFC говориться, что нужно уметь _минимум_ (at least) 312 байт.
Максимум же стандартом не оговаривается - я понимаю это так: размер поля может быть любым, главное запихнуть это все в 1 пакет.

> У него в середине дыра получается :)
>> Понимаю, что к вашим проблемам это пока не относиться, но посмотрите внимательно)

Я даже попробывал на паре платформ, не воспроизвел само-собой Ж)
может там ключики у компилятора в make/env или еще какая-то странность...

Ответить | Правка | ^ к родителю #22 | Наверх | Cообщить модератору

26. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 22-Фев-11, 18:40 
> Куда-то не туда смотрите. В RFC говориться, что нужно уметь _минимум_ (at least) 312 байт.

Ну там про клиента говориться. Все равно ISC DHCP круче :)

>> У него в середине дыра получается :)
>>> Понимаю, что к вашим проблемам это пока не относиться, но посмотрите внимательно)
> Я даже попробывал на паре платформ, не воспроизвел само-собой Ж)
> может там ключики у компилятора в make/env или еще какая-то странность...

Вот эту попробуй, без __attribute__((packed))


struct x  {
  u_long a;
  u_long b;
  u_long c;
  char array[50];
};

тут нули в конце будут.
Ответить | Правка | ^ к родителю #25 | Наверх | Cообщить модератору

27. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 25-Фев-11, 16:04 
Все нормально, с пропусками разобрался недавно. Ошибка была в программе тупейшая, так что прошу прощения!!!

Ответить | Правка | ^ к родителю #19 | Наверх | Cообщить модератору

28. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 25-Фев-11, 19:55 
> ... Ошибка была в программе тупейшая,...

:)

Ну давай рассказывай.

Ответить | Правка | ^ к родителю #27 | Наверх | Cообщить модератору

29. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 05-Мрт-11, 10:27 
Завтра напишу в чем была проблема с рассчетом КС. Про выравнивание писать даже нечего. Просто моя тупейшая ошибка.

У меня к вам назрел еще один вопрос. Нет ли в Linux библиотечки, позволяющей работать с канальным уровнем стека протоколов TCP/IP??? То есть, очень хочется получить возможность формирования Ethernet-кадров вручную. В Windows такие штуки я вытворял с использованием библиотеки packet32.dll. Это нужно для решения одной задачки. Необходимо вложить в отправляемый пакет некую величину непосредственно перед отправкой пакета в сеть, а на приеме - изъять эту величину сразу же после приема пакета сетевой картой.


Ответить | Правка | ^ к родителю #28 | Наверх | Cообщить модератору

30. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 05-Мрт-11, 12:59 
> У меня к вам назрел еще один вопрос. Нет ли в Linux библиотечки, позволяющей

libnet глянь

http://libnet.sourceforge.net/libnet.html (это cтарый)
http://packetfactory.openwall.net/projects/libnet/ (это наследник, но тоже дохлый)
http://github.com/sam-github/libnet  (свежак)

Ответить | Правка | ^ к родителю #29 | Наверх | Cообщить модератору

31. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 05-Мрт-11, 14:59 
Спасибо! Почитал, вроде бы то, что нужно!!!

Ответить | Правка | ^ к родителю #30 | Наверх | Cообщить модератору

32. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 07-Мрт-11, 22:55 
Здравствуйте!
Отписываюсь по поводу решения проблемы с контрольной суммой TCP-заголовка. Заранее прошу прощения за столь долгую паузу в ответе.

Итак, начнем.
Структура p_header. В ней, как верно заметил один из ответчиков, последнее поле должно иметь не тип int, а тип short. Отмечу, что на результат рассчета данная ошибка ни коем образом не влияет (если объект типа p_header правильно проинициализирован). Два лишних нулевых байта ни коим образом не влияют на результат. Таким образом, структура псевдозаголовка выглядит следующим образом:

struct p_header
{
  u_long s_addr;
  u_long d_addr;
  u_char zer0;
  u_char protocol;
  u_short lenght;
};

Теперь про инициализацию псевдозаголовка.
Вот изначальный вариант:

pseudo->s_addr = inet_addr ("1.2.3.4");
pseudo->d_addr = sin.sin_addr.s_addr;
pseudo->protocol = 6;
pseudo->lenght = 5;

Ошибочка таится в последней строчке. Данное поле - длина tcp-заголовка в БАЙТАХ!!!
Таким образом, должно быть что-то вроде:

pseudo->lenght = htons((unsigned short)sizeof (struct tcphdr));

Заметьте так же, что в данной структуре везде используется сетевой порядок следования байтов. Например, данные в памяти моей машины размещаются по принципу little-endian. То есть, если предположить, что длина моего tcp-заголовка равна 2048 байт, то данное значение в 16-разрядной ячейки памяти компьютера будет храниться в виде 0xFF07. В поле структуры pseudo->lenght они должны храниться в виде 0x07FF.

Ну вот вроде бы и все. Не припомню, чтобы я нашел в коде что-то еще. Да, еще один момент. Если не инициализировать псевдозаголовок нулями, перед его заполнением, то выше сказанные мною слова о том, что 2 лишних байта в струкре псевдозаголовка не влияют на рассчет КС, становятся недействительными =)

Хочу поблагодарить всех, кто отозвался! Особая благодарность пользователю под ником Pavlinux!!!

Ответить | Правка | ^ к родителю #31 | Наверх | Cообщить модератору

33. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 08-Мрт-11, 17:52 
Попробовал поюзать библиотечку libnet.
Написал простенькую прогу, попробовал собрать:

gcc timestamp.c -o timestamp`libnet-config --defines``libnet-config --libs``libnet-config --cflags`

Выдает предупреждение и ошибку:

<command-line>:0: warning: missing whitespace after the macro name
In file included from timestamp.c:1:
/usr/include/libnet.h:96: error: missing binary operator before token "1"

Команды для сборки программы: использующей библиотеку libnet взял из одной статьи.
Подскажите, пожалуйста, что не так?


Ответить | Правка | ^ к родителю #32 | Наверх | Cообщить модератору

34. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от goodfornothing email(ok) on 08-Мрт-11, 18:51 
gcc -ggdb -Wall `libnet-config --defines` `libnet-config --libs` timestamp.c -o timestamp

А вот так собирает! Не понятно, в чем разница и что за ключи -ggdb -Wall???

Ответить | Правка | ^ к родителю #33 | Наверх | Cообщить модератору

23. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от pavlinux (ok) on 22-Фев-11, 17:50 
Вот кусок из ISC DHCP


#define DHCP_UDP_OVERHEAD       (20 + /* IP header */                   \
                                8)   /* UDP header */
#define DHCP_SNAME_LEN          64
#define DHCP_FILE_LEN           128
#define DHCP_FIXED_NON_UDP      236
#define DHCP_FIXED_LEN          (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
                                                /* Everything but options. */
#define BOOTP_MIN_LEN           300

#define DHCP_MTU_MAX            1500
#define DHCP_MTU_MIN            576

#define DHCP_MAX_OPTION_LEN     (DHCP_MTU_MAX - DHCP_FIXED_LEN)
#define DHCP_MIN_OPTION_LEN     (DHCP_MTU_MIN - DHCP_FIXED_LEN)

struct dhcp_packet {
        u_int8_t  op;                   /* 0: Message opcode/type */
        u_int8_t  htype;                /* 1: Hardware addr type (net/if_types.h) */
        u_int8_t  hlen;                 /* 2: Hardware addr length */
        u_int8_t  hops;                 /* 3: Number of relay agent hops from client */
        u_int32_t xid;                  /* 4: Transaction ID */
        u_int16_t secs;                 /* 8: Seconds since client started looking */
        u_int16_t flags;                /* 10: Flag bits */
        struct in_addr ciaddr;          /* 12: Client IP address (if already in use) */
        struct in_addr yiaddr;          /* 16: Client IP address */
        struct in_addr siaddr;          /* 18: IP address of next server to talk to */
        struct in_addr giaddr;          /* 20: DHCP relay agent IP address */
        unsigned char chaddr [16];      /* 24: Client hardware address */
        char sname [DHCP_SNAME_LEN];    /* 40: Server name */
        char file [DHCP_FILE_LEN];      /* 104: Boot filename */
        unsigned char options [DHCP_MAX_OPTION_LEN]; /* 212: Optional parameters (actual length dependent on MTU). */
};

Где
DHCP_MAX_OPTION_LEN == (DHCP_MTU_MAX - DHCP_FIXED_LEN) == 1500 - (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD) == 1500 - (236 + 28) == 1236


Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

35. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от sd email(??) on 22-Дек-16, 22:18 
код весь неправильный.

структура размещена неверно.
datagram с неправильным типом.

инициализация статики default

Ответить | Правка | ^ к родителю #23 | Наверх | Cообщить модератору

36. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от sd email(??) on 22-Дек-16, 22:19 
> код весь неправильный.
> структура размещена неверно.
> datagram с неправильным типом.
> инициализация статики default

ip. tcp выложи для полного кода-то

Ответить | Правка | ^ к родителю #35 | Наверх | Cообщить модератору

37. "Проблема с подсчетом контрольной суммы TCP/UDP-заголовков"  +/
Сообщение от sd email(??) on 22-Дек-16, 22:22 
>> код весь неправильный.
>> структура размещена неверно.
>> datagram с неправильным типом.
>> инициализация статики default
> ip. tcp выложи для полного кода-то

htons правильно отрабатывает в рамках текущего примера. используется ntohs

Ответить | Правка | ^ к родителю #36 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру