Ошибка контрольной суммы TCP в Libnet - PullRequest
2 голосов
/ 24 октября 2011

Я пытаюсь собрать пакет TCP с использованием библиотеки libnet.Я использую '0' для автоматического вычисления значения контрольной суммы в функции libnet_build_tcp.Однако кажется, что контрольная сумма игнорирует pseudo-header при вычислении, что приводит к бесполезному пакету из-за ошибки контрольной суммы.Кто-нибудь знает как это решить?

1 Ответ

1 голос
/ 31 марта 2018

Насколько я вижу в коде, до тех пор, пока вы не использовали libnet_toggle_checksum(l, ptag, 1); ваш 0 в параметре sum libnet_build_tcp() должен вызывать автоматическое вычисление контрольной суммы для вас, вызывая libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM).

Я не могу сказать вам, как ее решить, но, поскольку вы создаете пакет, возможно, вы могли бы выбрать создание своей собственной контрольной суммы?

Псевдозаголовок TCP представляет собой 12-байтовое поле, содержащее IP-адреса источника и назначения, каждый из которых имеет размер 4 байта, зарезервированное поле размером 2 байта, всегда равное нулю, и длину 4-байтового сегмента TCP, равную размер заголовка 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);
}

Я использую это в реалистичной среде для вычисления контрольных сумм при 5 млн. PPS.

...