Я пытаюсь отправить пакет TCP SYN через сокет RAW в C (я знаю, что это не самая простая вещь, но у меня есть академические причины для этого).Контрольная сумма TCP неверна при попытке отправить пакет в C
Когда я проверяю исходящий пакет, все поля хороши, но одно: контрольная сумма TCP. Действительно, Вирешарк говорит мне, что это неверно. В следующем коде вы можете увидеть, как я создаю пакет (заголовки IP опущены, поскольку они, похоже, в порядке).
#define MINIMUM_TCP_HEADER_LENGTH 20
#define DEFAULT_TCP_WINDOW 32767
// [... Code that sets the IP headers ...]
struct tcphdr * tcpHeaders = (struct tcphdr *) (packetBuffer + IPHeaderLength);
tcpHeaders->source = htons(srcPort_16);
tcpHeaders->dest = htons(dstPort_16);
tcpHeaders->seq = htonl(tcpSeq_32);
tcpHeaders->ack_seq = 0;
tcpHeaders->doff = (MINIMUM_TCP_HEADER_LENGTH/4);
tcpHeaders->res1 = 0;
tcpHeaders->res2 = 0;
tcpHeaders->syn = 1;
tcpHeaders->ack = 0;
tcpHeaders->fin = 0;
tcpHeaders->psh = 0;
tcpHeaders->urg = 0;
tcpHeaders->rst = 0;
tcpHeaders->window = htons(DEFAULT_TCP_WINDOW);
tcpHeaders->check = 0x0;
tcpHeaders->urg_ptr = 0x0;
//Sets the data
uint8_t * tcdData = ((uint8_t*) tcpHeaders + MINIMUM_TCP_HEADER_LENGTH);
memcpy(tcdData, message, strlen(message));
//Compute TCP checksum over the pseudo TCP header
uint8_t * pseudo = pseudoBuffer;
memset(pseudo, 0, DEFAULT_BUFFER_SIZE);
memcpy(pseudo, &((ipHeaders->ip_src).s_addr), 4);
pseudo += 4;
memcpy(pseudo, &((ipHeaders->ip_dst).s_addr), 4);
pseudo += 4;
memset(pseudo++, 0, 1);
memset(pseudo++, IPPROTO_TCP, 1);
uint16_t tcpSegmentLength = htons(MINIMUM_TCP_HEADER_LENGTH + (uint32_t) strlen(message));
memcpy(pseudo, &tcpSegmentLength, 2);
pseudo += 2;
//Append the TCP headers and data to the pseudo header
memcpy(pseudo, tcpHeaders, MINIMUM_TCP_HEADER_LENGTH + strlen(attentionMessage));
pseudo += MINIMUM_TCP_HEADER_LENGTH + strlen(attentionMessage);
//Compute checksum
int pseudoBufferLength = pseudo - pseudoBuffer;
tcpHeaders->check = calculateInternetChecksum((uint16_t*) pseudoBuffer, pseudoBufferLength);
//[... Code that proceed to send the packet ...]
Стоит отметить, что оба «packetBuffer» были заполнены нулями, используя MemSet (точно так же, как «псевдо» есть) и что «сообщение» является регулярной строкой.
Вот функция, которая вычисляет контрольную сумму:
uint16_t onesComplementAddition(uint16_t *buff, unsigned int nbytes) {
if(buff == 0 || nbytes == 0)
return 0;
uint32_t sum = 0;
for (; nbytes > 1; nbytes -= 2)
sum += *buff++;
if (nbytes == 1)
sum += *(uint8_t*) buff;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
return sum;
}
uint16_t calculateInternetChecksum(uint16_t *buff, unsigned int nbytes) {
return ~(onesComplementAddition(buff, nbytes));
}
Wireshark позволяет предположить, что это может быть вызвано «TCP контрольной разгрузкой», но я сомневаюсь в этом, как я не получаю никакого ответа от машины I зонд (хотя я знаю, что я должен).
У кого-нибудь есть идея, почему контрольная сумма TCP неверна?
Заранее спасибо.