diff --git a/src/addr.c b/src/addr.c index fb7da57..b762355 100644 --- a/src/addr.c +++ b/src/addr.c @@ -97,7 +97,7 @@ addr32_t reg_get_addr32(HKEY key, const char *name, addr32_t default_value) { unsigned char buf[4], default_buf[4]; - addr48_out(default_buf, default_value); + addr32_out(default_buf, default_value); reg_get_bin(key, name, buf, 4, default_buf); return addr32_in(buf); diff --git a/src/config.c b/src/config.c index 17567c0..f031f8a 100644 --- a/src/config.c +++ b/src/config.c @@ -19,6 +19,7 @@ #include "config.h" #include "common.h" +#include "interface.h" main_config_t get_main_config(void) { @@ -37,24 +38,6 @@ main_config_t get_main_config(void) config.iface_mode = reg_get_dword(reg, "iface_mode", IFACE_MODE_ALL); - config.single_netnum = reg_get_addr32(reg, "single_netnum", addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01})); - config.single_nodenum = reg_get_addr48(reg, "single_nodenum", 0); - - if(config.single_nodenum == 0) - { - /* Generate a random node number and store it in the registry - * for persistence. - */ - - config.single_nodenum = gen_random_mac(); - - HKEY wreg = reg_open_main(true); - - reg_set_addr48(wreg, "single_nodenum", config.single_nodenum); - - reg_close(wreg); - } - if(version == 1) { struct v1_global_config reg_config; @@ -92,8 +75,6 @@ bool set_main_config(const main_config_t *config) HKEY reg = reg_open_main(true); bool ok = reg_set_dword(reg, "iface_mode", config->iface_mode) - && reg_set_addr32(reg, "single_netnum", config->single_netnum) - && reg_set_addr48(reg, "single_nodenum", config->single_nodenum) && reg_set_dword(reg, "port", config->udp_port) && reg_set_dword(reg, "router_port", config->router_port) @@ -115,15 +96,23 @@ 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 = { + .netnum = addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), + .nodenum = hwaddr, + + .enabled = true + }; - iface_config_t config; + HKEY reg = reg_open_main(false); + HKEY ifreg = reg_open_subkey(reg, id, false); - HKEY reg = reg_open_main(false); - DWORD version = reg_get_dword(reg, "config_version", 1); - - if(version == 1) + if(ifreg) { + config.netnum = reg_get_addr32(ifreg, "net", config.netnum); + config.nodenum = reg_get_addr48(ifreg, "node", config.nodenum); + config.enabled = reg_get_dword(ifreg, "enabled", config.enabled); + } + else{ struct v1_iface_config reg_config; if(reg_get_bin(reg, id, ®_config, sizeof(reg_config), NULL)) @@ -131,30 +120,21 @@ iface_config_t get_iface_config(addr48_t hwaddr) 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) + + if(hwaddr == WILDCARD_IFACE_HWADDR && config.nodenum == hwaddr) { - HKEY iface_reg = reg_open_subkey(reg, id, false); + /* Generate a random node number for the wildcard interface and + * store it in the registry for persistence. + */ - 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); + config.nodenum = gen_random_mac(); - reg_close(iface_reg); - reg_close(reg); - - return config; + set_iface_config(hwaddr, &config); } - config.netnum = default_net; - config.nodenum = hwaddr; - config.enabled = true; - + reg_close(ifreg); reg_close(reg); return config; @@ -169,8 +149,8 @@ bool set_iface_config(addr48_t hwaddr, const iface_config_t *config) HKEY ifreg = reg_open_subkey(reg, id, true); bool ok = reg_set_addr32(ifreg, "net", config->netnum) - && reg_set_addr32(ifreg, "node", config->nodenum) - && reg_set_addr32(ifreg, "enabled", config->enabled); + && reg_set_addr48(ifreg, "node", config->nodenum) + && reg_set_dword(ifreg, "enabled", config->enabled); reg_close(ifreg); reg_close(reg); diff --git a/src/config.h b/src/config.h index 3eb8a19..97d2baa 100644 --- a/src/config.h +++ b/src/config.h @@ -58,9 +58,6 @@ typedef struct main_config { enum ipx_log_level log_level; int iface_mode; - - addr32_t single_netnum; - addr48_t single_nodenum; } main_config_t; struct v1_global_config { diff --git a/src/interface.c b/src/interface.c index 1843f58..ec5ecd8 100644 --- a/src/interface.c +++ b/src/interface.c @@ -76,6 +76,46 @@ IP_ADAPTER_INFO *load_sys_interfaces(void) return ifroot; } +/* Allocate and initialise a new ipx_interface structure. + * Returns NULL on malloc failure. +*/ +static ipx_interface_t *_new_iface(addr32_t net, addr48_t node) +{ + ipx_interface_t *iface = malloc(sizeof(ipx_interface_t)); + if(!iface) + { + log_printf(LOG_ERROR, "Cannot allocate ipx_interface!"); + } + + memset(iface, 0, sizeof(*iface)); + + iface->ipx_net = net; + iface->ipx_node = node; + + return iface; +} + +/* Add an IP address to an ipx_interface structure. + * Returns false on malloc failure. +*/ +static bool _push_addr(ipx_interface_t *iface, uint32_t ipaddr, uint32_t netmask) +{ + ipx_interface_ip_t *addr = malloc(sizeof(ipx_interface_ip_t)); + if(!addr) + { + log_printf(LOG_ERROR, "Couldn't allocate ipx_interface_ip!"); + return false; + } + + addr->ipaddr = ipaddr; + addr->netmask = netmask; + addr->bcast = ipaddr | (~netmask); + + DL_APPEND(iface->ipaddr, addr); + + return true; +} + /* Load a list of virtual IPX interfaces. */ ipx_interface_t *load_ipx_interfaces(void) { @@ -85,6 +125,32 @@ ipx_interface_t *load_ipx_interfaces(void) ipx_interface_t *nics = NULL; + iface_config_t wc_config = get_iface_config(WILDCARD_IFACE_HWADDR); + + if(wc_config.enabled) + { + /* Initialise wildcard interface. */ + + ipx_interface_t *wc_iface = _new_iface(wc_config.netnum, wc_config.nodenum); + if(!wc_iface) + { + return NULL; + } + + /* Use 0.0.0.0/0 as the IP/network of the wildcard interface + * to broadcast to 255.255.255.255 and match packets from any + * address. + */ + + if(!_push_addr(wc_iface, 0, 0)) + { + free_ipx_interface(wc_iface); + return NULL; + } + + DL_APPEND(nics, wc_iface); + } + for(ifptr = ifroot; ifptr; ifptr = ifptr->Next) { addr48_t hwaddr = addr48_in(ifptr->Address); @@ -99,16 +165,16 @@ ipx_interface_t *load_ipx_interfaces(void) continue; } - ipx_interface_t *iface = malloc(sizeof(ipx_interface_t)); + ipx_interface_t *iface = _new_iface(config.netnum, config.nodenum); if(!iface) { - log_printf(LOG_ERROR, "Couldn't allocate ipx_interface!"); - free_ipx_interface_list(&nics); return NULL; } - iface->ipaddr = NULL; + /* Iterate over the interface IP address list and add them to + * the ipx_interface structure. + */ IP_ADDR_STRING *ip_ptr = &(ifptr->IpAddressList); @@ -126,29 +192,15 @@ ipx_interface_t *load_ipx_interfaces(void) continue; } - ipx_interface_ip_t *addr = malloc(sizeof(ipx_interface_ip_t)); - if(!addr) + if(!_push_addr(iface, ipaddr, netmask)) { - log_printf(LOG_ERROR, "Couldn't allocate ipx_interface_ip!"); - free_ipx_interface(iface); free_ipx_interface_list(&nics); - continue; + return NULL; } - - addr->ipaddr = ipaddr; - addr->netmask = netmask; - addr->bcast = ipaddr | (~netmask); - - DL_APPEND(iface->ipaddr, addr); } - iface->hwaddr = hwaddr; - - iface->ipx_net = config.netnum; - iface->ipx_node = config.nodenum; - /* Workaround for buggy versions of Hamachi that don't initialise * the interface hardware address correctly. */ @@ -163,7 +215,7 @@ ipx_interface_t *load_ipx_interfaces(void) iface->ipx_node = addr48_in(hamachi_bug); } - if(iface->hwaddr == primary) + if(hwaddr == primary) { /* Primary interface, insert at the start of the list */ DL_PREPEND(nics, iface); diff --git a/src/interface.h b/src/interface.h index 00644f2..741ebe4 100644 --- a/src/interface.h +++ b/src/interface.h @@ -18,6 +18,7 @@ #ifndef IPXWRAPPER_INTERFACE_H #define IPXWRAPPER_INTERFACE_H +#include #include #include @@ -27,6 +28,8 @@ extern "C" { #endif +#define WILDCARD_IFACE_HWADDR addr48_in((unsigned char[]){0x00,0x00,0x00,0x00,0x00,0x00}) + typedef struct ipx_interface_ip ipx_interface_ip_t; struct ipx_interface_ip { @@ -41,8 +44,6 @@ struct ipx_interface_ip { typedef struct ipx_interface ipx_interface_t; struct ipx_interface { - addr48_t hwaddr; - addr32_t ipx_net; addr48_t ipx_node;