|
|
|
@ -34,7 +34,7 @@ static struct icmp_request* req_find_by_id(struct icmp_request* head, uint16_t e |
|
|
|
|
|
|
|
|
|
|
|
// Build and send a raw ICMP echo request
|
|
|
|
// Build and send a raw ICMP echo request
|
|
|
|
static int exit_send_echo(struct UTUN_INSTANCE* inst, uint64_t client_node_id, |
|
|
|
static int exit_send_echo(struct UTUN_INSTANCE* inst, uint64_t client_node_id, |
|
|
|
uint32_t dst_ip, uint16_t echo_id, uint16_t echo_seq, |
|
|
|
uint32_t dst_ip, uint32_t orig_src_ip, uint16_t echo_id, uint16_t echo_seq, |
|
|
|
const uint8_t* payload, size_t payload_len) { |
|
|
|
const uint8_t* payload, size_t payload_len) { |
|
|
|
if (!g_icmp_ctx || g_icmp_ctx->raw_sock == SOCKET_INVALID) return -1; |
|
|
|
if (!g_icmp_ctx || g_icmp_ctx->raw_sock == SOCKET_INVALID) return -1; |
|
|
|
size_t icmp_len = ICMP_MINLEN + payload_len; |
|
|
|
size_t icmp_len = ICMP_MINLEN + payload_len; |
|
|
|
@ -64,7 +64,7 @@ static int exit_send_echo(struct UTUN_INSTANCE* inst, uint64_t client_node_id, |
|
|
|
|
|
|
|
|
|
|
|
struct icmp_request* r = u_calloc(1, sizeof(struct icmp_request)); |
|
|
|
struct icmp_request* r = u_calloc(1, sizeof(struct icmp_request)); |
|
|
|
if (!r) return 0; |
|
|
|
if (!r) return 0; |
|
|
|
r->client_node_id = client_node_id; r->dst_ip = dst_ip; |
|
|
|
r->client_node_id = client_node_id; r->dst_ip = dst_ip; r->orig_src_ip = orig_src_ip; |
|
|
|
r->echo_id = echo_id; r->echo_seq = echo_seq; |
|
|
|
r->echo_id = echo_id; r->echo_seq = echo_seq; |
|
|
|
r->payload_len = payload_len > sizeof(r->payload) ? sizeof(r->payload) : payload_len; |
|
|
|
r->payload_len = payload_len > sizeof(r->payload) ? sizeof(r->payload) : payload_len; |
|
|
|
if (payload_len > 0) memcpy(r->payload, payload, r->payload_len); |
|
|
|
if (payload_len > 0) memcpy(r->payload, payload, r->payload_len); |
|
|
|
@ -108,8 +108,9 @@ static void raw_read_cb(socket_t sock, void* arg) { |
|
|
|
e->dgram[1] = ICMP_PROXY_SUBCMD_REPLY; |
|
|
|
e->dgram[1] = ICMP_PROXY_SUBCMD_REPLY; |
|
|
|
memcpy(e->dgram + 2, &r->client_node_id, 8); |
|
|
|
memcpy(e->dgram + 2, &r->client_node_id, 8); |
|
|
|
memcpy(e->dgram + 10, &r->dst_ip, 4); |
|
|
|
memcpy(e->dgram + 10, &r->dst_ip, 4); |
|
|
|
memcpy(e->dgram + 14, &icmp_hdr->icmp_id, 2); |
|
|
|
memcpy(e->dgram + 14, &r->orig_src_ip, 4); |
|
|
|
memcpy(e->dgram + 16, &icmp_hdr->icmp_seq, 2); |
|
|
|
memcpy(e->dgram + 18, &icmp_hdr->icmp_id, 2); |
|
|
|
|
|
|
|
memcpy(e->dgram + 20, &icmp_hdr->icmp_seq, 2); |
|
|
|
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); |
|
|
|
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); |
|
|
|
e->len = ICMP_PROXY_HDR_SIZE + payload_len; |
|
|
|
e->len = ICMP_PROXY_HDR_SIZE + payload_len; |
|
|
|
int ret = etcp_route_send(g_icmp_ctx->inst, r->client_node_id, e); |
|
|
|
int ret = etcp_route_send(g_icmp_ctx->inst, r->client_node_id, e); |
|
|
|
@ -125,14 +126,15 @@ static void exit_handle_request(struct ETCP_CONN* conn, struct ll_entry* entry) |
|
|
|
if (!inst || !g_icmp_ctx || entry->len < ICMP_PROXY_HDR_SIZE + 1) goto drop; |
|
|
|
if (!inst || !g_icmp_ctx || entry->len < ICMP_PROXY_HDR_SIZE + 1) goto drop; |
|
|
|
|
|
|
|
|
|
|
|
uint64_t client_node_id; memcpy(&client_node_id, entry->dgram + 2, 8); |
|
|
|
uint64_t client_node_id; memcpy(&client_node_id, entry->dgram + 2, 8); |
|
|
|
uint32_t dst_ip; memcpy(&dst_ip, entry->dgram + 10, 4); |
|
|
|
uint32_t dst_ip; memcpy(&dst_ip, entry->dgram + 10, 4); |
|
|
|
uint16_t echo_id; memcpy(&echo_id, entry->dgram + 14, 2); |
|
|
|
uint32_t orig_src_ip; memcpy(&orig_src_ip, entry->dgram + 14, 4); |
|
|
|
uint16_t echo_seq; memcpy(&echo_seq, entry->dgram + 16, 2); |
|
|
|
uint16_t echo_id; memcpy(&echo_id, entry->dgram + 18, 2); |
|
|
|
|
|
|
|
uint16_t echo_seq; memcpy(&echo_seq, entry->dgram + 20, 2); |
|
|
|
uint8_t* payload = entry->dgram + ICMP_PROXY_HDR_SIZE; |
|
|
|
uint8_t* payload = entry->dgram + ICMP_PROXY_HDR_SIZE; |
|
|
|
size_t payload_len = entry->len - ICMP_PROXY_HDR_SIZE; |
|
|
|
size_t payload_len = entry->len - ICMP_PROXY_HDR_SIZE; |
|
|
|
|
|
|
|
|
|
|
|
if (g_icmp_ctx->raw_sock != SOCKET_INVALID) { |
|
|
|
if (g_icmp_ctx->raw_sock != SOCKET_INVALID) { |
|
|
|
exit_send_echo(inst, client_node_id, dst_ip, echo_id, echo_seq, payload, payload_len); |
|
|
|
exit_send_echo(inst, client_node_id, dst_ip, orig_src_ip, echo_id, echo_seq, payload, payload_len); |
|
|
|
} else if (g_icmp_ctx->test_loopback) { |
|
|
|
} else if (g_icmp_ctx->test_loopback) { |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: test loopback reply to 0x%08x", dst_ip); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: test loopback reply to 0x%08x", dst_ip); |
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
@ -143,8 +145,9 @@ static void exit_handle_request(struct ETCP_CONN* conn, struct ll_entry* entry) |
|
|
|
e->dgram[1] = ICMP_PROXY_SUBCMD_REPLY; |
|
|
|
e->dgram[1] = ICMP_PROXY_SUBCMD_REPLY; |
|
|
|
memcpy(e->dgram + 2, &client_node_id, 8); |
|
|
|
memcpy(e->dgram + 2, &client_node_id, 8); |
|
|
|
memcpy(e->dgram + 10, &dst_ip, 4); |
|
|
|
memcpy(e->dgram + 10, &dst_ip, 4); |
|
|
|
memcpy(e->dgram + 14, &echo_id, 2); |
|
|
|
memcpy(e->dgram + 14, &orig_src_ip, 4); |
|
|
|
memcpy(e->dgram + 16, &echo_seq, 2); |
|
|
|
memcpy(e->dgram + 18, &echo_id, 2); |
|
|
|
|
|
|
|
memcpy(e->dgram + 20, &echo_seq, 2); |
|
|
|
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); |
|
|
|
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); |
|
|
|
e->len = ICMP_PROXY_HDR_SIZE + payload_len; |
|
|
|
e->len = ICMP_PROXY_HDR_SIZE + payload_len; |
|
|
|
etcp_route_send(inst, client_node_id, e); |
|
|
|
etcp_route_send(inst, client_node_id, e); |
|
|
|
@ -164,14 +167,16 @@ drop: |
|
|
|
static void client_handle_reply(struct ETCP_CONN* conn, struct ll_entry* entry) { |
|
|
|
static void client_handle_reply(struct ETCP_CONN* conn, struct ll_entry* entry) { |
|
|
|
if (entry->len < ICMP_PROXY_HDR_SIZE + 1) { queue_entry_free(entry); queue_dgram_free(entry); return; } |
|
|
|
if (entry->len < ICMP_PROXY_HDR_SIZE + 1) { queue_entry_free(entry); queue_dgram_free(entry); return; } |
|
|
|
uint32_t src_ip; |
|
|
|
uint32_t src_ip; |
|
|
|
|
|
|
|
uint32_t orig_src_ip; |
|
|
|
uint16_t echo_id, echo_seq; |
|
|
|
uint16_t echo_id, echo_seq; |
|
|
|
memcpy(&src_ip, entry->dgram + 10, 4); |
|
|
|
memcpy(&src_ip, entry->dgram + 10, 4); |
|
|
|
memcpy(&echo_id, entry->dgram + 14, 2); |
|
|
|
memcpy(&orig_src_ip, entry->dgram + 14, 4); |
|
|
|
memcpy(&echo_seq, entry->dgram + 16, 2); |
|
|
|
memcpy(&echo_id, entry->dgram + 18, 2); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: client got reply id=0x%04x seq=%u from=0x%08x", |
|
|
|
memcpy(&echo_seq, entry->dgram + 20, 2); |
|
|
|
echo_id, echo_seq, src_ip); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: client got reply id=0x%04x seq=%u from=0x%08x dst=0x%08x", |
|
|
|
|
|
|
|
echo_id, echo_seq, src_ip, orig_src_ip); |
|
|
|
struct UTUN_INSTANCE* inst = conn ? conn->instance : (g_icmp_ctx ? g_icmp_ctx->inst : NULL); |
|
|
|
struct UTUN_INSTANCE* inst = conn ? conn->instance : (g_icmp_ctx ? g_icmp_ctx->inst : NULL); |
|
|
|
icmp_proxy_deliver_reply(inst, src_ip, echo_id, echo_seq, |
|
|
|
icmp_proxy_deliver_reply(inst, orig_src_ip, src_ip, echo_id, echo_seq, |
|
|
|
entry->dgram + ICMP_PROXY_HDR_SIZE, entry->len - ICMP_PROXY_HDR_SIZE); |
|
|
|
entry->dgram + ICMP_PROXY_HDR_SIZE, entry->len - ICMP_PROXY_HDR_SIZE); |
|
|
|
queue_entry_free(entry); queue_dgram_free(entry); |
|
|
|
queue_entry_free(entry); queue_dgram_free(entry); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -194,7 +199,7 @@ void icmp_proxy_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) { |
|
|
|
// Client side: send ICMP echo request to exit node
|
|
|
|
// Client side: send ICMP echo request to exit node
|
|
|
|
// ====================================================================
|
|
|
|
// ====================================================================
|
|
|
|
int icmp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id, |
|
|
|
int icmp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id, |
|
|
|
uint32_t dst_ip, uint16_t echo_id, uint16_t echo_seq, |
|
|
|
uint32_t dst_ip, uint32_t orig_src_ip, uint16_t echo_id, uint16_t echo_seq, |
|
|
|
const uint8_t* payload, size_t payload_len) { |
|
|
|
const uint8_t* payload, size_t payload_len) { |
|
|
|
if (!inst) return -1; |
|
|
|
if (!inst) return -1; |
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
@ -205,8 +210,9 @@ int icmp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id, |
|
|
|
e->dgram[1] = ICMP_PROXY_SUBCMD_REQUEST; |
|
|
|
e->dgram[1] = ICMP_PROXY_SUBCMD_REQUEST; |
|
|
|
memcpy(e->dgram + 2, &inst->node_id, 8); |
|
|
|
memcpy(e->dgram + 2, &inst->node_id, 8); |
|
|
|
memcpy(e->dgram + 10, &dst_ip, 4); |
|
|
|
memcpy(e->dgram + 10, &dst_ip, 4); |
|
|
|
memcpy(e->dgram + 14, &echo_id, 2); |
|
|
|
memcpy(e->dgram + 14, &orig_src_ip, 4); |
|
|
|
memcpy(e->dgram + 16, &echo_seq, 2); |
|
|
|
memcpy(e->dgram + 18, &echo_id, 2); |
|
|
|
|
|
|
|
memcpy(e->dgram + 20, &echo_seq, 2); |
|
|
|
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); |
|
|
|
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); |
|
|
|
e->len = ICMP_PROXY_HDR_SIZE + payload_len; |
|
|
|
e->len = ICMP_PROXY_HDR_SIZE + payload_len; |
|
|
|
return etcp_route_send(inst, exit_node_id, e); |
|
|
|
return etcp_route_send(inst, exit_node_id, e); |
|
|
|
@ -216,7 +222,7 @@ int icmp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id, |
|
|
|
// Client side: deliver ICMP echo reply to TUN
|
|
|
|
// Client side: deliver ICMP echo reply to TUN
|
|
|
|
// ====================================================================
|
|
|
|
// ====================================================================
|
|
|
|
int icmp_proxy_deliver_reply(struct UTUN_INSTANCE* inst, |
|
|
|
int icmp_proxy_deliver_reply(struct UTUN_INSTANCE* inst, |
|
|
|
uint32_t src_ip, uint16_t echo_id, uint16_t echo_seq, |
|
|
|
uint32_t dst_ip, uint32_t src_ip, uint16_t echo_id, uint16_t echo_seq, |
|
|
|
const uint8_t* payload, size_t payload_len) { |
|
|
|
const uint8_t* payload, size_t payload_len) { |
|
|
|
if (!inst || !inst->tcp_proxy || !inst->tcp_proxy->tun) { |
|
|
|
if (!inst || !inst->tcp_proxy || !inst->tcp_proxy->tun) { |
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: deliver_reply failed — no %s", |
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: deliver_reply failed — no %s", |
|
|
|
@ -224,7 +230,6 @@ int icmp_proxy_deliver_reply(struct UTUN_INSTANCE* inst, |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
struct tun_if* tun = inst->tcp_proxy->tun; |
|
|
|
struct tun_if* tun = inst->tcp_proxy->tun; |
|
|
|
uint32_t dst_ip = inst->tcp_proxy->tun_ip_addr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t icmp_len = ICMP_MINLEN + payload_len; |
|
|
|
size_t icmp_len = ICMP_MINLEN + payload_len; |
|
|
|
size_t pkt_len = 20 + icmp_len; |
|
|
|
size_t pkt_len = 20 + icmp_len; |
|
|
|
|