[英]Libnet TCP checksum error
I am trying to build a TCP
packet using libnet library. 我正在尝试使用libnet库构建
TCP
数据包。 I use '0'
for autocomputation of checksum value in the libnet_build_tcp
function. 我在
libnet_build_tcp
函数中使用'0'
来自动计算校验和值。 However, it seems the checksum ignores the pseudo-header
when being computed resulting in a useless packet because of checksum error. 但是,由于校验和错误,校验和似乎在计算时会忽略
pseudo-header
,从而导致无用的数据包。 Does anyone know how to solve this? 有谁知道如何解决这个问题?
As far as I can see in the code, as long as you haven't used libnet_toggle_checksum(l, ptag, 1);
据我在代码中看到的,只要您还没有使用
libnet_toggle_checksum(l, ptag, 1);
your 0
in the sum
parameter of libnet_build_tcp()
should be causing it to autocompute a checksum for you by calling libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM)
. libnet_build_tcp()
的sum
参数中的0
应该会导致它通过调用libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM)
为您自动计算校验和。
I couldn't really tell you how to solve it but since you are the one building the packet maybe you could opt for creating your own checksum? 我真的不能告诉您如何解决它,但是由于您是构建数据包的人,也许您可以选择创建自己的校验和?
The TCP pseudoheader is a 12 byte field containing the source and destination IP addresses which are both 4 bytes each, a reserved field which is 2 bytes and always set to zeros, and a 4 byte TCP segment length which is equal to the size of the TCP header + the payload length. TCP伪标头是一个12字节的字段,其中包含源IP地址和目标IP地址,二者均为4个字节;一个保留字段为2个字节,始终设置为零;以及一个4字节的TCP段长度,该长度等于IP地址的长度。 TCP标头+有效负载长度。
You could create something like this: 您可以创建以下内容:
First create your variables: 首先创建变量:
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;
Then create the actual function where b->len is the total size of the packet (just add all the headers + the payload and get the total size) and you would just have to memcpy your header and data to pkt_data: 然后创建实际函数,其中b-> len是数据包的总大小(只需添加所有标头+有效负载并获得总大小),您只需要将标头和数据存储到pkt_data中:
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);
And just use the checksum function provided by https://tools.ietf.org/html/rfc1071 to calculate the checksum over the buffer: 只需使用https://tools.ietf.org/html/rfc1071提供的校验和功能来计算缓冲区上的校验和:
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);
}
I use this in a realistic environment to calculate checksums at 5 million PPS. 我在现实的环境中使用它来计算500万PPS的校验和。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.