diff --git a/changes.txt b/changes.txt index ca4b939..0084ba0 100644 --- a/changes.txt +++ b/changes.txt @@ -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. diff --git a/src/addrtable.c b/src/addrtable.c index 90a7e56..b7e7c59 100644 --- a/src/addrtable.c +++ b/src/addrtable.c @@ -1,5 +1,5 @@ /* IPXWrapper - Address table - * Copyright (C) 2008-2012 Daniel Collins + * Copyright (C) 2008-2014 Daniel Collins * * 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); diff --git a/src/addrtable.h b/src/addrtable.h index a35be26..884f0b3 100644 --- a/src/addrtable.h +++ b/src/addrtable.h @@ -1,5 +1,5 @@ /* IPXWrapper - Address table - * Copyright (C) 2008-2012 Daniel Collins + * Copyright (C) 2008-2014 Daniel Collins * * 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); diff --git a/src/winsock.c b/src/winsock.c index d25d68d..12e63c5 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -1,5 +1,5 @@ /* ipxwrapper - Winsock functions - * Copyright (C) 2008 Daniel Collins + * Copyright (C) 2008-2014 Daniel Collins * * 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. */ diff --git a/tests/bind.t b/tests/bind.t index 9be0bfa..057077d 100644 --- a/tests/bind.t +++ b/tests/bind.t @@ -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