簡體   English   中英

IP和TCP標頭校驗和在C中計算

[英]IP and TCP header checksum calculate in c

我正在編寫一個簡單的程序來發送/接收TCP數據包,並將其合並到一個較大的項目中。 我卡在校驗和部分,在那里我計算出的數字與wireshark數字不匹配。

對於校驗和功能,我重新使用了Mike Muss的代碼,如下所示:

static int
in_cksum(u_short *addr, int len)
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

    /*
     * Our algorithm is simple, using a 32 bit accumulator (sum), we add
     * sequential 16 bit words to it, and at the end, fold back all the
     * carry bits from the top 16 bits into the lower 16 bits.
     */
    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }

    /* mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }

    /* add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
    sum += (sum >> 16);         /* add carry */
    answer = ~sum;              /* truncate to 16 bits */
    return(answer);
}

我收到一個數據包,並將其存儲在char緩沖區[2048]中。 為了獲得IP標頭,我這樣做:

struct iphdr* ip;
ip = (struct iphdr*) buffer;

從這里,我可以正確讀取信息,如ip-> protocol,ip-> saddr等,甚至可以打印出wireshark中顯示的正確校驗和。

printf("Print checksum = 0x%x\n",ntohs(ip->check));

然后我嘗試使用上面的函數計算校驗和並打印出來

printf("My calculated checksum =0x%x\n",in_cksum ((unsigned short*) ip, sizeof(struct iphdr)));

我得到的是“我的計算出的checksym = 0x0”,看來IP頭中沒有任何內容。 我想我可能無法正確傳遞in_cksum函數參數,但是我不確定如何解決或我的執行方式是否存在其他問題。

IP cksum問題已在下面解決。 但是,嘗試計算TCP校驗和時遇到類似的問題。 以下是我如何獲取tcp標頭:

tcp=(struct tcphdr*) (buffer+sizeof(struct iphdr);

之后,我可以再次讀取有關tcp標頭的正確信息,例如tcp-> source,tcp-> dest甚至tcp-> check

然后,我嘗試重新計算校驗和,如下所示:

tcp->check=0;
tcp->check=in_cksum((unsigned short*)tcp, ntohs(ip->tot_length)-(4*ip->ihl));

我在這里得到的結果與之前打印出的結果不同。 我認為我的問題可能是通過cksum函數傳遞的,但是我不確定如何解決它。

任何幫助將不勝感激。 先感謝您!

IP校驗和的計算中不得包含包含該校驗和的字段-應該對該字段使用零。 RFC 791開始

校驗和字段是標頭中所有16位字的一個補碼之和的16位一個補碼。 為了計算校驗和,校驗和字段的值為零。

我還沒有完成數學運算,但是我懷疑得到零是重新計算整個標頭的校驗和的預期結果,即,它導致計算出的總和自行抵消。

[我檢查了-Wikipedia同意: “如果沒有損壞,則將整個IP標頭(包括校驗和)相加的結果應為零” 因此,在驗證校驗和時,零實際上是正確的結果。

請注意,IP標頭只能是4個字節的倍數,因此,在這種特殊情況下,不需要填充代碼,盡管如果要計算其他數據的通用的“ 1”補碼校驗和,則很有用。

另外, 應該先傳遞4 * ip->ihl來解釋報頭中可能包含的任何IP選項,而不要傳遞sizeof(struct iphdr) ,首先要確保緩沖區中實際上至少有這么多字節。

總和+ =(總和>> 16); / *加進位/答案=〜sum; /截斷為16位* /

如果將進位加到低2個字節並將其取負。

顯然它將為零。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM