#ifndef ROUTE_BGP_H #define ROUTE_BGP_H #include #include #include "../lib/ll_queue.h" #include "route_lib.h" #include "route_node.h" #include "secure_channel.h" // ETCP ID для маршрутных пакетов #define ETCP_ID_ROUTE_ENTRY 0x01 // Sub-команды #define ROUTE_SUBCMD_NODEINFO 0x04 // полная информация об узле + маршруты #define ROUTE_SUBCMD_REQUEST_TABLE 0x05 // запрос полной таблицы #define ROUTE_SUBCMD_WITHDRAW 0x06 // узел стал недоступен #define ROUTE_SUBCMD_NAT_INFO 0x09 // информация о типе NAT клиента #define ROUTE_SUBCMD_NAT_CHECK_REQ 0x0A // запрос от клиента на проверку NAT для сокета #define MAX_HOPS 16 #define BGP_NODES_HASH_SIZE 256 /** * @brief Пакет с информацией об узле (NODEINFO) */ struct BGP_NODEINFO_PACKET { uint8_t cmd; // ETCP_ID_ROUTE_ENTRY uint8_t subcmd; // ROUTE_SUBCMD_NODEINFO struct NODEINFO node; } __attribute__((packed)); /** * @brief Пакет WITHDRAW (фиксированный) */ struct BGP_WITHDRAW_PACKET { uint8_t cmd; uint8_t subcmd; uint64_t node_id; // удаляемый узел (который стал недоступен) uint64_t wd_source; // узел который инициировал withdraw (при удалении он должен быть в hoplist или = current node_id) } __attribute__((packed)); /** * @brief Пакет запроса полной таблицы */ struct BGP_ROUTE_REQUEST { uint8_t cmd; uint8_t subcmd; } __attribute__((packed)); struct ROUTE_BGP_CONN_ITEM { struct ll_entry ll; struct ETCP_CONN* conn; }; /** * @brief Пакет NAT_INFO (фиксированный) */ struct BGP_NAT_INFO { uint8_t cmd; uint8_t subcmd; uint8_t socket_id; // MY socket id (link->conn->sock_id) uint8_t nat_ip[4]; // network byte order uint16_t nat_port; // network byte order uint8_t nat_type; // NAT_TYPE_* } __attribute__((packed)); /** * @brief Пакет запроса на проверку NAT от клиента к серверу */ struct BGP_NAT_CHECK_REQ { uint8_t cmd; uint8_t subcmd; // ROUTE_SUBCMD_NAT_CHECK_REQ uint8_t socket_id; // ID сокета клиента, который надо проверить } __attribute__((packed)); struct route_ping_pending; struct ROUTE_BGP { struct UTUN_INSTANCE* instance; struct ll_queue* senders_list; struct ll_queue* nodes; struct NODEINFO_Q* local_node; struct route_ping_pending* ping_pending; uint64_t next_ping_req_id; uint8_t allow_nat_check_local; // 1 = разрешить NAT check для локальных подсетей (для тестов) }; /** * @brief Инициализирует модуль BGP маршрутизации. * * Создает очереди, local_node из подсетей конфига, привязывает к ETCP_ID_ROUTE_ENTRY, * устанавливает коллбеки new_conn для on_up/on_down. * * @param instance экземпляр utun с node_id и конфигом * @return ROUTE_BGP или NULL при ошибке */ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance); /** * @brief Освобождает ресурсы BGP (очереди, local_node, снимает привязку ETCP). * * @param instance экземпляр utun */ void route_bgp_destroy(struct UTUN_INSTANCE* instance); /** * @brief Добавляет conn в senders_list (если нет), отправляет запрос таблицы (nodeinfo). * * Вызывается при ETCP on_up. */ void route_bgp_new_conn(struct ETCP_CONN* conn); /** * @brief Удаляет conn из senders_list, очищает paths во всех nodes, отправляет withdraw если node unreachable. * * Вызывается при ETCP on_down. */ void route_bgp_remove_conn(struct ETCP_CONN* conn); /** * @brief Обрабатывает пакет NODEINFO. * * Проверка версии, обновление или создание NODEINFO_Q, добавление пути, * вставка в роутинг, broadcast если не max hops. * * @return 0 при успехе */ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len); /** * @brief Обрабатывает WITHDRAW. * * Удаляет node из роутинга и nodes, broadcast withdraw. * * @return 0 при успехе */ int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len); /** * @brief Отправляет NODEINFO пакет одному conn (всегда local_node). */ void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn); /** * @brief Отправляет WITHDRAW для node_id (вызывает broadcast_withdraw). */ void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id); /** * @brief Поиск NODEINFO_Q по node_id через hash в nodes queue. * * @return node или NULL */ struct NODEINFO_Q* route_bgp_get_node(struct ROUTE_BGP* bgp, uint64_t node_id); /** * @brief Добавляет путь (conn) в paths узла. * * @return 0 при успехе */ int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count); /** * @brief Удаляет conn из paths узла. * * @return 1 если путей не осталось (unreachable) */ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn); /** * @brief Отправляет NAT_INFO клиенту с его типом NAT. * * @param conn соединение к клиенту * @param nat_ip IP клиента (network byte order) * @param nat_port порт клиента (network byte order) * @param nat_type NAT_TYPE_OPEN или NAT_TYPE_RESTRICTED */ void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type); /** * @brief Отправляет запрос на проверку NAT для указанного socket_id серверу. * * @param conn соединение к серверу * @param socket_id ID сокета для проверки */ void route_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id); /** * @brief Разрешить/запретить NAT check для локальных подсетей (127.0.0.1, 10.x.x.x и т.д.) * По умолчанию запрещено. Полезно для тестов. */ void route_bgp_set_nat_check_local(struct ROUTE_BGP* bgp, int allow); #endif // ROUTE_BGP_H