2
* Copyright (C) 1998-2001 Luca Deri <deri@ntop.org>
3
* Portions by Stefano Suin <stefano@ntop.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
* Copyright (c) 1994, 1996
24
* The Regents of the University of California. All rights reserved.
26
* Redistribution and use in source and binary forms, with or without
27
* modification, are permitted provided that: (1) source code distributions
28
* retain the above copyright notice and this paragraph in its entirety, (2)
29
* distributions including binary code include the above copyright notice and
30
* this paragraph in its entirety in the documentation or other materials
31
* provided with the distribution, and (3) all advertising materials mentioning
32
* features or use of this software display the following acknowledgement:
33
* ``This product includes software developed by the University of California,
34
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
35
* the University nor the names of its contributors may be used to endorse
36
* or promote products derived from this software without specific prior
38
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
39
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
40
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
48
static int enableDBsupport=0;
49
static int *servicesMapper = NULL; /* temporary value */
51
/* *************************** */
54
static void printMutexInfo(PthreadMutex *mutexId, char *mutexName) {
56
traceEvent(TRACE_INFO, "%s is %s (last lock %s:%d) [max lock time %s:%d (%d sec)]",
58
mutexId->isLocked ? "*locked*" : "unlocked",
59
mutexId->lockFile, mutexId->lockLine,
60
mutexId->maxLockedDurationUnlockFile,
61
mutexId->maxLockedDurationUnlockLine,
62
mutexId->maxLockedDuration);
67
void handleSigHup(int signalId _UNUSED_) {
69
traceEvent(TRACE_INFO, "========================================");
70
printMutexInfo(&gdbmMutex, "gdbmMutex");
71
printMutexInfo(&packetQueueMutex, "packetQueueMutex");
72
printMutexInfo(&addressResolutionMutex, "addressResolutionMutex");
73
printMutexInfo(&hashResizeMutex, "hashResizeMutex");
76
printMutexInfo(&lsofMutex, "lsofMutex");
77
printMutexInfo(&hostsHashMutex, "hostsHashMutex");
78
printMutexInfo(&graphMutex, "graphMutex");
79
#ifdef ASYNC_ADDRESS_RESOLUTION
81
printMutexInfo(&addressQueueMutex, "addressQueueMutex");
83
traceEvent(TRACE_INFO, "========================================");
84
#endif /* MULTITHREADED */
86
(void)setsignal(SIGHUP, handleSigHup);
91
/* *************************** */
95
void* pcapDispatch(void *_i) {
100
struct timeval timeout;
102
pcap_fd = pcap_fileno(device[i].pcapPtr);
104
if((pcap_fd == -1) && (rFileName != NULL)) {
106
This is a patch to overcome a bug of libpcap
107
while reading from a traffic file instead
108
of sniffying live from a NIC.
111
int fd, snapshot, linktype, tzoff, offset;
114
/* Other fields have been skipped. Please refer
115
to pcap-int.h for the full datatype.
119
pcap_fd = fileno(((struct mypcap *)(device[i].pcapPtr))->rfile);
122
for(;capturePackets == 1;) {
124
FD_SET(pcap_fd, &readMask);
126
timeout.tv_sec = 5 /* seconds */;
129
if(select(pcap_fd+1, &readMask, NULL, NULL, &timeout) > 0) {
130
/* printf("dispatch device %s\n", device[i].name);*/
131
if(!capturePackets) return(NULL);
132
rc = pcap_dispatch(device[i].pcapPtr, 1, processPacket, (u_char*)_i);
135
traceEvent(TRACE_ERROR, "Error while reading packets: %s.\n",
136
pcap_geterr(device[i].pcapPtr));
138
} else if((rc == 0) && (rFileName != NULL)) {
139
traceEvent(TRACE_INFO, "pcap_dispatch returned %d "
140
"[No more packets to read]", rc);
141
break; /* No more packets to read */
144
traceEvent(TRACE_INFO, "1) %d\n", numPkts++);
152
void* pcapDispatch(void *_i) {
156
for(;capturePackets == 1;) {
157
rc = pcap_dispatch(device[i].pcapPtr, 1, queuePacket, (u_char*)_i);
159
traceEvent(TRACE_ERROR, "Error while reading packets: %s.\n",
160
pcap_geterr(device[i].pcapPtr));
162
} /* elsetraceEvent(TRACE_INFO, "1) %d\n", numPkts++); */
170
/* **************************************** */
173
RETSIGTYPE handleDiedChild(int signal _UNUSED_) {
177
while((pidId = waitpid(-1, &status, WNOHANG)) > 0) {
181
traceEvent(TRACE_INFO,
182
"A child has terminated [pid=%d status=%d children=%d]\n",
183
pidId, status, numChildren);
188
/* setsignal(SIGCHLD, handleDiedChild); */
193
/* **************************************** */
197
void daemonize(void) {
200
signal(SIGHUP, SIG_IGN);
202
/* setsignal(SIGCHLD, handleDiedChild); */
203
setsignal(SIGCHLD, SIG_IGN);
205
signal(SIGQUIT, SIG_IGN);
207
if((childpid=fork()) < 0)
208
traceEvent(TRACE_ERROR, "An error occurred while daemonizing ntop (errno=%d)...\n", errno);
210
if(!childpid) { /* child */
211
traceEvent(TRACE_INFO, "Bye bye: I'm becoming a daemon...\n");
212
detachFromTerminal();
213
} else { /* father */
219
/* **************************************** */
221
void detachFromTerminal(void) {
222
#ifndef MULTITHREADED
223
alarm(120); /* Don't freeze */
227
useSyslog = 1; /* Log in the syslog */
231
setsid(); /* detach from the terminal */
233
#ifdef ORIGINAL_DETACH
234
if (freopen("/dev/null", "r", stdin) == NULL) {
235
traceEvent(TRACE_ERROR,
236
"ntop: unable to replace stdin with /dev/null: %s\n",
240
if (freopen("/dev/null", "w", stdout) == NULL) {
241
traceEvent(TRACE_ERROR,
242
"ntop: unable to replace stdout with /dev/null: %s\n",
247
if (freopen("/dev/null", "w", stderr) == NULL) {
248
traceEvent(TRACE_ERROR,
249
"ntop: unable to replace stderr with /dev/null: %s\n",
253
#else /* !ORIGINAL_DETACH */
256
/* fclose(stderr); */
259
* clear any inherited file mode creation mask
264
* Use linebuffered stdout
266
/* setlinebuf (stdout); */
267
setvbuf(stdout, (char *)NULL, _IOLBF, 0);
269
#endif /* ORIGINAL_DETACH */
273
/* **************************************** */
275
static short handleProtocol(char* protoName, char *protocol) {
276
int i, idx, lowProtoPort, highProtoPort;
277
short printWarnings = 0;
279
if(protocol[0] == '\0')
281
else if(isdigit(protocol[0])) {
282
/* numeric protocol port handling */
283
lowProtoPort = highProtoPort = 0;
284
sscanf(protocol, "%d-%d", &lowProtoPort, &highProtoPort);
285
if(highProtoPort < lowProtoPort)
286
highProtoPort = lowProtoPort;
288
if(lowProtoPort < 0) lowProtoPort = 0;
289
if(highProtoPort >= TOP_IP_PORT) highProtoPort = TOP_IP_PORT-1;
291
for(idx=lowProtoPort; idx<= highProtoPort; idx++) {
292
if(servicesMapper[idx] == -1) {
293
numIpPortsToHandle++;
296
printf("[%d] '%s' [port=%d]\n", numIpProtosToMonitor, protoName, idx);
298
servicesMapper[idx] = numIpProtosToMonitor;
299
} else if(printWarnings)
300
printf("WARNING: IP port %d (%s) has been discarded (multiple instances).\n",
307
for(i=1; i<numActServices; i++) {
310
if((udpSvc[i] != NULL) && (strcmp(udpSvc[i]->name, protocol) == 0))
311
idx = udpSvc[i]->port;
312
else if((tcpSvc[i] != NULL) && (strcmp(tcpSvc[i]->name, protocol) == 0))
313
idx = tcpSvc[i]->port;
316
if(servicesMapper[idx] == -1) {
317
numIpPortsToHandle++;
320
printf("[%d] '%s' [%s:%d]\n", numIpProtosToMonitor, protoName, protocol, idx);
322
servicesMapper[idx] = numIpProtosToMonitor;
323
} else if(printWarnings)
324
printf("WARNING: protocol '%s' has been discarded (multiple instances).\n",
331
traceEvent(TRACE_WARNING, "WARNING: unknown protocol '%s'. It has been ignored.\n",
337
/* **************************************** */
339
static void handleProtocolList(char* protoName,
340
char *protocolList) {
342
char* lastEntry, *protoEntry;
345
if(servicesMapper == NULL) {
346
servicesMapper = (int*)malloc(sizeof(int)*TOP_IP_PORT);
347
memset(servicesMapper, -1, sizeof(int)*TOP_IP_PORT);
351
traceEvent(TRACE_INFO, "%s - %s\n", protoName, protocolList);
354
/* The trick below is used to avoid to modify static
355
memory like in the case where this function is
356
called by addDefaultProtocols()
358
lastEntry = strncpy(tmpStr, protocolList, sizeof(tmpStr));
360
while((protoEntry = strchr(lastEntry, '|')) != NULL) {
361
protoEntry[0] = '\0';
362
rc = handleProtocol(protoName, lastEntry);
367
lastEntry = &protoEntry[1];
371
if(numIpProtosToMonitor == 0)
372
protoIPTrafficInfos = (char**)malloc(sizeof(char*));
374
protoIPTrafficInfos = (char**)realloc(protoIPTrafficInfos, sizeof(char*)*(numIpProtosToMonitor+1));
376
protoIPTrafficInfos[numIpProtosToMonitor] = strdup(protoName);
377
numIpProtosToMonitor++;
379
traceEvent(TRACE_INFO, "%d) %s - %s\n",
380
numIpProtosToMonitor, protoName, protocolList);
385
/* **************************************** */
387
void createPortHash() {
391
At this point in time servicesMapper contains all
392
the port data hence we can transform it from
393
an array to a hash table.
395
numIpPortMapperSlots = 2*numIpPortsToHandle;
396
theSize = sizeof(PortMapper)*2*numIpPortMapperSlots;
397
ipPortMapper = (PortMapper*)malloc(theSize);
398
for(i=0; i<numIpPortMapperSlots; i++) ipPortMapper[i].port = -1;
401
traceEvent(TRACE_INFO, "Allocating %d slots", numIpPortMapperSlots);
404
for(i=0; i<TOP_IP_PORT; i++) {
405
if(servicesMapper[i] != -1) {
406
int slotId = (3*i) % numIpPortMapperSlots;
408
while(ipPortMapper[slotId].port != -1)
409
slotId = (slotId+1) % numIpPortMapperSlots;
412
traceEvent(TRACE_INFO, "Mapping port %d to slotId %d", i, slotId);
414
ipPortMapper[slotId].port = i, ipPortMapper[slotId].mappedPort = servicesMapper[i];
418
free(servicesMapper);
421
/* **************************************** */
423
void handleProtocols(char *protos) {
424
char *proto, *buffer=NULL, *strtokState;
425
FILE *fd = fopen(protos, "rb");
428
proto = strtok_r(protos, ",", &strtokState);
433
if(stat(protos, &buf) != 0) {
434
traceEvent(TRACE_ERROR, "Error while stat() of %s\n", protos);
438
buffer = (char*)malloc(buf.st_size+8) /* just to be safe */;
440
for(i=0;i<buf.st_size;) {
441
len = fread(&buffer[i], sizeof(char), buf.st_size-i, fd);
448
/* remove trailing carriage return */
449
if(buffer[strlen(buffer)-1] == '\n')
450
buffer[strlen(buffer)-1] = 0;
452
proto = strtok_r(buffer, ",", &strtokState);
455
while(proto != NULL) {
456
char* protoName = strchr(proto, '=');
458
if(protoName == NULL)
459
traceEvent(TRACE_INFO,
460
"Unknown protocol '%s'. It has been ignored.\n",
467
memset(tmpStr, 0, sizeof(tmpStr));
468
strncpy(tmpStr, &protoName[1], sizeof(tmpStr));
469
len = strlen(tmpStr);
471
if(tmpStr[len-1] != '|') {
472
/* Make sure that the string ends with '|' */
474
tmpStr[len+1] = '\0';
477
handleProtocolList(proto, tmpStr);
480
proto = strtok_r(NULL, ",", &strtokState);
489
/* **************************************** */
491
void addDefaultProtocols(void) {
492
handleProtocolList("FTP", "ftp|ftp-data|");
493
handleProtocolList("HTTP", "http|www|https|");
494
handleProtocolList("DNS", "name|domain|");
495
handleProtocolList("Telnet", "telnet|login|");
496
handleProtocolList("NBios-IP", "netbios-ns|netbios-dgm|netbios-ssn|");
497
handleProtocolList("Mail", "pop-2|pop-3|pop3|kpop|smtp|imap|imap2|");
498
handleProtocolList("DHCP/BOOTP", "67-68|");
499
handleProtocolList("SNMP", "snmp|snmp-trap|");
500
handleProtocolList("NEWS", "nntp|");
501
handleProtocolList("NFS", "mount|pcnfs|bwnfs|nfsd|nfsd-status|");
502
handleProtocolList("X11", "6000-6010|");
503
/* 22 == ssh (just to make sure the port is defined) */
504
handleProtocolList("SSH", "22|");
509
/* **************************************** */
511
int mapGlobalToLocalIdx(int port) {
512
if((port < 0) || (port >= TOP_IP_PORT))
515
int j, found, slotId = (3*port) % numIpPortMapperSlots;
517
for(j=0, found=0; j<numIpPortMapperSlots; j++) {
518
if(ipPortMapper[slotId].port == -1)
520
else if(ipPortMapper[slotId].port == port) {
525
slotId = (slotId+1) % numIpPortMapperSlots;
529
return(ipPortMapper[slotId].mappedPort);
535
/* **************************************** */
538
void* updateThptLoop(void* notUsed _UNUSED_) {
541
traceEvent(TRACE_INFO, "Sleeping for %d seconds\n",
542
THROUGHPUT_REFRESH_TIME);
545
sleep(THROUGHPUT_REFRESH_TIME);
547
if(!capturePackets) break;
550
traceEvent(TRACE_INFO, "Trying to update throughput\n");
553
/* Don't update Thpt if the traffic is high */
554
/* if(packetQueueLen < (PACKET_QUEUE_LENGTH/3)) */ {
555
actTime = time(NULL);
556
accessMutex(&hostsHashMutex, "updateThptLoop");
558
traceEvent(TRACE_INFO, "Updating throughput\n");
560
updateThpt(); /* Update Throughput */
561
releaseMutex(&hostsHashMutex);
569
/* **************************************** */
572
void* updateHostTrafficStatsThptLoop(void* notUsed _UNUSED_) {
573
time_t nextUpdate = actTime+3600;
574
int hourId, minuteId, lastUpdatedHour=-1;
580
traceEvent(TRACE_INFO, "Sleeping for 60 seconds\n");
583
if(!capturePackets) break; /* Before */
587
if(!capturePackets) break; /* After */
590
traceEvent(TRACE_INFO, "Trying to update host traffic stats");
593
actTime = time(NULL);
594
strftime(theDate, 8, "%M", localtime_r(&actTime, &t));
595
minuteId = atoi(theDate);
596
strftime(theDate, 8, "%H", localtime_r(&actTime, &t));
597
hourId = atoi(theDate);
598
if((minuteId <= 1) && (hourId != lastUpdatedHour)) {
599
lastUpdatedHour = hourId;
600
accessMutex(&hostsHashMutex, "updateHostTrafficStatsThptLoop");
602
traceEvent(TRACE_INFO, "Updating host traffic stats\n");
604
updateHostTrafficStatsThpt(hourId); /* Update Throughput */
605
releaseMutex(&hostsHashMutex);
606
nextUpdate = actTime+3600;
614
/* **************************************** */
617
void* updateDBHostsTrafficLoop(void* notUsed _UNUSED_) {
618
u_short updateTime = DEFAULT_DB_UPDATE_TIME; /* This should be user configurable */
624
traceEvent(TRACE_INFO, "Sleeping for %d seconds\n", updateTime);
629
if(!capturePackets) break;
631
for(i=0; i<numDevices; i++)
632
if(!device[i].virtualDevice) {
634
accessMutex(&hostsHashMutex, "updateDbHostsTraffic");
635
#endif /* MULTITHREADED */
636
updateDbHostsTraffic(i);
638
releaseMutex(&hostsHashMutex);
639
#endif /* MULTITHREADED */
647
/* **************************************** */
649
void* scanIdleLoop(void* notUsed _UNUSED_) {
653
sleep(SESSION_SCAN_DELAY);
655
if(!capturePackets) break;
656
actTime = time(NULL);
658
for(i=0; i<numDevices; i++)
659
if(!device[i].virtualDevice) {
660
purgeIdleHosts(0 /* Delete only idle hosts */, i);
662
sched_yield(); /* Allow other threads to run */
664
sleep(1); /* leave some time to others */
670
cleanupHostEntries();
676
/* **************************************** */
678
void* cleanupExpiredHostEntriesLoop(void* notUsed _UNUSED_) {
680
sleep(PURGE_ADDRESS_TIMEOUT);
681
if(!capturePackets) break;
682
actTime = time(NULL);
683
cleanupHostEntries();
689
/* **************************************** */
691
void* scanIdleSessionsLoop(void* notUsed _UNUSED_) {
694
sleep(SESSION_SCAN_DELAY);
696
if(!capturePackets) break;
697
actTime = time(NULL);
700
accessMutex(&hostsHashMutex, "scanIdleSessionsLoop-1");
702
scanTimedoutTCPSessions();
704
releaseMutex(&hostsHashMutex);
708
sched_yield(); /* Allow other threads to run */
710
sleep(1); /* leave some time to others */
714
accessMutex(&hostsHashMutex, "scanIdleSessionsLoop-2");
716
purgeOldFragmentEntries();
718
releaseMutex(&hostsHashMutex);
722
scanAllTcpExpiredRules();
728
/* **************************************** */
731
void* periodicLsofLoop(void* notUsed _UNUSED_) {
734
refresh process list each minute
738
if(!capturePackets) break;
742
traceEvent(TRACE_INFO, "Wait please: reading lsof information...\n");
744
if(isLsofPresent) readLsofInfo();
746
traceEvent(TRACE_INFO, "Done with lsof.\n");
756
/* **************************************** */
758
#ifndef MULTITHREADED
759
void packetCaptureLoop(time_t *lastTime, int refreshRate) {
760
int numPkts=0, pcap_fd = pcap_fileno(device[0].pcapPtr);
762
struct timeval timeout;
764
if((pcap_fd == -1) && (rFileName != NULL)) {
766
This is a patch to overcome a bug of libpcap
767
while reading from a traffic file instead
768
of sniffying live from a NIC.
771
int fd, snapshot, linktype, tzoff, offset;
774
/* Other fields have been skipped. Please refer
775
to pcap-int.h for the full datatype.
779
pcap_fd = fileno(((struct mypcap *)(device[0].pcapPtr))->rfile);
786
if(!capturePackets) break;
789
if(pcap_fd != -1) FD_SET(pcap_fd, &readMask);
791
timeout.tv_sec = 5 /* seconds */;
794
if(select(pcap_fd+1, &readMask, NULL, NULL, &timeout) > 0) {
795
rc = pcap_dispatch(device[0].pcapPtr, 1, processPacket, NULL);
798
traceEvent(TRACE_ERROR, "Error while reading packets: %s.\n",
799
pcap_geterr(device[0].pcapPtr));
801
} else if((rc == 0) && (rFileName != NULL)) {
802
traceEvent(TRACE_INFO, "pcap_dispatch returned %d "
803
"[No more packets to read]", rc);
808
actTime = time(NULL);
810
if(actTime > (*lastTime)) {
811
if(nextSessionTimeoutScan < actTime) {
812
/* It's time to check for timeout sessions */
813
scanTimedoutTCPSessions();
814
nextSessionTimeoutScan = actTime+SESSION_SCAN_DELAY;
818
scanAllTcpExpiredRules();
819
updateThpt(); /* Update Throughput */
820
(*lastTime) = actTime + THROUGHPUT_REFRESH_TIME;
825
handleWebConnections(NULL);
830
/* **************************************** */
832
/* Report statistics and write out the raw packet file */
833
RETSIGTYPE cleanup(int signo) {
834
static int unloaded = 0;
835
struct pcap_stat stat;
843
traceEvent(TRACE_INFO, "Cleaning up...");
849
killThread(&dequeueThreadId);
850
killThread(&thptUpdateThreadId);
851
killThread(&hostTrafficStatsThreadId);
853
if(rFileName == NULL) {
854
killThread(&scanIdleThreadId);
855
killThread(&scanIdleSessionsThreadId);
859
killThread(&dbUpdateThreadId);
862
killThread(&lsofThreadId);
864
#ifdef ASYNC_ADDRESS_RESOLUTION
865
if(numericFlag == 0) {
866
killThread(&dequeueAddressThreadId);
867
killThread(&purgeAddressThreadId);
871
killThread(&handleWebConnectionsThreadId);
873
#ifdef FULL_MEMORY_FREE
874
cleanupAddressQueue();
875
cleanupPacketQueue();
879
#else /* #ifndef WIN32 */
883
Wies-Software <wies@wiessoft.de>
885
#else clause added to force dequeue threads to terminate
886
USE_SEMAPHORES is *NOT* tested!!!
889
#ifdef USE_SEMAPHORES
890
incrementSem(&queueSem);
891
#ifdef ASYNC_ADDRESS_RESOLUTION
892
incrementSem(&queueAddressSem);
895
signalCondvar(&queueCondvar);
896
#ifdef ASYNC_ADDRESS_RESOLUTION
897
signalCondvar(&queueAddressCondvar);
900
#endif /* MULTITREADED */
901
#endif /* #ifndef WIN32 */
904
traceEvent(TRACE_INFO, "Waiting until threads terminate...\n");
905
sleep(3); /* Just to wait until threads complete */
908
/* #ifdef FULL_MEMORY_FREE */
916
(void)fflush(stdout);
920
termNetFlowExporter();
921
termPassiveSessions();
928
deleteMutex(&packetQueueMutex);
929
deleteMutex(&addressResolutionMutex);
930
deleteMutex(&hashResizeMutex);
931
deleteMutex(&hostsHashMutex);
932
deleteMutex(&graphMutex);
934
deleteMutex(&lsofMutex);
935
#ifdef USE_SEMAPHORES
936
deleteSem(&queueSem);
937
#ifdef ASYNC_ADDRESS_RESOLUTION
938
deleteSem(&queueAddressSem);
941
deleteCondvar(&queueCondvar);
942
#ifdef ASYNC_ADDRESS_RESOLUTION
943
deleteCondvar(&queueAddressCondvar);
950
accessMutex(&gdbmMutex, "cleanup");
952
gdbm_close(gdbm_file); gdbm_file = NULL;
953
gdbm_close(pwFile); pwFile = NULL;
954
/* Courtesy of Wies-Software <wies@wiessoft.de> */
955
gdbm_close(hostsInfoFile); hostsInfoFile = NULL;
956
if(eventFile != NULL) {
957
gdbm_close(eventFile);
961
releaseMutex(&gdbmMutex);
965
deleteMutex(&gdbmMutex);
969
for(i=0; i<numDevices; i++) {
972
traceEvent(TRACE_INFO, "Freeing device %s (idx=%d)...", device[i].name, i);
974
if(!device[i].virtualDevice) {
975
if (pcap_stats(device[i].pcapPtr, &stat) >= 0) {
976
traceEvent(TRACE_INFO, "%s packets received by filter on %s\n",
977
formatPkts((TrafficCounter)stat.ps_recv), device[i].name);
978
traceEvent(TRACE_INFO, "%s packets dropped by kernel\n",
979
formatPkts((TrafficCounter)(stat.ps_drop)));
981
traceEvent(TRACE_INFO, "%s packets dropped by ntop\n",
982
formatPkts(device[i].droppedPkts));
987
if(device[i].ipTrafficMatrix != NULL) {
989
/* Courtesy of Wies-Software <wies@wiessoft.de> */
990
for(j=0; j<(device[i].numHosts*device[i].numHosts); j++)
991
if(device[i].ipTrafficMatrix[j] != NULL)
992
free(device[i].ipTrafficMatrix[j]);
994
free(device[i].ipTrafficMatrix);
997
if(device[i].ipTrafficMatrix != NULL)
998
free(device[i].ipTrafficMatrix);
1000
if(device[i].ipTrafficMatrixHosts != NULL)
1001
free(device[i].ipTrafficMatrixHosts);
1003
if(device[i].ipProtoStats != NULL)
1004
free(device[i].ipProtoStats);
1006
if(device[i].hash_hostTraffic != NULL)
1007
free(device[i].hash_hostTraffic);
1009
if(device[i].tcpSession != NULL)
1010
free(device[i].tcpSession);
1012
free(device[i].name);
1014
if(device[i].pcapDumper != NULL)
1015
pcap_dump_close(device[i].pcapDumper);
1017
if(device[i].pcapErrDumper != NULL)
1018
pcap_dump_close(device[i].pcapErrDumper);
1021
Wies-Software <wies@wiessoft.de> on 06/11/2001 says:
1022
device[i].pcapPtr seems to be already freed. further tests needed!
1024
if(device[i].pcapPtr != NULL)
1025
free(device[i].pcapPtr);
1030
if(numProcesses > 0)
1033
if(enableDBsupport) {
1034
closeSQLsocket(); /* *** SQL Engine *** */
1047
traceEvent(TRACE_INFO, "===================================\n");
1049
traceEvent(TRACE_INFO, "===================================\n");