73
73
} else if(hostIpAddress == NULL) {
74
74
memcpy(&idx, ðer_addr[LEN_ETHERNET_ADDRESS-sizeof(u_int)], sizeof(u_int));
75
75
(*useIPAddressForSearching) = 0;
76
} else if(isBroadcastAddress(hostIpAddress)) {
76
} else if(isBroadcastAddress(hostIpAddress, NULL, NULL)) {
77
77
*el = myGlobals.broadcastEntry;
78
78
return(BROADCAST_HOSTS_ENTRY);
79
} else if(isPseudoLocalAddress(hostIpAddress, actualDeviceId)) {
79
} else if(isPseudoLocalAddress(hostIpAddress, actualDeviceId, NULL, NULL)) {
80
80
memcpy(&idx, ðer_addr[LEN_ETHERNET_ADDRESS-sizeof(u_int)], sizeof(u_int));
81
81
(*useIPAddressForSearching) = 0;
83
83
if(hostIpAddress != NULL) {
84
84
if(myGlobals.runningPref.trackOnlyLocalHosts
85
&& (!isPseudoLocalAddress(hostIpAddress, actualDeviceId))) {
85
&& (!isPseudoLocalAddress(hostIpAddress, actualDeviceId, NULL, NULL))) {
86
86
*el = myGlobals.otherHostEntry;
87
87
return(OTHER_HOSTS_ENTRY);
564
549
/* ************************************ */
551
int is_host_ready_to_purge(int actDevice, HostTraffic *el, time_t now) {
552
/* Time used to decide whether a host need to be purged */
553
time_t noSessionPurgeTime = now-PARM_HOST_PURGE_MINIMUM_IDLE_NOACTVSES;
554
time_t withSessionPurgeTime = now-PARM_HOST_PURGE_MINIMUM_IDLE_ACTVSES;
559
&& ((!myGlobals.runningPref.rFileName)
560
&& (((el->numHostSessions == 0) && (el->lastSeen < noSessionPurgeTime))
561
|| ((el->numHostSessions > 0) && (el->lastSeen < withSessionPurgeTime))))
562
&& (!broadcastHost(el)) && (el != myGlobals.otherHostEntry)
563
&& (myGlobals.device[actDevice].virtualDevice /* e.g. sFlow/NetFlow */
564
|| (!myGlobals.runningPref.stickyHosts)
565
|| ((el->l2Family == FLAG_HOST_TRAFFIC_AF_ETH) &&
566
((el->hostNumIpAddress[0] == '\0') /* Purge MAC addresses too */
567
|| (!subnetPseudoLocalHost(el)))) /* Purge remote hosts only */
568
|| ((el->l2Family == FLAG_HOST_TRAFFIC_AF_FC) &&
569
(el->fcCounters->hostNumFcAddress[0] == '\0')))))
575
/* ************************************ */
566
577
int purgeIdleHosts(int actDevice) {
567
578
u_int idx, numFreedBuckets=0, numHosts = 0;
568
time_t startTime = time(NULL), noSessionPurgeTime, withSessionPurgeTime;
579
time_t now = time(NULL);
569
580
static time_t lastPurgeTime[MAX_NUM_DEVICES];
570
581
static char firstRun = 1;
571
582
HostTraffic **theFlaggedHosts = NULL;
588
599
gettimeofday(&hiresTimeStart, NULL);
590
if(startTime < (lastPurgeTime[actDevice]+PARM_HOST_PURGE_INTERVAL))
601
if(now < (lastPurgeTime[actDevice]+PARM_HOST_PURGE_INTERVAL))
591
602
return(0); /* Too short */
593
lastPurgeTime[actDevice] = startTime;
604
lastPurgeTime[actDevice] = now;
595
606
maxHosts = myGlobals.device[actDevice].hostsno; /* save it as it can change */
596
607
myGlobals.piMem = maxHosts*sizeof(HostTraffic*);
597
608
theFlaggedHosts = (HostTraffic**)calloc(1, myGlobals.piMem);
599
/* Time used to decide whether a host need to be purged */
600
noSessionPurgeTime = startTime-PARM_HOST_PURGE_MINIMUM_IDLE_NOACTVSES;
601
withSessionPurgeTime = startTime-PARM_HOST_PURGE_MINIMUM_IDLE_ACTVSES;
603
#ifdef IDLE_PURGE_DEBUG
604
traceEvent(CONST_TRACE_INFO, "IDLE_PURGE_DEBUG: Beginning noS < %d, wS < %d",
605
noSessionPurgeTime, withSessionPurgeTime);
608
610
purgeOldFragmentEntries(actDevice); /* let's do this too */
610
612
#ifdef IDLE_PURGE_DEBUG
622
624
accessMutex(&myGlobals.hostsHashLockMutex, "scanIdleLoop");
624
626
for(idx=0; idx<myGlobals.device[actDevice].actualHashSize; idx++) {
627
if(myGlobals.ntopRunState >= FLAG_NTOPSTATE_SHUTDOWN) break;
625
629
if((el = myGlobals.device[actDevice].hash_hostTraffic[idx]) != NULL) {
629
if((el->refCount == 0)
630
&& ( ((el->numHostSessions == 0) && (el->lastSeen < noSessionPurgeTime))
631
|| ((el->numHostSessions > 0) && (el->lastSeen < withSessionPurgeTime)))
632
&& (!broadcastHost(el)) && (el != myGlobals.otherHostEntry)
633
&& (myGlobals.device[actDevice].virtualDevice /* e.g. sFlow/NetFlow */
634
|| (!myGlobals.runningPref.stickyHosts)
635
|| ((el->l2Family == FLAG_HOST_TRAFFIC_AF_ETH) &&
636
((el->hostNumIpAddress[0] == '\0') /* Purge MAC addresses too */
637
|| (!subnetPseudoLocalHost(el)))) /* Purge remote hosts only */
638
|| ((el->l2Family == FLAG_HOST_TRAFFIC_AF_FC) &&
639
(el->fcCounters->hostNumFcAddress[0] == '\0')))) {
633
if(is_host_ready_to_purge(actDevice, el, now)) {
634
if(!el->to_be_deleted) {
635
el->to_be_deleted = 1; /* Delete it at the next run */
637
/* Skip it and move to next host */
640
641
/* Host selected for deletion */
641
642
theFlaggedHosts[numHosts++] = el;
643
el->magic = CONST_UNMAGIC_NUMBER;
644
purgeQueuedV4HostAddress(el->hostIpAddress.Ip4Address.s_addr);
645
remove_valid_ptr(el);
757
763
Searches a host and returns it. If the host is not
758
764
present in the hash a new bucket is created
760
HostTraffic* _lookupHost(HostAddr *hostIpAddress, u_char *ether_addr, short vlanId,
761
u_char checkForMultihoming, u_char forceUsingIPaddress,
762
int actualDeviceId, char *file, int line) {
766
HostTraffic* _lookupHost(HostAddr *hostIpAddress, u_char *ether_addr, u_int16_t vlanId,
767
u_char checkForMultihoming, u_char forceUsingIPaddress,
768
int actualDeviceId, char *file, int line) {
763
769
u_int idx, isMultihomed = 0;
764
770
HostTraffic *el=NULL;
765
771
char buf[MAX_LEN_SYM_HOST_NAME_HTML];
766
772
short useIPAddressForSearching = forceUsingIPaddress;
767
773
char* symEthName = NULL, *ethAddr;
768
u_char setSpoofingFlag = 0;
774
u_char setSpoofingFlag = 0, locked_mutex = 0;
769
775
u_short numRuns=0;
770
776
u_int hostFound = 0;
771
777
u_int updateIPinfo = 0;
778
u_int32_t the_local_network, the_local_network_mask;
773
780
if((hostIpAddress == NULL) && (ether_addr == NULL)) {
774
traceEvent(CONST_TRACE_WARNING, "Both Ethernet and IP addresses are NULL in lookupHost()[%s/%d]", file, line);
781
traceEvent(CONST_TRACE_WARNING, "Both Ethernet and IP addresses are NULL in lookupHost()[%s:%d]", file, line);
799
806
return(el); /* Found */
800
807
else if(idx == FLAG_NO_PEER)
803
810
el = myGlobals.device[actualDeviceId].hash_hostTraffic[idx];
812
lockHostsHashMutex(el, "_lookupHost");
813
accessMutex(&myGlobals.hostsHashLockMutex, "lookupHost");
814
el = myGlobals.device[actualDeviceId].hash_hostTraffic[idx];
805
819
while (el != NULL) {
806
820
if(el->magic != CONST_MAGIC_NUMBER) {
807
821
traceEvent(CONST_TRACE_ERROR,
808
"Bad magic number (expected=%d/real=%d) [deviceId=%d] lookupHost()[%s/%d]",
822
"Bad magic number (expected=%d/real=%d) [deviceId=%d] lookupHost()[%s:%d]",
809
823
CONST_MAGIC_NUMBER, el->magic, actualDeviceId,
811
825
break; /* Can't trust this chain ... */
814
828
if(el->hostTrafficBucket != idx) {
815
829
traceEvent(CONST_TRACE_WARNING,
816
"Error: wrong bucketIdx %s/%s (expected=%d/real=%d) [deviceId=%d] lookupHost()[%s/%d]",
830
"Error: wrong bucketIdx %s/%s (expected=%d/real=%d) [deviceId=%d] lookupHost()[%s:%d]",
817
831
el->ethAddressString, el->hostNumIpAddress,
818
832
idx, el->hostTrafficBucket, actualDeviceId,
822
if(useIPAddressForSearching == 0) {
823
/* compare with the ethernet-address then the IP address */
824
if(memcmp(el->ethAddress, ether_addr, LEN_ETHERNET_ADDRESS) == 0) {
825
if((hostIpAddress != NULL) &&
826
(hostIpAddress->hostFamily == el->hostIpAddress.hostFamily)) {
827
if((!isMultihomed) && checkForMultihoming) {
828
/* This is a local address hence this is a potential multihomed host. */
830
if(!(addrnull(&el->hostIpAddress)) &&
831
(addrcmp(&el->hostIpAddress,hostIpAddress) != 0)) {
833
FD_SET(FLAG_HOST_TYPE_MULTIHOMED, &el->flags);
840
} else if(hostIpAddress == NULL){ /* Only Mac Addresses */
843
} else { /* MAC match found and we have the IP - need to update... */
848
} else if((hostIpAddress != NULL) &&
849
(addrcmp(&el->hostIpAddress, hostIpAddress) == 0)) {
850
/* Spoofing or duplicated MAC address:
851
two hosts with the same IP address and different MAC
855
if(!hasDuplicatedMac(el)) {
856
FD_SET(FLAG_HOST_DUPLICATED_MAC, &el->flags);
858
if(myGlobals.runningPref.enableSuspiciousPacketDump) {
859
char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY];
861
traceEvent(CONST_TRACE_WARNING,
862
"Two MAC addresses found for the same IP address "
863
"%s: [%s/%s] (spoofing detected?)",
864
el->hostNumIpAddress,
865
etheraddr_string(ether_addr, etherbuf), el->ethAddressString);
866
dumpSuspiciousPacket(actualDeviceId);
875
/* -o | --no-mac (or NetFlow, which doesn't have MACs) - compare with only the IP address */
876
if(addrcmp(&el->hostIpAddress, hostIpAddress) == 0) {
836
if(!is_host_ready_to_purge(actualDeviceId, el, myGlobals.actTime)) {
837
if(useIPAddressForSearching == 0) {
838
/* compare with the ethernet-address then the IP address */
839
if(memcmp(el->ethAddress, ether_addr, LEN_ETHERNET_ADDRESS) == 0) {
840
if((hostIpAddress != NULL) &&
841
(hostIpAddress->hostFamily == el->hostIpAddress.hostFamily)) {
842
if((!isMultihomed) && checkForMultihoming) {
843
/* This is a local address hence this is a potential multihomed host. */
845
if(!(addrnull(&el->hostIpAddress)) &&
846
(addrcmp(&el->hostIpAddress,hostIpAddress) != 0)) {
848
FD_SET(FLAG_HOST_TYPE_MULTIHOMED, &el->flags);
855
} else if(hostIpAddress == NULL){ /* Only Mac Addresses */
858
} else { /* MAC match found and we have the IP - need to update... */
863
} else if((hostIpAddress != NULL) &&
864
(addrcmp(&el->hostIpAddress, hostIpAddress) == 0)) {
865
/* Spoofing or duplicated MAC address:
866
two hosts with the same IP address and different MAC
870
if(!hasDuplicatedMac(el)) {
871
FD_SET(FLAG_HOST_DUPLICATED_MAC, &el->flags);
873
if(myGlobals.runningPref.enableSuspiciousPacketDump) {
874
char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY];
876
traceEvent(CONST_TRACE_WARNING,
877
"Two MAC addresses found for the same IP address "
878
"%s: [%s/%s] (spoofing detected?)",
879
el->hostNumIpAddress,
880
etheraddr_string(ether_addr, etherbuf), el->ethAddressString);
881
dumpSuspiciousPacket(actualDeviceId);
890
/* -o | --no-mac (or NetFlow, which doesn't have MACs) - compare with only the IP address */
891
if(addrcmp(&el->hostIpAddress, hostIpAddress) == 0) {
886
if((hostFound == 1) && (vlanId > 0) && (vlanId != el->vlanId) && (!isMultivlaned(el))) {
901
if(locked_mutex) releaseMutex(&myGlobals.hostsHashLockMutex);
903
if((hostFound == 1) && (vlanId != NO_VLAN) && (vlanId != el->vlanId) && (!isMultivlaned(el))) {
887
904
FD_SET(FLAG_HOST_TYPE_MULTIVLANED, &el->flags);
888
905
if(myGlobals.multipleVLANedHostCount == 0) {
889
906
traceEvent(CONST_TRACE_ERROR, "mVLAN: Host (identical IP/MAC) found on multiple VLANs");
937
954
myGlobals.runningPref.maxNumHashEntries);
944
if(myGlobals.hostsCacheLen > 0) {
945
el = myGlobals.hostsCache[--myGlobals.hostsCacheLen];
946
myGlobals.hostsCacheReused++;
948
traceEvent(CONST_TRACE_INFO, "Fetched host from pointers cache (len=%d)",
949
(int)myGlobals.hostsCacheLen);
954
if((el = (HostTraffic*)malloc(sizeof(HostTraffic))) == NULL)
957
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
961
if((el = (HostTraffic*)malloc(sizeof(HostTraffic))) == NULL) {
962
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
957
966
memset(el, 0, sizeof(HostTraffic));
958
967
el->firstSeen = myGlobals.actTime;
967
976
freePortsUsage(el);
969
978
len = (size_t)myGlobals.numIpProtosList*sizeof(ShortProtoTrafficInfo**);
970
if((el->ipProtosList = (ShortProtoTrafficInfo**)malloc(len)) == NULL) return(NULL);
979
if((el->ipProtosList = (ShortProtoTrafficInfo**)malloc(len)) == NULL) {
980
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
971
983
memset(el->ipProtosList, 0, len);
973
985
len = (size_t)myGlobals.numIpProtosToMonitor*sizeof(ProtoTrafficInfo**);
974
if((el->protoIPTrafficInfos = (ProtoTrafficInfo**)malloc(len)) == NULL) return(NULL);
986
if((el->protoIPTrafficInfos = (ProtoTrafficInfo**)malloc(len)) == NULL) {
987
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
975
990
memset(el->protoIPTrafficInfos, 0, len);
977
992
el->magic = CONST_MAGIC_NUMBER;
985
1000
myGlobals.device[actualDeviceId].hash_hostTraffic[el->hostTrafficBucket] = el; /* Insert a new entry */
986
1001
myGlobals.device[actualDeviceId].hostsno++;
1004
traceEvent(CONST_TRACE_INFO, "-> Allocated(%d) [tot=%d]",
1005
actualDeviceId, myGlobals.device[actualDeviceId].hostsno);
1007
the_local_network = 0, the_local_network_mask = 0;
988
1009
if(ether_addr != NULL) {
989
1010
if((hostIpAddress == NULL)
990
1011
|| ((hostIpAddress != NULL)
991
&& isPseudoLocalAddress(hostIpAddress, actualDeviceId)
992
/* && (!isBroadcastAddress(hostIpAddress))*/
1012
&& isPseudoLocalAddress(hostIpAddress, actualDeviceId, &the_local_network, &the_local_network_mask)
1013
/* && (!isBroadcastAddress(hostIpAddress, &the_local_network, &the_local_network_mask))*/
994
1015
char etherbuf[LEN_ETHERNET_ADDRESS_DISPLAY];
1018
1040
FD_CLR(FLAG_SUBNET_LOCALHOST, &el->flags);
1020
if(isPrivateAddress(hostIpAddress)) FD_SET(FLAG_PRIVATE_IP_ADDRESS, &el->flags);
1042
if(isPrivateAddress(hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_PRIVATE_IP_ADDRESS, &el->flags);
1022
if(!isBroadcastAddress(hostIpAddress)) {
1023
if(isPseudoLocalAddress(hostIpAddress, actualDeviceId))
1044
if(!isBroadcastAddress(hostIpAddress, &the_local_network, &the_local_network_mask)) {
1045
if(isPseudoLocalAddress(hostIpAddress, actualDeviceId, &the_local_network, &the_local_network_mask))
1024
1046
FD_SET(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags);
1026
1048
FD_CLR(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags);
1098
1120
strncpy(el->hostNumIpAddress,
1099
1121
_addrtostr(hostIpAddress, buf, sizeof(buf)),
1100
1122
sizeof(el->hostNumIpAddress));
1101
if(isBroadcastAddress(&el->hostIpAddress)) FD_SET(FLAG_BROADCAST_HOST, &el->flags);
1102
if(isMulticastAddress(&el->hostIpAddress)) FD_SET(FLAG_MULTICAST_HOST, &el->flags);
1103
if(isPrivateAddress(hostIpAddress)) FD_SET(FLAG_PRIVATE_IP_ADDRESS, &el->flags);
1104
if((ether_addr == NULL) && (isPseudoLocalAddress(hostIpAddress, actualDeviceId)))
1123
if(isBroadcastAddress(&el->hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_BROADCAST_HOST, &el->flags);
1124
if(isMulticastAddress(&el->hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_MULTICAST_HOST, &el->flags);
1125
if(isPrivateAddress(hostIpAddress, &the_local_network, &the_local_network_mask)) FD_SET(FLAG_PRIVATE_IP_ADDRESS, &el->flags);
1126
if((ether_addr == NULL) && (isPseudoLocalAddress(hostIpAddress, actualDeviceId, &the_local_network, &the_local_network_mask)))
1105
1127
FD_SET(FLAG_SUBNET_PSEUDO_LOCALHOST, &el->flags);
1107
1129
setResolvedName(el, el->hostNumIpAddress, FLAG_HOST_SYM_ADDR_TYPE_IP);
1110
1132
if(myGlobals.runningPref.numericFlag == 0)
1111
1133
ipaddr2str(el->hostIpAddress, 1);
1114
1137
/* This is a new entry and hostIpAddress was NOT set. Fill in MAC address, if we have it */
1115
1138
if(symEthName[0] != '\0') {
1116
1139
/* This is a local address so we have the MAC address */
1117
safe_snprintf(__FILE__, __LINE__, buf, sizeof(buf), "%s%s", symEthName, &el->ethAddressString[8]);
1140
safe_snprintf(__FILE__, __LINE__, buf, sizeof(buf), "%s%s",
1141
symEthName, &el->ethAddressString[8]);
1119
1143
buf[MAX_LEN_SYM_HOST_NAME-1] = '\0';
1120
1144
setResolvedName(el, buf, FLAG_HOST_SYM_ADDR_TYPE_MAC);
1124
1148
#ifdef HASH_DEBUG
1125
traceEvent(CONST_TRACE_INFO, "HASH_DEBUG: Adding %s/%s [idx=%d][device=%d][actualHashSize=%d][#hosts=%d]",
1149
traceEvent(CONST_TRACE_INFO, "HASH_DEBUG: Adding %s/%s [idx=%d][device=%d]"
1150
"[actualHashSize=%d][#hosts=%d]",
1126
1151
el->ethAddressString, el->hostNumIpAddress, idx, actualDeviceId,
1127
myGlobals.device[actualDeviceId].actualHashSize, myGlobals.device[actualDeviceId].hostsno);
1152
myGlobals.device[actualDeviceId].actualHashSize,
1153
myGlobals.device[actualDeviceId].hostsno);
1130
1156
setHostSerial(el);
1131
1157
handlePluginHostCreationDeletion(el, (u_short)actualDeviceId, 1 /* host creation */);
1135
1160
if(el != NULL) {
1136
1161
el->lastSeen = myGlobals.actTime;
1233
1266
myGlobals.runningPref.maxNumHashEntries);
1269
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
1240
if(myGlobals.hostsCacheLen > 0) {
1241
el = myGlobals.hostsCache[--myGlobals.hostsCacheLen];
1242
myGlobals.hostsCacheReused++;
1244
traceEvent(CONST_TRACE_INFO, "Fetched host from pointers cache (len=%d)",
1245
(int)myGlobals.hostsCacheLen);
1250
if((el = (HostTraffic*)malloc(sizeof(HostTraffic))) == NULL)
1273
if((el = (HostTraffic*)malloc(sizeof(HostTraffic))) == NULL) {
1274
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
1254
1278
memset(el, 0, sizeof(HostTraffic));
1255
1279
el->firstSeen = myGlobals.actTime;
1257
1281
resetHostsVariables(el);
1259
if(allocFcScsiCounters(el) == NULL) return(NULL);
1283
if(allocFcScsiCounters(el) == NULL) {
1284
if(locked_mutex) unlockHostsHashMutex(myGlobals.device[actualDeviceId].hash_hostTraffic[idx]);
1260
1287
el->l2Family = FLAG_HOST_TRAFFIC_AF_FC;
1261
1288
el->fcCounters->devType = SCSI_DEV_UNINIT;
1262
1289
el->magic = CONST_MAGIC_NUMBER;
1370
1398
#endif /* HASH_DEBUG */
1400
/* ******************************
1402
Utility functions used by the remote plugin
1404
****************************** */
1406
#define MAX_NUM_VALID_PTRS 8
1407
static void* valid_ptrs[MAX_NUM_VALID_PTRS] = { NULL };
1409
void add_valid_ptr(void* ptr) {
1412
traceEvent(CONST_TRACE_INFO, "add_valid_ptr(%p)", ptr);
1414
for(i=0; i<MAX_NUM_VALID_PTRS; i++) {
1415
if(valid_ptrs[i] == NULL) {
1416
valid_ptrs[i] = ptr;
1421
valid_ptrs[MAX_NUM_VALID_PTRS-1] = ptr;
1424
/* ****************************** */
1426
void remove_valid_ptr(void* ptr) {
1429
for(i=0; i<MAX_NUM_VALID_PTRS; i++) {
1430
if(valid_ptrs[i] == ptr) {
1431
valid_ptrs[i] = NULL;
1436
/* traceEvent(CONST_TRACE_ERROR, "remove_valid_ptr(%p) failed", ptr); */
1439
/* ****************************** */
1441
int is_valid_ptr(void* ptr) {
1444
for(i=0; i<MAX_NUM_VALID_PTRS; i++) {
1445
if(valid_ptrs[i] == ptr) {
1447
/* Move towards the top */
1448
void *swap = valid_ptrs[i-1];
1449
valid_ptrs[i-1] = valid_ptrs[i];
1450
valid_ptrs[i] = swap;
1453
traceEvent(CONST_TRACE_INFO, "is_valid_ptr(%p): 1", ptr);
1458
traceEvent(CONST_TRACE_INFO, "is_valid_ptr(%p): 0", ptr);