Fix: Delete system routes on shutdown
- Add tun_route_del_all() to delete routes from config - Use netsh for route deletion on Windows (like add) - Store route_subnets in UTUN_INSTANCE for cleanup - Delete routes in utun_instance_destroy() before tun_close()
This commit is contained in:
1 parent
3945ff5665
commit
9269bc9c61
4 files changed
+69
-16
No files matched your search
+49
-11
@@ -158,10 +158,9 @@ int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
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);
|
||||
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
if (ifindex == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -173,7 +172,9 @@ int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
}
|
||||
|
||||
// Fallback to ip route command
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for %s", ifname);
|
||||
char ifname[16];
|
||||
snprintf(ifname, sizeof(ifname), "%u", ifindex);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for ifindex %u", ifindex);
|
||||
return ip_route_cmd(ifname, ntohl(network), prefix_len, "del");
|
||||
}
|
||||
|
||||
@@ -247,17 +248,35 @@ int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
if (ifindex == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct in_addr dest_addr;
|
||||
dest_addr.s_addr = htonl(network);
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "netsh interface ip delete route %s/%d interface=%lu store=active",
|
||||
inet_ntoa(dest_addr), prefix_len, (unsigned long)ifindex);
|
||||
int sys_ret = system(cmd);
|
||||
if (sys_ret == 0) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Deleted route %s/%d via ifindex=%lu",
|
||||
inet_ntoa(dest_addr), prefix_len, (unsigned long)ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIB_IPFORWARDROW route;
|
||||
memset(&route, 0, sizeof(route));
|
||||
|
||||
route.dwForwardDest = htonl(network);
|
||||
route.dwForwardMask = prefix_to_netmask(prefix_len);
|
||||
route.dwForwardIfIndex = if_nametoindex(ifname);
|
||||
route.dwForwardIfIndex = ifindex;
|
||||
|
||||
DWORD ret = DeleteIpForwardEntry(&route);
|
||||
if (ret != NO_ERROR) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to delete route: %lu", ret);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to delete route %s/%d: %lu",
|
||||
inet_ntoa(dest_addr), prefix_len, ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -299,6 +318,24 @@ int tun_route_flush(const char *ifname) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tun_route_del_all(uint32_t ifindex, 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_del(ifindex, network, entry->netmask) == 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Deleted %d routes via ifindex=%lu", count, (unsigned long)ifindex);
|
||||
return count;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// BSD / macOS routing socket implementation
|
||||
@@ -396,10 +433,9 @@ int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
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);
|
||||
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
if (ifindex == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -409,7 +445,9 @@ int tun_route_del(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
}
|
||||
|
||||
// Fallback to route command
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for %s", ifname);
|
||||
char ifname[16];
|
||||
snprintf(ifname, sizeof(ifname), "%u", ifindex);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for ifindex %u", ifindex);
|
||||
return route_cmd(ifname, network, prefix_len, "delete");
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -22,12 +22,20 @@ int tun_route_add(uint32_t ifindex, 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 ifindex Interface index
|
||||
* @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);
|
||||
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len);
|
||||
|
||||
/**
|
||||
* @brief Delete all system routes from config entries
|
||||
* @param ifindex Interface index
|
||||
* @param routes Linked list of route entries to delete
|
||||
* @return Number of routes deleted
|
||||
*/
|
||||
int tun_route_del_all(uint32_t ifindex, struct CFG_ROUTE_ENTRY *routes);
|
||||
|
||||
/**
|
||||
* @brief Delete all system routes via specified interface
|
||||
|
||||
+6
-3
@@ -108,6 +108,7 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
|
||||
if (config->route_subnets) {
|
||||
int added = tun_route_add_all(instance->tun->ifindex, instance->tun->ifname, config->route_subnets);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added %d system routes for TUN interface", added);
|
||||
instance->route_subnets = config->route_subnets;
|
||||
}
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN initialization disabled - skipping TUN device setup");
|
||||
@@ -237,9 +238,11 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
|
||||
if (instance->tun) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Closing TUN interface: %s", instance->tun->ifname);
|
||||
|
||||
// Flush all system routes for this interface
|
||||
tun_route_flush(instance->tun->ifname);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Flushed system routes for %s", instance->tun->ifname);
|
||||
// Delete system routes added at startup
|
||||
if (instance->tun->ifindex && instance->route_subnets) {
|
||||
int deleted = tun_route_del_all(instance->tun->ifindex, instance->route_subnets);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Deleted %d system routes for TUN interface", deleted);
|
||||
}
|
||||
|
||||
tun_close(instance->tun);
|
||||
instance->tun = NULL;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "../lib/memory_pool.h"
|
||||
#include "secure_channel.h"
|
||||
#include "etcp_api.h"
|
||||
#include "config_parser.h"
|
||||
|
||||
// Forward declarations
|
||||
struct utun_config;
|
||||
@@ -26,6 +27,9 @@ struct UTUN_INSTANCE {
|
||||
|
||||
// TUN interface
|
||||
struct tun_if* tun;
|
||||
|
||||
// Route subnets (for cleanup on shutdown)
|
||||
struct CFG_ROUTE_ENTRY* route_subnets;
|
||||
|
||||
struct ROUTE_TABLE* rt;
|
||||
struct ROUTE_BGP* bgp; // BGP module for route exchange
|
||||
|
||||
Reference in new issue
Block a user