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

View File

@ -29,6 +29,7 @@
#include "ipxwrapper.h"
#include "common.h"
#include "interface.h"
#include "router.h"
#define DLL_UNLOAD(dll) \
if(dll) {\
@ -41,7 +42,6 @@ struct ipx_interface *nics = NULL;
ipx_host *hosts = NULL;
SOCKET net_fd = -1;
struct reg_global global_conf;
static void *router_buf = NULL;
HMODULE winsock2_dll = NULL;
HMODULE mswsock_dll = NULL;
@ -49,10 +49,9 @@ HMODULE wsock32_dll = NULL;
static HANDLE mutex = NULL;
static HANDLE router_thread = NULL;
static DWORD router_tid = 0;
struct router_vars *router = NULL;
static int init_router(void);
static DWORD WINAPI router_main(LPVOID argp);
static BOOL start_router(void);
BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
if(why == DLL_PROCESS_ATTACH) {
@ -90,21 +89,23 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
return FALSE;
}
if(!init_router()) {
if(!start_router()) {
return FALSE;
}
}else if(why == DLL_PROCESS_DETACH) {
if(router_thread && GetCurrentThreadId() != router_tid) {
TerminateThread(router_thread, 0);
if(router_thread) {
EnterCriticalSection(&(router->crit_sec));
router->running = FALSE;
SetEvent(router->wsa_event);
LeaveCriticalSection(&(router->crit_sec));
WaitForSingleObject(router_thread, INFINITE);
router_thread = NULL;
}
free(router_buf);
router_buf = NULL;
if(net_fd >= 0) {
closesocket(net_fd);
net_fd = -1;
router_destroy(router);
router = NULL;
}
if(mutex) {
@ -182,143 +183,24 @@ void unlock_mutex(void) {
}
/* Initialize and start the router thread */
static int init_router(void) {
net_fd = r_socket(AF_INET, SOCK_DGRAM, 0);
if(net_fd == -1) {
log_printf("Failed to create network socket: %s", w32_error(WSAGetLastError()));
return 0;
static BOOL start_router(void) {
if(!(router = router_init(FALSE))) {
return FALSE;
}
struct sockaddr_in bind_addr;
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);
router_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&router_main, router, 0, NULL);
if(!router_thread) {
log_printf("Failed to create router thread");
return 0;
log_printf("Failed to create router thread: %s", w32_error(GetLastError()));
router_destroy(router);
router = NULL;
return FALSE;
}
return 1;
}
/* 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;
net_fd = router->udp_sock;
while(1) {
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;
return TRUE;
}
/* Add a host to the hosts list or update an existing one */

View File

@ -25,6 +25,7 @@
#include <stdio.h>
#include "config.h"
#include "router.h"
/* Maximum UDP data size is 65467, we use a smaller value to ensure we have
* 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 */
/* The following values are undefined when IPX_BOUND is not set */
struct ipx_interface *nic;
uint16_t socket; /* Stored in NETWORK BYTE ORDER */
struct sockaddr_ipx addr;
uint32_t nic_bcast;
/* Extra bind address, only used for receiving packets.
* Only defined when IPX_EX_BOUND is set.
@ -107,6 +108,7 @@ extern struct ipx_interface *nics;
extern ipx_host *hosts;
extern SOCKET net_fd;
extern struct reg_global global_conf;
extern struct router_vars *router;
extern HMODULE winsock2_dll;
extern HMODULE mswsock_dll;

View File

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

View File

@ -72,8 +72,8 @@ struct router_vars *router_init(BOOL global) {
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = 9999;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(global_conf.udp_port);
if(bind(router->udp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
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) {
struct router_vars *router = arg;
const unsigned char f6[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
while(1) {
WaitForSingleObject(router->wsa_event, INFINITE);
EnterCriticalSection(&(router->crit_sec));
WSAResetEvent(router->wsa_event);
if(!router->running) {
LeaveCriticalSection(&(router->crit_sec));
return 0;
}
LeaveCriticalSection(&(router->crit_sec));
struct sockaddr_in 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) {
LeaveCriticalSection(&(router->crit_sec));
if(WSAGetLastError() == WSAEWOULDBLOCK) {
if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET) {
continue;
}
@ -168,6 +172,8 @@ DWORD router_main(void *arg) {
return 1;
}
EnterCriticalSection(&(router->crit_sec));
ipx_packet *packet = (ipx_packet*)router->recvbuf;
/* Check that the packet arrived from the subnet of an enabled network
@ -186,6 +192,7 @@ DWORD router_main(void *arg) {
}
if(!iface) {
LeaveCriticalSection(&(router->crit_sec));
continue;
}
}
@ -193,7 +200,7 @@ DWORD router_main(void *arg) {
packet->size = ntohs(packet->size);
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;
}
@ -202,8 +209,6 @@ DWORD router_main(void *arg) {
struct router_addr *ra = router->addrs;
while(ra) {
unsigned char f6[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
if(
ra->local_port &&
(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_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()));
}
}
@ -228,7 +233,20 @@ DWORD router_main(void *arg) {
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;
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_nodenum, iface->ipx_node, 6);
*nic_bcast = iface->bcast;
free_interfaces(ifaces);
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));
}
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));
struct router_addr *addr = router->addrs, *prev = NULL;

View File

@ -61,9 +61,11 @@ struct router_vars {
struct router_vars *router_init(BOOL global);
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_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);
#endif /* !IPXWRAPPER_ROUTER_H */

View File

@ -26,6 +26,7 @@
#include "ipxwrapper.h"
#include "common.h"
#include "interface.h"
#include "router.h"
INT APIENTRY EnumProtocolsA(LPINT protocols, LPVOID buf, LPDWORD bsptr) {
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);
router_unbind(router, 0, fd);
if(ptr == sockets) {
sockets = ptr->next;
free(ptr);
@ -201,122 +204,61 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) {
ipx_socket *ptr = get_socket(fd);
if(ptr) {
struct sockaddr_ipx *ipxaddr = (struct sockaddr_ipx*)addr;
struct sockaddr_ipx ipxaddr;
char net_s[12], node_s[18];
NET_TO_STRING(net_s, ipxaddr->sa_netnum);
NODE_TO_STRING(node_s, ipxaddr->sa_nodenum);
if(addrlen < sizeof(ipxaddr)) {
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) {
log_printf("bind failed: socket already bound");
RETURN_WSA(WSAEINVAL, -1);
}
/* 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!
*/
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(router_bind(router, 0, fd, &ipxaddr, &(ptr->nic_bcast)) == -1) {
RETURN(-1);
}
if(!nic) {
log_printf("bind failed: no such address");
RETURN_WSA(WSAEADDRNOTAVAIL, -1);
}
NET_TO_STRING(net_s, ipxaddr.sa_netnum);
NODE_TO_STRING(node_s, ipxaddr.sa_nodenum);
ptr->nic = nic;
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.
*/
log_printf("bind address: net=%s node=%s socket=%hu", net_s, node_s, ntohs(ipxaddr.sa_socket));
struct sockaddr_in bind_addr;
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_port = 0;
int rval = r_bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr));
if(rval == 0) {
ptr->flags |= IPX_BOUND;
}else{
log_printf("Binding fake socket failed: %s", w32_error(WSAGetLastError()));
if(r_bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1) {
log_printf("Binding local UDP socket failed: %s", w32_error(WSAGetLastError()));
router_unbind(router, 0, fd);
RETURN(-1);
}
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{
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
*/
int ipx_ex_bind(SOCKET fd, const struct sockaddr_ipx *ipxaddr) {
ipx_socket *ptr = get_socket(fd);
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);
return 0;
}
int WSAAPI getsockname(SOCKET fd, struct sockaddr *addr, int *addrlen) {
struct sockaddr_ipx *ipxaddr = (struct sockaddr_ipx*)addr;
ipx_socket *ptr = get_socket(fd);
if(ptr) {
@ -390,11 +281,7 @@ int WSAAPI getsockname(SOCKET fd, struct sockaddr *addr, int *addrlen) {
RETURN_WSA(WSAEFAULT, -1);
}
ipxaddr->sa_family = AF_IPX;
memcpy(ipxaddr->sa_netnum, ptr->nic->ipx_net, 4);
memcpy(ipxaddr->sa_nodenum, ptr->nic->ipx_node, 6);
ipxaddr->sa_socket = ptr->socket;
memcpy(addr, &(ptr->addr), sizeof(ptr->addr));
*addrlen = sizeof(struct sockaddr_ipx);
RETURN(0);
@ -629,11 +516,16 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
sockptr->f_ptype = *intval;
sockptr->flags |= IPX_FILTER;
router_set_filter(router, 0, fd, *intval);
RETURN(0);
}
if(optname == IPX_STOPFILTERPTYPE) {
sockptr->flags &= ~IPX_FILTER;
router_set_filter(router, 0, fd, -1);
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};
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_node, sockptr->nic->ipx_node, 6);
packet->src_socket = sockptr->socket;
memcpy(packet->src_net, sockptr->addr.sa_netnum, 4);
memcpy(packet->src_node, sockptr->addr.sa_nodenum, 6);
packet->src_socket = sockptr->addr.sa_socket;
packet->size = htons(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;
saddr.sin_family = AF_INET;
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));
if(sval == -1) {
@ -744,6 +636,7 @@ int PASCAL shutdown(SOCKET fd, int cmd) {
if(cmd == SD_RECEIVE || cmd == SD_BOTH) {
sockptr->flags &= ~IPX_RECV;
router_set_port(router, 0, fd, 0);
}
RETURN(0);