# TUN Interface (tun_if) ## 1. Назначение Модуль создания и управления виртуальным сетевым интерфейсом (TUN) — точкой входа/выхода всего VPN-трафика. Через TUN-интерфейс ОС отправляет IP-пакеты в uTun и получает обработанные пакеты обратно. Реализует кроссплатформенную абстракцию над платформенными механизмами: Linux (`/dev/net/tun`), FreeBSD (`/dev/tun` + TUNSIFHEAD), Windows (WinTun API). Модель данных — две очереди: - **output_queue** — пакеты, прочитанные из TUN (ОС → uTun → routing) - **input_queue** — пакеты для записи в TUN (routing → uTun → ОС), с callback `tun_input_queue_callback` ## 2. Как пользоваться ```c // Инициализация из конфига (основной интерфейс VPN) tun = tun_init(ua, config); // или для NAT TUN с явными параметрами nat_tun = tun_init_nat(ua, "tun_nat", "10.0.1.1", 1500, 0); // Чтение: очередь output_queue наполняется автоматически (через uasync/epoll), // обработчик читает через queue_set_callback struct ll_queue* out = tun_get_output_queue(tun); // Запись: пакет кладётся в input_queue, callback пишет в TUN tun_write(tun, buf, len); // прямой вызов, не через очередь // Завершение tun_close(tun); ``` **Root-права:** требуются на всех платформах для создания TUN-устройств и настройки IP. **Тестовый режим** (`test_mode=1`): вместо реального TUN используется `socketpair(AF_UNIX, SOCK_DGRAM)`. Вторая сторона пары доступна через `tun_get_test_fd()`. **Платформенные различия:** - **Linux:** `open("/dev/net/tun")` + `ioctl(TUNSETIFF)` с `IFF_TUN | IFF_NO_PI`, неблокирующий режим через `fcntl(O_NONBLOCK)` - **FreeBSD:** `open("/dev/tun")` (cloning device), имя присваивается ядром, `ioctl(TUNSIFHEAD)` для multi-af (4-байтный заголовок AF), `ioctl(TUNSIFMODE)` для POINTOPOINT - **Windows:** WinTun API через `wintun.dll`, кольцевой буфер 4 MiB, отдельный read-поток (`tun_read_thread_proc`), пакеты передаются в main thread через `uasync_post → tun_packet_handler` ## 3. API ### Структуры - **`struct tun_if`** — хендл интерфейса: `fd` (Linux/BSD файловый дескриптор), `platform_handle`/`adapter_handle` (Windows WinTun), `ifname`, `ifindex`, очереди `input_queue`/`output_queue`, пул `pool` для ll_entry, счётчики статистики (`bytes_read/written`, `packets_read/written`, `read_errors`, `write_errors`) - **`struct tun_packet_data`** — обёртка для передачи пакета из read-потока (Windows) в main thread: указатели на `tun_if` и `ll_entry` ### Функции - **`tun_init(ua, config)`** / **`tun_init_nat(ua, ifname, ip, mtu, test_mode)`** — создают TUN-интерфейс: платформенный init, настройка IP/MTU, поднятие интерфейса, создание очередей, регистрация в uasync (Linux/BSD) или запуск read-потока (Windows). `tun_init_nat` — вариант для отдельного NAT TUN с явными параметрами вместо конфига - **`tun_close(tun)`** — остановка read-потока (Windows), удаление из uasync, слив и освобождение обеих очередей, уничтожение пула, платформенная очистка (`close(fd)` на Linux, `SIOCIFDESTROY` на FreeBSD, `WintunEndSession`+`WintunCloseAdapter` на Windows) - **`tun_write(tun, buf, len)`** — прямая запись в TUN (в тестовом режиме — в output_queue, иначе `tun_platform_write`). Пакет имеет префиксный байт, отбрасываемый при записи - **`tun_inject_packet(tun, buf, len)`** — инжекция пакета в output_queue (для тестов и Windows-нотификаций) - **`tun_read_packet(tun, buf, len)`** — тестовый helper: чтение одного пакета из input_queue - **`tun_packet_handler(arg)`** — callback для main thread (Windows): распаковывает `tun_packet_data`, кладёт `ll_entry` в output_queue - **Платформенные функции** (`tun_linux.c` / `tun_freebsd.c` / `tun_windows.c`): - `tun_platform_init()` — создание устройства, настройка IP/MTU, поднятие, получение `ifindex`, `O_NONBLOCK` - `tun_platform_cleanup()` — закрытие fd/хендлов - `tun_platform_read()` — чтение из TUN (FreeBSD: `readv` с отделением 4-байтного AF-заголовка) - `tun_platform_write()` — запись в TUN (FreeBSD: `writev` с AF-заголовком; Windows: `WintunAllocateSendPacket` + `WintunSendPacket`) - `tun_platform_get_poll_fd()` — fd для uasync (Windows возвращает -1, используется read-поток)