|
|
|
@ -13,26 +13,39 @@ |
|
|
|
#include <unistd.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <errno.h> |
|
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
#ifdef __linux__ |
|
|
|
#include <linux/netlink.h> |
|
|
|
#include <linux/netlink.h> |
|
|
|
#include <linux/rtnetlink.h> |
|
|
|
#include <linux/rtnetlink.h> |
|
|
|
#include <net/if.h> |
|
|
|
#include <net/if.h> |
|
|
|
|
|
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
|
|
|
|
|
|
|
#include <net/route.h> |
|
|
|
|
|
|
|
#include <net/if.h> |
|
|
|
|
|
|
|
#include <net/if_dl.h> |
|
|
|
|
|
|
|
#elif defined(_WIN32) |
|
|
|
|
|
|
|
#include <iphlpapi.h> |
|
|
|
|
|
|
|
#include <netioapi.h> |
|
|
|
|
|
|
|
#include <ws2ipdef.h> |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
struct SOCKET_MONITOR { |
|
|
|
struct SOCKET_MONITOR { |
|
|
|
struct UTUN_INSTANCE* instance; |
|
|
|
struct UTUN_INSTANCE* instance; |
|
|
|
socket_t nl_sock; |
|
|
|
|
|
|
|
void* uasync_handle; |
|
|
|
void* uasync_handle; |
|
|
|
int seq; |
|
|
|
|
|
|
|
uint32_t addr_changes; |
|
|
|
uint32_t addr_changes; |
|
|
|
uint32_t link_changes; |
|
|
|
uint32_t link_changes; |
|
|
|
uint32_t route_changes; |
|
|
|
uint32_t route_changes; |
|
|
|
uint32_t socket_updates; |
|
|
|
uint32_t socket_updates; |
|
|
|
|
|
|
|
#ifdef __linux__ |
|
|
|
|
|
|
|
socket_t nl_sock; |
|
|
|
|
|
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
|
|
|
|
|
|
|
socket_t route_sock; |
|
|
|
|
|
|
|
#elif defined(_WIN32) |
|
|
|
|
|
|
|
HANDLE addr_notify_handle; |
|
|
|
|
|
|
|
HANDLE route_notify_handle; |
|
|
|
|
|
|
|
#endif |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void socket_monitor_read_cb(int fd, void* arg); |
|
|
|
/* ===== Common functions (all platforms) ===== */ |
|
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
|
|
|
static void socket_monitor_update_if_addr(struct ETCP_SOCKET* es) { |
|
|
|
static void socket_monitor_update_if_addr(struct ETCP_SOCKET* es) { |
|
|
|
if (es->local_addr.ss_family == AF_INET) { |
|
|
|
if (es->local_addr.ss_family == AF_INET) { |
|
|
|
if (es->netif_index > 0) { |
|
|
|
if (es->netif_index > 0) { |
|
|
|
@ -103,8 +116,7 @@ static void socket_monitor_update_if_addr(struct ETCP_SOCKET* es) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void socket_monitor_check_and_fire(struct SOCKET_MONITOR* sm, struct ETCP_SOCKET* es, uint32_t ifindex) { |
|
|
|
static void socket_monitor_fire_one(struct SOCKET_MONITOR* sm, struct ETCP_SOCKET* es) { |
|
|
|
if (es->netif_index != ifindex) return; |
|
|
|
|
|
|
|
struct sockaddr_storage old_if_addr = es->interface_addr; |
|
|
|
struct sockaddr_storage old_if_addr = es->interface_addr; |
|
|
|
socket_monitor_update_if_addr(es); |
|
|
|
socket_monitor_update_if_addr(es); |
|
|
|
if (memcmp(&old_if_addr, &es->interface_addr, sizeof(old_if_addr)) != 0) { |
|
|
|
if (memcmp(&old_if_addr, &es->interface_addr, sizeof(old_if_addr)) != 0) { |
|
|
|
@ -115,6 +127,14 @@ static void socket_monitor_check_and_fire(struct SOCKET_MONITOR* sm, struct ETCP |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void socket_monitor_check_and_fire(struct SOCKET_MONITOR* sm, struct ETCP_SOCKET* es, uint32_t ifindex) { |
|
|
|
|
|
|
|
if (es->netif_index != ifindex) return; |
|
|
|
|
|
|
|
socket_monitor_fire_one(sm, es); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ===== Linux: netlink ===== */ |
|
|
|
|
|
|
|
#ifdef __linux__ |
|
|
|
|
|
|
|
|
|
|
|
static void socket_monitor_handle_addr(struct SOCKET_MONITOR* sm, struct ifaddrmsg* ifa, int msg_type) { |
|
|
|
static void socket_monitor_handle_addr(struct SOCKET_MONITOR* sm, struct ifaddrmsg* ifa, int msg_type) { |
|
|
|
sm->addr_changes++; |
|
|
|
sm->addr_changes++; |
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "addr event: type=%s ifindex=%u family=%d", |
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "addr event: type=%s ifindex=%u family=%d", |
|
|
|
@ -196,17 +216,126 @@ static void socket_monitor_read_cb(int fd, void* arg) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ===== FreeBSD: AF_ROUTE routing socket ===== */ |
|
|
|
|
|
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void socket_monitor_bsd_read_cb(int fd, void* arg) { |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)arg; |
|
|
|
|
|
|
|
char buf[8192]; |
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
|
|
|
ssize_t n = read(fd, buf, sizeof(buf)); |
|
|
|
|
|
|
|
if (n < 0) { |
|
|
|
|
|
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) break; |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "route socket read fd=%d failed: %s", fd, strerror(errno)); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (n < (ssize_t)sizeof(struct rt_msghdr)) break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct rt_msghdr* rtm = (struct rt_msghdr*)buf; |
|
|
|
|
|
|
|
if (rtm->rtm_version != RTM_VERSION) continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (rtm->rtm_type) { |
|
|
|
|
|
|
|
case RTM_IFINFO: |
|
|
|
|
|
|
|
case RTM_IFANNOUNCE: |
|
|
|
|
|
|
|
sm->link_changes++; |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "link event: type=%d", rtm->rtm_type); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct ETCP_SOCKET* es = sm->instance->etcp_sockets; |
|
|
|
|
|
|
|
while (es) { |
|
|
|
|
|
|
|
etcp_socket_cbk_fire(es, ETCP_SOCKET_EVENT_STATUS_CHANGED); |
|
|
|
|
|
|
|
socket_monitor_fire_one(sm, es); |
|
|
|
|
|
|
|
es = es->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case RTM_NEWADDR: |
|
|
|
|
|
|
|
case RTM_DELADDR: |
|
|
|
|
|
|
|
sm->addr_changes++; |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "addr event: type=%s", rtm->rtm_type == RTM_NEWADDR ? "NEW" : "DEL"); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct ETCP_SOCKET* es = sm->instance->etcp_sockets; |
|
|
|
|
|
|
|
while (es) { socket_monitor_fire_one(sm, es); es = es->next; } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case RTM_ADD: |
|
|
|
|
|
|
|
case RTM_DELETE: |
|
|
|
|
|
|
|
sm->route_changes++; |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "route event: type=%s", rtm->rtm_type == RTM_ADD ? "ADD" : "DELETE"); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct ETCP_SOCKET* es = sm->instance->etcp_sockets; |
|
|
|
|
|
|
|
while (es) { |
|
|
|
|
|
|
|
if (es->netif_index != 0 || es->local_addr.ss_family == 0) { es = es->next; continue; } |
|
|
|
|
|
|
|
int is_any = 0; |
|
|
|
|
|
|
|
if (es->local_addr.ss_family == AF_INET) { |
|
|
|
|
|
|
|
struct sockaddr_in* sin = (struct sockaddr_in*)&es->local_addr; |
|
|
|
|
|
|
|
is_any = (sin->sin_addr.s_addr == 0); |
|
|
|
|
|
|
|
} else if (es->local_addr.ss_family == AF_INET6) { |
|
|
|
|
|
|
|
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&es->local_addr; |
|
|
|
|
|
|
|
is_any = (memcmp(&sin6->sin6_addr, &in6addr_any, 16) == 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (is_any) socket_monitor_fire_one(sm, es); |
|
|
|
|
|
|
|
es = es->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ===== Windows: IP Helper callbacks ===== */ |
|
|
|
|
|
|
|
#elif defined(_WIN32) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void process_win_addr_notify(void* arg) { |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)arg; |
|
|
|
|
|
|
|
struct ETCP_SOCKET* es = sm->instance->etcp_sockets; |
|
|
|
|
|
|
|
while (es) { socket_monitor_fire_one(sm, es); es = es->next; } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void process_win_route_notify(void* arg) { |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)arg; |
|
|
|
|
|
|
|
struct ETCP_SOCKET* es = sm->instance->etcp_sockets; |
|
|
|
|
|
|
|
while (es) { |
|
|
|
|
|
|
|
if (es->netif_index != 0 || es->local_addr.ss_family == 0) { es = es->next; continue; } |
|
|
|
|
|
|
|
int is_any = 0; |
|
|
|
|
|
|
|
if (es->local_addr.ss_family == AF_INET) { |
|
|
|
|
|
|
|
struct sockaddr_in* sin = (struct sockaddr_in*)&es->local_addr; |
|
|
|
|
|
|
|
is_any = (sin->sin_addr.s_addr == 0); |
|
|
|
|
|
|
|
} else if (es->local_addr.ss_family == AF_INET6) { |
|
|
|
|
|
|
|
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&es->local_addr; |
|
|
|
|
|
|
|
is_any = (memcmp(&sin6->sin6_addr, &in6addr_any, 16) == 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (is_any) socket_monitor_fire_one(sm, es); |
|
|
|
|
|
|
|
es = es->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void WINAPI addr_change_cb(PVOID ctx, PMIB_UNICASTIPADDRESS_ROW row, MIB_NOTIFICATION_TYPE type) { |
|
|
|
|
|
|
|
(void)row; (void)type; |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)ctx; |
|
|
|
|
|
|
|
sm->addr_changes++; |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "addr event: type=%d", (int)type); |
|
|
|
|
|
|
|
uasync_post(sm->instance->ua, process_win_addr_notify, sm); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void WINAPI route_change_cb(PVOID ctx, PMIB_IPFORWARD_ROW2 row, MIB_NOTIFICATION_TYPE type) { |
|
|
|
|
|
|
|
(void)row; (void)type; |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)ctx; |
|
|
|
|
|
|
|
sm->route_changes++; |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "route event: type=%d", (int)type); |
|
|
|
|
|
|
|
uasync_post(sm->instance->ua, process_win_route_notify, sm); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ===== Public API ===== */ |
|
|
|
|
|
|
|
|
|
|
|
int socket_monitor_init(struct UTUN_INSTANCE* instance) { |
|
|
|
int socket_monitor_init(struct UTUN_INSTANCE* instance) { |
|
|
|
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "instance is NULL"); return -1; } |
|
|
|
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "instance is NULL"); return -1; } |
|
|
|
if (instance->socket_monitor) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socket monitor already initialized"); return -1; } |
|
|
|
if (instance->socket_monitor) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socket monitor already initialized"); return -1; } |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "initializing socket monitor"); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "initializing socket monitor"); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
#ifdef __linux__ |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor not available on Windows"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = u_calloc(1, sizeof(struct SOCKET_MONITOR)); |
|
|
|
struct SOCKET_MONITOR* sm = u_calloc(1, sizeof(struct SOCKET_MONITOR)); |
|
|
|
if (!sm) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "alloc failed"); return -1; } |
|
|
|
if (!sm) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "alloc failed"); return -1; } |
|
|
|
sm->instance = instance; |
|
|
|
sm->instance = instance; |
|
|
|
@ -240,15 +369,68 @@ int socket_monitor_init(struct UTUN_INSTANCE* instance) { |
|
|
|
instance->socket_monitor = sm; |
|
|
|
instance->socket_monitor = sm; |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor initialized: nl_sock=%d", sm->nl_sock); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor initialized: nl_sock=%d", sm->nl_sock); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = u_calloc(1, sizeof(struct SOCKET_MONITOR)); |
|
|
|
|
|
|
|
if (!sm) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "alloc failed"); return -1; } |
|
|
|
|
|
|
|
sm->instance = instance; |
|
|
|
|
|
|
|
sm->route_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); |
|
|
|
|
|
|
|
if (sm->route_sock < 0) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "failed to create route socket: %s", strerror(errno)); |
|
|
|
|
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (fcntl(sm->route_sock, F_SETFL, O_NONBLOCK) < 0) { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "failed to set route socket non-blocking: %s", strerror(errno)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
sm->uasync_handle = uasync_add_socket(instance->ua, sm->route_sock, socket_monitor_bsd_read_cb, NULL, NULL, sm); |
|
|
|
|
|
|
|
if (!sm->uasync_handle) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "failed to register route socket fd=%d with uasync", sm->route_sock); |
|
|
|
|
|
|
|
close(sm->route_sock); |
|
|
|
|
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
instance->socket_monitor = sm; |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor initialized: route_sock=%d", sm->route_sock); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(_WIN32) |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = u_calloc(1, sizeof(struct SOCKET_MONITOR)); |
|
|
|
|
|
|
|
if (!sm) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "alloc failed"); return -1; } |
|
|
|
|
|
|
|
sm->instance = instance; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD ret = NotifyUnicastIpAddressChange(AF_UNSPEC, addr_change_cb, sm, FALSE, &sm->addr_notify_handle); |
|
|
|
|
|
|
|
if (ret != NO_ERROR) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "NotifyUnicastIpAddressChange failed: %lu", (unsigned long)ret); |
|
|
|
|
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "NotifyUnicastIpAddressChange registered: handle=%p", sm->addr_notify_handle); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret = NotifyRouteChange2(AF_UNSPEC, route_change_cb, sm, FALSE, &sm->route_notify_handle); |
|
|
|
|
|
|
|
if (ret != NO_ERROR) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "NotifyRouteChange2 failed: %lu", (unsigned long)ret); |
|
|
|
|
|
|
|
CancelMibChangeNotify2(sm->addr_notify_handle); |
|
|
|
|
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "NotifyRouteChange2 registered: handle=%p", sm->route_notify_handle); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
instance->socket_monitor = sm; |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor initialized via IP Helper"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor not available on this platform"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void socket_monitor_destroy(struct UTUN_INSTANCE* instance) { |
|
|
|
void socket_monitor_destroy(struct UTUN_INSTANCE* instance) { |
|
|
|
if (!instance) return; |
|
|
|
if (!instance) return; |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "destroying socket monitor"); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "destroying socket monitor"); |
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
return; |
|
|
|
#ifdef __linux__ |
|
|
|
#else |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)instance->socket_monitor; |
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)instance->socket_monitor; |
|
|
|
if (!sm) return; |
|
|
|
if (!sm) return; |
|
|
|
instance->socket_monitor = NULL; |
|
|
|
instance->socket_monitor = NULL; |
|
|
|
@ -257,5 +439,28 @@ void socket_monitor_destroy(struct UTUN_INSTANCE* instance) { |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor destroyed: nl_sock=%d addr_changes=%u link_changes=%u route_changes=%u socket_updates=%u", |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor destroyed: nl_sock=%d addr_changes=%u link_changes=%u route_changes=%u socket_updates=%u", |
|
|
|
sm->nl_sock, sm->addr_changes, sm->link_changes, sm->route_changes, sm->socket_updates); |
|
|
|
sm->nl_sock, sm->addr_changes, sm->link_changes, sm->route_changes, sm->socket_updates); |
|
|
|
u_free(sm); |
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)instance->socket_monitor; |
|
|
|
|
|
|
|
if (!sm) return; |
|
|
|
|
|
|
|
instance->socket_monitor = NULL; |
|
|
|
|
|
|
|
uasync_remove_socket(instance->ua, sm->uasync_handle); |
|
|
|
|
|
|
|
close(sm->route_sock); |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor destroyed: route_sock=%d addr_changes=%u link_changes=%u route_changes=%u socket_updates=%u", |
|
|
|
|
|
|
|
sm->route_sock, sm->addr_changes, sm->link_changes, sm->route_changes, sm->socket_updates); |
|
|
|
|
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(_WIN32) |
|
|
|
|
|
|
|
struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)instance->socket_monitor; |
|
|
|
|
|
|
|
if (!sm) return; |
|
|
|
|
|
|
|
instance->socket_monitor = NULL; |
|
|
|
|
|
|
|
CancelMibChangeNotify2(sm->addr_notify_handle); |
|
|
|
|
|
|
|
CancelMibChangeNotify2(sm->route_notify_handle); |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket monitor destroyed: addr_changes=%u link_changes=%u route_changes=%u socket_updates=%u", |
|
|
|
|
|
|
|
sm->addr_changes, sm->link_changes, sm->route_changes, sm->socket_updates); |
|
|
|
|
|
|
|
u_free(sm); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
(void)instance; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|