2008-12-09 21:36:07 +00:00
|
|
|
/* ipxwrapper - Library functions
|
2023-09-10 08:47:48 +01:00
|
|
|
* Copyright (C) 2008-2023 Daniel Collins <solemnwarning@solemnwarning.net>
|
2008-12-09 21:36:07 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 as published by
|
|
|
|
* the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
|
|
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2014-06-25 23:19:37 +01:00
|
|
|
#define WINSOCK_API_LINKAGE
|
|
|
|
|
2008-12-09 21:36:07 +00:00
|
|
|
#include <winsock2.h>
|
2014-06-25 23:19:37 +01:00
|
|
|
#include <windows.h>
|
2008-12-09 21:36:07 +00:00
|
|
|
#include <wsipx.h>
|
|
|
|
#include <nspapi.h>
|
|
|
|
#include <iphlpapi.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdint.h>
|
2011-04-23 23:42:14 +00:00
|
|
|
#include <time.h>
|
2008-12-09 21:36:07 +00:00
|
|
|
|
|
|
|
#include "ipxwrapper.h"
|
2011-08-28 21:27:06 +00:00
|
|
|
#include "common.h"
|
2021-01-20 20:51:16 +00:00
|
|
|
#include "funcprof.h"
|
2011-08-29 13:21:18 +00:00
|
|
|
#include "interface.h"
|
2011-09-07 20:03:16 +00:00
|
|
|
#include "router.h"
|
2012-10-20 18:06:11 +00:00
|
|
|
#include "addrcache.h"
|
2008-12-09 21:36:07 +00:00
|
|
|
|
2011-11-14 02:21:29 +00:00
|
|
|
extern const char *version_string;
|
|
|
|
extern const char *compile_time;
|
|
|
|
|
2011-10-03 11:13:45 +00:00
|
|
|
struct ipaddr_list {
|
|
|
|
uint32_t ipaddr;
|
|
|
|
struct ipaddr_list *next;
|
|
|
|
};
|
|
|
|
|
2008-12-09 21:36:07 +00:00
|
|
|
ipx_socket *sockets = NULL;
|
2012-10-21 10:26:52 +00:00
|
|
|
main_config_t main_config;
|
2008-12-09 21:36:07 +00:00
|
|
|
|
2011-09-08 00:20:34 +00:00
|
|
|
static CRITICAL_SECTION sockets_cs;
|
|
|
|
|
2014-01-25 23:33:11 +00:00
|
|
|
typedef ULONGLONG WINAPI (*GetTickCount64_t)(void);
|
|
|
|
static HMODULE kernel32 = NULL;
|
|
|
|
|
2021-01-20 20:51:16 +00:00
|
|
|
struct FuncStats ipxwrapper_fstats[] = {
|
|
|
|
#define FPROF_DECL(func) { #func },
|
|
|
|
#include "ipxwrapper_prof_defs.h"
|
|
|
|
#undef FPROF_DECL
|
|
|
|
};
|
|
|
|
|
|
|
|
const unsigned int ipxwrapper_fstats_size = sizeof(ipxwrapper_fstats) / sizeof(*ipxwrapper_fstats);
|
|
|
|
|
2023-11-21 20:18:19 +00:00
|
|
|
unsigned int send_packets = 0, send_bytes = 0; /* Sent from emulated socket */
|
|
|
|
unsigned int recv_packets = 0, recv_bytes = 0; /* Forwarded to emulated socket */
|
|
|
|
|
2012-10-20 18:06:11 +00:00
|
|
|
static void init_cs(CRITICAL_SECTION *cs)
|
|
|
|
{
|
|
|
|
if(!InitializeCriticalSectionAndSpinCount(cs, 0x80000000))
|
|
|
|
{
|
2011-11-16 21:32:59 +00:00
|
|
|
log_printf(LOG_ERROR, "Failed to initialise critical section: %s", w32_error(GetLastError()));
|
2012-10-20 18:06:11 +00:00
|
|
|
abort();
|
2011-09-08 00:20:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-24 16:06:41 +01:00
|
|
|
static HANDLE prof_thread_handle = NULL;
|
|
|
|
static HANDLE prof_thread_exit = NULL;
|
|
|
|
|
2023-11-21 20:18:19 +00:00
|
|
|
static void report_packet_stats(void)
|
|
|
|
{
|
|
|
|
unsigned int my_send_packets = __atomic_exchange_n(&send_packets, 0, __ATOMIC_RELAXED);
|
|
|
|
unsigned int my_send_bytes = __atomic_exchange_n(&send_bytes, 0, __ATOMIC_RELAXED);
|
|
|
|
|
|
|
|
unsigned int my_recv_packets = __atomic_exchange_n(&recv_packets, 0, __ATOMIC_RELAXED);
|
|
|
|
unsigned int my_recv_bytes = __atomic_exchange_n(&recv_bytes, 0, __ATOMIC_RELAXED);
|
|
|
|
|
|
|
|
log_printf(LOG_INFO, "IPX sockets sent %u packets (%u bytes)", my_send_packets, my_send_bytes);
|
|
|
|
log_printf(LOG_INFO, "IPX sockets received %u packets (%u bytes)", my_recv_packets, my_recv_bytes);
|
|
|
|
}
|
|
|
|
|
2019-08-24 16:06:41 +01:00
|
|
|
static DWORD WINAPI prof_thread_main(LPVOID lpParameter)
|
|
|
|
{
|
|
|
|
static const int PROF_INTERVAL_MS = 10000;
|
|
|
|
|
|
|
|
while(WaitForSingleObject(prof_thread_exit, PROF_INTERVAL_MS) == WAIT_TIMEOUT)
|
|
|
|
{
|
|
|
|
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
|
2021-01-20 20:51:16 +00:00
|
|
|
fprof_report("ipxwrapper.dll", ipxwrapper_fstats, ipxwrapper_fstats_size);
|
2023-11-21 20:18:19 +00:00
|
|
|
report_packet_stats();
|
2019-08-24 16:06:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-18 02:47:51 +01:00
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
2012-11-11 15:54:54 +00:00
|
|
|
{
|
2017-06-18 02:47:51 +01:00
|
|
|
if(fdwReason == DLL_PROCESS_ATTACH)
|
2012-11-11 15:54:54 +00:00
|
|
|
{
|
2019-08-24 16:06:41 +01:00
|
|
|
fprof_init(stub_fstats, NUM_STUBS);
|
2021-01-20 20:51:16 +00:00
|
|
|
fprof_init(ipxwrapper_fstats, ipxwrapper_fstats_size);
|
2019-08-23 20:25:14 +01:00
|
|
|
|
2011-09-18 14:36:24 +00:00
|
|
|
log_open("ipxwrapper.log");
|
2008-12-09 21:36:07 +00:00
|
|
|
|
2011-11-16 21:32:59 +00:00
|
|
|
log_printf(LOG_INFO, "IPXWrapper %s", version_string);
|
|
|
|
log_printf(LOG_INFO, "Compiled at %s", compile_time);
|
2011-11-14 02:21:29 +00:00
|
|
|
|
2012-11-11 15:54:54 +00:00
|
|
|
if(!getenv("SystemRoot"))
|
|
|
|
{
|
2012-05-10 01:18:25 +00:00
|
|
|
log_printf(LOG_WARNING, "SystemRoot is not set in the environment");
|
|
|
|
|
|
|
|
char env[268] = "SystemRoot=";
|
|
|
|
GetSystemWindowsDirectory(env+11, 256);
|
|
|
|
|
|
|
|
log_printf(LOG_INFO, "Setting SystemRoot to '%s'", env+11);
|
|
|
|
_putenv(env);
|
|
|
|
}
|
|
|
|
|
2012-10-21 10:26:52 +00:00
|
|
|
main_config = get_main_config();
|
2012-10-28 15:53:54 +00:00
|
|
|
min_log_level = main_config.log_level;
|
2021-08-21 14:42:49 +01:00
|
|
|
ipx_encap_type = main_config.encap_type;
|
2012-10-21 10:26:52 +00:00
|
|
|
|
2013-12-11 00:53:30 +00:00
|
|
|
if(main_config.fw_except)
|
|
|
|
{
|
|
|
|
log_printf(LOG_INFO, "Adding exception to Windows Firewall");
|
|
|
|
add_self_to_firewall();
|
|
|
|
}
|
|
|
|
|
2012-10-20 18:06:11 +00:00
|
|
|
addr_cache_init();
|
|
|
|
|
2012-11-03 01:21:25 +00:00
|
|
|
ipx_interfaces_init();
|
|
|
|
|
2012-10-20 18:06:11 +00:00
|
|
|
init_cs(&sockets_cs);
|
2008-12-09 21:36:07 +00:00
|
|
|
|
|
|
|
WSADATA wsdata;
|
|
|
|
int err = WSAStartup(MAKEWORD(1,1), &wsdata);
|
2012-11-11 15:54:54 +00:00
|
|
|
if(err)
|
|
|
|
{
|
2011-11-16 21:32:59 +00:00
|
|
|
log_printf(LOG_ERROR, "Failed to initialize winsock: %s", w32_error(err));
|
2008-12-09 21:36:07 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-11-11 15:54:54 +00:00
|
|
|
router_init();
|
2019-08-24 16:06:41 +01:00
|
|
|
|
2023-11-19 21:49:52 +00:00
|
|
|
if(main_config.profile)
|
2019-08-24 16:06:41 +01:00
|
|
|
{
|
2023-11-19 21:49:52 +00:00
|
|
|
stubs_enable_profile = true;
|
2019-08-24 16:06:41 +01:00
|
|
|
|
2023-11-19 21:49:52 +00:00
|
|
|
prof_thread_exit = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
|
if(prof_thread_exit != NULL)
|
2019-08-24 16:06:41 +01:00
|
|
|
{
|
2023-11-19 21:49:52 +00:00
|
|
|
prof_thread_handle = CreateThread(
|
|
|
|
NULL, /* lpThreadAttributes */
|
|
|
|
0, /* dwStackSize */
|
|
|
|
&prof_thread_main, /* lpStartAddress */
|
|
|
|
NULL, /* lpParameter */
|
|
|
|
0, /* dwCreationFlags */
|
|
|
|
NULL); /* lpThreadId */
|
|
|
|
|
|
|
|
if(prof_thread_handle == NULL)
|
|
|
|
{
|
|
|
|
log_printf(LOG_ERROR,
|
|
|
|
"Unable to create prof_thread_main thread: %s",
|
|
|
|
w32_error(GetLastError()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
2019-08-24 16:06:41 +01:00
|
|
|
log_printf(LOG_ERROR,
|
2023-11-19 21:49:52 +00:00
|
|
|
"Unable to create prof_thread_exit event object: %s",
|
2019-08-24 16:06:41 +01:00
|
|
|
w32_error(GetLastError()));
|
|
|
|
}
|
|
|
|
}
|
2012-11-11 15:54:54 +00:00
|
|
|
}
|
2017-06-18 02:47:51 +01:00
|
|
|
else if(fdwReason == DLL_PROCESS_DETACH)
|
2012-11-11 15:54:54 +00:00
|
|
|
{
|
2017-06-18 02:47:51 +01:00
|
|
|
/* When the "lpvReserved" parameter is non-NULL, the process is terminating rather
|
|
|
|
* than the DLL being unloaded dynamically and any threads will have been terminated
|
|
|
|
* at unknown points, meaning any global data may be in an inconsistent state and we
|
|
|
|
* cannot (safely) clean up. MSDN states we should do nothing.
|
|
|
|
*/
|
|
|
|
if(lpvReserved != NULL)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2019-08-24 16:06:41 +01:00
|
|
|
if(prof_thread_exit != NULL)
|
|
|
|
{
|
|
|
|
SetEvent(prof_thread_exit);
|
|
|
|
|
|
|
|
if(prof_thread_handle != NULL)
|
|
|
|
{
|
|
|
|
WaitForSingleObject(prof_thread_handle, INFINITE);
|
|
|
|
|
|
|
|
CloseHandle(prof_thread_handle);
|
|
|
|
prof_thread_handle = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle(prof_thread_exit);
|
|
|
|
prof_thread_exit = NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-11 15:54:54 +00:00
|
|
|
router_cleanup();
|
2008-12-09 21:36:07 +00:00
|
|
|
|
2011-09-08 00:20:34 +00:00
|
|
|
WSACleanup();
|
|
|
|
|
2012-10-20 18:06:11 +00:00
|
|
|
DeleteCriticalSection(&sockets_cs);
|
2011-08-29 13:15:10 +00:00
|
|
|
|
2012-11-03 01:21:25 +00:00
|
|
|
ipx_interfaces_cleanup();
|
|
|
|
|
2012-10-20 18:06:11 +00:00
|
|
|
addr_cache_cleanup();
|
|
|
|
|
2011-09-11 13:28:41 +00:00
|
|
|
unload_dlls();
|
2011-07-13 22:56:19 +00:00
|
|
|
|
2023-11-19 21:49:52 +00:00
|
|
|
if(main_config.profile)
|
|
|
|
{
|
|
|
|
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
|
|
|
|
fprof_report("ipxwrapper.dll", ipxwrapper_fstats, ipxwrapper_fstats_size);
|
2023-11-21 20:18:19 +00:00
|
|
|
|
|
|
|
report_packet_stats();
|
2023-11-19 21:49:52 +00:00
|
|
|
}
|
2019-08-24 16:06:41 +01:00
|
|
|
|
2011-07-13 22:56:19 +00:00
|
|
|
log_close();
|
2014-01-25 23:33:11 +00:00
|
|
|
|
|
|
|
if(kernel32)
|
|
|
|
{
|
|
|
|
FreeLibrary(kernel32);
|
|
|
|
kernel32 = NULL;
|
|
|
|
}
|
2019-08-23 20:25:14 +01:00
|
|
|
|
2021-01-20 20:51:16 +00:00
|
|
|
fprof_cleanup(ipxwrapper_fstats, ipxwrapper_fstats_size);
|
2019-08-24 16:06:41 +01:00
|
|
|
fprof_cleanup(stub_fstats, NUM_STUBS);
|
2008-12-09 21:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-11-11 20:54:43 +00:00
|
|
|
/* Lock the sockets table and search for one by file descriptor.
|
2023-09-10 08:47:48 +01:00
|
|
|
*
|
2012-11-11 20:54:43 +00:00
|
|
|
* Returns an ipx_socket pointer on success, unlocks the sockets table and
|
|
|
|
* returns NULL if no match is found.
|
2008-12-09 21:36:07 +00:00
|
|
|
*/
|
2012-11-11 20:54:43 +00:00
|
|
|
ipx_socket *get_socket(SOCKET sockfd)
|
|
|
|
{
|
2011-09-08 00:20:34 +00:00
|
|
|
lock_sockets();
|
2008-12-09 21:36:07 +00:00
|
|
|
|
2012-11-11 20:54:43 +00:00
|
|
|
ipx_socket *sock;
|
|
|
|
HASH_FIND_INT(sockets, &sockfd, sock);
|
2008-12-09 21:36:07 +00:00
|
|
|
|
2012-11-11 20:54:43 +00:00
|
|
|
if(!sock)
|
|
|
|
{
|
2011-09-08 00:20:34 +00:00
|
|
|
unlock_sockets();
|
2008-12-09 21:36:07 +00:00
|
|
|
}
|
|
|
|
|
2012-11-11 20:54:43 +00:00
|
|
|
return sock;
|
2008-12-09 21:36:07 +00:00
|
|
|
}
|
|
|
|
|
2023-09-10 08:47:48 +01:00
|
|
|
/* Like get_socket(), but also calls wait_for_ready() if an IPX socket was found. */
|
|
|
|
ipx_socket *get_socket_wait_for_ready(SOCKET sockfd, int timeout_ms)
|
|
|
|
{
|
|
|
|
ipx_socket *sock = get_socket(sockfd);
|
|
|
|
|
|
|
|
if(sock)
|
|
|
|
{
|
|
|
|
unlock_sockets();
|
|
|
|
wait_for_ready(timeout_ms);
|
|
|
|
|
|
|
|
sock = get_socket(sockfd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sock;
|
|
|
|
lock_sockets();
|
|
|
|
}
|
|
|
|
|
2008-12-09 21:36:07 +00:00
|
|
|
/* Lock the mutex */
|
2012-11-11 20:54:43 +00:00
|
|
|
void lock_sockets(void)
|
|
|
|
{
|
2021-01-20 20:51:16 +00:00
|
|
|
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS_lock_sockets]));
|
2011-09-08 00:20:34 +00:00
|
|
|
EnterCriticalSection(&sockets_cs);
|
2008-12-09 21:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the mutex */
|
2012-11-11 20:54:43 +00:00
|
|
|
void unlock_sockets(void)
|
|
|
|
{
|
2011-09-08 00:20:34 +00:00
|
|
|
LeaveCriticalSection(&sockets_cs);
|
2008-12-09 21:36:07 +00:00
|
|
|
}
|
2014-01-25 23:33:11 +00:00
|
|
|
|
|
|
|
uint64_t get_ticks(void)
|
|
|
|
{
|
|
|
|
static GetTickCount64_t GetTickCount64 = NULL;
|
|
|
|
|
|
|
|
if(!kernel32 && (kernel32 = LoadLibrary("kernel32.dll")))
|
|
|
|
{
|
|
|
|
GetTickCount64 = (GetTickCount64_t)(GetProcAddress(kernel32, "GetTickCount64"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if(GetTickCount64)
|
|
|
|
{
|
|
|
|
return GetTickCount64();
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
return GetTickCount();
|
|
|
|
}
|
|
|
|
}
|