Browse Source

Fix: Add portable tc_htonl/tc_htons/tc_ntohl/tc_ntohs macros, replace winsock2-incompatible hton*/nto* in NAT test files

congestion
Evgeny 5 months ago
parent
commit
aafa0cfcab
  1. 6
      lib/platform_compat.h
  2. 62
      tests/test_nat_engine.c
  3. 36
      tests/test_nat_stress.c
  4. 32
      tests/test_nat_transport.c

6
lib/platform_compat.h

@ -153,6 +153,12 @@
#include <stdint.h>
// Portable byte-order: no winsock2, no struct in_addr, pure C
static inline uint16_t tc_htons(uint16_t x) { return (uint16_t)(((x & 0xFFU) << 8) | ((x & 0xFF00U) >> 8)); }
static inline uint32_t tc_htonl(uint32_t x) { return (((x & 0x000000FFU) << 24) | ((x & 0x0000FF00U) << 8) | ((x & 0x00FF0000U) >> 8) | ((x & 0xFF000000U) >> 24)); }
#define tc_ntohs(x) tc_htons(x)
#define tc_ntohl(x) tc_htonl(x)
// Generate cryptographically secure random bytes
// Returns 0 on success, -1 on error
int random_bytes(uint8_t *buffer, size_t len);

62
tests/test_nat_engine.c

@ -36,19 +36,19 @@ static struct {
#define ASSERT_EQ(a,b,m) ASSERT((a)==(b),m)
/* ================================================================
* Helpers: build IP packets (uses htonl/htons + memcpy: network byte order in wire)
* Helpers: build IP packets (uses tc_htonl/tc_htons + memcpy: network byte order in wire)
* ================================================================ */
static void build_ip_hdr(uint8_t* buf, uint8_t proto, uint32_t src_host, uint32_t dst_host, uint16_t total_len) {
buf[0] = 0x45;
buf[1] = 0x00;
uint16_t n = htons(total_len); memcpy(buf + 2, &n, 2);
uint16_t n = tc_htons(total_len); memcpy(buf + 2, &n, 2);
buf[4] = 0x12; buf[5] = 0x34;
memset(buf + 6, 0, 2);
buf[8] = 64;
buf[9] = proto;
memset(buf + 10, 0, 2); // checksum slot = 0 for now
uint32_t s_net = htonl(src_host), d_net = htonl(dst_host);
uint32_t s_net = tc_htonl(src_host), d_net = tc_htonl(dst_host);
memcpy(buf + 12, &s_net, 4);
memcpy(buf + 16, &d_net, 4);
}
@ -98,7 +98,7 @@ static struct global_config make_global_config(void) {
g.nat_port_start = TEST_PORT_START;
g.nat_port_end = TEST_PORT_END;
g.nat_tun_ip.family = AF_INET;
g.nat_tun_ip.addr.v4.s_addr = htonl(TEST_GW_HOST);
g.nat_tun_ip.addr.v4.s_addr = tc_htonl(TEST_GW_HOST);
return g;
}
@ -181,10 +181,10 @@ static uint8_t* make_udp_pkt(uint32_t src_host, uint16_t src_port_host, uint32_t
uint8_t* pkt = calloc(1, ip_udp_len);
build_ip_hdr(pkt, IPPROTO_UDP_UINT8, src_host, dst_host, ip_udp_len);
// UDP header
uint16_t sp = htons(src_port_host), dp = htons(dst_port_host);
uint16_t sp = tc_htons(src_port_host), dp = tc_htons(dst_port_host);
memcpy(pkt + 20, &sp, 2); // src port
memcpy(pkt + 22, &dp, 2); // dst port
uint16_t udp_len = htons(8 + TEST_PAYLOAD_LEN);
uint16_t udp_len = tc_htons(8 + TEST_PAYLOAD_LEN);
memcpy(pkt + 24, &udp_len, 2); // length
memset(pkt + 26, 0, 2); // checksum = 0 (no UDP csum)
memset(pkt + 28, 0xAB, TEST_PAYLOAD_LEN); // payload
@ -208,7 +208,7 @@ static void test_port_alloc(void) {
// Check port was allocated from table index
struct eim_nat_entry* e = &ctx.table[10000 + i];
ASSERT(e->state == EIM_NAT_ENTRY_ACTIVE, "entry active");
ASSERT_EQ(e->internal_port, htons(50000 + i), "internal port stored");
ASSERT_EQ(e->internal_port, tc_htons(50000 + i), "internal port stored");
free(pkt);
}
ASSERT(ctx.next_port == 10003, "next_port advanced");
@ -258,7 +258,7 @@ static void test_port_alloc(void) {
r = eim_nat_egress(&ctx, p3, 20 + 8 + TEST_PAYLOAD_LEN, 1, get_mock_conn());
ASSERT_EQ(r, 0, "third egress ok after wrap");
ASSERT(ctx.table[10000].state == EIM_NAT_ENTRY_ACTIVE, "port 10000 reused");
ASSERT_EQ(ctx.table[10000].internal_port, htons(50003), "new entry for reused port");
ASSERT_EQ(ctx.table[10000].internal_port, tc_htons(50003), "new entry for reused port");
free(p3);
eim_nat_destroy_ctx(&ctx);
@ -316,13 +316,13 @@ static void test_egress_udp(void) {
// Check src IP = gateway
uint32_t new_src_ip_net; memcpy(&new_src_ip_net, pkt + 12, 4);
ASSERT_EQ(ntohl(new_src_ip_net), TEST_GW_HOST, "src IP = gateway");
ASSERT_EQ(tc_ntohl(new_src_ip_net), TEST_GW_HOST, "src IP = gateway");
// Check dst IP unchanged
uint32_t dst_ip_net; memcpy(&dst_ip_net, pkt + 16, 4);
ASSERT_EQ(dst_ip_net, orig_dst_ip_net, "dst IP unchanged");
// Check src port changed
uint16_t new_src_port_net; memcpy(&new_src_port_net, pkt + 20, 2);
ASSERT(ntohs(new_src_port_net) == TEST_PORT_START, "src port = port_start");
ASSERT(tc_ntohs(new_src_port_net) == TEST_PORT_START, "src port = port_start");
// Check dst port unchanged
uint16_t dst_port_net; memcpy(&dst_port_net, pkt + 22, 2);
ASSERT_EQ(dst_port_net, orig_dst_port_net, "dst port unchanged");
@ -332,7 +332,7 @@ static void test_egress_udp(void) {
struct eim_nat_entry* e = &ctx.table[TEST_PORT_START];
ASSERT_EQ(e->state, EIM_NAT_ENTRY_ACTIVE, "entry active");
ASSERT_EQ(e->internal_ip, TEST_IP_SRC_HOST, "internal_ip stored");
ASSERT_EQ(e->internal_port, htons(TEST_SRC_PORT), "internal_port stored");
ASSERT_EQ(e->internal_port, tc_htons(TEST_SRC_PORT), "internal_port stored");
ASSERT_EQ(e->proto, IPPROTO_UDP_UINT8, "proto=UDP");
ASSERT_EQ(e->src_node_id, 0x5555ULL, "src_node_id stored");
ASSERT(e->src_conn == get_mock_conn(), "src_conn stored");
@ -350,7 +350,7 @@ static uint8_t* make_tcp_pkt(uint32_t src_host, uint16_t src_port_host, uint32_t
const size_t ip_tcp_len = 20 + 20 + TEST_PAYLOAD_LEN; // 20 TCP hdr min
uint8_t* pkt = calloc(1, ip_tcp_len);
build_ip_hdr(pkt, IPPROTO_TCP_UINT8, src_host, dst_host, ip_tcp_len);
uint16_t sp = htons(src_port_host), dp = htons(dst_port_host);
uint16_t sp = tc_htons(src_port_host), dp = tc_htons(dst_port_host);
memcpy(pkt + 20, &sp, 2);
memcpy(pkt + 22, &dp, 2);
// seq, ack, offset+flags, window
@ -374,10 +374,10 @@ static void test_egress_tcp(void) {
ASSERT_EQ(r, 0, "egress TCP ok");
// Check src IP = gateway
uint32_t new_src; memcpy(&new_src, pkt + 12, 4);
ASSERT_EQ(ntohl(new_src), TEST_GW_HOST, "src IP=gw");
ASSERT_EQ(tc_ntohl(new_src), TEST_GW_HOST, "src IP=gw");
// Check src port
uint16_t new_sport; memcpy(&new_sport, pkt + 20, 2);
ASSERT_EQ(ntohs(new_sport), TEST_PORT_START, "src port=start");
ASSERT_EQ(tc_ntohs(new_sport), TEST_PORT_START, "src port=start");
// IP checksum valid
ASSERT(verify_ip_checksum(pkt) == 1, "IP checksum valid");
// Entry proto = TCP
@ -399,7 +399,7 @@ static uint8_t* make_icmp_echo_pkt(uint32_t src_host, uint32_t dst_host, uint8_t
pkt[21] = 0x00; // code
// checksum = 0 for now
memset(pkt + 22, 0, 2);
uint16_t id_n = htons(id_host), seq_n = htons(seq_host);
uint16_t id_n = tc_htons(id_host), seq_n = tc_htons(seq_host);
memcpy(pkt + 24, &id_n, 2);
memcpy(pkt + 26, &seq_n, 2);
memset(pkt + 28, 0xDD, TEST_PAYLOAD_LEN);
@ -420,12 +420,12 @@ static void test_egress_icmp(void) {
ASSERT_EQ(r, 0, "egress ICMP echo ok");
// ICMP ID should be overwritten with allocated port
uint16_t new_id_net; memcpy(&new_id_net, pkt + 24, 2);
ASSERT_EQ(ntohs(new_id_net), TEST_PORT_START, "ICMP ID = allocated port");
ASSERT_EQ(tc_ntohs(new_id_net), TEST_PORT_START, "ICMP ID = allocated port");
// IP checksum valid
ASSERT(verify_ip_checksum(pkt) == 1, "IP checksum valid");
// Entry proto = ICMP
ASSERT_EQ(ctx.table[TEST_PORT_START].proto, IPPROTO_ICMP_UINT8, "proto=ICMP");
ASSERT_EQ(ctx.table[TEST_PORT_START].internal_port, htons(icmp_id), "internal port = ICMP ID");
ASSERT_EQ(ctx.table[TEST_PORT_START].internal_port, tc_htons(icmp_id), "internal port = ICMP ID");
free(pkt);
eim_nat_destroy_ctx(&ctx);
}
@ -538,7 +538,7 @@ static void test_egress_invalid(void) {
uint8_t pkt[20 + 8 + TEST_PAYLOAD_LEN];
build_ip_hdr(pkt, 0x63, TEST_IP_SRC_HOST, TEST_IP_DST_HOST, sizeof(pkt));
// Fill fake UDP header
uint16_t sp = htons(TEST_SRC_PORT), dp = htons(TEST_DST_PORT);
uint16_t sp = tc_htons(TEST_SRC_PORT), dp = tc_htons(TEST_DST_PORT);
memcpy(pkt + 20, &sp, 2); memcpy(pkt + 22, &dp, 2);
compute_ip_checksum(pkt);
int r = eim_nat_egress(&ctx, pkt, sizeof(pkt), 1, get_mock_conn());
@ -582,13 +582,13 @@ static void test_ingress_udp(void) {
ASSERT(entry == &ctx.table[TEST_PORT_START], "correct entry");
// Check dst IP → internal IP
uint32_t new_dst_net; memcpy(&new_dst_net, resp + 16, 4);
ASSERT_EQ(ntohl(new_dst_net), internal_ip, "dst IP = internal IP");
ASSERT_EQ(tc_ntohl(new_dst_net), internal_ip, "dst IP = internal IP");
// Check dst port → internal port
uint16_t new_dst_port_net; memcpy(&new_dst_port_net, resp + 22, 2);
ASSERT_EQ(new_dst_port_net, internal_port_net, "dst port = internal port");
// Check src IP unchanged
uint32_t src_net; memcpy(&src_net, resp + 12, 4);
ASSERT_EQ(ntohl(src_net), TEST_IP_DST_HOST, "src IP unchanged");
ASSERT_EQ(tc_ntohl(src_net), TEST_IP_DST_HOST, "src IP unchanged");
ASSERT(verify_ip_checksum(resp) == 1, "IP checksum valid");
free(resp);
@ -654,8 +654,8 @@ static void test_ingress_icmp(void) {
reply[20] = 0; // Echo Reply
reply[21] = 0;
memset(reply + 22, 0, 2); // checksum
uint16_t alloc_id_net = htons(TEST_PORT_START); // the port allocated by egress
uint16_t seq = htons(1);
uint16_t alloc_id_net = tc_htons(TEST_PORT_START); // the port allocated by egress
uint16_t seq = tc_htons(1);
memcpy(reply + 24, &alloc_id_net, 2);
memcpy(reply + 26, &seq, 2);
memset(reply + 28, 0xDD, TEST_PAYLOAD_LEN);
@ -666,7 +666,7 @@ static void test_ingress_icmp(void) {
int r = eim_nat_ingress(&ctx, reply, len, &entry);
ASSERT_EQ(r, 0, "ingress icmp reply ok");
uint16_t new_id_net; memcpy(&new_id_net, reply + 24, 2);
ASSERT_EQ(ntohs(new_id_net), icmp_id, "ICMP ID restored to original");
ASSERT_EQ(tc_ntohs(new_id_net), icmp_id, "ICMP ID restored to original");
ASSERT(entry != NULL, "entry returned");
ASSERT(verify_ip_checksum(reply) == 1, "IP checksum valid");
free(reply);
@ -686,12 +686,12 @@ static void test_port_forward(void) {
eim_nat_init_ctx(&ctx, &g);
int r = eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8,
0x0A0000FE, htons(8080), // internal 10.0.0.254:8080
0x0A0000FE, tc_htons(8080), // internal 10.0.0.254:8080
10050);
ASSERT_EQ(r, 0, "add_forward ok");
ASSERT(ctx.table[10050].state == EIM_NAT_ENTRY_STATIC, "entry static");
ASSERT_EQ(ctx.table[10050].internal_ip, 0x0A0000FE, "internal_ip");
ASSERT_EQ(ctx.table[10050].internal_port, htons(8080), "internal_port");
ASSERT_EQ(ctx.table[10050].internal_port, tc_htons(8080), "internal_port");
ASSERT_EQ(ctx.table[10050].proto, IPPROTO_TCP_UINT8, "proto=TCP");
eim_nat_destroy_ctx(&ctx);
}
@ -703,8 +703,8 @@ static void test_port_forward(void) {
struct eim_nat_ctx ctx;
eim_nat_init_ctx(&ctx, &g);
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, htons(8080), 10050);
int r = eim_nat_add_forward(&ctx, IPPROTO_UDP_UINT8, 0x0A0000FF, htons(9090), 10050);
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, tc_htons(8080), 10050);
int r = eim_nat_add_forward(&ctx, IPPROTO_UDP_UINT8, 0x0A0000FF, tc_htons(9090), 10050);
ASSERT_EQ(r, -1, "duplicate rejects");
eim_nat_destroy_ctx(&ctx);
}
@ -717,7 +717,7 @@ static void test_port_forward(void) {
eim_nat_init_ctx(&ctx, &g);
// Static forward: external port 10050 → internal 10.0.0.254:8080 TCP
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, htons(8080), 10050);
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, tc_htons(8080), 10050);
// Ingress TCP packet to gateway:10050
uint8_t* resp = make_tcp_pkt(TEST_IP_DST_HOST, 443, TEST_GW_HOST, 10050);
@ -728,10 +728,10 @@ static void test_port_forward(void) {
ASSERT_EQ(entry->state, EIM_NAT_ENTRY_STATIC, "static entry");
// Check dst IP → 10.0.0.254
uint32_t dst_net; memcpy(&dst_net, resp + 16, 4);
ASSERT_EQ(ntohl(dst_net), 0x0A0000FE, "dst IP = 10.0.0.254");
ASSERT_EQ(tc_ntohl(dst_net), 0x0A0000FE, "dst IP = 10.0.0.254");
// Check dst port → 8080
uint16_t dst_port; memcpy(&dst_port, resp + 22, 2);
ASSERT_EQ(dst_port, htons(8080), "dst port = 8080");
ASSERT_EQ(dst_port, tc_htons(8080), "dst port = 8080");
ASSERT(verify_ip_checksum(resp) == 1, "IP checksum valid");
free(resp);
eim_nat_destroy_ctx(&ctx);
@ -758,7 +758,7 @@ static void test_bypass_flows(void) {
eim_nat_egress(&ctx, p2, 20 + 8 + TEST_PAYLOAD_LEN, 0x1111, get_mock_conn());
// Should reuse same port (matching internal_ip:port:proto)
uint16_t sp; memcpy(&sp, p2 + 20, 2);
ASSERT_EQ(ntohs(sp), TEST_PORT_START, "same port reused");
ASSERT_EQ(tc_ntohs(sp), TEST_PORT_START, "same port reused");
free(p2);
eim_nat_destroy_ctx(&ctx);
}

36
tests/test_nat_stress.c

@ -39,16 +39,16 @@ static uint8_t* make_udp_pkt(uint32_t src_host, uint16_t src_port_host, uint32_t
const size_t len = 20 + 8 + 14;
uint8_t* pkt = calloc(1, len);
pkt[0] = 0x45; pkt[1] = 0x00;
uint16_t tot = htons((uint16_t)len); memcpy(pkt + 2, &tot, 2);
uint16_t tot = tc_htons((uint16_t)len); memcpy(pkt + 2, &tot, 2);
pkt[4] = 0x12; pkt[5] = 0x34;
memset(pkt + 6, 0, 2);
pkt[8] = 64; pkt[9] = IPPROTO_UDP_UINT8;
memset(pkt + 10, 0, 2);
uint32_t sn = htonl(src_host), dn = htonl(dst_host);
uint32_t sn = tc_htonl(src_host), dn = tc_htonl(dst_host);
memcpy(pkt + 12, &sn, 4); memcpy(pkt + 16, &dn, 4);
uint16_t sp = htons(src_port_host), dp = htons(dst_port_host);
uint16_t sp = tc_htons(src_port_host), dp = tc_htons(dst_port_host);
memcpy(pkt + 20, &sp, 2); memcpy(pkt + 22, &dp, 2);
uint16_t ul = htons(8 + 14); memcpy(pkt + 24, &ul, 2);
uint16_t ul = tc_htons(8 + 14); memcpy(pkt + 24, &ul, 2);
memset(pkt + 26, 0, 2);
memset(pkt + 28, 0xAB, 14);
uint32_t sum = 0;
@ -81,7 +81,7 @@ static struct global_config make_config(uint16_t port_start, uint16_t port_end)
g.nat_port_start = port_start;
g.nat_port_end = port_end;
g.nat_tun_ip.family = AF_INET;
g.nat_tun_ip.addr.v4.s_addr = htonl(0x0A000001); // 10.0.0.1
g.nat_tun_ip.addr.v4.s_addr = tc_htonl(0x0A000001); // 10.0.0.1
return g;
}
@ -157,7 +157,7 @@ static void stress_table_full_and_lookup(void) {
ASSERT(entry != NULL, "entry non-null");
ASSERT_EQ(entry - ctx.table, ext_port, "entry index");
ASSERT_EQ(entry->internal_ip, 0x0A000002, "internal IP");
uint16_t expected_port_net = htons(40000 + i);
uint16_t expected_port_net = tc_htons(40000 + i);
ASSERT_EQ(entry->internal_port, expected_port_net, "internal port");
ASSERT(verify_ip_checksum(resp), "IP checksum");
free(resp);
@ -292,14 +292,14 @@ static void stress_tcp_mixed_with_udp(void) {
const size_t tcp_len = 20 + 20 + 14;
uint8_t* pkt = calloc(1, tcp_len);
pkt[0] = 0x45; pkt[1] = 0x00;
uint16_t tot = htons((uint16_t)tcp_len); memcpy(pkt + 2, &tot, 2);
uint16_t tot = tc_htons((uint16_t)tcp_len); memcpy(pkt + 2, &tot, 2);
pkt[4] = 0x12; pkt[5] = 0x34;
memset(pkt + 6, 0, 2);
pkt[8] = 64; pkt[9] = IPPROTO_TCP_UINT8;
memset(pkt + 10, 0, 2);
uint32_t sn = htonl(0x0A000002), dn = htonl(0x08080808);
uint32_t sn = tc_htonl(0x0A000002), dn = tc_htonl(0x08080808);
memcpy(pkt + 12, &sn, 4); memcpy(pkt + 16, &dn, 4);
uint16_t sp = htons(sport), dp = htons(80);
uint16_t sp = tc_htons(sport), dp = tc_htons(80);
memcpy(pkt + 20, &sp, 2); memcpy(pkt + 22, &dp, 2);
pkt[32] = 0x50;
memset(pkt + 36, 0, 2);
@ -338,14 +338,14 @@ static void stress_tcp_mixed_with_udp(void) {
const size_t tcp_len = 20 + 20 + 14;
uint8_t* resp = calloc(1, tcp_len);
resp[0] = 0x45; resp[1] = 0x00;
uint16_t tot = htons((uint16_t)tcp_len); memcpy(resp + 2, &tot, 2);
uint16_t tot = tc_htons((uint16_t)tcp_len); memcpy(resp + 2, &tot, 2);
resp[4] = 0x12; resp[5] = 0x34;
memset(resp + 6, 0, 2);
resp[8] = 64; resp[9] = IPPROTO_TCP_UINT8;
memset(resp + 10, 0, 2);
uint32_t sn = htonl(0x08080808), dn = htonl(0x0A000001);
uint32_t sn = tc_htonl(0x08080808), dn = tc_htonl(0x0A000001);
memcpy(resp + 12, &sn, 4); memcpy(resp + 16, &dn, 4);
uint16_t sp = htons(80), dp = htons(tcp_ext_port);
uint16_t sp = tc_htons(80), dp = tc_htons(tcp_ext_port);
memcpy(resp + 20, &sp, 2); memcpy(resp + 22, &dp, 2);
resp[32] = 0x50;
memset(resp + 36, 0, 2);
@ -382,16 +382,16 @@ static void stress_icmp_mixed(void) {
const size_t len = 20 + 8 + 14;
uint8_t* pkt = calloc(1, len);
pkt[0] = 0x45; pkt[1] = 0x00;
uint16_t tot = htons((uint16_t)len); memcpy(pkt + 2, &tot, 2);
uint16_t tot = tc_htons((uint16_t)len); memcpy(pkt + 2, &tot, 2);
pkt[4] = 0x12; pkt[5] = 0x34;
memset(pkt + 6, 0, 2);
pkt[8] = 64; pkt[9] = IPPROTO_ICMP_UINT8;
memset(pkt + 10, 0, 2);
uint32_t sn = htonl(0x0A000002), dn = htonl(0x08080808);
uint32_t sn = tc_htonl(0x0A000002), dn = tc_htonl(0x08080808);
memcpy(pkt + 12, &sn, 4); memcpy(pkt + 16, &dn, 4);
pkt[20] = 8; pkt[21] = 0;
memset(pkt + 22, 0, 2);
uint16_t id_n = htons(icmp_id), seq_n = htons(1);
uint16_t id_n = tc_htons(icmp_id), seq_n = tc_htons(1);
memcpy(pkt + 24, &id_n, 2); memcpy(pkt + 26, &seq_n, 2);
memset(pkt + 28, 0xDD, 14);
uint32_t sum = 0;
@ -427,16 +427,16 @@ static void stress_icmp_mixed(void) {
const size_t len = 20 + 8 + 14;
uint8_t* reply = calloc(1, len);
reply[0] = 0x45; reply[1] = 0x00;
uint16_t tot = htons((uint16_t)len); memcpy(reply + 2, &tot, 2);
uint16_t tot = tc_htons((uint16_t)len); memcpy(reply + 2, &tot, 2);
reply[4] = 0x12; reply[5] = 0x34;
memset(reply + 6, 0, 2);
reply[8] = 64; reply[9] = IPPROTO_ICMP_UINT8;
memset(reply + 10, 0, 2);
uint32_t sn = htonl(0x08080808), dn = htonl(0x0A000001);
uint32_t sn = tc_htonl(0x08080808), dn = tc_htonl(0x0A000001);
memcpy(reply + 12, &sn, 4); memcpy(reply + 16, &dn, 4);
reply[20] = 0; reply[21] = 0;
memset(reply + 22, 0, 2);
uint16_t ext_id_net = htons(icmp_ext), seq_n = htons(1);
uint16_t ext_id_net = tc_htons(icmp_ext), seq_n = tc_htons(1);
memcpy(reply + 24, &ext_id_net, 2); memcpy(reply + 26, &seq_n, 2);
memset(reply + 28, 0xDD, 14);
uint32_t sum = 0;

32
tests/test_nat_transport.c

@ -191,21 +191,21 @@ static uint8_t* build_udp_pkt(uint32_t src_host, uint16_t src_port_host,
uint8_t* pkt = calloc(1, len);
pkt[0] = 0x45; pkt[1] = 0x00;
uint16_t tot = htons((uint16_t)len);
uint16_t tot = tc_htons((uint16_t)len);
memcpy(pkt + 2, &tot, 2);
pkt[4] = 0x12; pkt[5] = 0x34;
memset(pkt + 6, 0, 2);
pkt[8] = 64;
pkt[9] = IPPROTO_UDP_UINT8;
memset(pkt + 10, 0, 2);
uint32_t sn = htonl(src_host), dn = htonl(dst_host);
uint32_t sn = tc_htonl(src_host), dn = tc_htonl(dst_host);
memcpy(pkt + 12, &sn, 4);
memcpy(pkt + 16, &dn, 4);
uint16_t sp = htons(src_port_host), dp = htons(dst_port_host);
uint16_t sp = tc_htons(src_port_host), dp = tc_htons(dst_port_host);
memcpy(pkt + 20, &sp, 2);
memcpy(pkt + 22, &dp, 2);
uint16_t ul = htons(8 + 14);
uint16_t ul = tc_htons(8 + 14);
memcpy(pkt + 24, &ul, 2);
memset(pkt + 26, 0, 2);
memset(pkt + 28, 0xAB, 14);
@ -344,7 +344,7 @@ static int test_provider_egress(void) {
test_state.egress_proto = e->proto;
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Provider egress: internal=%08x:%u proto=%u ext_port=%u node=%016llx",
e->internal_ip, ntohs(e->internal_port), e->proto,
e->internal_ip, tc_ntohs(e->internal_port), e->proto,
inst_provider->nat.port_start, (unsigned long long)e->src_node_id);
if (e->src_node_id != NODE_ID_CLIENT) {
@ -356,8 +356,8 @@ static int test_provider_egress(void) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "internal_ip mismatch: %08x", e->internal_ip);
return 0;
}
if (e->internal_port != htons(40000)) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "internal_port mismatch: %u vs 40000", ntohs(e->internal_port));
if (e->internal_port != tc_htons(40000)) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "internal_port mismatch: %u vs 40000", tc_ntohs(e->internal_port));
return 0;
}
if (e->proto != IPPROTO_UDP_UINT8) {
@ -436,15 +436,15 @@ static int test_provider_ingress_response(void) {
}
// Check dst IP = original internal IP
uint32_t dst_net; memcpy(&dst_net, test_state.captured + 16, 4);
uint32_t expected_dst = htonl(0x0A0000FE); // 10.0.0.254
uint32_t expected_dst = tc_htonl(0x0A0000FE); // 10.0.0.254
if (dst_net != expected_dst) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Response dst IP: %08x, expected %08x", ntohl(dst_net), ntohl(expected_dst));
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Response dst IP: %08x, expected %08x", tc_ntohl(dst_net), tc_ntohl(expected_dst));
return 0;
}
// Check dst port = original internal port
uint16_t dst_port_net; memcpy(&dst_port_net, test_state.captured + 22, 2);
if (dst_port_net != htons(40000)) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Response dst port: %u, expected 40000", ntohs(dst_port_net));
if (dst_port_net != tc_htons(40000)) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Response dst port: %u, expected 40000", tc_ntohs(dst_port_net));
return 0;
}
@ -495,13 +495,13 @@ static int test_full_roundtrip(void) {
// Verify NAT entry
struct eim_nat_entry* e = &inst_provider->nat.table[inst_provider->nat.port_start];
if (e->state != EIM_NAT_ENTRY_ACTIVE || e->internal_ip != 0x0A0000CD || e->internal_port != htons(44444)) {
if (e->state != EIM_NAT_ENTRY_ACTIVE || e->internal_ip != 0x0A0000CD || e->internal_port != tc_htons(44444)) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Egress entry not found: ip=%08x port=%u state=%d",
e->internal_ip, ntohs(e->internal_port), e->state);
e->internal_ip, tc_ntohs(e->internal_port), e->state);
return 0;
}
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Egress entry ok: %08x:%u ext=%u proto=%u",
e->internal_ip, ntohs(e->internal_port), inst_provider->nat.port_start, e->proto);
e->internal_ip, tc_ntohs(e->internal_port), inst_provider->nat.port_start, e->proto);
// === Step 2: Manually inject internet response into provider's TUN ===
if (client_tun->output_queue) queue_set_callback(client_tun->output_queue, capture_tun_out_cb, NULL);
@ -528,9 +528,9 @@ static int test_full_roundtrip(void) {
// Verify captured response
if (!verify_ip_checksum(test_state.captured)) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Captured IP checksum invalid"); return 0; }
uint32_t dst_net; memcpy(&dst_net, test_state.captured + 16, 4);
if (dst_net != htonl(0x0A0000CD)) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Roundtrip dst IP mismatch"); return 0; }
if (dst_net != tc_htonl(0x0A0000CD)) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Roundtrip dst IP mismatch"); return 0; }
uint16_t dp_net; memcpy(&dp_net, test_state.captured + 22, 2);
if (dp_net != htons(44444)) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Roundtrip dst port mismatch"); return 0; }
if (dp_net != tc_htons(44444)) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Roundtrip dst port mismatch"); return 0; }
return 1;
}

Loading…
Cancel
Save