etcp_router: вынести подпись/шифрование в route_crypto, одна функция отправки с флагами
- route_crypto_encode/decode: автономный пред/пост-обработчик пакета (encrypt-then-sign, стандартный Ed25519 вместо sc_stream_sign) - одна функция отправки etcp_route_send/etcp_router_conn_send с bitmask mode - формат доставки: [svc_id][src][dst][rx_flags][payload] (статус подписи/шифрования) - ROUTER_INFLIGHT хранит финальный wire-пакет (чинит потерю подписи при ретрансмите) - дедуп инициализации: router_conn_reset/free_queues - учёт inflight через inflight_q count (seq присваивается на enqueue)
This commit is contained in:
1 parent
7c95ddb09b
commit
2d04bf941b
25 files changed
+549
-592
No files matched your search
@@ -61,6 +61,7 @@ utun_CORE_SOURCES = \
|
||||
ntp_node_time.c \
|
||||
proxy/tcp_proxy_client.c \
|
||||
routing_layer/etcp_router.c \
|
||||
routing_layer/route_crypto.c \
|
||||
proxy/tcp_proxy_server.c \
|
||||
proxy/udp_proxy.c \
|
||||
proxy/socks_proxy.c \
|
||||
@@ -143,6 +144,7 @@ libutun_a_SOURCES = \
|
||||
ntp_node_time.c \
|
||||
proxy/tcp_proxy_client.c \
|
||||
routing_layer/etcp_router.c \
|
||||
routing_layer/route_crypto.c \
|
||||
proxy/tcp_proxy_server.c \
|
||||
proxy/udp_proxy.c \
|
||||
proxy/socks_proxy.c \
|
||||
|
||||
@@ -412,7 +412,7 @@ static int md_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_n
|
||||
if (!e->dgram) { queue_entry_free(e); return -1; }
|
||||
e->dgram[0] = ETCP_RT_ID_MEDIA_DELIVERY;
|
||||
memcpy(e->dgram + 1, data, len); e->len = (uint16_t)(len + 1);
|
||||
int rc = etcp_route_send(inst, group_id, dst_node_id, e, 1);
|
||||
int rc = etcp_route_send(inst, group_id, dst_node_id, e, 1, 0);
|
||||
if (rc != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "%s: md_send FAIL rc=%d dst=0x%016llx group=0x%016llx",
|
||||
MD_ID, rc, (unsigned long long)dst_node_id, (unsigned long long)group_id);
|
||||
|
||||
@@ -72,7 +72,7 @@ static int md_dl_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t ds
|
||||
if (!e->dgram) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: u_malloc(%zu) failed for send to 0x%016llx", MDL_ID, len + 1, (unsigned long long)dst); queue_entry_free(e); return -1; }
|
||||
e->dgram[0] = ETCP_RT_ID_MEDIA_DELIVERY;
|
||||
memcpy(e->dgram + 1, data, len); e->len = (uint16_t)(len + 1);
|
||||
int rc = etcp_route_send(inst, group_id, dst, e, 1);
|
||||
int rc = etcp_route_send(inst, group_id, dst, e, 1, 0);
|
||||
if (rc != 0) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "%s: etcp_route_send failed rc=%d to 0x%016llx group=0x%016llx", MDL_ID, rc, (unsigned long long)dst, (unsigned long long)group_id); u_free(e->dgram); queue_entry_free(e); }
|
||||
return rc;
|
||||
}
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@ static void nat_transport_client_tun_out_cb(struct ll_queue* q, void* arg) {
|
||||
queue_dgram_free(pkt); queue_entry_free(pkt);
|
||||
queue_resume_callback(q);
|
||||
|
||||
int ret = etcp_route_send(inst, TOPO_GROUP_UTUN, tr->nat_via_node_id, new_entry, 0);
|
||||
int ret = etcp_route_send(inst, TOPO_GROUP_UTUN, tr->nat_via_node_id, new_entry, 0, 0);
|
||||
if (ret != 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT client: etcp_route_send to provider %016llx failed",
|
||||
(unsigned long long)tr->nat_via_node_id);
|
||||
@@ -89,7 +89,7 @@ static void nat_transport_provider_tun_out_cb(struct ll_queue* q, void* arg) {
|
||||
queue_dgram_free(pkt); queue_entry_free(pkt);
|
||||
queue_resume_callback(q);
|
||||
|
||||
int send_ret = etcp_route_send(inst, TOPO_GROUP_UTUN, entry->src_node_id, new_entry, 0);
|
||||
int send_ret = etcp_route_send(inst, TOPO_GROUP_UTUN, entry->src_node_id, new_entry, 0, 0);
|
||||
if (send_ret != 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT provider: etcp_route_send back to node %016llx failed",
|
||||
(unsigned long long)entry->src_node_id);
|
||||
|
||||
@@ -143,7 +143,7 @@ static void raw_read_cb(socket_t sock, void* arg) {
|
||||
memcpy(e->dgram + 12, &icmp_hdr->icmp_seq, 2);
|
||||
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len);
|
||||
e->len = ICMP_PROXY_HDR_SIZE + payload_len;
|
||||
int ret = etcp_route_send(g_icmp_ctx->inst, TOPO_GROUP_UTUN, r->client_node_id, e, 0);
|
||||
int ret = etcp_route_send(g_icmp_ctx->inst, TOPO_GROUP_UTUN, r->client_node_id, e, 0, 0);
|
||||
if (ret != 0) DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "icmp_proxy: etcp_route_send reply failed: %d", ret);
|
||||
else DEBUG_INFO(DEBUG_CATEGORY_PROXY, "icmp_proxy: reply forwarded to client %016llx", (unsigned long long)r->client_node_id);
|
||||
u_free(r);
|
||||
@@ -180,7 +180,7 @@ static void exit_handle_request(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
memcpy(e->dgram + 12, &echo_seq, 2);
|
||||
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len);
|
||||
e->len = ICMP_PROXY_HDR_SIZE + payload_len;
|
||||
etcp_route_send(inst, TOPO_GROUP_UTUN, client_node_id, e, 0);
|
||||
etcp_route_send(inst, TOPO_GROUP_UTUN, client_node_id, e, 0, 0);
|
||||
} else queue_entry_free(e);
|
||||
}
|
||||
} else {
|
||||
@@ -244,7 +244,7 @@ int icmp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id,
|
||||
memcpy(e->dgram + 12, &echo_seq, 2);
|
||||
if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len);
|
||||
e->len = ICMP_PROXY_HDR_SIZE + payload_len;
|
||||
return etcp_route_send(inst, TOPO_GROUP_UTUN, exit_node_id, e, 0);
|
||||
return etcp_route_send(inst, TOPO_GROUP_UTUN, exit_node_id, e, 0, 0);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
@@ -70,7 +70,7 @@ static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst,
|
||||
queue_dgram_free(e); queue_entry_free(e); return -1;
|
||||
}
|
||||
e->len = (uint16_t)(TCP_PROXY_HDR_SIZE + len);
|
||||
int ret = etcp_route_send(inst, group_id, dst, e, force);
|
||||
int ret = etcp_route_send(inst, group_id, dst, e, force, 0);
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_PROXY, "SOCKS send_msg subcmd=%02x sid=%08x len=%zu force=%d → ret=%d",
|
||||
subcmd, sid, len, force, ret);
|
||||
return ret;
|
||||
|
||||
@@ -79,7 +79,7 @@ static int tcp_proxy_client_send_msg(struct UTUN_INSTANCE* inst, uint64_t group_
|
||||
memcpy(e->dgram + 2, &sid, 4);
|
||||
if (len > 0) memcpy(e->dgram + TCP_PROXY_HDR_SIZE, data, len);
|
||||
e->len = TCP_PROXY_HDR_SIZE + len;
|
||||
return etcp_route_send(inst, group_id, dst, e, force);
|
||||
return etcp_route_send(inst, group_id, dst, e, force, 0);
|
||||
}
|
||||
|
||||
static int tcp_proxy_client_send_connect(struct tcp_proxy_client_conn* pc) {
|
||||
|
||||
@@ -65,7 +65,7 @@ static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst,
|
||||
queue_dgram_free(e); queue_entry_free(e); return -1;
|
||||
}
|
||||
e->len = TCP_PROXY_HDR_SIZE + len;
|
||||
return etcp_route_send(inst, group_id, dst, e, force);
|
||||
return etcp_route_send(inst, group_id, dst, e, force, 0);
|
||||
}
|
||||
|
||||
static void close_retry_cb(void* arg) {
|
||||
|
||||
@@ -64,7 +64,7 @@ static void flow_read_cb(socket_t sock, void* arg) {
|
||||
memcpy(e->dgram + UDP_PROXY_HDR_SIZE, buf, n);
|
||||
e->len = UDP_PROXY_HDR_SIZE + n;
|
||||
|
||||
etcp_route_send(g_udp_ctx->inst, TOPO_GROUP_UTUN, f->client_node_id, e, 0);
|
||||
etcp_route_send(g_udp_ctx->inst, TOPO_GROUP_UTUN, f->client_node_id, e, 0, 0);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -168,7 +168,7 @@ int udp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id,
|
||||
memcpy(e->dgram + 12, &dst_port, 2);
|
||||
if (payload_len > 0) memcpy(e->dgram + UDP_PROXY_HDR_SIZE, payload, payload_len);
|
||||
e->len = UDP_PROXY_HDR_SIZE + payload_len;
|
||||
return etcp_route_send(inst, TOPO_GROUP_UTUN, exit_node_id, e, 0);
|
||||
return etcp_route_send(inst, TOPO_GROUP_UTUN, exit_node_id, e, 0, 0);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
@@ -440,7 +440,7 @@ void conn_mgr_close(struct CONN_MGR_HANDLE* h) {
|
||||
pkt.cmd = ETCP_RT_ID_CONN_MGR; pkt.subcmd = CM_SUBCMD_DISCONNECT; pkt.node_id = entry->node_id;
|
||||
struct ll_entry* qe = queue_entry_new(0);
|
||||
if (qe) { qe->dgram = u_malloc(sizeof(pkt)); memcpy(qe->dgram, &pkt, sizeof(pkt)); qe->len = sizeof(pkt);
|
||||
etcp_route_send(entry->mgr->instance, entry->mgr->group->group_id, entry->node_id, qe, 1); }
|
||||
etcp_route_send(entry->mgr->instance, entry->mgr->group->group_id, entry->node_id, qe, 1, 0); }
|
||||
/* NCD CLOSE — транспортный уровень (отправит CLOSE/KEEP_ALIVE через node_conn_direct) */
|
||||
}
|
||||
cm_entry_cleanup(entry); u_free(h);
|
||||
@@ -458,7 +458,7 @@ int conn_mgr_send(struct CONN_MGR_HANDLE* h, struct ll_entry* e) {
|
||||
entry->last_traffic_tb = get_time_tb();
|
||||
struct ETCP_ROUTER_CONN* r = etcp_router_conn_get(entry->mgr->instance, entry->mgr->group->group_id, entry->node_id, ETCP_RT_ID_CONN_MGR);
|
||||
if (!r) { queue_entry_free(e); return -1; }
|
||||
int ret = etcp_router_conn_send(r, e->dgram, e->len); queue_entry_free(e); return ret;
|
||||
int ret = etcp_router_conn_send(r, e->dgram, e->len, 0); queue_entry_free(e); return ret;
|
||||
}
|
||||
|
||||
/* ═══════ локальное сканирование ═══════ */
|
||||
@@ -676,7 +676,7 @@ void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) {
|
||||
for (uint8_t i=0;i<dc;i++) { *p++=addrs[i].t; memcpy(p,addrs[i].ip,4);p+=4; memcpy(p,&addrs[i].port,2);p+=2; *p++=addrs[i].sid; }
|
||||
struct ll_entry* qe = queue_entry_new(0);
|
||||
if (!qe) { u_free(pkt); cm_deliver_event(entry, CONN_EVENT_TIMEOUT); return; }
|
||||
qe->dgram=pkt; qe->len=(uint16_t)sz; etcp_route_send(entry->mgr->instance, group->group_id, entry->node_id, qe, 1);
|
||||
qe->dgram=pkt; qe->len=(uint16_t)sz; etcp_route_send(entry->mgr->instance, group->group_id, entry->node_id, qe, 1, 0);
|
||||
struct cm_reverse_pending* rp = u_calloc(1, sizeof(*rp));
|
||||
if (rp) { rp->request_id=req_id; rp->entry=entry; rp->next=entry->mgr->reverse_pending; entry->mgr->reverse_pending=rp; }
|
||||
entry->main.timer = uasync_set_timeout(entry->mgr->instance->ua, CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS*10,
|
||||
|
||||
@@ -26,7 +26,7 @@ void cm_start_phase_indirect(struct CONN_MGR_ENTRY* entry) {
|
||||
for (uint8_t i=0;i<req.candidate_count;i++) req.candidates[i]=mgr->best_candidates[i];
|
||||
struct ll_entry* qe = queue_entry_new(0); if (!qe) return;
|
||||
qe->dgram=u_malloc(sizeof(req)); memcpy(qe->dgram,&req,sizeof(req)); qe->len=sizeof(req);
|
||||
etcp_route_send(mgr->instance, mgr->group->group_id, entry->node_id, qe, 1);
|
||||
etcp_route_send(mgr->instance, mgr->group->group_id, entry->node_id, qe, 1, 0);
|
||||
entry->main.timer = uasync_set_timeout(mgr->instance->ua, CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS*10, entry, cm_exchange_timeout_cb, "conn_mgr_interm_exch");
|
||||
struct cm_exchange_pending* ep = u_calloc(1,sizeof(*ep));
|
||||
if (ep) { ep->request_id=entry->main.request_id; ep->entry=entry; ep->timer=entry->main.timer; ep->next=mgr->exchange_pending; mgr->exchange_pending=ep; }
|
||||
@@ -67,7 +67,7 @@ void cm_compute_intermediaries(struct CONN_MGR_ENTRY* entry, struct CM_EXCHANGE_
|
||||
for(uint8_t i=0;i<sel;i++){pkt.selected[i].node_id=all[i].nid;pkt.selected[i].rtt=0;
|
||||
struct TOPO_GROUP_NODE* nq=topo_node_find_by_id(entry->mgr->group,all[i].nid); if(nq)pkt.selected[i].rtt=topo_get_chain_rtt(nq);}
|
||||
struct ll_entry* qe=queue_entry_new(0);
|
||||
if(qe){qe->dgram=u_malloc(sizeof(pkt));memcpy(qe->dgram,&pkt,sizeof(pkt));qe->len=sizeof(pkt);etcp_route_send(entry->mgr->instance,entry->mgr->group->group_id,entry->node_id,qe,1);}
|
||||
if(qe){qe->dgram=u_malloc(sizeof(pkt));memcpy(qe->dgram,&pkt,sizeof(pkt));qe->len=sizeof(pkt);etcp_route_send(entry->mgr->instance,entry->mgr->group->group_id,entry->node_id,qe,1,0);}
|
||||
entry->conn_type=CONN_TYPE_INDIRECT; entry->state=CONN_MGR_STATE_CONNECTED;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL,"conn_mgr: indirect OK for 0x%016llx via %u intermediaries",(unsigned long long)entry->node_id,sel);
|
||||
cm_update_nodeinfo(entry); cm_deliver_event(entry,CONN_EVENT_UP);
|
||||
@@ -140,6 +140,6 @@ void cm_handle_interm_exchange_req(struct ETCP_CONN* conn, struct CM_EXCHANGE_RE
|
||||
}
|
||||
size_t sz=offsetof(struct CM_EXCHANGE_RESP,your_candidates)+(size_t)resp.your_count*sizeof(struct CONN_MGR_CANDIDATE);
|
||||
struct ll_entry* qe=queue_entry_new(0);
|
||||
if(qe){qe->dgram=u_malloc(sz);memcpy(qe->dgram,&resp,sz);qe->len=(uint16_t)sz;etcp_route_send(mgr->instance,mgr->group->group_id,conn->peer_node_id,qe,1);}
|
||||
if(qe){qe->dgram=u_malloc(sz);memcpy(qe->dgram,&resp,sz);qe->len=(uint16_t)sz;etcp_route_send(mgr->instance,mgr->group->group_id,conn->peer_node_id,qe,1,0);}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL,"conn_mgr: sent EXCHANGE_RESP to 0x%016llx my=%u your=%u",(unsigned long long)conn->peer_node_id,resp.my_count,resp.your_count);
|
||||
}
|
||||
+238
-498
File diff suppressed because it is too large.
Load diff
@@ -1,10 +1,11 @@
|
||||
// etcp_router.h — Сервисный слой маршрутизации поверх ETCP
|
||||
// Маршрутизирует сервисные пакеты до целевой ноды, на промежуточных нодах ретранслирует
|
||||
// Упрощённый TCP поверх ETCP: восстановление порядка, дедупликация, без переповторов
|
||||
// Упрощённый TCP поверх ETCP: восстановление порядка, дедупликация, ретрансмиты, inflight-контроль.
|
||||
// Подпись/шифрование вынесены в автономный модуль route_crypto (encode/decode).
|
||||
//
|
||||
// Формат SVC_ROUTE пакета:
|
||||
// [cmd:1] [group_id:8] [dst_node_id:8] [src_node_id:8] [seq:4] [svc_id:1] [flags:1] [timestamp:2] [payload...]
|
||||
// flags: bit7=START, bit6=RST, bit5-4=sess_id(0-3), bit2=ENCRYPTED, bit1=CLOSE
|
||||
// flags: bit7=START, bit6=RST, bit5-4=sess_id(0-3), bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE
|
||||
// ACK-пакет: тот же заголовок, seq=rx_seq, payload_len=0
|
||||
#ifndef ETCP_ROUTER_H
|
||||
#define ETCP_ROUTER_H
|
||||
@@ -35,12 +36,14 @@ struct SVC_ROUTE_HDR {
|
||||
#define SVC_ROUTE_MAX_BINDINGS 256
|
||||
|
||||
// Единый формат доставки сервисной кодограммы (router → сервис):
|
||||
// [svc_id:1][src_node_id:8][dst_node_id:8][payload...]
|
||||
// [svc_id:1][src_node_id:8][dst_node_id:8][rx_flags:1][payload...]
|
||||
// src/dst — реальные end-to-end узлы из SVC_ROUTE заголовка (не промежуточные).
|
||||
// rx_flags — биты ROUTER_FLAG_ENCRYPTED/SIGNED, бывшие на wire (статус для сервиса).
|
||||
#define ROUTER_SVC_SRC_OFF 1
|
||||
#define ROUTER_SVC_DST_OFF 9
|
||||
#define ROUTER_SVC_PAYLOAD_OFF 17
|
||||
#define ROUTER_SVC_HDR_SIZE 17 // svc_id(1) + src_node_id(8) + dst_node_id(8)
|
||||
#define ROUTER_SVC_FLAGS_OFF 17
|
||||
#define ROUTER_SVC_PAYLOAD_OFF 18
|
||||
#define ROUTER_SVC_HDR_SIZE 18 // svc_id(1) + src_node_id(8) + dst_node_id(8) + rx_flags(1)
|
||||
|
||||
// Биты в flags
|
||||
#define ROUTER_FLAG_START 0x80
|
||||
@@ -158,15 +161,14 @@ struct ETCP_ROUTER_CONN {
|
||||
#define MINRTT_WINDOW_SIZE 10
|
||||
#define MINRTT_DEFAULT_TB 100 // default minRTT = 10ms (заменяется первым RTT)
|
||||
|
||||
// Inflight запись — копия отправленного пакета для возможного ретрансмита
|
||||
// Inflight запись — копия финального wire-пакета (уже закодирован encode'ом) для ретрансмита
|
||||
struct ROUTER_INFLIGHT {
|
||||
struct ll_entry ll; // индекс по seq (4 байта, offset 0)
|
||||
uint32_t seq;
|
||||
uint64_t last_sent_tb; // время последней отправки (0.1ms)
|
||||
uint8_t send_count; // число переотправок
|
||||
uint8_t is_encrypted; // 1 = E2E-шифрованный пакет
|
||||
uint8_t* payload; // копия данных
|
||||
size_t payload_len;
|
||||
uint8_t* dgram; // копия финального пакета [SVC_ROUTE_HDR][payload][sig?]
|
||||
size_t dgram_len;
|
||||
};
|
||||
|
||||
// Bindings для сервисов внутри etcp_router (аналогично ETCP_BINDINGS)
|
||||
@@ -184,24 +186,18 @@ void etcp_router_destroy(struct UTUN_INSTANCE* inst);
|
||||
int etcp_router_bind(struct UTUN_INSTANCE* inst, uint8_t svc_id, etcp_recv_fn callback);
|
||||
int etcp_router_unbind(struct UTUN_INSTANCE* inst, uint8_t svc_id);
|
||||
|
||||
// Отправить сервисный пакет (авто-conn, seq, inflight-контроль через send_q)
|
||||
int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_node_id, struct ll_entry* entry, int force);
|
||||
|
||||
// Отправить сервисный пакет с E2E-шифрованием (AES-128-CCM через X25519 ECDH)
|
||||
int etcp_route_send_encrypted(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_node_id, struct ll_entry* entry, int force);
|
||||
// Отправить сервисный пакет (авто-conn, seq, inflight-контроль через send_q).
|
||||
// mode — битовая маска ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT (см. route_crypto.h), 0 = обычный пакет.
|
||||
int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_node_id, struct ll_entry* entry, int force, int mode);
|
||||
|
||||
// Найти/создать состояние seq-подключения по (group_id, remote_node_id, svc_id)
|
||||
struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst,
|
||||
uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id);
|
||||
|
||||
// Отправить данные с авто-seq и контролем inflight
|
||||
// data: payload без svc_id, flags: битовые флаги (зарезервировано)
|
||||
// data: payload без svc_id, mode: ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT (0 = обычный)
|
||||
int etcp_router_conn_send(struct ETCP_ROUTER_CONN* rconn,
|
||||
const uint8_t* data, size_t len);
|
||||
|
||||
// Отправить данные с Ed25519 подписью (аналог etcp_router_conn_send с флагом ROUTER_FLAG_SIGNED)
|
||||
int etcp_router_conn_send_signed(struct ETCP_ROUTER_CONN* rconn,
|
||||
const uint8_t* data, size_t len);
|
||||
const uint8_t* data, size_t len, int mode);
|
||||
|
||||
// Закрыть seq-подключение
|
||||
void etcp_router_conn_close(struct ETCP_ROUTER_CONN* rconn);
|
||||
|
||||
@@ -22,20 +22,21 @@ e->dgram = u_malloc(1 + payload_len);
|
||||
e->dgram[0] = svc_id;
|
||||
memcpy(e->dgram + 1, payload, payload_len);
|
||||
e->len = 1 + payload_len;
|
||||
etcp_route_send(inst, dst_node_id, e, force);
|
||||
etcp_route_send(inst, group_id, dst_node_id, e, force, mode); // mode: 0 / ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT
|
||||
|
||||
// Или через существующий ROUTER_CONN:
|
||||
struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, remote_node_id, svc_id);
|
||||
etcp_router_conn_send(rconn, data, len);
|
||||
struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, group_id, remote_node_id, svc_id);
|
||||
etcp_router_conn_send(rconn, data, len, mode);
|
||||
```
|
||||
|
||||
### Приём
|
||||
```c
|
||||
void my_service_callback(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
if (!entry) { /* соединение закрыто */ return; }
|
||||
uint8_t svc_id = entry->dgram[0];
|
||||
uint64_t from = *(uint64_t*)(entry->dgram + 1); // remote_node_id
|
||||
// ... данные начиная с entry->dgram[9] ...
|
||||
uint8_t svc_id = entry->dgram[0];
|
||||
uint64_t from = *(uint64_t*)(entry->dgram + ROUTER_SVC_SRC_OFF); // remote_node_id
|
||||
uint8_t rx_flags = entry->dgram[ROUTER_SVC_FLAGS_OFF]; // был ли SIGNED/ENCRYPTED на wire
|
||||
// ... данные начиная с entry->dgram[ROUTER_SVC_PAYLOAD_OFF] ...
|
||||
queue_dgram_free(entry);
|
||||
queue_entry_free(entry);
|
||||
}
|
||||
@@ -45,34 +46,40 @@ void my_service_callback(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
```c
|
||||
// На send_q (inflight переполнен):
|
||||
struct queue_waiter_handle h;
|
||||
etcp_router_on_send_ready(inst, node_id, svc_id, &h, my_ready_cb, my_arg);
|
||||
etcp_router_on_send_ready(inst, group_id, node_id, svc_id, &h, my_ready_cb, my_arg);
|
||||
// Когда send_q освободится — вызовется my_ready_cb
|
||||
|
||||
// На normalizer->input (сетевая очередь):
|
||||
etcp_router_waiter_register(inst, node_id, &h, my_ready_cb, my_arg);
|
||||
etcp_router_waiter_register(inst, group_id, node_id, &h, my_ready_cb, my_arg);
|
||||
```
|
||||
|
||||
### Подписанные сообщения
|
||||
### Подпись / шифрование (модуль route_crypto)
|
||||
```c
|
||||
etcp_router_conn_send_signed(rconn, data, len); // добавляет Ed25519-подпись
|
||||
// mode — битовая маска, применяется в начале функции отправки (route_crypto_encode),
|
||||
// при приёме проверяется/расшифровывается перед вызовом коллбэка (route_crypto_decode).
|
||||
#include "route_crypto.h"
|
||||
etcp_route_send(inst, group_id, dst, e, force, ROUTE_CRYPTO_SIGN | ROUTE_CRYPTO_ENCRYPT);
|
||||
```
|
||||
|
||||
## 3. API
|
||||
|
||||
### Ключевые структуры
|
||||
|
||||
**SVC_ROUTE_HDR** (25 байт) — заголовок пакета:
|
||||
`cmd(1) + dst_node_id(8) + src_node_id(8) + seq(4) + svc_id(1) + flags(1) + timestamp(2)`
|
||||
**SVC_ROUTE_HDR** (33 байта) — заголовок пакета:
|
||||
`cmd(1) + group_id(8) + dst_node_id(8) + src_node_id(8) + seq(4) + svc_id(1) + flags(1) + timestamp(2)`
|
||||
|
||||
Флаги: `ROUTER_FLAG_START` (0x80), `ROUTER_FLAG_RST` (0x40), `ROUTER_FLAG_SIGNED` (0x08), `ROUTER_FLAG_CLOSE` (0x02). Sess_id в bits 5-4.
|
||||
Флаги: `ROUTER_FLAG_START` (0x80), `ROUTER_FLAG_RST` (0x40), `ROUTER_FLAG_SIGNED` (0x08), `ROUTER_FLAG_ENCRYPTED` (0x04), `ROUTER_FLAG_CLOSE` (0x02). Sess_id в bits 5-4.
|
||||
|
||||
**ETCP_ROUTER_CONN** — состояние логического подключения (remote_node_id + svc_id):
|
||||
**Формат доставки сервису** (router → callback):
|
||||
`[svc_id:1][src_node_id:8][dst_node_id:8][rx_flags:1][payload...]` (ROUTER_SVC_HDR_SIZE = 18).
|
||||
|
||||
**ETCP_ROUTER_CONN** — состояние логического подключения (group_id + remote_node_id + svc_id):
|
||||
- `tx_seq`, `rx_seq`, `tx_acked` — seq-нумерация для порядка и inflight
|
||||
- `recv_q` — reorder-очередь с хеш-индексом по seq (восстановление порядка)
|
||||
- `send_q` — очередь ожидания при полном inflight (backpressure)
|
||||
- `send_waiter` — waiter на send_input_q (по 1 пакету, round-robin между сервисами)
|
||||
- `watchdog_timer` — медленная проверка инварианта drain (страховка от заклинивания)
|
||||
- `inflight_q` — копии отправленных пакетов для ретрансмита (хеш по seq)
|
||||
- `inflight_q` — копии финальных отправленных пакетов для ретрансмита (хеш по seq)
|
||||
- `incoming_q` — FIFO между сетевым приёмом и recv_q (защита от гонок)
|
||||
- `rtt`, `rtt_jitter`, `minrtt` — измерения задержки
|
||||
- `inflight_limit` — текущий лимит пакетов в полёте (minrtt_probe снижает до 4)
|
||||
@@ -80,9 +87,9 @@ etcp_router_conn_send_signed(rconn, data, len); // добавляет Ed25519-
|
||||
- `start_sent`, `peer_sync_done` — синхронизация после (пере)подключения
|
||||
- `closed` — флаг закрытия (игнорирование таймеров)
|
||||
|
||||
**ROUTER_INFLIGHT** — запись в inflight_q: `seq, last_sent_tb, send_count, payload*`
|
||||
**ROUTER_INFLIGHT** — запись в inflight_q: `seq, last_sent_tb, send_count, dgram*` (финальный wire-пакет)
|
||||
|
||||
**TRANSIT_QUEUE** — per (src,dst) пара на промежуточном узле:
|
||||
**TRANSIT_QUEUE** — per (group_id, src, dst) пара на промежуточном узле:
|
||||
- `q` — FIFO транзитных пакетов
|
||||
- `waiter` — backpressure на send_input_q next_hop'а
|
||||
- `conn` — ETCP_CONN следующего шага
|
||||
@@ -91,11 +98,11 @@ etcp_router_conn_send_signed(rconn, data, len); // добавляет Ed25519-
|
||||
```
|
||||
Приём: сеть → incoming_q (FIFO) → router_incoming_q_cb → recv_q (хеш по seq)
|
||||
↓
|
||||
router_try_assembly → deliver (rx_seq++)
|
||||
router_try_assembly → deliver → route_crypto_decode → cb
|
||||
|
||||
Отправка: router_enqueue_send → send_q (FIFO, backpressure)
|
||||
Отправка: router_enqueue_send → router_build_packet (seq + route_crypto_encode) → send_q (FIFO, backpressure)
|
||||
router_send_kick → waiter на send_input_q → router_send_drain_cb (по 1 пакету, round-robin)
|
||||
→ router_send_one_flags → etcp_send + inflight_q (копия)
|
||||
→ etcp_send + inflight_q (копия финального пакета)
|
||||
↓
|
||||
router_track_inflight_state + retrans_schedule
|
||||
ACK: периодический (10ms) + idle (500ms) → router_send_ack(rx_seq)
|
||||
@@ -119,17 +126,22 @@ ACK: периодический (10ms) + idle (500ms) → router_send_ack(rx_seq
|
||||
| `etcp_router_destroy(inst)` | Деинициализация: unbind + close_all + free |
|
||||
| `etcp_router_bind(inst, svc_id, cb)` | Зарегистрировать обработчик сервиса |
|
||||
| `etcp_router_unbind(inst, svc_id)` | Удалить обработчик сервиса |
|
||||
| `etcp_route_send(inst, dst, entry, force)` | Отправить пакет (loopback/transit/direct) |
|
||||
| `etcp_router_conn_get(inst, remote, svc_id)` | Найти или создать ROUTER_CONN |
|
||||
| `etcp_router_conn_send(rconn, data, len)` | Отправить данные с авто-seq и inflight-контролем |
|
||||
| `etcp_router_conn_send_signed(rconn, data, len)` | Отправить с Ed25519-подписью |
|
||||
| `etcp_route_send(inst, group, dst, entry, force, mode)` | Отправить пакет (loopback/transit/direct); mode = ROUTE_CRYPTO_SIGN/ENCRYPT |
|
||||
| `etcp_router_conn_get(inst, group, remote, svc_id)` | Найти или создать ROUTER_CONN |
|
||||
| `etcp_router_conn_send(rconn, data, len, mode)` | Отправить данные с авто-seq и inflight-контролем |
|
||||
| `etcp_router_conn_close(rconn)` | Закрыть seq-подключение (CLOSE + уведомление сервиса) |
|
||||
| `etcp_router_conn_close_async(rconn, cb, arg)` | Асинхронное закрытие с коллбэком |
|
||||
| `etcp_router_conn_close_all_for_node(inst, node_id)` | Закрыть все conn к узлу |
|
||||
| `etcp_router_conn_restart(inst, remote, svc_id)` | Сброс состояния (перезапуск удалённой стороны) |
|
||||
| `etcp_router_conn_close_all_for_node(inst, group, node_id)` | Закрыть все conn к узлу |
|
||||
| `etcp_router_conn_restart(inst, group, remote, svc_id)` | Сброс состояния (перезапуск удалённой стороны) |
|
||||
| `etcp_router_pause_retrans_for_node(inst, node_id)` | Сбросить ретрансмиты без закрытия (для conn reinit) |
|
||||
| `router_set_max_inflight(rconn, new_max)` | Установить рабочий max_inflight |
|
||||
| `etcp_router_input_q_count(inst, node_id)` | Размер normalizer->input очереди узла |
|
||||
| `etcp_router_waiter_register/cancel(inst, node_id, h, cb, arg)` | Backpressure на normalizer->input |
|
||||
| `etcp_router_on_send_ready/cancel_send_ready(inst, node, svc, h, cb, arg)` | Backpressure на send_q |
|
||||
| `etcp_router_input_q_count(inst, group, node_id)` | Размер normalizer->input очереди узла |
|
||||
| `etcp_router_waiter_register/cancel(inst, group, node_id, h, cb, arg)` | Backpressure на normalizer->input |
|
||||
| `etcp_router_on_send_ready/cancel_send_ready(inst, group, node, svc, h, cb, arg)` | Backpressure на send_q |
|
||||
| `etcp_router_transit_queues_destroy(conn)` | Удалить все транзитные очереди ETCP_CONN |
|
||||
|
||||
### Модуль route_crypto (пред/пост-обработка пакета)
|
||||
| Функция | Описание |
|
||||
|---|---|
|
||||
| `route_crypto_encode(inst, peer, base, len, mode, &out, &len)` | Шифрование/подпись в начале отправки → финальный пакет |
|
||||
| `route_crypto_decode(inst, wire, len, &out, &len, &rx_flags)` | Проверка подписи/расшифровка перед коллбэком; ошибка → дроп |
|
||||
@@ -0,0 +1,160 @@
|
||||
// route_crypto.c — пред/пост-обработка SVC_ROUTE пакетов (шифрование + подпись)
|
||||
#include "route_crypto.h"
|
||||
#include "utun_instance.h"
|
||||
#include "topo_node.h"
|
||||
#include "../transport_layer/secure_channel.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/mem.h"
|
||||
#include <string.h>
|
||||
|
||||
// ECDH-контекст для пира (кэш в inst->e2e_ctx_cache). NULL = нет NODEINFO / ECDH не удался.
|
||||
static struct secure_channel* route_crypto_e2e_ctx(struct UTUN_INSTANCE* inst, uint64_t peer_node_id) {
|
||||
for (int i = 0; i < E2E_CTX_CACHE_SIZE; i++) {
|
||||
if (inst->e2e_ctx_cache[i].valid && inst->e2e_ctx_cache[i].peer_node_id == peer_node_id)
|
||||
return &inst->e2e_ctx_cache[i].ctx;
|
||||
}
|
||||
struct TOPO_NODE* tn = topo_node_registry_find(inst->topo_groups, peer_node_id);
|
||||
if (!tn) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto: no NODEINFO for peer=%016llx", (unsigned long long)peer_node_id);
|
||||
return NULL;
|
||||
}
|
||||
int slot = -1;
|
||||
for (int i = 0; i < E2E_CTX_CACHE_SIZE; i++) {
|
||||
if (!inst->e2e_ctx_cache[i].valid) { slot = i; break; }
|
||||
}
|
||||
if (slot < 0) slot = 0;
|
||||
sc_init_ctx(&inst->e2e_ctx_cache[slot].ctx, &inst->my_keys);
|
||||
if (sc_set_peer_public_key(&inst->e2e_ctx_cache[slot].ctx, tn->public_key, SC_PEER_PUBKEY_BIN) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto: ECDH failed peer=%016llx", (unsigned long long)peer_node_id);
|
||||
inst->e2e_ctx_cache[slot].valid = 0;
|
||||
return NULL;
|
||||
}
|
||||
inst->e2e_ctx_cache[slot].peer_node_id = peer_node_id;
|
||||
inst->e2e_ctx_cache[slot].valid = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "route_crypto: new context for peer=%016llx slot=%d",
|
||||
(unsigned long long)peer_node_id, slot);
|
||||
return &inst->e2e_ctx_cache[slot].ctx;
|
||||
}
|
||||
|
||||
int route_crypto_encode(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
|
||||
const uint8_t* base, size_t base_len, int mode,
|
||||
uint8_t** out, size_t* out_len) {
|
||||
if (!inst || !base || base_len < SVC_ROUTE_HDR_SIZE || !out || !out_len) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_encode: invalid args inst=%p base=%p len=%zu mode=%d",
|
||||
(void*)inst, (const void*)base, base_len, mode);
|
||||
return -1;
|
||||
}
|
||||
const uint8_t* pl = base + SVC_ROUTE_HDR_SIZE;
|
||||
size_t pl_len = base_len - SVC_ROUTE_HDR_SIZE;
|
||||
|
||||
const uint8_t* body = pl;
|
||||
size_t body_len = pl_len;
|
||||
uint8_t* enc_buf = NULL;
|
||||
|
||||
if (mode & ROUTE_CRYPTO_ENCRYPT) {
|
||||
struct secure_channel* e2e = route_crypto_e2e_ctx(inst, peer_node_id);
|
||||
if (!e2e) return -1;
|
||||
size_t enc_cap = pl_len + SC_NONCE_SIZE + SC_CRC32_SIZE + SC_TAG_SIZE;
|
||||
enc_buf = u_malloc(enc_cap);
|
||||
if (!enc_buf) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_encode: enc_buf alloc fail"); return -1; }
|
||||
size_t enc_len = 0;
|
||||
if (sc_encrypt(e2e, pl, pl_len, enc_buf, &enc_len) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_encode: sc_encrypt FAIL peer=%016llx len=%zu",
|
||||
(unsigned long long)peer_node_id, pl_len);
|
||||
u_free(enc_buf); return -1;
|
||||
}
|
||||
body = enc_buf; body_len = enc_len;
|
||||
}
|
||||
|
||||
size_t sig_len = (mode & ROUTE_CRYPTO_SIGN) ? SC_SIGN_SIZE : 0;
|
||||
size_t total = SVC_ROUTE_HDR_SIZE + body_len + sig_len;
|
||||
uint8_t* dgram = u_malloc(total);
|
||||
if (!dgram) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_encode: out alloc fail"); if (enc_buf) u_free(enc_buf); return -1; }
|
||||
memcpy(dgram, base, SVC_ROUTE_HDR_SIZE);
|
||||
memcpy(dgram + SVC_ROUTE_HDR_SIZE, body, body_len);
|
||||
|
||||
struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)dgram;
|
||||
if (mode & ROUTE_CRYPTO_ENCRYPT) hdr->flags |= ROUTER_FLAG_ENCRYPTED;
|
||||
if (mode & ROUTE_CRYPTO_SIGN) {
|
||||
hdr->flags |= ROUTER_FLAG_SIGNED;
|
||||
if (sc_ed25519_sign(inst->my_ed25519_privkey, dgram, SVC_ROUTE_HDR_SIZE + body_len,
|
||||
dgram + SVC_ROUTE_HDR_SIZE + body_len) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_encode: sign FAIL peer=%016llx", (unsigned long long)peer_node_id);
|
||||
u_free(dgram); if (enc_buf) u_free(enc_buf); return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_buf) u_free(enc_buf);
|
||||
*out = dgram; *out_len = total;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int route_crypto_decode(struct UTUN_INSTANCE* inst,
|
||||
const uint8_t* wire, size_t wire_len,
|
||||
uint8_t** out, size_t* out_len, uint8_t* rx_flags) {
|
||||
if (!inst || !wire || wire_len < SVC_ROUTE_HDR_SIZE || !out || !out_len || !rx_flags) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: invalid args inst=%p wire=%p len=%zu",
|
||||
(void*)inst, (const void*)wire, wire_len);
|
||||
return -1;
|
||||
}
|
||||
struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)wire;
|
||||
uint8_t fl = hdr->flags & (ROUTER_FLAG_ENCRYPTED | ROUTER_FLAG_SIGNED);
|
||||
*rx_flags = fl;
|
||||
|
||||
const uint8_t* body = wire + SVC_ROUTE_HDR_SIZE;
|
||||
size_t body_len = wire_len - SVC_ROUTE_HDR_SIZE;
|
||||
|
||||
if (fl & ROUTER_FLAG_SIGNED) {
|
||||
if (body_len < SC_SIGN_SIZE) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: SIGNED packet too short len=%zu from %016llx",
|
||||
wire_len, (unsigned long long)hdr->src_node_id);
|
||||
return -1;
|
||||
}
|
||||
size_t signed_len = SVC_ROUTE_HDR_SIZE + body_len - SC_SIGN_SIZE;
|
||||
const uint8_t* sig = wire + signed_len;
|
||||
struct TOPO_NODE* sni = topo_node_registry_find(inst->topo_groups, hdr->src_node_id);
|
||||
if (!sni) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: SIGNED from unknown node %016llx — dropping",
|
||||
(unsigned long long)hdr->src_node_id);
|
||||
return -1;
|
||||
}
|
||||
uint8_t zero[SC_PUBKEY_SIZE] = {0};
|
||||
if (memcmp(sni->ed25519_public_key, zero, SC_PUBKEY_SIZE) == 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: no Ed25519 pubkey for node %016llx — dropping",
|
||||
(unsigned long long)hdr->src_node_id);
|
||||
return -1;
|
||||
}
|
||||
if (sc_ed25519_verify(sni->ed25519_public_key, wire, signed_len, sig) != SC_OK) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: signature FAILED for node %016llx svc_id=%u — dropping",
|
||||
(unsigned long long)hdr->src_node_id, hdr->svc_id);
|
||||
return -1;
|
||||
}
|
||||
body_len -= SC_SIGN_SIZE;
|
||||
}
|
||||
|
||||
uint8_t* pt_buf = NULL;
|
||||
if (fl & ROUTER_FLAG_ENCRYPTED) {
|
||||
struct secure_channel* e2e = route_crypto_e2e_ctx(inst, hdr->src_node_id);
|
||||
if (!e2e) return -1;
|
||||
pt_buf = u_malloc(body_len);
|
||||
size_t pt_len = 0;
|
||||
if (!pt_buf || sc_decrypt(e2e, body, body_len, pt_buf, &pt_len) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: decrypt FAIL src=%016llx svc=%u len=%zu",
|
||||
(unsigned long long)hdr->src_node_id, hdr->svc_id, body_len);
|
||||
if (pt_buf) u_free(pt_buf);
|
||||
return -1;
|
||||
}
|
||||
body = pt_buf; body_len = pt_len;
|
||||
}
|
||||
|
||||
size_t total = SVC_ROUTE_HDR_SIZE + body_len;
|
||||
uint8_t* dgram = u_malloc(total);
|
||||
if (!dgram) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "route_crypto_decode: out alloc fail"); if (pt_buf) u_free(pt_buf); return -1; }
|
||||
memcpy(dgram, wire, SVC_ROUTE_HDR_SIZE);
|
||||
memcpy(dgram + SVC_ROUTE_HDR_SIZE, body, body_len);
|
||||
((struct SVC_ROUTE_HDR*)dgram)->flags &= ~(ROUTER_FLAG_ENCRYPTED | ROUTER_FLAG_SIGNED);
|
||||
|
||||
if (pt_buf) u_free(pt_buf);
|
||||
*out = dgram; *out_len = total;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// route_crypto.h — пред/пост-обработка SVC_ROUTE пакетов (шифрование + подпись)
|
||||
// Автономный модуль: из одного пакета формирует другой, пригодный для отправки/обработки.
|
||||
//
|
||||
// encode(): вызывается в начале функции отправки.
|
||||
// [SVC_ROUTE_HDR][plaintext] + mode → [SVC_ROUTE_HDR][payload][sig?]
|
||||
// decode(): вызывается перед вызовом сервисного коллбэка.
|
||||
// [SVC_ROUTE_HDR][payload][sig?] → [SVC_ROUTE_HDR][plaintext]
|
||||
//
|
||||
// Порядок кодирования: encrypt-then-sign (подпись поверх всего протокола, включая шифртекст).
|
||||
// При ошибке декодирования (плохая подпись / не удалось расшифровать) пакет дропается.
|
||||
#ifndef ROUTE_CRYPTO_H
|
||||
#define ROUTE_CRYPTO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "etcp_router.h"
|
||||
|
||||
struct UTUN_INSTANCE;
|
||||
|
||||
// Флаги трансформации (bitmask), совпадают с битами SVC_ROUTE_HDR.flags
|
||||
#define ROUTE_CRYPTO_ENCRYPT ROUTER_FLAG_ENCRYPTED // 0x04
|
||||
#define ROUTE_CRYPTO_SIGN ROUTER_FLAG_SIGNED // 0x08
|
||||
|
||||
// Кодировать пакет: base = [SVC_ROUTE_HDR][plaintext payload].
|
||||
// mode — битовая маска ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT.
|
||||
// Возвращает новый буфер (u_malloc) с финальным пакетом. 0 = успех, <0 = ошибка.
|
||||
int route_crypto_encode(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
|
||||
const uint8_t* base, size_t base_len, int mode,
|
||||
uint8_t** out, size_t* out_len);
|
||||
|
||||
// Декодировать пакет: wire = [SVC_ROUTE_HDR][payload][sig?].
|
||||
// Проверяет подпись и/или расшифровывает. Через *rx_flags сообщает, что было на wire
|
||||
// (ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT). Возвращает [SVC_ROUTE_HDR][plaintext] с очищенными флагами.
|
||||
// 0 = успех, <0 = ошибка (пакет дропается).
|
||||
int route_crypto_decode(struct UTUN_INSTANCE* inst,
|
||||
const uint8_t* wire, size_t wire_len,
|
||||
uint8_t** out, size_t* out_len, uint8_t* rx_flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // ROUTE_CRYPTO_H
|
||||
@@ -145,7 +145,7 @@ void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry, uint64_t
|
||||
} else {
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to node %016llx dst=%s",
|
||||
ip_len, (unsigned long long)nq->node_id, ip_to_str(&addr, AF_INET).str);
|
||||
int send_err = etcp_route_send(instance, TOPO_GROUP_UTUN, nq->node_id, entry, 1);
|
||||
int send_err = etcp_route_send(instance, TOPO_GROUP_UTUN, nq->node_id, entry, 1, 0);
|
||||
if (send_err != 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_route_send failed: dst=%s err=%d",
|
||||
ip_to_str(&addr, AF_INET).str, send_err);
|
||||
|
||||
Reference in new issue
Block a user