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:
parent
646ab3b011
commit
fd555ce7c2
2
Makefile
2
Makefile
@ -85,5 +85,5 @@ src/dpwsockx_stubs.s: src/dpwsockx_stubs.txt
|
||||
src/%_stubs.o: src/%_stubs.s
|
||||
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 $@ $<
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define IPX_RECV (int)(1<<4)
|
||||
#define IPX_REUSE (int)(1<<6)
|
||||
#define IPX_CONNECTED (int)(1<<7)
|
||||
#define IPX_RECV_BCAST (int)(1<<8)
|
||||
|
||||
#define RETURN(...) \
|
||||
unlock_sockets();\
|
||||
|
60
src/router.c
60
src/router.c
@ -287,8 +287,8 @@ DWORD router_main(void *arg) {
|
||||
if(
|
||||
ra->local_port &&
|
||||
(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_node, ra->addr.sa_nodenum, 6) == 0 || memcmp(packet->dest_node, f6, 6) == 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 && (ra->flags & IPX_BROADCAST || !global_conf.w95_bug) && ra->flags & IPX_RECV_BCAST)) &&
|
||||
packet->dest_socket == ra->addr.sa_socket &&
|
||||
|
||||
/* Check source IP is within correct subnet */
|
||||
@ -314,7 +314,7 @@ DWORD router_main(void *arg) {
|
||||
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
|
||||
* 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;
|
||||
|
||||
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");
|
||||
|
||||
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->control_socket = control;
|
||||
new_addr->filter_ptype = -1;
|
||||
new_addr->reuse = reuse;
|
||||
new_addr->flags = flags;
|
||||
new_addr->ipaddr = iface_ipaddr;
|
||||
new_addr->netmask = iface_netmask;
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
struct router_addr *addr = router_get(router, control, sock);
|
||||
if(addr) {
|
||||
struct router_addr *test = router->addrs;
|
||||
|
||||
while(test) {
|
||||
if(addr != test && memcmp(&(addr->addr), &(test->addr), sizeof(struct sockaddr_ipx)) == 0 && !reuse) {
|
||||
/* Refuse to disable SO_REUSEADDR when another binding for the same address exists */
|
||||
LeaveCriticalSection(&(router->crit_sec));
|
||||
return 0;
|
||||
}
|
||||
if(addr->flags & IPX_REUSE && !(flags & IPX_REUSE)) {
|
||||
struct router_addr *test = router->addrs;
|
||||
|
||||
test = test->next;
|
||||
while(test) {
|
||||
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 */
|
||||
LeaveCriticalSection(&(router->crit_sec));
|
||||
return WSAEINVAL;
|
||||
}
|
||||
|
||||
test = test->next;
|
||||
}
|
||||
}
|
||||
|
||||
addr->reuse = reuse;
|
||||
addr->flags = flags;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -579,11 +581,8 @@ static BOOL router_handle_call(struct router_vars *router, int sock, struct rout
|
||||
break;
|
||||
}
|
||||
|
||||
case rc_reuse: {
|
||||
if(!router_set_reuse(router, sock, call->sock, call->arg_int)) {
|
||||
ret.err_code = WSAEINVAL;
|
||||
}
|
||||
|
||||
case rc_flags: {
|
||||
ret.err_code = router_set_flags(router, sock, call->sock, call->arg_int);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -879,14 +878,14 @@ BOOL rclient_set_filter(struct rclient *rclient, SOCKET sock, int ptype) {
|
||||
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) {
|
||||
struct router_call call;
|
||||
struct router_ret ret;
|
||||
|
||||
call.call = rc_reuse;
|
||||
call.call = rc_flags;
|
||||
call.sock = sock;
|
||||
call.arg_int = reuse;
|
||||
call.arg_int = flags;
|
||||
|
||||
if(!rclient_do(rclient, &call, &ret)) {
|
||||
return FALSE;
|
||||
@ -895,11 +894,18 @@ BOOL rclient_set_reuse(struct rclient *rclient, SOCKET sock, BOOL reuse) {
|
||||
if(ret.err_code == ERROR_SUCCESS) {
|
||||
return TRUE;
|
||||
}else{
|
||||
WSASetLastError(WSAEINVAL);
|
||||
WSASetLastError(ret.err_code);
|
||||
return FALSE;
|
||||
}
|
||||
}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;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ struct router_call {
|
||||
rc_unbind,
|
||||
rc_port,
|
||||
rc_filter,
|
||||
rc_reuse,
|
||||
rc_flags,
|
||||
rc_remote
|
||||
} call;
|
||||
|
||||
@ -56,7 +56,7 @@ struct router_addr {
|
||||
SOCKET ws_socket; /* Application socket */
|
||||
SOCKET control_socket; /* Control socket */
|
||||
int filter_ptype; /* Packet type filter, negative to disable */
|
||||
BOOL reuse; /* SO_REUSEADDR */
|
||||
int flags;
|
||||
|
||||
/* Address of IP interface */
|
||||
uint32_t ipaddr;
|
||||
@ -118,11 +118,11 @@ BOOL rclient_init(struct rclient *rclient);
|
||||
BOOL rclient_start(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_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_flags(struct rclient *rclient, SOCKET sock, int flags);
|
||||
BOOL rclient_set_remote(struct rclient *rclient, SOCKET sock, const struct sockaddr_ipx *addr);
|
||||
|
||||
#endif /* !IPXWRAPPER_ROUTER_H */
|
||||
|
@ -160,7 +160,7 @@ SOCKET WSAAPI socket(int af, int type, int protocol) {
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#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 *intval = (int*)optval;
|
||||
BOOL *bval = (BOOL*)optval;
|
||||
@ -578,28 +590,25 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
|
||||
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);
|
||||
}
|
||||
|
||||
if(level == SOL_SOCKET) {
|
||||
if(optname == SO_BROADCAST) {
|
||||
if(*bval) {
|
||||
sockptr->flags |= IPX_BROADCAST;
|
||||
}else{
|
||||
sockptr->flags &= ~IPX_BROADCAST;
|
||||
}
|
||||
|
||||
SET_FLAG(IPX_BROADCAST, *bval);
|
||||
RETURN(0);
|
||||
}else if(optname == SO_REUSEADDR) {
|
||||
if(sockptr->flags & IPX_BOUND && !rclient_set_reuse(&g_rclient, fd, *bval)) {
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
if(*bval) {
|
||||
sockptr->flags |= IPX_REUSE;
|
||||
}else{
|
||||
sockptr->flags &= ~IPX_REUSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(optname == SO_REUSEADDR) {
|
||||
RC_SET_FLAG(IPX_REUSE, *bval);
|
||||
SET_FLAG(IPX_REUSE, *bval);
|
||||
|
||||
RETURN(0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user