From ebcf1673e2552d327032869b76c052458b791052 Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Sun, 21 Oct 2012 10:26:52 +0000 Subject: [PATCH] REFACTOR ALL THE THINGS. --- Makefile | 4 +- src/addr.c | 133 +++++++++++++++++++++++++++++ src/addr.h | 50 +++++++++++ src/addrcache.c | 18 ++-- src/addrcache.h | 4 +- src/common.c | 129 ++++++++++++++-------------- src/common.h | 28 +++---- src/config.c | 133 +++++++++++++++++++++++++++++ src/config.h | 40 +++++++-- src/directplay.c | 13 +-- src/interface.c | 191 ++++++++++++++++++++---------------------- src/interface.h | 18 ++-- src/ipxconfig.cpp | 5 +- src/ipxwrapper.c | 17 +--- src/ipxwrapper.h | 2 +- src/mswsock_stubs.txt | 1 - src/router-exe.c | 13 +-- src/router.c | 28 ++++--- src/stubdll.c | 13 +-- src/winsock.c | 22 ++--- 20 files changed, 591 insertions(+), 271 deletions(-) create mode 100644 src/addr.c create mode 100644 src/addr.h create mode 100644 src/config.c diff --git a/Makefile b/Makefile index e11fe0d..b6516bf 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ CXXFLAGS := $(CFLAGS) VERSION := r$(shell svn info | grep Revision | sed -e 's/.*: //') IPXWRAPPER_DEPS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \ - src/interface.o src/router.o src/ipxwrapper.def src/addrcache.o + src/interface.o src/router.o src/ipxwrapper.def src/addrcache.o src/config.o src/addr.o BIN_FILES := changes.txt license.txt readme.txt ipxwrapper.dll mswsock.dll wsock32.dll ipxconfig.exe \ ipxrouter.exe dpwsockx.dll directplay-win32.reg directplay-win64.reg @@ -69,7 +69,7 @@ ipxconfig.exe: src/ipxconfig.cpp icons/ipxconfig.o dpwsockx.dll: src/directplay.o src/log.o src/dpwsockx_stubs.o src/common.o $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o dpwsockx.dll src/directplay.o src/log.o src/common.o src/dpwsockx_stubs.o src/dpwsockx.def -lwsock32 -ipxrouter.exe: src/router-exe.o src/router.o src/interface.o src/common.o src/log.o icons/ipxrouter.o +ipxrouter.exe: src/router-exe.o src/router.o src/interface.o src/common.o src/log.o icons/ipxrouter.o src/config.o src/addr.o $(CC) $(CFLAGS) -static-libgcc -mwindows -o ipxrouter.exe $^ -lws2_32 -liphlpapi src/ipxwrapper_stubs.s: src/ipxwrapper_stubs.txt diff --git a/src/addr.c b/src/addr.c new file mode 100644 index 0000000..bce9999 --- /dev/null +++ b/src/addr.c @@ -0,0 +1,133 @@ +/* ipxwrapper - Address manipulation functions + * Copyright (C) 2012 Daniel Collins + * + * 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. +*/ + +#include +#include +#include +#include +#include + +#include "addr.h" +#include "common.h" + +addr32_t addr32_in(const void *src) +{ + addr32_t buf = 0; + memcpy(&buf, src, 4); + + return buf; +} + +/* Write out a 32-bit address in network byte order. */ +void *addr32_out(void *dest, addr32_t src) +{ + return memcpy(dest, &src, 4); +} + +/* Convert a 32-bit address to a string in the format XX:XX:XX:XX */ +char *addr32_string(char *buf, addr32_t addr) +{ + unsigned char c[6]; + addr32_out(c, addr); + + sprintf( + buf, + + "%02X:%02X:%02X:%02X", + + (unsigned int)(c[0]), + (unsigned int)(c[1]), + (unsigned int)(c[2]), + (unsigned int)(c[3]) + ); + + return buf; +} + +/* Read a 32-bit network address from the registry. + * Returns default_value upon failure. +*/ +addr32_t reg_get_addr32(HKEY key, const char *name, addr32_t default_value) +{ + unsigned char buf[4]; + reg_get_bin(key, name, buf, 4, &default_value); + + return addr32_in(buf); +} + +addr48_t addr48_in(const void *src) +{ + addr48_t buf = 0; + memcpy(((char*)&buf) + 2, src, 6); + + return buf; +} + +/* Write out a 48-bit address in network byte order. */ +void *addr48_out(void *dest, addr48_t src) +{ + return memcpy(dest, ((char*)&src) + 2, 6); +} + +/* Convert a 48-bit address to a string in the format XX:XX:XX:XX:XX:XX */ +char *addr48_string(char *buf, addr48_t addr) +{ + unsigned char c[6]; + addr48_out(c, addr); + + sprintf( + buf, + + "%02X:%02X:%02X:%02X:%02X:%02X", + + (unsigned int)(c[0]), + (unsigned int)(c[1]), + (unsigned int)(c[2]), + (unsigned int)(c[3]), + (unsigned int)(c[4]), + (unsigned int)(c[5]) + ); + + return buf; +} + +/* Read a 48-bit network address from the registry. + * Returns default_value upon failure. +*/ +addr48_t reg_get_addr48(HKEY key, const char *name, addr48_t default_value) +{ + unsigned char buf[6]; + reg_get_bin(key, name, buf, 6, &default_value); + + return addr48_in(buf); +} + +/* Format an IPX address as a string. + * + * The socket number should be in network byte order and the supplied buffer + * must be at least IPX_SADDR_SIZE bytes long. +*/ +void ipx_to_string(char *buf, addr32_t net, addr48_t node, uint16_t sock) +{ + addr32_string(buf, net); + buf[17] = '/'; + + addr48_string(buf + 18, node); + buf[29] = '/'; + + sprintf(buf + 30, "%hu", ntohs(sock)); +} diff --git a/src/addr.h b/src/addr.h new file mode 100644 index 0000000..c7f9021 --- /dev/null +++ b/src/addr.h @@ -0,0 +1,50 @@ +/* ipxwrapper - Address manipulation functions + * Copyright (C) 2012 Daniel Collins + * + * 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. +*/ + +#ifndef IPXWRAPPER_ADDR_H +#define IPXWRAPPER_ADDR_H + +#include + +typedef uint32_t addr32_t; +typedef uint64_t addr48_t; + +#define ADDR32_STRING_SIZE 12 + +addr32_t addr32_in(const void *src); +void *addr32_out(void *dest, addr32_t src); +char *addr32_string(char *buf, addr32_t addr); + +addr32_t reg_get_addr32(HKEY key, const char *name, addr32_t default_value); + +#define ADDR48_STRING_SIZE 18 + +addr48_t addr48_in(const void *src); +void *addr48_out(void *dest, addr48_t src); +char *addr48_string(char *buf, addr48_t addr); + +addr48_t reg_get_addr48(HKEY key, const char *name, addr48_t default_value); + +#define IPX_SADDR_SIZE 36 + +#define IPX_STRING_ADDR(var, net, node, sock) \ + char var[IPX_SADDR_SIZE]; \ + ipx_to_string(var, net, node, sock); + +void ipx_to_string(char *buf, addr32_t net, addr48_t node, uint16_t sock); + +#endif /* !IPXWRAPPER_ADDR_H */ diff --git a/src/addrcache.c b/src/addrcache.c index 13faa5c..9d9fbaf 100644 --- a/src/addrcache.c +++ b/src/addrcache.c @@ -26,8 +26,8 @@ #include "common.h" struct host_table_key { - netnum_t netnum; - nodenum_t nodenum; + addr32_t netnum; + addr48_t nodenum; }; struct host_table { @@ -63,13 +63,13 @@ static void host_table_unlock(void) /* Search the host table for a node with the given net/node pair. * Returns NULL on failure. */ -static host_table_t *host_table_find(const netnum_t net, const nodenum_t node) +static host_table_t *host_table_find(addr32_t net, addr48_t node) { host_table_key_t key; memset(&key, 0, sizeof(key)); - memcpy(key.netnum, net, sizeof(netnum_t)); - memcpy(key.nodenum, node, sizeof(nodenum_t)); + key.netnum = net; + key.nodenum = node; host_table_t *host; @@ -118,7 +118,7 @@ void addr_cache_cleanup(void) * Writes a sockaddr structure and addrlen to the provided pointers. Returns * true if a cached address was found, false otherwise. */ -int addr_cache_get(SOCKADDR_STORAGE *addr, size_t *addrlen, netnum_t net, nodenum_t node, uint16_t sock) +int addr_cache_get(SOCKADDR_STORAGE *addr, size_t *addrlen, addr32_t net, addr48_t node, uint16_t sock) { host_table_lock(); @@ -146,7 +146,7 @@ int addr_cache_get(SOCKADDR_STORAGE *addr, size_t *addrlen, netnum_t net, nodenu * The given sockaddr structure will be copied and may be deallocated as soon as * this function returns. */ -void addr_cache_set(const struct sockaddr *addr, size_t addrlen, netnum_t net, nodenum_t node, uint16_t sock) +void addr_cache_set(const struct sockaddr *addr, size_t addrlen, addr32_t net, addr48_t node, uint16_t sock) { host_table_lock(); @@ -168,8 +168,8 @@ void addr_cache_set(const struct sockaddr *addr, size_t addrlen, netnum_t net, n memset(host, 0, sizeof(host_table_t)); - memcpy(host->key.netnum, net, sizeof(netnum_t)); - memcpy(host->key.nodenum, node, sizeof(nodenum_t)); + host->key.netnum = net; + host->key.nodenum = node; HASH_ADD(hh, host_table, key, sizeof(host->key), host); } diff --git a/src/addrcache.h b/src/addrcache.h index c293d1a..eb6da99 100644 --- a/src/addrcache.h +++ b/src/addrcache.h @@ -29,7 +29,7 @@ extern unsigned int addr_cache_ttl; void addr_cache_init(void); void addr_cache_cleanup(void); -int addr_cache_get(SOCKADDR_STORAGE *addr, size_t *addrlen, netnum_t net, nodenum_t node, uint16_t sock); -void addr_cache_set(const struct sockaddr *addr, size_t addrlen, netnum_t net, nodenum_t node, uint16_t sock); +int addr_cache_get(SOCKADDR_STORAGE *addr, size_t *addrlen, addr32_t net, addr48_t node, uint16_t sock); +void addr_cache_set(const struct sockaddr *addr, size_t addrlen, addr32_t net, addr48_t node, uint16_t sock); #endif /* !_ADDRCACHE_H */ diff --git a/src/common.c b/src/common.c index 5f7d56f..d8bcc80 100644 --- a/src/common.c +++ b/src/common.c @@ -21,8 +21,6 @@ #include "common.h" #include "config.h" -HKEY regkey = NULL; - enum ipx_log_level min_log_level = LOG_INFO; static const char *dll_names[] = { @@ -45,82 +43,83 @@ const char *w32_error(DWORD errnum) { return buf; } -/* Format an IPX address as a string. - * - * The socket number should be in network byte order and the supplied buffer - * must be at least IPX_SADDR_SIZE bytes long. -*/ -void ipx_to_string(char *buf, const netnum_t net, const nodenum_t node, uint16_t sock) +HKEY reg_open_main(bool readwrite) { - /* World's ugliest use of sprintf? */ - - sprintf( - buf, - - "%02X:%02X:%02X:%02X/%02X:%02X:%02X:%02X:%02X:%02X/%hu", - - (unsigned int)(unsigned char)(net[0]), - (unsigned int)(unsigned char)(net[1]), - (unsigned int)(unsigned char)(net[2]), - (unsigned int)(unsigned char)(net[3]), - - (unsigned int)(unsigned char)(node[0]), - (unsigned int)(unsigned char)(node[1]), - (unsigned int)(unsigned char)(node[2]), - (unsigned int)(unsigned char)(node[3]), - (unsigned int)(unsigned char)(node[4]), - (unsigned int)(unsigned char)(node[5]), - - ntohs(sock) - ); + return reg_open_subkey(HKEY_CURRENT_USER, "Software\\IPXWrapper", readwrite); } -BOOL reg_open(REGSAM access) { - int err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\IPXWrapper", 0, access, ®key); +HKEY reg_open_subkey(HKEY parent, const char *path, bool readwrite) +{ + if(parent == NULL) + { + return NULL; + } - if(err != ERROR_SUCCESS) { + HKEY key; + int err; + + if(readwrite) + { + err = RegCreateKeyEx(parent, path, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &key, NULL); + } + else{ + err = RegOpenKeyEx(parent, path, 0, KEY_READ, &key); + } + + if(err != ERROR_SUCCESS) + { log_printf(LOG_ERROR, "Could not open registry: %s", w32_error(err)); - regkey = NULL; + return NULL; + } + + return key; +} + +void reg_close(HKEY key) +{ + if(key != NULL) + { + RegCloseKey(key); + } +} + +bool reg_get_bin(HKEY key, const char *name, void *buf, size_t size, const void *default_value) +{ + if(key != NULL) + { + DWORD bs = size; + int err = RegQueryValueEx(key, name, NULL, NULL, (BYTE*)buf, &bs); - return FALSE; - } - - return TRUE; -} - -void reg_close(void) { - if(regkey) { - RegCloseKey(regkey); - regkey = NULL; - } -} - -char reg_get_char(const char *val_name, char default_val) { - char buf; - return reg_get_bin(val_name, &buf, 1) == 1 ? buf : default_val; -} - -DWORD reg_get_bin(const char *val_name, void *buf, DWORD size) { - if(!regkey) { - return 0; - } - - int err = RegQueryValueEx(regkey, val_name, NULL, NULL, (BYTE*)buf, &size); - - if(err != ERROR_SUCCESS) { - if(err != ERROR_FILE_NOT_FOUND) { + if(err == ERROR_SUCCESS) + { + if(bs == size) + { + return true; + } + else{ + log_printf(LOG_WARNING, "Registry value with incorrect size: %s", name); + } + } + else if(err != ERROR_FILE_NOT_FOUND) + { log_printf(LOG_ERROR, "Error reading registry value: %s", w32_error(err)); } - - return 0; } - return size; + if(default_value) + { + memcpy(buf, default_value, size); + } + + return false; } -DWORD reg_get_dword(const char *val_name, DWORD default_val) { +DWORD reg_get_dword(HKEY key, const char *name, DWORD default_value) +{ DWORD buf; - return reg_get_bin(val_name, &buf, sizeof(buf)) == sizeof(buf) ? buf : default_val; + reg_get_bin(key, name, &buf, sizeof(buf), &default_value); + + return buf; } void load_dll(unsigned int dllnum) { diff --git a/src/common.h b/src/common.h index 5d04fa2..43719c3 100644 --- a/src/common.h +++ b/src/common.h @@ -22,10 +22,14 @@ #include #include -#define IPX_SADDR_SIZE 36 +#include "addr.h" -typedef unsigned char netnum_t[4]; -typedef unsigned char nodenum_t[6]; +#ifndef __cplusplus + typedef unsigned char bool; + + #define true 1 + #define false 0 +#endif enum ipx_log_level { LOG_CALL = 1, @@ -35,24 +39,16 @@ enum ipx_log_level { LOG_ERROR }; -extern HKEY regkey; - extern enum ipx_log_level min_log_level; const char *w32_error(DWORD errnum); -#define IPX_STRING_ADDR(var, net, node, sock) \ - char var[IPX_SADDR_SIZE]; \ - ipx_to_string(var, net, node, sock); +HKEY reg_open_main(bool readwrite); +HKEY reg_open_subkey(HKEY parent, const char *path, bool readwrite); +void reg_close(HKEY key); -void ipx_to_string(char *buf, const netnum_t net, const nodenum_t node, uint16_t sock); - -BOOL reg_open(REGSAM access); -void reg_close(void); - -char reg_get_char(const char *val_name, char default_val); -DWORD reg_get_bin(const char *val_name, void *buf, DWORD size); -DWORD reg_get_dword(const char *val_name, DWORD default_val); +bool reg_get_bin(HKEY key, const char *name, void *buf, size_t size, const void *default_value); +DWORD reg_get_dword(HKEY key, const char *name, DWORD default_value); void load_dll(unsigned int dllnum); void unload_dlls(void); diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..89b9e5f --- /dev/null +++ b/src/config.c @@ -0,0 +1,133 @@ +/* ipxwrapper - Configuration header + * Copyright (C) 2011 Daniel Collins + * + * 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. +*/ + +#include + +#include "config.h" +#include "common.h" + +main_config_t get_main_config(void) +{ + /* Defaults */ + + main_config_t config; + + config.udp_port = DEFAULT_PORT; + config.router_port = DEFAULT_ROUTER_PORT; + config.w95_bug = true; + config.bcast_all = false; + config.src_filter = true; + + HKEY reg = reg_open_main(false); + DWORD version = reg_get_dword(reg, "config_version", 1); + + if(version == 1) + { + struct v1_global_config reg_config; + + if(reg_get_bin(reg, "global", ®_config, sizeof(reg_config), NULL)) + { + config.udp_port = reg_config.udp_port; + config.w95_bug = reg_config.w95_bug; + config.bcast_all = reg_config.bcast_all; + config.src_filter = reg_config.filter; + } + } + else if(version == 2) + { + config.udp_port = reg_get_dword(reg, "port", config.udp_port); + config.router_port = reg_get_dword(reg, "router_port", config.router_port); + config.w95_bug = reg_get_dword(reg, "w95_bug", config.w95_bug); + config.bcast_all = reg_get_dword(reg, "bcast_all", config.bcast_all); + config.src_filter = reg_get_dword(reg, "src_filter", config.src_filter); + } + + reg_close(reg); + + return config; +} + +iface_config_t get_iface_config(addr48_t hwaddr) +{ + char id[18]; + addr48_string(id, hwaddr); + + addr32_t default_net = addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}); + + iface_config_t config; + + HKEY reg = reg_open_main(false); + DWORD version = reg_get_dword(reg, "config_version", 1); + + if(version == 1) + { + struct v1_iface_config reg_config; + + if(reg_get_bin(reg, id, ®_config, sizeof(reg_config), NULL)) + { + config.netnum = addr32_in(reg_config.ipx_net); + config.nodenum = addr48_in(reg_config.ipx_node); + config.enabled = reg_config.enabled; + + reg_close(reg); + + return config; + } + } + else if(version == 2) + { + HKEY iface_reg = reg_open_subkey(reg, id, false); + + config.netnum = reg_get_addr32(iface_reg, "net", default_net); + config.nodenum = reg_get_addr48(iface_reg, "node", hwaddr); + config.enabled = reg_get_dword(iface_reg, "enabled", true); + + reg_close(iface_reg); + reg_close(reg); + + return config; + } + + config.netnum = default_net; + config.nodenum = hwaddr; + config.enabled = true; + + reg_close(reg); + + return config; +} + +addr48_t get_primary_iface(void) +{ + addr48_t primary = addr48_in((unsigned char[]){ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); + + HKEY reg = reg_open_main(false); + DWORD version = reg_get_dword(reg, "config_version", 1); + + if(version == 1) + { + /* TODO: Iterate... */ + } + else if(version == 2) + { + primary = reg_get_addr48(reg, "primary", primary); + } + + reg_close(reg); + + return primary; +} diff --git a/src/config.h b/src/config.h index 43c6528..7479c8d 100644 --- a/src/config.h +++ b/src/config.h @@ -19,22 +19,44 @@ #define IPX_CONFIG_H #define DEFAULT_PORT 54792 -#define DEFAULT_CONTROL_PORT 54793 -#define HOST_TTL 60 +#define DEFAULT_ROUTER_PORT 54793 #define IFACE_TTL 10 -struct reg_value { - unsigned char ipx_net[4]; - unsigned char ipx_node[6]; - unsigned char enabled; - unsigned char primary; -} __attribute__((__packed__)); +#include "common.h" -struct reg_global { +typedef struct main_config { + uint16_t udp_port; + uint16_t router_port; + + bool w95_bug; + bool bcast_all; + bool src_filter; +} main_config_t; + +struct v1_global_config { uint16_t udp_port; unsigned char w95_bug; unsigned char bcast_all; unsigned char filter; } __attribute__((__packed__)); +typedef struct iface_config { + addr32_t netnum; + addr48_t nodenum; + + bool enabled; +} iface_config_t; + +struct v1_iface_config { + unsigned char ipx_net[4]; + unsigned char ipx_node[6]; + unsigned char enabled; + unsigned char primary; +} __attribute__((__packed__)); + +main_config_t get_main_config(void); + +iface_config_t get_iface_config(addr48_t hwaddr); +addr48_t get_primary_iface(); + #endif /* !IPX_CONFIG_H */ diff --git a/src/directplay.c b/src/directplay.c index 8a3d637..7d327fd 100644 --- a/src/directplay.c +++ b/src/directplay.c @@ -578,15 +578,18 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) { } BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { - if(why == DLL_PROCESS_ATTACH) { + if(why == DLL_PROCESS_ATTACH) + { log_open("ipxwrapper.log"); - reg_open(KEY_QUERY_VALUE); + HKEY reg = reg_open_main(false); - min_log_level = reg_get_dword("min_log_level", LOG_INFO); + min_log_level = reg_get_dword(reg, "min_log_level", LOG_INFO); - reg_close(); - }else if(why == DLL_PROCESS_DETACH) { + reg_close(reg); + } + else if(why == DLL_PROCESS_DETACH) + { unload_dlls(); log_close(); } diff --git a/src/interface.c b/src/interface.c index 23bb6c1..19f77fc 100644 --- a/src/interface.c +++ b/src/interface.c @@ -22,75 +22,80 @@ #include "common.h" #include "config.h" -/* Get virtual IPX interfaces - * Select a single interface by setting ifnum >= 0 +/* Fetch a list of network interfaces available on the system. + * + * Returns a linked list of IP_ADAPTER_INFO structures, all allocated within a + * single memory block beginning at the first node. */ -struct ipx_interface *get_interfaces(int ifnum) { - IP_ADAPTER_INFO *ifroot, tbuf; - ULONG bufsize = sizeof(IP_ADAPTER_INFO); +IP_ADAPTER_INFO *get_sys_interfaces(void) +{ + IP_ADAPTER_INFO *ifroot = NULL, *ifptr; + ULONG bufsize = sizeof(IP_ADAPTER_INFO) * 8; - int err = GetAdaptersInfo(&tbuf, &bufsize); - if(err == ERROR_NO_DATA) { - log_printf(LOG_WARNING, "No network interfaces detected!"); - return NULL; - }else if(err != ERROR_SUCCESS && err != ERROR_BUFFER_OVERFLOW) { - log_printf(LOG_ERROR, "Error fetching network interfaces: %s", w32_error(err)); - return NULL; - } + int err = ERROR_BUFFER_OVERFLOW; - if(!(ifroot = malloc(bufsize))) { - log_printf(LOG_ERROR, "Out of memory! (Tried to allocate %u bytes)", (unsigned int)bufsize); - return NULL; - } - - err = GetAdaptersInfo(ifroot, &bufsize); - if(err != ERROR_SUCCESS) { - log_printf(LOG_ERROR, "Error fetching network interfaces: %s", w32_error(err)); + while(err == ERROR_BUFFER_OVERFLOW) + { + if(!(ifptr = realloc(ifroot, bufsize))) + { + log_printf(LOG_ERROR, "Couldn't allocate IP_ADAPTER_INFO structures!"); + break; + } + ifroot = ifptr; + + err = GetAdaptersInfo(ifroot, &bufsize); + + if(err == ERROR_NO_DATA) + { + log_printf(LOG_WARNING, "No network interfaces detected!"); + break; + } + else if(err != ERROR_SUCCESS && err != ERROR_BUFFER_OVERFLOW) + { + log_printf(LOG_ERROR, "Error fetching network interfaces: %s", w32_error(err)); + break; + } + } + + if(err != ERROR_SUCCESS) + { free(ifroot); return NULL; } - struct ipx_interface *nics = NULL, *enic = NULL; + return ifroot; +} + +/* Get virtual IPX interfaces + * Select a single interface by setting ifnum >= 0 +*/ +ipx_interface_t *get_interfaces(int ifnum) +{ + IP_ADAPTER_INFO *ifroot = get_sys_interfaces(), *ifptr; - IP_ADAPTER_INFO *ifptr = ifroot; + addr48_t primary = get_primary_iface(); - while(ifptr) { - struct reg_value rv; - int got_rv = 0; + ipx_interface_t *nics = NULL; + + for(ifptr = ifroot; ifptr; ifptr = ifptr->Next) + { + addr48_t hwaddr = addr48_in(ifptr->Address); - /* Format the hardware address as a hex string for fetching - * settings from the registry. - */ + iface_config_t config = get_iface_config(hwaddr); - char vname[18]; - - sprintf( - vname, - - "%02X:%02X:%02X:%02X:%02X:%02X", - - (unsigned int)(unsigned char)(ifptr->Address[0]), - (unsigned int)(unsigned char)(ifptr->Address[1]), - (unsigned int)(unsigned char)(ifptr->Address[2]), - (unsigned int)(unsigned char)(ifptr->Address[3]), - (unsigned int)(unsigned char)(ifptr->Address[4]), - (unsigned int)(unsigned char)(ifptr->Address[5]) - ); - - if(reg_get_bin(vname, &rv, sizeof(rv)) == sizeof(rv)) { - got_rv = 1; - } - - if(got_rv && !rv.enabled) { + if(!config.enabled) + { /* Interface has been disabled, don't add it */ + ifptr = ifptr->Next; continue; } struct ipx_interface *nnic = malloc(sizeof(struct ipx_interface)); - if(!nnic) { - log_printf(LOG_ERROR, "Out of memory! (Tried to allocate %u bytes)", (unsigned int)sizeof(struct ipx_interface)); + if(!nnic) + { + log_printf(LOG_ERROR, "Couldn't allocate ipx_interface!"); free_interfaces(nics); return NULL; @@ -100,78 +105,64 @@ struct ipx_interface *get_interfaces(int ifnum) { nnic->netmask = inet_addr(ifptr->IpAddressList.IpMask.String); nnic->bcast = nnic->ipaddr | ~nnic->netmask; - memcpy(nnic->hwaddr, ifptr->Address, 6); + nnic->hwaddr = hwaddr; - if(got_rv) { - memcpy(nnic->ipx_net, rv.ipx_net, 4); - memcpy(nnic->ipx_node, rv.ipx_node, 6); - }else{ - unsigned char net[] = {0,0,0,1}; - - memcpy(nnic->ipx_net, net, 4); - memcpy(nnic->ipx_node, nnic->hwaddr, 6); - } - - nnic->next = NULL; + nnic->ipx_net = config.netnum; + nnic->ipx_node = config.nodenum; /* Workaround for buggy versions of Hamachi that don't initialise * the interface hardware address correctly. */ - const unsigned char hamachi_bug[] = {0x7A, 0x79, 0x00, 0x00, 0x00, 0x00}; + unsigned char hamachi_bug[] = {0x7A, 0x79, 0x00, 0x00, 0x00, 0x00}; - if(strcmp(ifptr->Description, "Hamachi Network Interface") == 0 && memcmp(nnic->ipx_node, hamachi_bug, 6) == 0) { + if(nnic->ipx_node == addr48_in(hamachi_bug)) + { log_printf(LOG_WARNING, "Invalid Hamachi interface detected, correcting node number"); - memcpy(nnic->ipx_node + 2, &(nnic->ipaddr), 4); - } - - if(got_rv && rv.primary) { - /* Force primary flag set, insert at start of NIC list */ - nnic->next = nics; - nics = nnic; - if(!enic) { - enic = nnic; - } - }else if(enic) { - enic->next = nnic; - enic = nnic; - }else{ - enic = nics = nnic; + addr32_out(hamachi_bug + 2, nnic->ipaddr); + nnic->ipx_node = addr48_in(hamachi_bug); } - ifptr = ifptr->Next; + if(nnic->hwaddr == primary) + { + /* Primary interface, insert at the start of the list */ + DL_PREPEND(nics, nnic); + } + else{ + DL_APPEND(nics, nnic); + } } free(ifroot); /* Delete every entry in the NIC list except the requested one */ - if(ifnum >= 0) { + + if(ifnum >= 0) + { int this_ifnum = 0; + ipx_interface_t *iface, *tmp; - while(nics && this_ifnum++ < ifnum) { - struct ipx_interface *dnic = nics; - nics = nics->next; - - free(dnic); - } - - while(nics && nics->next) { - struct ipx_interface *dnic = nics->next; - nics->next = nics->next->next; - - free(dnic); + DL_FOREACH_SAFE(nics, iface, tmp) + { + if(this_ifnum++ != ifnum) + { + DL_DELETE(nics, iface); + free(iface); + } } } return nics; } -void free_interfaces(struct ipx_interface *iface) { - while(iface) { - struct ipx_interface *del = iface; - iface = iface->next; - - free(del); +void free_interfaces(ipx_interface_t *list) +{ + ipx_interface_t *iface, *tmp; + + DL_FOREACH_SAFE(list, iface, tmp) + { + DL_DELETE(list, iface); + free(iface); } } diff --git a/src/interface.h b/src/interface.h index 7d382d3..db17a12 100644 --- a/src/interface.h +++ b/src/interface.h @@ -19,21 +19,27 @@ #define IPXWRAPPER_INTERFACE_H #include +#include + +#include "common.h" + +typedef struct ipx_interface ipx_interface_t; struct ipx_interface { uint32_t ipaddr; uint32_t netmask; uint32_t bcast; - unsigned char hwaddr[6]; + addr48_t hwaddr; - unsigned char ipx_net[4]; - unsigned char ipx_node[6]; + addr32_t ipx_net; + addr48_t ipx_node; - struct ipx_interface *next; + ipx_interface_t *prev; + ipx_interface_t *next; }; -struct ipx_interface *get_interfaces(int ifnum); -void free_interfaces(struct ipx_interface *iface); +ipx_interface_t *get_interfaces(int ifnum); +void free_interfaces(ipx_interface_t *iface); #endif /* !IPXWRAPPER_INTERFACE_H */ diff --git a/src/ipxconfig.cpp b/src/ipxconfig.cpp index 431da53..35a6a49 100644 --- a/src/ipxconfig.cpp +++ b/src/ipxconfig.cpp @@ -79,6 +79,9 @@ static RECT get_window_rect(HWND hwnd); static std::string w32_errmsg(DWORD errnum); static void die(std::string msg); +typedef struct v1_global_config reg_global; +typedef struct v1_iface_config reg_value; + static iface_list nics; static reg_global global_conf; static HKEY regkey = NULL; @@ -698,7 +701,7 @@ static void init_windows() { DWORD port_buf; if(reg_read("control_port", &port_buf, sizeof(DWORD)) != sizeof(DWORD) || port_buf > 65535) { - port_buf = DEFAULT_CONTROL_PORT; + port_buf = DEFAULT_ROUTER_PORT; } sprintf(port_s, "%hu", (uint16_t)port_buf); diff --git a/src/ipxwrapper.c b/src/ipxwrapper.c index 2502fec..505b60b 100644 --- a/src/ipxwrapper.c +++ b/src/ipxwrapper.c @@ -42,7 +42,7 @@ struct ipaddr_list { ipx_socket *sockets = NULL; SOCKET send_fd = -1; -struct reg_global global_conf; +main_config_t main_config; struct rclient g_rclient; @@ -81,23 +81,14 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { _putenv(env); } + main_config = get_main_config(); + addr_cache_init(); if(!rclient_init(&g_rclient)) { return FALSE; } - reg_open(KEY_QUERY_VALUE); - - if(reg_get_bin("global", &global_conf, sizeof(global_conf)) != sizeof(global_conf)) { - global_conf.udp_port = DEFAULT_PORT; - global_conf.w95_bug = 1; - global_conf.bcast_all = 0; - global_conf.filter = 1; - } - - min_log_level = reg_get_dword("min_log_level", LOG_INFO); - init_cs(&sockets_cs); init_cs(&addrs_cs); @@ -148,8 +139,6 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { DeleteCriticalSection(&addrs_cs); DeleteCriticalSection(&sockets_cs); - reg_close(); - addr_cache_cleanup(); unload_dlls(); diff --git a/src/ipxwrapper.h b/src/ipxwrapper.h index 675616d..e0b255e 100644 --- a/src/ipxwrapper.h +++ b/src/ipxwrapper.h @@ -98,7 +98,7 @@ struct ipx_host { extern ipx_socket *sockets; extern SOCKET send_fd; -extern struct reg_global global_conf; +extern main_config_t main_config; extern struct rclient g_rclient; ipx_socket *get_socket(SOCKET fd); diff --git a/src/mswsock_stubs.txt b/src/mswsock_stubs.txt index a0e474b..3bc0062 100644 --- a/src/mswsock_stubs.txt +++ b/src/mswsock_stubs.txt @@ -32,4 +32,3 @@ s_perror sethostname inet_addr WSHEnumProtocols:0 -ntohs:1 diff --git a/src/router-exe.c b/src/router-exe.c index b2d8c57..05bd637 100644 --- a/src/router-exe.c +++ b/src/router-exe.c @@ -23,7 +23,7 @@ #include "common.h" #include "config.h" -struct reg_global global_conf; +main_config_t main_config; #define APPWM_TRAY (WM_APP+1) #define MNU_EXIT 101 @@ -36,14 +36,7 @@ static void show_menu(HWND hwnd); int main(int argc, char **argv) { log_open("ipxrouter.log"); - reg_open(KEY_QUERY_VALUE); - - if(reg_get_bin("global", &global_conf, sizeof(global_conf)) != sizeof(global_conf)) { - global_conf.udp_port = DEFAULT_PORT; - global_conf.w95_bug = 1; - global_conf.bcast_all = 0; - global_conf.filter = 1; - } + main_config = get_main_config(); WSADATA wsdata; int err = WSAStartup(MAKEWORD(2,0), &wsdata); @@ -87,8 +80,6 @@ int main(int argc, char **argv) { WSACleanup(); - reg_close(); - log_close(); return 0; diff --git a/src/router.c b/src/router.c index 90a0e8e..f1b7c94 100644 --- a/src/router.c +++ b/src/router.c @@ -75,7 +75,7 @@ struct router_vars *router_init(BOOL global) { addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(global_conf.udp_port); + addr.sin_port = htons(main_config.udp_port); if(bind(router->udp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { log_printf(LOG_ERROR, "Error binding UDP socket: %s", w32_error(WSAGetLastError())); @@ -114,7 +114,7 @@ struct router_vars *router_init(BOOL global) { } addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(reg_get_dword("control_port", DEFAULT_CONTROL_PORT)); + addr.sin_port = htons(main_config.router_port); if(bind(router->listener, (struct sockaddr*)&addr, sizeof(addr)) == -1) { log_printf(LOG_ERROR, "Failed to bind TCP socket: %s", w32_error(WSAGetLastError())); @@ -278,8 +278,8 @@ DWORD router_main(void *arg) { } if(min_log_level <= LOG_DEBUG) { - IPX_STRING_ADDR(src_addr, packet->src_net, packet->src_node, packet->src_socket); - IPX_STRING_ADDR(dest_addr, packet->dest_net, packet->dest_node, packet->dest_socket); + IPX_STRING_ADDR(src_addr, addr32_in(packet->src_net), addr48_in(packet->src_node), packet->src_socket); + IPX_STRING_ADDR(dest_addr, addr32_in(packet->dest_net), addr48_in(packet->dest_node), packet->dest_socket); log_printf(LOG_DEBUG, "Recieved packet from %s (%s) for %s", src_addr, inet_ntoa(addr.sin_addr), dest_addr); } @@ -293,12 +293,12 @@ DWORD router_main(void *arg) { if( ra->local_port && (ra->filter_ptype < 0 || ra->filter_ptype == packet->ptype) && - (memcmp(packet->dest_net, ra->addr.sa_netnum, 4) == 0 || (memcmp(packet->dest_net, f6, 4) == 0 && (ra->flags & IPX_BROADCAST || !global_conf.w95_bug) && ra->flags & IPX_RECV_BCAST)) && - (memcmp(packet->dest_node, ra->addr.sa_nodenum, 6) == 0 || (memcmp(packet->dest_node, f6, 6) == 0 && (ra->flags & IPX_BROADCAST || !global_conf.w95_bug) && ra->flags & IPX_RECV_BCAST)) && + (memcmp(packet->dest_net, ra->addr.sa_netnum, 4) == 0 || (memcmp(packet->dest_net, f6, 4) == 0 && (ra->flags & IPX_BROADCAST || !main_config.w95_bug) && ra->flags & IPX_RECV_BCAST)) && + (memcmp(packet->dest_node, ra->addr.sa_nodenum, 6) == 0 || (memcmp(packet->dest_node, f6, 6) == 0 && (ra->flags & IPX_BROADCAST || !main_config.w95_bug) && ra->flags & IPX_RECV_BCAST)) && packet->dest_socket == ra->addr.sa_socket && /* Check source IP is within correct subnet */ - ((ra->ipaddr & ra->netmask) == (addr.sin_addr.s_addr & ra->netmask) || !global_conf.filter) && + ((ra->ipaddr & ra->netmask) == (addr.sin_addr.s_addr & ra->netmask) || !main_config.src_filter) && /* Check source address matches remote_addr if set */ (ra->remote_addr.sa_family == AF_UNSPEC || (memcmp(ra->remote_addr.sa_netnum, packet->src_net, 4) == 0 && memcmp(ra->remote_addr.sa_nodenum, packet->src_node, 6) == 0)) @@ -337,12 +337,14 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, */ struct ipx_interface *ifaces = get_interfaces(-1), *iface; - unsigned char z6[] = {0,0,0,0,0,0}; + + addr32_t sa_netnum = addr32_in(addr->sa_netnum); + addr48_t sa_nodenum = addr48_in(addr->sa_nodenum); for(iface = ifaces; iface; iface = iface->next) { if( - (memcmp(addr->sa_netnum, iface->ipx_net, 4) == 0 || memcmp(addr->sa_netnum, z6, 4) == 0) && - (memcmp(addr->sa_nodenum, iface->ipx_node, 6) == 0 || memcmp(addr->sa_nodenum, z6, 6) == 0) + (sa_netnum == iface->ipx_net || sa_netnum == 0) + && (sa_nodenum == iface->ipx_node || sa_nodenum == 0) ) { break; } @@ -357,8 +359,8 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, return -1; } - memcpy(addr->sa_netnum, iface->ipx_net, 4); - memcpy(addr->sa_nodenum, iface->ipx_node, 6); + addr32_out(addr->sa_netnum, iface->ipx_net); + addr48_out(addr->sa_nodenum, iface->ipx_node); *nic_bcast = iface->bcast; @@ -676,7 +678,7 @@ BOOL rclient_start(struct rclient *rclient) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(reg_get_dword("control_port", DEFAULT_CONTROL_PORT)); + addr.sin_port = htons(main_config.router_port); if(connect(rclient->sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { return TRUE; diff --git a/src/stubdll.c b/src/stubdll.c index b1144ba..e75d18a 100644 --- a/src/stubdll.c +++ b/src/stubdll.c @@ -22,15 +22,18 @@ #include "common.h" BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { - if(why == DLL_PROCESS_ATTACH) { + if(why == DLL_PROCESS_ATTACH) + { log_open("ipxwrapper.log"); - reg_open(KEY_QUERY_VALUE); + HKEY reg = reg_open_main(false); - min_log_level = reg_get_dword("min_log_level", LOG_INFO); + min_log_level = reg_get_dword(reg, "min_log_level", LOG_INFO); - reg_close(); - }else if(why == DLL_PROCESS_DETACH) { + reg_close(reg); + } + else if(why == DLL_PROCESS_DETACH) + { unload_dlls(); log_close(); } diff --git a/src/winsock.c b/src/winsock.c index e183abe..455cc96 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -240,7 +240,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) { memcpy(&ipxaddr, addr, sizeof(ipxaddr)); - IPX_STRING_ADDR(req_addr_s, ipxaddr.sa_netnum, ipxaddr.sa_nodenum, ipxaddr.sa_socket); + IPX_STRING_ADDR(req_addr_s, addr32_in(ipxaddr.sa_netnum), addr48_in(ipxaddr.sa_nodenum), ipxaddr.sa_socket); log_printf(LOG_INFO, "bind(%d, %s)", fd, req_addr_s); @@ -253,7 +253,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) { RETURN(-1); } - IPX_STRING_ADDR(got_addr_s, ipxaddr.sa_netnum, ipxaddr.sa_nodenum, ipxaddr.sa_socket); + IPX_STRING_ADDR(got_addr_s, addr32_in(ipxaddr.sa_netnum), addr48_in(ipxaddr.sa_nodenum), ipxaddr.sa_socket); log_printf(LOG_INFO, "bind address: %s", got_addr_s); @@ -362,7 +362,7 @@ static int recv_packet(ipx_socket *sockptr, char *buf, int bufsize, int flags, s if(min_log_level <= LOG_DEBUG) { - IPX_STRING_ADDR(addr_s, packet->src_net, packet->src_node, packet->src_socket); + IPX_STRING_ADDR(addr_s, addr32_in(packet->src_net), addr48_in(packet->src_node), packet->src_socket); log_printf(LOG_DEBUG, "Received packet from %s", addr_s); } @@ -372,9 +372,9 @@ static int recv_packet(ipx_socket *sockptr, char *buf, int bufsize, int flags, s struct sockaddr_in real_addr; real_addr.sin_family = AF_INET; real_addr.sin_addr.s_addr = rp_header->src_ipaddr; - real_addr.sin_port = htons(global_conf.udp_port); + real_addr.sin_port = htons(main_config.udp_port); - addr_cache_set((struct sockaddr*)&real_addr, sizeof(real_addr), packet->src_net, packet->src_node, 0); + addr_cache_set((struct sockaddr*)&real_addr, sizeof(real_addr), addr32_in(packet->src_net), addr48_in(packet->src_node), 0); if(addr) { addr->sa_family = AF_IPX; @@ -530,8 +530,8 @@ int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int F RETURN_WSA(ERROR_NO_DATA, -1); } - memcpy(ipxdata->netnum, nic->ipx_net, 4); - memcpy(ipxdata->nodenum, nic->ipx_node, 6); + addr32_out(ipxdata->netnum, nic->ipx_net); + addr48_out(ipxdata->nodenum, nic->ipx_node); /* TODO: LAN/WAN detection, link speed detection */ ipxdata->wan = FALSE; @@ -777,15 +777,15 @@ int WSAAPI sendto(SOCKET fd, const char *buf, int len, int flags, const struct s SOCKADDR_STORAGE send_addr; size_t addrlen; - if(!addr_cache_get(&send_addr, &addrlen, packet->dest_net, packet->dest_node, packet->dest_socket)) + if(!addr_cache_get(&send_addr, &addrlen, addr32_in(packet->dest_net), addr48_in(packet->dest_node), packet->dest_socket)) { /* No cached address. Send using broadcast. */ struct sockaddr_in *bcast = (struct sockaddr_in*)&send_addr; bcast->sin_family = AF_INET; - bcast->sin_addr.s_addr = (global_conf.bcast_all ? INADDR_BROADCAST : sockptr->nic_bcast); - bcast->sin_port = htons(global_conf.udp_port); + bcast->sin_addr.s_addr = (main_config.bcast_all ? INADDR_BROADCAST : sockptr->nic_bcast); + bcast->sin_port = htons(main_config.udp_port); addrlen = sizeof(*bcast); } @@ -795,7 +795,7 @@ int WSAAPI sendto(SOCKET fd, const char *buf, int len, int flags, const struct s struct sockaddr_in *v4 = (struct sockaddr_in*)&send_addr; - IPX_STRING_ADDR(addr_s, packet->dest_net, packet->dest_node, packet->dest_socket); + IPX_STRING_ADDR(addr_s, addr32_in(packet->dest_net), addr48_in(packet->dest_node), packet->dest_socket); log_printf(LOG_DEBUG, "Sending packet to %s (%s)", addr_s, inet_ntoa(v4->sin_addr)); }