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

Allow address sharing when the existing socket doesn't have SO_REUSEADDR.

The IPX/SPX protocol versions in 98/2000/XP only require the second socket to
have SO_REUSEADDR when attempting to bind to an already-used address. The state
of the option on the first socket is ignored.

The ADDR_TABLE_ENTRY_REUSE flag is kept and set on all sockets in the address
table to keep compatibility with previous versions.
This commit is contained in:
Daniel Collins 2014-01-05 02:40:21 +00:00
parent 533e35729d
commit 68d13baac2
5 changed files with 17 additions and 23 deletions

View File

@ -1,3 +1,6 @@
Version XXX:
Bugfix: Allow address reuse when only the binding socket has SO_REUSEADDR.
Version 0.4.1:
Feature: Added workaround for point-to-point links.

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Address table
* Copyright (C) 2008-2012 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2008-2014 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -179,7 +179,7 @@ void addr_table_unlock(void)
*
* Returns false if a conflict was confirmed, true otherwise.
*/
bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse)
bool addr_table_check(const struct sockaddr_ipx *addr)
{
if(addr_table_base)
{
@ -190,12 +190,8 @@ bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse)
while(entry < end && (entry->flags & ADDR_TABLE_ENTRY_VALID))
{
if(addr->sa_socket == entry->socket && (!(entry->flags & ADDR_TABLE_ENTRY_REUSE) || !reuse))
if(addr->sa_socket == entry->socket)
{
/* A socket is already bound to this address and either
* it or this one doesn't have SO_REUSEADDR set.
*/
addr_table_unlock();
return false;
}
@ -217,7 +213,7 @@ bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse)
HASH_ITER(hh, sockets, s, tmp)
{
if(memcmp(&(s->addr), addr, sizeof(struct sockaddr_ipx)) == 0 && (!(s->flags & IPX_REUSE) || !reuse))
if(memcmp(&(s->addr), addr, sizeof(struct sockaddr_ipx)) == 0)
{
unlock_sockets();
return true;
@ -303,7 +299,7 @@ uint16_t addr_table_auto_socket(void)
* Performs no conflict checking. Take the address table lock in the caller and
* use addr_table_check() before calling this.
*/
void addr_table_add(const struct sockaddr_ipx *addr, uint16_t port, bool reuse)
void addr_table_add(const struct sockaddr_ipx *addr, uint16_t port)
{
if(!addr_table_base)
{
@ -330,12 +326,7 @@ void addr_table_add(const struct sockaddr_ipx *addr, uint16_t port, bool reuse)
entry->nodenum = addr48_in(addr->sa_nodenum);
entry->socket = addr->sa_socket;
entry->flags = ADDR_TABLE_ENTRY_VALID;
if(reuse)
{
entry->flags |= ADDR_TABLE_ENTRY_REUSE;
}
entry->flags = ADDR_TABLE_ENTRY_VALID | ADDR_TABLE_ENTRY_REUSE;
entry->port = port;
entry->time = time(NULL);

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Address table
* Copyright (C) 2008-2012 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2008-2014 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -61,10 +61,10 @@ void addr_table_cleanup(void);
void addr_table_lock(void);
void addr_table_unlock(void);
bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse);
bool addr_table_check(const struct sockaddr_ipx *addr);
uint16_t addr_table_auto_socket(void);
void addr_table_add(const struct sockaddr_ipx *addr, uint16_t port, bool reuse);
void addr_table_add(const struct sockaddr_ipx *addr, uint16_t port);
void addr_table_remove(uint16_t port);
void addr_table_update(void);

View File

@ -1,5 +1,5 @@
/* ipxwrapper - Winsock functions
* Copyright (C) 2008 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2008-2014 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -335,7 +335,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen)
/* Check that the address is free. */
if(!addr_table_check(&ipxaddr, !!(sock->flags & IPX_REUSE)))
if(!(sock->flags & IPX_REUSE) && !addr_table_check(&ipxaddr))
{
/* Address has already been bound. */
@ -401,7 +401,7 @@ int WSAAPI bind(SOCKET fd, const struct sockaddr *addr, int addrlen)
/* Add to the address table. */
addr_table_add(&ipxaddr, sock->port, !!(sock->flags & IPX_REUSE));
addr_table_add(&ipxaddr, sock->port);
/* Mark the IPX socket as bound. */

View File

@ -81,7 +81,7 @@ try_binds(
try_binds(
"Single process, conflicting socket numbers, second using SO_REUSEADDR",
"bind.exe 0 1234 --reuse 0 1234" => "FAIL",
"bind.exe 0 1234 --reuse 0 1234" => "OK",
);
try_binds(
@ -144,7 +144,7 @@ try_binds(
"Two processes, conflicting socket numbers, second using SO_REUSEADDR",
"bind.exe 0 1234" => "OK",
"bind.exe --reuse 0 1234" => "FAIL",
"bind.exe --reuse 0 1234" => "OK",
);
sub try_binds