Browse Source
- Переименовано поле allowed_subnets -> route_subnets в конфигурации - Обновлен парсинг конфига: allowed_subnet -> route_subnet - Создан новый модуль tun_route для управления системными маршрутами - Linux: реализация через netlink sockets с fallback на ip route - Windows: реализация через IP Helper API - BSD: реализация через routing sockets с fallback на route - При запуске: автоматическое добавление маршрутов route_subnet на TUN интерфейс - При завершении: автоматическое удаление всех маршрутов через tun_route_flush - Обновлены Makefile.am для сборки новых файловnodeinfo-routing-update
11 changed files with 537 additions and 53 deletions
@ -0,0 +1,429 @@ |
|||||||
|
// tun_route.c - Cross-platform system routing table management
|
||||||
|
// Linux: netlink sockets, Windows: IP Helper API, BSD: routing sockets
|
||||||
|
|
||||||
|
#include "tun_route.h" |
||||||
|
#include "config_parser.h" |
||||||
|
#include "../lib/debug_config.h" |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <errno.h> |
||||||
|
|
||||||
|
// Platform detection
|
||||||
|
#ifdef _WIN32 |
||||||
|
#include <windows.h> |
||||||
|
#include <winsock2.h> |
||||||
|
#include <ws2tcpip.h> |
||||||
|
#include <iphlpapi.h> |
||||||
|
#elif defined(__linux__) |
||||||
|
#include <linux/netlink.h> |
||||||
|
#include <linux/rtnetlink.h> |
||||||
|
#include <sys/socket.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <net/if.h> |
||||||
|
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) |
||||||
|
#include <sys/socket.h> |
||||||
|
#include <net/route.h> |
||||||
|
#include <net/if.h> |
||||||
|
#include <netinet/in.h> |
||||||
|
#include <unistd.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
// Convert prefix length to netmask
|
||||||
|
static uint32_t prefix_to_netmask(uint8_t prefix_len) { |
||||||
|
return (prefix_len == 0) ? 0 : htonl(~((1U << (32 - prefix_len)) - 1)); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef __linux__ |
||||||
|
|
||||||
|
// Linux netlink implementation
|
||||||
|
|
||||||
|
struct nl_req { |
||||||
|
struct nlmsghdr nl; |
||||||
|
struct rtmsg rt; |
||||||
|
char buf[256]; |
||||||
|
}; |
||||||
|
|
||||||
|
static int netlink_route(int ifindex, uint32_t network, uint8_t prefix_len, int cmd, int flags) { |
||||||
|
int fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); |
||||||
|
if (fd < 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create netlink socket: %s", strerror(errno)); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
struct nl_req req; |
||||||
|
memset(&req, 0, sizeof(req)); |
||||||
|
|
||||||
|
req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); |
||||||
|
req.nl.nlmsg_type = cmd; // RTM_NEWROUTE or RTM_DELROUTE
|
||||||
|
req.nl.nlmsg_flags = flags | NLM_F_REQUEST; |
||||||
|
req.nl.nlmsg_seq = 1; |
||||||
|
req.nl.nlmsg_pid = getpid(); |
||||||
|
|
||||||
|
req.rt.rtm_family = AF_INET; |
||||||
|
req.rt.rtm_table = RT_TABLE_MAIN; |
||||||
|
req.rt.rtm_protocol = RTPROT_STATIC; |
||||||
|
req.rt.rtm_scope = RT_SCOPE_UNIVERSE; |
||||||
|
req.rt.rtm_type = RTN_UNICAST; |
||||||
|
req.rt.rtm_dst_len = prefix_len; |
||||||
|
|
||||||
|
// Add destination address attribute
|
||||||
|
struct rtattr *rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nl.nlmsg_len)); |
||||||
|
rta->rta_type = RTA_DST; |
||||||
|
rta->rta_len = RTA_LENGTH(4); |
||||||
|
memcpy(RTA_DATA(rta), &network, 4); |
||||||
|
req.nl.nlmsg_len = NLMSG_ALIGN(req.nl.nlmsg_len) + RTA_ALIGN(rta->rta_len); |
||||||
|
|
||||||
|
// Add output interface attribute
|
||||||
|
rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nl.nlmsg_len)); |
||||||
|
rta->rta_type = RTA_OIF; |
||||||
|
rta->rta_len = RTA_LENGTH(4); |
||||||
|
memcpy(RTA_DATA(rta), &ifindex, 4); |
||||||
|
req.nl.nlmsg_len = NLMSG_ALIGN(req.nl.nlmsg_len) + RTA_ALIGN(rta->rta_len); |
||||||
|
|
||||||
|
if (send(fd, &req, req.nl.nlmsg_len, 0) < 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to send netlink message: %s", strerror(errno)); |
||||||
|
close(fd); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Receive response
|
||||||
|
char reply[4096]; |
||||||
|
ssize_t len = recv(fd, reply, sizeof(reply), 0); |
||||||
|
if (len < 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to receive netlink response: %s", strerror(errno)); |
||||||
|
close(fd); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
struct nlmsghdr *nl_hdr = (struct nlmsghdr *)reply; |
||||||
|
if (nl_hdr->nlmsg_type == NLMSG_ERROR) { |
||||||
|
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nl_hdr); |
||||||
|
if (err->error < 0) { |
||||||
|
errno = -err->error; |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Netlink error: %s", strerror(errno)); |
||||||
|
close(fd); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
close(fd); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Fallback: use ip route command
|
||||||
|
static int ip_route_cmd(const char *ifname, uint32_t network, uint8_t prefix_len, const char *cmd) { |
||||||
|
char network_str[INET_ADDRSTRLEN]; |
||||||
|
struct in_addr addr; |
||||||
|
addr.s_addr = network; |
||||||
|
if (!inet_ntop(AF_INET, &addr, network_str, sizeof(network_str))) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
char cmdline[256]; |
||||||
|
snprintf(cmdline, sizeof(cmdline), "ip route %s %s/%d dev %s 2>/dev/null", |
||||||
|
cmd, network_str, prefix_len, ifname); |
||||||
|
|
||||||
|
int ret = system(cmdline); |
||||||
|
return (ret == 0) ? 0 : -1; |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) { |
||||||
|
int ifindex = if_nametoindex(ifname); |
||||||
|
if (ifindex == 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
network = htonl(network); |
||||||
|
|
||||||
|
// Try netlink first
|
||||||
|
if (netlink_route(ifindex, network, prefix_len, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL) == 0) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Fallback to ip route command
|
||||||
|
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for %s", ifname); |
||||||
|
return ip_route_cmd(ifname, ntohl(network), prefix_len, "add"); |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len) { |
||||||
|
int ifindex = if_nametoindex(ifname); |
||||||
|
if (ifindex == 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
network = htonl(network); |
||||||
|
|
||||||
|
// Try netlink first
|
||||||
|
if (netlink_route(ifindex, network, prefix_len, RTM_DELROUTE, 0) == 0) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Fallback to ip route command
|
||||||
|
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for %s", ifname); |
||||||
|
return ip_route_cmd(ifname, ntohl(network), prefix_len, "del"); |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_flush(const char *ifname) { |
||||||
|
// Use ip route flush as primary method - works reliably
|
||||||
|
char cmdline[256]; |
||||||
|
snprintf(cmdline, sizeof(cmdline), "ip route flush dev %s 2>/dev/null", ifname); |
||||||
|
int ret = system(cmdline); |
||||||
|
|
||||||
|
if (ret != 0) { |
||||||
|
// Fallback: try to list and delete routes one by one
|
||||||
|
DEBUG_WARN(DEBUG_CATEGORY_TUN, "ip route flush failed, trying alternative method"); |
||||||
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
|
"ip route show dev %s 2>/dev/null | while read r; do ip route del $r dev %s 2>/dev/null; done", |
||||||
|
ifname, ifname); |
||||||
|
ret = system(cmdline); |
||||||
|
} |
||||||
|
|
||||||
|
return (ret == 0) ? 0 : -1; |
||||||
|
} |
||||||
|
|
||||||
|
#elif defined(_WIN32) |
||||||
|
|
||||||
|
// Windows IP Helper API implementation
|
||||||
|
|
||||||
|
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) { |
||||||
|
MIB_IPFORWARDROW route; |
||||||
|
memset(&route, 0, sizeof(route)); |
||||||
|
|
||||||
|
route.dwForwardDest = htonl(network); |
||||||
|
route.dwForwardMask = prefix_to_netmask(prefix_len); |
||||||
|
route.dwForwardPolicy = 0; |
||||||
|
route.dwForwardNextHop = 0; // On-link route
|
||||||
|
route.dwForwardIfIndex = if_nametoindex(ifname); |
||||||
|
route.dwForwardType = MIB_IPROUTE_TYPE_DIRECT; |
||||||
|
route.dwForwardProto = MIB_IPPROTO_NETMGMT; |
||||||
|
route.dwForwardAge = 0; |
||||||
|
route.dwForwardNextHopAS = 0; |
||||||
|
route.dwForwardMetric1 = 1; |
||||||
|
route.dwForwardMetric2 = 0; |
||||||
|
route.dwForwardMetric3 = 0; |
||||||
|
route.dwForwardMetric4 = 0; |
||||||
|
route.dwForwardMetric5 = 0; |
||||||
|
|
||||||
|
DWORD ret = CreateIpForwardEntry(&route); |
||||||
|
if (ret != NO_ERROR) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to add route: %lu", ret); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len) { |
||||||
|
MIB_IPFORWARDROW route; |
||||||
|
memset(&route, 0, sizeof(route)); |
||||||
|
|
||||||
|
route.dwForwardDest = htonl(network); |
||||||
|
route.dwForwardMask = prefix_to_netmask(prefix_len); |
||||||
|
route.dwForwardIfIndex = if_nametoindex(ifname); |
||||||
|
|
||||||
|
DWORD ret = DeleteIpForwardEntry(&route); |
||||||
|
if (ret != NO_ERROR) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to delete route: %lu", ret); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_flush(const char *ifname) { |
||||||
|
PMIB_IPFORWARDTABLE table = NULL; |
||||||
|
DWORD size = 0; |
||||||
|
DWORD ret; |
||||||
|
|
||||||
|
DWORD ifindex = if_nametoindex(ifname); |
||||||
|
if (ifindex == 0) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Get table size
|
||||||
|
ret = GetIpForwardTable(NULL, &size, 0); |
||||||
|
if (ret != ERROR_INSUFFICIENT_BUFFER) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
table = (PMIB_IPFORWARDTABLE)malloc(size); |
||||||
|
if (!table) return -1; |
||||||
|
|
||||||
|
ret = GetIpForwardTable(table, &size, 0); |
||||||
|
if (ret != NO_ERROR) { |
||||||
|
free(table); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Delete all routes for this interface
|
||||||
|
for (DWORD i = 0; i < table->dwNumEntries; i++) { |
||||||
|
if (table->table[i].dwForwardIfIndex == ifindex) { |
||||||
|
DeleteIpForwardEntry(&table->table[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
free(table); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
#else |
||||||
|
|
||||||
|
// BSD / macOS routing socket implementation
|
||||||
|
|
||||||
|
static int routing_socket_cmd(int ifindex, uint32_t network, uint8_t prefix_len, int cmd) { |
||||||
|
int fd = socket(PF_ROUTE, SOCK_RAW, AF_INET); |
||||||
|
if (fd < 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create routing socket: %s", strerror(errno)); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t buf[512]; |
||||||
|
memset(buf, 0, sizeof(buf)); |
||||||
|
|
||||||
|
struct rt_msghdr *rtm = (struct rt_msghdr *)buf; |
||||||
|
rtm->rtm_msglen = sizeof(struct rt_msghdr); |
||||||
|
rtm->rtm_version = RTM_VERSION; |
||||||
|
rtm->rtm_type = cmd; // RTM_ADD or RTM_DELETE
|
||||||
|
rtm->rtm_index = ifindex; |
||||||
|
rtm->rtm_pid = getpid(); |
||||||
|
rtm->rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP; |
||||||
|
rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; |
||||||
|
|
||||||
|
// Destination address (network)
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *)(rtm + 1); |
||||||
|
sin->sin_family = AF_INET; |
||||||
|
sin->sin_len = sizeof(struct sockaddr_in); |
||||||
|
sin->sin_addr.s_addr = htonl(network); |
||||||
|
rtm->rtm_msglen += sizeof(struct sockaddr_in); |
||||||
|
|
||||||
|
// Netmask
|
||||||
|
sin++; |
||||||
|
sin->sin_family = AF_INET; |
||||||
|
sin->sin_len = sizeof(struct sockaddr_in); |
||||||
|
sin->sin_addr.s_addr = prefix_to_netmask(prefix_len); |
||||||
|
rtm->rtm_msglen += sizeof(struct sockaddr_in); |
||||||
|
|
||||||
|
// Interface name
|
||||||
|
sin++; |
||||||
|
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sin; |
||||||
|
sdl->sdl_family = AF_LINK; |
||||||
|
sdl->sdl_index = ifindex; |
||||||
|
sdl->sdl_len = sizeof(struct sockaddr_dl); |
||||||
|
rtm->rtm_msglen += sizeof(struct sockaddr_dl); |
||||||
|
|
||||||
|
if (write(fd, rtm, rtm->rtm_msglen) < 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to send routing message: %s", strerror(errno)); |
||||||
|
close(fd); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Read response
|
||||||
|
ssize_t n = read(fd, buf, sizeof(buf)); |
||||||
|
if (n >= sizeof(struct rt_msghdr)) { |
||||||
|
if (rtm->rtm_errno != 0) { |
||||||
|
errno = rtm->rtm_errno; |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Routing error: %s", strerror(errno)); |
||||||
|
close(fd); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
close(fd); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Fallback: use route command
|
||||||
|
static int route_cmd(const char *ifname, uint32_t network, uint8_t prefix_len, const char *cmd) { |
||||||
|
char network_str[INET_ADDRSTRLEN]; |
||||||
|
struct in_addr addr; |
||||||
|
addr.s_addr = htonl(network); |
||||||
|
if (!inet_ntop(AF_INET, &addr, network_str, sizeof(network_str))) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
char cmdline[256]; |
||||||
|
snprintf(cmdline, sizeof(cmdline), "route %s -net %s/%d -interface %s 2>/dev/null", |
||||||
|
cmd, network_str, prefix_len, ifname); |
||||||
|
|
||||||
|
int ret = system(cmdline); |
||||||
|
return (ret == 0) ? 0 : -1; |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) { |
||||||
|
int ifindex = if_nametoindex(ifname); |
||||||
|
if (ifindex == 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Try routing socket first
|
||||||
|
if (routing_socket_cmd(ifindex, network, prefix_len, RTM_ADD) == 0) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Fallback to route command
|
||||||
|
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for %s", ifname); |
||||||
|
return route_cmd(ifname, network, prefix_len, "add"); |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len) { |
||||||
|
int ifindex = if_nametoindex(ifname); |
||||||
|
if (ifindex == 0) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Try routing socket first
|
||||||
|
if (routing_socket_cmd(ifindex, network, prefix_len, RTM_DELETE) == 0) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Fallback to route command
|
||||||
|
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for %s", ifname); |
||||||
|
return route_cmd(ifname, network, prefix_len, "delete"); |
||||||
|
} |
||||||
|
|
||||||
|
int tun_route_flush(const char *ifname) { |
||||||
|
// Use route command to flush routes - more reliable on BSD
|
||||||
|
char cmdline[256]; |
||||||
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
|
"route -n show -interface %s 2>/dev/null | grep -v '^[[:space:]]*#' | " |
||||||
|
"awk '/^[0-9]+\\./{print $1}' | while read r; do route delete -net $r 2>/dev/null; done", |
||||||
|
ifname); |
||||||
|
int ret = system(cmdline); |
||||||
|
|
||||||
|
return (ret == 0) ? 0 : -1; |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
// Platform-independent functions
|
||||||
|
|
||||||
|
int tun_route_add_all(const char *ifname, struct CFG_ROUTE_ENTRY *routes) { |
||||||
|
int count = 0; |
||||||
|
struct CFG_ROUTE_ENTRY *entry = routes; |
||||||
|
|
||||||
|
while (entry) { |
||||||
|
uint32_t network = ntohl(entry->ip.addr.v4.s_addr); |
||||||
|
if (entry->ip.family == AF_INET) { |
||||||
|
if (tun_route_add(ifname, network, entry->netmask) == 0) { |
||||||
|
char ip_str[INET_ADDRSTRLEN]; |
||||||
|
struct in_addr addr; |
||||||
|
addr.s_addr = entry->ip.addr.v4.s_addr; |
||||||
|
inet_ntop(AF_INET, &addr, ip_str, sizeof(ip_str)); |
||||||
|
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added route %s/%d via %s", ip_str, entry->netmask, ifname); |
||||||
|
count++; |
||||||
|
} else { |
||||||
|
char ip_str[INET_ADDRSTRLEN]; |
||||||
|
struct in_addr addr; |
||||||
|
addr.s_addr = entry->ip.addr.v4.s_addr; |
||||||
|
inet_ntop(AF_INET, &addr, ip_str, sizeof(ip_str)); |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to add route %s/%d via %s", ip_str, entry->netmask, ifname); |
||||||
|
} |
||||||
|
} |
||||||
|
entry = entry->next; |
||||||
|
} |
||||||
|
|
||||||
|
return count; |
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
// tun_route.h - Cross-platform system routing table management
|
||||||
|
#ifndef TUN_ROUTE_H |
||||||
|
#define TUN_ROUTE_H |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <stddef.h> |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
struct CFG_ROUTE_ENTRY; |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add system route for a subnet via TUN interface |
||||||
|
* @param ifname Interface name (e.g., "tun0") |
||||||
|
* @param network Network address in host byte order |
||||||
|
* @param prefix_len Prefix length (1-32) |
||||||
|
* @return 0 on success, -1 on error |
||||||
|
*/ |
||||||
|
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete system route for a subnet via TUN interface |
||||||
|
* @param ifname Interface name (e.g., "tun0") |
||||||
|
* @param network Network address in host byte order |
||||||
|
* @param prefix_len Prefix length (1-32) |
||||||
|
* @return 0 on success, -1 on error |
||||||
|
*/ |
||||||
|
int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete all system routes via specified interface |
||||||
|
* @param ifname Interface name (e.g., "tun0") |
||||||
|
* @return 0 on success, -1 on error |
||||||
|
*/ |
||||||
|
int tun_route_flush(const char *ifname); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add multiple routes from config entries |
||||||
|
* @param ifname Interface name (e.g., "tun0") |
||||||
|
* @param routes Linked list of route entries |
||||||
|
* @return Number of routes added successfully |
||||||
|
*/ |
||||||
|
int tun_route_add_all(const char *ifname, struct CFG_ROUTE_ENTRY *routes); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* TUN_ROUTE_H */ |
||||||
@ -1,44 +0,0 @@ |
|||||||
[global] |
|
||||||
tun_ip=10.0.0.1 |
|
||||||
mtu=1500 # MTU for all connections (0 = use default 1500) |
|
||||||
control_ip=127.0.0.1 |
|
||||||
control_port=12345 |
|
||||||
net_debug=0 |
|
||||||
|
|
||||||
my_node_id=61be9d4cd3c60c2d |
|
||||||
my_private_key=1313912e5d34768983b0e06530a48c77816d228a5b5605e1ab3dc443d107a3dc |
|
||||||
my_public_key=dde6cec8a9023339a758f60883ef41534d24a1ffdc09bbb787a5c24ddfd891e3092461835a97d37944c681fc6b2c1f5acde8ad192f7d2cdc9920aa0d3ff78e99 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[routing] |
|
||||||
allowed_subnet=10.0.0.0/24 |
|
||||||
allowed_subnet=10.22.0.0/16 |
|
||||||
allowed_subnet=10.23.0.0/16 |
|
||||||
my_subnet=10.23.5.0/24 |
|
||||||
my_subnet=10.23.6.0/24 |
|
||||||
|
|
||||||
# секция server обязательна и у сервера и у клиента. это рабочий сокет. |
|
||||||
# мои адреса и каналы |
|
||||||
[server: lo0_test] |
|
||||||
addr=127.0.0.1:1330 |
|
||||||
#so_mark=100 |
|
||||||
#netif=eth0 |
|
||||||
type=nat # public / nat / private |
|
||||||
|
|
||||||
[server: lan1] |
|
||||||
addr=192.168.29.117:1333 |
|
||||||
so_mark=100 |
|
||||||
netif=eth0 |
|
||||||
type=public # public / nat / private |
|
||||||
|
|
||||||
[client: client_test1] |
|
||||||
|
|
||||||
# линки |
|
||||||
link=lo0_test:192.168.0.20:1234 |
|
||||||
#link=wired1_fast:1.2.3.4:1234 |
|
||||||
link=lan1:192.168.0.20:1234 |
|
||||||
#link=wireless_bkp:1.2.3.4:1234 |
|
||||||
|
|
||||||
keepalive=1 |
|
||||||
peer_public_key=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbe |
|
||||||
@ -0,0 +1,32 @@ |
|||||||
|
[global] |
||||||
|
tun_ip=10.0.0.1 |
||||||
|
mtu=1500 # MTU for all connections (0 = use default 1500) |
||||||
|
control_ip=127.0.0.1 |
||||||
|
control_port=12345 |
||||||
|
net_debug=0 |
||||||
|
|
||||||
|
my_node_id= |
||||||
|
my_private_key= |
||||||
|
my_public_key= |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[routing] |
||||||
|
route_subnet=10.0.0.0/24 |
||||||
|
route_subnet=10.23.0.0/16 |
||||||
|
#allowed_subnet=10.23.0.0/16 |
||||||
|
my_subnet=10.23.1.0/24 |
||||||
|
|
||||||
|
# секция server обязательна и у сервера и у клиента. это рабочий сокет. |
||||||
|
# мои адреса и каналы |
||||||
|
[server: lo0_test] |
||||||
|
addr=127.0.0.1:1330 |
||||||
|
#so_mark=100 |
||||||
|
#netif=eth0 |
||||||
|
type=nat # public / nat / private |
||||||
|
|
||||||
|
[server: lan1] |
||||||
|
addr=192.168.29.117:1333 |
||||||
|
#so_mark=100 |
||||||
|
#netif=eth0 |
||||||
|
type=public # public / nat / private |
||||||
Loading…
Reference in new issue