C Программирование контрольной суммы TCP - PullRequest
6 голосов
/ 13 января 2012

У меня были проблемы с выполнением контрольной суммы для TCP в течение нескольких дней.Я просмотрел много источников в Интернете, но ни один из примеров, которые я видел, не показывает, как сделать контрольную сумму TCP.Я также посмотрел документ RFC , и все еще у меня возникают проблемы:

Ниже приведен код, который я использую для генерации контрольной суммы:

unsigned short checksum(unsigned short * buffer, int bytes)
{
    unsigned long sum = 0;
    unsigned short answer = 0;
    int i = bytes;
    while(i>0)
    {
            sum+=*buffer;
            buffer+=1;
            i-=2;
    }
    sum = (sum >> 16) + (sum & htonl(0x0000ffff));
    sum += (sum >> 16);
    return ~sum;
}

Эта функцияработает для контрольной суммы IP.

Ниже приведена структура, которую я создал для своего заголовка TCP:

struct tcp_header
{
    unsigned short tcp_sprt;
    unsigned short tcp_dprt;
    unsigned int tcp_seq;
    unsigned int tcp_ack;
    unsigned char tcp_res:4;
    unsigned char tcp_off:4;
    unsigned char tcp_flags;
    unsigned short tcp_win;
    unsigned short tcp_csum;
    unsigned short tcp_urp;
};

Я использовал Wireshark для проверки этих пакетов, и единственная неправильная вещь - это контрольная сумма.

Наконец, вот структура псевдозаголовка, которую я загружаю с заголовком TCP и информацией из заголовка IP:

struct pseudoTcpHeader
{
    unsigned int ip_src;
    unsigned int ip_dst;
    unsigned char zero;//always zero
    unsigned char protocol;// = 6;//for tcp
    unsigned short tcp_len;
    struct tcp_header tcph;
};

Как только я загружаю эту структуру с правильной информацией, яиспользуйте функцию контрольной суммы всей структуры псевдозаголовка и присвойте контрольную сумму TCP этому значению.Вы видите что-то не так с тем, что я предоставил?Если проблема не в этом, это может быть неосторожная ошибка, которую я не вижу.

Ответы [ 4 ]

5 голосов
/ 13 января 2012

Я нашел довольно хороший пример в списке рассылки winpcap-users , который должен содержать комментарий Грега о данных нечетной длины и дать вам что-то для сравнения вашего кода.

USHORT CheckSum(USHORT *buffer, int size)
{
    unsigned long cksum=0;
    while(size >1)
    {
        cksum+=*buffer++;
        size -=sizeof(USHORT);
    }
    if(size)
        cksum += *(UCHAR*)buffer;

    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
    return (USHORT)(~cksum);
}
3 голосов
/ 13 января 2012

Я вижу несколько вещей:

  • Вы не учитываете данные нечетной длины, заполняя их нулями.
  • При чтении каждого необходимо учитывать сетевой порядок байтовСлово из пакета.
  • Использование htonl(0x0000ffff) кажется подозрительным.Почему вы конвертируете константу в сетевой порядок байтов, чтобы объединить ее с данными в host порядке байтов?
2 голосов
/ 13 января 2012

RFC 793 говорит: «Если сегмент содержит нечетное число октетов заголовка и текста для контрольной суммы, последний октет дополняется нулями справа, образуя 16-битное слово для целей контрольной суммы».Ваш код выше не обрабатывает этот случай.Я думаю, что условный цикл должен быть i> 1, а затем проверить i == 1 вне цикла и выполнить специальную обработку для последнего октета.

0 голосов
/ 10 июля 2018

Я тоже изо всех сил пытался найти код на языке c ++ / c, который его вычисляет, пока не нашел Как вычислить реализацию контрольной суммы IP / TCP / UDP - часть 2 - roman10 , и это сработало! Протестировано с проверкой Wireshark.

...