|
|
|
|
@ -54,10 +54,13 @@ static int exit_send_echo(struct UTUN_INSTANCE* inst, uint64_t client_node_id,
|
|
|
|
|
while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); |
|
|
|
|
icmp_hdr->icmp_cksum = ~(uint16_t)sum; |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: sendto dst=0x%08x id=0x%04x seq=%u len=%zu", |
|
|
|
|
dst_ip, echo_id, echo_seq, icmp_len); |
|
|
|
|
struct sockaddr_in addr = {.sin_family = AF_INET, .sin_addr = {.s_addr = dst_ip}}; |
|
|
|
|
ssize_t n = sendto(g_icmp_ctx->raw_sock, buf, icmp_len, 0, (struct sockaddr*)&addr, sizeof(addr)); |
|
|
|
|
u_free(buf); |
|
|
|
|
if (n < 0) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: sendto failed: %s", strerror(errno)); return -1; } |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: sendto sent %zd bytes", n); |
|
|
|
|
|
|
|
|
|
struct icmp_request* r = u_calloc(1, sizeof(struct icmp_request)); |
|
|
|
|
if (!r) return 0; |
|
|
|
|
@ -77,6 +80,7 @@ static void raw_read_cb(socket_t sock, void* arg) {
|
|
|
|
|
uint8_t buf[65536]; |
|
|
|
|
struct sockaddr_in from; socklen_t flen = sizeof(from); |
|
|
|
|
ssize_t n = recvfrom(g_icmp_ctx->raw_sock, buf, sizeof(buf), 0, (struct sockaddr*)&from, &flen); |
|
|
|
|
if (n <= 0) { if (n < 0) DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: recvfrom error: %s", strerror(errno)); return; } |
|
|
|
|
if (n < (ssize_t)(sizeof(struct ip) + ICMP_MINLEN)) return; |
|
|
|
|
|
|
|
|
|
struct ip* ip_hdr = (struct ip*)buf; |
|
|
|
|
@ -88,6 +92,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) return; |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
size_t payload_len = n - ip_hdr_len - ICMP_MINLEN; |
|
|
|
|
if (payload_len > 1500) payload_len = 1500; |
|
|
|
|
@ -125,6 +131,7 @@ static void exit_handle_request(struct ETCP_CONN* conn, struct ll_entry* entry)
|
|
|
|
|
if (g_icmp_ctx->raw_sock != SOCKET_INVALID) { |
|
|
|
|
exit_send_echo(inst, client_node_id, dst_ip, echo_id, echo_seq, payload, payload_len); |
|
|
|
|
} else if (g_icmp_ctx->test_loopback) { |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: test loopback reply to 0x%08x", dst_ip); |
|
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
|
if (e) { |
|
|
|
|
e->dgram = u_malloc(ICMP_PROXY_HDR_SIZE + payload_len); |
|
|
|
|
@ -269,10 +276,11 @@ int icmp_proxy_init(struct UTUN_INSTANCE* inst, struct UASYNC* ua) {
|
|
|
|
|
g_icmp_ctx = ctx; |
|
|
|
|
|
|
|
|
|
if (ctx->is_exit) { |
|
|
|
|
ctx->raw_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); |
|
|
|
|
ctx->raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); |
|
|
|
|
if (ctx->raw_sock == SOCKET_INVALID) |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: raw socket failed (need root): %s", strerror(errno)); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: raw socket(SOCK_RAW) failed: %s", strerror(errno)); |
|
|
|
|
else { |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: raw socket created fd=%d", ctx->raw_sock); |
|
|
|
|
ctx->raw_read_id = uasync_add_socket(ua, ctx->raw_sock, raw_read_cb, NULL, NULL, NULL); |
|
|
|
|
if (!ctx->raw_read_id) { socket_close_wrapper(ctx->raw_sock); ctx->raw_sock = SOCKET_INVALID; } |
|
|
|
|
} |
|
|
|
|
|