Refactor: TUN ioctl helpers, routing documentation; prepare for tun_if simplification
This commit is contained in:
1 parent
1bb59bad98
commit
2e48f9a111
14 files changed
+298
-184
No files matched your search
+9
-12
@@ -126,7 +126,7 @@ bool routing_table_insert(struct routing_table *table, const struct route_entry
|
||||
struct route_entry *new_entries = realloc(table->entries, new_capacity * sizeof(struct route_entry));
|
||||
if (!new_entries) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "routing_table_insert: failed to expand routing table to %zu entries", new_capacity);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
table->entries = new_entries;
|
||||
@@ -313,13 +313,13 @@ bool routing_get_all_routes(const struct routing_table *table, uint32_t network,
|
||||
void routing_table_print(const struct routing_table *table) {
|
||||
if (!table) return;
|
||||
|
||||
printf("\n=== Routing Table ===\n");
|
||||
printf("Total routes: %zu\n", table->count);
|
||||
printf("Dynamic subnets: %zu, Local subnets: %zu\n",
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "=== Routing Table ===");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Total routes: %zu", table->count);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Dynamic subnets: %zu, Local subnets: %zu",
|
||||
table->dynamic_subnet_count / 2, table->local_subnet_count / 2);
|
||||
|
||||
if (table->count > 0) {
|
||||
printf("\nRoutes:\n");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routes:");
|
||||
for (size_t i = 0; i < table->count; i++) {
|
||||
const struct route_entry *entry = &table->entries[i];
|
||||
char network_str[16], next_hop_str[16];
|
||||
@@ -327,27 +327,24 @@ void routing_table_print(const struct routing_table *table) {
|
||||
ip_to_string(entry->network, network_str);
|
||||
ip_to_string(entry->next_hop_ip, next_hop_str);
|
||||
|
||||
printf(" %zu: %s/%d -> %s [%s]\n",
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, " %zu: %s/%d -> %s [%s]",
|
||||
i + 1, network_str, entry->prefix_length, next_hop_str,
|
||||
route_type_to_string(entry->type));
|
||||
|
||||
printf(" Bandwidth: %uK, Loss: %.2f%%, Latency: %ums, Hops: %d\n",
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, " Bandwidth: %uK, Loss: %.2f%%, Latency: %ums, Hops: %d",
|
||||
entry->metrics.bandwidth_kbps,
|
||||
entry->metrics.packet_loss_rate / 100.0,
|
||||
entry->metrics.latency_ms,
|
||||
entry->metrics.hop_count);
|
||||
|
||||
|
||||
|
||||
printf(" Flags: %s%s%s%s\n",
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, " Flags: %s%s%s%s",
|
||||
(entry->flags & ROUTE_FLAG_ACTIVE) ? "ACTIVE " : "",
|
||||
(entry->flags & ROUTE_FLAG_VALIDATED) ? "VALIDATED " : "",
|
||||
(entry->flags & ROUTE_FLAG_ADVERTISED) ? "ADVERTISED " : "",
|
||||
(entry->flags & ROUTE_FLAG_LEARNED) ? "LEARNED" : "");
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\nNo routes configured.\n");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No routes configured.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+162
-48
@@ -7,81 +7,195 @@
|
||||
// Forward declarations
|
||||
struct ETCP_CONNECTIONS;
|
||||
|
||||
// Типы маршрутов
|
||||
/**
|
||||
* @brief Типы маршрутов
|
||||
*/
|
||||
typedef enum {
|
||||
ROUTE_TYPE_STATIC = 0,
|
||||
ROUTE_TYPE_DYNAMIC = 1,
|
||||
ROUTE_TYPE_LOCAL = 2,
|
||||
ROUTE_TYPE_LEARNED = 3
|
||||
ROUTE_TYPE_STATIC = 0, /**< Статический маршрут */
|
||||
ROUTE_TYPE_DYNAMIC = 1, /**< Динамический маршрут */
|
||||
ROUTE_TYPE_LOCAL = 2, /**< Локальный маршрут */
|
||||
ROUTE_TYPE_LEARNED = 3 /**< Изученный маршрут */
|
||||
} route_type_t;
|
||||
|
||||
// Флаги маршрута
|
||||
/**
|
||||
* @brief Флаги маршрута
|
||||
*/
|
||||
typedef enum {
|
||||
ROUTE_FLAG_ACTIVE = (1 << 0),
|
||||
ROUTE_FLAG_VALIDATED = (1 << 1),
|
||||
ROUTE_FLAG_ADVERTISED = (1 << 2),
|
||||
ROUTE_FLAG_LEARNED = (1 << 3)
|
||||
ROUTE_FLAG_ACTIVE = (1 << 0), /**< Маршрут активен */
|
||||
ROUTE_FLAG_VALIDATED = (1 << 1), /**< Маршрут валидирован */
|
||||
ROUTE_FLAG_ADVERTISED = (1 << 2), /**< Маршрут анонсирован */
|
||||
ROUTE_FLAG_LEARNED = (1 << 3) /**< Маршрут изучен */
|
||||
} route_flags_t;
|
||||
|
||||
// Расширенные метрики маршрута
|
||||
/**
|
||||
* @brief Расширенные метрики маршрута
|
||||
*
|
||||
* Структура содержит дополнительные метрики для оценки качества маршрута.
|
||||
*/
|
||||
struct route_metrics {
|
||||
uint32_t bandwidth_kbps;
|
||||
uint16_t packet_loss_rate;
|
||||
uint16_t latency_ms;
|
||||
uint8_t hop_count;
|
||||
uint64_t last_updated;
|
||||
uint32_t bandwidth_kbps; /**< Пропускная способность в Кбит/с */
|
||||
uint16_t packet_loss_rate; /**< Уровень потери пакетов (в промилле) */
|
||||
uint16_t latency_ms; /**< Задержка в миллисекундах */
|
||||
uint8_t hop_count; /**< Количество прыжков */
|
||||
uint64_t last_updated; /**< Время последнего обновления (в микросекундах) */
|
||||
};
|
||||
|
||||
// Расширенная запись маршрута
|
||||
/**
|
||||
* @brief Расширенная запись маршрута
|
||||
*
|
||||
* Структура представляет собой отдельную запись в таблице маршрутизации с детальной информацией о маршруте.
|
||||
*/
|
||||
struct route_entry {
|
||||
uint32_t network;
|
||||
uint8_t prefix_length;
|
||||
uint32_t next_hop_ip;
|
||||
struct ETCP_SOCKET* next_hop;
|
||||
route_type_t type;
|
||||
uint8_t flags;
|
||||
struct route_metrics metrics;
|
||||
uint64_t created_time;
|
||||
uint64_t last_update;
|
||||
uint64_t last_used;
|
||||
uint32_t network; /**< Сетевой адрес */
|
||||
uint8_t prefix_length; /**< Длина префикса подсети */
|
||||
uint32_t next_hop_ip; /**< IP-адрес следующего хопа */
|
||||
struct ETCP_SOCKET* next_hop; /**< Указатель на сокет следующего хопа */
|
||||
route_type_t type; /**< Тип маршрута */
|
||||
uint8_t flags; /**< Флаги маршрута */
|
||||
struct route_metrics metrics; /**< Метрики маршрута */
|
||||
uint64_t created_time; /**< Время создания (в микросекундах) */
|
||||
uint64_t last_update; /**< Время последнего обновления (в микросекундах) */
|
||||
uint64_t last_used; /**< Время последнего использования (в микросекундах) */
|
||||
};
|
||||
|
||||
// Таблица маршрутизации
|
||||
/**
|
||||
* @brief Таблица маршрутизации
|
||||
*
|
||||
* Структура представляет собой таблицу маршрутизации, содержащую записи маршрутов, подсети и статистику.
|
||||
*/
|
||||
struct routing_table {
|
||||
struct route_entry *entries;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
uint32_t *dynamic_subnets;
|
||||
size_t dynamic_subnet_count;
|
||||
uint32_t *local_subnets;
|
||||
size_t local_subnet_count;
|
||||
struct route_entry *entries; /**< Массив записей маршрутов */
|
||||
size_t count; /**< Текущее количество записей */
|
||||
size_t capacity; /**< Максимальная емкость таблицы */
|
||||
uint32_t *dynamic_subnets; /**< Динамические подсети (массив пар: сеть, префикс) */
|
||||
size_t dynamic_subnet_count; /**< Количество динамических подсетей */
|
||||
uint32_t *local_subnets; /**< Локальные подсети (массив пар: сеть, префикс) */
|
||||
size_t local_subnet_count; /**< Количество локальных подсетей */
|
||||
struct {
|
||||
uint64_t total_routes;
|
||||
uint64_t static_routes;
|
||||
uint64_t dynamic_routes;
|
||||
uint64_t local_routes;
|
||||
uint64_t learned_routes;
|
||||
uint64_t routes_added;
|
||||
uint64_t routes_deleted;
|
||||
uint64_t lookup_count;
|
||||
uint64_t hit_count;
|
||||
uint64_t routes_lookup_hits;
|
||||
uint64_t routes_lookup_misses;
|
||||
uint64_t validation_failures;
|
||||
} stats;
|
||||
uint64_t total_routes; /**< Общее количество маршрутов */
|
||||
uint64_t static_routes; /**< Количество статических маршрутов */
|
||||
uint64_t dynamic_routes; /**< Количество динамических маршрутов */
|
||||
uint64_t local_routes; /**< Количество локальных маршрутов */
|
||||
uint64_t learned_routes; /**< Количество изученных маршрутов */
|
||||
uint64_t routes_added; /**< Количество добавленных маршрутов */
|
||||
uint64_t routes_deleted; /**< Количество удаленных маршрутов */
|
||||
uint64_t lookup_count; /**< Количество запросов поиска */
|
||||
uint64_t hit_count; /**< Количество успешных поисков */
|
||||
uint64_t routes_lookup_hits; /**< Количество попаданий в поиск маршрутов */
|
||||
uint64_t routes_lookup_misses; /**< Количество промахов в поиск маршрутов */
|
||||
uint64_t validation_failures; /**< Количество неудачных валидаций */
|
||||
} stats; /**< Статистика таблицы маршрутизации */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Создает новую таблицу маршрутизации
|
||||
*
|
||||
* @return Указатель на созданную таблицу или NULL в случае ошибки
|
||||
*/
|
||||
struct routing_table *routing_table_create(void);
|
||||
|
||||
/**
|
||||
* @brief Уничтожает таблицу маршрутизации и освобождает ресурсы
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
*/
|
||||
void routing_table_destroy(struct routing_table *table);
|
||||
|
||||
/**
|
||||
* @brief Вставляет новую запись в таблицу маршрутизации
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param entry Указатель на вставляемую запись маршрута
|
||||
* @return true если вставка успешна, false иначе
|
||||
*/
|
||||
bool routing_table_insert(struct routing_table *table, const struct route_entry *entry);
|
||||
|
||||
/**
|
||||
* @brief Удаляет запись из таблицы маршрутизации
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param network Сетевой адрес
|
||||
* @param prefix_length Длина префикса
|
||||
* @param source_node_id Идентификатор источника узла
|
||||
* @return true если удаление успешно, false иначе
|
||||
*/
|
||||
bool routing_table_delete(struct routing_table *table, uint32_t network, uint8_t prefix_length, uint32_t source_node_id);
|
||||
|
||||
/**
|
||||
* @brief Выполняет поиск лучшего маршрута для заданного IP-адреса
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param dest_ip Целевой IP-адрес
|
||||
* @param best_route Указатель на структуру для хранения лучшего маршрута
|
||||
* @return true если маршрут найден, false иначе
|
||||
*/
|
||||
bool routing_table_lookup(struct routing_table *table, uint32_t dest_ip, struct route_entry *best_route);
|
||||
|
||||
/**
|
||||
* @brief Валидирует маршрут на основе типа и подсетей
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param network Сетевой адрес
|
||||
* @param prefix_length Длина префикса
|
||||
* @param route_type Тип маршрута
|
||||
* @return true если маршрут валиден, false иначе
|
||||
*/
|
||||
bool routing_validate_route(struct routing_table *table, uint32_t network, uint8_t prefix_length, route_type_t route_type);
|
||||
|
||||
/**
|
||||
* @brief Добавляет динамическую подсеть в таблицу
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param network Сетевой адрес
|
||||
* @param prefix_length Длина префикса
|
||||
* @return true если добавление успешно, false иначе
|
||||
*/
|
||||
bool routing_add_dynamic_subnet(struct routing_table *table, uint32_t network, uint8_t prefix_length);
|
||||
|
||||
/**
|
||||
* @brief Добавляет локальную подсеть в таблицу
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param network Сетевой адрес
|
||||
* @param prefix_length Длина префикса
|
||||
* @return true если добавление успешно, false иначе
|
||||
*/
|
||||
bool routing_add_local_subnet(struct routing_table *table, uint32_t network, uint8_t prefix_length);
|
||||
|
||||
/**
|
||||
* @brief Получает все маршруты для заданной сети и префикса
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
* @param network Сетевой адрес
|
||||
* @param prefix_length Длина префикса
|
||||
* @param routes Указатель на массив маршрутов (будет выделен)
|
||||
* @param count Указатель на количество найденных маршрутов
|
||||
* @return true если операция успешна, false иначе
|
||||
*/
|
||||
bool routing_get_all_routes(const struct routing_table *table, uint32_t network, uint8_t prefix_length, struct route_entry **routes, size_t *count);
|
||||
|
||||
/**
|
||||
* @brief Печатает содержимое таблицы маршрутизации
|
||||
*
|
||||
* @param table Указатель на таблицу маршрутизации
|
||||
*/
|
||||
void routing_table_print(const struct routing_table *table);
|
||||
|
||||
/**
|
||||
* @brief Преобразует тип маршрута в строковое представление
|
||||
*
|
||||
* @param type Тип маршрута
|
||||
* @return Строковое представление типа
|
||||
*/
|
||||
const char* route_type_to_string(route_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Преобразует IP-адрес в строковое представление
|
||||
*
|
||||
* @param ip IP-адрес в сетевом формате
|
||||
* @param buffer Буфер для хранения строки (минимум 16 байт)
|
||||
* @return Указатель на буфер с строкой
|
||||
*/
|
||||
char* ip_to_string(uint32_t ip, char *buffer);
|
||||
|
||||
#endif // ROUTING_H
|
||||
+112
-110
@@ -4,7 +4,6 @@
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/u_async.h"
|
||||
#include "etcp_connections.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -21,91 +20,97 @@
|
||||
#include <linux/if_tun.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Helper for interface ioctl operations
|
||||
static int if_ioctl(const char *ifname, unsigned long request, struct ifreq *ifr) {
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create ioctl socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(ifr->ifr_name, ifname, IFNAMSIZ - 1);
|
||||
ifr->ifr_name[IFNAMSIZ - 1] = '\0';
|
||||
|
||||
int ret = ioctl(sock, request, ifr);
|
||||
if (ret < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "ioctl failed for %s (request=0x%lx): %s", ifname, request, strerror(errno));
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Parse IP address and CIDR mask
|
||||
static int parse_ip_mask(const char *ip_addr, struct in_addr *ip, struct in_addr *netmask) {
|
||||
if (!ip_addr || !ip || !netmask) return -1;
|
||||
|
||||
char ip_str[INET_ADDRSTRLEN];
|
||||
char *slash = strchr(ip_addr, '/');
|
||||
if (!slash) return -1; // Require /mask
|
||||
|
||||
size_t ip_len = slash - ip_addr;
|
||||
if (ip_len >= sizeof(ip_str)) return -1;
|
||||
strncpy(ip_str, ip_addr, ip_len);
|
||||
ip_str[ip_len] = '\0';
|
||||
|
||||
if (inet_pton(AF_INET, ip_str, ip) <= 0) return -1;
|
||||
|
||||
char *endptr;
|
||||
long cidr = strtol(slash + 1, &endptr, 10);
|
||||
if (*endptr != '\0' || cidr < 0 || cidr > 32) return -1;
|
||||
|
||||
uint32_t mask = (cidr == 0) ? 0 : ~((1U << (32 - cidr)) - 1);
|
||||
netmask->s_addr = htonl(mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create TUN device
|
||||
static int create_tun_device(char *ifname, size_t ifname_len) {
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
|
||||
|
||||
fd = open("/dev/net/tun", O_RDWR);
|
||||
if (fd < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to open /dev/net/tun: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
||||
|
||||
|
||||
if (ifname && ifname_len > 0 && ifname[0] != '\0') {
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
|
||||
}
|
||||
|
||||
|
||||
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to configure TUN device: %s", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (ifname && ifname_len > 0) {
|
||||
strncpy(ifname, ifr.ifr_name, ifname_len - 1);
|
||||
ifname[ifname_len - 1] = '\0';
|
||||
}
|
||||
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Run system command
|
||||
static int run_command(const char *cmd) {
|
||||
int ret = system(cmd);
|
||||
if (ret == -1) {
|
||||
perror("system");
|
||||
return -1;
|
||||
}
|
||||
if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Command failed: %s", cmd);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse IP address and mask
|
||||
static int parse_ip_mask(const char *ip_addr, char *ip, size_t ip_len, int *mask) {
|
||||
if (!ip_addr || !ip || !mask) return -1;
|
||||
|
||||
char *slash = strchr(ip_addr, '/');
|
||||
if (!slash) {
|
||||
// Default mask /32
|
||||
*mask = 32;
|
||||
strncpy(ip, ip_addr, ip_len - 1);
|
||||
ip[ip_len - 1] = '\0';
|
||||
} else {
|
||||
size_t ip_size = slash - ip_addr;
|
||||
if (ip_size >= ip_len) return -1;
|
||||
strncpy(ip, ip_addr, ip_size);
|
||||
ip[ip_size] = '\0';
|
||||
|
||||
char *endptr;
|
||||
long mask_val = strtol(slash + 1, &endptr, 10);
|
||||
if (*endptr != '\0' || mask_val < 0 || mask_val > 32) return -1;
|
||||
*mask = (int)mask_val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tun_create(struct tun_config *config) {
|
||||
if (!config) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Create TUN device
|
||||
int fd = create_tun_device(config->ifname, sizeof(config->ifname));
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
config->fd = fd;
|
||||
|
||||
|
||||
// Configure IP if specified
|
||||
if (config->ip_addr[0] != '\0') {
|
||||
if (tun_set_ip(config->ifname, config->ip_addr) < 0) {
|
||||
@@ -113,20 +118,20 @@ int tun_create(struct tun_config *config) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set MTU if specified
|
||||
if (config->mtu > 0) {
|
||||
if (tun_set_mtu(config->ifname, config->mtu) < 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Failed to set MTU %d on %s: %s", config->mtu, config->ifname, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Bring interface up
|
||||
if (tun_set_up(config->ifname) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
config->is_up = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -136,21 +141,29 @@ int tun_set_ip(const char *ifname, const char *ip_addr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char ip[64];
|
||||
int mask;
|
||||
if (parse_ip_mask(ip_addr, ip, sizeof(ip), &mask) < 0) {
|
||||
|
||||
struct in_addr ip, netmask;
|
||||
if (parse_ip_mask(ip_addr, &ip, &netmask) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Invalid IP address format: %s", ip_addr);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "ip addr add %s dev %s", ip_addr, ifname);
|
||||
if (run_command(cmd) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
// Set IP address
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_addr = ip;
|
||||
if (if_ioctl(ifname, SIOCSIFADDR, &ifr) < 0) return -1;
|
||||
|
||||
// Set netmask
|
||||
addr = (struct sockaddr_in *)&ifr.ifr_netmask;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_addr = netmask;
|
||||
if (if_ioctl(ifname, SIOCSIFNETMASK, &ifr) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -159,13 +172,17 @@ int tun_set_up(const char *ifname) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "ip link set %s up", ifname);
|
||||
if (run_command(cmd) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
// Get current flags
|
||||
if (if_ioctl(ifname, SIOCGIFFLAGS, &ifr) < 0) return -1;
|
||||
|
||||
// Set UP and RUNNING
|
||||
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
|
||||
if (if_ioctl(ifname, SIOCSIFFLAGS, &ifr) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,13 +191,13 @@ int tun_set_mtu(const char *ifname, int mtu) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "ip link set %s mtu %d", ifname, mtu);
|
||||
if (run_command(cmd) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_mtu = mtu;
|
||||
|
||||
if (if_ioctl(ifname, SIOCSIFMTU, &ifr) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -189,12 +206,12 @@ ssize_t tun_read(int fd, uint8_t *buffer, size_t size) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ssize_t nread = read(fd, buffer, size);
|
||||
if (nread < 0) {
|
||||
perror("tun_read");
|
||||
}
|
||||
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
@@ -203,23 +220,23 @@ ssize_t tun_write(int fd, const uint8_t *buffer, size_t size) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ssize_t nwritten = write(fd, buffer, size);
|
||||
if (nwritten < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to write to TUN device fd=%d: %s", fd, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
void tun_close(struct tun_config *config) {
|
||||
if (!config) return;
|
||||
|
||||
|
||||
if (config->fd >= 0) {
|
||||
close(config->fd);
|
||||
config->fd = -1;
|
||||
}
|
||||
|
||||
|
||||
config->is_up = 0;
|
||||
}
|
||||
|
||||
@@ -228,27 +245,15 @@ int tun_get_config(const char *ifname, struct tun_config *config) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Implement reading current interface configuration
|
||||
// This would require parsing ip addr show output
|
||||
|
||||
// This would require ioctl SIOCGIFADDR, SIOCGIFNETMASK, etc.
|
||||
|
||||
memset(config, 0, sizeof(*config));
|
||||
strncpy(config->ifname, ifname, sizeof(config->ifname) - 1);
|
||||
config->fd = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Extract destination IPv4 address from packet
|
||||
static uint32_t tun_get_dest_ip(const uint8_t *packet, size_t len) {
|
||||
if (len < 20) return 0; // Minimum IPv4 header size
|
||||
// Check IP version (first nibble)
|
||||
uint8_t version = (packet[0] >> 4) & 0x0F;
|
||||
if (version != 4) return 0;
|
||||
// Destination IP is at offset 16
|
||||
uint32_t dest_ip;
|
||||
memcpy(&dest_ip, packet + 16, 4);
|
||||
return dest_ip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Extract destination IPv4 address from packet
|
||||
@@ -263,12 +268,11 @@ static uint32_t get_dest_ip(const uint8_t *packet, size_t len) {
|
||||
return dest_ip;
|
||||
}
|
||||
|
||||
|
||||
// Callback for TUN device read events
|
||||
void tun_read_callback(int fd, void* user_arg) {
|
||||
struct UTUN_INSTANCE *instance = (struct UTUN_INSTANCE*)user_arg;
|
||||
uint8_t buffer[MAX_PACKET_SIZE];
|
||||
|
||||
|
||||
// Read from TUN device
|
||||
ssize_t nread = tun_read(fd, buffer, sizeof(buffer));
|
||||
if (nread < 0) {
|
||||
@@ -276,12 +280,11 @@ void tun_read_callback(int fd, void* user_arg) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to read from TUN device %s: %s", instance->tun.ifname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (nread > 0) {
|
||||
// Route packet based on destination IP
|
||||
uint32_t dest_ip = get_dest_ip(buffer, nread);
|
||||
|
||||
//...
|
||||
// ... (rest of the routing logic)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,15 +294,15 @@ int utun_instance_register_sockets(struct UTUN_INSTANCE *instance) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Invalid instance or TUN fd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Register TUN file descriptor
|
||||
instance->tun_socket_id = uasync_add_socket(instance->ua, instance->tun.fd,
|
||||
instance->tun_socket_id = uasync_add_socket(instance->ua, instance->tun.fd,
|
||||
tun_read_callback, NULL, NULL, instance);
|
||||
if (!instance->tun_socket_id) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to register TUN socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Registered TUN socket (fd=%d)", instance->tun.fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -307,11 +310,10 @@ int utun_instance_register_sockets(struct UTUN_INSTANCE *instance) {
|
||||
// Unregister sockets
|
||||
void utun_instance_unregister_sockets(struct UTUN_INSTANCE *instance) {
|
||||
if (!instance || !instance->ua) return;
|
||||
|
||||
|
||||
if (instance->tun_socket_id) {
|
||||
uasync_remove_socket(instance->ua, instance->tun_socket_id);
|
||||
instance->tun_socket_id = NULL;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Unregistered TUN socket: %s", instance->tun.ifname);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+12
-14
@@ -1,7 +1,6 @@
|
||||
// tun_if.h - TUN interface management for utun
|
||||
#ifndef TUN_IF_H
|
||||
#define TUN_IF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
@@ -17,18 +16,18 @@ extern "C" {
|
||||
|
||||
// TUN interface configuration
|
||||
struct tun_config {
|
||||
char ifname[16]; // Interface name (e.g., "tun12")
|
||||
char ip_addr[64]; // IP address with mask (e.g., "10.0.0.1/24")
|
||||
int mtu; // MTU size
|
||||
int fd; // File descriptor
|
||||
uint8_t is_up; // 1 if interface is up
|
||||
char ifname[16]; // Interface name (e.g., "tun12")
|
||||
char ip_addr[64]; // IP address with mask (e.g., "10.0.0.1/24")
|
||||
int mtu; // MTU size
|
||||
int fd; // File descriptor
|
||||
uint8_t is_up; // 1 if interface is up
|
||||
// Statistics
|
||||
uint64_t bytes_read; // Bytes read from TUN
|
||||
uint64_t bytes_written; // Bytes written to TUN
|
||||
uint32_t packets_read; // Packets read from TUN
|
||||
uint32_t packets_written; // Packets written to TUN
|
||||
uint32_t read_errors; // Read errors
|
||||
uint32_t write_errors; // Write errors
|
||||
uint64_t bytes_read; // Bytes read from TUN
|
||||
uint64_t bytes_written; // Bytes written to TUN
|
||||
uint32_t packets_read; // Packets read from TUN
|
||||
uint32_t packets_written; // Packets written to TUN
|
||||
uint32_t read_errors; // Read errors
|
||||
uint32_t write_errors; // Write errors
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -99,9 +98,8 @@ void utun_instance_unregister_sockets(struct UTUN_INSTANCE *instance);
|
||||
// TUN callback function
|
||||
void tun_read_callback(int fd, void* user_arg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TUN_IF_H */
|
||||
#endif /* TUN_IF_H */
|
||||
Reference in new issue
Block a user