#ifndef UTUN_TEST_HOOKS_H #define UTUN_TEST_HOOKS_H #include #include #include #include #include // 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