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

Implemented IPX_RECEIVE_BROADCAST option, updated router/rclient API and added proper checks when receiving broadcast packets to the router main loop.

This commit is contained in:
Daniel Collins 2011-09-17 23:47:31 +00:00
parent 646ab3b011
commit fd555ce7c2
5 changed files with 65 additions and 49 deletions

View File

@ -85,5 +85,5 @@ src/dpwsockx_stubs.s: src/dpwsockx_stubs.txt
src/%_stubs.o: src/%_stubs.s src/%_stubs.o: src/%_stubs.s
nasm -f win32 -o $@ $< nasm -f win32 -o $@ $<
src/%.o: src/%.c src/ipxwrapper.h src/config.h src/common.h src/%.o: src/%.c src/ipxwrapper.h src/config.h src/common.h src/router.h
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<

View File

@ -38,6 +38,7 @@
#define IPX_RECV (int)(1<<4) #define IPX_RECV (int)(1<<4)
#define IPX_REUSE (int)(1<<6) #define IPX_REUSE (int)(1<<6)
#define IPX_CONNECTED (int)(1<<7) #define IPX_CONNECTED (int)(1<<7)
#define IPX_RECV_BCAST (int)(1<<8)
#define RETURN(...) \ #define RETURN(...) \
unlock_sockets();\ unlock_sockets();\

View File

@ -287,8 +287,8 @@ DWORD router_main(void *arg) {
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) &&
(memcmp(packet->dest_net, ra->addr.sa_netnum, 4) == 0 || memcmp(packet->dest_net, f6, 4) == 0) && (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) && (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)) &&
packet->dest_socket == ra->addr.sa_socket && packet->dest_socket == ra->addr.sa_socket &&
/* Check source IP is within correct subnet */ /* Check source IP is within correct subnet */
@ -314,7 +314,7 @@ DWORD router_main(void *arg) {
return 0; return 0;
} }
static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse) { static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, int flags) {
/* Network number 00:00:00:00 is specified as the "current" network, this code /* 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. * treats it as a wildcard when used for the network OR node numbers.
* *
@ -406,7 +406,7 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock,
struct router_addr *a = router->addrs; struct router_addr *a = router->addrs;
while(a) { while(a) {
if(a->addr.sa_socket == addr->sa_socket && (!a->reuse || !reuse)) { if(a->addr.sa_socket == addr->sa_socket && (!(a->flags & IPX_REUSE) || !(flags & IPX_REUSE))) {
log_printf("bind failed: requested socket in use"); log_printf("bind failed: requested socket in use");
LeaveCriticalSection(&(router->crit_sec)); LeaveCriticalSection(&(router->crit_sec));
@ -433,7 +433,7 @@ static int router_bind(struct router_vars *router, SOCKET control, SOCKET sock,
new_addr->ws_socket = sock; new_addr->ws_socket = sock;
new_addr->control_socket = control; new_addr->control_socket = control;
new_addr->filter_ptype = -1; new_addr->filter_ptype = -1;
new_addr->reuse = reuse; new_addr->flags = flags;
new_addr->ipaddr = iface_ipaddr; new_addr->ipaddr = iface_ipaddr;
new_addr->netmask = iface_netmask; new_addr->netmask = iface_netmask;
new_addr->next = router->addrs; new_addr->next = router->addrs;
@ -512,28 +512,30 @@ static void router_set_filter(struct router_vars *router, SOCKET control, SOCKET
LeaveCriticalSection(&(router->crit_sec)); LeaveCriticalSection(&(router->crit_sec));
} }
static int router_set_reuse(struct router_vars *router, SOCKET control, SOCKET sock, BOOL reuse) { static int router_set_flags(struct router_vars *router, SOCKET control, SOCKET sock, int flags) {
EnterCriticalSection(&(router->crit_sec)); EnterCriticalSection(&(router->crit_sec));
struct router_addr *addr = router_get(router, control, sock); struct router_addr *addr = router_get(router, control, sock);
if(addr) { if(addr) {
if(addr->flags & IPX_REUSE && !(flags & IPX_REUSE)) {
struct router_addr *test = router->addrs; struct router_addr *test = router->addrs;
while(test) { while(test) {
if(addr != test && memcmp(&(addr->addr), &(test->addr), sizeof(struct sockaddr_ipx)) == 0 && !reuse) { if(addr != test && memcmp(&(addr->addr), &(test->addr), sizeof(struct sockaddr_ipx)) == 0) {
/* Refuse to disable SO_REUSEADDR when another binding for the same address exists */ /* Refuse to disable SO_REUSEADDR when another binding for the same address exists */
LeaveCriticalSection(&(router->crit_sec)); LeaveCriticalSection(&(router->crit_sec));
return 0; return WSAEINVAL;
} }
test = test->next; test = test->next;
} }
}
addr->reuse = reuse; addr->flags = flags;
} }
LeaveCriticalSection(&(router->crit_sec)); LeaveCriticalSection(&(router->crit_sec));
return 1; return ERROR_SUCCESS;
} }
static BOOL router_set_remote(struct router_vars *router, SOCKET control, SOCKET sock, const struct sockaddr_ipx *addr) { static BOOL router_set_remote(struct router_vars *router, SOCKET control, SOCKET sock, const struct sockaddr_ipx *addr) {
@ -579,11 +581,8 @@ static BOOL router_handle_call(struct router_vars *router, int sock, struct rout
break; break;
} }
case rc_reuse: { case rc_flags: {
if(!router_set_reuse(router, sock, call->sock, call->arg_int)) { ret.err_code = router_set_flags(router, sock, call->sock, call->arg_int);
ret.err_code = WSAEINVAL;
}
break; break;
} }
@ -879,14 +878,14 @@ BOOL rclient_set_filter(struct rclient *rclient, SOCKET sock, int ptype) {
return FALSE; return FALSE;
} }
BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse) { BOOL rclient_set_flags(struct rclient *rclient, SOCKET sock, int flags) {
if(rclient->sock != -1) { if(rclient->sock != -1) {
struct router_call call; struct router_call call;
struct router_ret ret; struct router_ret ret;
call.call = rc_reuse; call.call = rc_flags;
call.sock = sock; call.sock = sock;
call.arg_int = reuse; call.arg_int = flags;
if(!rclient_do(rclient, &call, &ret)) { if(!rclient_do(rclient, &call, &ret)) {
return FALSE; return FALSE;
@ -895,11 +894,18 @@ BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse) {
if(ret.err_code == ERROR_SUCCESS) { if(ret.err_code == ERROR_SUCCESS) {
return TRUE; return TRUE;
}else{ }else{
WSASetLastError(WSAEINVAL); WSASetLastError(ret.err_code);
return FALSE; return FALSE;
} }
}else if(rclient->router) { }else if(rclient->router) {
router_set_reuse(rclient->router, 0, sock, reuse); int err = router_set_flags(rclient->router, 0, sock, flags);
if(err == ERROR_SUCCESS) {
return TRUE;
}else{
WSASetLastError(err);
return FALSE;
}
return TRUE; return TRUE;
} }

View File

@ -31,7 +31,7 @@ struct router_call {
rc_unbind, rc_unbind,
rc_port, rc_port,
rc_filter, rc_filter,
rc_reuse, rc_flags,
rc_remote rc_remote
} call; } call;
@ -56,7 +56,7 @@ struct router_addr {
SOCKET ws_socket; /* Application socket */ SOCKET ws_socket; /* Application socket */
SOCKET control_socket; /* Control socket */ SOCKET control_socket; /* Control socket */
int filter_ptype; /* Packet type filter, negative to disable */ int filter_ptype; /* Packet type filter, negative to disable */
BOOL reuse; /* SO_REUSEADDR */ int flags;
/* Address of IP interface */ /* Address of IP interface */
uint32_t ipaddr; uint32_t ipaddr;
@ -118,11 +118,11 @@ BOOL rclient_init(struct rclient *rclient);
BOOL rclient_start(struct rclient *rclient); BOOL rclient_start(struct rclient *rclient);
void rclient_stop(struct rclient *rclient); void rclient_stop(struct rclient *rclient);
BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse); BOOL rclient_bind(struct rclient *rclient, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, int flags);
BOOL rclient_unbind(struct rclient *rclient, SOCKET sock); BOOL rclient_unbind(struct rclient *rclient, SOCKET sock);
BOOL rclient_set_port(struct rclient *rclient, SOCKET sock, uint16_t port); 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_filter(struct rclient *rclient, SOCKET sock, int ptype);
BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse); BOOL rclient_set_flags(struct rclient *rclient, SOCKET sock, int flags);
BOOL rclient_set_remote(struct rclient *rclient, SOCKET sock, const struct sockaddr_ipx *addr); BOOL rclient_set_remote(struct rclient *rclient, SOCKET sock, const struct sockaddr_ipx *addr);
#endif /* !IPXWRAPPER_ROUTER_H */ #endif /* !IPXWRAPPER_ROUTER_H */

View File

@ -160,7 +160,7 @@ SOCKET WSAAPI socket(int af, int type, int protocol) {
return -1; return -1;
} }
nsock->flags = IPX_SEND | IPX_RECV; nsock->flags = IPX_SEND | IPX_RECV | IPX_RECV_BCAST;
nsock->s_ptype = (protocol ? NSPROTO_IPX - protocol : 0); nsock->s_ptype = (protocol ? NSPROTO_IPX - protocol : 0);
lock_sockets(); lock_sockets();
@ -544,6 +544,18 @@ int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int F
return r_getsockopt(fd, level, optname, optval, optlen); return r_getsockopt(fd, level, optname, optval, optlen);
} }
#define SET_FLAG(flag, state) \
if(state) { \
sockptr->flags |= flag; \
}else{ \
sockptr->flags &= flag; \
}
#define RC_SET_FLAG(flag, state) \
if(sockptr->flags & IPX_BOUND && !rclient_set_flags(&g_rclient, fd, (sockptr->flags & ~(flag)) | ((state) ? (flag) : 0))) { \
RETURN(-1); \
}
int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval, int optlen) { int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval, int optlen) {
int *intval = (int*)optval; int *intval = (int*)optval;
BOOL *bval = (BOOL*)optval; BOOL *bval = (BOOL*)optval;
@ -578,28 +590,25 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
RETURN(0); RETURN(0);
} }
if(optname == IPX_RECEIVE_BROADCAST) {
RC_SET_FLAG(IPX_RECV_BCAST, *bval);
SET_FLAG(IPX_RECV_BCAST, *bval);
RETURN(0);
}
RETURN_WSA(WSAENOPROTOOPT, -1); RETURN_WSA(WSAENOPROTOOPT, -1);
} }
if(level == SOL_SOCKET) { if(level == SOL_SOCKET) {
if(optname == SO_BROADCAST) { if(optname == SO_BROADCAST) {
if(*bval) { SET_FLAG(IPX_BROADCAST, *bval);
sockptr->flags |= IPX_BROADCAST;
}else{
sockptr->flags &= ~IPX_BROADCAST;
}
RETURN(0); RETURN(0);
}else if(optname == SO_REUSEADDR) {
if(sockptr->flags & IPX_BOUND && !rclient_set_reuse(&g_rclient, fd, *bval)) {
RETURN(-1);
} }
if(*bval) { if(optname == SO_REUSEADDR) {
sockptr->flags |= IPX_REUSE; RC_SET_FLAG(IPX_REUSE, *bval);
}else{ SET_FLAG(IPX_REUSE, *bval);
sockptr->flags &= ~IPX_REUSE;
}
RETURN(0); RETURN(0);
} }