簡體   English   中英

嘗試在C中發送數據包時,TCP校驗和不正確

[英]TCP checksum is incorrect when trying to send packet in C

我正在嘗試通過C中的RAW套接字發送TCP SYN數據包(我知道這不是最簡單的事情,但我有學術理由這樣做)。

當我檢查傳出數據包時,每個字段都很好,但只有一個:TCP校驗和。 確實,Wireshark告訴我這是不正確的。 在下面的代碼中,您可以看到我如何構建數據包(IP頭被省略了,因為它們看起來還可以)。

#define MINIMUM_TCP_HEADER_LENGTH 20
#define DEFAULT_TCP_WINDOW 32767

// [... Code that sets the IP headers ...]

struct tcphdr * tcpHeaders = (struct tcphdr *) (packetBuffer + IPHeaderLength);

tcpHeaders->source = htons(srcPort_16);
tcpHeaders->dest = htons(dstPort_16);
tcpHeaders->seq = htonl(tcpSeq_32);
tcpHeaders->ack_seq = 0;
tcpHeaders->doff = (MINIMUM_TCP_HEADER_LENGTH / 4);
tcpHeaders->res1 = 0;
tcpHeaders->res2 = 0;
tcpHeaders->syn = 1;
tcpHeaders->ack = 0;
tcpHeaders->fin = 0;
tcpHeaders->psh = 0;
tcpHeaders->urg = 0;
tcpHeaders->rst = 0;
tcpHeaders->window = htons(DEFAULT_TCP_WINDOW);
tcpHeaders->check = 0x0;
tcpHeaders->urg_ptr = 0x0;

//Sets the data
uint8_t * tcdData = ((uint8_t*) tcpHeaders + MINIMUM_TCP_HEADER_LENGTH);
memcpy(tcdData, message, strlen(message));

//Compute TCP checksum over the pseudo TCP header
uint8_t * pseudo = pseudoBuffer;
memset(pseudo, 0, DEFAULT_BUFFER_SIZE);
memcpy(pseudo, &((ipHeaders->ip_src).s_addr), 4);
pseudo += 4;
memcpy(pseudo, &((ipHeaders->ip_dst).s_addr), 4);
pseudo += 4;
memset(pseudo++, 0, 1);
memset(pseudo++, IPPROTO_TCP, 1);
uint16_t tcpSegmentLength = htons(MINIMUM_TCP_HEADER_LENGTH + (uint32_t) strlen(message));
memcpy(pseudo, &tcpSegmentLength, 2);
pseudo += 2;

//Append the TCP headers and data to the pseudo header
memcpy(pseudo, tcpHeaders, MINIMUM_TCP_HEADER_LENGTH + strlen(attentionMessage));
pseudo += MINIMUM_TCP_HEADER_LENGTH + strlen(attentionMessage);

//Compute checksum
int pseudoBufferLength = pseudo - pseudoBuffer;
tcpHeaders->check = calculateInternetChecksum((uint16_t*) pseudoBuffer, pseudoBufferLength);

//[... Code that proceed to send the packet ...]

值得注意的是,兩個“ packetBuffer”都使用memset填充了零(就像“ pseudo”一樣),並且“ message”是常規字符串。

這是計算校驗和的函數:

uint16_t onesComplementAddition(uint16_t *buff, unsigned int nbytes) {
    if(buff == 0 || nbytes == 0)
        return 0;

    uint32_t sum = 0;
    for (; nbytes > 1; nbytes -= 2)
        sum += *buff++;

    if (nbytes == 1)
        sum += *(uint8_t*) buff;

    sum  = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);

    return sum;
}

uint16_t calculateInternetChecksum(uint16_t *buff, unsigned int nbytes) {
    return ~(onesComplementAddition(buff, nbytes));
}

Wireshark建議這可能是由於“ TCP校驗和卸載”引起的,但我對此表示懷疑,因為我沒有從所探測的計算機收到任何響應(即使我知道應該這樣做)。

有誰知道為什么TCP校驗和不正確?

提前致謝。

抱歉,這是問問題實際上給我答案的那一次。

如果我正確理解了文檔,則在使用RAW套接字時,僅當“源”字段為0時,內核才會將IP源地址替換為發送接口的地址( http://man7.org/linux/man- pages / man7 / raw.7.html#DESCRIPTION )。

當我使用該功能時,我通過IP源為0的TCP偽頭計算了校驗和。這顯然不起作用。

如果有人試圖解決我的問題,謝謝。

暫無
暫無

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

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