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

Implemented connect function.

This commit is contained in:
Daniel Collins 2011-09-15 18:47:31 +00:00
parent 18fda2a86c
commit 390663ba83
7 changed files with 119 additions and 8 deletions

View File

@ -15,3 +15,4 @@ EXPORTS
WSARecvEx
ioctlsocket
WSHEnumProtocols
connect

View File

@ -39,6 +39,7 @@
#define IPX_SEND (int)(1<<3)
#define IPX_RECV (int)(1<<4)
#define IPX_REUSE (int)(1<<6)
#define IPX_CONNECTED (int)(1<<7)
#define RETURN(...) \
unlock_sockets();\
@ -64,11 +65,8 @@ struct ipx_socket {
struct sockaddr_ipx addr;
uint32_t nic_bcast;
/* Extra bind address, only used for receiving packets.
* Only defined when IPX_EX_BOUND is set.
*/
struct ipx_interface *ex_nic;
uint16_t ex_socket;
/* Address used with connect call, only set when IPX_CONNECTED is */
struct sockaddr_ipx remote_addr;
ipx_socket *next;
};
@ -131,5 +129,6 @@ int WSAAPI r_setsockopt(SOCKET,int,int,const char*,int);
int WSAAPI r_shutdown(SOCKET,int);
SOCKET WSAAPI r_socket(int,int,int);
int PASCAL r_ioctlsocket(SOCKET fd, long cmd, u_long *argp);
int PASCAL r_connect(SOCKET fd, const struct sockaddr *addr, int addrlen);
#endif /* !IPXWRAPPER_H */

View File

@ -31,3 +31,4 @@ r_setsockopt:4
r_shutdown:4
r_socket:4
r_ioctlsocket:4
r_connect:4

View File

@ -297,7 +297,10 @@ DWORD router_main(void *arg) {
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) || !global_conf.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))
) {
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = ra->local_port;
@ -538,6 +541,18 @@ static int router_set_reuse(struct router_vars *router, SOCKET control, SOCKET s
return 1;
}
static BOOL router_set_remote(struct router_vars *router, SOCKET control, SOCKET sock, const struct sockaddr_ipx *addr) {
EnterCriticalSection(&(router->crit_sec));
struct router_addr *ra = router_get(router, control, sock);
if(ra) {
ra->remote_addr = *addr;
}
LeaveCriticalSection(&(router->crit_sec));
return TRUE;
}
static BOOL router_handle_call(struct router_vars *router, int sock, struct router_call *call) {
struct router_ret ret;
@ -577,6 +592,11 @@ static BOOL router_handle_call(struct router_vars *router, int sock, struct rout
break;
}
case rc_remote: {
router_set_remote(router, sock, call->sock, &(call->arg_addr));
break;
}
default: {
log_printf("Recieved unknown call, dropping client");
return FALSE;
@ -893,3 +913,27 @@ BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse) {
WSASetLastError(WSAENETDOWN);
return FALSE;
}
BOOL rclient_set_remote(struct rclient *rclient, SOCKET sock, const struct sockaddr_ipx *addr) {
if(rclient->sock != -1) {
struct router_call call;
struct router_ret ret;
call.call = rc_remote;
call.sock = sock;
call.arg_addr = *addr;
if(!rclient_do(rclient, &call, &ret)) {
return FALSE;
}
return TRUE;
}else if(rclient->router) {
return router_set_remote(rclient->router, 0, sock, addr);
}
log_printf("rclient_bind: No router?!");
WSASetLastError(WSAENETDOWN);
return FALSE;
}

View File

@ -31,7 +31,8 @@ struct router_call {
rc_unbind,
rc_port,
rc_filter,
rc_reuse
rc_reuse,
rc_remote
} call;
SOCKET sock;
@ -61,6 +62,9 @@ struct router_addr {
uint32_t ipaddr;
uint32_t netmask;
/* Only accept packets from this address (any if AF_UNSPEC) */
struct sockaddr_ipx remote_addr;
struct router_addr *next;
};
@ -114,5 +118,6 @@ BOOL rclient_unbind(struct rclient *rclient, SOCKET sock);
BOOL rclient_set_port(struct rclient *rclient, SOCKET sock, uint16_t port);
BOOL rclient_set_filter(struct rclient *rclient, SOCKET sock, int ptype);
BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse);
BOOL rclient_set_remote(struct rclient *rclient, SOCKET sock, const struct sockaddr_ipx *addr);
#endif /* !IPXWRAPPER_ROUTER_H */

View File

@ -741,3 +741,64 @@ int PASCAL ioctlsocket(SOCKET fd, long cmd, u_long *argp) {
return r_ioctlsocket(fd, cmd, argp);
}
int PASCAL connect(SOCKET fd, const struct sockaddr *addr, int addrlen) {
ipx_socket *sockptr = get_socket(fd);
if(sockptr) {
if(addrlen < sizeof(struct sockaddr_ipx)) {
RETURN_WSA(WSAEFAULT, -1);
}
struct sockaddr_ipx *ipxaddr = (struct sockaddr_ipx*)addr;
const unsigned char z6[] = {0,0,0,0,0,0};
if(ipxaddr->sa_family == AF_UNSPEC || (ipxaddr->sa_family == AF_IPX && memcmp(ipxaddr->sa_nodenum, z6, 6) == 0)) {
if(!(sockptr->flags & IPX_CONNECTED)) {
RETURN(0);
}
struct sockaddr_ipx dc_addr;
dc_addr.sa_family = AF_UNSPEC;
if(!rclient_set_remote(&g_rclient, fd, &dc_addr)) {
RETURN(-1);
}
sockptr->flags &= ~IPX_CONNECTED;
RETURN(0);
}
if(ipxaddr->sa_family != AF_IPX) {
RETURN_WSA(WSAEAFNOSUPPORT, -1);
}
if(!(sockptr->flags & IPX_BOUND)) {
log_printf("connect() on unbound socket, attempting implicit bind");
struct sockaddr_ipx bind_addr;
bind_addr.sa_family = AF_IPX;
memcpy(bind_addr.sa_netnum, ipxaddr->sa_netnum, 4);
memset(bind_addr.sa_nodenum, 0, 6);
bind_addr.sa_socket = 0;
if(bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1) {
RETURN(-1);
}
}
if(!rclient_set_remote(&g_rclient, fd, ipxaddr)) {
RETURN(-1);
}
memcpy(&(sockptr->remote_addr), addr, sizeof(*ipxaddr));
sockptr->flags |= IPX_CONNECTED;
RETURN(0);
}else{
return r_connect(fd, addr, addrlen);
}
}

View File

@ -1,7 +1,7 @@
accept
bind:0
closesocket:0
connect
connect:0
getpeername
getsockname:0
getsockopt:0