From 9881da31a3c144bbb3622f3a70964dfe87bb72f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 7 Feb 2006 07:47:31 +0000 Subject: [PATCH] STABLE14-viced-host-nat-20060207 When we discover a new address for an existing host we can take the opportunity to cleanup the hash table and the interface list if the new address differs from an existing address only by the port number. In that case we know the client is communicating to us from behind a NAT and the old addr/port number combination is no longer going to be of use to us. (cherry picked from commit e4c21e9c6fe4a030cf271b614d8e3d78130e4fc9) --- src/viced/host.c | 91 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/src/viced/host.c b/src/viced/host.c index 7d7ff208b7..7347f179cd 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -1011,6 +1011,61 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port) } +/* + * This is called with host locked and held. At this point, the + * hostHashTable should not be having entries for the alternate + * interfaces. This function has to insert these entries in the + * hostHashTable. + * + * All addresses are in network byte order. + */ +int +removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port) +{ + int i; + int number; + int found; + struct Interface *interface; + char hoststr[16], hoststr2[16]; + + 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), + afs_inet_ntoa_r(addr, hoststr2), ntohs(port))); + + /* + * Make sure this address is on the list of known addresses + * for this host. + */ + interface = host->interface; + number = host->interface->numberOfInterfaces; + for (i = 0, found = 0; i < number; i++) { + if (interface->interface[i].addr == addr && + interface->interface[i].port == port) { + found = 1; + break; + } + } + 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->numberOfInterfaces = number; + } + + /* + * Remove the hash table entry for this address + */ + hashDelete_r(addr, port, host); + + return 0; +} + + /* Host is returned held */ struct host * h_GetHost_r(struct rx_connection *tcon) @@ -1283,13 +1338,38 @@ 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. */ + if (oldHost->host != haddr || oldHost->port != hport) { ViceLog(25, ("CB: new addr %s:%d for old host %s:%d\n", afs_inet_ntoa_r(host->host, hoststr), - ntohs(host->port), afs_inet_ntoa_r(oldHost->host, - hoststr2), + ntohs(host->port), + afs_inet_ntoa_r(oldHost->host, hoststr2), ntohs(oldHost->port))); + if (oldHost->host == haddr) { + /* We have just been contacted by a client behind a NAT */ + removeInterfaceAddr_r(oldHost, oldHost->host, oldHost->port); + } else { + int i, found; + struct Interface *interface = oldHost->interface; + int number = oldHost->interface->numberOfInterfaces; + for (i = 0, found = 0; i < number; i++) { + if (interface->interface[i].addr == haddr && + interface->interface[i].port != hport) { + found = 1; + break; + } + } + if (found) { + /* We have just been contacted by a client that has been + * seen from behind a NAT and at least one other address. + */ + removeInterfaceAddr_r(oldHost, haddr, interface->interface[i].port); + } + } addInterfaceAddr_r(oldHost, haddr, hport); + oldHost->host = haddr; + oldHost->port = hport; + } host->hostFlags |= HOSTDELETED; h_Unlock_r(host); if (!held) @@ -1323,9 +1403,12 @@ h_GetHost_r(struct rx_connection *tcon) ("CB: RCallBackConnectBack failed for %s:%d\n", hoststr, ntohs(host->port))); host->hostFlags |= VENUSDOWN; - } else + } else { + ViceLog(125, + ("CB: RCallBackConnectBack succeeded for %s:%d\n", + hoststr, ntohs(host->port))); host->hostFlags |= RESETDONE; - + } } if (caps.Capabilities_val && (caps.Capabilities_val[0] & CAPABILITY_ERRORTRANS))