fix use-after-free in queue_entry_free/dgram_free ordering + add tcp_proxy stress test + proxy diagnostics logging
- Fix queue_entry_free before queue_dgram_free in all proxy files (UAF bug causing segfault) - Add PROXY/RP prefixed diagnostic logs for transparent proxy flow tracking - Add tcp_proxy integration test: real utun instances, ETCP, remote_proxy, DNAT routing - 7 test scenarios: basic_1mb, concurrent_5, concurrent_20, half_close, idle, conn_refused, stress (10 threads x 20 iterations) - stress_client.py with --verbose per-thread phase timing (connect/send/recv)
This commit is contained in:
1 parent
2585ef6f29
commit
a02c474b94
13 files changed
+673
-56
No files matched your search
+13
-13
@@ -12,14 +12,14 @@
|
||||
// Обработчик ETCP_ID_SVC_ROUTE — вызывается etcp_int_recv на каждом узле
|
||||
static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
if (!conn || !entry) {
|
||||
if (entry) { queue_entry_free(entry); queue_dgram_free(entry); }
|
||||
if (entry) { queue_dgram_free(entry); queue_entry_free(entry); }
|
||||
return;
|
||||
}
|
||||
struct UTUN_INSTANCE* inst = conn->instance;
|
||||
if (!inst || entry->len < SVC_ROUTE_HDR_SIZE) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "etcp_router: invalid packet inst=%p len=%zu min=%d",
|
||||
(void*)inst, entry ? entry->len : 0, SVC_ROUTE_HDR_SIZE);
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
uint8_t svc_id = entry->dgram[1];
|
||||
@@ -28,21 +28,21 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
if (!inst->router_bindings.callbacks[svc_id]) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "etcp_router: no handler for svc_id=%u dst=%016llx self=%016llx",
|
||||
svc_id, (unsigned long long)dst_node_id, (unsigned long long)inst->node_id);
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
size_t payload_len = entry->len - SVC_ROUTE_HDR_SIZE;
|
||||
struct ll_entry* svc_entry = queue_entry_new(0);
|
||||
if (!svc_entry) { queue_entry_free(entry); queue_dgram_free(entry); return; }
|
||||
if (!svc_entry) { queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
svc_entry->len = 1 + payload_len;
|
||||
svc_entry->dgram = u_malloc(svc_entry->len);
|
||||
if (!svc_entry->dgram) { queue_entry_free(svc_entry); queue_entry_free(entry); queue_dgram_free(entry); return; }
|
||||
if (!svc_entry->dgram) { queue_entry_free(svc_entry); queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
svc_entry->dgram[0] = svc_id;
|
||||
if (payload_len > 0) memcpy(svc_entry->dgram + 1, entry->dgram + SVC_ROUTE_HDR_SIZE, payload_len);
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "etcp_router: delivering svc_id=%u len=%zu to handler %p src=%016llx",
|
||||
svc_id, payload_len, (void*)inst->router_bindings.callbacks[svc_id],
|
||||
(unsigned long long)(*(uint64_t*)(entry->dgram + 10)));
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
inst->router_bindings.callbacks[svc_id](conn, svc_entry);
|
||||
if (svc_id == ETCP_ID_ICMP_PROXY)
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_router: ICMP_PROXY reply delivered to handler self=%016llx",
|
||||
@@ -52,7 +52,7 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
if (!next) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "etcp_router: no route to %016llx svc_id=%u, dropping",
|
||||
(unsigned long long)dst_node_id, svc_id);
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "etcp_router: forwarding svc_id=%u → %016llx via %s",
|
||||
@@ -101,12 +101,12 @@ int etcp_router_unbind(struct UTUN_INSTANCE* inst, uint8_t svc_id) {
|
||||
int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_entry* entry) {
|
||||
if (!inst || !entry) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_route_send: NULL inst=%p entry=%p", (void*)inst, (void*)entry);
|
||||
if (entry) { queue_entry_free(entry); queue_dgram_free(entry); }
|
||||
if (entry) { queue_dgram_free(entry); queue_entry_free(entry); }
|
||||
return -1;
|
||||
}
|
||||
if (!entry->dgram || entry->len < 1) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_route_send: empty entry");
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return -1;
|
||||
}
|
||||
uint8_t svc_id = entry->dgram[0];
|
||||
@@ -117,14 +117,14 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "etcp_route_send: loopback svc_id=%u len=%zu", svc_id, payload_len);
|
||||
if (inst->router_bindings.callbacks[svc_id])
|
||||
inst->router_bindings.callbacks[svc_id](NULL, entry);
|
||||
else { queue_entry_free(entry); queue_dgram_free(entry); }
|
||||
else { queue_dgram_free(entry); queue_entry_free(entry); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Упаковываем в routing header
|
||||
size_t total_len = SVC_ROUTE_HDR_SIZE + payload_len;
|
||||
uint8_t* new_dgram = u_malloc(total_len);
|
||||
if (!new_dgram) { queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!new_dgram) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
new_dgram[0] = ETCP_ID_SVC_ROUTE;
|
||||
new_dgram[1] = svc_id;
|
||||
memcpy(new_dgram + 2, &dst_node_id, 8);
|
||||
@@ -132,11 +132,11 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_
|
||||
if (payload_len > 0) memcpy(new_dgram + SVC_ROUTE_HDR_SIZE, entry->dgram + 1, payload_len);
|
||||
|
||||
struct ll_entry* new_entry = queue_entry_new(0);
|
||||
if (!new_entry) { u_free(new_dgram); queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!new_entry) { u_free(new_dgram); queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
new_entry->dgram = new_dgram;
|
||||
new_entry->len = total_len;
|
||||
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
|
||||
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, dst_node_id);
|
||||
if (!conn) {
|
||||
|
||||
+3
-3
@@ -166,7 +166,7 @@ static void exit_handle_request(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
}
|
||||
|
||||
drop:
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -186,7 +186,7 @@ static void client_handle_reply(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
struct UTUN_INSTANCE* inst = conn ? conn->instance : (g_icmp_ctx ? g_icmp_ctx->inst : NULL);
|
||||
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);
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -200,7 +200,7 @@ void icmp_proxy_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
uint8_t subcmd = entry->dgram[1];
|
||||
if (subcmd == ICMP_PROXY_SUBCMD_REQUEST) { exit_handle_request(conn, entry); return; }
|
||||
if (subcmd == ICMP_PROXY_SUBCMD_REPLY) { client_handle_reply(conn, entry); return; }
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ static void nat_transport_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry*
|
||||
}
|
||||
}
|
||||
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ==================== Init / Destroy ====================
|
||||
|
||||
+17
-15
@@ -62,6 +62,7 @@ static void rp_sock_read_cb(socket_t sock, void* arg) {
|
||||
if (!rc || rc->sock == SOCKET_INVALID) return;
|
||||
uint8_t buf[8192]; ssize_t n = recv(rc->sock, buf, sizeof(buf), 0);
|
||||
if (n > 0) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "RP RECV ← stream=%016llx len=%zd seq=%u", (unsigned long long)rc->stream_id, n, rc->send_seq);
|
||||
struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL;
|
||||
if (inst) {
|
||||
rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, rc->send_seq, buf, (size_t)n);
|
||||
@@ -132,7 +133,7 @@ static void rp_conn_free(struct remote_proxy_conn* rc) {
|
||||
static void rp_standalone_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
struct UTUN_INSTANCE* i = conn ? conn->instance : (g_rp_ctx ? g_rp_ctx->inst : NULL);
|
||||
if (!i || !entry || entry->dgram == NULL || entry->len < TCP_PROXY_HDR_SIZE) {
|
||||
if (entry) { queue_entry_free(entry); queue_dgram_free(entry); }
|
||||
if (entry) { queue_dgram_free(entry); queue_entry_free(entry); }
|
||||
return;
|
||||
}
|
||||
uint8_t subcmd = entry->dgram[1];
|
||||
@@ -140,8 +141,8 @@ static void rp_standalone_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry
|
||||
uint64_t src = conn ? conn->peer_node_id : i->node_id;
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CONNECT) { remote_proxy_handle_connect(i, entry, sid, src); return; }
|
||||
if (subcmd == TCP_PROXY_SUBCMD_DATA) { remote_proxy_handle_data(i, entry, sid); return; }
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CLOSE) { remote_proxy_handle_close(i, sid); queue_entry_free(entry); queue_dgram_free(entry); return; }
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CLOSE) { remote_proxy_handle_close(i, sid); queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -155,24 +156,24 @@ struct remote_proxy_conn* remote_proxy_find_conn(struct remote_proxy_ctx* ctx, u
|
||||
|
||||
int remote_proxy_handle_connect(struct UTUN_INSTANCE* inst, struct ll_entry* entry,
|
||||
uint64_t stream_id, uint64_t src_node_id) {
|
||||
if (!inst || !inst->remote_proxy.enabled) { queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!inst || !inst->remote_proxy.enabled) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
struct remote_proxy_ctx* ctx = &inst->remote_proxy;
|
||||
if (entry->len < TCP_PROXY_CONNECT_HDR_SIZE) { queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (entry->len < TCP_PROXY_CONNECT_HDR_SIZE) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
uint8_t* dest_ip = entry->dgram + TCP_PROXY_HDR_SIZE;
|
||||
uint16_t dest_port = 0; memcpy(&dest_port, dest_ip + 4, 2);
|
||||
|
||||
struct remote_proxy_conn* rc = u_calloc(1, sizeof(struct remote_proxy_conn));
|
||||
if (!rc) { queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!rc) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
rc->ctx = ctx; rc->stream_id = stream_id; rc->peer_node_id = src_node_id;
|
||||
memcpy(rc->dest_ip, dest_ip, 4); rc->dest_port = dest_port;
|
||||
rc->ua = inst->ua; rc->sock = SOCKET_INVALID;
|
||||
rc->send_seq = 0; rc->recv_seq_init = 0;
|
||||
|
||||
rc->sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (rc->sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: socket() failed"); rp_conn_free(rc); queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (rc->sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: socket() failed"); rp_conn_free(rc); queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
socket_set_nonblocking(rc->sock);
|
||||
rc->read_id = uasync_add_socket_t(rc->ua, rc->sock, rp_sock_read_cb, rp_sock_write_cb, rp_sock_error_cb, rc);
|
||||
if (!rc->read_id) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: uasync_add_socket_t failed"); rp_conn_free(rc); queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!rc->read_id) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: uasync_add_socket_t failed"); rp_conn_free(rc); queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
|
||||
struct sockaddr_in addr; memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET; memcpy(&addr.sin_addr.s_addr, dest_ip, 4); addr.sin_port = dest_port;
|
||||
@@ -183,19 +184,19 @@ int remote_proxy_handle_connect(struct UTUN_INSTANCE* inst, struct ll_entry* ent
|
||||
if (ret < 0 && errno != EINPROGRESS) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: connect() failed: %s", strerror(errno));
|
||||
rp_send_connected(inst, src_node_id, stream_id, 0, TCP_PROXY_CONNECTED_REFUSED);
|
||||
rp_conn_free(rc); queue_entry_free(entry); queue_dgram_free(entry); return -1;
|
||||
rp_conn_free(rc); queue_dgram_free(entry); queue_entry_free(entry); return -1;
|
||||
}
|
||||
|
||||
rc->next = ctx->conns; ctx->conns = rc;
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remote_proxy_handle_data(struct UTUN_INSTANCE* inst, struct ll_entry* entry, uint64_t stream_id) {
|
||||
if (!inst) { queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!inst) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
struct remote_proxy_ctx* ctx = &inst->remote_proxy;
|
||||
struct remote_proxy_conn* rc = remote_proxy_find_conn(ctx, stream_id);
|
||||
if (!rc || rc->sock == SOCKET_INVALID || rc->connected != 1) { queue_entry_free(entry); queue_dgram_free(entry); return -1; }
|
||||
if (!rc || rc->sock == SOCKET_INVALID || rc->connected != 1) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
|
||||
uint16_t seq; memcpy(&seq, entry->dgram + 10, 2);
|
||||
if (!rc->recv_seq_init) {
|
||||
rc->recv_last_seq = seq; rc->recv_seq_init = 1;
|
||||
@@ -203,23 +204,24 @@ int remote_proxy_handle_data(struct UTUN_INSTANCE* inst, struct ll_entry* entry,
|
||||
int16_t delta = (int16_t)(seq - rc->recv_last_seq);
|
||||
if (delta <= 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "remote_proxy: duplicate DATA seq=%u stream=%016llx, discard", seq, (unsigned long long)stream_id);
|
||||
queue_entry_free(entry); queue_dgram_free(entry); return 0;
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return 0;
|
||||
}
|
||||
if (delta > 1) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: seq gap seq=%u last=%u stream=%016llx, tearing down", seq, rc->recv_last_seq, (unsigned long long)stream_id);
|
||||
rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, 0, NULL, 0);
|
||||
rp_conn_free(rc);
|
||||
queue_entry_free(entry); queue_dgram_free(entry); return -1;
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return -1;
|
||||
}
|
||||
rc->recv_last_seq = seq;
|
||||
}
|
||||
size_t data_len = entry->len - TCP_PROXY_HDR_SIZE;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "RP SEND → stream=%016llx seq=%u len=%zu", (unsigned long long)stream_id, seq, data_len);
|
||||
uint8_t* data = entry->dgram + TCP_PROXY_HDR_SIZE;
|
||||
ssize_t n = send(rc->sock, data, data_len, MSG_NOSIGNAL);
|
||||
if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: send error %s", strerror(errno));
|
||||
}
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+23
-21
@@ -137,7 +137,7 @@ static err_t tcp_output_cb(void *arg, struct pbuf *p, uint32_t src_ip, uint32_t
|
||||
pbuf_copy_partial(p, buf + 2, len, 0);
|
||||
ssize_t n = write(proxy->ip_fd, buf, 2 + len); (void)n;
|
||||
}
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TRAFFIC, "TCP OUT %u.%u.%u.%u→%u.%u.%u.%u len=%u",
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "PROXY TCP_OUT %u.%u.%u.%u:%u len=%u",
|
||||
(uint8_t)(src_ip), (uint8_t)(src_ip>>8), (uint8_t)(src_ip>>16), (uint8_t)(src_ip>>24),
|
||||
(uint8_t)(dst_ip), (uint8_t)(dst_ip>>8), (uint8_t)(dst_ip>>16), (uint8_t)(dst_ip>>24), len);
|
||||
return LERR_OK;
|
||||
@@ -192,13 +192,13 @@ static void proxy_feed_from_transport(struct proxy_conn *pc) {
|
||||
int entries_fed = 0;
|
||||
while (1) {
|
||||
uint16_t space = tcp_sndbuf(pc->pcb);
|
||||
if (space < TCP_MSS / 2) { DEBUG_ERROR(DEBUG_CATEGORY_TRAFFIC, "FEED space=%u<ssthresh break active=%d", space, pc->active); break; }
|
||||
if (space < TCP_MSS / 2) { DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "PROXY FEED → stream=%016llx space=%u break", (unsigned long long)pc->remote_stream_id, space); break; }
|
||||
struct ll_entry *e = queue_data_get(pc->transport_to_uip);
|
||||
if (!e) break;
|
||||
uint16_t len = e->len;
|
||||
if (len > space) len = space;
|
||||
err_t ret = tcp_write(pc->pcb, e->dgram, len, TCP_WRITE_FLAG_COPY);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TRAFFIC, "FEED tcp_write len=%u ret=%d active=%d cwnd=%u snd_wnd=%u unsent=%p", len, ret, pc->active, pc->pcb->cwnd, pc->pcb->snd_wnd, (void*)pc->pcb->unsent);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "PROXY FEED → stream=%016llx len=%u ret=%d sndbuf=%u", (unsigned long long)pc->remote_stream_id, len, ret, pc->pcb->snd_buf);
|
||||
if (ret == LERR_OK) {
|
||||
sent_any = 1;
|
||||
if (len >= e->len) { queue_dgram_free(e); queue_entry_free(e); }
|
||||
@@ -311,6 +311,7 @@ static err_t proxy_poll_cb(void *arg, struct tcp_pcb *pcb) {
|
||||
struct proxy_conn *pc = (struct proxy_conn *)arg;
|
||||
if (!pc) return LERR_OK;
|
||||
if (pc->closing_tun && pc->closing_rem && pc->pcb) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLOSE stream=%016llx tun=1 rem=1", (unsigned long long)pc->remote_stream_id);
|
||||
struct tcp_pcb *save = pc->pcb;
|
||||
tcp_arg(save, NULL); pc->pcb = NULL; tcp_close(save);
|
||||
struct tcp_proxy *proxy = pc->proxy;
|
||||
@@ -396,9 +397,8 @@ static void tcp_proxy_raw_read(int fd, void* arg) {
|
||||
uint32_t src_ip, dst_ip;
|
||||
memcpy(&src_ip, pkt + 12, 4); memcpy(&dst_ip, pkt + 16, 4);
|
||||
uint16_t tcp_len = ip_total - ip_hdr_len;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TRAFFIC, "TCP IN %u.%u.%u.%u→%u.%u.%u.%u iplen=%u",
|
||||
(uint8_t)(src_ip), (uint8_t)(src_ip>>8), (uint8_t)(src_ip>>16), (uint8_t)(src_ip>>24),
|
||||
(uint8_t)(dst_ip), (uint8_t)(dst_ip>>8), (uint8_t)(dst_ip>>16), (uint8_t)(dst_ip>>24), ip_total);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "PROXY TCP_IN %u.%u.%u.%u:%u len=%u",
|
||||
(uint8_t)(src_ip), (uint8_t)(src_ip>>8), (uint8_t)(src_ip>>16), (uint8_t)(src_ip>>24), ntohs(dport_net), tcp_len);
|
||||
struct pbuf *pb = pbuf_alloc(PBUF_RAW, tcp_len);
|
||||
if (pb) { pbuf_take(pb, pkt + ip_hdr_len, tcp_len); lwip_tcp_input(p->lwip, pb, src_ip, dst_ip); }
|
||||
}
|
||||
@@ -645,15 +645,16 @@ static struct proxy_conn* find_pc_by_stream(struct tcp_proxy* p, uint64_t stream
|
||||
static void handle_connected(struct tcp_proxy* p, uint64_t stream_id, struct ll_entry* entry) {
|
||||
struct proxy_conn* pc = find_pc_by_stream(p, stream_id);
|
||||
if (!pc || !pc->transport) {
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "PROXY CONNECTED stream=%016llx pc=%p transport=%p — drop", (unsigned long long)stream_id, (void*)pc, pc ? pc->transport : NULL);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
struct etcp_transport* et = (struct etcp_transport*)pc->transport;
|
||||
if (et->base.ops != &etcp_transport_ops) { queue_entry_free(entry); queue_dgram_free(entry); return; }
|
||||
if (et->base.ops != &etcp_transport_ops) { queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
if (entry->len >= TCP_PROXY_CONNECTED_HDR_SIZE) {
|
||||
uint8_t status = entry->dgram[TCP_PROXY_HDR_SIZE + 2];
|
||||
if (status == TCP_PROXY_CONNECTED_OK) { et->connected = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "TCP proxy: remote connected stream=%016llx", (unsigned long long)stream_id);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CONNECTED stream=%016llx status=OK", (unsigned long long)stream_id);
|
||||
struct ll_entry* e;
|
||||
while ((e = queue_data_get(pc->uip_to_transport)) != NULL) {
|
||||
if (e->len > 0) {
|
||||
@@ -665,7 +666,7 @@ static void handle_connected(struct tcp_proxy* p, uint64_t stream_id, struct ll_
|
||||
else { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP proxy: remote refused stream=%016llx", (unsigned long long)stream_id);
|
||||
pc->closing_rem = 1; }
|
||||
}
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -673,7 +674,7 @@ static void handle_connected(struct tcp_proxy* p, uint64_t stream_id, struct ll_
|
||||
// ====================================================================
|
||||
void tcp_proxy_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
if (!entry || !entry->dgram || entry->len < TCP_PROXY_HDR_SIZE) {
|
||||
if (entry) { queue_entry_free(entry); queue_dgram_free(entry); }
|
||||
if (entry) { queue_dgram_free(entry); queue_entry_free(entry); }
|
||||
return;
|
||||
}
|
||||
uint8_t subcmd = entry->dgram[1];
|
||||
@@ -690,7 +691,7 @@ void tcp_proxy_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
struct remote_proxy_conn* rc = remote_proxy_find_conn(&inst->remote_proxy, stream_id);
|
||||
if (rc) {
|
||||
if (subcmd == TCP_PROXY_SUBCMD_DATA) { remote_proxy_handle_data(inst, entry, stream_id); return; }
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CLOSE) { remote_proxy_handle_close(inst, stream_id); queue_entry_free(entry); queue_dgram_free(entry); return; }
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CLOSE) { remote_proxy_handle_close(inst, stream_id); queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
}
|
||||
}
|
||||
if (proxy) {
|
||||
@@ -707,22 +708,23 @@ void tcp_proxy_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
int16_t delta = (int16_t)(seq - et->recv_last_seq);
|
||||
if (delta <= 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "TCP proxy: duplicate DATA seq=%u stream=%016llx, discard", seq, (unsigned long long)stream_id);
|
||||
queue_entry_free(entry); queue_dgram_free(entry); return;
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return;
|
||||
}
|
||||
if (delta > 1) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP proxy: seq gap seq=%u last=%u stream=%016llx, tearing down", seq, et->recv_last_seq, (unsigned long long)stream_id);
|
||||
pc->closing_rem = 1;
|
||||
if (pc->transport) { pc->transport->ops->destroy(pc->transport); pc->transport = NULL; }
|
||||
queue_entry_free(entry); queue_dgram_free(entry); return;
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return;
|
||||
}
|
||||
et->recv_last_seq = seq;
|
||||
}
|
||||
}
|
||||
size_t data_len = entry->len - TCP_PROXY_HDR_SIZE;
|
||||
if (data_len > 0) {
|
||||
struct ll_entry* e = entry_from_data(pc->proxy->entry_pool, entry->dgram + TCP_PROXY_HDR_SIZE, (uint16_t)data_len);
|
||||
if (e) queue_data_put(pc->transport_to_uip, e);
|
||||
proxy_feed_from_transport(pc);
|
||||
size_t data_len = entry->len - TCP_PROXY_HDR_SIZE;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "PROXY DATA ← stream=%016llx seq=%u len=%zu", (unsigned long long)stream_id, seq, data_len);
|
||||
if (data_len > 0) {
|
||||
struct ll_entry* e = entry_from_data(pc->proxy->entry_pool, entry->dgram + TCP_PROXY_HDR_SIZE, (uint16_t)data_len);
|
||||
if (e) queue_data_put(pc->transport_to_uip, e);
|
||||
proxy_feed_from_transport(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -734,7 +736,7 @@ void tcp_proxy_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
}
|
||||
}
|
||||
}
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
+3
-3
@@ -107,7 +107,7 @@ static void exit_handle_data(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
sendto(f->sock, payload, payload_len, 0, (struct sockaddr*)&addr, sizeof(addr));
|
||||
|
||||
drop:
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -128,7 +128,7 @@ static void client_handle_reply(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
|
||||
struct UTUN_INSTANCE* inst = conn ? conn->instance : (g_udp_ctx ? g_udp_ctx->inst : NULL);
|
||||
udp_proxy_deliver_reply(inst, src_ip, src_port, dst_ip, dst_port, payload, payload_len);
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -145,7 +145,7 @@ void udp_proxy_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
else client_handle_reply(conn, entry);
|
||||
return;
|
||||
}
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
Reference in new issue
Block a user