You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
5.1 KiB
126 lines
5.1 KiB
#ifndef UTUN_TEST_HOOKS_H |
|
#define UTUN_TEST_HOOKS_H |
|
|
|
#include <sys/types.h> |
|
#include <sys/socket.h> |
|
#include <stdint.h> |
|
#include <stddef.h> |
|
#include <unistd.h> |
|
|
|
// Forward declarations |
|
struct UTUN_INSTANCE; |
|
struct ETCP_SOCKET; |
|
|
|
// UDP packet interception callbacks |
|
typedef ssize_t (*utun_sendto_hook_t)(int sockfd, const void *buf, size_t len, int flags, |
|
const struct sockaddr *dest_addr, socklen_t addrlen, |
|
void* context); |
|
typedef ssize_t (*utun_recvfrom_hook_t)(int sockfd, void *buf, size_t len, int flags, |
|
struct sockaddr *src_addr, socklen_t *addrlen, |
|
void* context); |
|
|
|
// TUN virtual interface callbacks |
|
typedef int (*tun_create_hook_t)(void* priv_data); |
|
typedef ssize_t (*tun_read_hook_t)(int fd, void *buf, size_t count, void* priv_data); |
|
typedef ssize_t (*tun_write_hook_t)(int fd, const void *buf, size_t count, void* priv_data); |
|
|
|
// Socket creation callback |
|
typedef int (*socket_create_hook_t)(int domain, int type, int protocol, void* context); |
|
|
|
// Test packet capture callback |
|
typedef void (*packet_capture_hook_t)(struct UTUN_INSTANCE* instance, |
|
const uint8_t* packet, size_t len, |
|
const char* direction, // "tun_in", "tun_out", "udp_in", "udp_out" |
|
void* context); |
|
|
|
struct utun_test_hooks { |
|
// UDP socket hooks |
|
utun_sendto_hook_t sendto_override; |
|
utun_recvfrom_hook_t recvfrom_override; |
|
|
|
// TUN hooks |
|
tun_create_hook_t tun_create_override; |
|
tun_read_hook_t tun_read_override; |
|
tun_write_hook_t tun_write_override; |
|
|
|
// Socket creation hook |
|
socket_create_hook_t socket_create_override; |
|
|
|
// Packet capture |
|
packet_capture_hook_t packet_captured; |
|
|
|
// Context for callbacks |
|
void* test_context; |
|
}; |
|
|
|
// Global test hooks - NULL in production, set only by test code |
|
extern struct utun_test_hooks* g_utun_test_hooks; |
|
|
|
// Test-aware wrapper functions - inline for zero overhead when NULL |
|
static inline ssize_t utun_sendto_hook(int sockfd, const void *buf, size_t len, int flags, |
|
const struct sockaddr *dest_addr, socklen_t addrlen) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->sendto_override) { |
|
return g_utun_test_hooks->sendto_override(sockfd, buf, len, flags, dest_addr, addrlen, |
|
g_utun_test_hooks->test_context); |
|
} |
|
return sendto(sockfd, buf, len, flags, dest_addr, addrlen); |
|
} |
|
|
|
static inline ssize_t utun_recvfrom_hook(int sockfd, void *buf, size_t len, int flags, |
|
struct sockaddr *src_addr, socklen_t *addrlen) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->recvfrom_override) { |
|
return g_utun_test_hooks->recvfrom_override(sockfd, buf, len, flags, src_addr, addrlen, |
|
g_utun_test_hooks->test_context); |
|
} |
|
return recvfrom(sockfd, buf, len, flags, src_addr, addrlen); |
|
} |
|
|
|
static inline int tun_create_hook(void* priv_data) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->tun_create_override) { |
|
return g_utun_test_hooks->tun_create_override(priv_data); |
|
} |
|
return -1; // Default: no TUN available in test mode |
|
} |
|
|
|
static inline ssize_t tun_read_hook(int fd, void *buf, size_t count, void* priv_data) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->tun_read_override) { |
|
return g_utun_test_hooks->tun_read_override(fd, buf, count, priv_data); |
|
} |
|
return read(fd, buf, count); |
|
} |
|
|
|
static inline ssize_t tun_write_hook(int fd, const void *buf, size_t count, void* priv_data) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->tun_write_override) { |
|
return g_utun_test_hooks->tun_write_override(fd, buf, count, priv_data); |
|
} |
|
return write(fd, buf, count); |
|
} |
|
|
|
static inline int socket_create_hook(int domain, int type, int protocol) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->socket_create_override) { |
|
return g_utun_test_hooks->socket_create_override(domain, type, protocol, |
|
g_utun_test_hooks->test_context); |
|
} |
|
return socket(domain, type, protocol); |
|
} |
|
|
|
static inline void packet_capture_hook(struct UTUN_INSTANCE* instance, |
|
const uint8_t* packet, size_t len, |
|
const char* direction) { |
|
if (g_utun_test_hooks && g_utun_test_hooks->packet_captured) { |
|
g_utun_test_hooks->packet_captured(instance, packet, len, direction, |
|
g_utun_test_hooks->test_context); |
|
} |
|
} |
|
|
|
// Functions to set/clear test hooks (only available in test builds) |
|
#ifdef TEST_BUILD |
|
void utun_test_hooks_set(struct utun_test_hooks* hooks); |
|
void utun_test_hooks_clear(void); |
|
#else |
|
// In production builds, these are no-ops for safety |
|
static inline void utun_test_hooks_set(struct utun_test_hooks* hooks) { (void)hooks; } |
|
static inline void utun_test_hooks_clear(void) {} |
|
#endif |
|
|
|
#endif // UTUN_TEST_HOOKS_H
|