亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 3687 | 回復: 12
打印 上一主題 下一主題

[網絡] tcp 校驗問題 [復制鏈接]

論壇徽章:
1
天蝎座
日期:2015-03-09 10:14:22
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2015-06-18 09:54 |只看該作者 |倒序瀏覽
本帖最后由 Fart_King 于 2015-06-18 09:54 編輯


uint16_t checksum(void *buffer, uint32_t length)
{
        uint16_t *pAddr = (uint16_t *)buffer;
        uint32_t sum = 0;

        while (length > 1)
        {
                sum += *(uint16_t *)pAddr++;
                if (sum & 0x80000000)
                {
                        sum = (sum & 0xffff) + (sum >> 16);
                }
                length -= 2;
        }

        if (length > 1)
        {
                sum += *(uint8_t *)pAddr;
        }

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

        return ~sum;
}



void test_checksum(char *buf, PSDHEADER *psdHeader,unsigned char* calcBuf)
{
  
        struct ether_header *ethHdr = (struct ether_header*)buf;
        struct ip *ipHdr = (struct ip*)(buf + sizeof(struct ether_header));
        struct tcphdr *tcpHdr = (struct tcphdr*)(buf + sizeof(struct ether_header) + sizeof(struct ip));
  u_short ip_sum = 0;
  uint16_t tcp_check = 0;
        char *httpbuf = (char*)(buf + sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct tcphdr));
        //strcpy(httpbuf, request);
        int len = 0; //http + tcp len
        
  
        fprintf(stdout, "auto tcp->check = %d\n",  tcpHdr->check);
        ipHdr->ip_sum = 0;
        tcpHdr->check = 0;
        
        len = ntohs(ipHdr->ip_len)- ((ipHdr->ip_hl)&15)*4;
        fprintf(stdout, "ip len = %d http + tcp len = %d\n", ((ipHdr->ip_hl)&15)*4, len);
        memset(calcBuf, 0, sizeof(calcBuf));
        memcpy(calcBuf, (void*)ipHdr, sizeof(struct ip));
        
        
        ip_sum = checksum((uint16_t*)(buf + sizeof(struct ether_header)), sizeof(struct ip));
        
  
        
        
        psdHeader->saddr = (unsigned long)ipHdr->ip_src.s_addr;
        psdHeader->daddr = (unsigned long)ipHdr->ip_dst.s_addr;
        
        psdHeader->mbz   = 0;
        psdHeader->ptcl  = 0x06;
//        psdHeader->tcpl  = htons((u_short)(sizeof (struct tcphdr) + http_len));
        psdHeader->tcpl  = htons((u_short)(len));
        
        //tcpHdr->check        = CalcTCPSum((u_int16_t *)psdHeader, (u_int16_t *)tcpHdr,sizeof(struct tcphdr) + http_len);
        memset(calcBuf, 0, sizeof(calcBuf));
        memcpy(calcBuf, (void*)psdHeader, sizeof(PSDHEADER));
        memcpy(calcBuf + sizeof(PSDHEADER), (void*)tcpHdr, sizeof(struct tcphdr));
        //memcpy(calcBuf + sizeof(PSDHEADER), (void*)tcpHdr, len);
        memcpy(calcBuf + sizeof(PSDHEADER) + sizeof(struct tcphdr), (void*)httpbuf, len - sizeof(struct tcphdr));
        
        tcp_check = checksum((u_int16_t*)calcBuf, sizeof(PSDHEADER) + len); //
//        tcpHdr->check = tcp4_checksum (*ipHdr, *tcpHdr, (uint8_t *) httpbuf, http_len);
        
        
        fprintf(stdout, "tcp_check = %d\n",  tcp_check);
        
}  

這個函數(shù)是我用來測試tcp checksum是否正確的function。
參數(shù) buf 就是raw sock 接收的以太網幀 psdheader 是tcp 偽首部 。
為什么一旦tcp包中帶了數(shù)據(jù)tcp->check 就不正確了呢。求大神指點

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
2 [報告]
發(fā)表于 2015-06-18 22:15 |只看該作者
回復 1# Fart_King


    你的這個校驗算法有問題吧?從while跳出后,if那句肯定執(zhí)行不到,算法原意是如果是奇數(shù)個字節(jié),落單的那個字節(jié)也要加上去,廢話少說,網上另找的一段代碼,你看看,跟你的就不一樣了:
  1. USHORT checksum(USHORT *buffer,int size)  
  2. {  
  3.     unsigned long cksum=0;  
  4.     while(size>1)  
  5.     {  
  6.         cksum+=*buffer++;  
  7.         size-=sizeof(USHORT);  
  8.     }  
  9.     if(size)  
  10.     {  
  11.         cksum+=*(UCHAR *)buffer;  
  12.     }  
  13.     //將32位數(shù)轉換成16  
  14.     while (cksum>>16)  
  15.         cksum=(cksum>>16)+(cksum & 0xffff);  
  16.     return (USHORT) (~cksum);  
  17. }  
復制代碼

論壇徽章:
1
天蝎座
日期:2015-03-09 10:14:22
3 [報告]
發(fā)表于 2015-06-23 12:47 |只看該作者
回復 2# 羽劍天涯

這是應對自構造的包的函數(shù),當包比較大的時候會進入if
   

論壇徽章:
1
天蝎座
日期:2015-03-09 10:14:22
4 [報告]
發(fā)表于 2015-06-23 12:48 |只看該作者
所以這個函數(shù)應該沒有問題

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
5 [報告]
發(fā)表于 2015-06-23 12:59 |只看該作者
回復 4# Fart_King


    while 跳出的條件只有(length > 1)不滿足,此時怎么都不會進入if,請仔細看一下,或者舉個例子,while跳出后可以進入if。
    這個就是個IP、TCP等的標準校驗算法。

論壇徽章:
1
天蝎座
日期:2015-03-09 10:14:22
6 [報告]
發(fā)表于 2015-06-23 14:06 |只看該作者
回復 5# 羽劍天涯


                if (sum & 0x80000000)
                {
                        sum = (sum & 0xffff) + (sum >> 16);
                }

    如果發(fā)現(xiàn)整形最高位已經是1時,就把它先轉化成16bit數(shù)據(jù),這樣就不會溢出,導致計算錯誤。

論壇徽章:
1
天蝎座
日期:2015-03-09 10:14:22
7 [報告]
發(fā)表于 2015-06-23 14:07 |只看該作者
本帖最后由 Fart_King 于 2015-06-23 14:09 編輯

這個問題還是沒有解決,可能是這個函數(shù)的帶參問題,有沒有人能告知一下。
tcp 偽首部 + tcp首部 + data 計算出來的校驗和為何有時對有時錯呢..

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
8 [報告]
發(fā)表于 2015-06-23 14:49 |只看該作者
回復 7# Fart_King


    我真要暈到點了,大哥,有沒有仔細看我的發(fā)帖呢? 我是說你這個校驗算法寫得有問題,if那一句執(zhí)行不到,導致有可能算出來的校驗和是錯的,舉個簡單例子:
    例如:需要計算校驗和的數(shù)據(jù)是11個字節(jié)(checksum傳遞的length是11),那么while跳出時,length為1,此時不會執(zhí)行if,那么buffer中最后一個字節(jié)沒有加到sum中去,計算出來的sum就是錯的,你如果按照校驗的方法加起來,結果將不會是0。
    又如,需要計算校驗和的數(shù)據(jù)是10個字節(jié),那么if那句不執(zhí)行也沒關系,這樣算出來的sum就是對的。
    你可以試試,將每次計算校驗和的長度打印出來,看看正確與否是否跟數(shù)據(jù)長度的奇偶有關!

論壇徽章:
1
天蝎座
日期:2015-03-09 10:14:22
9 [報告]
發(fā)表于 2015-06-23 15:11 |只看該作者
回復 8# 羽劍天涯


   ..疏忽了,改過來之后tcp校驗和 還是會偶爾錯誤,帶http數(shù)據(jù)的校驗和計算有過經驗嗎?能否賜教一下

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
10 [報告]
發(fā)表于 2015-06-23 15:44 |只看該作者
回復 9# Fart_King


    不管是負載的http、https還是telnet等,都是基于tcp協(xié)議的,僅僅是使用的端口,和負載的內容格式不同罷了,TCP校驗和的算法是不變的,你這個問題問得比較大,你可以貼一些結果出來,比如原始數(shù)據(jù)是什么(tcpdump抓到的是什么,你程序中抓到的是什么),計算出來錯誤的校驗和是什么,然后我們再分析你這段代碼為什么會算錯。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP