подсчёт контрольной суммы tcp заголовка

Тема в разделе "WASM.NETWORKS", создана пользователем featurelles, 5 сен 2009.

  1. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Добрый день, проблема заключается в следующем. ( первая проблема, не нашёл на форуме аналогичную тему, а вторая -> )
    Никак не могу правильно высчитать контрольную сумму протокола транспортного уровня. (tcp, udp)
    вот код

    struct pseudo_tcp_hdr //заполняем псевдо tcp заголовок для подсчёта контрольной суммы tcp пакета
    {
    __be32 saddr; // порт отправителя до подсчёта контрольной суммы применяем htons(saddr)
    __be32 daddr; // порт получуталя до подсчёта контрольной суммы применяем htons(daddr)
    short int num; // нули
    short int protocol; // идентификатор протокола //IPPROTO_TCP
    int tcp_size; // размер tcp пакета + данные (не больше 1500 байт)

    } pseudo_tcp_hdr, *pseudo_tcp_hdr_ptr;


    __be32 saddr ; // равен числовому значению размером в 4байта, преобразованному из ascii "22.22.22.22"
    __be32 daddr ; // равен числовому значению размером в 4байта, преобразованному из ascii "12.21.12.21"

    unsigned short checksum( unsigned short *tcp, int tcp_len, unsigned short * pseudo_tcp, int pseudo_tcp_len) // вычисление контрольной суммы
    {
    unsigned short result;
    unsigned int sum = 0;

    while ( tcp_len > 1) // просчитываем tcp заголовок
    {
    sum += *tcp++;
    tcp_len -= 2;
    }

    if ( tcp_len == 1 )
    sum += *(unsigned char*) tcp;

    while ( pseudo_tcp > 1) // просчитываем псевдозаголовок
    {
    sum += *pseudo_tcp++;
    pseudo_tcp_len -= 2;
    }

    if ( pseudo_tcp_len == 1 )
    sum += *(unsigned char*) pseudo_tcp;


    sum = ( sum >> 16 ) + ( sum & 0xffff );
    sum += ( sum >> 16 );
    result =~sum; // инверсия
    return result;

    }




    unsigned char *payload_ptr; // данные
    payload_ptr = kmalloc( 1500-sizeof(struct tcphdr), GFP_ATOMIC ); // пакет tcp заголовка не должен превышать размера в 1500 байт (tcp заголовок + данные)
    struct tcphdr *tcphdr_ptr; // указатель на tcp заголовок
    tcphdr_ptr = kmalloc( sizeof(struct tcphdr), GFP_ATOMIC );
    struct pseudo_tcp_hdr *pseudo_tcp_hdr_ptr; // указатель на псевдо заголовок tcp
    pseudo_tcp_hdr_ptr = kmalloc( sizeof(struct pseudo_tcp_hdr), GFP_ATOMIC );

    memset(payload_ptr, 'A', 1500-sizeof(struct tcphdr)); // заполняем память данных буквой 'A' для теста
    /* Заполняем псевдо заголовок */
    pseudo_tcp_hdr_ptr->saddr = saddr ; // IP адресс отправителя (без htonl )
    pseudo_tcp_hdr_ptr->daddr = daddr ; // IP адресс назначения (без htonl )
    short int num = 0;
    pseudo_tcp_hdr_ptr->protocol = IPPROTO_TCP ; // идентификатор протокола
    pseudo_tcp_hdr_ptr->udp_size = 1500 ; // размер tcp пакета

    /* Заполняем tcp заголовок */
    tcphdr_ptr->source = htons(101) ; // исходный порт от 1 до 65535
    tcphdr_ptr->dest = htons(100) ; // порт назначения
    tcphdr_ptr->seq = 1; // любые числа для теста
    tcphdr_ptr->ack_seq = 100;// любые числа для теста
    tcphdr_ptr->check = checksum(tcphdr_ptr, sizeof(struct tcphdr), pseudo_tcp_hdr_ptr, sizeof(struct pseudo_tcp_hdr)); // какбы вычислили контрольную сумму, но она не верна)
    // потом отправляем пакетик..

    kfree(payload_ptr);
    kfree(tcphdr_ptr);
    kfree(pseudo_tcp_hdr_ptr);


    Код представил коротенько, для экономии места.
    Давайте по порядку, где ошибки... где не верно привожу байты к сетевому порядку, что не учитываю при подсчёте контрольной суммы.. правильно ли
    передаю адреса структур tcp и псевдо tcp.... верно ли, что пакет tcp заголовка не должен превышать размера в 1500 байт (tcp заголовок + данные)...
    И остальные замечания....
     
  2. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Прошло 22 часа, после данного поста.
    А народу ответить лень... 100% все сталкивались с подсчётом контрольной суммы. (хоть и на прикладном уровне, но отличий, кажется НОЛЬ от ядра)
     
  3. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.568
    Адрес:
    Russia
    featurelles
    Вообще процедура подсчета CRC ничем таким не выделяется. В книге Олифера был дан пример подсчета контрольной суммы.
    Код (Text):
    1. //
    2. // Function: checksum
    3. //
    4. // Description:
    5. //    This function calculates the 16-bit one's complement sum
    6. //    for the supplied buffer
    7. //
    8. USHORT checksum(USHORT *buffer, int size)
    9. {
    10.     unsigned long cksum=0;
    11.  
    12.     while (size > 1)
    13.     {
    14.         cksum += *buffer++;
    15.         size  -= sizeof(USHORT);  
    16.     }
    17.     if (size)
    18.     {
    19.         cksum += *(UCHAR*)buffer;  
    20.     }
    21.     cksum = (cksum >> 16) + (cksum & 0xffff);
    22.     cksum += (cksum >>16);
    23.  
    24.     return (USHORT)(~cksum);
    25. }
    Это было в 14 уроке. Читайте.
     
  4. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.568
    Адрес:
    Russia
    Ах да, чексумма считается для всего пакета. То есть если это пакет UDP то мы имеем: IPhdr + UDPhdr + Msg(Payload) (если в кратце). В книге более подробно описан этот момент:

    Код (Text):
    1.  iUdpChecksumSize = 0;
    2.     ptr = buf;
    3.     ZeroMemory(buf, MAX_PACKET);
    4.  
    5.     memcpy(ptr, &ipHdr.ip_srcaddr,  sizeof(ipHdr.ip_srcaddr));  
    6.     ptr += sizeof(ipHdr.ip_srcaddr);
    7.     iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);
    8.  
    9.     memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr));
    10.     ptr += sizeof(ipHdr.ip_destaddr);
    11.     iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);
    12.  
    13.     ptr++;
    14.     iUdpChecksumSize += 1;
    15.  
    16.     memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol));
    17.     ptr += sizeof(ipHdr.ip_protocol);
    18.     iUdpChecksumSize += sizeof(ipHdr.ip_protocol);
    19.  
    20.     memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length));
    21.     ptr += sizeof(udpHdr.udp_length);
    22.     iUdpChecksumSize += sizeof(udpHdr.udp_length);
    23.    
    24.     memcpy(ptr, &udpHdr, sizeof(udpHdr));
    25.     ptr += sizeof(udpHdr);
    26.     iUdpChecksumSize += sizeof(udpHdr);
    27.  
    28.     for(i = 0; i < strlen(strMessage); i++, ptr++)
    29.         *ptr = strMessage[i];
    30.     iUdpChecksumSize += strlen(strMessage);
    31.  
    32.     cksum = checksum((USHORT *)buf, iUdpChecksumSize);
    33.     udpHdr.udp_checksum = cksum;
     
  5. o14189

    o14189 New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2009
    Сообщения:
    320
    вобще исходников в сети куча. код из первого поста не разбирал, но предположительно, возможно не учтен какой-либо из заголовков, либо не учтено то, что сумма считается для данных выровненных на границу слова

    считать можно к примеру так
    Код (Text):
    1. UINT16
    2. TcpCalculateChecksum(
    3.     IN PPACKET_CONTEXT pPacketCtx
    4.     )
    5. {
    6.     TCP_PSEUDO_HEADER   TcpPseudoHeader = {0};
    7.     UINT8*              pTcpData        = (UINT8*)pPacketCtx->TcpHeader;
    8.     UINT16              TcpDataSize     = (UINT16)pPacketCtx->TcpPacketLength;
    9.     UINT16              Padding         = 0;
    10.     UINT32              Checksum        = 0;
    11.     INT16               i               = 0;
    12.  
    13.     KdPrintEx(DBG_TRACE, "==> "__FUNCTION__"\n");
    14.  
    15.     TcpPseudoHeader.SrcIp = pPacketCtx->IpHeader->SrcAddr;
    16.     TcpPseudoHeader.DstIp = pPacketCtx->IpHeader->DstAddr;
    17.     TcpPseudoHeader.Reserved0_0 = 0;
    18.     TcpPseudoHeader.Protocol = IP_PROTOCOL_TYPE_TCP;
    19.     TcpPseudoHeader.Length = ntohs(pPacketCtx->TcpPacketLength);
    20.    
    21.     if(TcpDataSize&1)
    22.         Checksum = (UINT16)pTcpData[TcpDataSize-1];
    23.  
    24.     for(i = 0; i < sizeof(TcpPseudoHeader)>>1; i++)
    25.     {
    26.         KdPrintEx(
    27.             DBG_TRACE,
    28.             "TCP pseudo header [%02d] = %.04X\n",
    29.             i,
    30.             ((UINT16 *)&TcpPseudoHeader)[i]
    31.             );
    32.  
    33.         Checksum += ((UINT16 *)&TcpPseudoHeader)[i];
    34.  
    35.         KdPrintEx(
    36.             DBG_TRACE,
    37.             "(%.08X)\n",
    38.             Checksum
    39.             );
    40.     }
    41.    
    42.     for(i = 0; i < TcpDataSize>>1; i++)
    43.     {
    44.        
    45.         KdPrintEx(
    46.             DBG_TRACE,
    47.             "TCP Data [%02d] = %.04X\n",
    48.             i,
    49.             ((UINT16 *)pTcpData)[i]
    50.             );
    51.        
    52.  
    53.         Checksum += ((UINT16 *)pTcpData)[i];
    54.  
    55.         KdPrintEx(
    56.             DBG_TRACE,
    57.             "(%.08X)\n",
    58.             Checksum
    59.             );
    60.     }
    61.    
    62.     KdPrintEx(
    63.         DBG_TRACE,
    64.         "Checksum without carries = %.08X\n",
    65.         Checksum
    66.         );
    67.  
    68.     while(Checksum>>16)
    69.         Checksum = (Checksum>>16)+(Checksum&0xFFFF);
    70.    
    71.     KdPrintEx(
    72.         DBG_TRACE,
    73.         "Checksum with carries = %.08X\n",
    74.         Checksum
    75.         );
    76.    
    77.     Checksum =~ (Checksum);
    78.    
    79.     KdPrintEx(
    80.         DBG_INFO,
    81.         "Checksum calculated = %.04X\n",
    82.         (UINT16)Checksum
    83.         );
    84.    
    85.     KdPrintEx(DBG_TRACE, "<== "__FUNCTION__"\n");
    86.  
    87.     return (UINT16)Checksum;
    88. }
     
  6. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Всё-же никак не могу найти, где валяются грабли..
    Проверяю работу через wireshark , в большинстве(забавное слово, ведь все пакеты абсолютно одинаковые у меня) пакетов пишет bogus TCP header length
    что это за ошибка такая? точнее как её поправить?
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    featurelles
    Не понял почему выделяешь память частями, для заголовков и данных. Ещё в pseudo_tcp, длину надо переводить в сетевой порядок байт.

    Вот клиентик, корректно передающий SYN вместе с данными:
    Код (Text):
    1. #include <winsock2.h>
    2. #include <windows.h>
    3. #include <iostream>
    4.  
    5. #define IP_OPTIONS     1 /* set/get IP options */
    6. #define IP_HDRINCL     2 /* header is included with data */
    7.  
    8. #pragma pack(push, 1)
    9. struct ip // Структура заголовка IP
    10. {
    11.     BYTE ip_verlen; // Version and header length
    12.     BYTE ip_tos; // Type of service
    13.     WORD ip_len; // Total packet length
    14.     WORD ip_id; // Datagram identification
    15.     WORD ip_fragoff; // Fragment offset
    16.     BYTE ip_ttl; // Time to live
    17.     BYTE ip_proto; // Protocol
    18.     WORD ip_chksum; // Checksum
    19.     IN_ADDR ip_src_addr; // Source address
    20.     IN_ADDR ip_dst_addr; // Destination address
    21. };
    22.  
    23. struct tcp
    24. {
    25.     u_short src_port;
    26.     u_short dst_port;
    27.     DWORD sequence_number;
    28.     DWORD acknowledgment_number;
    29.     unsigned char th_x2:4, th_off:4;
    30.     unsigned char th_flags;
    31.     u_short window; //
    32.     u_short checksum;
    33.     u_short urgent_pointer;
    34.     //DWORD options_padding;
    35. };
    36.  
    37. struct pseudo_tcp
    38. {
    39.     IN_ADDR src_addr;
    40.     IN_ADDR dst_addr;
    41.     char reserved;
    42.     char protocol;
    43.     u_short tcp_len;
    44. };
    45. #pragma pack(pop)
    46.  
    47. inline u_short in_cksum(u_short *addr, int len)
    48. {
    49.     register int nleft = len;
    50.     register u_short *w = addr;
    51.     register int sum = 0;
    52.     u_short answer = 0;
    53.  
    54.      /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
    55.       * sequential 16 bit words to it, and at the end, fold back all the
    56.       * carry bits from the top 16 bits into the lower 16 bits. */
    57.  
    58.      while (nleft > 1)  {
    59.          sum += *w++;
    60.          nleft -= 2;
    61.      }
    62.  
    63.      /* mop up an odd byte, if necessary */
    64.      if (nleft == 1) {
    65.          *(u_char *)(&answer) = *(u_char *) w;
    66.          sum += answer;
    67.      }
    68.  
    69.      /* add back carry outs from top 16 bits to low 16 bits */
    70.      sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
    71.      sum += (sum >> 16);                /* add carry */
    72.      answer = ~sum;                     /* truncate to 16 bits */
    73.      return(answer);
    74. }
    75.  
    76.  
    77. int main (int argc, char* argv[])
    78. {
    79.     if (argc<3)
    80.     {
    81.         std::cout<<"use: name_prog <address> <port>"<<std::endl;
    82.         return 1;
    83.     }
    84.  
    85.     WSADATA wsa;
    86.     if (WSAStartup(MAKEWORD(2, 2), &wsa))
    87.     {
    88.         std::cout<<"WSAStartup error"<<std::endl;
    89.         return 1;
    90.     }
    91.  
    92.     SOCKET hSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    93.     if (INVALID_SOCKET==hSocket)
    94.     {
    95.         std::cout<<"socket error"<<std::endl;
    96.         WSACleanup();
    97.         return 1;
    98.     }
    99.  
    100.     char buff[256];
    101.     memset(buff, 0, sizeof(buff));
    102.     ip *pIp = (ip*)buff;
    103.     pIp->ip_verlen = 0x45;
    104.     pIp->ip_tos = 0;
    105.     pIp->ip_len = sizeof(buff);//sizeof (struct ip) + sizeof (struct tcp);
    106.     pIp->ip_id = htonl(54321);
    107.     pIp->ip_fragoff = 0;
    108.     pIp->ip_ttl = 255;
    109.     pIp->ip_proto = 6;
    110.     pIp->ip_chksum = 0;
    111.     pIp->ip_src_addr.S_un.S_addr = inet_addr("127.0.0.1");
    112.     pIp->ip_dst_addr.S_un.S_addr = inet_addr(argv[1]);
    113.     pIp->ip_chksum = 0;
    114.  
    115.     tcp *pTcp = (tcp*)(buff+sizeof(ip));
    116.     pTcp->src_port = htons(12345);
    117.     pTcp->dst_port = htons(atoi(argv[2]));
    118.     pTcp->sequence_number = 0;
    119.     pTcp->acknowledgment_number = 0;
    120.     pTcp->th_x2 = 0;
    121.     pTcp->th_off = 5;
    122.     pTcp->th_flags = 2; //TH_SYN;
    123.     pTcp->window = htons(0xffff);
    124.     pTcp->checksum = 0;
    125.     pTcp->urgent_pointer = 0;
    126.     pTcp->checksum =0;
    127.  
    128.     char* pData = buff+sizeof(ip) + sizeof(tcp);
    129.  
    130.     strcpy(pData, "Hello sailor!");
    131.  
    132.     char buff2[512];
    133.     pseudo_tcp *pPseudo_tcp = (pseudo_tcp*)buff2;
    134.     pPseudo_tcp->src_addr = pIp->ip_src_addr;
    135.     pPseudo_tcp->dst_addr = pIp->ip_dst_addr;
    136.     pPseudo_tcp->reserved = 0;
    137.     pPseudo_tcp->protocol = pIp->ip_proto;
    138.     int len = sizeof(buff)+sizeof(pseudo_tcp) - sizeof(ip);
    139.     pPseudo_tcp->tcp_len = htons(len-sizeof(pseudo_tcp));
    140.     memcpy((buff2+sizeof(pseudo_tcp)), pTcp, len);
    141.     pTcp->checksum = in_cksum((unsigned short*)pPseudo_tcp, len);
    142.  
    143.     int one = 1;
    144.         const int *val = &one;
    145.         if (setsockopt (hSocket, IPPROTO_IP, IP_HDRINCL, (const char*)val, sizeof (one)) < 0)
    146.             printf ("Warning: Cannot set HDRINCL!\n");
    147.  
    148.     sockaddr_in sin;
    149.     sin.sin_family = AF_INET;
    150.     sin.sin_port =  htons(atoi(argv[2]));
    151.     sin.sin_addr.s_addr = inet_addr (argv[1]);
    152.     memset(&sin.sin_zero, 0, sizeof(sin.sin_zero));
    153.  
    154.     if (SOCKET_ERROR==sendto (hSocket, buff, pIp->ip_len, 0, (const sockaddr*)&sin,
    155.                                                sizeof(sin)))
    156.     {
    157.         std::cout<<WSAGetLastError()<<std::endl;
    158.     }
    159.  
    160.     WSACleanup();
    161. }
     
  8. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Всю ночь просидел, искал,что за ХЗ твориться. ( при каждом запуске проги, контрольная сумма у пакетов tcp была разной, флаги от балды проставлялись. )
    Как выяснилось, была модификация данных при отправки пакета в сетевуху. ( многие моменты исправил, и теперь комп шлёт в инет стабильно правильные данные. )
    Но одного не сделал. Всёравно при отправке пакета в сеть, снифер показывает
    bogus TCP header length ( выставлен в 0 )

    Где? кем проставляется header length ?!

    Вообще ОООЧЕНЬ прошу посодействовать, просмотреть мой код. (я его очень хорошо прокомментировал) Я в упор не вижу ошибки. (100 раз смотрел, не увидел...)

    unsigned short checksum( unsigned short *addr, int len ) // вычисление контрольной суммы Мона не проверять, это просто для полноты кода
    {
    unsigned short result;
    unsigned int sum = 0;

    while ( len > 1)
    {
    sum += *addr++;
    len -= 2;
    }

    if ( len == 1 )
    sum += *(unsigned char*) addr;

    sum = ( sum >> 16 ) + ( sum & 0xffff );
    sum += ( sum >> 16 );
    result =~sum; // инверсия
    return result;
    }




    /* переменные участвующие в подсчёте */
    struct pseudo_tcp_hdr //заполняем псевдо tcp заголовок для подсчёта контрольной суммы tcp пакета
    {
    __be32 saddr;
    __be32 daddr;
    short int num; // нули
    short int protocol; // идентификатор протокола
    int tcp_size; // размер tcp пакета + данные

    } pseudo_tcp_hdr, *pseudo_tcp_hdr_ptr;

    saddr ; // содержит адрес отправителя ( кажется в сетевом порядке байт, важно ли это? )
    daddr ; // содержит адрес получателя ( кажется в сетевом порядке байт,важно ли это? )

    struct tcphdr *tcphdr_ptr; // указатель на TCP заголовок
    tcphdr_ptr = kmalloc( sizeof(struct tcphdr), GFP_ATOMIC ); // выделели память для TCP заголовка
    unsigned char *payload; // указатель на отсылаемые данные
    unsigned long len = 1500-sizeof(struct tcphdr); // длинна отсылаемых данных
    payload = kmalloc( len, GFP_ATOMIC ); // выдели память для отсылаемых данных
    memset(payload, 0, len ); // заполнили payload нулями
    struct pseudo_tcp_hdr *pseudo_tcp_hdr_ptr; // указатель на псевдозаголовок TCP
    pseudo_tcp_hdr_ptr = kmalloc(sizeof(struct pseudo_tcp_hdr), GFP_ATOMIC); //выделили память для псевдозаголовка
    unsigned char *transport_check_ptr; // указатель на буфер, который будет содержать псевдо tcp заголовок, tcp заголовок, и данные отправки для подсчёта контрольной суммы
    transport_check_ptr = kmalloc( sizeof(struct tcphdr)+ sizeof(struct pseudo_tcp_hdr) + len , GFP_ATOMIC); // выделили место

    /* сверху я показал действующие переменные, а теперь собственно сам код */

    tcphdr_ptr->source = htons(100) ; // исходный порт от 1 до 65535
    tcphdr_ptr->dest = htons(101) ; // порт назначения
    tcphdr_ptr->check = 0; // вычисление контрольной суммы
    tcphdr_ptr->seq = 0;
    tcphdr_ptr->ack_seq = 0;
    tcphdr_ptr->window = htons(0xffff)
    ;

    pseudo_tcp_hdr_ptr->saddr = saddr ;//адрес отправителя
    pseudo_tcp_hdr_ptr->daddr = daddr ;
    pseudo_tcp_hdr_ptr->protocol = IPPROTO_TCP ; // идентификатор протокола
    pseudo_tcp_hdr_ptr->tcp_size = htons(len+sizeof(struct tcphdr)) ; // размер tcp пакета (tcp заголовок и данные)

    /* заполняем буфер данными , чтоб вычеслить контрольную сумму */
    memcpy( transport_check_ptr, tcphdr_ptr, sizeof(struct tcphdr) ); // копируем TCP заголовок
    memcpy( transport_check_ptr+sizeof(struct pseudo_tcp_hdr), pseudo_tcp_hdr_ptr, sizeof(struct pseudo_tcp_hdr) ); // копируем псевдозаголовок
    memcpy( transport_check_ptr+sizeof(struct pseudo_tcp_hdr)+sizeof(struct pseudo_tcp_hdr), payload, len); копируем данные для отправки


    /* Контрольная сумма равна */
    tcphdr_ptr->check = checksum( transport_check_ptr, sizeof(struct tcphdr)+ sizeof(struct pseudo_tcp_hdr) + len );

    /* отправляем в сеть и всё такое * =)

    Топчусь на одном месте, потому и прошу помочь. ( если тут ошибку не высмотрите , то буду её искать в других участках кода )
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Где выставляешь длину tcp заголовка? В моём предыдущий посте: tcp::th_off = 5 (длина в 32 битных словах)
     
  10. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Код (Text):
    1. struct tcphdr {
    2.     __be16  source;
    3.     __be16  dest;
    4.     __be32  seq;
    5.     __be32  ack_seq;
    6. #if defined(__LITTLE_ENDIAN_BITFIELD)
    7.     __u16   res1:4,
    8.         doff:4,
    9.         fin:1,
    10.         syn:1,
    11.         rst:1,
    12.         psh:1,
    13.         ack:1,
    14.         urg:1,
    15.         ece:1,
    16.         cwr:1;
    17. #elif defined(__BIG_ENDIAN_BITFIELD)
    18.     __u16   doff:4,
    19.         res1:4,
    20.         cwr:1,
    21.         ece:1,
    22.         urg:1,
    23.         ack:1,
    24.         psh:1,
    25.         rst:1,
    26.         syn:1,
    27.         fin:1;
    28. #else
    29. #error  "Adjust your <asm/byteorder.h> defines"
    30. #endif 
    31.     __be16  window;
    32.     __sum16 check;
    33.     __be16  urg_ptr;
    34. };
    Поставил tcphdr_ptr->doff = 5; теперь длину tcp пакета показывает верно, но checksum всёравно не верна. =(
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Я же дал корректный пример. Неужели сложно сделать аналогично(заполнить также все поля)?

    Ещё вот это я не понял:
    Код (Text):
    1. memcpy( transport_check_ptr, tcphdr_ptr, sizeof(struct tcphdr) ); // копируем TCP заголовок
    2. memcpy( transport_check_ptr+sizeof(struct pseudo_tcp_hdr), pseudo_tcp_hdr_ptr, sizeof(struct pseudo_tcp_hdr) ); // копируем псевдозаголовок
    Для чего копировать tcp_hdr, затем pseudo_tcp_hdr со смещением sizeof(struct pseudo_tcp_hdr)? У тебя копипаст что-ли?
     
  12. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Booster
    У меня есть оправдание, всю ночь не спал, голова уже трещит от сиденья за компом.
    Аналогичный код я конечно могу составить, и составлял и при отправлении пакетов, была не верна контрольная сумма. Затем опять этот аналогичный код изменял, и снова не верно и так много раз. Затем нашёл проблему номер 1, при отправлении пакета на сетевуху. Исправил её, и по новой код отлаживать и всё теже ошибки.
    А так как у меня нет 100% уверенности, что банальный код подсчёта tcp верен (приходится его проверять по 100 раз), Как Вы заметили в последнем посте копипаст сделал своё дело, и нашлась очередная ошибка. ( кстати подсчёт всё ещё не верен. )
    Перестаю народ мучать, сегодня вечером, на свежую голову, после сна, снова просмотрю код. Может чего найду.
    Кстати, Booster спасибо за быстрые и содержательные ответы.
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    featurelles
    Вначале должен быть pseudo_tcp_hdr и затем tcp_hdr.
     
  14. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Booster
    Ок, ещё раз спасибо.
    Ща поправлю.
     
  15. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Второй день сижу) никак не подсчитывается верная контрольная сумма.
    Пытаюсь высчитать контрольную сумму, принятого мной пакета!
    ПОЖАЛУЙСТА ПОСМОТРИТЕ КОД!!! я уже задолбался с ним =(

    unsigned char *data_ptr; // указатель на данные
    unsigned char *tail_ptr;
    struct iphdr *ip_ptr = NULL;
    struct tcphdr *tcp_ptr = NULL;
    unsigned short data_len; // длинна данных
    unsigned short tcp_len = 0;
    unsigned short *transport_check_ptr;
    ip_ptr = skb->network_header; // получаем заголовок ip пакета
    tcp_ptr = (char *)ip_ptr + (ip_ptr->ihl*4); // теперь указываем на TCP заголовок
    tcp_len = tcp_ptr->doff * 4; // размер TCP пакета

    data_len = (char *)tail_ptr - (char *)data_ptr; // количество байт в tcp пакете
    pseudo_tcp_ptr = kmalloc(sizeof(struct pseudo_tcp_hdr), GFP_ATOMIC);
    memset( pseudo_tcp_ptr, 0, sizeof(struct pseudo_tcp_hdr) );

    СТРУКТУРА псевдозаголовка tcp пакета, заполнена верно
    длинна псевдозаголовка установлена в htons(tcp_len + data_len)

    transport_check_ptr = kmalloc( tcp_len + sizeof(struct pseudo_tcp_hdr) + data_len , GFP_ATOMIC);

    //ВЫСЧИТАТЬ КОНТРОЛЬНУЮ СУММУ TCP заголовка
    memset( transport_check_ptr, 0, tcp_len + sizeof(struct pseudo_tcp_hdr) + data_len );
    memcpy( transport_check_ptr, pseudo_tcp_ptr, sizeof(struct pseudo_tcp_hdr) );
    memcpy( transport_check_ptr+sizeof(struct pseudo_tcp_hdr), tcp_ptr, tcp_len );
    memcpy( transport_check_ptr+sizeof(struct pseudo_tcp_hdr)+tcp_len, data_ptr, data_len);

    // функция checksum верная смотреть пост #8 в этой теме
    tcp_ptr->check = 0;
    tcp_ptr->check = checksum( (unsigned char *)transport_check_ptr, sizeof(struct pseudo_tcp_hdr)+tcp_len + data_len ); // вычисление контрольной суммы

    после этих действий Результат высчита checksum не верен!!!
    бьюсь два дня уже, в упор ошибки не вижу.
     
  16. o14189

    o14189 New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2009
    Сообщения:
    320
    какое отклониние обычно от верного результата?
    длина скорее всего не та, что нужно, пересчитывай например на калькуляторе
     
  17. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    а для чего это вообще ? Вот ищу инфу для написания ддос в ознакомительных целях, может ченибуть подкинете?
     
  18. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    lobzik
    Статей на эту тему, для прикладного уровня в инете...до жопы
     
  19. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    o14189
    Отклонение в результатах такое
    C28 верный
    9C1 не верный ( после моей функции )

    D32B верный
    42BD не верный

    CB37 верный
    BCAB не верный

    5B66 верный
    CAA3 не верный

    19E5 верный
    9FB9 не верный

    F1B8
    BC93

    Скорее всего это важно!
    Два отличия от формирования пакетов, которые описаны в самом начале темы.
    Первое, что пакет принят моим компом от кого-то и передан ядру от сетевого адаптера, таким(я так думаю) каким он был послан. Тоесть есть поля которые находятся в сетевом порядке байтов. (это проверено мной)
    Второе. То что принятый пакет содержит опции tcp_len = tcp_ptr->doff * 4;
    выходят такие данные, ip заголовок 20 байт, тотл лен в ip равна 60(в сетевом порядке байт),.. tcp_len = tcp_ptr->doff * 4 = 40, данные в пакете = 0..

    Сверял заголовки со снифером, всё точно! ( кстати, chekcsum ip заголовка высчитывается верно! по тому же алгоритму) .


    localhost klogd: Выводим полученный tcp заголовок (полностью совпадает с данными в снифере)
    localhost klogd: 0 50 a3 3f 76 46 8e b0 0 0 0 1 a0 12 16 a0 4a 28 0 0 2 4 5 b4 4 2 8 a dd 57 fa 34 0 2 6a 5b 1 3 3 0

    localhost klogd: Выводим pseudo_tcp_hdr (псевдозаголовок размером sizeof(struct pseudo_tcp_hdr) )
    localhost klogd: 4d dd 9f 9a 4d 25 c2 20 0 6 0 28 0

    Спустя некоторое время, обнаружил следующее
    Выводим transport_check_ptr после memset, заполненную нулями)
    localhost klogd: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    localhost klogd: Выводим transport_check_ptr после записи pseudo_tcp_hdr в transport_check_ptr
    localhost klogd: 4d dd 9f 9a 4d 25 c2 20 0 6 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    localhost klogd: Выводим transport_check_ptr после записи tcp_ptr ( memcpy( transport_check_ptr+sizeof(struct pseudo_tcp_hdr), tcp_ptr, tcp_len ); )
    localhost klogd: 4d dd 9f 9a 4d 25 c2 20 0 6 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 50 a3 3f 76 46 8e b0 0 0 0 1 a0 12 16 a0 4a 28 0 0 2 4 5 b4 4 2 8 a
    Откуда взялись эти нули????
    ну и далее передаётся указатель на эти данные 4d dd 9f 9a 4d 25 c2 20 0 6 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 50 a3 3f 76 46 8e b0 0 0 0 1 a0 12 16 a0 4a 28 0 0 2 4 5 b4 4 2 8 a в функцию check, где собственно и происходит не правильный подсчёт
     
  20. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    для полноты
    struct pseudo_tcp_hdr //заполняем псевдо tcp заголовок для подсчёта контрольной суммы tcp пакета
    {
    __be32 saddr;
    __be32 daddr;
    char num; // нули
    char protocol;
    unsigned short int tcp_size;
    } pseudo_tcp_hdr, *pseudo_tcp_hdr_ptr;