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: Version 0.4.1:
Feature: Added workaround for point-to-point links. Feature: Added workaround for point-to-point links.

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Address table /* 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 * 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 * 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. * 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) 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)) 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(); addr_table_unlock();
return false; return false;
} }
@ -217,7 +213,7 @@ bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse)
HASH_ITER(hh, sockets, s, tmp) 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(); unlock_sockets();
return true; 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 * Performs no conflict checking. Take the address table lock in the caller and
* use addr_table_check() before calling this. * 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) 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->nodenum = addr48_in(addr->sa_nodenum);
entry->socket = addr->sa_socket; entry->socket = addr->sa_socket;
entry->flags = ADDR_TABLE_ENTRY_VALID; entry->flags = ADDR_TABLE_ENTRY_VALID | ADDR_TABLE_ENTRY_REUSE;
if(reuse)
{
entry->flags |= ADDR_TABLE_ENTRY_REUSE;
}
entry->port = port; entry->port = port;
entry->time = time(NULL); entry->time = time(NULL);

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Address table /* 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 * 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 * 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_lock(void);
void addr_table_unlock(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); 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_remove(uint16_t port);
void addr_table_update(void); void addr_table_update(void);

View File

@ -1,5 +1,5 @@
/* ipxwrapper - Winsock functions /* 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 * 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 * 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. */ /* 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. */ /* 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. */ /* 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. */ /* Mark the IPX socket as bound. */

View File

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