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

Switchover to new router code

This commit is contained in:
Daniel Collins 2011-09-07 20:03:16 +00:00
parent 37e9db8fba
commit d046b6522d
7 changed files with 126 additions and 323 deletions

View File

@ -18,14 +18,14 @@ CFLAGS := -Wall -I./include/
CXXFLAGS := -Wall -I./include/ CXXFLAGS := -Wall -I./include/
IPXWRAPPER_DEPS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \ IPXWRAPPER_DEPS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \
src/interface.o src/ipxwrapper.def src/interface.o src/router.o src/ipxwrapper.def
BIN_FILES := changes.txt license.txt readme.txt ipxwrapper.dll mswsock.dll wsock32.dll ipxconfig.exe BIN_FILES := changes.txt license.txt readme.txt ipxwrapper.dll mswsock.dll wsock32.dll ipxconfig.exe
SRC_FILES := changes.txt license.txt Makefile mkstubs.pl readme.txt src/config.h src/ipxconfig.cpp \ SRC_FILES := changes.txt license.txt Makefile mkstubs.pl readme.txt src/config.h src/ipxconfig.cpp \
src/ipxwrapper.c src/ipxwrapper.def src/ipxwrapper.h src/ipxwrapper_stubs.txt src/log.c \ src/ipxwrapper.c src/ipxwrapper.def src/ipxwrapper.h src/ipxwrapper_stubs.txt src/log.c \
src/mswsock.def src/mswsock_stubs.txt src/stubdll.c src/winsock.c src/winstuff.h src/wsock32.def \ src/mswsock.def src/mswsock_stubs.txt src/stubdll.c src/winsock.c src/winstuff.h src/wsock32.def \
src/wsock32_stubs.txt src/directplay.c src/dpwsockx.def src/dpwsockx_stubs.txt src/common.c \ src/wsock32_stubs.txt src/directplay.c src/dpwsockx.def src/dpwsockx_stubs.txt src/common.c \
src/common.h include/dplay.h include/dplaysp.h include/dplobby.h src/common.h src/router.c src/router.h include/dplay.h include/dplaysp.h include/dplobby.h
all: ipxwrapper.dll wsock32.dll mswsock.dll ipxconfig.exe dpwsockx.dll all: ipxwrapper.dll wsock32.dll mswsock.dll ipxconfig.exe dpwsockx.dll

View File

@ -29,6 +29,7 @@
#include "ipxwrapper.h" #include "ipxwrapper.h"
#include "common.h" #include "common.h"
#include "interface.h" #include "interface.h"
#include "router.h"
#define DLL_UNLOAD(dll) \ #define DLL_UNLOAD(dll) \
if(dll) {\ if(dll) {\
@ -41,7 +42,6 @@ struct ipx_interface *nics = NULL;
ipx_host *hosts = NULL; ipx_host *hosts = NULL;
SOCKET net_fd = -1; SOCKET net_fd = -1;
struct reg_global global_conf; struct reg_global global_conf;
static void *router_buf = NULL;
HMODULE winsock2_dll = NULL; HMODULE winsock2_dll = NULL;
HMODULE mswsock_dll = NULL; HMODULE mswsock_dll = NULL;
@ -49,10 +49,9 @@ HMODULE wsock32_dll = NULL;
static HANDLE mutex = NULL; static HANDLE mutex = NULL;
static HANDLE router_thread = NULL; static HANDLE router_thread = NULL;
static DWORD router_tid = 0; struct router_vars *router = NULL;
static int init_router(void); static BOOL start_router(void);
static DWORD WINAPI router_main(LPVOID argp);
BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
if(why == DLL_PROCESS_ATTACH) { if(why == DLL_PROCESS_ATTACH) {
@ -90,21 +89,23 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
return FALSE; return FALSE;
} }
if(!init_router()) { if(!start_router()) {
return FALSE; return FALSE;
} }
}else if(why == DLL_PROCESS_DETACH) { }else if(why == DLL_PROCESS_DETACH) {
if(router_thread && GetCurrentThreadId() != router_tid) { if(router_thread) {
TerminateThread(router_thread, 0); EnterCriticalSection(&(router->crit_sec));
router->running = FALSE;
SetEvent(router->wsa_event);
LeaveCriticalSection(&(router->crit_sec));
WaitForSingleObject(router_thread, INFINITE);
router_thread = NULL; router_thread = NULL;
}
router_destroy(router);
free(router_buf); router = NULL;
router_buf = NULL;
if(net_fd >= 0) {
closesocket(net_fd);
net_fd = -1;
} }
if(mutex) { if(mutex) {
@ -182,143 +183,24 @@ void unlock_mutex(void) {
} }
/* Initialize and start the router thread */ /* Initialize and start the router thread */
static int init_router(void) { static BOOL start_router(void) {
net_fd = r_socket(AF_INET, SOCK_DGRAM, 0); if(!(router = router_init(FALSE))) {
if(net_fd == -1) { return FALSE;
log_printf("Failed to create network socket: %s", w32_error(WSAGetLastError()));
return 0;
} }
struct sockaddr_in bind_addr; router_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&router_main, router, 0, NULL);
bind_addr.sin_family = AF_INET;
bind_addr.sin_addr.s_addr = INADDR_ANY;
bind_addr.sin_port = htons(global_conf.udp_port);
if(r_bind(net_fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1) {
log_printf("Failed to bind network socket: %s", w32_error(WSAGetLastError()));
return 0;
}
BOOL broadcast = TRUE;
int bufsize = 524288; /* 512KiB */
r_setsockopt(net_fd, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof(BOOL));
r_setsockopt(net_fd, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, sizeof(int));
r_setsockopt(net_fd, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(int));
router_buf = malloc(PACKET_BUF_SIZE);
if(!router_buf) {
log_printf("Not enough memory for router buffer (64KiB)");
return 0;
}
router_thread = CreateThread(NULL, 0, &router_main, NULL, 0, &router_tid);
if(!router_thread) { if(!router_thread) {
log_printf("Failed to create router thread"); log_printf("Failed to create router thread: %s", w32_error(GetLastError()));
return 0;
router_destroy(router);
router = NULL;
return FALSE;
} }
return 1; net_fd = router->udp_sock;
}
/* Router thread main function
*
* The router thread recieves packets from the listening port and forwards them
* to the UDP sockets which emulate IPX.
*/
static DWORD WINAPI router_main(LPVOID notused) {
ipx_packet *packet = router_buf;
int addrlen, rval, sval;
unsigned char f6[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
struct sockaddr_in addr;
ipx_socket *sockptr;
while(1) { return TRUE;
addrlen = sizeof(addr);
rval = r_recvfrom(net_fd, (char*)packet, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen);
if(rval <= 0) {
log_printf("Error recieving packet: %s", w32_error(WSAGetLastError()));
continue;
}
if(global_conf.filter) {
struct ipx_interface *nic = nics;
while(nic) {
if((nic->ipaddr & nic->netmask) == (addr.sin_addr.s_addr & nic->netmask)) {
break;
}
nic = nic->next;
}
if(!nic) {
/* Packet not recieved from subnet of an enabled interface */
continue;
}
}
packet->size = ntohs(packet->size);
if(packet->size > MAX_PACKET_SIZE || packet->size+sizeof(ipx_packet)-1 != rval) {
log_printf("Recieved packet with incorrect size field, discarding");
continue;
}
lock_mutex();
add_host(packet->src_net, packet->src_node, addr.sin_addr.s_addr);
for(sockptr = sockets; sockptr; sockptr = sockptr->next) {
if(
sockptr->flags & IPX_RECV &&
(
!(sockptr->flags & IPX_FILTER) ||
packet->ptype == sockptr->f_ptype
) && ((
sockptr->flags & IPX_BOUND &&
packet->dest_socket == sockptr->socket &&
(
memcmp(packet->dest_net, sockptr->nic->ipx_net, 4) == 0 ||
(
memcmp(packet->dest_net, f6, 4) == 0 &&
(!global_conf.w95_bug || sockptr->flags & IPX_BROADCAST)
)
) && (
memcmp(packet->dest_node, sockptr->nic->ipx_node, 6) == 0 ||
(
memcmp(packet->dest_node, f6, 6) == 0 &&
(!global_conf.w95_bug || sockptr->flags & IPX_BROADCAST)
)
)
) || (
sockptr->flags & IPX_EX_BOUND &&
packet->dest_socket == sockptr->ex_socket &&
(
memcmp(packet->dest_net, sockptr->ex_nic->ipx_net, 4) == 0 ||
memcmp(packet->dest_net, f6, 4) == 0
) && (
memcmp(packet->dest_node, sockptr->ex_nic->ipx_node, 6) == 0 ||
memcmp(packet->dest_node, f6, 6) == 0
)
))
) {
addrlen = sizeof(addr);
if(r_getsockname(sockptr->fd, (struct sockaddr*)&addr, &addrlen) == -1) {
continue;
}
sval = r_sendto(sockptr->fd, (char*)packet, rval, 0, (struct sockaddr*)&addr, addrlen);
if(sval == -1) {
log_printf("Error relaying packet: %s", w32_error(WSAGetLastError()));
}
}
}
unlock_mutex();
}
return 0;
} }
/* Add a host to the hosts list or update an existing one */ /* Add a host to the hosts list or update an existing one */

View File

@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include "config.h" #include "config.h"
#include "router.h"
/* Maximum UDP data size is 65467, we use a smaller value to ensure we have /* Maximum UDP data size is 65467, we use a smaller value to ensure we have
* plenty of space to play with for headers, etc * plenty of space to play with for headers, etc
@ -65,8 +66,8 @@ struct ipx_socket {
uint8_t f_ptype; /* Undefined when IPX_FILTER isn't set */ uint8_t f_ptype; /* Undefined when IPX_FILTER isn't set */
/* The following values are undefined when IPX_BOUND is not set */ /* The following values are undefined when IPX_BOUND is not set */
struct ipx_interface *nic; struct sockaddr_ipx addr;
uint16_t socket; /* Stored in NETWORK BYTE ORDER */ uint32_t nic_bcast;
/* Extra bind address, only used for receiving packets. /* Extra bind address, only used for receiving packets.
* Only defined when IPX_EX_BOUND is set. * Only defined when IPX_EX_BOUND is set.
@ -107,6 +108,7 @@ extern struct ipx_interface *nics;
extern ipx_host *hosts; extern ipx_host *hosts;
extern SOCKET net_fd; extern SOCKET net_fd;
extern struct reg_global global_conf; extern struct reg_global global_conf;
extern struct router_vars *router;
extern HMODULE winsock2_dll; extern HMODULE winsock2_dll;
extern HMODULE mswsock_dll; extern HMODULE mswsock_dll;

View File

@ -8,6 +8,10 @@ ntohl
htons htons
ntohs ntohs
select select
WSACreateEvent
WSAEventSelect
WSACloseEvent
WSAResetEvent
r_EnumProtocolsA r_EnumProtocolsA
r_EnumProtocolsW r_EnumProtocolsW
r_WSARecvEx r_WSARecvEx

View File

@ -72,8 +72,8 @@ struct router_vars *router_init(BOOL global) {
struct sockaddr_in addr; struct sockaddr_in addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 9999; addr.sin_port = htons(global_conf.udp_port);
if(bind(router->udp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { if(bind(router->udp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
log_printf("Error binding UDP socket: %s", w32_error(WSAGetLastError())); log_printf("Error binding UDP socket: %s", w32_error(WSAGetLastError()));
@ -143,24 +143,28 @@ void router_destroy(struct router_vars *router) {
DWORD router_main(void *arg) { DWORD router_main(void *arg) {
struct router_vars *router = arg; struct router_vars *router = arg;
const unsigned char f6[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
while(1) { while(1) {
WaitForSingleObject(router->wsa_event, INFINITE); WaitForSingleObject(router->wsa_event, INFINITE);
EnterCriticalSection(&(router->crit_sec)); EnterCriticalSection(&(router->crit_sec));
WSAResetEvent(router->wsa_event);
if(!router->running) { if(!router->running) {
LeaveCriticalSection(&(router->crit_sec)); LeaveCriticalSection(&(router->crit_sec));
return 0; return 0;
} }
LeaveCriticalSection(&(router->crit_sec));
struct sockaddr_in addr; struct sockaddr_in addr;
int addrlen = sizeof(addr); int addrlen = sizeof(addr);
int len = recvfrom(router->udp_sock, router->recvbuf, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen); int len = r_recvfrom(router->udp_sock, router->recvbuf, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen);
if(len == -1) { if(len == -1) {
LeaveCriticalSection(&(router->crit_sec)); if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET) {
if(WSAGetLastError() == WSAEWOULDBLOCK) {
continue; continue;
} }
@ -168,6 +172,8 @@ DWORD router_main(void *arg) {
return 1; return 1;
} }
EnterCriticalSection(&(router->crit_sec));
ipx_packet *packet = (ipx_packet*)router->recvbuf; ipx_packet *packet = (ipx_packet*)router->recvbuf;
/* Check that the packet arrived from the subnet of an enabled network /* Check that the packet arrived from the subnet of an enabled network
@ -186,6 +192,7 @@ DWORD router_main(void *arg) {
} }
if(!iface) { if(!iface) {
LeaveCriticalSection(&(router->crit_sec));
continue; continue;
} }
} }
@ -193,7 +200,7 @@ DWORD router_main(void *arg) {
packet->size = ntohs(packet->size); packet->size = ntohs(packet->size);
if(packet->size > MAX_PACKET_SIZE || packet->size + sizeof(ipx_packet) - 1 != len) { if(packet->size > MAX_PACKET_SIZE || packet->size + sizeof(ipx_packet) - 1 != len) {
log_printf("Recieved packet with incorrect size field, discarding"); LeaveCriticalSection(&(router->crit_sec));
continue; continue;
} }
@ -202,8 +209,6 @@ DWORD router_main(void *arg) {
struct router_addr *ra = router->addrs; struct router_addr *ra = router->addrs;
while(ra) { while(ra) {
unsigned char f6[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
if( if(
ra->local_port && ra->local_port &&
(ra->filter_ptype < 0 || ra->filter_ptype == packet->ptype) && (ra->filter_ptype < 0 || ra->filter_ptype == packet->ptype) &&
@ -214,7 +219,7 @@ DWORD router_main(void *arg) {
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = ra->local_port; addr.sin_port = ra->local_port;
if(sendto(router->udp_sock, (char*)packet, len, 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) { if(r_sendto(router->udp_sock, (char*)packet, len, 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
log_printf("Error relaying packet: %s", w32_error(WSAGetLastError())); log_printf("Error relaying packet: %s", w32_error(WSAGetLastError()));
} }
} }
@ -228,7 +233,20 @@ DWORD router_main(void *arg) {
return 0; return 0;
} }
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr) { int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast) {
/* Network number 00:00:00:00 is specified as the "current" network, this code
* treats it as a wildcard when used for the network OR node numbers.
*
* According to MSDN 6, IPX socket numbers are unique to systems rather than
* interfaces and as such, the same socket number cannot be bound to more than
* one interface, my code lacks any "catch all" address like INADDR_ANY as I have
* not found any mentions of an equivalent address for IPX. This means that a
* given socket number may only be used on one interface.
*
* If you know the above information about IPX socket numbers to be incorrect,
* PLEASE email me with corrections!
*/
struct ipx_interface *ifaces = get_interfaces(-1), *iface; struct ipx_interface *ifaces = get_interfaces(-1), *iface;
unsigned char z6[] = {0,0,0,0,0,0}; unsigned char z6[] = {0,0,0,0,0,0};
@ -253,6 +271,8 @@ int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct
memcpy(addr->sa_netnum, iface->ipx_net, 4); memcpy(addr->sa_netnum, iface->ipx_net, 4);
memcpy(addr->sa_nodenum, iface->ipx_node, 6); memcpy(addr->sa_nodenum, iface->ipx_node, 6);
*nic_bcast = iface->bcast;
free_interfaces(ifaces); free_interfaces(ifaces);
EnterCriticalSection(&(router->crit_sec)); EnterCriticalSection(&(router->crit_sec));
@ -352,7 +372,7 @@ void router_set_port(struct router_vars *router, SOCKET control, SOCKET sock, ui
LeaveCriticalSection(&(router->crit_sec)); LeaveCriticalSection(&(router->crit_sec));
} }
void router_close(struct router_vars *router, SOCKET control, SOCKET sock) { void router_unbind(struct router_vars *router, SOCKET control, SOCKET sock) {
EnterCriticalSection(&(router->crit_sec)); EnterCriticalSection(&(router->crit_sec));
struct router_addr *addr = router->addrs, *prev = NULL; struct router_addr *addr = router->addrs, *prev = NULL;

View File

@ -61,9 +61,11 @@ struct router_vars {
struct router_vars *router_init(BOOL global); struct router_vars *router_init(BOOL global);
void router_destroy(struct router_vars *router); void router_destroy(struct router_vars *router);
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr); DWORD router_main(void *arg);
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast);
void router_set_port(struct router_vars *router, SOCKET control, SOCKET sock, uint16_t port); void router_set_port(struct router_vars *router, SOCKET control, SOCKET sock, uint16_t port);
void router_close(struct router_vars *router, SOCKET control, SOCKET sock); void router_unbind(struct router_vars *router, SOCKET control, SOCKET sock);
void router_set_filter(struct router_vars *router, SOCKET control, SOCKET sock, int ptype); void router_set_filter(struct router_vars *router, SOCKET control, SOCKET sock, int ptype);
#endif /* !IPXWRAPPER_ROUTER_H */ #endif /* !IPXWRAPPER_ROUTER_H */

View File

@ -26,6 +26,7 @@
#include "ipxwrapper.h" #include "ipxwrapper.h"
#include "common.h" #include "common.h"
#include "interface.h" #include "interface.h"
#include "router.h"
INT APIENTRY EnumProtocolsA(LPINT protocols, LPVOID buf, LPDWORD bsptr) { INT APIENTRY EnumProtocolsA(LPINT protocols, LPVOID buf, LPDWORD bsptr) {
int bufsize = *bsptr, rval, i, want_ipx = 0; int bufsize = *bsptr, rval, i, want_ipx = 0;
@ -180,6 +181,8 @@ int WSAAPI closesocket(SOCKET fd) {
log_printf("IPX socket closed (fd = %d)", fd); log_printf("IPX socket closed (fd = %d)", fd);
router_unbind(router, 0, fd);
if(ptr == sockets) { if(ptr == sockets) {
sockets = ptr->next; sockets = ptr->next;
free(ptr); free(ptr);
@ -201,122 +204,61 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) {
ipx_socket *ptr = get_socket(fd); ipx_socket *ptr = get_socket(fd);
if(ptr) { if(ptr) {
struct sockaddr_ipx *ipxaddr = (struct sockaddr_ipx*)addr; struct sockaddr_ipx ipxaddr;
char net_s[12], node_s[18]; char net_s[12], node_s[18];
NET_TO_STRING(net_s, ipxaddr->sa_netnum); if(addrlen < sizeof(ipxaddr)) {
NODE_TO_STRING(node_s, ipxaddr->sa_nodenum); RETURN_WSA(WSAEFAULT, -1);
}
log_printf("bind(%d, net=%s node=%s socket=%hu)", fd, net_s, node_s, ntohs(ipxaddr->sa_socket)); memcpy(&ipxaddr, addr, sizeof(ipxaddr));
NET_TO_STRING(net_s, ipxaddr.sa_netnum);
NODE_TO_STRING(node_s, ipxaddr.sa_nodenum);
log_printf("bind(%d, net=%s node=%s socket=%hu)", fd, net_s, node_s, ntohs(ipxaddr.sa_socket));
if(ptr->flags & IPX_BOUND) { if(ptr->flags & IPX_BOUND) {
log_printf("bind failed: socket already bound"); log_printf("bind failed: socket already bound");
RETURN_WSA(WSAEINVAL, -1); RETURN_WSA(WSAEINVAL, -1);
} }
/* Network number 00:00:00:00 is specified as the "current" network, this code if(router_bind(router, 0, fd, &ipxaddr, &(ptr->nic_bcast)) == -1) {
* treats it as a wildcard when used for the network OR node numbers. RETURN(-1);
*
* According to MSDN 6, IPX socket numbers are unique to systems rather than
* interfaces and as such, the same socket number cannot be bound to more than
* one interface, my code lacks any "catch all" address like INADDR_ANY as I have
* not found any mentions of an equivalent address for IPX. This means that a
* given socket number may only be used on one interface.
*
* If you know the above information about IPX socket numbers to be incorrect,
* PLEASE email me with corrections!
*/
unsigned char z6[] = {0,0,0,0,0,0};
struct ipx_interface *nic = nics;
while(nic) {
if(
(memcmp(ipxaddr->sa_netnum, nic->ipx_net, 4) == 0 || memcmp(ipxaddr->sa_netnum, z6, 4) == 0) &&
(memcmp(ipxaddr->sa_nodenum, nic->ipx_node, 6) == 0 || memcmp(ipxaddr->sa_nodenum, z6, 6) == 0)
) {
break;
}
nic = nic->next;
} }
if(!nic) { NET_TO_STRING(net_s, ipxaddr.sa_netnum);
log_printf("bind failed: no such address"); NODE_TO_STRING(node_s, ipxaddr.sa_nodenum);
RETURN_WSA(WSAEADDRNOTAVAIL, -1);
}
ptr->nic = nic; log_printf("bind address: net=%s node=%s socket=%hu", net_s, node_s, ntohs(ipxaddr.sa_socket));
if(ipxaddr->sa_socket == 0) {
/* Automatic socket allocations start at 1024, I have no idea if
* this is normal IPX behaviour, but IP does it and it doesn't seem
* to interfere with any IPX software I've tested.
*/
uint16_t s = 1024;
ipx_socket *socket = sockets;
while(socket) {
if(ntohs(socket->socket) == s && socket->flags & IPX_BOUND) {
if(s == 65535) {
log_printf("bind failed: out of sockets?!");
RETURN_WSA(WSAEADDRNOTAVAIL, -1);
}
s++;
socket = sockets;
continue;
}
socket = socket->next;
}
ptr->socket = htons(s);
}else{
/* Test if any bound socket is using the requested socket number. */
ipx_socket *socket = sockets;
while(socket) {
if(socket->socket == ipxaddr->sa_socket && socket->flags & IPX_BOUND) {
log_printf("bind failed: requested socket in use");
RETURN_WSA(WSAEADDRINUSE, -1);
}
socket = socket->next;
}
ptr->socket = ipxaddr->sa_socket;
}
NET_TO_STRING(net_s, nic->ipx_net);
NODE_TO_STRING(node_s, nic->ipx_node);
log_printf("bind address: net=%s node=%s socket=%hu", net_s, node_s, ntohs(ptr->socket));
/* TODO: Bind fake socket in socket() call rather than here?
*
* I think I put the bind() call for it here so that the fd given to the
* program would be in the expected un-bound state, although I'm not sure
* if there are any winsock calls it could ONLY make on such a socket.
*/
struct sockaddr_in bind_addr; struct sockaddr_in bind_addr;
bind_addr.sin_family = AF_INET; bind_addr.sin_family = AF_INET;
bind_addr.sin_port = 0;
bind_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); bind_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind_addr.sin_port = 0;
int rval = r_bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)); if(r_bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1) {
log_printf("Binding local UDP socket failed: %s", w32_error(WSAGetLastError()));
if(rval == 0) {
ptr->flags |= IPX_BOUND; router_unbind(router, 0, fd);
}else{ RETURN(-1);
log_printf("Binding fake socket failed: %s", w32_error(WSAGetLastError()));
} }
RETURN(rval); int al = sizeof(bind_addr);
if(r_getsockname(fd, (struct sockaddr*)&bind_addr, &al) == -1) {
log_printf("getsockname failed: %s", w32_error(WSAGetLastError()));
router_unbind(router, 0, fd);
RETURN(-1);
}
memcpy(&(ptr->addr), &ipxaddr, sizeof(ipxaddr));
ptr->flags |= IPX_BOUND;
router_set_port(router, 0, fd, bind_addr.sin_port);
RETURN(0);
}else{ }else{
RETURN(r_bind(fd, addr, addrlen)); RETURN(r_bind(fd, addr, addrlen));
} }
@ -326,61 +268,10 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) {
* Attempts to bind socket 0 will really bind socket 0 * Attempts to bind socket 0 will really bind socket 0
*/ */
int ipx_ex_bind(SOCKET fd, const struct sockaddr_ipx *ipxaddr) { int ipx_ex_bind(SOCKET fd, const struct sockaddr_ipx *ipxaddr) {
ipx_socket *ptr = get_socket(fd); return 0;
if(!ipxaddr) {
/* Call with NULL address to remove extra bind */
log_printf("ipx_ex_bind(%d, NULL)", fd);
ptr->flags &= ~IPX_EX_BOUND;
RETURN(0);
}
char net_s[12], node_s[18];
NET_TO_STRING(net_s, ipxaddr->sa_netnum);
NODE_TO_STRING(node_s, ipxaddr->sa_nodenum);
log_printf("ipx_ex_bind(%d, net=%s node=%s socket=%hu)", fd, net_s, node_s, ntohs(ipxaddr->sa_socket));
if(!(ptr->flags & IPX_BOUND)) {
log_printf("ipx_ex_bind: Socket is not bound");
RETURN_WSA(WSAEINVAL, -1);
}
unsigned char z6[] = {0,0,0,0,0,0};
struct ipx_interface *nic = nics;
while(nic) {
if(
(memcmp(ipxaddr->sa_netnum, nic->ipx_net, 4) == 0 || memcmp(ipxaddr->sa_netnum, z6, 4) == 0) &&
(memcmp(ipxaddr->sa_nodenum, nic->ipx_node, 6) == 0 || memcmp(ipxaddr->sa_nodenum, z6, 6) == 0)
) {
break;
}
nic = nic->next;
}
if(!nic) {
log_printf("ipx_ex_bind: no such address");
RETURN_WSA(WSAEADDRNOTAVAIL, -1);
}
NET_TO_STRING(net_s, nic->ipx_net);
NODE_TO_STRING(node_s, nic->ipx_node);
log_printf("bind address: net=%s node=%s socket=%hu", net_s, node_s, ntohs(ipxaddr->sa_socket));
ptr->ex_nic = nic;
ptr->ex_socket = ipxaddr->sa_socket;
ptr->flags |= IPX_EX_BOUND;
RETURN(0);
} }
int WSAAPI getsockname(SOCKET fd, struct sockaddr *addr, int *addrlen) { int WSAAPI getsockname(SOCKET fd, struct sockaddr *addr, int *addrlen) {
struct sockaddr_ipx *ipxaddr = (struct sockaddr_ipx*)addr;
ipx_socket *ptr = get_socket(fd); ipx_socket *ptr = get_socket(fd);
if(ptr) { if(ptr) {
@ -390,11 +281,7 @@ int WSAAPI getsockname(SOCKET fd, struct sockaddr *addr, int *addrlen) {
RETURN_WSA(WSAEFAULT, -1); RETURN_WSA(WSAEFAULT, -1);
} }
ipxaddr->sa_family = AF_IPX; memcpy(addr, &(ptr->addr), sizeof(ptr->addr));
memcpy(ipxaddr->sa_netnum, ptr->nic->ipx_net, 4);
memcpy(ipxaddr->sa_nodenum, ptr->nic->ipx_node, 6);
ipxaddr->sa_socket = ptr->socket;
*addrlen = sizeof(struct sockaddr_ipx); *addrlen = sizeof(struct sockaddr_ipx);
RETURN(0); RETURN(0);
@ -629,11 +516,16 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
sockptr->f_ptype = *intval; sockptr->f_ptype = *intval;
sockptr->flags |= IPX_FILTER; sockptr->flags |= IPX_FILTER;
router_set_filter(router, 0, fd, *intval);
RETURN(0); RETURN(0);
} }
if(optname == IPX_STOPFILTERPTYPE) { if(optname == IPX_STOPFILTERPTYPE) {
sockptr->flags &= ~IPX_FILTER; sockptr->flags &= ~IPX_FILTER;
router_set_filter(router, 0, fd, -1);
RETURN(0); RETURN(0);
} }
@ -705,12 +597,12 @@ int WSAAPI sendto(SOCKET fd, const char *buf, int len, int flags, const struct s
unsigned char z6[] = {0,0,0,0,0,0}; unsigned char z6[] = {0,0,0,0,0,0};
if(memcmp(packet->dest_net, z6, 4) == 0) { if(memcmp(packet->dest_net, z6, 4) == 0) {
memcpy(packet->dest_net, sockptr->nic->ipx_net, 4); memcpy(packet->dest_net, sockptr->addr.sa_netnum, 4);
} }
memcpy(packet->src_net, sockptr->nic->ipx_net, 4); memcpy(packet->src_net, sockptr->addr.sa_netnum, 4);
memcpy(packet->src_node, sockptr->nic->ipx_node, 6); memcpy(packet->src_node, sockptr->addr.sa_nodenum, 6);
packet->src_socket = sockptr->socket; packet->src_socket = sockptr->addr.sa_socket;
packet->size = htons(len); packet->size = htons(len);
memcpy(packet->data, buf, len); memcpy(packet->data, buf, len);
@ -720,7 +612,7 @@ int WSAAPI sendto(SOCKET fd, const char *buf, int len, int flags, const struct s
struct sockaddr_in saddr; struct sockaddr_in saddr;
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(global_conf.udp_port); saddr.sin_port = htons(global_conf.udp_port);
saddr.sin_addr.s_addr = (host ? host->ipaddr : (global_conf.bcast_all ? INADDR_BROADCAST : sockptr->nic->bcast)); saddr.sin_addr.s_addr = (host ? host->ipaddr : (global_conf.bcast_all ? INADDR_BROADCAST : sockptr->nic_bcast));
int sval = r_sendto(net_fd, (char*)packet, psize, 0, (struct sockaddr*)&saddr, sizeof(saddr)); int sval = r_sendto(net_fd, (char*)packet, psize, 0, (struct sockaddr*)&saddr, sizeof(saddr));
if(sval == -1) { if(sval == -1) {
@ -744,6 +636,7 @@ int PASCAL shutdown(SOCKET fd, int cmd) {
if(cmd == SD_RECEIVE || cmd == SD_BOTH) { if(cmd == SD_RECEIVE || cmd == SD_BOTH) {
sockptr->flags &= ~IPX_RECV; sockptr->flags &= ~IPX_RECV;
router_set_port(router, 0, fd, 0);
} }
RETURN(0); RETURN(0);