|
|
|
|
@ -26,6 +26,9 @@
|
|
|
|
|
|
|
|
|
|
static struct icmp_proxy_ctx* g_icmp_ctx = NULL; |
|
|
|
|
|
|
|
|
|
static void req_expire_timer_cb(void* arg); |
|
|
|
|
static void req_expire(struct icmp_proxy_ctx* ctx); |
|
|
|
|
|
|
|
|
|
static struct icmp_request* req_find_by_id(struct icmp_request* head, uint16_t echo_id, uint16_t echo_seq) { |
|
|
|
|
struct icmp_request* r; |
|
|
|
|
for (r = head; r; r = r->next) if (r->echo_id == echo_id && r->echo_seq == echo_seq) return r; |
|
|
|
|
@ -70,6 +73,8 @@ static int exit_send_echo(struct UTUN_INSTANCE* inst, uint64_t client_node_id,
|
|
|
|
|
if (payload_len > 0) memcpy(r->payload, payload, r->payload_len); |
|
|
|
|
r->sent_tb = get_time_tb(); |
|
|
|
|
r->next = g_icmp_ctx->pending; g_icmp_ctx->pending = r; |
|
|
|
|
if (!g_icmp_ctx->expire_timer) |
|
|
|
|
g_icmp_ctx->expire_timer = uasync_set_timeout(g_icmp_ctx->ua, g_icmp_ctx->request_timeout_tb, g_icmp_ctx, req_expire_timer_cb, "icmp_expire"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -93,6 +98,8 @@ static void raw_read_cb(socket_t sock, void* arg) {
|
|
|
|
|
struct icmp_request* r = req_find_by_id(g_icmp_ctx->pending, icmp_hdr->icmp_id, icmp_hdr->icmp_seq); |
|
|
|
|
if (!r) { DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "icmp_proxy: unclaimed echo reply id=0x%04x seq=%u from=0x%08x", |
|
|
|
|
icmp_hdr->icmp_id, icmp_hdr->icmp_seq, from.sin_addr.s_addr); return; } |
|
|
|
|
{ struct icmp_request** rp = &g_icmp_ctx->pending; |
|
|
|
|
while (*rp) { if (*rp == r) { *rp = r->next; break; } rp = &(*rp)->next; } } |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: echo reply id=0x%04x seq=%u from=0x%08x", |
|
|
|
|
icmp_hdr->icmp_id, icmp_hdr->icmp_seq, from.sin_addr.s_addr); |
|
|
|
|
|
|
|
|
|
@ -116,6 +123,7 @@ static void raw_read_cb(socket_t sock, void* arg) {
|
|
|
|
|
int ret = etcp_route_send(g_icmp_ctx->inst, r->client_node_id, e); |
|
|
|
|
if (ret != 0) DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: etcp_route_send reply failed: %d", ret); |
|
|
|
|
else DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: reply forwarded to client %016llx", (unsigned long long)r->client_node_id); |
|
|
|
|
u_free(r); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ====================================================================
|
|
|
|
|
@ -272,6 +280,14 @@ void icmp_proxy_set_test_loopback(struct UTUN_INSTANCE* inst, int enabled) {
|
|
|
|
|
if (g_icmp_ctx) g_icmp_ctx->test_loopback = enabled; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void req_expire_timer_cb(void* arg) { |
|
|
|
|
struct icmp_proxy_ctx* ctx = (struct icmp_proxy_ctx*)arg; |
|
|
|
|
req_expire(ctx); |
|
|
|
|
ctx->expire_timer = NULL; |
|
|
|
|
if (ctx->pending) |
|
|
|
|
ctx->expire_timer = uasync_set_timeout(ctx->ua, ctx->request_timeout_tb, ctx, req_expire_timer_cb, "icmp_expire"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void req_expire(struct icmp_proxy_ctx* ctx) { |
|
|
|
|
uint64_t now = get_time_tb(); struct icmp_request** prev = &ctx->pending; |
|
|
|
|
while (*prev) { |
|
|
|
|
@ -292,6 +308,7 @@ int icmp_proxy_init(struct UTUN_INSTANCE* inst, struct UASYNC* ua) {
|
|
|
|
|
ctx->request_timeout_tb = ICMP_TIMEOUT_TB; |
|
|
|
|
ctx->is_exit = inst->remote_proxy.enabled; |
|
|
|
|
ctx->test_loopback = 0; |
|
|
|
|
ctx->expire_timer = NULL; |
|
|
|
|
g_icmp_ctx = ctx; |
|
|
|
|
|
|
|
|
|
if (ctx->is_exit) { |
|
|
|
|
@ -314,6 +331,7 @@ int icmp_proxy_init(struct UTUN_INSTANCE* inst, struct UASYNC* ua) {
|
|
|
|
|
void icmp_proxy_destroy(struct UTUN_INSTANCE* inst) { |
|
|
|
|
if (!inst || !g_icmp_ctx) return; |
|
|
|
|
etcp_router_unbind(inst, ETCP_ID_ICMP_PROXY); |
|
|
|
|
if (g_icmp_ctx->expire_timer) { uasync_cancel_timeout(g_icmp_ctx->ua, g_icmp_ctx->expire_timer); g_icmp_ctx->expire_timer = NULL; } |
|
|
|
|
if (g_icmp_ctx->raw_sock != SOCKET_INVALID) { |
|
|
|
|
if (g_icmp_ctx->raw_read_id) { uasync_remove_socket_t(g_icmp_ctx->ua, g_icmp_ctx->raw_sock); g_icmp_ctx->raw_read_id = NULL; } |
|
|
|
|
socket_close_wrapper(g_icmp_ctx->raw_sock); |
|
|
|
|
|