gpt4 book ai didi

c - TCP校验和C代码返回错误结果

转载 作者:可可西里 更新时间:2023-11-01 02:43:45 26 4
gpt4 key购买 nike

我得到一个很大的 TCP 校验和结果,而它本应为 0。我通过将 TCP psuedoheader 复制到数组的前 12 个字节,然后将 TCP header 和数据复制到接下来的几个字节来解决这个问题数组的字节,并将该数组及其长度传递给校验和函数。我无法弄清楚为什么校验和与正确值有很大不同(即其中一个数据包的 9180 本应为 0)。

这是我的 IP、TCP 和伪 TCP header :

typedef struct __attribute__((__packed__)) IPHeader {
#if __BYTE_ORDER__ == __LITTLE_ENDIAN__
uint8_t hdrLen:4;
uint8_t version:4;
#else
uint8_t version:4;
uint8_t hdrLen:4;
#endif
uint8_t TOS;
uint16_t totLen;
uint16_t id;
uint16_t offset;
#define DF 0x4
#define MF 0x2
#define OFF 0
uint8_t TTL;
uint8_t protocol;
uint16_t checksum;
struct in_addr srcIP;
struct in_addr destIP;
}IPHeader;

typedef struct __attribute__((__packed__)) TCPHeader {
uint16_t srcPort;
uint16_t destPort;
uint32_t seqNum;
uint32_t ackNum;
uint8_t offset:4;
uint8_t res:4;
uint8_t flags;
uint16_t window;
uint16_t checksum;
uint16_t urg;
}TCPHeader;

typedef struct __attribute__((__packed__)) TCPPseudo {
struct in_addr srcAddr;
struct in_addr destAddr;
uint8_t zeroes;
uint8_t protocol;
uint16_t len;
}TCPPseudo;

下面是我如何将数据复制到数组中:

IPHeader *iph
TCPPseudo ts;
TCPHeader *tcp;
u_char checkData[1000];
uint16_t checkLen = 0;
---
tcp = (TCPHeader *)(packet + ETHER_SIZE + iph->hdrLen * 4);
ts.srcAddr = iph->srcIP;
ts.destAddr = iph->destIP;
ts.zeroes = 0;
ts.protocol = iph->protocol;
checkLen = ntohs(iph->totLen) - (iph->hdrLen * 4);
ts.len = checkLen;
memcpy(checkData, &ts, 12);
memcpy(checkData + 12, tcp, checkLen);
getTCPInfo(tcp, iph, checkData, checkLen);
---
unsigned short checksum = in_cksum((unsigned short *)checkData, len + 12);
printf("\t\tChecksum: %d, (0x%x)", checksum, htons(tcp->checksum));

这是我计算校验和的方法:

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

/*
* 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);
}

最佳答案

您应该保存接收到的数据包的 TCP 校验和,然后在计算伪报头和 TCP 段的校验和之前,将 tcp header 中的校验和字段设置为零。然后将计算出的校验和与之前保存的值进行匹配。如果网络传输没有错误,两者应该相等。这样做

recvPktChkSum = tcp->checksum
tcp->checksum = 0;

同样在计算校验和之前你应该确保长度是网络字节顺序

ts.len = htons(checkLen);

之前

memcpy(checkData + 12, tcp, checkLen);

之后

checksum = in_cksum((unsigned short *)checkData, len + 12);

比较

if(htons(recvPktChkSum) == htons(checksum))
printf("checksum valid");

关于c - TCP校验和C代码返回错误结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21128066/

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