/* * Copyright (C) 1998-2007 Luca Deri * * http://www.ntop.org/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ntop.h" /* #define HASH_DEBUG */ /* #define DNS_DEBUG */ #ifdef HASH_DEBUG static void hashSanityCheck(); static void hostHashSanityCheck(HostTraffic *host); #endif /* ******************************* */ u_int hashHost(HostAddr *hostIpAddress, u_char *ether_addr, short* useIPAddressForSearching, HostTraffic **el, int actualDeviceId) { u_int idx = 0; *el = NULL; if(myGlobals.runningPref.dontTrustMACaddr) /* MAC addresses don't make sense here */ (*useIPAddressForSearching) = 1; if((*useIPAddressForSearching) && (hostIpAddress == NULL)) { #if 0 traceEvent(CONST_TRACE_WARNING, "Index calculation problem (hostIpAddress=%x, ether_addr=%x)", hostIpAddress, ether_addr); #endif return(FLAG_NO_PEER); } if(((*useIPAddressForSearching) == 1) || ((ether_addr == NULL) && (hostIpAddress != NULL))) { if(myGlobals.runningPref.trackOnlyLocalHosts && (!isLocalAddress(hostIpAddress, actualDeviceId, NULL, NULL)) && (!_pseudoLocalAddress(hostIpAddress, NULL, NULL))) { *el = myGlobals.otherHostEntry; return(OTHER_HOSTS_ENTRY); } else { /* idx = hostIpAddress->s_addr; */ if(hostIpAddress->hostFamily == AF_INET) idx = (hostIpAddress->Ip4Address.s_addr & 0xffff) ^ ((hostIpAddress->Ip4Address.s_addr >> 15) & 0xffff); #ifdef INET6 else if(hostIpAddress->hostFamily == AF_INET6) idx = in6_hash(&hostIpAddress->Ip6Address); #endif } (*useIPAddressForSearching) = 1; } else if(memcmp(ether_addr, myGlobals.broadcastEntry->ethAddress, LEN_ETHERNET_ADDRESS) == 0) { *el = myGlobals.broadcastEntry; return(BROADCAST_HOSTS_ENTRY); } else if(hostIpAddress == NULL) { memcpy(&idx, ðer_addr[LEN_ETHERNET_ADDRESS-sizeof(u_int)], sizeof(u_int)); (*useIPAddressForSearching) = 0; } else if(isBroadcastAddress(hostIpAddress, NULL, NULL)) { *el = myGlobals.broadcastEntry; return(BROADCAST_HOSTS_ENTRY); } else if(isPseudoLocalAddress(hostIpAddress, actualDeviceId, NULL, NULL)) { memcpy(&idx, ðer_addr[LEN_ETHERNET_ADDRESS-sizeof(u_int)], sizeof(u_int)); (*useIPAddressForSearching) = 0; } else { if(hostIpAddress != NULL) { if(myGlobals.runningPref.trackOnlyLocalHosts && (!isPseudoLocalAddress(hostIpAddress, actualDeviceId, NULL, NULL))) { *el = myGlobals.otherHostEntry; return(OTHER_HOSTS_ENTRY); } else { /* idx = hostIpAddress->s_addr; */ if(hostIpAddress->hostFamily == AF_INET) idx = (hostIpAddress->Ip4Address.s_addr & 0xffff) ^ ((hostIpAddress->Ip4Address.s_addr >> 15) & 0xffff); #ifdef INET6 else if(hostIpAddress->hostFamily == AF_INET6) idx = in6_hash(&hostIpAddress->Ip6Address); #endif } } else { idx = FLAG_NO_PEER; traceEvent(CONST_TRACE_WARNING, "Index calculation problem (1)"); } (*useIPAddressForSearching) = 1; } idx = idx % myGlobals.device[actualDeviceId].actualHashSize; /* Skip reserved entries */ if((idx == BROADCAST_HOSTS_ENTRY) || (idx == OTHER_HOSTS_ENTRY)) idx = FIRST_HOSTS_ENTRY; return(idx); } /* ************************************ */ u_int hashFcHost(FcAddress *fcaddr, u_short vsanId, HostTraffic **el, int actualDeviceId) { u_int idx = 0; *el = NULL; if(fcaddr == NULL) { #if 0 traceEvent(CONST_TRACE_WARNING, "Index calculation problem (hostIpAddress=%x, ether_addr=%x)", hostIpAddress, ether_addr); #endif return(FLAG_NO_PEER); } idx = (fcaddr->domain & 0xff) ^ (fcaddr->area & 0xff) ^ (fcaddr->port & 0xff) ^ vsanId; if(actualDeviceId == -1) { idx = idx % CONST_HASH_INITIAL_SIZE; } else { idx = idx % myGlobals.device[actualDeviceId].actualHashSize; } /* Skip reserved entries */ if((idx == BROADCAST_HOSTS_ENTRY) || (idx == OTHER_HOSTS_ENTRY)) idx = FIRST_HOSTS_ENTRY; return(idx); } /* ************************************ */ /* Description: This function is called when a host is freed. Therefore it is necessary to free all the (eventual) sessions of such host. */ static void freeHostSessions(HostTraffic *host, int theDevice) { int i; if(host->l2Family == FLAG_HOST_TRAFFIC_AF_ETH) { for(i=0; i FLAG_NTOPSTATE_RUN /* i.e. active, not cleanup */ ) return; if(host->numHostSessions == 0) return; accessMutex(&myGlobals.tcpSessionsMutex, "freeHostSessions"); prevSession = theSession = myGlobals.device[theDevice].tcpSession[i]; while(theSession != NULL) { nextSession = theSession->next; if(host->numHostSessions == 0) break; if((theSession->initiator == host) || (theSession->remotePeer == host)) { if(myGlobals.device[theDevice].tcpSession[i] == theSession) { myGlobals.device[theDevice].tcpSession[i] = nextSession; prevSession = myGlobals.device[theDevice].tcpSession[i]; } else prevSession->next = nextSession; freeSession(theSession, theDevice, 0 /* don't allocate */, 0 /* locked by the purge thread */); theSession = prevSession; } else { prevSession = theSession; theSession = nextSession; } if(theSession && (theSession->next == theSession)) { traceEvent(CONST_TRACE_WARNING, "Internal Error (1)"); } } /* while */ releaseMutex(&myGlobals.tcpSessionsMutex); ntop_conditional_sched_yield(); /* Allow other threads to run */ } /* for */ #ifndef DELAY_SESSION_PURGE if(host->numHostSessions > 0) { traceEvent(CONST_TRACE_ERROR, "====> Host %s/%s has %d sessions still to be purged", host->hostNumIpAddress, host->hostResolvedName, host->numHostSessions); } #endif } else { for(i=0; i FLAG_NTOPSTATE_RUN /* i.e. active, not cleanup */ ) return; if(host->numHostSessions == 0) return; accessMutex(&myGlobals.fcSessionsMutex, "freeHostSessions"); prevSession = theSession = myGlobals.device[theDevice].fcSession[i]; while(theSession != NULL) { nextSession = theSession->next; if(host->numHostSessions == 0) break; if((theSession->initiator == host) || (theSession->remotePeer == host)) { if(myGlobals.device[theDevice].fcSession[i] == theSession) { myGlobals.device[theDevice].fcSession[i] = nextSession; prevSession = myGlobals.device[theDevice].fcSession[i]; } else prevSession->next = nextSession; freeFcSession(theSession, theDevice, 0 /* don't allocate */, 0 /* locked by the purge thread */); theSession = prevSession; } else { prevSession = theSession; theSession = nextSession; } if(theSession && (theSession->next == theSession)) { traceEvent(CONST_TRACE_WARNING, "Internal Error (1)"); } } /* while */ releaseMutex(&myGlobals.fcSessionsMutex); ntop_conditional_sched_yield(); /* Allow other threads to run */ } /* for */ #ifndef DELAY_SESSION_PURGE if(host->numHostSessions > 0) { traceEvent(CONST_TRACE_ERROR, "====> Host %s/%s has %d sessions still to be purged", host->hostNumIpAddress, host->hostResolvedName, host->numHostSessions); } #endif } } /* **************************************** */ void freeHostInfo(HostTraffic *host, int actualDeviceId) { u_int i, deleteAddressFromCache = 1; if(host == NULL) { traceEvent(CONST_TRACE_WARNING, "Attempting to call freeHostInfo(NULL)"); return; } /* If this is one of the special ones, let's clear the other pointer to it * to prevent a free of freed memory error later. */ if(host == myGlobals.otherHostEntry) { traceEvent(CONST_TRACE_WARNING, "Attempting to call freeHostInfo(otherHostEntry)"); return; } if(host == myGlobals.broadcastEntry) { traceEvent(CONST_TRACE_WARNING, "Attempting to call freeHostInfo(broadcastEntry)"); return; } if((host->magic != CONST_MAGIC_NUMBER) && (host->magic != CONST_UNMAGIC_NUMBER)) { traceEvent(CONST_TRACE_ERROR, "Bad magic number (expected=%d/real=%d) freeHostInfo()", CONST_MAGIC_NUMBER, host->magic); return; } /* Flag that this entry is being deleted. */ host->magic = CONST_UNMAGIC_NUMBER; #ifdef DEBUG traceEvent(CONST_TRACE_INFO, "Entering freeHostInfo(%u)", host->hostTrafficBucket); #endif /* ********** */ #if 0 traceEvent(CONST_TRACE_INFO, "HOST_FREE_DEBUG: Deleting a hash_hostTraffic entry [%s/%s/%s][idx=%d]", host->ethAddressString, host->hostNumIpAddress, host->hostResolvedName, host->hostTrafficBucket); #endif if(deleteAddressFromCache) { datum key_data; if(host->hostIpAddress.hostFamily == AF_INET) { key_data.dptr = (void*)&host->hostIpAddress.Ip4Address.s_addr; key_data.dsize = 4; } #ifdef INET6 else if(host->hostIpAddress.hostFamily == AF_INET6) { key_data.dptr = (void*)&host->hostIpAddress.Ip6Address.s6_addr; key_data.dsize = 16; } #endif else key_data.dsize = 0; if(key_data.dsize && (key_data.dptr != NULL)) { gdbm_delete(myGlobals.addressQueueFile, key_data); #ifdef DNS_DEBUG traceEvent(CONST_TRACE_INFO, "HOST_FREE_DEBUG: Deleting from GDBM address cache host [%s/%s]", host->hostNumIpAddress, host->hostResolvedName); #endif } } handlePluginHostCreationDeletion(host, (u_short)actualDeviceId, 0 /* host deletion */); /* Make sure this host is not part of the ipTrafficMatrixHosts list */ if((myGlobals.device[actualDeviceId].ipTrafficMatrix != NULL) && (myGlobals.device[actualDeviceId].numHosts > 0) && isMatrixHost(host, actualDeviceId)) { int id = matrixHostHash(host, actualDeviceId, 0); myGlobals.device[actualDeviceId].ipTrafficMatrixHosts[id] = NULL; for(i=0; ifcCounters != NULL) { if(host->l2Family == FLAG_HOST_TRAFFIC_AF_FC) { for (i = 0; i < MAX_LUNS_SUPPORTED; i++) { if(host->fcCounters->activeLuns[i] != NULL) { free(host->fcCounters->activeLuns[i]); } } } free(host->fcCounters); } myGlobals.device[actualDeviceId].hostsno--; if(host->protoIPTrafficInfos != NULL) { for(i=0; iprotoIPTrafficInfos[i] != NULL) free(host->protoIPTrafficInfos[i]); free(host->protoIPTrafficInfos); } if(host->ipProtosList != NULL) { for(i=0; iipProtosList[i] != NULL) free(host->ipProtosList[i]); free(host->ipProtosList); } if(host->nonIPTraffic) { if(host->nonIPTraffic->nbHostName != NULL) free(host->nonIPTraffic->nbHostName); if(host->nonIPTraffic->nbAccountName != NULL) free(host->nonIPTraffic->nbAccountName); if(host->nonIPTraffic->nbDomainName != NULL) free(host->nonIPTraffic->nbDomainName); if(host->nonIPTraffic->nbDescr != NULL) free(host->nonIPTraffic->nbDescr); if(host->nonIPTraffic->atNodeName != NULL) free(host->nonIPTraffic->atNodeName); for(i=0; inonIPTraffic->atNodeType[i] != NULL) free(host->nonIPTraffic->atNodeType[i]); if(host->nonIPTraffic->atNodeName != NULL) free(host->nonIPTraffic->atNodeName); if(host->nonIPTraffic->ipxHostName != NULL) free(host->nonIPTraffic->ipxHostName); if(host->nonIPTraffic->unknownProtoSent != NULL) free(host->nonIPTraffic->unknownProtoSent); if(host->nonIPTraffic->unknownProtoRcvd != NULL) free(host->nonIPTraffic->unknownProtoRcvd); free(host->nonIPTraffic); } if(host->nonIpProtoTrafficInfos != NULL) { NonIpProtoTrafficInfo *list = host->nonIpProtoTrafficInfos; while(list != NULL) { NonIpProtoTrafficInfo *next = list->next; free(list); list = next; } } if(host->secHostPkts != NULL) { free(host->secHostPkts); host->secHostPkts = NULL; /* just to be safe in case of persistent storage */ } if(host->fingerprint != NULL) free(host->fingerprint); if(host->routedTraffic != NULL) free(host->routedTraffic); if(host->portsUsage != NULL) freePortsUsage(host); if(myGlobals.runningPref.enablePacketDecoding && (host->protocolInfo != NULL)) { if(host->protocolInfo->httpVirtualHosts != NULL) { VirtualHostList *list = host->protocolInfo->httpVirtualHosts; while(list != NULL) { VirtualHostList *next = list->next; if(list->virtualHostName != NULL) /* This is a silly check as it should be true all the time */ free(list->virtualHostName); free(list); list = next; } } if(host->protocolInfo->userList != NULL) { UserList *list = host->protocolInfo->userList; while(list != NULL) { UserList *next = list->next; if(list->userName != NULL) free(list->userName); free(list); list = next; } } if(host->protocolInfo->fileList != NULL) { FileList *list = host->protocolInfo->fileList; while(list != NULL) { FileList *next = list->next; if(list->fileName != NULL) free(list->fileName); free(list); list = next; } } if(host->protocolInfo->dnsStats != NULL) free(host->protocolInfo->dnsStats); if(host->protocolInfo->httpStats != NULL) free(host->protocolInfo->httpStats); if(host->protocolInfo->dhcpStats != NULL) free(host->protocolInfo->dhcpStats); } if(host->protocolInfo != NULL) free(host->protocolInfo); /* ************************************* */ if(host->icmpInfo != NULL) free(host->icmpInfo); if(host->trafficDistribution != NULL) free(host->trafficDistribution); if(host->dnsDomainValue != NULL) free(host->dnsDomainValue); host->dnsDomainValue = NULL; if(host->dnsTLDValue != NULL) free(host->dnsTLDValue); host->dnsTLDValue = NULL; if(host->description != NULL) free(host->description); if(host->hwModel != NULL) free(host->hwModel); if(host->community != NULL) free(host->community); if(host->ip2ccValue != NULL) free(host->ip2ccValue); host->ip2ccValue = NULL; /* ********** */ /* #ifdef HASH_DEBUG hostHashSanityCheck(host); #endif */ memset(host, 0, sizeof(HostTraffic)); /* Debug code */ free(host); myGlobals.numPurgedHosts++; #ifdef DEBUG traceEvent(CONST_TRACE_INFO, "Leaving freeHostInfo()"); #endif } /* ************************************ */ /* This function is called before the final cleanup when ntop shutsdown */ void freeHostInstances(int actualDeviceId) { u_int idx, i, max, num=0; if(myGlobals.runningPref.mergeInterfaces) max = 1; else max = myGlobals.numDevices; traceEvent(CONST_TRACE_INFO, "FREE_HOST: Start, %d device(s)", max); for(i=0; i= myGlobals.numDevices) break; } actualDeviceId = i; #ifdef HASH_DEBUG hashSanityCheck(); #endif for(idx=FIRST_HOSTS_ENTRY; idx= FLAG_NTOPSTATE_SHUTDOWN) break; while(el != NULL) { HostTraffic *nextEl = el->next; el->next = NULL; num++; freeHostInfo(el, actualDeviceId); ntop_conditional_sched_yield(); /* Allow other threads to run */ el = nextEl; } myGlobals.device[actualDeviceId].hash_hostTraffic[idx] = NULL; } /* for */ #ifdef HASH_DEBUG hashSanityCheck(); #endif } traceEvent(CONST_TRACE_INFO, "FREE_HOST: End, freed %d", num); } /* ************************************ */ int is_host_ready_to_purge(int actDevice, HostTraffic *el, time_t now) { /* Time used to decide whether a host need to be purged */ time_t noSessionPurgeTime = now-PARM_HOST_PURGE_MINIMUM_IDLE_NOACTVSES; time_t withSessionPurgeTime = now-PARM_HOST_PURGE_MINIMUM_IDLE_ACTVSES; if(el->to_be_deleted || ( (el->refCount == 0) && ((!myGlobals.runningPref.rFileName) && (((el->numHostSessions == 0) && (el->lastSeen < noSessionPurgeTime)) || ((el->numHostSessions > 0) && (el->lastSeen < withSessionPurgeTime)))) && (!broadcastHost(el)) && (el != myGlobals.otherHostEntry) && (myGlobals.device[actDevice].virtualDevice /* e.g. sFlow/NetFlow */ || (!myGlobals.runningPref.stickyHosts) || ((el->l2Family == FLAG_HOST_TRAFFIC_AF_ETH) && ((el->hostNumIpAddress[0] == '\0') /* Purge MAC addresses too */ || (!subnetPseudoLocalHost(el)))) /* Purge remote hosts only */ || ((el->l2Family == FLAG_HOST_TRAFFIC_AF_FC) && (el->fcCounters->hostNumFcAddress[0] == '\0'))))) return(1); else return(0); } /* ************************************ */ int purgeIdleHosts(int actDevice) { u_int idx, numFreedBuckets=0, numHosts = 0; time_t now = time(NULL); static time_t lastPurgeTime[MAX_NUM_DEVICES]; static char firstRun = 1; HostTraffic **theFlaggedHosts = NULL; u_int maxHosts, scannedHosts=0; float hiresDeltaTime; struct timeval hiresTimeStart, hiresTimeEnd; HostTraffic *el, *prev, *next; /* if(myGlobals.runningPref.rFileName != NULL) return; */ #ifdef IDLE_PURGE_DEBUG traceEvent(CONST_TRACE_INFO, "IDLE_PURGE_DEBUG: purgeIdleHosts() invoked"); #endif if(firstRun) { firstRun = 0; memset(lastPurgeTime, 0, sizeof(lastPurgeTime)); } gettimeofday(&hiresTimeStart, NULL); if(now < (lastPurgeTime[actDevice]+PARM_HOST_PURGE_INTERVAL)) return(0); /* Too short */ else lastPurgeTime[actDevice] = now; maxHosts = myGlobals.device[actDevice].hostsno; /* save it as it can change */ myGlobals.piMem = maxHosts*sizeof(HostTraffic*); theFlaggedHosts = (HostTraffic**)calloc(1, myGlobals.piMem); purgeOldFragmentEntries(actDevice); /* let's do this too */ #ifdef IDLE_PURGE_DEBUG traceEvent(CONST_TRACE_INFO, "IDLE_PURGE_DEBUG: accessMutex(purgeMutex)...calling"); #endif accessMutex(&myGlobals.purgeMutex, "purgeIdleHosts"); #ifdef IDLE_PURGE_DEBUG traceEvent(CONST_TRACE_INFO, "IDLE_PURGE_DEBUG: accessMutex(purgeMutex)...locked"); #endif #ifdef HASH_DEBUG hashSanityCheck(); #endif accessMutex(&myGlobals.hostsHashLockMutex, "scanIdleLoop"); for(idx=0; idx= FLAG_NTOPSTATE_SHUTDOWN) break; if((el = myGlobals.device[actDevice].hash_hostTraffic[idx]) != NULL) { prev = NULL; while(el) { if(is_host_ready_to_purge(actDevice, el, now)) { if(!el->to_be_deleted) { el->to_be_deleted = 1; /* Delete it at the next run */ /* Skip it and move to next host */ prev = el; el = el->next; } else { /* Host selected for deletion */ theFlaggedHosts[numHosts++] = el; el->magic = CONST_UNMAGIC_NUMBER; purgeQueuedV4HostAddress(el->hostIpAddress.Ip4Address.s_addr); remove_valid_ptr(el); next = el->next; if(prev != NULL) prev->next = next; else myGlobals.device[actDevice].hash_hostTraffic[idx] = next; el->next = NULL; el = next; } } else { /* Move to next host */ prev = el; el = el->next; } scannedHosts++; #ifdef MAX_HOSTS_PURGE_PER_CYCLE if(numHosts >= MAX_HOSTS_PURGE_PER_CYCLE) break; #endif if(numHosts >= (maxHosts-1)) break; } /* while */ if(numHosts >= (maxHosts-1)) { break; } } } releaseMutex(&myGlobals.hostsHashLockMutex); #ifdef HASH_DEBUG hashSanityCheck(); #endif #ifdef IDLE_PURGE_DEBUG traceEvent(CONST_TRACE_INFO, "IDLE_PURGE_DEBUG: releaseMutex(purgeMutex)...calling"); #endif releaseMutex(&myGlobals.purgeMutex); #ifdef IDLE_PURGE_DEBUG traceEvent(CONST_TRACE_INFO, "IDLE_PURGE_DEBUG: releaseMutex(purgeMutex)...released"); #endif traceEvent(CONST_TRACE_NOISY, "IDLE_PURGE: Device %d [%s] FINISHED selection, " "%d [out of %d] hosts selected", actDevice, myGlobals.device[actDevice].name, numHosts, scannedHosts); /* Now free the entries */ for(idx=0; idxlastSeen, theFlaggedHosts[idx]->hostResolvedName); #endif freeHostInfo(theFlaggedHosts[idx], actDevice); numFreedBuckets++; ntop_conditional_sched_yield(); /* Allow other threads to run */ } free(theFlaggedHosts); if(myGlobals.runningPref.enableSessionHandling) scanTimedoutTCPSessions(actDevice); /* let's check timedout sessions too */ gettimeofday(&hiresTimeEnd, NULL); hiresDeltaTime = timeval_subtract(hiresTimeEnd, hiresTimeStart); if(numFreedBuckets > 0) traceEvent(CONST_TRACE_NOISY, "IDLE_PURGE: Device %d [%s]: %d/%d hosts deleted, elapsed time is %.6f seconds (%.6f per host)", actDevice, myGlobals.device[actDevice].name, numFreedBuckets, maxHosts, hiresDeltaTime, hiresDeltaTime / numFreedBuckets); else traceEvent(CONST_TRACE_NOISY, "IDLE_PURGE: Device %s: no hosts [out of %d] deleted", myGlobals.device[actDevice].name, maxHosts); return(numFreedBuckets); } /* **************************************************** */ void setHostSerial(HostTraffic *el) { /* Nothing to do */ if(el->hostSerial.serialType != SERIAL_NONE) return; if(isFcHost(el)) { if(el->fcCounters->hostNumFcAddress[0] != '\0') { el->hostSerial.serialType = SERIAL_FC; el->hostSerial.value.fcSerial.fcAddress.domain = el->fcCounters->hostFcAddress.domain; el->hostSerial.value.fcSerial.fcAddress.area = el->fcCounters->hostFcAddress.area; el->hostSerial.value.fcSerial.fcAddress.port = el->fcCounters->hostFcAddress.port; el->hostSerial.value.fcSerial.vsanId = el->fcCounters->vsanId; } else traceEvent (CONST_TRACE_ERROR, "setHostSerial: Received NULL FC Address entry"); } else if(el->hostNumIpAddress[0] == '\0') { el->hostSerial.serialType = SERIAL_MAC; memcpy(&el->hostSerial.value.ethSerial.ethAddress, el->ethAddress, LEN_ETHERNET_ADDRESS); el->hostSerial.value.ethSerial.vlanId = el->vlanId; } else { if(el->hostIpAddress.hostFamily == AF_INET){ el->hostSerial.serialType = SERIAL_IPV4; } else if(el->hostIpAddress.hostFamily == AF_INET6){ el->hostSerial.serialType = SERIAL_IPV6; } addrcpy(&el->hostSerial.value.ipSerial.ipAddress, &el->hostIpAddress); el->hostSerial.value.ipSerial.vlanId = el->vlanId; } } /* ********************************************************* */ /* Searches a host and returns it. If the host is not present in the hash a new bucket is created */ HostTraffic* _lookupHost(HostAddr *hostIpAddress, u_char *ether_addr, u_int16_t vlanId, u_char checkForMultihoming, u_char forceUsingIPaddress, int actualDeviceId, char *file, int line) { u_int idx, isMultihomed = 0; HostTraffic *el=NULL; char buf[MAX_LEN_SYM_HOST_NAME_HTML]; short useIPAddressForSearching = forceUsingIPaddress; char* symEthName = NULL, *ethAddr; u_char setSpoofingFlag = 0, locked_mutex = 0; u_short numRuns=0; u_int hostFound = 0; u_int updateIPinfo = 0; u_int32_t the_local_network, the_local_network_mask; if((hostIpAddress == NULL) && (ether_addr == NULL)) { traceEvent(CONST_TRACE_WARNING, "Both Ethernet and IP addresses are NULL in lookupHost()[%s:%d]", file, line); return(NULL); } #ifdef DEBUG traceEvent(CONST_TRACE_NOISY, "DEBUG: lookupHost(%s, %s, m=%u, f=%u, dev=%d, vlan=%d)", addrtostr(hostIpAddress), etheraddr_string(ether_addr, buf), checkForMultihoming, forceUsingIPaddress, actualDeviceId, vlanId); #endif #ifdef HASH_DEBUG hashSanityCheck(); #endif idx = hashHost(hostIpAddress, ether_addr, &useIPAddressForSearching, &el, actualDeviceId); /* Remember the side effect of above routine - if -o | --no-mac is set,\ * useIPAddressForSearching is now 1 */ /* If we found it or had an error */ if(el != NULL) return(el); /* Found */ else if(idx == FLAG_NO_PEER) return(NULL); else { el = myGlobals.device[actualDeviceId].hash_hostTraffic[idx]; if(el) { lockHostsHashMutex(el, "_lookupHost"); accessMutex(&myGlobals.hostsHashLockMutex, "lookupHost"); el = myGlobals.device[actualDeviceId].hash_hostTraffic[idx]; locked_mutex = 1; } } while (el != NULL) { if(el->magic != CONST_MAGIC_NUMBER) { traceEvent(CONST_TRACE_ERROR, "Bad magic number (expected=%d/real=%d) [deviceId=%d] lookupHost()[%s:%d]", CONST_MAGIC_NUMBER, el->magic, actualDeviceId, file, line); break; /* Can't trust this chain ... */ } if(el->hostTrafficBucket != idx) { traceEvent(CONST_TRACE_WARNING, "Error: wrong bucketIdx %s/%s (expected=%d/real=%d) [deviceId=%d] lookupHost()[%s:%d]", el->ethAddressString, el->hostNumIpAddress, idx, el->hostTrafficBucket, actualDeviceId, file, line); } if(!is_host_ready_to_purge(actualDeviceId, el, myGlobals.actTime)) { if(useIPAddressForSearching == 0) { /* compare with the ethernet-address then the IP address */ if(memcmp(el->ethAddress, ether_addr, LEN_ETHERNET_ADDRESS) == 0) { if((hostIpAddress != NULL) && (hostIpAddress->hostFamily == el->hostIpAddress.hostFamily)) { if((!isMultihomed) && checkForMultihoming) { /* This is a local address hence this is a potential multihomed host. */ if(!(addrnull(&el->hostIpAddress)) && (addrcmp(&el->hostIpAddress,hostIpAddress) != 0)) { isMultihomed = 1; FD_SET(FLAG_HOST_TYPE_MULTIHOMED, &el->flags); } else { updateIPinfo = 1; } } hostFound = 1; break; } else if(hostIpAddress == NULL){ /* Only Mac Addresses */ hostFound = 1; break; } else { /* MAC match found and we have the IP - need to update... */ updateIPinfo = 1; hostFound = 1; break; } } else if((hostIpAddress != NULL) && (addrcmp(&el->hostIpAddress, hostIpAddress) == 0)) { /* Spoofing or duplicated MAC address: two hosts with the same IP address and different MAC addresses */ if(!hasDuplicatedMac(el)) { FD_SET(FLAG_HOST_DUPLICATED_MAC, &el->flags); if(myGlobals.runningPref.enableSuspiciousPacketDump) { char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY]; traceEvent(CONST_TRACE_WARNING, "Two MAC addresses found for the same IP address " "%s: [%s/%s] (spoofing detected?)", el->hostNumIpAddress, etheraddr_string(ether_addr, etherbuf), el->ethAddressString); dumpSuspiciousPacket(actualDeviceId); } } setSpoofingFlag = 1; hostFound = 1; break; } } else { /* -o | --no-mac (or NetFlow, which doesn't have MACs) - compare with only the IP address */ if(addrcmp(&el->hostIpAddress, hostIpAddress) == 0) { hostFound = 1; break; } } } el = el->next; numRuns++; } /* while */ if(locked_mutex) releaseMutex(&myGlobals.hostsHashLockMutex); if((hostFound == 1) && (vlanId != NO_VLAN) && (vlanId != el->vlanId) && (!isMultivlaned(el))) { FD_SET(FLAG_HOST_TYPE_MULTIVLANED, &el->flags); if(myGlobals.multipleVLANedHostCount == 0) { traceEvent(CONST_TRACE_ERROR, "mVLAN: Host (identical IP/MAC) found on multiple VLANs"); traceEvent(CONST_TRACE_INFO, "mVLAN: ntop continues but will consolidate and thus probably overcount this traffic"); traceEvent(CONST_TRACE_NOISY, "mVLAN: Up to %d examples will be printed", MAX_MULTIPLE_VLAN_WARNINGS); } if(++myGlobals.multipleVLANedHostCount < MAX_MULTIPLE_VLAN_WARNINGS) traceEvent(CONST_TRACE_NOISY, "mVLAN: Device %d Host %s (%02x:%02x:%02x:%02x:%02x:%02x) VLANs %d and %d", actualDeviceId, addrtostr(hostIpAddress), ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5], min(vlanId, el->vlanId), max(vlanId, el->vlanId)); } if(numRuns > myGlobals.device[actualDeviceId].hashListMaxLookups) myGlobals.device[actualDeviceId].hashListMaxLookups = numRuns ; if(hostFound) { /* Existing host entry */ if((updateIPinfo == 1) && (el->hostNumIpAddress[0] == '\0')) { /* This entry didn't have IP fields set: let's set them now */ addrcpy(&el->hostIpAddress, hostIpAddress); strncpy(el->hostNumIpAddress, _addrtostr(hostIpAddress, buf, sizeof(buf)), sizeof(el->hostNumIpAddress)); setResolvedName(el, el->hostNumIpAddress, FLAG_HOST_SYM_ADDR_TYPE_IP); if(myGlobals.runningPref.numericFlag == 0) ipaddr2str(el->hostIpAddress, 1); if(isBroadcastAddress(&el->hostIpAddress, NULL, NULL)) FD_SET(FLAG_BROADCAST_HOST, &el->flags); } } else { /* New host entry */ int len; if(myGlobals.device[actualDeviceId].hostsno >= myGlobals.runningPref.maxNumHashEntries) { static char messageShown = 0; if(!messageShown) { messageShown = 1; traceEvent(CONST_TRACE_INFO, "WARNING: Max num hash entries (%u) reached (see -x)", myGlobals.runningPref.maxNumHashEntries); } if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } if((el = (HostTraffic*)malloc(sizeof(HostTraffic))) == NULL) { if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } memset(el, 0, sizeof(HostTraffic)); el->firstSeen = myGlobals.actTime; resetHostsVariables(el); el->vlanId = vlanId; if(isMultihomed) FD_SET(FLAG_HOST_TYPE_MULTIHOMED, &el->flags); if(el->portsUsage != NULL) freePortsUsage(el); len = (size_t)myGlobals.numIpProtosList*sizeof(ShortProtoTrafficInfo**); if((el->ipProtosList = (ShortProtoTrafficInfo**)malloc(len)) == NULL) { if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } memset(el->ipProtosList, 0, len); len = (size_t)myGlobals.numIpProtosToMonitor*sizeof(ProtoTrafficInfo**); if((el->protoIPTrafficInfos = (ProtoTrafficInfo**)malloc(len)) == NULL) { if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } memset(el->protoIPTrafficInfos, 0, len); el->magic = CONST_MAGIC_NUMBER; el->hostTrafficBucket = idx; /* Set the bucket index */ el->originalHostTrafficBucket = idx; /* Set the bucket index */ /* traceEvent(CONST_TRACE_INFO, "new entry added at bucket %d", idx); */ /* Put the new entry on top of the list */ el->next = myGlobals.device[actualDeviceId].hash_hostTraffic[el->hostTrafficBucket]; myGlobals.device[actualDeviceId].hash_hostTraffic[el->hostTrafficBucket] = el; /* Insert a new entry */ myGlobals.device[actualDeviceId].hostsno++; if(0) traceEvent(CONST_TRACE_INFO, "-> Allocated(%d) [tot=%d]", actualDeviceId, myGlobals.device[actualDeviceId].hostsno); the_local_network = 0, the_local_network_mask = 0; if(ether_addr != NULL) { if((hostIpAddress == NULL) || ((hostIpAddress != NULL) && isPseudoLocalAddress(hostIpAddress, actualDeviceId, &the_local_network, &the_local_network_mask) /* && (!isBroadcastAddress(hostIpAddress, &the_local_network, &the_local_network_mask))*/ )) { char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY]; /* This is a local address and then the ethernet address does make sense */ ethAddr = etheraddr_string(ether_addr, etherbuf); memcpy(el->ethAddress, ether_addr, LEN_ETHERNET_ADDRESS); strncpy(el->ethAddressString, ethAddr, sizeof(el->ethAddressString)); symEthName = getSpecialMacInfo(el, (short)(!myGlobals.separator[0])); FD_SET(FLAG_SUBNET_LOCALHOST, &el->flags); FD_SET(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags); /* traceEvent(CONST_TRACE_WARNING, "-> %u/%u", the_local_network, the_local_network_mask); */ } else if(hostIpAddress != NULL) { /* This is packet that's being routed or belonging to a remote network that uses the same physical wire (or forged)*/ memcpy(el->lastEthAddress, ether_addr, LEN_ETHERNET_ADDRESS); if(hostIpAddress != NULL) { if(hostIpAddress->hostFamily == AF_INET) memcpy(el->ethAddress, &hostIpAddress->Ip4Address.s_addr, 4); /* Dummy/unique eth address */ #ifdef INET6 else if(hostIpAddress->hostFamily == AF_INET6) memcpy(el->ethAddress, &hostIpAddress->Ip6Address.s6_addr[8], 4); #endif FD_CLR(FLAG_SUBNET_LOCALHOST, &el->flags); if(isPrivateAddress(hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_PRIVATE_IP_ADDRESS, &el->flags); if(!isBroadcastAddress(hostIpAddress, &the_local_network, &the_local_network_mask)) { if(isPseudoLocalAddress(hostIpAddress, actualDeviceId, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags); else FD_CLR(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags); } } } else { FD_CLR(FLAG_SUBNET_LOCALHOST, &el->flags); FD_CLR(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags); } if(strncmp(el->ethAddressString, "FF:", 3) == 0) { /* The trick below allows me not to duplicate the "" string in the code */ if(hostIpAddress != NULL) { if(hostIpAddress->hostFamily == AF_INET) el->hostIp4Address.s_addr = INADDR_BROADCAST; #ifdef INET6 else if(hostIpAddress->hostFamily == AF_INET6) el->hostIp6Address = _in6addr_linklocal_allnodes; #endif } FD_SET(FLAG_BROADCAST_HOST, &el->flags); if(isMulticastAddress(&el->hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_MULTICAST_HOST, &el->flags); strncpy(el->hostNumIpAddress, _addrtostr(&el->hostIpAddress, buf, sizeof(buf)), strlen(el->hostNumIpAddress)); setResolvedName(el, el->hostNumIpAddress, FLAG_HOST_SYM_ADDR_TYPE_IP); if((!addrnull(&el->hostIpAddress)) /* 0.0.0.0 */ && (!addrfull(&el->hostIpAddress)) /* 255.255.255.255 */ && isBroadcastAddress(&el->hostIpAddress, &the_local_network, &the_local_network_mask)) { /* The sender of this packet has obviously a wrong netmask because: - it is a local host - it has sent a packet to a broadcast address - it has not used the FF:FF:FF:FF:FF:FF MAC address */ traceEvent(CONST_TRACE_WARNING, "Wrong netmask detected [%s/%s]", _addrtostr(&el->hostIpAddress, buf, sizeof(buf)), el->ethAddressString); } } #ifdef DEBUG { char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY]; /* if((strcmp(etheraddr_string(ether_addr, etherbuf), "08:00:20:89:79:D7") == 0) || (strcmp(el->hostResolvedName, "more") == 0)) */ printf("Added a new hash_hostTraffic entry [%s/%s/%s/%d][idx=%d]\n", etheraddr_string(ether_addr, etherbuf), el->hostResolvedName, el->hostNumIpAddress, myGlobals.device[actualDeviceId].hostsno, idx); } #endif el->lastSeen = myGlobals.actTime; if(myGlobals.runningPref.enableSuspiciousPacketDump) checkSpoofing(el, actualDeviceId); } if(hostIpAddress != NULL) { if(myGlobals.runningPref.dontTrustMACaddr && (ether_addr != NULL)) memcpy(el->lastEthAddress, ether_addr, LEN_ETHERNET_ADDRESS); addrcpy(&el->hostIpAddress,hostIpAddress); strncpy(el->hostNumIpAddress, _addrtostr(hostIpAddress, buf, sizeof(buf)), sizeof(el->hostNumIpAddress)); if(isBroadcastAddress(&el->hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_BROADCAST_HOST, &el->flags); if(isMulticastAddress(&el->hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_MULTICAST_HOST, &el->flags); if(isPrivateAddress(hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_PRIVATE_IP_ADDRESS, &el->flags); if((ether_addr == NULL) && (isPseudoLocalAddress(hostIpAddress, actualDeviceId, &the_local_network, &the_local_network_mask))) FD_SET(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags); setResolvedName(el, el->hostNumIpAddress, FLAG_HOST_SYM_ADDR_TYPE_IP); /* Trick to fill up the address cache */ if(myGlobals.runningPref.numericFlag == 0) ipaddr2str(el->hostIpAddress, 1); getHostAS(el); } else { /* This is a new entry and hostIpAddress was NOT set. Fill in MAC address, if we have it */ if(symEthName[0] != '\0') { /* This is a local address so we have the MAC address */ safe_snprintf(__FILE__, __LINE__, buf, sizeof(buf), "%s%s", symEthName, &el->ethAddressString[8]); buf[MAX_LEN_SYM_HOST_NAME-1] = '\0'; setResolvedName(el, buf, FLAG_HOST_SYM_ADDR_TYPE_MAC); } } #ifdef HASH_DEBUG traceEvent(CONST_TRACE_INFO, "HASH_DEBUG: Adding %s/%s [idx=%d][device=%d]" "[actualHashSize=%d][#hosts=%d]", el->ethAddressString, el->hostNumIpAddress, idx, actualDeviceId, myGlobals.device[actualDeviceId].actualHashSize, myGlobals.device[actualDeviceId].hostsno); #endif setHostSerial(el); handlePluginHostCreationDeletion(el, (u_short)actualDeviceId, 1 /* host creation */); } if(el != NULL) { el->lastSeen = myGlobals.actTime; if(setSpoofingFlag) FD_SET(FLAG_HOST_DUPLICATED_MAC, &el->flags); #ifdef DEBUG { if((hostIpAddress != NULL) && (hostIpAddress->hostFamily == AF_INET6)){ char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY]; traceEvent(CONST_TRACE_INFO, "lookupHost(idx=%d/actualDeviceId=%d) [%s/%s/%s/%d/%d]", idx, actualDeviceId, etheraddr_string(ether_addr, etherbuf), el->hostResolvedName, el->hostNumIpAddress, myGlobals.device[actualDeviceId].hostsno, useIPAddressForSearching); } } #endif } #ifdef DEBUG if(el == NULL) traceEvent(CONST_TRACE_INFO, "lookupHost(idx=%d) is NULL", idx); #endif #ifdef HASH_DEBUG hashSanityCheck(); #endif if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(el); } /* ********************************************************** */ HostTraffic *lookupFcHost (FcAddress *hostFcAddress, u_short vsanId, int actualDeviceId) { u_int idx; HostTraffic *el=NULL; FcNameServerCacheEntry *fcnsEntry; u_char locked_mutex = 0; u_short numRuns=0; u_int hostFound = 0; if(hostFcAddress == NULL) { traceEvent(CONST_TRACE_ERROR, "lookupFcHost: Call invoked with NULL" "FC Address, vsan = %d, device = %d", vsanId, actualDeviceId); return(NULL); } idx = hashFcHost (hostFcAddress, vsanId, &el, actualDeviceId); if(el != NULL) { return (el); } else if(idx == FLAG_NO_PEER) return(NULL); else { el = myGlobals.device[actualDeviceId].hash_hostTraffic[idx]; if(el) { lockHostsHashMutex(el, "lookupFcHost"); el = myGlobals.device[actualDeviceId].hash_hostTraffic[idx]; locked_mutex = 1; } } hostFound = 0; /* This is the same type as the one of HashList */ while(el != NULL) { if(el->magic != CONST_MAGIC_NUMBER) { traceEvent(CONST_TRACE_ERROR, "Bad magic number (expected=%d/real=%d) lookupFcHost()", CONST_MAGIC_NUMBER, el->magic); break; /* Can't trust this chain ... */ } if(el->hostTrafficBucket != idx) { traceEvent(CONST_TRACE_WARNING, "Error: wrong bucketIdx %s/%s (expected=%d/real=%d)", el->ethAddressString, el->hostNumIpAddress, idx, el->hostTrafficBucket); } if ((el->fcCounters != NULL) && (memcmp ((u_int8_t *)&(el->fcCounters->hostFcAddress), hostFcAddress, LEN_FC_ADDRESS) == 0)) { hostFound = 1; break; } el = el->next; numRuns++; } if(numRuns > myGlobals.device[actualDeviceId].hashListMaxLookups) { myGlobals.device[actualDeviceId].hashListMaxLookups = numRuns ; } if(!hostFound) { /* New host entry */ if(myGlobals.device[actualDeviceId].hostsno >= myGlobals.runningPref.maxNumHashEntries) { static char messageShown = 0; if(!messageShown) { messageShown = 1; traceEvent(CONST_TRACE_INFO, "WARNING: Max num hash entries (%u) reached (see -x)", myGlobals.runningPref.maxNumHashEntries); } if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } if((el = (HostTraffic*)malloc(sizeof(HostTraffic))) == NULL) { if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } memset(el, 0, sizeof(HostTraffic)); el->firstSeen = myGlobals.actTime; resetHostsVariables(el); if(allocFcScsiCounters(el) == NULL) { if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(NULL); } el->l2Family = FLAG_HOST_TRAFFIC_AF_FC; el->fcCounters->devType = SCSI_DEV_UNINIT; el->magic = CONST_MAGIC_NUMBER; el->hostTrafficBucket = idx; el->next = myGlobals.device[actualDeviceId].hash_hostTraffic[el->hostTrafficBucket]; myGlobals.device[actualDeviceId].hash_hostTraffic[el->hostTrafficBucket] = el; /* Insert a new entry */ myGlobals.device[actualDeviceId].hostsno++; el->fcCounters->hostFcAddress.domain = hostFcAddress->domain; el->fcCounters->hostFcAddress.area = hostFcAddress->area; el->fcCounters->hostFcAddress.port = hostFcAddress->port; safe_snprintf(__FILE__, __LINE__, el->fcCounters->hostNumFcAddress, sizeof(el->fcCounters->hostNumFcAddress), fc_to_str ((u_int8_t *)hostFcAddress)); /* TBD: Resolve FC_ID to WWN */ el->fcCounters->vsanId = vsanId; /* If there is a cache entry, use it */ if((fcnsEntry = findFcHostNSCacheEntry (&el->fcCounters->hostFcAddress, vsanId)) != NULL) { if(fcnsEntry->alias != NULL) setResolvedName(el, fcnsEntry->alias, FLAG_HOST_SYM_ADDR_TYPE_FC_ALIAS); else setResolvedName(el, (char*)fcnsEntry->pWWN.str, FLAG_HOST_SYM_ADDR_TYPE_FC_WWN); memcpy (el->fcCounters->pWWN.str, fcnsEntry->pWWN.str, LEN_WWN_ADDRESS); memcpy (el->fcCounters->nWWN.str, fcnsEntry->nWWN.str, LEN_WWN_ADDRESS); } else { setResolvedName(el, el->fcCounters->hostNumFcAddress, FLAG_HOST_SYM_ADDR_TYPE_FCID); } #ifdef HASH_DEBUG traceEvent(CONST_TRACE_INFO, "HASH_DEBUG: Adding %s/%s [idx=%d][device=%d][actualHashSize=%d][#hosts=%d]", el->ethAddressString, el->hostNumIpAddress, list->idx, actualDeviceId, myGlobals.device[actualDeviceId].actualHashSize, myGlobals.device[actualDeviceId].hostsno); #endif setHostSerial(el); } if(el != NULL) { el->lastSeen = myGlobals.actTime; } if(el == NULL) traceEvent(CONST_TRACE_ALWAYSDISPLAY, "getHostInfo(idx=%d)(ptr=%p)", idx, (void*)myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); #ifdef HASH_DEBUG hashSanityCheck(); #endif if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]); return(el); } /* ************************************ */ #ifdef HASH_DEBUG static void dumpHash() { int i=0; HostTraffic *el; for(el=getFirstHost(myGlobals.actualReportDeviceId); el != NULL; el = getNextHost(myGlobals.actualReportDeviceId, el)) { traceEvent(CONST_TRACE_INFO, "HASH_DEBUG: (%3d) %s / %s [bkt=%d][orig bkt=%d][next=0x%X]", i++, el->ethAddressString, el->hostNumIpAddress, el->hostTrafficBucket, el->originalHostTrafficBucket, el->next); } } /* ***************************************** */ static void hashSanityCheck() { int i=0; for(i=FIRST_HOSTS_ENTRY; ihostTrafficBucket != i) traceEvent(CONST_TRACE_ERROR, "HASH: (%3d) %s / %s [bkt=%d][orig bkt=%d][next=0x%X]", i, el->ethAddressString, el->hostNumIpAddress, el->hostTrafficBucket, el->originalHostTrafficBucket, el->next); el = el->next; } } } /* ***************************************** */ static void hostHashSanityCheck(HostTraffic *host) { int i=0; for(i=FIRST_HOSTS_ENTRY; iethAddressString, el->hostNumIpAddress, el->hostTrafficBucket, el->originalHostTrafficBucket, el->next); el = el->next; } } } #endif /* HASH_DEBUG */ /* ****************************** Utility functions used by the remote plugin ****************************** */ #define MAX_NUM_VALID_PTRS 8 static void* valid_ptrs[MAX_NUM_VALID_PTRS] = { NULL }; void add_valid_ptr(void* ptr) { int i; traceEvent(CONST_TRACE_INFO, "add_valid_ptr(%p)", ptr); for(i=0; i 0) { /* Move towards the top */ void *swap = valid_ptrs[i-1]; valid_ptrs[i-1] = valid_ptrs[i]; valid_ptrs[i] = swap; } traceEvent(CONST_TRACE_INFO, "is_valid_ptr(%p): 1", ptr); return(1); } } traceEvent(CONST_TRACE_INFO, "is_valid_ptr(%p): 0", ptr); return(0); }