首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Libnet TCP校验和错误

Libnet TCP校验和错误
EN

Stack Overflow用户
提问于 2011-10-24 12:24:18
回答 1查看 490关注 0票数 2

我正在尝试使用libnet库构建一个TCP包。我使用'0'自动计算libnet_build_tcp函数中的校验和值。然而,似乎校验和在计算时忽略了pseudo-header,由于校验和错误而导致无用的数据包。有人知道怎么解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-31 09:13:21

就我在代码中所看到的,只要您还没有使用过libnet_toggle_checksum(l, ptag, 1);,那么您在libnet_build_tcp()sum参数中的0应该会导致它通过调用libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM)来自动计算校验和。

我真的不能告诉你如何解决它,但既然你是一个构建数据包的人,也许你可以选择创建自己的校验和?

TCP伪报头是一个12字节的字段,包含每个都是4字节的源和目的地IP地址、2个字节并且总是被设置为0的保留字段、以及等于TCP报头的大小+有效载荷长度的4字节TCP段长度。

你可以创建类似这样的东西:

首先创建您的变量:

代码语言:javascript
复制
int bytesRead;
int pseudoHeaderLength;
int payloadLength;
int tcpHdrLength;
int tcpSegmentLength;
int ipHdrLength;
int headerLengths;
int ethIPHdrLengths;

struct ethhdr *ethHdr;
struct iphdr *ipHdr;
struct tcphdr *tcpHdr;

u_int8_t *pkt_data;
u_int8_t pseudoHeader[12];
u_int8_t packetBuffer[1600];
u_int16_t newChecksum;

然后创建实际的函数,其中b->len是数据包的总大小(只需将所有报头+有效负载相加,得到总大小),您只需将报头和数据memcpy到pkt_data:

代码语言:javascript
复制
ethHdr = (struct ethhdr*)pkt_data;
ipHdr = (struct iphdr*)(pkt_data + ETH_HLEN);

ipHdrLength = ipHdr->ihl * 4;

ethIPHdrLengths = ETH_HLEN + ipHdrLength;

tcpHdr = (struct tcphdr*)(pkt_data + ethIPHdrLengths);

tcpHdrLength = tcpHdr->doff * 4;

headerLengths = ethIPHdrLengths + tcpHdrLength;

payloadLength = b->len - headerLengths;

tcpSegmentLength = tcpHdrLength + payloadLength;

pseudoHeaderLength = tcpSegmentLength + 12;

pseudoHeader[0] = pkt_data[30];
pseudoHeader[1] = pkt_data[31];
pseudoHeader[2] = pkt_data[32];
pseudoHeader[3] = pkt_data[33];
pseudoHeader[4] = pkt_data[26];
pseudoHeader[5] = pkt_data[27];
pseudoHeader[6] = pkt_data[28];
pseudoHeader[7] = pkt_data[29];
pseudoHeader[8] = 0x00;
pseudoHeader[9] = 0x06;
pseudoHeader[10] = (tcpSegmentLength >> 8) & 0xFF;
pseudoHeader[11] = tcpSegmentLength & 0xFF;

bytesRead = 0;

for(i = 0; i < 12; i++) {
    packetBuffer[bytesRead] = pseudoHeader[i];
    bytesRead++;
}

for(i = ethIPHdrLengths; i < headerLengths; i++) {
    packetBuffer[bytesRead] = pkt_data[i];
    bytesRead++;
}

for(i = b->len - payloadLength; i < b->len; i++) {
    packetBuffer[bytesRead] = pkt_data[i];
    bytesRead++;
}

newChecksum = checksum((uint16_t *)packetBuffer, pseudoHeaderLength);

并且只需使用https://www.rfc-editor.org/rfc/rfc1071提供的校验和函数来计算缓冲区上的校验和:

代码语言:javascript
复制
uint16_t checksum(uint16_t *addr, int len)
{

int count = len;
register uint32_t sum = 0;
uint16_t answer = 0;

while (count > 1) {
    sum += *(addr++);
    count -= 2;
}

if (count > 0) {
    sum += *(uint8_t *) addr;
}

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

answer = ~sum;

return (answer);
}

我在现实环境中使用它来计算每秒500万次的校验和。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7871285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档