From 8fd710578d596fe0e34262ca6079852fb493c6ad Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Mon, 3 Oct 2011 11:13:45 +0000 Subject: [PATCH] Set 0x02 in sa_flags when packet is from a local (IPX) IP and free the hosts list while cleaning up. --- changes.txt | 2 ++ src/config.h | 1 + src/ipxwrapper.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++- src/ipxwrapper.h | 6 +--- src/winsock.c | 4 ++- 5 files changed, 97 insertions(+), 7 deletions(-) diff --git a/changes.txt b/changes.txt index e4f00f6..25334f3 100644 --- a/changes.txt +++ b/changes.txt @@ -10,6 +10,8 @@ Version 0.3.1: Update: Include thread ID with every log message. Feature: Implemented IPX_EXTENDED_ADDRESS socket option. + + Bugfix: Deallocate hosts list in DLL cleanup. Version 0.3: Cleanup: Moved certain library functions out of ipxwrapper.c and tidied up. diff --git a/src/config.h b/src/config.h index cd8b251..98fb1fb 100644 --- a/src/config.h +++ b/src/config.h @@ -21,6 +21,7 @@ #define DEFAULT_PORT 54792 #define DEFAULT_CONTROL_PORT 54793 #define TTL 60 +#define IFACE_TTL 10 struct reg_value { unsigned char ipx_net[4]; diff --git a/src/ipxwrapper.c b/src/ipxwrapper.c index faa5242..7f1a303 100644 --- a/src/ipxwrapper.c +++ b/src/ipxwrapper.c @@ -37,15 +37,25 @@ dll = NULL;\ } +struct ipaddr_list { + uint32_t ipaddr; + struct ipaddr_list *next; +}; + ipx_socket *sockets = NULL; -ipx_host *hosts = NULL; SOCKET send_fd = -1; struct reg_global global_conf; struct rclient g_rclient; +static ipx_host *hosts = NULL; + static CRITICAL_SECTION sockets_cs; static CRITICAL_SECTION hosts_cs; +static CRITICAL_SECTION addrs_cs; + +static struct ipaddr_list *local_addrs = NULL; +static time_t local_updated = 0; #define INIT_CS(cs) if(!init_cs(cs, &initialised_cs)) { return FALSE; } @@ -59,6 +69,9 @@ static BOOL init_cs(CRITICAL_SECTION *cs, int *counter) { return TRUE; } +static void free_hosts(void); +static void free_local_ips(void); + BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { static int initialised_cs = 0; @@ -80,6 +93,7 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { INIT_CS(&sockets_cs); INIT_CS(&hosts_cs); + INIT_CS(&addrs_cs); WSADATA wsdata; int err = WSAStartup(MAKEWORD(1,1), &wsdata); @@ -121,9 +135,13 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { rclient_stop(&g_rclient); + free_local_ips(); + free_hosts(); + WSACleanup(); switch(initialised_cs) { + case 3: DeleteCriticalSection(&addrs_cs); case 2: DeleteCriticalSection(&hosts_cs); case 1: DeleteCriticalSection(&sockets_cs); default: break; @@ -246,3 +264,74 @@ ipx_host *find_host(const unsigned char *net, const unsigned char *node) { LeaveCriticalSection(&hosts_cs); return hptr; } + +static void free_hosts(void) { + ipx_host *p = hosts, *d; + + while(p) { + d = p; + p = p->next; + + free(d); + } + + hosts = NULL; +} + +/* Check if supplied IP (network byte order) is a local address */ +BOOL ip_is_local(uint32_t ipaddr) { + EnterCriticalSection(&addrs_cs); + + if(local_updated + IFACE_TTL < time(NULL)) { + /* TODO: Use all local IPs rather than just the ones with associated IPX addresses? */ + + struct ipx_interface *ifaces = get_interfaces(-1); + struct ipx_interface *i = ifaces; + + while(i) { + struct ipaddr_list *nn = malloc(sizeof(struct ipaddr_list)); + if(!nn) { + log_printf("Out of memory! Can't allocate ipaddr_list structure!"); + break; + } + + nn->ipaddr = i->ipaddr; + nn->next = local_addrs; + local_addrs = nn; + + i = i->next; + } + + free_interfaces(ifaces); + + local_updated = time(NULL); + } + + struct ipaddr_list *p = local_addrs; + + while(p) { + if(p->ipaddr == ipaddr) { + LeaveCriticalSection(&addrs_cs); + return TRUE; + } + + p = p->next; + } + + LeaveCriticalSection(&addrs_cs); + return FALSE; +} + +/* Free local IP address list */ +static void free_local_ips(void) { + struct ipaddr_list *p = local_addrs, *d; + + while(p) { + d = p; + p = p->next; + + free(d); + } + + local_addrs = NULL; +} diff --git a/src/ipxwrapper.h b/src/ipxwrapper.h index 13d8a32..6fb226f 100644 --- a/src/ipxwrapper.h +++ b/src/ipxwrapper.h @@ -97,20 +97,16 @@ struct ipx_host { }; extern ipx_socket *sockets; -extern ipx_host *hosts; extern SOCKET send_fd; extern struct reg_global global_conf; extern struct rclient g_rclient; -extern HMODULE winsock2_dll; -extern HMODULE mswsock_dll; -extern HMODULE wsock32_dll; - ipx_socket *get_socket(SOCKET fd); void lock_sockets(void); void unlock_sockets(void); ipx_host *find_host(const unsigned char *net, const unsigned char *node); void add_host(const unsigned char *net, const unsigned char *node, uint32_t ipaddr); +BOOL ip_is_local(uint32_t ipaddr); INT APIENTRY r_EnumProtocolsA(LPINT,LPVOID,LPDWORD); INT APIENTRY r_EnumProtocolsW(LPINT,LPVOID,LPDWORD); diff --git a/src/winsock.c b/src/winsock.c index 6e56649..a859418 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -377,7 +377,9 @@ static int recv_packet(ipx_socket *sockptr, char *buf, int bufsize, int flags, s flags |= 0x01; } - /* TODO: Set 0x02 if packet was sent from local machine */ + if(ip_is_local(rp_header->src_ipaddr)) { + flags |= 0x02; + } }else{ log_printf("IPX_EXTENDED_ADDRESS enabled, but recvfrom called with addrlen %d", addrlen); }