Files
utun2/src/config_parser_doc.md
T

9.2 KiB

Config Parser (config_parser.c/h)

1. Назначение

INI-style парсер конфигурационного файла uTun. Читает текстовый конфиг, разбирает его на структуры и возвращает заполненный struct utun_config — корневое представление всех настроек.

Поддерживает два режима входа:

  • parse_config(filename) — чтение из файла
  • parse_config_from_buf(buf, len, filename) — чтение из буфера (для chatgui/in-memory использования)

Формат: стандартные .ini-секции [section], строки key=value, комментарии #. Именованные секции через двоеточие: [server:main], [client:peer1], [network:mynet].

Файл и буфер проходят один разбор. Общие функции в config_ini.h удаляют пробелы вокруг имён секций, ключей и значений. Имена секций нечувствительны к регистру, имена ключей чувствительны. Встроенный NUL и физические строки длиннее 1022 байтов до LF запрещены; CR учитывается в этом пределе. Ошибки разбора опций [nat] отклоняют весь конфиг. Формат статического проброса: forward=proto:node_id_hex:IPv4:internal_port:external_port; узел назначения обязателен, оба порта — десятичные 1..65535. Динамический диапазон дополнительно проверяется при запуске NAT.

2. Как пользоваться

struct utun_config *cfg = parse_config("/etc/utun/config.ini");
if (!cfg) { /* ошибка — смотри логи DEBUG_CATEGORY_CONFIG */ }

// Работа с конфигом...
const char *tun_name = cfg->global.tun_ifname;
struct CFG_SERVER *srv = cfg->servers;
while (srv) {
    ip_str_t addr = sockaddr_storage_to_str(&srv->ip);
    srv = srv->next;
}

// Освобождение
free_config(cfg);

Нюансы:

  • parse_config возвращает NULL при ошибках открытия, чтения, закрытия, памяти и обязательных проверок формата. Некоторые ошибки отдельных опций только логируются и пропускаются; ненулевой результат не гарантирует корректность всех полей.
  • Обработка длинных значений зависит от поля: часть строк обрезается, assign_string отклоняет значение без изменения поля.
  • Ключи клиента link требуют, чтобы сервер ([server:имя]) был объявлен выше по файлу. Иначе ошибка.
  • tun_enabled по умолчанию 0. При явном включении и отсутствии имени интерфейса используется tun0.
  • IPv6-адреса в [server:...] addr поддерживают префиксы temporary_ipv6: и permanent_ipv6:.
  • HEX декодируется после проверки каждого символа. Ошибочный список REALITY short_ids отклоняется целиком и оставляет short_id_count=0; ошибочный последний REALITY-ключ сбрасывает соответствующий has_*_key.

3. API

Структуры

Структура Назначение
struct utun_config Корневой контейнер: global + связные списки servers, clients, route_subnets, my_subnets, networks
struct global_config Глобальные настройки (ключи, TUN, таймауты, firewall, NAT, SOCKS/HTTP-прокси, NTP, debug, allowed_keys...)
struct CFG_SERVER Локальный серверный линк: addr (ip:port), netif_index, so_mark, fib, type, transport (udp/tcp), mtu, only_local
struct CFG_CLIENT Удалённый пир: peer_public_key_hex, keepalive, связный список links
struct CFG_CLIENT_LINK Привязка клиента к локальному серверу: local_srv (указатель на CFG_SERVER), remote_addr
struct CFG_ROUTE_ENTRY Маршрут: IP + netmask
struct CFG_NETWORK Именованная сеть: id (56-bit), pubkey_hex, signing_key_hex
struct CFG_FIREWALL_RULE Правило фаервола: ip (host order), port, bypass
struct CFG_ALLOWED_KEY Разрешённый публичный ключ (32 байта binary) для контрольного сервера
struct CFG_CONTROL_ALLOW Разрешённая подсеть для control-сервера
struct CFG_NTP_SERVER NTP-сервер: имя хоста

Секции конфига

Секция Обработчик Ключевые поля
[global] parse_global() my_node_name, my_private_key, my_public_key, my_node_id, tun_ifname, tun_ip, mtu, keepalive_*, bbr_max_cwnd, debug_level, log_file, db_path, db_sync_*, enable_timestamp, enable_colors, tun_test_mode
[server:name] parse_server() addr, so_mark, fib, netif, type (public/nat/private/local), transport (udp/tcp), mtu, only_local
[client:name] parse_client() link (формат: server_name:ip:port), peer_public_key, keepalive
[network:name] parse_network() id (hex), pubkey, signing_key
[routing] inline route_subnet, my_subnet
[firewall] parse_firewall_rule() allow=IPv4[:port] или allow=all; порт 0–65535, 0 разрешает весь IP; CIDR запрещён
[control] parse_control() ip, port, allow (подсеть)
[allowed_keys] inline allow_all, key (64 hex)
[nat] parse_nat() tun_ifname, tun_ip, nat_via, port_start, port_end, forward (proto:node_id_hex:IPv4:in_port:ext_port)
[tcp_proxy_client] parse_tcp_proxy_client() enabled, tun_name, tun_ip, mtu, via_node, socks_*, http_proxy_*, forward (port -> ip:port)
[tcp_proxy_server] inline tcp_recv_buf
[ntp] inline enabled, server, interval
[stun] parse_stun() enabled, повторяющийся server=host[:port]; минимум два сервера при включении
[gui] игнорируется (зарезервировано)

Функции

Функция Назначение
parse_config(filename) Читает и закрывает файл, затем вызывает parse_config_from_buf. Возвращает utun_config* или NULL.
parse_config_from_buf(buf, len, filename) Парсит конфиг из буфера (in-memory). filename используется только для сообщений об ошибках.
free_config(config) Рекурсивно освобождает все связные списки и сам utun_config. Безопасен для NULL.
print_config(config) Выводит всё содержимое конфига через DEBUG_INFO(DEBUG_CATEGORY_CONFIG, ...). Полезно для проверки после парсинга.
update_config_keys(filename, priv_key, pub_key) Устарела. Дописывает ключи в конец файла. Используй config_ensure_keys_and_node_id() из config_updater.h.

Внутренние хелперы (static)

Функция Назначение
config_ini_trim(str) Общий INI-код: удаляет пробелы слева и справа на месте, сохраняя адрес строки
config_ini_key_value(line, ...) Общий INI-код: разбирает key=value, удаляет комментарий после # и пробелы
parse_ip_with_netmask(str, ip, netmask) Парсит 1.2.3.4/24 или ::1/64 в struct IP
parse_sockaddr(addr, port, sockaddr) Преобразует адрес+порт в sockaddr_storage через getaddrinfo
parse_address_and_port(str, sockaddr) Разбирает строку ip:port → вызов parse_sockaddr
get_netif_index(ifname) Получает индекс сетевого интерфейса через if_nametoindex
parse_firewall_rule(rule_str, global) Строго разбирает allow=IPv4[:port] или all; ошибка/неизвестная опция firewall отменяет весь новый конфиг
parse_control_allow(rule_str, global) Парсит allow=IP[/CIDR]
config_ini_hex(hex_str, binary, len) Общий INI-код: проверяет весь HEX до декодирования