Browse Source

transport: publish ports assigned by the operating system

master
evgeny 6 days ago
parent
commit
991fc0a2c1
  1. 8
      src/transport_layer/etcp_connections.c
  2. 18
      src/transport_layer/stcp_link.c
  3. 2
      src/transport_layer/stcp_link.h
  4. 14
      tests/test_ncd_config.c

8
src/transport_layer/etcp_connections.c

@ -777,6 +777,14 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
u_free(e_sock);
return NULL;
}
socklen_t bound_len = sizeof(e_sock->local_addr);
if (getsockname(e_sock->fd, (struct sockaddr*)&e_sock->local_addr, &bound_len) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socket %s: cannot read bound address: %s",
name, socket_strerror(socket_get_error()));
socket_close_wrapper(e_sock->fd); u_free(e_sock); return NULL;
}
// Порт 0 выбирает ОС; NODEINFO и подбор сокетов должны видеть фактический адрес.
e_sock->interface_addr = e_sock->local_addr;
if (bind_addr->ss_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)bind_addr;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port));

18
src/transport_layer/stcp_link.c

@ -179,12 +179,28 @@ struct stcp_server *stcp_server_listen(struct stcp_link_config *cfg, uint16_t po
ss->srv = stcp_server_create(cfg->inst->ua, port, &cfg->inst->my_keys, cfg->inst->my_ed25519_pubkey,
cfg->inst, server_accept_cb, ss, NULL, NULL, cfg->listen_family);
if (!ss->srv) { u_free(ss); return NULL; }
uint16_t bound_port = stcp_server_get_port(ss->srv);
if (!bound_port) { stcp_server_destroy(ss->srv); u_free(ss); return NULL; }
if (tcp_sock) {
if (tcp_sock->local_addr.ss_family == AF_INET) {
((struct sockaddr_in*)&tcp_sock->local_addr)->sin_port = htons(bound_port);
((struct sockaddr_in*)&tcp_sock->interface_addr)->sin_port = htons(bound_port);
} else if (tcp_sock->local_addr.ss_family == AF_INET6) {
((struct sockaddr_in6*)&tcp_sock->local_addr)->sin6_port = htons(bound_port);
((struct sockaddr_in6*)&tcp_sock->interface_addr)->sin6_port = htons(bound_port);
}
}
if (cfg->reality_enabled && cfg->inst && cfg->inst->config)
stcp_server_set_reality(ss->srv, &cfg->inst->config->global.reality);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "port=%u", port);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "listen requested_port=%u bound_port=%u", port, bound_port);
return ss;
}
uint16_t stcp_link_server_get_port(const struct stcp_server *ss) {
if (!ss || !ss->srv) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp link server: missing listener"); return 0; }
return stcp_server_get_port(ss->srv);
}
void stcp_link_server_destroy(struct stcp_server *ss) {
if (!ss) return;
if (ss->srv) stcp_server_destroy(ss->srv);

2
src/transport_layer/stcp_link.h

@ -38,6 +38,8 @@ typedef void (*stcp_server_on_link_cb)(struct stcp_link *link, struct ETCP_SOCKE
struct stcp_server *stcp_server_listen(struct stcp_link_config *cfg, uint16_t port,
stcp_server_on_link_cb on_link, struct ETCP_SOCKET *tcp_sock);
void stcp_link_server_destroy(struct stcp_server *srv);
// Фактический порт слушателя адаптера (включая listen с port=0); 0 при ошибке.
uint16_t stcp_link_server_get_port(const struct stcp_server *srv);
/* Server list management (multiple servers per instance) */
void stcp_server_list_add(struct UTUN_INSTANCE *inst, struct stcp_server *srv);

14
tests/test_ncd_config.c

@ -7,6 +7,7 @@
#include "transport_layer/etcp.h"
#include "transport_layer/etcp_connections.h"
#include "transport_layer/node_conn_direct.h"
#include "transport_layer/stcp_link.h"
#include "../lib/u_async.h"
#include "../lib/debug_config.h"
@ -33,6 +34,19 @@ int main(void) {
"[server: udp]\naddr=127.0.0.1:0\ntype=public\n"
"[server: tcp]\naddr=127.0.0.1:0\ntype=public\ntransport=tcp\n");
assert(inst && utun_instance_init(inst) >= 0);
for (struct ETCP_SOCKET* sock = inst->etcp_sockets; sock; sock = sock->next) {
uint16_t port;
if (sock->is_tcp) {
struct stcp_server* listener = stcp_server_list_find_by_sock(inst, sock); assert(listener);
port = stcp_link_server_get_port(listener);
} else {
struct sockaddr_storage bound; socklen_t size = sizeof(bound);
assert(getsockname(sock->fd, (struct sockaddr*)&bound, &size) == 0);
port = ss_get_port(&bound);
}
assert(port && ss_get_port(&sock->local_addr) == port && ss_get_port(&sock->interface_addr) == port);
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "ephemeral %s socket=%s actual_port=%u verified", sock->is_tcp ? "TCP" : "UDP", sock->name, port);
}
struct CFG_SERVER *udp = NULL, *tcp = NULL;
for (struct CFG_SERVER* s = inst->config->servers; s; s = s->next) {
if (!strcmp(s->name, "udp")) udp = s;

Loading…
Cancel
Save