fix: auto_socket TCP duplicate sockets + NAT v4 address resolution

auto_socket.c: create_iface_tcp_socket returns stcp_server* instead of int,
ifa->v4_tcp/ifa->v6_tcp now properly track the created server, preventing
duplicate bind/listen on every reconcile_iface call.

etcp_connections.c: tcp_socket_add now resolves interface_addr via
get_interface_ip_by_index/get_interface_ipv6_addr_nl for any type (not just
PUBLIC), preventing NAT TCP v4 sockets from being destroyed due to INADDR_ANY.
This commit is contained in:
evgeny committed 2026-08-07 20:06:30 +03:00
1 parent de61a2dacc
commit 80e77f12c2
12 files changed
+202 -66

No files matched your search

+29 -11
View File
@@ -531,13 +531,18 @@ static void cm_direct_add_links(struct ETCP_CONN* conn, struct CONN_MGR_ENTRY* e
/* v4 */
if (db_loaded) {
for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) {
if (!(a->protocol & TOPO_PROTO_UDP)) continue;
struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets;
while (s) { if (s->local_addr.ss_family == AF_INET) {
struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET;
memcpy(&sin.sin_addr.s_addr,a->addr,4); sin.sin_port=htons(a->port);
struct sockaddr_storage sa; memcpy(&sa,&sin,sizeof(sin));
if (etcp_link_new(conn,s,&sa,0)) any=1; } s=s->next; }
struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET;
memcpy(&sin.sin_addr.s_addr,a->addr,4); sin.sin_port=htons(a->port);
struct sockaddr_storage sa; memcpy(&sa,&sin,sizeof(sin));
if (a->protocol & TOPO_PROTO_TCP) {
struct ETCP_LINK *tlink = etcp_link_new(conn, NULL, NULL, 0);
if (tlink) { tlink->is_tcp = 1; etcp_tcp_link_start_connect(tlink, &sa, a->port); any = 1; }
}
if (a->protocol & TOPO_PROTO_UDP) {
struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets;
while (s) { if (s->local_addr.ss_family == AF_INET) {
if (etcp_link_new(conn,s,&sa,0)) any=1; } s=s->next; }
}
}
} else {
uint8_t prio[]={TOPO_ADDR_NAT,TOPO_ADDR_INTERFACE};
@@ -556,10 +561,23 @@ static void cm_direct_add_links(struct ETCP_CONN* conn, struct CONN_MGR_ENTRY* e
}
/* v6 */
for (const struct TOPO_ADDR6* a6=ni->v6_addrs;a6;a6=a6->next) {
if (!(a6->protocol&TOPO_PROTO_UDP)) continue;
uint8_t tc=cm_classify_v6_addr(a6->addr); if(tc==CM_V6_OTH) continue;
struct ETCP_SOCKET* s=entry->mgr->instance->etcp_sockets;
while(s){uint8_t sc=cm_sock_v6_classify(s);if(sc==CM_V6_ANY||sc==tc){cm_add_v6_link(conn,a6->addr,a6->port,s);any=1;} s=s->next;}
int is_ll = (a6->addr[0] == 0xfe && (a6->addr[1] & 0xc0) == 0x80);
if (a6->protocol & TOPO_PROTO_TCP) {
struct sockaddr_in6 sin6; memset(&sin6,0,sizeof(sin6)); sin6.sin6_family=AF_INET6;
memcpy(&sin6.sin6_addr,a6->addr,16); sin6.sin6_port=htons(a6->port);
if (is_ll) { struct ETCP_SOCKET* sv=entry->mgr->instance->etcp_sockets;
while(sv){if(sv->local_addr.ss_family==AF_INET6&&sv->netif_index)
{sin6.sin6_scope_id=sv->netif_index;break;} sv=sv->next;}
}
struct sockaddr_storage sa; memcpy(&sa,&sin6,sizeof(sin6));
struct ETCP_LINK *tlink = etcp_link_new(conn, NULL, NULL, 0);
if (tlink) { tlink->is_tcp = 1; etcp_tcp_link_start_connect(tlink, &sa, a6->port); any = 1; }
}
if (a6->protocol & TOPO_PROTO_UDP) {
uint8_t tc=cm_classify_v6_addr(a6->addr); if(tc==CM_V6_OTH) continue;
struct ETCP_SOCKET* s=entry->mgr->instance->etcp_sockets;
while(s){uint8_t sc=cm_sock_v6_classify(s);if(sc==CM_V6_ANY||sc==tc){cm_add_v6_link(conn,a6->addr,a6->port,s);any=1;} s=s->next;}
}
}
if (any) return;
+8 -6
View File
@@ -623,8 +623,8 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
{
sqlite3_stmt* s = NULL;
if (sqlite3_prepare_v2(db,
"SELECT address,port,addr_type,socket_id FROM node_addresses"
" WHERE node_id=? AND family=4 AND protocol=1 ORDER BY addr_type",
"SELECT address,port,addr_type,socket_id,protocol FROM node_addresses"
" WHERE node_id=? AND family=4 ORDER BY addr_type",
-1, &s, NULL) == SQLITE_OK) {
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
while (sqlite3_step(s) == SQLITE_ROW) {
@@ -638,8 +638,9 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
struct TOPO_ADDR4* a4 = memory_pool_alloc(groups->v4_addr_pool);
if (!a4) continue;
memset(a4, 0, sizeof(*a4));
int proto = sqlite3_column_int(s, 4);
memcpy(a4->addr, addr, 4); a4->port = (uint16_t)port;
a4->type = type; a4->socket_id = sock_id; a4->protocol = TOPO_PROTO_UDP;
a4->type = type; a4->socket_id = sock_id; a4->protocol = (uint8_t)proto;
if (!v4_head) v4_head = v4_tail = a4;
else { v4_tail->next = a4; v4_tail = a4; }
}
@@ -651,8 +652,8 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
{
sqlite3_stmt* s = NULL;
if (sqlite3_prepare_v2(db,
"SELECT address,port,addr_type,socket_id FROM node_addresses"
" WHERE node_id=? AND family=6 AND protocol=1 ORDER BY addr_type",
"SELECT address,port,addr_type,socket_id,protocol FROM node_addresses"
" WHERE node_id=? AND family=6 ORDER BY addr_type",
-1, &s, NULL) == SQLITE_OK) {
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
while (sqlite3_step(s) == SQLITE_ROW) {
@@ -666,8 +667,9 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
struct TOPO_ADDR6* a6 = memory_pool_alloc(groups->v6_addr_pool);
if (!a6) continue;
memset(a6, 0, sizeof(*a6));
int proto6 = sqlite3_column_int(s, 4);
memcpy(a6->addr, addr, 16); a6->port = (uint16_t)port;
a6->type = type; a6->socket_id = sock_id; a6->protocol = TOPO_PROTO_UDP;
a6->type = type; a6->socket_id = sock_id; a6->protocol = (uint8_t)proto6;
if (!v6_head) v6_head = v6_tail = a6;
else { v6_tail->next = a6; v6_tail = a6; }
}
+12 -14
View File
@@ -132,7 +132,7 @@ struct AUTO_SOCKET {
/* ─── forward declarations ─── */
static int create_iface_udp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, const char* ifname, int family, uint8_t type);
static int create_iface_tcp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, const char* ifname, int family, uint8_t type);
static struct stcp_server* create_iface_tcp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, const char* ifname, int family, uint8_t type);
static void remove_iface_sockets(struct AUTO_SOCKET* as, uint32_t ifindex);
static int scan_and_classify_iface(uint32_t ifindex, const char* ifname, int* out_has_v4, int* out_has_v6, uint8_t* out_v4_type, uint8_t* out_v6_type);
static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char* ifname);
@@ -273,7 +273,7 @@ static int create_iface_udp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, con
return -1;
}
static int create_iface_tcp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, const char* ifname, int family, uint8_t type) {
static struct stcp_server* create_iface_tcp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, const char* ifname, int family, uint8_t type) {
struct UTUN_INSTANCE* inst = as->instance;
uint16_t saved_port = load_port_from_db(as, ifname, family, AS_PROTO_TCP);
@@ -296,7 +296,7 @@ static int create_iface_tcp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, con
else
DEBUG_WARN(DEBUG_CATEGORY_AS, "[as] TCP socket create failed if=%s fam=%d port=%u att=%d err=%d",
ifname, family, port, attempt + 1, socket_get_error());
if (socket_get_error() != EADDRINUSE) return -1;
if (socket_get_error() != EADDRINUSE) return NULL;
continue;
}
@@ -334,11 +334,11 @@ static int create_iface_tcp_socket(struct AUTO_SOCKET* as, uint32_t ifindex, con
save_port_to_db(as, ifname, family, AS_PROTO_TCP, port);
DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] TCP socket created: if=%s(%u) type=%d port=%u", ifname, ifindex, type, port);
return 0;
return tsrv;
}
DEBUG_ERROR(DEBUG_CATEGORY_AS, "[as] failed to create TCP socket after %d attempts if=%s fam=%d", max_att, ifname, family);
return -1;
DEBUG_ERROR(DEBUG_CATEGORY_AS, "[as] failed to create TCP socket after %d attempts if=%s fam=%d", max_att, ifname, family);
return NULL;
}
int auto_socket_add_interface(struct UTUN_INSTANCE* inst, uint32_t ifindex,
@@ -365,9 +365,8 @@ int auto_socket_add_interface(struct UTUN_INSTANCE* inst, uint32_t ifindex,
struct ETCP_SOCKET* s = inst->etcp_sockets;
while (s) { if (s->netif_index == ifindex && s->local_addr.ss_family == AF_INET && !ifa->v4_udp) { ifa->v4_udp = s; break; } s = s->next; }
}
if (create_iface_tcp_socket(as, ifindex, ifname, AF_INET, v4_type) == 0) {
added++;
}
{ struct stcp_server* tsrv = create_iface_tcp_socket(as, ifindex, ifname, AF_INET, v4_type);
if (tsrv) { added++; ifa->v4_tcp = tsrv; } }
}
if (has_v6) {
if (create_iface_udp_socket(as, ifindex, ifname, AF_INET6, v6_type) == 0) {
@@ -375,9 +374,8 @@ int auto_socket_add_interface(struct UTUN_INSTANCE* inst, uint32_t ifindex,
struct ETCP_SOCKET* s = inst->etcp_sockets;
while (s) { if (s->netif_index == ifindex && s->local_addr.ss_family == AF_INET6 && !ifa->v6_udp) { ifa->v6_udp = s; break; } s = s->next; }
}
if (create_iface_tcp_socket(as, ifindex, ifname, AF_INET6, v6_type) == 0) {
added++;
}
{ struct stcp_server* tsrv = create_iface_tcp_socket(as, ifindex, ifname, AF_INET6, v6_type);
if (tsrv) { added++; ifa->v6_tcp = tsrv; } }
}
if (added > 0) {
@@ -713,7 +711,7 @@ static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char
struct stcp_server* srv = ifa ? ifa->v4_tcp : NULL;
if (has && !srv) {
if (!ifa) ifa = reconcile_get_ifa(as, ifindex);
if (ifa) { create_iface_tcp_socket(as, ifindex, ifname, AF_INET, v4_need_type); ifa->v4_tcp = NULL; /* find below */ changed = 1; }
if (ifa) { struct stcp_server* tsrv = create_iface_tcp_socket(as, ifindex, ifname, AF_INET, v4_need_type); ifa->v4_tcp = tsrv; if (tsrv) changed = 1; }
} else if (!has && srv) {
DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] v4 TCP removed: %s ifidx=%u", ifname, ifindex);
{ char buf[IFNAMSIZ]; const char* nm = if_indextoname(ifindex, buf) ? buf : ifname;
@@ -735,7 +733,7 @@ static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char
struct stcp_server* srv = ifa ? ifa->v6_tcp : NULL;
if (has && !srv) {
if (!ifa) ifa = reconcile_get_ifa(as, ifindex);
if (ifa) { create_iface_tcp_socket(as, ifindex, ifname, AF_INET6, v6_need_type); ifa->v6_tcp = NULL; changed = 1; }
if (ifa) { struct stcp_server* tsrv = create_iface_tcp_socket(as, ifindex, ifname, AF_INET6, v6_need_type); ifa->v6_tcp = tsrv; if (tsrv) changed = 1; }
} else if (!has && srv) {
DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] v6 TCP removed: %s ifidx=%u", ifname, ifindex);
{ char buf[IFNAMSIZ]; const char* nm = if_indextoname(ifindex, buf) ? buf : ifname;
+4
View File
@@ -32,6 +32,10 @@ struct ETCP_SOCKET;
int auto_socket_init(struct UTUN_INSTANCE* inst);
void auto_socket_destroy(struct UTUN_INSTANCE* inst);
/* Platform notification: call from any thread when network interfaces change.
* Posts auto_socket_scan_all() to uasync thread. Safe for JNI/ConnectivityManager callbacks. */
void auto_socket_on_network_change(struct UTUN_INSTANCE* inst);
/* ─── Platform-agnostic API: управление сокетами на конкретном интерфейсе ─── */
/*
+27 -4
View File
@@ -44,7 +44,7 @@ static void tcp_link_close_cb(struct stcp_link *sl, int err, void *arg);
void etcp_link_enter_ready_tcp(struct ETCP_LINK *link);
// TCP server: on new incoming connection → create ETCP_LINK + enter ready
static void tcp_server_on_link(struct stcp_link *link, void *arg) {
void tcp_server_on_link(struct stcp_link *link, void *arg) {
struct UTUN_INSTANCE *inst = (struct UTUN_INSTANCE *)arg;
const uint8_t *pubkey = stcp_link_get_peer_pubkey(link);
if (!pubkey) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: no peer pubkey"); return; }
@@ -180,7 +180,9 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t c
// padding
int wire_ov_init = WIRE_OVERHEAD(link->remote_addr.ss_family);
int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize;
int pad_range = (int)link->handshake_maxsize - (int)link->handshake_minsize;
if (pad_range <= 0) pad_range = 1;
int s = rand() % pad_range + link->handshake_minsize;
int s_max = (int)(link->mtu) - wire_ov_init;
if (s > s_max) s = s_max;
if (s < 0) s = 0;
@@ -830,6 +832,15 @@ struct TCP_SOCKET* tcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SER
struct sockaddr_in* sin = (struct sockaddr_in*)&server->ip;
memcpy(&ts->local_addr, sin, sizeof(*sin));
ts->interface_addr = ts->local_addr;
if (sin->sin_addr.s_addr == 0 && server->netif_index > 0) {
uint32_t if_ip = get_interface_ip_by_index(server->netif_index);
if (if_ip != 0) {
struct sockaddr_in* if_sin = (struct sockaddr_in*)&ts->interface_addr;
if_sin->sin_family = AF_INET;
if_sin->sin_addr.s_addr = if_ip;
if_sin->sin_port = sin->sin_port;
}
}
if (server->type == CFG_SERVER_TYPE_PUBLIC && sin->sin_addr.s_addr == 0) {
struct sockaddr_storage remote; memset(&remote, 0, sizeof(remote));
struct sockaddr_in* rs = (struct sockaddr_in*)&remote;
@@ -845,6 +856,16 @@ struct TCP_SOCKET* tcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SER
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&server->ip;
memcpy(&ts->local_addr, sin6, sizeof(*sin6));
ts->interface_addr = ts->local_addr;
if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0 && server->netif_index > 0) {
uint8_t v6addr[16];
int got = get_interface_ipv6_addr_nl(server->netif_index, 1, v6addr);
if (got != 0) got = get_interface_ipv6_addr_nl(server->netif_index, 0, v6addr);
if (got == 0) {
struct sockaddr_in6* if6 = (struct sockaddr_in6*)&ts->interface_addr;
if6->sin6_family = AF_INET6; memcpy(&if6->sin6_addr, v6addr, 16);
if6->sin6_port = sin6->sin6_port;
}
}
if (server->type == CFG_SERVER_TYPE_PUBLIC && memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0) {
uint16_t v6if = (server->netif_index > 0) ? server->netif_index : get_default_route_netif_index(AF_INET6);
if (v6if > 0) {
@@ -905,7 +926,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
link->is_tcp = (uint8_t)is_tcp;
int mtu;
mtu = conn ? conn->mtu : STCP_MAX_MSG_SIZE;
if (is_tcp) { mtu = STCP_MAX_MSG_SIZE; link->mtu_local = mtu; link->mtu = mtu; link->inflight_lim_bytes = mtu * 4; }
if (is_tcp) { mtu = STCP_MAX_MSG_SIZE; link->mtu_local = mtu; link->mtu = mtu; link->inflight_lim_bytes = mtu * 4; link->handshake_minsize = 100; link->handshake_maxsize = mtu; }
else { if (mtu == 0) mtu = 1500; if (mtu > PACKET_DATA_MAX_MTU) mtu = PACKET_DATA_MAX_MTU; link->mtu_local = mtu; link->mtu = mtu; link->inflight_lim_bytes = mtu * 4; link->handshake_minsize = 100; link->handshake_maxsize = mtu; }
/* mtu init moved above */
etcp_update_mtu(etcp);
@@ -1603,7 +1624,9 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
// padding
int wire_ov = WIRE_OVERHEAD(link->remote_addr.ss_family);
int max_data = link->mtu - wire_ov;
int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize;
int pad_range = (int)link->handshake_maxsize - (int)link->handshake_minsize;
if (pad_range <= 0) pad_range = 1;
int s = rand() % pad_range + link->handshake_minsize;
if (s > (int)(link->mtu)) s = (int)(link->mtu);
if (s < 0) s = 0;
+3
View File
@@ -342,6 +342,9 @@ struct TCP_SOCKET {
struct TCP_SOCKET* tcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SERVER* server);
void tcp_socket_remove(struct TCP_SOCKET* sock);
struct stcp_link;
void tcp_server_on_link(struct stcp_link *link, void *arg);
// connection functions
// создает новый канал связи для etcp подключения (ETCP_CONN)
struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn, struct sockaddr_storage* remote_addr, uint8_t is_server);
+1 -1
View File
@@ -27,7 +27,7 @@ void stcp_conn_set_on_close(struct stcp_conn *c, void (*cb)(struct stcp_conn *co
void stcp_conn_free(struct stcp_conn *c) {
if (!c) return;
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_conn_free: c=%p sock=%d sock_id=%p recv_buf=%p state=%d allocated=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_conn_free: c=%p sock=%d sock_id=%p recv_buf=%p state=%d allocated=%d",
(void*)c, (int)c->sock, (void*)c->socket_id, (void*)c->recv_buf, (int)c->state, (int)c->allocated);
if (c->socket_id) { uasync_remove_socket_t(c->ua, c->sock); c->socket_id = NULL; }
if (c->sock != SOCKET_INVALID) { socket_close_wrapper(c->sock); c->sock = SOCKET_INVALID; }
+11 -13
View File
@@ -38,7 +38,7 @@ static int client_derive_session(struct stcp_conn *c, const uint8_t *peer_pubkey
if (sc_set_peer_public_key(&sc, peer_pubkey, SC_PEER_PUBKEY_BIN) != SC_OK) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "client ECDH failed"); return -1; }
memcpy(c->session_key, sc.session_key, SC_SESSION_KEY_SIZE);
memcpy(c->peer_pubkey, peer_pubkey, SC_PUBKEY_SIZE); c->peer_pubkey_set = 1;
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_client session_key", c->session_key, 16);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "stcp_client session_key", c->session_key, 16);
if (sc_stream_init(&sc, &c->stream_send, STCP_STREAM_CLIENT_SEND) != SC_OK) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "client stream_send init failed"); return -1; }
if (sc_stream_init(&sc, &c->stream_recv, STCP_STREAM_SERVER_SEND) != SC_OK) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "client stream_recv init failed"); return -1; }
return 0;
@@ -69,7 +69,7 @@ static void client_send_handshake(struct stcp_conn *c, const uint8_t *server_pub
}
static void process_server_response(struct stcp_conn *c) {
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_client process_srv_resp recv_buf", c->recv_buf, c->recv_buf_len);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_ETCP, "stcp_client process_srv_resp recv_buf", c->recv_buf, c->recv_buf_len);
if (!c->hs_key_processed) {
const uint8_t *salt = c->recv_buf;
const uint8_t *enc_pubkey = salt + SC_PUBKEY_ENC_SALT_SIZE;
@@ -83,10 +83,10 @@ static void process_server_response(struct stcp_conn *c) {
}
uint8_t enc_hs[STCP_HS_ENC_SERVER];
memcpy(enc_hs, c->recv_buf + SC_PUBKEY_ENC_SIZE, STCP_HS_ENC_SERVER);
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_client enc_hs BEFORE xor", enc_hs, STCP_HS_ENC_SERVER);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "stcp_client enc_hs BEFORE xor", enc_hs, STCP_HS_ENC_SERVER);
size_t hs_data_len;
if (stcp_frame_decrypt(enc_hs, STCP_HS_ENC_SERVER, &c->stream_recv, &hs_data_len)) { client_do_close(c, 3); return; }
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_client enc_hs AFTER xor", enc_hs, STCP_HS_ENC_SERVER);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "stcp_client enc_hs AFTER xor", enc_hs, STCP_HS_ENC_SERVER);
memcpy(c->peer_ed25519_pubkey, enc_hs, SC_PUBKEY_SIZE); c->peer_ed25519_set = 1;
uint8_t status = enc_hs[32];
uint16_t padding_size = (uint16_t)enc_hs[33] | ((uint16_t)enc_hs[34] << 8);
@@ -106,7 +106,7 @@ static void finish_server_response(struct stcp_conn *c) {
}
static void stcp_conn_process_recv(struct stcp_conn *c) {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: process_recv entry state=%d sock=%d recv_buf=%p len=%zu cap=%zu",
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "stcp_client: process_recv entry state=%d sock=%d recv_buf=%p len=%zu cap=%zu",
c->state, (int)c->sock, (void*)c->recv_buf, c->recv_buf_len, c->recv_buf_cap);
if (!c->recv_buf && c->recv_buf_len > 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_client: process_recv NULL recv_buf with len=%zu — closing", c->recv_buf_len);
@@ -136,8 +136,6 @@ static void stcp_conn_process_recv(struct stcp_conn *c) {
if (e) { e->dgram = u_malloc(data_len); if (e->dgram) { if (data_len) memcpy(e->dgram, enc_data, data_len); e->len = (uint16_t)data_len; queue_data_put(c->rx_queue, e); } else { queue_entry_free(e); } }
if (c->state != STCP_STATE_DATA) return;
}
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: memmove recv_buf=%p src=%p(+%zu) len=%zu (total=%zu recv_buf_len=%zu)",
(void*)c->recv_buf, (void*)(c->recv_buf + total), total, c->recv_buf_len - total, total, c->recv_buf_len);
if ((uintptr_t)c->recv_buf < 4096) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_client: suspicious recv_buf=%p (addr < 4K) — closing", (void*)c->recv_buf);
client_do_close(c, EFAULT); return;
@@ -154,10 +152,10 @@ static void stcp_conn_process_recv(struct stcp_conn *c) {
static void client_conn_read_cb(socket_t sock, void *arg) {
struct stcp_conn *c = (struct stcp_conn *)arg;
if (c->state == STCP_STATE_CLOSED || c->state == STCP_STATE_ERROR) {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: read_cb SKIP state=%d sock=%d c=%p recv_buf=%p", c->state, (int)sock, (void*)c, (void*)c->recv_buf);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_client: read_cb SKIP state=%d sock=%d c=%p recv_buf=%p", c->state, (int)sock, (void*)c, (void*)c->recv_buf);
return;
}
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: read_cb state=%d sock=%d c=%p recv_buf=%p len=%zu cap=%zu",
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "stcp_client: read_cb state=%d sock=%d c=%p recv_buf=%p len=%zu cap=%zu",
c->state, (int)sock, (void*)c, (void*)c->recv_buf, c->recv_buf_len, c->recv_buf_cap);
if (!c->recv_buf) { c->recv_buf_cap = STCP_RECV_BUF_INIT; c->recv_buf = u_malloc(c->recv_buf_cap); if (!c->recv_buf) { client_do_close(c, ENOMEM); return; } }
if (c->recv_buf_len + 4096 > c->recv_buf_cap) {
@@ -208,14 +206,14 @@ static void client_do_close(struct stcp_conn *c, int err) {
int prev = c->state;
c->state = STCP_STATE_CLOSED;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_client: closed is_server=%d err=%d prev_state=%d", c->is_server, err, prev);
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: do_close sock=%d sock_id=%p recv_buf=%p len=%zu cap=%zu send_buf=%p on_close=%p",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_client: do_close sock=%d sock_id=%p recv_buf=%p len=%zu cap=%zu send_buf=%p on_close=%p",
(int)c->sock, (void*)c->socket_id, (void*)c->recv_buf, c->recv_buf_len, c->recv_buf_cap, (void*)c->send_buf, (void*)c->on_close);
if (c->socket_id) { uasync_remove_socket_t(c->ua, c->sock); c->socket_id = NULL; }
if (c->sock != SOCKET_INVALID) { socket_close_wrapper(c->sock); c->sock = SOCKET_INVALID; }
if (c->recv_buf) { void *p = c->recv_buf; u_free(c->recv_buf); c->recv_buf = NULL; c->recv_buf_len = 0; c->recv_buf_cap = 0; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: do_close u_free recv_buf=%p", p); }
if (c->send_buf) { void *p = c->send_buf; u_free(c->send_buf); c->send_buf = NULL; c->send_len = 0; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: do_close u_free send_buf=%p", p); }
if (c->recv_buf) { void *p = c->recv_buf; u_free(c->recv_buf); c->recv_buf = NULL; c->recv_buf_len = 0; c->recv_buf_cap = 0; DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_client: do_close u_free recv_buf=%p", p); }
if (c->send_buf) { void *p = c->send_buf; u_free(c->send_buf); c->send_buf = NULL; c->send_len = 0; DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_client: do_close u_free send_buf=%p", p); }
stcp_pending_clear(c);
if (c->on_close) { void (*cb)(struct stcp_conn*, int, void*) = c->on_close; c->on_close = NULL; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: do_close calling on_close=%p", (void*)cb); cb(c, err, c->close_arg); DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_client: do_close on_close returned"); }
if (c->on_close) { void (*cb)(struct stcp_conn*, int, void*) = c->on_close; c->on_close = NULL; DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_client: do_close calling on_close=%p", (void*)cb); cb(c, err, c->close_arg); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_client: do_close on_close returned"); }
}
struct stcp_client *stcp_client_connect(struct UASYNC *ua, const char *addr, uint16_t port,
+11 -13
View File
@@ -44,7 +44,7 @@ static int derive_session_and_streams(struct stcp_conn *c, const uint8_t *peer_p
return -1;
}
memcpy(c->session_key, sc.session_key, SC_SESSION_KEY_SIZE);
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_server session_key", c->session_key, 16);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "stcp_server session_key", c->session_key, 16);
if (sc_stream_init(&sc, &c->stream_send, STCP_STREAM_SERVER_SEND) != SC_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stream_send init failed");
return -1;
@@ -101,17 +101,17 @@ static void finish_client_handshake(struct stcp_conn *c) {
uint8_t *enc_dst = resp + SC_PUBKEY_ENC_SIZE;
memcpy(enc_dst, plain_hs, 35);
enc_dst[35] = (uint8_t)(crc >> 0); enc_dst[36] = (uint8_t)(crc >> 8); enc_dst[37] = (uint8_t)(crc >> 16); enc_dst[38] = (uint8_t)(crc >> 24);
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_server hs_resp BEFORE xor", enc_dst, STCP_HS_ENC_SERVER);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "stcp_server hs_resp BEFORE xor", enc_dst, STCP_HS_ENC_SERVER);
if (sc_stream_xor(&c->stream_send, enc_dst, STCP_HS_ENC_SERVER) != SC_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "encrypt failed");
u_free(resp); stcp_conn_do_close(c, 3); return;
}
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_server hs_resp AFTER xor", enc_dst, STCP_HS_ENC_SERVER);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO, "stcp_server hs_resp AFTER xor", enc_dst, STCP_HS_ENC_SERVER);
for (int i = 0; i < padding; i++) resp[SC_PUBKEY_ENC_SIZE + STCP_HS_ENC_SERVER + i] = (uint8_t)(salt2[0] ^ i);
c->state = STCP_STATE_DATA;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_server: handshake OK, entering DATA state");
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_DEBUG, "stcp_server FULL RESP", resp, total_resp);
log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_ETCP, "stcp_server FULL RESP", resp, total_resp);
int r = stcp_try_send(c, resp, total_resp);
if (r < 0) { u_free(resp); stcp_conn_do_close(c, 3); return; }
if (c->on_ready) c->on_ready(c, c->ready_arg);
@@ -120,10 +120,10 @@ static void finish_client_handshake(struct stcp_conn *c) {
static void server_conn_read_cb(socket_t sock, void *arg) {
struct stcp_conn *c = (struct stcp_conn *)arg;
if (c->state == STCP_STATE_CLOSED || c->state == STCP_STATE_ERROR) {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: read_cb SKIP state=%d sock=%d c=%p recv_buf=%p", c->state, (int)sock, (void*)c, (void*)c->recv_buf);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_server: read_cb SKIP state=%d sock=%d c=%p recv_buf=%p", c->state, (int)sock, (void*)c, (void*)c->recv_buf);
return;
}
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: read_cb state=%d sock=%d c=%p recv_buf=%p len=%zu cap=%zu",
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "stcp_server: read_cb state=%d sock=%d c=%p recv_buf=%p len=%zu cap=%zu",
c->state, (int)sock, (void*)c, (void*)c->recv_buf, c->recv_buf_len, c->recv_buf_cap);
if (c->recv_buf_cap == 0) {
@@ -152,7 +152,7 @@ static void server_conn_read_cb(socket_t sock, void *arg) {
}
static void stcp_conn_process_recv(struct stcp_conn *c) {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: process_recv entry state=%d sock=%d recv_buf=%p len=%zu cap=%zu",
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "stcp_server: process_recv entry state=%d sock=%d recv_buf=%p len=%zu cap=%zu",
c->state, (int)c->sock, (void*)c->recv_buf, c->recv_buf_len, c->recv_buf_cap);
if (!c->recv_buf && c->recv_buf_len > 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_server: process_recv NULL recv_buf with len=%zu — closing", c->recv_buf_len);
@@ -191,8 +191,6 @@ static void stcp_conn_process_recv(struct stcp_conn *c) {
else { queue_entry_free(e); DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "rx malloc(%zu) failed", data_len); }
} else { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "queue_entry_new failed"); }
}
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: memmove recv_buf=%p src=%p(+%zu) len=%zu (total=%zu recv_buf_len=%zu)",
(void*)c->recv_buf, (void*)(c->recv_buf + total), total, c->recv_buf_len - total, total, c->recv_buf_len);
if ((uintptr_t)c->recv_buf < 4096) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_server: suspicious recv_buf=%p (addr < 4K) — closing", (void*)c->recv_buf);
stcp_conn_do_close(c, EFAULT); return;
@@ -228,13 +226,13 @@ static void stcp_conn_do_close(struct stcp_conn *c, int err) {
c->state = STCP_STATE_CLOSED;
if (c->socket_id) { uasync_remove_socket_t(c->ua, c->sock); c->socket_id = NULL; }
if (c->sock != SOCKET_INVALID) { socket_close_wrapper(c->sock); c->sock = SOCKET_INVALID; }
if (c->recv_buf) { void *p = c->recv_buf; u_free(c->recv_buf); c->recv_buf = NULL; c->recv_buf_len = 0; c->recv_buf_cap = 0; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: do_close u_free recv_buf=%p", p); }
if (c->send_buf) { void *p = c->send_buf; u_free(c->send_buf); c->send_buf = NULL; c->send_len = 0; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: do_close u_free send_buf=%p", p); }
if (c->recv_buf) { void *p = c->recv_buf; u_free(c->recv_buf); c->recv_buf = NULL; c->recv_buf_len = 0; c->recv_buf_cap = 0; DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_server: do_close u_free recv_buf=%p", p); }
if (c->send_buf) { void *p = c->send_buf; u_free(c->send_buf); c->send_buf = NULL; c->send_len = 0; DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_server: do_close u_free send_buf=%p", p); }
stcp_pending_clear(c);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_conn closed is_server=%d prev_state=%d err=%d sock=%d", c->is_server, prev, err, (int)c->sock);
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: do_close sock=%d sock_id=%p recv_buf was=%p on_close=%p",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_server: do_close sock=%d sock_id=%p recv_buf was=%p on_close=%p",
(int)c->sock, (void*)c->socket_id, (void*)c->recv_buf, (void*)c->on_close);
if (c->on_close) { void (*cb)(struct stcp_conn*, int, void*) = c->on_close; c->on_close = NULL; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: do_close calling on_close=%p", (void*)cb); cb(c, err, c->close_arg); DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "stcp_server: do_close on_close returned"); }
if (c->on_close) { void (*cb)(struct stcp_conn*, int, void*) = c->on_close; c->on_close = NULL; DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_server: do_close calling on_close=%p", (void*)cb); cb(c, err, c->close_arg); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_server: do_close on_close returned"); }
else if (prev == STCP_STATE_HS_SERVER_WAIT) { sc_stream_cleanup(&c->stream_send); sc_stream_cleanup(&c->stream_recv); if (c->allocated) uasync_call_soon(c->ua, c, stcp_conn_deferred_free); }
}