Browse Source

chatgui: IPv4+IPv6 dual-stack listen by default

- Default config creates [server:lan] (0.0.0.0) + [server:lan6] ([::])
- Network settings save also writes [server:lan6] section
- Sets IPV6_V6ONLY=1 on IPv6 sockets to avoid conflict with IPv4
- interface_addr for [::] bind prefers permanent IPv6 over temporary
topo_upd
evgeny 2 months ago
parent
commit
af3e2ee869
  1. 22
      src/transport_layer/etcp_connections.c
  2. 5
      tools/chatgui/src/networksettingspage.cpp
  3. 4
      tools/chatgui/transport/node_config.cpp

22
src/transport_layer/etcp_connections.c

@ -557,6 +557,13 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set non-blocking mode"); DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set non-blocking mode");
} }
if (family == AF_INET6) {
int v6only = 1;
if (setsockopt(e_sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) < 0) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set IPV6_V6ONLY: %s", socket_strerror(socket_get_error()));
}
}
// Set socket mark if specified (Linux only) // Set socket mark if specified (Linux only)
if (so_mark > 0) { if (so_mark > 0) {
socket_set_mark(e_sock->fd, so_mark); socket_set_mark(e_sock->fd, so_mark);
@ -637,7 +644,19 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
} else if (ip->ss_family == AF_INET6) { } else if (ip->ss_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip; struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip;
if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0) { if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0) {
// :: — определяем через default route // :: — приоритет: permanent > temporary > get_outgoing_local_ip
uint16_t v6if = (netif_index > 0) ? netif_index : get_default_route_netif_index(AF_INET6);
if (v6if > 0) {
uint8_t v6addr[16];
int got = get_interface_ipv6_by_index(v6if, 0, v6addr);
if (got != 0) got = get_interface_ipv6_by_index(v6if, 1, v6addr);
if (got == 0) {
struct sockaddr_in6* if6 = (struct sockaddr_in6*)&e_sock->interface_addr;
if6->sin6_family = AF_INET6;
memcpy(&if6->sin6_addr, v6addr, 16);
}
}
if (e_sock->interface_addr.ss_family == 0) {
struct sockaddr_storage remote; struct sockaddr_storage remote;
memset(&remote, 0, sizeof(remote)); memset(&remote, 0, sizeof(remote));
struct sockaddr_in6* rem_sin6 = (struct sockaddr_in6*)&remote; struct sockaddr_in6* rem_sin6 = (struct sockaddr_in6*)&remote;
@ -650,6 +669,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
} }
} }
} }
}
if (e_sock->interface_addr.ss_family == 0) { if (e_sock->interface_addr.ss_family == 0) {
// Не удалось определить автоматически — используем адрес из конфига // Не удалось определить автоматически — используем адрес из конфига
if (ip) memcpy(&e_sock->interface_addr, ip, sizeof(struct sockaddr_storage)); if (ip) memcpy(&e_sock->interface_addr, ip, sizeof(struct sockaddr_storage));

5
tools/chatgui/src/networksettingspage.cpp

@ -140,6 +140,11 @@ void NetworkSettingsPage::saveToConfig(const QString& configPath) const {
config_update_option(configPath, SECTION, "transport", config_update_option(configPath, SECTION, "transport",
m_protoCombo->currentText().toLower(), m_protoCombo->currentText().toLower(),
CONFIG_UPDATE_REPLACE); CONFIG_UPDATE_REPLACE);
// IPv6 dual-stack: always add [server:lan6] with same port
config_update_option(configPath, "server:lan6", "addr",
QString("[::]:%1").arg(m_portSpin->value()),
CONFIG_UPDATE_REPLACE);
} }
void NetworkSettingsPage::onInterfaceChanged(int index) { void NetworkSettingsPage::onInterfaceChanged(int index) {

4
tools/chatgui/transport/node_config.cpp

@ -177,8 +177,10 @@ bool NodeConfig::create(const QString& nodeName, quint16 listenPort) {
m_controlAddr = "127.0.0.1:9999"; m_controlAddr = "127.0.0.1:9999";
m_servers.clear(); m_servers.clear();
m_clients.clear(); m_clients.clear();
if (listenPort > 0) if (listenPort > 0) {
m_servers.append({"lan", QString("0.0.0.0:%1").arg(listenPort)}); m_servers.append({"lan", QString("0.0.0.0:%1").arg(listenPort)});
m_servers.append({"lan6", QString("[::]:%1").arg(listenPort)});
}
if (m_dbPath.isEmpty()) if (m_dbPath.isEmpty())
m_dbPath = "chat_data"; m_dbPath = "chat_data";
return save(); return save();

Loading…
Cancel
Save