簡體   English   中英

Libnet TCP校驗和錯誤

[英]Libnet TCP checksum error

我正在嘗試使用libnet庫構建TCP數據包。 我在libnet_build_tcp函數中使用'0'來自動計算校驗和值。 但是,由於校驗和錯誤,校驗和似乎在計算時會忽略pseudo-header ,從而導致無用的數據包。 有誰知道如何解決這個問題?

據我在代碼中看到的,只要您還沒有使用libnet_toggle_checksum(l, ptag, 1); libnet_build_tcp()sum參數中的0應該會導致它通過調用libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM)為您自動計算校驗和。

我真的不能告訴您如何解決它,但是由於您是構建數據包的人,也許您可​​以選擇創建自己的校驗和?

TCP偽標頭是一個12字節的字段,其中包含源IP地址和目標IP地址,二者均為4個字節;一個保留字段為2個字節,始終設置為零;以及一個4字節的TCP段長度,該長度等於IP地址的長度。 TCP標頭+有效負載長度。

您可以創建以下內容:

首先創建變量:

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是數據包的總大小(只需添加所有標頭+有效負載並獲得總大小),您只需要將標頭和數據存儲到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);

只需使用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);
}

我在現實的環境中使用它來計算500萬PPS的校驗和。

暫無
暫無

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

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