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
|
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 $@ $<
|
||||||
|
@ -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();\
|
||||||
|
46
src/router.c
46
src/router.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user