fix: use generic header_rest field instead of hardcoded id/seq

This commit is contained in:
lohhiiccc 2026-01-27 05:04:38 +01:00
parent 47fca07406
commit bfd61e3636
7 changed files with 32 additions and 39 deletions

View file

@ -33,6 +33,7 @@ int icmp_get_fd(const icmp_handle_t *h);
/* Send functions */ /* Send functions */
int icmp_send_raw(icmp_handle_t *h, uint8_t type, uint8_t code, int icmp_send_raw(icmp_handle_t *h, uint8_t type, uint8_t code,
uint32_t header_rest,
const void *payload, size_t len, struct in_addr dest, const void *payload, size_t len, struct in_addr dest,
uint8_t ttl); uint8_t ttl);

View file

@ -6,7 +6,7 @@
#include <netinet/in.h> #include <netinet/in.h>
int icmp_build_packet(void *buffer, size_t buffer_len, uint8_t type, int icmp_build_packet(void *buffer, size_t buffer_len, uint8_t type,
uint8_t code, uint16_t id, uint16_t seq, uint8_t code, uint32_t header_rest,
const void *payload, size_t payload_len); const void *payload, size_t payload_len);
int icmp_parse_ip_header(const void *buffer, size_t buffer_len, int icmp_parse_ip_header(const void *buffer, size_t buffer_len,

View file

@ -7,14 +7,14 @@
/* Forward declarations */ /* Forward declarations */
static void write_icmp_header(struct icmp_header *hdr, uint8_t type, static void write_icmp_header(struct icmp_header *hdr, uint8_t type,
uint8_t code, uint16_t id, uint16_t seq); uint8_t code, uint32_t header_rest);
static void copy_payload(void *dest, const void *src, size_t len); static void copy_payload(void *dest, const void *src, size_t len);
static void compute_and_set_checksum(struct icmp_header *hdr, size_t total_len); static void compute_and_set_checksum(struct icmp_header *hdr, size_t total_len);
/* -------------------- */ /* -------------------- */
int int
icmp_build_packet(void *buffer, size_t buffer_len, uint8_t type, uint8_t code, icmp_build_packet(void *buffer, size_t buffer_len, uint8_t type, uint8_t code,
uint16_t id, uint16_t seq, const void *payload, uint32_t header_rest, const void *payload,
size_t payload_len) size_t payload_len)
{ {
const size_t required_len = sizeof(struct icmp_header) + payload_len; const size_t required_len = sizeof(struct icmp_header) + payload_len;
@ -24,7 +24,7 @@ icmp_build_packet(void *buffer, size_t buffer_len, uint8_t type, uint8_t code,
struct icmp_header *h = (struct icmp_header *)buffer; struct icmp_header *h = (struct icmp_header *)buffer;
write_icmp_header(h, type, code, id, seq); write_icmp_header(h, type, code, header_rest);
if (payload_len > 0) if (payload_len > 0)
{ {
copy_payload((unsigned char*)buffer + sizeof(struct icmp_header), copy_payload((unsigned char*)buffer + sizeof(struct icmp_header),
@ -38,13 +38,12 @@ icmp_build_packet(void *buffer, size_t buffer_len, uint8_t type, uint8_t code,
static void static void
write_icmp_header(struct icmp_header *hdr, uint8_t type, uint8_t code, write_icmp_header(struct icmp_header *hdr, uint8_t type, uint8_t code,
uint16_t id, uint16_t seq) uint32_t header_rest)
{ {
hdr->type = type; hdr->type = type;
hdr->code = code; hdr->code = code;
hdr->checksum = 0; // will be computed later hdr->checksum = 0; // will be computed later
hdr->un.echo.id = id; hdr->un.gateway = header_rest;
hdr->un.echo.seq = seq;
} }
static void static void

View file

@ -2,10 +2,6 @@
#include "internal/icmp_send.h" #include "internal/icmp_send.h"
#include "icmp_types.h" #include "icmp_types.h"
#include <stdint.h> #include <stdint.h>
#include <arpa/inet.h>
/* ICMP echo header: type(1) + code(1) + checksum(2) + id(2) + seq(2) = 8 */
#define ECHO_HEADER_SIZE 4
int int
icmp_send_echo(icmp_handle_t *h, struct in_addr dest, uint16_t id, icmp_send_echo(icmp_handle_t *h, struct in_addr dest, uint16_t id,
@ -14,15 +10,8 @@ icmp_send_echo(icmp_handle_t *h, struct in_addr dest, uint16_t id,
if (0 == send_validate_handle(h)) if (0 == send_validate_handle(h))
return -1; return -1;
uint16_t id_net = htons(id); uint32_t header_rest = (uint32_t)id | ((uint32_t)seq << 16);
uint16_t seq_net = htons(seq);
uint8_t payload[ECHO_HEADER_SIZE];
payload[0] = (id_net >> 8) & 0xFF; return icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, header_rest,
payload[1] = id_net & 0xFF; NULL, 0, dest, ttl);
payload[2] = (seq_net >> 8) & 0xFF;
payload[3] = seq_net & 0xFF;
return icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0,
payload, ECHO_HEADER_SIZE, dest, ttl);
} }

View file

@ -15,6 +15,7 @@ static int validate_payload(struct icmp_handle *h, const void *payload,
int int
icmp_send_raw(icmp_handle_t *h, uint8_t type, uint8_t code, icmp_send_raw(icmp_handle_t *h, uint8_t type, uint8_t code,
uint32_t header_rest,
const void *payload, size_t len, struct in_addr dest, const void *payload, size_t len, struct in_addr dest,
uint8_t ttl) uint8_t ttl)
{ {
@ -27,7 +28,7 @@ icmp_send_raw(icmp_handle_t *h, uint8_t type, uint8_t code,
uint8_t buffer[MAX_PACKET_SIZE]; uint8_t buffer[MAX_PACKET_SIZE];
int packet_len = icmp_build_packet(buffer, sizeof(buffer), int packet_len = icmp_build_packet(buffer, sizeof(buffer),
type, code, 0, 0, payload, len); type, code, header_rest, payload, len);
if (-1 == packet_len) if (-1 == packet_len)
{ {
icmp_set_error_fmt(h, ICMP_ERR_INVALID, icmp_set_error_fmt(h, ICMP_ERR_INVALID,

View file

@ -1,5 +1,6 @@
#include <criterion/criterion.h> #include <criterion/criterion.h>
#include <string.h> #include <string.h>
#include <arpa/inet.h>
#include "internal/icmp_packet_internal.h" #include "internal/icmp_packet_internal.h"
#include "internal/icmp_packet.h" #include "internal/icmp_packet.h"
#include "internal/icmp_utils.h" #include "internal/icmp_utils.h"
@ -10,9 +11,10 @@ Test(packet_build, echo_request_no_payload)
uint8_t type = 8, code = 0; uint8_t type = 8, code = 0;
uint16_t id = 0x1234; uint16_t id = 0x1234;
uint16_t seq = 0x0001; uint16_t seq = 0x0001;
uint32_t header_rest = (uint32_t)id | ((uint32_t)seq << 16);
int ret = icmp_build_packet(buffer, sizeof(buffer), type, code, id, seq, int ret = icmp_build_packet(buffer, sizeof(buffer), type, code,
NULL, 0); header_rest, NULL, 0);
cr_assert_eq(ret, 8, "Expected packet size 8, got %d", ret); cr_assert_eq(ret, 8, "Expected packet size 8, got %d", ret);
struct icmp_header *hdr = (struct icmp_header *)buffer; struct icmp_header *hdr = (struct icmp_header *)buffer;
@ -31,10 +33,10 @@ Test(packet_build, echo_request_with_payload)
size_t payload_len = sizeof(payload) - 1; size_t payload_len = sizeof(payload) - 1;
uint8_t buffer[8 + 5] = {0}; uint8_t buffer[8 + 5] = {0};
uint8_t type = 8, code = 0; uint8_t type = 8, code = 0;
uint16_t id = 0xabcd, seq = 0x1234; uint32_t header_rest = (uint32_t)0xabcd | ((uint32_t)0x1234 << 16);
int ret = icmp_build_packet(buffer, sizeof(buffer), type, code, id, seq, int ret = icmp_build_packet(buffer, sizeof(buffer), type, code,
payload, payload_len); header_rest, payload, payload_len);
cr_assert_eq(ret, 13, "Expected packet size 13, got %d", ret); cr_assert_eq(ret, 13, "Expected packet size 13, got %d", ret);
cr_assert(memcmp(buffer + 8, payload, 5) == 0, cr_assert(memcmp(buffer + 8, payload, 5) == 0,
@ -45,12 +47,12 @@ Test(packet_build, checksum_correct)
{ {
uint8_t buffer[16] = {0}; uint8_t buffer[16] = {0};
uint8_t type = 8, code = 0; uint8_t type = 8, code = 0;
uint16_t id = 0x77aa, seq = 0x0033; uint32_t header_rest = (uint32_t)0x77aa | ((uint32_t)0x0033 << 16);
const char payload[] = "ABC"; const char payload[] = "ABC";
size_t payload_len = 3; size_t payload_len = 3;
int ret = icmp_build_packet(buffer, sizeof(buffer), type, code, id, seq, int ret = icmp_build_packet(buffer, sizeof(buffer), type, code,
payload, payload_len); header_rest, payload, payload_len);
cr_assert_eq(ret, 11, "Expected packet size 11, got %d", ret); cr_assert_eq(ret, 11, "Expected packet size 11, got %d", ret);
struct icmp_header *hdr = (struct icmp_header *)buffer; struct icmp_header *hdr = (struct icmp_header *)buffer;
@ -58,16 +60,17 @@ Test(packet_build, checksum_correct)
hdr->checksum = 0; hdr->checksum = 0;
uint16_t checksum = icmp_checksum(buffer, ret); uint16_t checksum = icmp_checksum(buffer, ret);
hdr->checksum = old_checksum; hdr->checksum = old_checksum;
cr_assert_eq(old_checksum, checksum, cr_assert_eq(ntohs(old_checksum), checksum,
"Checksum in packet (%04x) does not match recomputed one (%04x)", "Checksum in packet (%04x) does not match recomputed one (%04x)",
old_checksum, checksum); ntohs(old_checksum), checksum);
} }
Test(packet_build, buffer_too_small) Test(packet_build, buffer_too_small)
{ {
uint8_t buf[4]; uint8_t buf[4];
const char payload[8] = "ABCDEFG"; const char payload[8] = "ABCDEFG";
int ret = icmp_build_packet(buf, sizeof(buf), 8, 0, 0x1111, 0x2222, uint32_t header_rest = (uint32_t)0x1111 | ((uint32_t)0x2222 << 16);
int ret = icmp_build_packet(buf, sizeof(buf), 8, 0, header_rest,
payload, 8); payload, 8);
cr_assert_eq(ret, -1, "Expected -1 for too small buffer, got %d", ret); cr_assert_eq(ret, -1, "Expected -1 for too small buffer, got %d", ret);
} }

View file

@ -20,7 +20,7 @@ Test(send_raw, simple_packet)
struct in_addr dest; struct in_addr dest;
dest.s_addr = inet_addr("127.0.0.1"); dest.s_addr = inet_addr("127.0.0.1");
int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, NULL, 0, dest, 64); int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, 0, NULL, 0, dest, 64);
cr_assert_eq(ret, 0, "Expected success (0)"); cr_assert_eq(ret, 0, "Expected success (0)");
cr_assert_str_eq(icmp_strerror(h), "No error"); cr_assert_str_eq(icmp_strerror(h), "No error");
@ -43,7 +43,7 @@ Test(send_raw, with_payload)
dest.s_addr = inet_addr("127.0.0.1"); dest.s_addr = inet_addr("127.0.0.1");
const char payload[] = "HELLO"; const char payload[] = "HELLO";
int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, 0,
payload, 5, dest, 64); payload, 5, dest, 64);
cr_assert_eq(ret, 0, "Expected success (0)"); cr_assert_eq(ret, 0, "Expected success (0)");
@ -58,7 +58,7 @@ Test(send_raw, null_handle)
struct in_addr dest; struct in_addr dest;
dest.s_addr = inet_addr("127.0.0.1"); dest.s_addr = inet_addr("127.0.0.1");
int ret = icmp_send_raw(NULL, ICMP_TYPE_ECHO_REQUEST, 0, int ret = icmp_send_raw(NULL, ICMP_TYPE_ECHO_REQUEST, 0, 0,
NULL, 0, dest, 64); NULL, 0, dest, 64);
cr_assert_eq(ret, -1, "Expected -1 for NULL handle"); cr_assert_eq(ret, -1, "Expected -1 for NULL handle");
@ -78,7 +78,7 @@ Test(send_raw, null_payload_with_length)
struct in_addr dest; struct in_addr dest;
dest.s_addr = inet_addr("127.0.0.1"); dest.s_addr = inet_addr("127.0.0.1");
int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, 0,
NULL, 10, dest, 64); NULL, 10, dest, 64);
cr_assert_eq(ret, -1, "Expected -1 for NULL payload with len > 0"); cr_assert_eq(ret, -1, "Expected -1 for NULL payload with len > 0");
@ -107,7 +107,7 @@ Test(send_raw, payload_too_large)
uint8_t large_payload[2000]; uint8_t large_payload[2000];
memset(large_payload, 0xAA, sizeof(large_payload)); memset(large_payload, 0xAA, sizeof(large_payload));
int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, int ret = icmp_send_raw(h, ICMP_TYPE_ECHO_REQUEST, 0, 0,
large_payload, sizeof(large_payload), dest, 64); large_payload, sizeof(large_payload), dest, 64);
cr_assert_eq(ret, -1, "Expected -1 for payload too large"); cr_assert_eq(ret, -1, "Expected -1 for payload too large");
@ -130,7 +130,7 @@ Test(send_raw, invalid_fd)
struct in_addr dest; struct in_addr dest;
dest.s_addr = inet_addr("127.0.0.1"); dest.s_addr = inet_addr("127.0.0.1");
int ret = icmp_send_raw((icmp_handle_t *)&h, ICMP_TYPE_ECHO_REQUEST, 0, int ret = icmp_send_raw((icmp_handle_t *)&h, ICMP_TYPE_ECHO_REQUEST, 0, 0,
NULL, 0, dest, 64); NULL, 0, dest, 64);
cr_assert_eq(ret, -1, "Expected -1 for invalid FD"); cr_assert_eq(ret, -1, "Expected -1 for invalid FD");