279 lines
12 KiB
C
279 lines
12 KiB
C
/* INI-конфигурация ядра: слушающие сокеты, исходящие пиры, сети/подсети и настройки сервисов.
|
||
* parse_config читает файл, parse_config_from_buf — текст; filename задаёт источник в диагностике.
|
||
* Успех возвращает выделенную utun_config со списками; освобождение — только free_config.
|
||
* Парсер заполняет модель, запуск сетевых ресурсов выполняет utun_instance. */
|
||
#ifndef CONFIG_PARSER_H
|
||
#define CONFIG_PARSER_H
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
#include "../lib/platform_compat.h"
|
||
#include "../lib/debug_config.h"
|
||
#include "secure_channel.h"
|
||
#include "transport_layer/reality.h"
|
||
#include "chat/chat_setting.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define MAX_CONN_NAME_LEN 64
|
||
#define MAX_KEY_LEN 256
|
||
#define MAX_ADDR_LEN 64
|
||
|
||
struct IP {
|
||
sa_family_t family;
|
||
union {
|
||
struct in_addr v4;
|
||
struct in6_addr v6;
|
||
} addr;
|
||
};
|
||
|
||
#define CFG_SERVER_TYPE_UNKNOWN 0
|
||
#define CFG_SERVER_TYPE_PUBLIC 1
|
||
#define CFG_SERVER_TYPE_NAT 2
|
||
#define CFG_SERVER_TYPE_PRIVATE 3
|
||
#define CFG_SERVER_TYPE_LOCAL 4
|
||
|
||
/* Режимы auto_sockets: OFF — ручные [server]; SYSTEM — авто-сокеты из системных
|
||
* интерфейсов; ANDROID — авто-сокеты из [server] секций конфига (генерирует Kotlin). */
|
||
#define CFG_AUTO_SOCKETS_OFF 0
|
||
#define CFG_AUTO_SOCKETS_SYSTEM 1
|
||
#define CFG_AUTO_SOCKETS_ANDROID 2
|
||
|
||
#define CFG_IPV6_MODE_NONE 0 // normal explicit address
|
||
#define CFG_IPV6_MODE_TEMPORARY 1 // temporary IPv6 from interface
|
||
#define CFG_IPV6_MODE_PERMANENT 2 // permanent IPv6 from interface
|
||
|
||
struct CFG_SERVER {
|
||
struct CFG_SERVER* next;
|
||
char name[MAX_CONN_NAME_LEN];
|
||
struct sockaddr_storage ip; // ip:port
|
||
uint32_t netif_index;// if_nameindex, 0 - no interface specified
|
||
int so_mark;
|
||
int fib; // FreeBSD FIB (routing table), -1 = don't set
|
||
uint8_t type; // public/nat/private
|
||
uint8_t transport; // 0=udp (default), 1=tcp
|
||
uint8_t reality_enabled; // 1 = TCP-порт с REALITY-камуфляжем (только transport=1)
|
||
uint8_t socks_enabled; // 1 = UDP-сокет туннелировать через SOCKS5 (только transport=0)
|
||
uint8_t ipv6_mode; // CFG_IPV6_MODE_*
|
||
int mtu;
|
||
uint8_t only_local; // 1 = only local connections, no forwarding
|
||
};
|
||
|
||
struct CFG_CLIENT_LINK {
|
||
struct CFG_CLIENT_LINK *next; // Next link in linked list
|
||
struct CFG_SERVER* local_srv;
|
||
char server_name[MAX_CONN_NAME_LEN]; // Name of local server for this link
|
||
struct sockaddr_storage remote_addr; // ip:port
|
||
};
|
||
|
||
struct CFG_CLIENT {
|
||
char name[MAX_CONN_NAME_LEN];
|
||
char peer_public_key_hex[MAX_KEY_LEN];
|
||
int keepalive;
|
||
struct CFG_CLIENT_LINK *links; // Linked list of links
|
||
struct CFG_CLIENT *next; // Next client in linked list
|
||
uint8_t reality_enabled; // 1 = TCP-линк с REALITY-камуфляжем
|
||
struct reality_client_config reality; // short_id, server_static_pubkey, version, server_name, fingerprint
|
||
};
|
||
|
||
struct CFG_NETWORK {
|
||
struct CFG_NETWORK* next;
|
||
char name[64];
|
||
uint64_t id; // 56-bit network ID
|
||
char pubkey_hex[SC_PUBKEY_SIZE * 2 + 1]; // 64 hex chars
|
||
char signing_key_hex[SC_PRIVKEY_SIZE * 2 + 1]; // 64 hex chars
|
||
};
|
||
|
||
struct CFG_ROUTE_ENTRY {
|
||
struct CFG_ROUTE_ENTRY* next;
|
||
struct IP ip;
|
||
uint8_t netmask;
|
||
};
|
||
|
||
struct CFG_FIREWALL_RULE {
|
||
uint32_t ip; // IPv4 in host byte order for sorting
|
||
uint16_t port; // 0 means any port
|
||
uint8_t bypass; // 1 for allow=all (bypass all checks)
|
||
};
|
||
|
||
struct CFG_CONTROL_ALLOW {
|
||
uint32_t network; // IPv4 network in host byte order
|
||
uint32_t netmask; // netmask in host byte order (e.g. 0xffffff00 for /24)
|
||
};
|
||
|
||
struct CFG_ALLOWED_KEY {
|
||
uint8_t key_bin[SC_PUBKEY_SIZE]; // public key in binary (32 bytes, X25519)
|
||
struct CFG_ALLOWED_KEY *next;
|
||
};
|
||
|
||
struct CFG_NTP_SERVER {
|
||
char name[256];
|
||
struct CFG_NTP_SERVER *next;
|
||
};
|
||
|
||
/* STUN-серверы обходятся в порядке конфигурации; DNS выполняет модуль stun_nat. */
|
||
struct CFG_STUN_SERVER {
|
||
struct CFG_STUN_SERVER* next;
|
||
char host[256];
|
||
uint16_t port;
|
||
};
|
||
|
||
#define MAX_TCP_PROXY_CLIENT_MAPPINGS 32
|
||
struct tcp_proxy_client_mapping_config {
|
||
uint16_t local_port;
|
||
char remote_ip[64];
|
||
uint16_t remote_port;
|
||
};
|
||
|
||
struct global_config {
|
||
char name[MAX_CONN_NAME_LEN]; // Instance name
|
||
char my_private_key_hex[MAX_KEY_LEN];
|
||
char my_public_key_hex[MAX_KEY_LEN];
|
||
uint64_t my_node_id;
|
||
uint8_t client_type; // 0=server, 1=desktop, 2=mobile
|
||
int tun_enabled; // 1 = create TUN (default), 0 = skip TUN (run without root)
|
||
char tun_ifname[16]; // TUN interface name (e.g., "tun12")
|
||
struct IP tun_ip;
|
||
int mtu;
|
||
struct sockaddr_storage control_sock;
|
||
char control_ip[MAX_ADDR_LEN]; // Control server IP address
|
||
// Debug and logging configuration
|
||
char log_file[256]; // Path to log file (empty = stdout)
|
||
char db_path[256]; // Path to SQLite database (empty = disabled)
|
||
int db_sync_enabled; // 1 = enable distributed DB sync (default: 0)
|
||
int chatserver_enabled; // 1 = chat server mode (set by [chatserver] section presence)
|
||
uint32_t db_sync_ttl; // TTL for unsent records in seconds (default: 86400)
|
||
// UDP log target
|
||
char log_udp_ip[64];
|
||
int log_udp_port;
|
||
char debug_level[16]; // debug level: error, warn, info, debug, trace
|
||
int enable_timestamp; // enable timestamps in logs
|
||
int enable_function_names; // enable function names in logs
|
||
int enable_file_lines; // enable file:line in logs
|
||
int enable_colors; // enable ANSI colors in logs
|
||
|
||
// Per-category debug levels (loaded from [debug] section)
|
||
struct {
|
||
char category[DEBUG_CATEGORY_COUNT][16]; // category name
|
||
char level[DEBUG_CATEGORY_COUNT][16]; // level string
|
||
int count;
|
||
} debug_levels;
|
||
|
||
int tun_test_mode; // test mode: 1 = don't open real TUN, queues only
|
||
int keepalive_timeout; // keepalive timeout in ms (default: 2000)
|
||
int keepalive_interval; // keepalive interval in ms (default: 200)
|
||
int keepalive_adaptive; // 1 = adaptive period (default), 0 = fixed interval
|
||
int bbr_max_cwnd; // BBR cwnd cap in bytes (default: 100000)
|
||
|
||
// Firewall configuration
|
||
struct CFG_FIREWALL_RULE *firewall_rules;
|
||
int firewall_rule_count;
|
||
int firewall_bypass_all;
|
||
|
||
// Control server configuration ([control] section)
|
||
struct CFG_CONTROL_ALLOW *control_allows;
|
||
int control_allow_count;
|
||
|
||
// Allowed keys configuration ([allowed_keys] section)
|
||
struct CFG_ALLOWED_KEY *allowed_keys;
|
||
int allowed_keys_count;
|
||
int allowed_keys_allow_all;
|
||
|
||
// NAT configuration ([nat] section)
|
||
int nat_enabled;
|
||
char nat_tun_ifname[16];
|
||
struct IP nat_tun_ip;
|
||
uint64_t nat_via_node_id; // 0 = this node is provider; !=0 = client, use this provider
|
||
uint16_t nat_port_start;
|
||
uint16_t nat_port_end;
|
||
#define MAX_NAT_FORWARDS 64
|
||
struct {
|
||
uint8_t proto;
|
||
uint32_t internal_ip_host;
|
||
uint16_t internal_port_net;
|
||
uint16_t external_port;
|
||
} nat_forwards[MAX_NAT_FORWARDS];
|
||
int nat_forward_count;
|
||
|
||
// TCP proxy client configuration ([tcp_proxy_client] section)
|
||
int tcp_proxy_client_enabled;
|
||
char tcp_proxy_client_tun_name[16];
|
||
char tcp_proxy_client_tun_ip[64];
|
||
int tcp_proxy_client_mtu;
|
||
uint64_t tcp_proxy_client_via_node_id; // через этот узел проксируются все forward-правила
|
||
struct tcp_proxy_client_mapping_config tcp_proxy_client_mappings[MAX_TCP_PROXY_CLIENT_MAPPINGS];
|
||
int tcp_proxy_client_mapping_count;
|
||
int tcp_proxy_client_socks_enabled;
|
||
char tcp_proxy_client_socks_addr[64]; // e.g. "127.0.0.1:1080"
|
||
int tcp_proxy_client_http_proxy_enabled;
|
||
char tcp_proxy_client_http_proxy_addr[64]; // e.g. "127.0.0.1:8080"
|
||
|
||
// TCP proxy server (exit node) configuration ([tcp_proxy_server] section)
|
||
int tcp_proxy_server_enabled;
|
||
int auto_sockets; // CFG_AUTO_SOCKETS_*: OFF/SYSTEM/ANDROID (см. константы ниже)
|
||
int auto_socket_skip_no_default_route; // 1 = в авто-режиме не создавать сокеты на интерфейсах без default-маршрута
|
||
int tcp_recv_buf; // SO_RCVBUF для TCP сокетов (0=default ОС)
|
||
int tcp_proxy_server_fib; // FreeBSD SO_SETFIB, 0=не менять
|
||
int tcp_proxy_server_so_mark; // Linux SO_MARK, 0=не менять
|
||
uint32_t tcp_proxy_server_netif_index; // Linux SO_BINDTODEVICE, 0=нет
|
||
char tcp_proxy_server_bind_ip[64]; // IP для bind() перед connect()
|
||
int tcp_proxy_server_connect_timeout_ms; // таймаут connect(), мс (0 = без таймаута)
|
||
|
||
// NTP configuration ([ntp] section)
|
||
int ntp_enabled;
|
||
struct CFG_NTP_SERVER *ntp_servers; // linked list, unlimited
|
||
int ntp_server_count;
|
||
int ntp_resync_interval; // seconds, default 3600
|
||
|
||
int stun_enabled; // [stun] enabled=yes; по умолчанию выключено
|
||
struct CFG_STUN_SERVER* stun_servers;
|
||
int stun_server_count;
|
||
|
||
// Chatserver configuration ([chatserver] section)
|
||
char chatserver_join_password[128]; // пароль для входа в группу
|
||
char chatserver_allowed_groups[1024]; // "all" или hex-ID через запятую
|
||
uint64_t chatserver_storage_total_size; // bytes, общий лимит хранилища (0 = безлимит)
|
||
uint64_t chatserver_storage_unit_size; // bytes, лимит одного файла (0 = отключено)
|
||
char headless_control_bind[64]; // ip:port для headless chat CLI (пусто = отключено)
|
||
char call_audio_bind[64]; // ip:port для headless аудио-сокета звонков (пусто = отключено)
|
||
char radio_audio_bind[64]; // ip:port для headless аудио-сокета рации (пусто = отключено)
|
||
struct chat_setting_state chat_settings; // chat-настройки из [chatserver] (per-instance)
|
||
|
||
// Reality-камуфляж ([reality] section)
|
||
struct reality_config reality;
|
||
|
||
// SOCKS5-прокси для исходящих ETCP-линков ([socks] section)
|
||
int socks_enabled; // 1 = TCP/STCP-линки подключаются через SOCKS5
|
||
char socks_host[64]; // host прокси (ip или домен)
|
||
uint16_t socks_port; // порт прокси
|
||
char socks_username[64]; // пусто = no-auth
|
||
char socks_password[64];
|
||
};
|
||
|
||
struct utun_config {
|
||
struct global_config global;
|
||
struct CFG_SERVER* servers;
|
||
struct CFG_CLIENT* clients;
|
||
struct CFG_ROUTE_ENTRY* route_subnets;
|
||
struct CFG_ROUTE_ENTRY* my_subnets;
|
||
struct CFG_NETWORK* networks;
|
||
};
|
||
|
||
struct utun_config* parse_config(const char *filename);
|
||
struct utun_config* parse_config_from_buf(const char *buf, size_t len, const char *filename);
|
||
void free_config(struct utun_config *config);
|
||
void print_config(const struct utun_config *config);
|
||
void print_chatserver_invite_link(const struct utun_config *config, const struct CFG_SERVER *servers);
|
||
int update_config_keys(const char *filename, const char *priv_key, const char *pub_key);
|
||
|
||
/* Узел (по pubkey, 32 байта) присутствует в списке [client] конфига? 1=да, 0=нет. */
|
||
int config_peer_in_clients(const struct utun_config* config, const uint8_t* pubkey);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif
|