mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Implemented proper SO_REUSEADDR support and fixed getsockopt to return proper value when SOL_SOCKET/SO_BROADCAST is requested.
This commit is contained in:
parent
48b141d7e9
commit
b1828e0958
@ -39,6 +39,7 @@
|
||||
#define IPX_SEND (int)(1<<3)
|
||||
#define IPX_RECV (int)(1<<4)
|
||||
#define IPX_EX_BOUND (int)(1<<5)
|
||||
#define IPX_REUSE (int)(1<<6)
|
||||
|
||||
#define RETURN(...) \
|
||||
unlock_sockets();\
|
||||
|
31
src/router.c
31
src/router.c
@ -240,7 +240,7 @@ DWORD router_main(void *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast) {
|
||||
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse) {
|
||||
/* 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.
|
||||
*
|
||||
@ -323,13 +323,13 @@ int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct
|
||||
}
|
||||
|
||||
addr->sa_socket = htons(s);
|
||||
}else if(addr->sa_family != AF_IPX_SHARE) {
|
||||
}else{
|
||||
/* Test if any bound socket is using the requested socket number. */
|
||||
|
||||
struct router_addr *a = router->addrs;
|
||||
|
||||
while(a) {
|
||||
if(a->addr.sa_socket == addr->sa_socket) {
|
||||
if(a->addr.sa_socket == addr->sa_socket && (!a->reuse || !reuse)) {
|
||||
log_printf("bind failed: requested socket in use");
|
||||
|
||||
LeaveCriticalSection(&(router->crit_sec));
|
||||
@ -356,6 +356,7 @@ int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct
|
||||
new_addr->ws_socket = sock;
|
||||
new_addr->control_socket = control;
|
||||
new_addr->filter_ptype = -1;
|
||||
new_addr->reuse = reuse;
|
||||
new_addr->next = NULL;
|
||||
|
||||
router->addrs = new_addr;
|
||||
@ -431,3 +432,27 @@ void router_set_filter(struct router_vars *router, SOCKET control, SOCKET sock,
|
||||
|
||||
LeaveCriticalSection(&(router->crit_sec));
|
||||
}
|
||||
|
||||
int router_set_reuse(struct router_vars *router, SOCKET control, SOCKET sock, BOOL reuse) {
|
||||
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;
|
||||
}
|
||||
|
||||
test = test->next;
|
||||
}
|
||||
|
||||
addr->reuse = reuse;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&(router->crit_sec));
|
||||
return 1;
|
||||
}
|
||||
|
@ -23,11 +23,6 @@
|
||||
#include <wsipx.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Special address family for use when binding AF_IPX sockets, allows multiple
|
||||
* sockets to share the same address.
|
||||
*/
|
||||
#define AF_IPX_SHARE 42
|
||||
|
||||
/* Represents a bound IPX address */
|
||||
struct router_addr {
|
||||
struct sockaddr_ipx addr;
|
||||
@ -36,6 +31,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 */
|
||||
|
||||
struct router_addr *next;
|
||||
};
|
||||
@ -63,9 +59,10 @@ void router_destroy(struct router_vars *router);
|
||||
|
||||
DWORD router_main(void *arg);
|
||||
|
||||
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast);
|
||||
int router_bind(struct router_vars *router, SOCKET control, SOCKET sock, struct sockaddr_ipx *addr, uint32_t *nic_bcast, BOOL reuse);
|
||||
void router_set_port(struct router_vars *router, SOCKET control, SOCKET sock, uint16_t port);
|
||||
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);
|
||||
int router_set_reuse(struct router_vars *router, SOCKET control, SOCKET sock, BOOL reuse);
|
||||
|
||||
#endif /* !IPXWRAPPER_ROUTER_H */
|
||||
|
@ -190,7 +190,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen) {
|
||||
RETURN_WSA(WSAEINVAL, -1);
|
||||
}
|
||||
|
||||
if(router_bind(router, 0, fd, &ipxaddr, &(ptr->nic_bcast)) == -1) {
|
||||
if(router_bind(router, 0, fd, &ipxaddr, &(ptr->nic_bcast), ptr->flags & IPX_REUSE ? TRUE : FALSE) == -1) {
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
@ -395,6 +395,7 @@ int PASCAL WSARecvEx(SOCKET fd, char *buf, int len, int *flags) {
|
||||
|
||||
int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int FAR *optlen) {
|
||||
int* intval = (int*)optval;
|
||||
BOOL *bval = (BOOL*)optval;
|
||||
|
||||
ipx_socket *ptr = get_socket(fd);
|
||||
|
||||
@ -473,6 +474,22 @@ int WSAAPI getsockopt(SOCKET fd, int level, int optname, char FAR *optval, int F
|
||||
RETURN_WSA(WSAENOPROTOOPT, -1);
|
||||
}
|
||||
|
||||
if(level == SOL_SOCKET) {
|
||||
if(optname == SO_BROADCAST) {
|
||||
CHECK_OPTLEN(sizeof(BOOL));
|
||||
|
||||
*bval = ptr->flags & IPX_BROADCAST ? TRUE : FALSE;
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
if(optname == SO_REUSEADDR) {
|
||||
CHECK_OPTLEN(sizeof(BOOL));
|
||||
|
||||
*bval = ptr->flags & IPX_REUSE ? TRUE : FALSE;
|
||||
RETURN(0);
|
||||
}
|
||||
}
|
||||
|
||||
unlock_sockets();
|
||||
}
|
||||
|
||||
@ -514,12 +531,25 @@ int WSAAPI setsockopt(SOCKET fd, int level, int optname, const char FAR *optval,
|
||||
|
||||
if(level == SOL_SOCKET) {
|
||||
if(optname == SO_BROADCAST) {
|
||||
if(*bval == TRUE) {
|
||||
if(*bval) {
|
||||
sockptr->flags |= IPX_BROADCAST;
|
||||
}else{
|
||||
sockptr->flags &= ~IPX_BROADCAST;
|
||||
}
|
||||
|
||||
RETURN(0);
|
||||
}else if(optname == SO_REUSEADDR) {
|
||||
if(!router_set_reuse(router, 0, fd, *bval)) {
|
||||
WSASetLastError(WSAEINVAL);
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
if(*bval) {
|
||||
sockptr->flags |= IPX_REUSE;
|
||||
}else{
|
||||
sockptr->flags &= ~IPX_REUSE;
|
||||
}
|
||||
|
||||
RETURN(0);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user