Calculating the checksum of a UDP packet
Posted: Mon Mar 25, 2024 1:05 pm
In an ESP32C6 project I am sending UDP packets over ethernet to another device. I am trying to calculate the checksum of the UDP packet I have to send.
To do this I have:
I know that the result of the checksum of the UDP header is "ec 16" but the result I get is "13 e9".
Can someone tell me what I have wrong?
To do this I have:
Code: Untitled.c Select all
static void convert_hex_to_uint8(const char *data_hex)
{
unsigned int temp;
for (size_t i = 0; i < sizeof(mensajeUDP); i++) {
sscanf(&data_hex[i*3], "%02x", &temp);
mensajeUDP[i] = temp;
}
}
static void enviarConfiguracionABalanza(void)
{
uint8_t src_mac[] = {0x00, 0x08, 0xef, 0x00, 0x01, 0x37};
uint8_t dest_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
uint32_t src_ip = 0xc0a80a98;
uint32_t dest_ip = 0xc0a80aff;
uint16_t src_port = 6000;
uint16_t dest_port = 6000;
int msg_len;
if (enviarRespuestaUDP == false)
return;
else
enviarRespuestaUDP = false;
const char *data_hex = "44 50 48 00 04 01 00 ff 00 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 01 4d 41 53 00 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 98 0a a8 c0 0e 00 00 00 31 31 37 00 20 20 45 00 00 00 00 00 01 00 00 00 46 00 00 00 30 2e 31 37 00 00 00 00 00 00 00 05 30 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff 00 00 01 00 00 00 00 00";
msg_len = strlen(data_hex);
printf ("%d",msg_len);
convert_hex_to_uint8(data_hex);
ethernet_header_t *eth_header = (ethernet_header_t *)bufferUDP;
ip_header_t *ip_header = (ip_header_t *)(bufferUDP + sizeof(ethernet_header_t));
udp_header_t *udp_header = (udp_header_t *)(bufferUDP + sizeof(ethernet_header_t) + sizeof(ip_header_t));
memcpy(eth_header->src_mac, src_mac, 6);
memcpy(eth_header->dest_mac, dest_mac, 6);
eth_header->ethertype = htons(0x0800); // IP
ip_header->version_ihl = 0x45;
ip_header->type_of_service = 0;
ip_header->total_length = 0x2001;
ip_header->identification = 0x2900;
ip_header->flags_fragment_offset = 0;
ip_header->ttl = 128;
ip_header->header_checksum = 0;
ip_header->protocol = 17; // UDP
ip_header->src_ip = htonl(src_ip);
ip_header->dest_ip = htonl(dest_ip);
ip_header->header_checksum = calculate_ip_checksum(ip_header);
udp_header->src_port = htons(src_port);
udp_header->dest_port = htons(dest_port);
udp_header->checksum = 0;
udp_header->length = 0x0c01;
udp_header->checksum = calculate_udp_checksum(ip_header, udp_header, mensajeUDP, 260);
memcpy(bufferUDP + sizeof(ethernet_header_t) + sizeof(ip_header_t) + sizeof(udp_header_t), mensajeUDP, 260);
if (esp_eth_transmit(s_eth_handle[0], bufferUDP, 302) != ESP_OK)
ESP_LOGE(TAG, "Error");
}
static uint16_t calculate_checksum(uint16_t *buffer, int length)
{
uint32_t sum = 0;
while (length > 1) {
sum += *buffer++;
length -= 2;
}
if (length > 0) {
sum += *(uint8_t *)buffer;
}
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
return (uint16_t)~sum;
}
static uint16_t calculate_ip_checksum(ip_header_t *ip_header)
{
ip_header->header_checksum = 0;
return (calculate_checksum((uint16_t *)ip_header, sizeof(ip_header_t)));
}
static uint16_t calculate_udp_checksum(ip_header_t *ip_header, udp_header_t *udp_header, uint8_t *data, uint16_t data_len)
{
uint16_t total_length = sizeof(udp_header_t) + data_len;
uint8_t pseudo_header_buffer[sizeof(pseudo_header_t) + sizeof(udp_header_t)];
pseudo_header_t *pseudo_header = (pseudo_header_t *)pseudo_header_buffer;
pseudo_header->src_ip = ip_header->src_ip;
pseudo_header->dest_ip = ip_header->dest_ip;
pseudo_header->zero = 0;
pseudo_header->protocol = ip_header->protocol;
pseudo_header->udp_length = htons(total_length);
uint32_t sum = 0;
sum += calculate_checksum((uint16_t *)pseudo_header, sizeof(pseudo_header_t));
sum += calculate_checksum((uint16_t *)udp_header, sizeof(udp_header_t));
sum += calculate_checksum((uint16_t *)data, data_len);
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
return (uint16_t)~sum;
}
Can someone tell me what I have wrong?