mirror of
https://git.openafs.org/openafs.git
synced 2025-01-31 05:27:44 +00:00
STABLE14-vice-hash-minimal-20070808
This delta is a minimal variation on vice-hash-20070808. The differences between the two are that there has not been a significant updating of ViceLog entries and renaming of functions and variables for consistency has not been performed. (1) fixes a bug that could cause a 'host' structure to not be removed from the global host list if the 'host' did not possess an interface list. This would happen with older AFS clients that do not support the WhoAreYou family of RPCs. Windows clients older than 1.3.80 and old Transarc UNIX clients. (2) fixes a bug which could result in ViceLog being called with an uninitialized 'hoststr' buffer as a parameter. (3) ensures that only addresses known to belong to the 'host' are added to the address hash table. The list of addresses provided by the client are stored as alternates and are only used when searching for a client that is no longer accessible on the primary address. These addresses are not stored in the address hash table within initInterfaceAddr_r(). The addresses provided by the client should not be added to the hash table because they have not been verified as belonging to the 'host' that provided them. The contents of the list may in fact be completely unreliable. Consider the existing UNIX clients that generate the list at startup and never alter it even after the client has migrated to a different network. If two client's both claim the same address, lookups by address may fail to find the correct one. a. The client list might contain private address ranges which are likely to be re-used by many clients allocated addresses by a NAT. b. The client list will not include any public addresses that are hidden by a NAT. c. Private address ranges that are exposed to the server will be obtained from the rx connections that use them. d. Lists provided by the client are not necessarily truthful. Many existing clients (UNIX) do not refresh the IP address list as the actual assigned addresses change. The end result is that they report the initial address list for the lifetime of the process. In other words, a client can report addresses that they are in fact not using. Adding these addresses to the host interface list without verification is not only pointless, it is downright dangerous. e. The reported addresses do not include port numbers and guessing that the port number is 7001 does not work when port mapping devices such as NATs or some VPNs are in use. (4) [not in this delta] (5) logs the UUID along with the client addresses when initializing the host's interface list. (level 125) (6) saves memory by using a smaller structure for the UUID hash table
This commit is contained in:
parent
1059d9aa6d
commit
9535989cad
@ -2039,10 +2039,8 @@ MultiBreakCallBackAlternateAddress_r(struct host *host,
|
||||
if (!host->interface)
|
||||
return 1; /* failure */
|
||||
|
||||
assert(host->interface->numberOfInterfaces > 0);
|
||||
|
||||
/* the only address is the primary interface */
|
||||
if (host->interface->numberOfInterfaces == 1)
|
||||
if (host->interface->numberOfInterfaces <= 1)
|
||||
return 1; /* failure */
|
||||
|
||||
/* initialise a security object only once */
|
||||
@ -2087,8 +2085,10 @@ MultiBreakCallBackAlternateAddress_r(struct host *host,
|
||||
if (host->callback_rxcon)
|
||||
rx_DestroyConnection(host->callback_rxcon);
|
||||
host->callback_rxcon = conns[multi_i];
|
||||
hashDelete_r(host->host, host->port, host);
|
||||
host->host = interfaces[multi_i].addr;
|
||||
host->port = interfaces[multi_i].port;
|
||||
hashInsert_r(host->host, host->port, host);
|
||||
connSuccess = conns[multi_i];
|
||||
rx_SetConnDeadTime(host->callback_rxcon, 50);
|
||||
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
|
||||
@ -2180,21 +2180,25 @@ MultiProbeAlternateAddress_r(struct host *host)
|
||||
H_LOCK;
|
||||
if (host->callback_rxcon)
|
||||
rx_DestroyConnection(host->callback_rxcon);
|
||||
hashDelete_r(host->host, host->port, host);
|
||||
host->callback_rxcon = conns[multi_i];
|
||||
host->host = interfaces[multi_i].addr;
|
||||
host->port = interfaces[multi_i].port;
|
||||
hashInsert_r(host->host, host->port, host);
|
||||
connSuccess = conns[multi_i];
|
||||
rx_SetConnDeadTime(host->callback_rxcon, 50);
|
||||
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
|
||||
ViceLog(125,
|
||||
("multiprobe success with addr %s\n",
|
||||
afs_inet_ntoa_r(interfaces[multi_i].addr, hoststr)));
|
||||
("multiprobe success for host %x; new primary addr %s:%d\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr),
|
||||
ntohs(host->port)));
|
||||
H_UNLOCK;
|
||||
multi_Abort;
|
||||
} else {
|
||||
ViceLog(125,
|
||||
("multiprobe failure with addr %s\n",
|
||||
afs_inet_ntoa_r(interfaces[multi_i].addr, hoststr)));
|
||||
("multiprobe failure with addr %s:%d\n",
|
||||
afs_inet_ntoa_r(interfaces[multi_i].addr, hoststr),
|
||||
ntohs(interfaces[multi_i].port)));
|
||||
|
||||
/* This is less than desirable but its the best we can do.
|
||||
* The AFS Cache Manager will return either 0 for a Uuid
|
||||
@ -2204,18 +2208,9 @@ MultiProbeAlternateAddress_r(struct host *host)
|
||||
* Uuid and fix the host tables.
|
||||
*/
|
||||
if (multi_error == 1) {
|
||||
struct host * newhost;
|
||||
|
||||
/* remove the current alternate address from this host */
|
||||
H_LOCK;
|
||||
for (i = 0, j = 0; i < host->interface->numberOfInterfaces; i++) {
|
||||
if (interfaces[multi_i].addr != host->interface->interface[i].addr &&
|
||||
interfaces[multi_i].port != host->interface->interface[i].port) {
|
||||
host->interface->interface[j] = host->interface->interface[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
host->interface->numberOfInterfaces--;
|
||||
removeInterfaceAddr_r(host, interfaces[multi_i].addr, interfaces[multi_i].port);
|
||||
H_UNLOCK;
|
||||
}
|
||||
}
|
||||
|
353
src/viced/host.c
353
src/viced/host.c
@ -83,6 +83,8 @@ struct host *hostList = 0; /* linked list of all hosts */
|
||||
int hostCount = 0; /* number of hosts in hostList */
|
||||
int rxcon_ident_key;
|
||||
int rxcon_client_key;
|
||||
static struct rx_securityClass *sc = NULL;
|
||||
|
||||
|
||||
#define CESPERBLOCK 73
|
||||
struct CEBlock { /* block of CESPERBLOCK file entries */
|
||||
@ -90,7 +92,6 @@ struct CEBlock { /* block of CESPERBLOCK file entries */
|
||||
};
|
||||
|
||||
static void h_TossStuff_r(register struct host *host);
|
||||
static int hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host *host);
|
||||
|
||||
/*
|
||||
* Make sure the subnet macros have been defined.
|
||||
@ -184,8 +185,8 @@ static struct host *HTFree = 0; /* first free file entry */
|
||||
* to map IP addresses onto host pointers, and another
|
||||
* to map host UUIDs onto host pointers.
|
||||
*/
|
||||
static struct h_hashChain *hostHashTable[h_HASHENTRIES];
|
||||
static struct h_hashChain *hostUuidHashTable[h_HASHENTRIES];
|
||||
static struct h_AddrHashChain *hostAddrHashTable[h_HASHENTRIES];
|
||||
static struct h_UuidHashChain *hostUuidHashTable[h_HASHENTRIES];
|
||||
#define h_HashIndex(hostip) ((hostip) & (h_HASHENTRIES-1))
|
||||
#define h_UuidHashIndex(uuidp) (((int)(afs_uuid_hash(uuidp))) & (h_HASHENTRIES-1))
|
||||
|
||||
@ -752,7 +753,6 @@ h_Alloc_r(register struct rx_connection *r_con)
|
||||
{
|
||||
struct servent *serverentry;
|
||||
register struct host *host;
|
||||
static struct rx_securityClass *sc = 0;
|
||||
afs_int32 now;
|
||||
#if FS_STATS_DETAILED
|
||||
afs_uint32 newHostAddr_HBO; /*New host IP addr, in host byte order */
|
||||
@ -823,13 +823,13 @@ struct host *
|
||||
h_Lookup_r(afs_uint32 haddr, afs_uint16 hport, int *heldp)
|
||||
{
|
||||
register afs_int32 now;
|
||||
register struct host *host = 0;
|
||||
register struct h_hashChain *chain;
|
||||
register struct host *host = NULL;
|
||||
register struct h_AddrHashChain *chain;
|
||||
register index = h_HashIndex(haddr);
|
||||
extern int hostaclRefresh;
|
||||
|
||||
restart:
|
||||
for (chain = hostHashTable[index]; chain; chain = chain->next) {
|
||||
for (chain = hostAddrHashTable[index]; chain; chain = chain->next) {
|
||||
host = chain->hostPtr;
|
||||
assert(host);
|
||||
if (!(host->hostFlags & HOSTDELETED) && chain->addr == haddr
|
||||
@ -870,7 +870,7 @@ struct host *
|
||||
h_LookupUuid_r(afsUUID * uuidp)
|
||||
{
|
||||
register struct host *host = 0;
|
||||
register struct h_hashChain *chain;
|
||||
register struct h_UuidHashChain *chain;
|
||||
register index = h_UuidHashIndex(uuidp);
|
||||
|
||||
for (chain = hostUuidHashTable[index]; chain; chain = chain->next) {
|
||||
@ -961,7 +961,7 @@ h_TossStuff_r(register struct host *host)
|
||||
host->hostFlags &= ~CLIENTDELETED;
|
||||
|
||||
if (host->hostFlags & HOSTDELETED) {
|
||||
register struct h_hashChain **hp, *th;
|
||||
register struct h_AddrHashChain **ahp, *ath;
|
||||
register struct rx_connection *rxconn;
|
||||
afsUUID *uuidp;
|
||||
struct AddrPort hostAddrPort;
|
||||
@ -982,49 +982,51 @@ h_TossStuff_r(register struct host *host)
|
||||
|
||||
/* if alternate addresses do not exist */
|
||||
if (!(host->interface)) {
|
||||
for (hp = &hostHashTable[h_HashIndex(host->host)]; (th = *hp);
|
||||
hp = &th->next) {
|
||||
assert(th->hostPtr);
|
||||
if (th->hostPtr == host) {
|
||||
*hp = th->next;
|
||||
h_DeleteList_r(host);
|
||||
FreeHT(host);
|
||||
free(th);
|
||||
for (ahp = &hostAddrHashTable[h_HashIndex(host->host)]; (ath = *ahp);
|
||||
ahp = &ath->next) {
|
||||
assert(ath->hostPtr);
|
||||
if (ath->hostPtr == host) {
|
||||
*ahp = ath->next;
|
||||
free(ath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* delete all hash entries for the UUID */
|
||||
register struct h_UuidHashChain **uhp, *uth;
|
||||
/* delete the hash entry for the UUID */
|
||||
uuidp = &host->interface->uuid;
|
||||
for (hp = &hostUuidHashTable[h_UuidHashIndex(uuidp)]; (th = *hp);
|
||||
hp = &th->next) {
|
||||
assert(th->hostPtr);
|
||||
if (th->hostPtr == host) {
|
||||
*hp = th->next;
|
||||
free(th);
|
||||
for (uhp = &hostUuidHashTable[h_UuidHashIndex(uuidp)]; (uth = *uhp);
|
||||
uhp = &uth->next) {
|
||||
assert(uth->hostPtr);
|
||||
if (uth->hostPtr == host) {
|
||||
*uhp = uth->next;
|
||||
free(uth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* delete all hash entries for alternate addresses */
|
||||
assert(host->interface->numberOfInterfaces > 0);
|
||||
/* delete the hash entry for each alternate addresses */
|
||||
for (i = 0; i < host->interface->numberOfInterfaces; i++) {
|
||||
hostAddrPort = host->interface->interface[i];
|
||||
|
||||
for (hp = &hostHashTable[h_HashIndex(hostAddrPort.addr)]; (th = *hp);
|
||||
hp = &th->next) {
|
||||
assert(th->hostPtr);
|
||||
if (th->hostPtr == host) {
|
||||
*hp = th->next;
|
||||
free(th);
|
||||
if (!hostAddrPort.valid)
|
||||
continue;
|
||||
|
||||
for (ahp = &hostAddrHashTable[h_HashIndex(hostAddrPort.addr)]; (ath = *ahp);
|
||||
ahp = &ath->next) {
|
||||
assert(ath->hostPtr);
|
||||
if (ath->hostPtr == host) {
|
||||
*ahp = ath->next;
|
||||
free(ath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(host->interface);
|
||||
host->interface = NULL;
|
||||
h_DeleteList_r(host); /* remove host from global host List */
|
||||
FreeHT(host);
|
||||
} /* if alternate address exists */
|
||||
|
||||
h_DeleteList_r(host); /* remove host from global host List */
|
||||
FreeHT(host);
|
||||
}
|
||||
} /*h_TossStuff_r */
|
||||
|
||||
@ -1111,13 +1113,19 @@ void
|
||||
hashInsertUuid_r(struct afsUUID *uuid, struct host *host)
|
||||
{
|
||||
int index;
|
||||
struct h_hashChain *chain;
|
||||
struct h_UuidHashChain *chain;
|
||||
|
||||
/* hash into proper bucket */
|
||||
index = h_UuidHashIndex(uuid);
|
||||
|
||||
/* don't add the same entry multiple times */
|
||||
for (chain = hostUuidHashTable[index]; chain; chain = chain->next) {
|
||||
if (host->interface && afs_uuid_equal(&host->interface->uuid, uuid))
|
||||
return;
|
||||
}
|
||||
|
||||
/* insert into beginning of list for this bucket */
|
||||
chain = (struct h_hashChain *)malloc(sizeof(struct h_hashChain));
|
||||
chain = (struct h_UuidHashChain *)malloc(sizeof(struct h_UuidHashChain));
|
||||
if (!chain) {
|
||||
ViceLog(0, ("Failed malloc in hashInsertUuid_r\n"));
|
||||
assert(0);
|
||||
@ -1134,35 +1142,46 @@ void
|
||||
hashInsert_r(afs_uint32 addr, afs_uint16 port, struct host *host)
|
||||
{
|
||||
int index;
|
||||
struct h_hashChain *chain;
|
||||
|
||||
struct h_AddrHashChain *chain;
|
||||
int found = 0;
|
||||
char hoststr[16];
|
||||
|
||||
/* hash into proper bucket */
|
||||
index = h_HashIndex(addr);
|
||||
|
||||
/* don't add the same entry multiple times */
|
||||
for (chain = hostHashTable[index]; chain; chain = chain->next) {
|
||||
if (chain->hostPtr == host && chain->addr == addr && chain->port == port)
|
||||
return;
|
||||
for (chain = hostAddrHashTable[index]; chain; chain = chain->next) {
|
||||
if (chain->addr == addr && chain->port == port) {
|
||||
if (chain->hostPtr == host)
|
||||
found = 1;
|
||||
else if (!(host->hostFlags & HOSTDELETED))
|
||||
ViceLog(125, ("Addr %s:%d assigned to %x and %x.\n",
|
||||
afs_inet_ntoa_r(addr, hoststr), ntohs(port),
|
||||
host, chain));
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return;
|
||||
|
||||
/* insert into beginning of list for this bucket */
|
||||
chain = (struct h_hashChain *)malloc(sizeof(struct h_hashChain));
|
||||
chain = (struct h_AddrHashChain *)malloc(sizeof(struct h_AddrHashChain));
|
||||
if (!chain) {
|
||||
ViceLog(0, ("Failed malloc in hashInsert_r\n"));
|
||||
assert(0);
|
||||
}
|
||||
chain->hostPtr = host;
|
||||
chain->next = hostHashTable[index];
|
||||
chain->next = hostAddrHashTable[index];
|
||||
chain->addr = addr;
|
||||
chain->port = port;
|
||||
hostHashTable[index] = chain;
|
||||
hostAddrHashTable[index] = chain;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called with host locked and held. At this point, the
|
||||
* hostHashTable should not be having entries for the alternate
|
||||
* hostAddrHashTable should not have entries for the alternate
|
||||
* interfaces. This function has to insert these entries in the
|
||||
* hostHashTable.
|
||||
* hostAddrHashTable.
|
||||
*
|
||||
* All addresses are in network byte order.
|
||||
*/
|
||||
@ -1178,10 +1197,6 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
assert(host);
|
||||
assert(host->interface);
|
||||
|
||||
ViceLog(125, ("addInterfaceAddr : host %s:%d addr %s:%d\n",
|
||||
afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
|
||||
afs_inet_ntoa_r(addr, hoststr2), ntohs(port)));
|
||||
|
||||
/*
|
||||
* Make sure this address is on the list of known addresses
|
||||
* for this host.
|
||||
@ -1189,9 +1204,16 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
number = host->interface->numberOfInterfaces;
|
||||
for (i = 0, found = 0; i < number && !found; i++) {
|
||||
if (host->interface->interface[i].addr == addr &&
|
||||
host->interface->interface[i].port == port)
|
||||
host->interface->interface[i].port == port) {
|
||||
found = 1;
|
||||
host->interface->interface[i].valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ViceLog(125, ("addInterfaceAddr : host %x (%s:%d) addr %s:%d : found:%d\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
|
||||
afs_inet_ntoa_r(addr, hoststr2), ntohs(port), found));
|
||||
|
||||
if (!found) {
|
||||
interface = (struct Interface *)
|
||||
malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * number));
|
||||
@ -1205,24 +1227,20 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
interface->interface[i] = host->interface->interface[i];
|
||||
interface->interface[number].addr = addr;
|
||||
interface->interface[number].port = port;
|
||||
interface->interface[number].valid = 1;
|
||||
free(host->interface);
|
||||
host->interface = interface;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a hash table entry for this address
|
||||
*/
|
||||
hashInsert_r(addr, port, host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is called with host locked and held. At this point, the
|
||||
* hostHashTable should not be having entries for the alternate
|
||||
* hostAddrHashTable should not be having entries for the alternate
|
||||
* interfaces. This function has to insert these entries in the
|
||||
* hostHashTable.
|
||||
* hostAddrHashTable.
|
||||
*
|
||||
* All addresses are in network byte order.
|
||||
*/
|
||||
@ -1238,8 +1256,8 @@ removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
assert(host);
|
||||
assert(host->interface);
|
||||
|
||||
ViceLog(125, ("removeInterfaceAddr : host %s:%d addr %s:%d\n",
|
||||
afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
|
||||
ViceLog(125, ("removeInterfaceAddr : host %x (%s:%d) addr %s:%d\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
|
||||
afs_inet_ntoa_r(addr, hoststr2), ntohs(port)));
|
||||
|
||||
/*
|
||||
@ -1248,18 +1266,17 @@ removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
*/
|
||||
interface = host->interface;
|
||||
number = host->interface->numberOfInterfaces;
|
||||
for (i = 0, found = 0; i < number; i++) {
|
||||
for (i = 0, found = 0; i < number && !found; i++) {
|
||||
if (interface->interface[i].addr == addr &&
|
||||
interface->interface[i].port == port) {
|
||||
found = 1;
|
||||
break;
|
||||
interface->interface[i].valid = 0;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
number--;
|
||||
for (; i < number; i++) {
|
||||
interface->interface[i].addr = interface->interface[i+1].addr;
|
||||
interface->interface[i].port = interface->interface[i+1].port;
|
||||
interface->interface[i] = interface->interface[i+1];
|
||||
}
|
||||
interface->numberOfInterfaces = number;
|
||||
}
|
||||
@ -1272,6 +1289,87 @@ removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called with host locked and held. This function differs
|
||||
* from removeInterfaceAddr_r in that it is called when the address
|
||||
* is being removed from the host regardless of whether or not there
|
||||
* is an interface list for the host. This function will delete the
|
||||
* host if there are no addresses left on it.
|
||||
*
|
||||
* All addresses are in network byte order.
|
||||
*/
|
||||
int
|
||||
removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port)
|
||||
{
|
||||
int i;
|
||||
char hoststr[16], hoststr2[16];
|
||||
|
||||
if (!host->interface) {
|
||||
if (host->host == addr && host->port == port) {
|
||||
ViceLog(25,
|
||||
("Removing only address for host %x (%s:%d), deleting host.\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
|
||||
host->hostFlags |= HOSTDELETED;
|
||||
}
|
||||
} else {
|
||||
removeInterfaceAddr_r(host, host->host, host->port);
|
||||
if (host->interface->numberOfInterfaces == 0) {
|
||||
ViceLog(25,
|
||||
("Removed only address for host %x (%s:%d), no alternate interfaces, deleting host.\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
|
||||
host->hostFlags |= HOSTDELETED;
|
||||
} else {
|
||||
struct rx_connection *rxconn;
|
||||
|
||||
rxconn = host->callback_rxcon;
|
||||
host->callback_rxcon = NULL;
|
||||
|
||||
if (rxconn) {
|
||||
struct client *client;
|
||||
/*
|
||||
* If rx_DestroyConnection calls h_FreeConnection we will
|
||||
* deadlock on the host_glock_mutex. Work around the problem
|
||||
* by unhooking the client from the connection before
|
||||
* destroying the connection.
|
||||
*/
|
||||
client = rx_GetSpecific(rxconn, rxcon_client_key);
|
||||
rx_SetSpecific(rxconn, rxcon_client_key, (void *)0);
|
||||
rx_DestroyConnection(rxconn);
|
||||
}
|
||||
|
||||
for (i=0; i < host->interface->numberOfInterfaces; i++) {
|
||||
if (host->interface->interface[i].valid) {
|
||||
ViceLog(25,
|
||||
("Removed address for host %x (%s:%d), new primary interface %s:%d.\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
|
||||
afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr2),
|
||||
ntohs(host->interface->interface[i].port)));
|
||||
host->host = host->interface->interface[i].addr;
|
||||
host->port = host->interface->interface[i].port;
|
||||
hashInsert_r(host->host, host->port, host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == host->interface->numberOfInterfaces) {
|
||||
ViceLog(25,
|
||||
("Removed only address for host %x (%s:%d), no valid alternate interfaces, deleting host.\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
|
||||
host->hostFlags |= HOSTDELETED;
|
||||
} else {
|
||||
if (!sc)
|
||||
sc = rxnull_NewClientSecurityObject();
|
||||
host->callback_rxcon =
|
||||
rx_NewConnection(host->host, host->port, 1, sc, 0);
|
||||
rx_SetConnDeadTime(host->callback_rxcon, 50);
|
||||
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
h_threadquota(int waiting)
|
||||
{
|
||||
@ -1298,7 +1396,7 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
struct host *host;
|
||||
struct host *oldHost;
|
||||
int code;
|
||||
int held, oheld;
|
||||
int held;
|
||||
struct interfaceAddr interf;
|
||||
int interfValid = 0;
|
||||
struct Identity *identP = NULL;
|
||||
@ -1394,9 +1492,9 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
* then this is not the same host as before. */
|
||||
if (!host->interface
|
||||
|| !afs_uuid_equal(&interf.uuid, &host->interface->uuid)) {
|
||||
ViceLog(25,
|
||||
("Host %s:%d has changed its identity, deleting.\n",
|
||||
afs_inet_ntoa_r(host->host, hoststr), host->port));
|
||||
ViceLog(25,
|
||||
("Uuid doesn't match host %x (%s:%d). Host deleted.\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
|
||||
host->hostFlags |= HOSTDELETED;
|
||||
host->hostFlags &= ~HWHO_INPROGRESS;
|
||||
h_Unlock_r(host);
|
||||
@ -1406,9 +1504,9 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
afs_inet_ntoa_r(host->host, hoststr);
|
||||
ViceLog(0,
|
||||
("CB: WhoAreYou failed for %s:%d, error %d\n", hoststr,
|
||||
("CB: WhoAreYou failed for host %x (%s:%d), error %d\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr),
|
||||
ntohs(host->port), code));
|
||||
host->hostFlags |= VENUSDOWN;
|
||||
}
|
||||
@ -1536,7 +1634,7 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
if (oldHost) {
|
||||
int probefail = 0;
|
||||
|
||||
if (!(oheld = h_Held_r(oldHost)))
|
||||
if (!h_Held_r(oldHost))
|
||||
h_Hold_r(oldHost);
|
||||
h_Lock_r(oldHost);
|
||||
oldHost->hostFlags |= HWHO_INPROGRESS;
|
||||
@ -1574,15 +1672,20 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
/* This is a new address for an existing host. Update
|
||||
* the list of interfaces for the existing host and
|
||||
* delete the host structure we just allocated. */
|
||||
|
||||
/* prevent warnings while manipulating interface lists */
|
||||
host->hostFlags |= HOSTDELETED;
|
||||
|
||||
if (oldHost->host != haddr || oldHost->port != hport) {
|
||||
struct rx_connection *rxconn;
|
||||
|
||||
ViceLog(25,
|
||||
("CB: new addr %s:%d for old host %s:%d\n",
|
||||
afs_inet_ntoa_r(haddr, hoststr),
|
||||
ntohs(hport),
|
||||
afs_inet_ntoa_r(oldHost->host, hoststr2),
|
||||
ntohs(oldHost->port)));
|
||||
("CB: Host %x (%s:%d) has new addr %s:%d\n",
|
||||
oldHost,
|
||||
afs_inet_ntoa_r(oldHost->host, hoststr2),
|
||||
ntohs(oldHost->port),
|
||||
afs_inet_ntoa_r(haddr, hoststr),
|
||||
ntohs(hport)));
|
||||
if (probefail || oldHost->host == haddr) {
|
||||
/* The probe failed which means that the old address is
|
||||
* either unreachable or is not the same host we were just
|
||||
@ -1610,6 +1713,7 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
}
|
||||
}
|
||||
addInterfaceAddr_r(oldHost, haddr, hport);
|
||||
hashInsert_r(haddr, hport, oldHost);
|
||||
oldHost->host = haddr;
|
||||
oldHost->port = hport;
|
||||
rxconn = oldHost->callback_rxcon;
|
||||
@ -1629,7 +1733,6 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
rx_DestroyConnection(rxconn);
|
||||
}
|
||||
}
|
||||
host->hostFlags |= HOSTDELETED;
|
||||
host->hostFlags &= ~HWHO_INPROGRESS;
|
||||
h_Unlock_r(host);
|
||||
/* release host because it was allocated by h_Alloc_r */
|
||||
@ -1659,15 +1762,14 @@ h_GetHost_r(struct rx_connection *tcon)
|
||||
}
|
||||
}
|
||||
if (code) {
|
||||
afs_inet_ntoa_r(host->host, hoststr);
|
||||
ViceLog(0,
|
||||
("CB: RCallBackConnectBack failed for %s:%d\n",
|
||||
hoststr, ntohs(host->port)));
|
||||
("CB: RCallBackConnectBack failed for host %x (%s:%d)\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
|
||||
host->hostFlags |= VENUSDOWN;
|
||||
} else {
|
||||
ViceLog(125,
|
||||
("CB: RCallBackConnectBack succeeded for %s:%d\n",
|
||||
hoststr, ntohs(host->port)));
|
||||
("CB: RCallBackConnectBack succeeded for host %x (%s:%d)\n",
|
||||
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
|
||||
host->hostFlags |= RESETDONE;
|
||||
}
|
||||
}
|
||||
@ -2673,9 +2775,9 @@ h_CheckHosts()
|
||||
|
||||
/*
|
||||
* This is called with host locked and held. At this point, the
|
||||
* hostHashTable should not have any entries for the alternate
|
||||
* hostAddrHashTable should not have any entries for the alternate
|
||||
* interfaces. This function has to insert these entries in the
|
||||
* hostHashTable.
|
||||
* hostAddrHashTable.
|
||||
*
|
||||
* The addresses in the interfaceAddr list are in host byte order.
|
||||
*/
|
||||
@ -2689,6 +2791,8 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
|
||||
int found;
|
||||
struct Interface *interface;
|
||||
char hoststr[16];
|
||||
char uuidstr[128];
|
||||
afs_uint16 port7001 = htons(7001);
|
||||
|
||||
assert(host);
|
||||
assert(interf);
|
||||
@ -2709,8 +2813,39 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert IP addresses to network byte order, and remove for
|
||||
* duplicate IP addresses from the interface list.
|
||||
* The client's notion of its own IP addresses is not reliable.
|
||||
*
|
||||
* 1. The client list might contain private address ranges which
|
||||
* are likely to be re-used by many clients allocated addresses
|
||||
* by a NAT.
|
||||
*
|
||||
* 2. The client list will not include any public addresses that
|
||||
* are hidden by a NAT.
|
||||
*
|
||||
* 3. Private address ranges that are exposed to the server will
|
||||
* be obtained from the rx connections that use them.
|
||||
*
|
||||
* 4. Lists provided by the client are not necessarily truthful.
|
||||
* Many existing clients (UNIX) do not refresh the IP address
|
||||
* list as the actual assigned addresses change. The end result
|
||||
* is that they report the initial address list for the lifetime
|
||||
* of the process. In other words, a client can report addresses
|
||||
* that they are in fact not using. Adding these addresses to
|
||||
* the host interface list without verification is not only
|
||||
* pointless, it is downright dangerous.
|
||||
*
|
||||
* We therefore do not add alternate addresses to the addr hash table.
|
||||
* We only use them for multi-rx callback breaks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert IP addresses to network byte order, and remove
|
||||
* duplicate IP addresses from the interface list, and
|
||||
* determine whether or not the incoming addr/port is
|
||||
* listed. Note that if the address matches it is not
|
||||
* truly a match because the port number for the entries
|
||||
* in the interface list are port 7001 and the port number
|
||||
* for this connection might not be 7001.
|
||||
*/
|
||||
for (i = 0, count = 0, found = 0; i < number; i++) {
|
||||
interf->addr_in[i] = htonl(interf->addr_in[i]);
|
||||
@ -2720,7 +2855,8 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
|
||||
}
|
||||
if (j == count) {
|
||||
interf->addr_in[count] = interf->addr_in[i];
|
||||
if (interf->addr_in[count] == myAddr)
|
||||
if (interf->addr_in[count] == myAddr &&
|
||||
port7001 == myPort)
|
||||
found = 1;
|
||||
count++;
|
||||
}
|
||||
@ -2734,31 +2870,42 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
|
||||
malloc(sizeof(struct Interface) +
|
||||
(sizeof(struct AddrPort) * (count - 1)));
|
||||
if (!interface) {
|
||||
ViceLog(0, ("Failed malloc in initInterfaceAddr_r\n"));
|
||||
ViceLog(0, ("Failed malloc in initInterfaceAddr_r 1\n"));
|
||||
assert(0);
|
||||
}
|
||||
interface->numberOfInterfaces = count;
|
||||
} else {
|
||||
interface = (struct Interface *)
|
||||
malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * count));
|
||||
assert(interface);
|
||||
if (!interface) {
|
||||
ViceLog(0, ("Failed malloc in initInterfaceAddr_r 2\n"));
|
||||
assert(0);
|
||||
}
|
||||
interface->numberOfInterfaces = count + 1;
|
||||
interface->interface[count].addr = myAddr;
|
||||
interface->interface[count].port = myPort;
|
||||
interface->interface[count].valid = 1;
|
||||
}
|
||||
interface->uuid = interf->uuid;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
interface->interface[i].addr = interf->addr_in[i];
|
||||
/* We store the port as 7001 because the addresses reported by
|
||||
|
||||
interface->interface[i].addr = interf->addr_in[i];
|
||||
/* We store the port as 7001 because the addresses reported by
|
||||
* TellMeAboutYourself and WhoAreYou RPCs are only valid if they
|
||||
* are coming from fully connected hosts (no NAT/PATs)
|
||||
*/
|
||||
interface->interface[i].port = htons(7001);
|
||||
interface->interface[i].port = port7001;
|
||||
interface->interface[i].valid = 1; /* valid until a conflict is found */
|
||||
}
|
||||
|
||||
interface->uuid = interf->uuid;
|
||||
|
||||
assert(!host->interface);
|
||||
host->interface = interface;
|
||||
|
||||
afsUUID_to_string(&interface->uuid, uuidstr, 127);
|
||||
|
||||
ViceLog(125, ("--- uuid %s\n", uuidstr));
|
||||
for (i = 0; i < host->interface->numberOfInterfaces; i++) {
|
||||
ViceLog(125, ("--- alt address %s:%d\n",
|
||||
afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr),
|
||||
@ -2770,13 +2917,14 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
|
||||
|
||||
/* deleted a HashChain structure for this address and host */
|
||||
/* returns 1 on success */
|
||||
static int
|
||||
hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host *host)
|
||||
int
|
||||
hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host *
|
||||
host)
|
||||
{
|
||||
int flag;
|
||||
register struct h_hashChain **hp, *th;
|
||||
register struct h_AddrHashChain **hp, *th;
|
||||
|
||||
for (hp = &hostHashTable[h_HashIndex(addr)]; (th = *hp);) {
|
||||
for (hp = &hostAddrHashTable[h_HashIndex(addr)]; (th = *hp);) {
|
||||
assert(th->hostPtr);
|
||||
if (th->hostPtr == host && th->addr == addr && th->port == port) {
|
||||
*hp = th->next;
|
||||
@ -2804,10 +2952,13 @@ printInterfaceAddr(struct host *host, int level)
|
||||
if (host->interface) {
|
||||
/* check alternate addresses */
|
||||
number = host->interface->numberOfInterfaces;
|
||||
assert(number > 0);
|
||||
for (i = 0; i < number; i++)
|
||||
ViceLog(level, ("%s:%d ", afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr),
|
||||
ntohs(host->interface->interface[i].port)));
|
||||
if (number == 0)
|
||||
ViceLog(level, ("no-addresses "));
|
||||
else {
|
||||
for (i = 0; i < number; i++)
|
||||
ViceLog(level, ("%s:%d ", afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr),
|
||||
ntohs(host->interface->interface[i].port)));
|
||||
}
|
||||
}
|
||||
ViceLog(level, ("\n"));
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ struct Identity {
|
||||
struct AddrPort {
|
||||
afs_uint32 addr; /* in network byte order */
|
||||
afs_uint16 port; /* in network byte order */
|
||||
afs_int16 valid;
|
||||
};
|
||||
|
||||
struct Interface {
|
||||
@ -103,13 +104,18 @@ struct host {
|
||||
/* * Don't zero the index, lock or condition varialbles */
|
||||
#define HOST_TO_ZERO(H) (int)(((char *)(&((H)->index))-(char *)(H)))
|
||||
|
||||
struct h_hashChain {
|
||||
struct h_AddrHashChain {
|
||||
struct host *hostPtr;
|
||||
struct h_hashChain *next;
|
||||
struct h_AddrHashChain *next;
|
||||
afs_uint32 addr;
|
||||
afs_uint16 port;
|
||||
};
|
||||
|
||||
struct h_UuidHashChain {
|
||||
struct host *hostPtr;
|
||||
struct h_UuidHashChain *next;
|
||||
};
|
||||
|
||||
struct client {
|
||||
struct client *next; /* next client entry for host */
|
||||
struct host *host; /* ptr to parent host entry */
|
||||
@ -216,6 +222,14 @@ extern void h_PrintClients();
|
||||
extern void h_GetWorkStats();
|
||||
extern void h_flushhostcps(register afs_uint32 hostaddr,
|
||||
register afs_uint16 hport);
|
||||
extern void hashInsertUuid_r(struct afsUUID *uuid, struct host *host);
|
||||
extern void hashInsert_r(afs_uint32 addr, afs_uint16 port, struct host *host);
|
||||
extern int hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host *host);
|
||||
extern int initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf);
|
||||
extern int addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port);
|
||||
extern int removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port);
|
||||
extern int removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port);
|
||||
|
||||
struct Interface *MultiVerifyInterface_r();
|
||||
|
||||
struct host *(hosttableptrs[h_MAXHOSTTABLES]); /* Used by h_itoh */
|
||||
|
Loading…
x
Reference in New Issue
Block a user