diff --git a/src/tun_route.c b/src/tun_route.c index 710eb34a..73448730 100644 --- a/src/tun_route.c +++ b/src/tun_route.c @@ -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"); } diff --git a/src/tun_route.h b/src/tun_route.h index 1deb813a..c66d8532 100644 --- a/src/tun_route.h +++ b/src/tun_route.h @@ -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 diff --git a/src/utun_instance.c b/src/utun_instance.c index e1766945..a67d459d 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -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; diff --git a/src/utun_instance.h b/src/utun_instance.h index 984b3fa0..0ea3256e 100644 --- a/src/utun_instance.h +++ b/src/utun_instance.h @@ -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