1
0
mirror of https://github.com/solemnwarning/ipxwrapper synced 2024-12-30 16:45:37 +01:00

REFACTOR ALL THE THINGS.

This commit is contained in:
Daniel Collins 2012-10-21 10:26:52 +00:00
parent c836c55ee4
commit ebcf1673e2
20 changed files with 591 additions and 271 deletions

View File

@ -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

133
src/addr.c Normal file
View File

@ -0,0 +1,133 @@
/* ipxwrapper - Address manipulation functions
* Copyright (C) 2012 Daniel Collins <solemnwarning@solemnwarning.net>
*
* 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 <windows.h>
#include <winsock2.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#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));
}

50
src/addr.h Normal file
View File

@ -0,0 +1,50 @@
/* ipxwrapper - Address manipulation functions
* Copyright (C) 2012 Daniel Collins <solemnwarning@solemnwarning.net>
*
* 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 <stdint.h>
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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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, &regkey);
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) {

View File

@ -22,10 +22,14 @@
#include <stdio.h>
#include <stdint.h>
#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);

133
src/config.c Normal file
View File

@ -0,0 +1,133 @@
/* ipxwrapper - Configuration header
* Copyright (C) 2011 Daniel Collins <solemnwarning@solemnwarning.net>
*
* 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 <stdio.h>
#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", &reg_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, &reg_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;
}

View File

@ -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 */

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -19,21 +19,27 @@
#define IPXWRAPPER_INTERFACE_H
#include <stdint.h>
#include <utlist.h>
#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 */

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -32,4 +32,3 @@ s_perror
sethostname
inet_addr
WSHEnumProtocols:0
ntohs:1

View File

@ -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;

View File

@ -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;

View File

@ -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();
}

View File

@ -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));
}