gpt4 book ai didi

c - 尝试在 C 中发送数据包时 TCP 校验和不正确

转载 作者:可可西里 更新时间:2023-11-01 02:46:12 24 4
gpt4 key购买 nike

我正在尝试通过 C 中的 RAW 套接字发送 TCP SYN 数据包(我知道这不是最简单的事情,但我有学术理由这样做)。

当我检查传出数据包时,每个字段都很好,但只有一个:TCP 校验和。事实上,Wireshark 告诉我这是不正确的。在下面的代码中,您可以看到我是如何构建数据包的(省略了 IP header ,因为它们似乎没问题)。

#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 ( http://man7.org/linux/man-pages/man7/raw.7.html#DESCRIPTION ) 时,内核才会将 IP 源地址替换为发送接口(interface)的地址。

当我使用该功能时,我通过 IP 源为 0 的 TCP 伪报头计算了我的校验和。这显然行不通。

如果有人试图解决我的问题,谢谢。

关于c - 尝试在 C 中发送数据包时 TCP 校验和不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41466810/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com