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
#include "globals-report.h"
28
#ifdef HAVE_UCD_SNMP_UCD_SNMP_AGENT_INCLUDES_H
29
#include <ucd-snmp/version.h>
33
static short alternateColor=0;
37
void handleSingleWebConnection(fd_set *fdmask);
41
/* ************************************* */
45
void execCGI(char* cgiName) {
46
char* userName = "nobody", line[384], buf[256];
47
struct passwd * newUser = NULL;
51
if(!(newUser = getpwnam(userName))) {
52
traceEvent(TRACE_WARNING, "WARNING: unable to find user %s\n", userName);
55
setgid(newUser->pw_gid);
56
setuid(newUser->pw_uid);
59
for(num=0, i=0; cgiName[i] != '\0'; i++)
60
if(cgiName[i] == '?') {
62
if(snprintf(buf, sizeof(buf), "QUERY_STRING=%s", &cgiName[i+1]) < 0)
63
traceEvent(TRACE_ERROR, "Buffer overflow!");
69
if(num == 0) putenv("QUERY_STRING=");
71
if(snprintf(line, sizeof(line), "%s/cgi/%s", getenv("PWD"), cgiName) < 0)
72
traceEvent(TRACE_ERROR, "Buffer overflow!");
74
if((fd = sec_popen(line, "r")) == NULL) {
75
traceEvent(TRACE_WARNING, "WARNING: unable to exec %s\n", cgiName);
79
num = fread(line, 1, 383, fd);
81
sendStringLen(line, num);
89
/* **************************************** */
91
#if (defined(HAVE_DIRENT_H) && defined(HAVE_DLFCN_H)) || defined(WIN32) || defined(HPUX) || defined(AIX) || defined(DARWIN)
92
void showPluginsList(char* pluginName) {
93
FlowFilterList *flows = flowsList;
94
short printHeader = 0;
95
char tmpBuf[BUF_SIZE], *thePlugin;
96
int newPluginStatus = 0;
98
if(pluginName[0] != '\0') {
101
thePlugin = pluginName;
103
for(i=0; pluginName[i] != '\0'; i++)
104
if(pluginName[i] == '=') {
105
pluginName[i] = '\0';
106
newPluginStatus = atoi(&pluginName[i+1]);
112
while(flows != NULL) {
113
if((flows->pluginStatus.pluginPtr != NULL)
114
&& (flows->pluginStatus.pluginPtr->pluginURLname != NULL)) {
117
&& (strcmp(flows->pluginStatus.pluginPtr->pluginURLname, thePlugin) == 0))
118
flows->pluginStatus.activePlugin = newPluginStatus;
121
/* printHTTPheader(); */
122
printHTMLheader("Available Plugins", 0);
123
sendString("<CENTER>\n"
124
""TABLE_ON"<TABLE BORDER=1><TR>\n"
125
"<TR><TH "TH_BG">Name</TH><TH>Description</TH>"
126
"<TH "TH_BG">Version</TH>"
127
"<TH "TH_BG">Author</TH>"
128
"<TH "TH_BG">Active</TH>"
133
if(snprintf(tmpBuf, sizeof(tmpBuf), "<TR %s><TH "TH_BG" ALIGN=LEFT><A HREF=/plugins/%s>%s</TH>"
134
"<TD "TD_BG" ALIGN=LEFT>%s</TD>"
135
"<TD "TD_BG" ALIGN=CENTER>%s</TD>"
136
"<TD "TD_BG" ALIGN=LEFT>%s</TD>"
137
"<TD "TD_BG" ALIGN=CENTER><A HREF="STR_SHOW_PLUGINS"?%s=%d>%s</A></TD>"
140
flows->pluginStatus.pluginPtr->pluginURLname,
141
flows->pluginStatus.pluginPtr->pluginURLname,
142
flows->pluginStatus.pluginPtr->pluginDescr,
143
flows->pluginStatus.pluginPtr->pluginVersion,
144
flows->pluginStatus.pluginPtr->pluginAuthor,
145
flows->pluginStatus.pluginPtr->pluginURLname,
146
flows->pluginStatus.activePlugin ? 0: 1,
147
flows->pluginStatus.activePlugin ?
148
"Yes" : "<FONT COLOR=#FF0000>No</FONT>") < 0)
149
traceEvent(TRACE_ERROR, "Buffer overflow!");
157
printHTMLheader("No Plugins available", 0);
159
sendString("</TABLE>"TABLE_OFF"<p>\n");
160
sendString("</CENTER>\n");
164
#else /* defined(HAVE_DIRENT_H) && defined(HAVE_DLFCN_H) */
166
void showPluginsList(char* pluginName) {
170
void loadPlugins(void) {
174
void unloadPlugins(void) {
178
#endif /* defined(HAVE_DIRENT_H) && defined(HAVE_DLFCN_H) */
180
/* ******************************* */
182
char* makeHostLink(HostTraffic *el, short mode,
183
short cutName, short addCountryFlag) {
184
static char buf[5][BUF_SIZE];
185
char symIp[256], *tmpStr, linkName[256], flag[128];
186
char *blinkOn, *blinkOff, *dynIp;
187
char *multihomed, *gwStr, *dnsStr, *printStr, *smtpStr, *healthStr = "";
188
short specialMacAddress = 0;
189
static short bufIdx=0;
190
short usedEthAddress=0;
196
|| ((el->hostIpAddress.s_addr == 0) && (el->ethAddressString[0] == '\0'))) {
197
if(mode == LONG_FORMAT)
198
return("<TH "TH_BG" ALIGN=LEFT><broadcast></TH>");
200
return("<broadcast>");
203
blinkOn = "", blinkOff = "";
205
bufIdx = (bufIdx+1)%5;
208
accessMutex(&addressResolutionMutex, "makeHostLink");
211
tmpStr = el->hostSymIpAddress;
213
if((tmpStr == NULL) || (tmpStr[0] == '\0')) {
214
/* The DNS is still getting the entry name */
215
if(el->hostNumIpAddress[0] != '\0')
216
strncpy(symIp, el->hostNumIpAddress, sizeof(symIp));
218
strncpy(symIp, el->ethAddressString, sizeof(symIp));
221
} else if(tmpStr[0] != '\0') {
222
strncpy(symIp, tmpStr, sizeof(symIp));
223
if(tmpStr[strlen(tmpStr)-1] == ']') /* "... [MAC]" */ {
225
specialMacAddress = 1;
227
if(cutName && (symIp[0] != '*')
228
&& strcmp(symIp, el->hostNumIpAddress)) {
231
for(i=0; symIp[i] != '\0'; i++)
232
if(symIp[i] == '.') {
239
strncpy(symIp, el->ethAddressString, sizeof(symIp));
244
releaseMutex(&addressResolutionMutex);
247
if(specialMacAddress) {
248
tmpStr = el->ethAddressString;
250
traceEvent(TRACE_INFO, "->'%s/%s'\n", symIp, el->ethAddressString);
254
if (usedEthAddress) {
255
if(el->nbHostName != NULL) {
256
strncpy(symIp, el->nbHostName, sizeof(linkName));
257
} else if(el->ipxHostName != NULL) {
258
strncpy(symIp, el->ipxHostName, sizeof(linkName));
262
if(el->hostNumIpAddress[0] != '\0') {
263
tmpStr = el->hostNumIpAddress;
265
tmpStr = el->ethAddressString;
266
/* tmpStr = symIp; */
270
strncpy(linkName, tmpStr, sizeof(linkName));
273
/* Patch for ethernet addresses and MS Explorer */
275
char tmpStr[256], *vendorInfo;
277
if(el->nbHostName != NULL) {
278
strncpy(symIp, el->nbHostName, sizeof(linkName));
279
} else if(el->ipxHostName != NULL) {
280
strncpy(symIp, el->ipxHostName, sizeof(linkName));
282
vendorInfo = getVendorInfo(el->ethAddress, 0);
283
if(vendorInfo[0] != '\0') {
284
sprintf(tmpStr, "%s%s", vendorInfo, &linkName[8]);
285
strcpy(symIp, tmpStr);
288
for(i=0; linkName[i] != '\0'; i++)
289
if(linkName[i] == ':')
294
if(addCountryFlag == 0)
297
if(snprintf(flag, sizeof(flag), "<TD "TD_BG" ALIGN=CENTER>%s</TD>",
298
getHostCountryIconURL(el)) < 0)
299
traceEvent(TRACE_ERROR, "Buffer overflow!");
303
dynIp = " <IMG ALT=\"DHCP Client\" SRC=/bulb.gif BORDER=0> ";
306
dynIp = " <IMG ALT=\"DHCP Server\" SRC=/wheel.gif BORDER=0> ";
311
if(isMultihomed(el)) multihomed = " <IMG ALT=\"Multihomed host\" SRC=/multihomed.gif BORDER=0> "; else multihomed = "";
312
if(gatewayHost(el)) gwStr = " <IMG ALT=Router SRC=/router.gif BORDER=0> "; else gwStr = "";
313
if(nameServerHost(el)) dnsStr = " <IMG ALT=\"DNS Server\" SRC=/dns.gif BORDER=0> "; else dnsStr = "";
314
if(isPrinter(el)) printStr = " <IMG ALT=Printer SRC=/printer.gif BORDER=0> "; else printStr = "";
315
if(isSMTPhost(el)) smtpStr = " <IMG ALT=\"Mail Server (SMTP)\" SRC=/mail.gif BORDER=0> "; else smtpStr = "";
317
switch(isHostHealthy(el)) {
321
case 1: /* Warning */
322
healthStr = "<IMG ALT=\"Medium Risk\" SRC=/Risk_medium.gif BORDER=0>";
325
healthStr = "<IMG ALT=\"High Risk\" SRC=/Risk_high.gif BORDER=0>";
329
if(mode == LONG_FORMAT) {
330
if(snprintf(buf[bufIdx], BUF_SIZE, "<TH "TH_BG" ALIGN=LEFT NOWRAP>%s"
331
"<A HREF=\"/%s.html\">%s</A>%s%s%s%s%s%s%s%s</TH>%s",
332
blinkOn, linkName, symIp, dynIp,
333
multihomed, gwStr, dnsStr, printStr, smtpStr, healthStr,
335
traceEvent(TRACE_ERROR, "Buffer overflow!");
337
if(snprintf(buf[bufIdx], BUF_SIZE, "%s<A HREF=\"/%s.html\" NOWRAP>%s</A>%s%s%s%s%s%s%s%s%s",
338
blinkOn, linkName, symIp,
339
multihomed, gwStr, dnsStr, printStr, smtpStr, healthStr,
340
dynIp, blinkOff, flag) < 0)
341
traceEvent(TRACE_ERROR, "Buffer overflow!");
347
/* ******************************* */
349
char* getHostName(HostTraffic *el, short cutName) {
350
static char buf[5][80];
352
static short bufIdx=0;
354
if(broadcastHost(el))
357
bufIdx = (bufIdx+1)%5;
360
accessMutex(&addressResolutionMutex, "getHostName");
363
tmpStr = el->hostSymIpAddress;
366
/* The DNS is still getting the entry name */
367
if(el->hostNumIpAddress[0] == '\0')
368
strncpy(buf[bufIdx], el->hostNumIpAddress, 80);
370
strncpy(buf[bufIdx], el->ethAddressString, 80);
371
} else if(tmpStr[0] != '\0') {
372
strncpy(buf[bufIdx], tmpStr, 80);
376
for(i=0; buf[bufIdx][i] != '\0'; i++)
377
if((buf[bufIdx][i] == '.')
378
&& (!(isdigit(buf[bufIdx][i-1])
379
&& isdigit(buf[bufIdx][i+1]))
381
buf[bufIdx][i] = '\0';
386
strncpy(buf[bufIdx], el->ethAddressString, 80);
389
releaseMutex(&addressResolutionMutex);
395
/* ********************************** */
397
char* calculateCellColor(TrafficCounter actualValue,
398
TrafficCounter avgTrafficLow,
399
TrafficCounter avgTrafficHigh) {
401
if(actualValue < avgTrafficLow)
402
return("BGCOLOR=#AAAAAAFF"); /* light blue */
403
else if(actualValue < avgTrafficHigh)
404
return("BGCOLOR=#00FF75"); /* light green */
406
return("BGCOLOR=#FF7777"); /* light red */
410
/* ************************ */
412
char* getCountryIconURL(char* domainName) {
413
if((domainName == NULL) || (domainName[0] == '\0')) {
414
/* Courtesy of Roberto De Luca <deluca@tandar.cnea.gov.ar> */
417
static char flagBuf[384];
421
if(snprintf(path, sizeof(path), "./html/statsicons/flags/%s.gif",
423
traceEvent(TRACE_ERROR, "Buffer overflow!");
425
if(stat(path, &buf) != 0) {
426
if(snprintf(path, sizeof(path), "%s/html/statsicons/flags/%s.gif",
427
DATAFILE_DIR, domainName) < 0)
428
traceEvent(TRACE_ERROR, "Buffer overflow!");
430
if(stat(path, &buf) != 0)
434
if(snprintf(flagBuf, sizeof(flagBuf),
435
"<IMG ALT=\"Flag for domain %s\" ALIGN=MIDDLE SRC=/statsicons/flags/%s.gif BORDER=0>",
436
domainName, domainName) < 0) traceEvent(TRACE_ERROR, "Buffer overflow!");
442
/* ************************ */
444
char* getHostCountryIconURL(HostTraffic *el) {
445
char path[128], *ret;
450
if(snprintf(path, sizeof(path), "%s/html/statsicons/flags/%s.gif",
451
DATAFILE_DIR, el->fullDomainName) < 0)
452
traceEvent(TRACE_ERROR, "Buffer overflow!");
454
if(stat(path, &buf) == 0)
455
ret = getCountryIconURL(el->fullDomainName);
457
ret = getCountryIconURL(el->dotDomainName);
465
/* ******************************* */
467
char* getRowColor(void) {
468
/* #define USE_COLOR */
471
if(alternateColor == 0) {
473
return("BGCOLOR=#C3C9D9"); /* EFEFEF */
483
/* ******************************* */
485
char* getActualRowColor(void) {
486
/* #define USE_COLOR */
489
if(alternateColor == 1) {
490
return("BGCOLOR=#EFEFEF");
499
/* ******************************* */
501
void switchNwInterface(int _interface) {
502
int i, mwInterface=_interface-1;
503
char buf[BUF_SIZE], *selected;
505
printHTMLheader("Network Interface Switch", HTML_FLAG_NO_REFRESH);
506
sendString("<HR>\n<P>\n<FONT FACE=\"Helvetica, Arial, Sans Serif\"><B>\n");
508
if(mergeInterfaces) {
509
if(snprintf(buf, sizeof(buf), "You can't switch among different inferfaces if the -M "
510
"command line switch is not used. Sorry.\n") < 0)
511
traceEvent(TRACE_ERROR, "Buffer overflow!");
513
} else if((mwInterface != -1) &&
514
((mwInterface >= numDevices) || device[mwInterface].virtualDevice)) {
515
if(snprintf(buf, sizeof(buf), "Invalid interface selected. Sorry.\n") < 0)
516
traceEvent(TRACE_ERROR, "Buffer overflow!");
518
} else if(numDevices == 1) {
519
if(snprintf(buf, sizeof(buf), "You're currently capturing traffic from one "
520
"interface [%s]. The interface switch feature is active only when "
521
"you active ntop with multiple interfaces (-i command line switch). "
522
"Sorry.\n", device[actualReportDeviceId].name) < 0)
523
traceEvent(TRACE_ERROR, "Buffer overflow!");
525
} else if(mwInterface >= 0) {
526
actualReportDeviceId = (mwInterface)%numDevices;
527
if(snprintf(buf, sizeof(buf), "The current interface is now [%s].\n",
528
device[actualReportDeviceId].name) < 0)
529
traceEvent(TRACE_ERROR, "Buffer overflow!");
532
sendString("Available Network Interfaces:</B><P>\n<FORM ACTION="SWITCH_NIC_HTML">\n");
534
for(i=0; i<numDevices; i++)
535
if(!device[i].virtualDevice) {
536
if(actualReportDeviceId == i)
541
if(snprintf(buf, sizeof(buf), "<INPUT TYPE=radio NAME=interface VALUE=%d %s> %s<br>\n",
542
i+1, selected, device[i].name) < 0) traceEvent(TRACE_ERROR, "Buffer overflow!");
547
sendString("<p><INPUT TYPE=submit> <INPUT TYPE=reset>\n</FORM>\n");
552
sendString("</font><p>\n");
555
/* **************************************** */
557
void shutdownNtop(void) {
558
printHTMLheader("ntop is shutting down...", HTML_FLAG_NO_REFRESH);
559
closeNwSocket(&newSock);
564
/* ******************************** */
566
static void printFeatureConfigInfo(char* feature, char* status) {
567
sendString("<TR><TH "TH_BG" ALIGN=left>");
569
sendString("</TH><TD "TD_BG" ALIGN=right>");
571
sendString("</TD></TR>\n");
574
/* ******************************** */
577
static void printMutexStatus(PthreadMutex *mutexId, char *mutexName) {
580
if(mutexId->lockLine == 0) /* Mutex never used */
583
if(snprintf(buf, sizeof(buf),
584
"<TR><TH "TH_BG" ALIGN=left>%s</TH><TD ALIGN=CENTER>%s</TD>"
585
"<TD ALIGN=RIGHT>%s:%d</TD>"
586
"<TD ALIGN=RIGHT>%s:%d</TD>"
587
"<TD ALIGN=RIGHT>%u</TD><TD ALIGN=LEFT>%u</TD>"
588
"<TD ALIGN=RIGHT>%d sec [%s:%d]</TD></TR>",
590
mutexId->isLocked ? "<FONT COLOR=red>locked</FONT>" : "unlocked",
591
mutexId->lockFile, mutexId->lockLine,
592
mutexId->unlockFile, mutexId->unlockLine,
593
mutexId->numLocks, mutexId->numReleases,
594
mutexId->maxLockedDuration,
595
mutexId->maxLockedDurationUnlockFile,
596
mutexId->maxLockedDurationUnlockLine) < 0)
597
traceEvent(TRACE_ERROR, "Buffer overflow!");
603
void printNtopConfigInfo(void) {
606
#ifdef HAVE_PCAP_VERSION
607
extern char pcap_version[];
608
#endif /* HAVE_PCAP_VERSION */
610
printHTMLheader("Current ntop Configuration", 0);
611
sendString("<CENTER>\n");
612
sendString("<P><HR><P>"TABLE_ON"<TABLE BORDER=1>\n");
614
printFeatureConfigInfo("OS", osName);
615
printFeatureConfigInfo("ntop version", version);
616
printFeatureConfigInfo("Built on", buildDate);
618
/* *************************** */
620
sendString("<TR><TH "TH_BG" ALIGN=left>Started as</TH><TD "TD_BG" ALIGN=right>");
621
for(i=0; i<ntop_argc; i++) {
622
sendString(ntop_argv[i]);
625
sendString("</TD></TR>\n");
627
/* *************************** */
629
#ifdef HAVE_PCAP_VERSION
630
printFeatureConfigInfo("Libpcap version", pcap_version);
631
#endif /* HAVE_PCAP_VERSION */
632
#if defined(WIN32) && defined(__GNUC__)
633
/* on mingw, gdbm_version not exported by library */
635
printFeatureConfigInfo("GDBM version", gdbm_version);
639
printFeatureConfigInfo("<A HREF=http://www.openssl.org/>OpenSSL Support</A>",
640
(char*)SSLeay_version(0));
642
sprintf(buf, "%d", sslPort);
643
printFeatureConfigInfo("SSL Port", buf);
645
printFeatureConfigInfo("SSL Port", "Not Active");
647
printFeatureConfigInfo("<A HREF=http://www.openssl.org/>OpenSSL Support</A>", "Absent");
651
printFeatureConfigInfo("Multithreaded", "Yes");
653
printFeatureConfigInfo("Multithreaded", "No");
657
printFeatureConfigInfo("<A HREF=http://www.fred.net/brv/chart/>GD Chart</A>", "Present");
658
printFeatureConfigInfo("Chart Format", CHART_FORMAT);
660
printFeatureConfigInfo("<A HREF=http://www.fred.net/brv/chart/>GD Chart</A>", "Absent");
663
#ifdef HAVE_UCD_SNMP_UCD_SNMP_AGENT_INCLUDES_H
664
printFeatureConfigInfo("<A HREF=http://net-snmp.sourceforge.net/>UCD/NET SNMP</A>",
667
printFeatureConfigInfo("<A HREF=http://net-snmp.sourceforge.net/>UCD/NET SNMP </A>",
672
printFeatureConfigInfo("TCP Wrappers", "Present");
674
printFeatureConfigInfo("TCP Wrappers", "Absent");
677
#ifdef ASYNC_ADDRESS_RESOLUTION
678
printFeatureConfigInfo("Async. Addr. Resolution", "Yes");
680
printFeatureConfigInfo("Async. Addr. Resolution", "No");
684
printFeatureConfigInfo("<A HREF=ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/>lsof</A> Support", "Yes");
686
printFeatureConfigInfo("<A HREF=ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/>lsof</A> Support",
687
"No (Either disabled [Use -E option] or missing)");
690
printFeatureConfigInfo("<A HREF=http://www.insecure.org/nmap/>nmap</A> Support", "Yes");
692
printFeatureConfigInfo("<A HREF=http://www.insecure.org/nmap/>nmap</A> Support",
693
"No (Either disabled [Use -E option] or missing)");
695
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Handled HTTP Requests</TH>"
696
"<TD "TD_BG" align=right>%lu</TD></TR>\n", numHandledHTTPrequests) < 0)
697
traceEvent(TRACE_ERROR, "Buffer overflow!");
700
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left>Actual Hash Size</TH>"
701
"<TD "TD_BG" align=right>%d</TD></TR>\n",
702
(int)device[actualReportDeviceId].actualHashSize) < 0)
703
traceEvent(TRACE_ERROR, "Buffer overflow!");
706
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left>Top Hash Size</TH>"
707
"<TD "TD_BG" align=right>%d</TD></TR>\n", topHashSize) < 0)
708
traceEvent(TRACE_ERROR, "Buffer overflow!");
712
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Queued Pkts to Process</TH>"
713
"<TD "TD_BG" align=right>%d</TD></TR>\n",
715
traceEvent(TRACE_ERROR, "Buffer overflow!");
718
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Max Queued Pkts</TH>"
719
"<TD "TD_BG" align=right>%u</TD></TR>\n",
720
maxPacketQueueLen) < 0)
721
traceEvent(TRACE_ERROR, "Buffer overflow!");
725
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Stored Hash Hosts</TH>"
726
"<TD "TD_BG" align=right>%d [%d %%]</TD></TR>\n",
727
(int)device[actualReportDeviceId].hostsno,
728
(((int)device[actualReportDeviceId].hostsno*100)/
729
(int)device[actualReportDeviceId].actualHashSize)) < 0)
730
traceEvent(TRACE_ERROR, "Buffer overflow!");
733
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Purged Hash Hosts</TH>"
734
"<TD "TD_BG" align=right>%u</TD></TR>\n",
735
(unsigned int)numPurgedHosts) < 0)
736
traceEvent(TRACE_ERROR, "Buffer overflow!");
739
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># TCP Sessions</TH>"
740
"<TD "TD_BG" align=right>%u</TD></TR>\n",
741
device[actualReportDeviceId].numTcpSessions) < 0)
742
traceEvent(TRACE_ERROR, "Buffer overflow!");
745
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Terminated TCP Sessions</TH>"
746
"<TD "TD_BG" align=right>%u</TD></TR>\n",
747
(unsigned int)numTerminatedSessions) < 0)
748
traceEvent(TRACE_ERROR, "Buffer overflow!");
751
#if defined(MULTITHREADED) && defined(ASYNC_ADDRESS_RESOLUTION)
752
accessMutex(&addressQueueMutex, "NumQueuedAddresses");
753
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Queued Addresses</TH>"
754
"<TD "TD_BG" align=right>%d</TD></TR>\n", addressQueueLen) < 0)
755
traceEvent(TRACE_ERROR, "Buffer overflow!");
757
releaseMutex(&addressQueueMutex);
762
#if defined(MULTITHREADED)
763
accessMutex(&addressQueueMutex, "NumQueuedAddresses");
766
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Addresses Resolved with DNS</TH>"
767
"<TD "TD_BG" align=right>%ld</TD></TR>\n", numResolvedWithDNSAddresses) < 0)
768
traceEvent(TRACE_ERROR, "Buffer overflow!");
771
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Addresses Kept Numeric</TH>"
772
"<TD "TD_BG" align=right>%ld</TD></TR>\n", numKeptNumericAddresses) < 0)
773
traceEvent(TRACE_ERROR, "Buffer overflow!");
776
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Addresses Found in Cache</TH>"
777
"<TD "TD_BG" align=right>%ld</TD></TR>\n", numResolvedOnCacheAddresses) < 0)
778
traceEvent(TRACE_ERROR, "Buffer overflow!");
781
#if defined(MULTITHREADED)
782
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Dropped Addresses</TH>"
783
"<TD "TD_BG" align=right>%ld</TD></TR>\n", (long int)droppedAddresses) < 0)
784
traceEvent(TRACE_ERROR, "Buffer overflow!");
788
#if defined(MULTITHREADED)
789
releaseMutex(&addressQueueMutex);
794
#if defined(MULTITHREADED)
795
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Active Threads</TH>"
796
"<TD "TD_BG" align=right>%d</TD></TR>\n", numThreads) < 0)
797
traceEvent(TRACE_ERROR, "Buffer overflow!");
802
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left>Allocated Memory</TH>"
803
"<TD "TD_BG" align=right>%s</TD></TR>\n",
804
formatBytes(allocatedMemory, 0)) < 0)
805
traceEvent(TRACE_ERROR, "Buffer overflow!");
810
if(snprintf(buf, sizeof(buf), "<TR><TH "TH_BG" align=left># Monitored Processes</TH>"
811
"<TD "TD_BG" align=right>%d</TD></TR>\n", numProcesses) < 0)
812
traceEvent(TRACE_ERROR, "Buffer overflow!");
816
sendString("</TABLE>"TABLE_OFF"\n");
818
/* **************************** */
821
sendString("<P>"TABLE_ON"<TABLE BORDER=1>\n");
822
sendString("<TR><TH>Mutex Name</TH><TH>State</TH><TH>Last Lock</TH><TH>Last UnLock</TH>"
823
"<TH COLSPAN=2># Locks/Releases</TH><TH>Max Lock</TH></TR>");
824
printMutexStatus(&gdbmMutex, "gdbmMutex");
825
printMutexStatus(&packetQueueMutex, "packetQueueMutex");
826
printMutexStatus(&addressResolutionMutex, "addressResolutionMutex");
827
printMutexStatus(&hashResizeMutex, "hashResizeMutex");
828
if(isLsofPresent) printMutexStatus(&lsofMutex, "lsofMutex");
829
printMutexStatus(&hostsHashMutex, "hostsHashMutex");
830
printMutexStatus(&graphMutex, "graphMutex");
831
#ifdef ASYNC_ADDRESS_RESOLUTION
832
if(numericFlag == 0) printMutexStatus(&addressQueueMutex, "addressQueueMutex");
834
sendString("</TABLE>"TABLE_OFF"\n");
835
#endif /* MULTITHREADED */
837
sendString("</CENTER>\n");
840
#endif /* MICRO_NTOP */
842
/* ******************************* */
844
static void initializeWeb(void) {
846
columnSort = 0, sortSendMode = 0;
848
addDefaultAdminUser();
852
/* **************************************** */
856
Curtis Doty <Curtis@GreenKey.net>
858
void initWeb(int webPort, char* webAddr, char* sslAddr) {
860
struct sockaddr_in sin;
865
actualReportDeviceId = 0;
868
sin.sin_family = AF_INET;
869
sin.sin_port = (int)htons((unsigned short int)webPort);
870
sin.sin_addr.s_addr = INADDR_ANY;
874
if(!inet_aton(sslAddr,&sin.sin_addr))
875
traceEvent(TRACE_ERROR, "Unable to convert address '%s'...\n"
876
"Not binding SSL to a particular interface!\n", sslAddr);
879
if (webAddr) { /* Code added to be able to bind to a particular interface */
880
if (!inet_aton(webAddr,&sin.sin_addr))
881
traceEvent(TRACE_ERROR, "Unable to convert address '%s'...\n"
882
"Not binding to a particular interface!\n", webAddr);
886
sock = socket(AF_INET, SOCK_STREAM, 0);
888
traceEvent(TRACE_ERROR, "Unable to create a new socket");
892
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt));
898
sock_ssl = socket(AF_INET, SOCK_STREAM, 0);
900
traceEvent(TRACE_ERROR, "unable to create a new socket");
904
setsockopt(sock_ssl, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt));
909
if(bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
910
traceEvent(TRACE_WARNING, "bind: port %d already in use.", webPort);
911
closeNwSocket(&sock);
918
sin.sin_family = AF_INET;
919
sin.sin_port = (int)htons(sslPort);
920
sin.sin_addr.s_addr = INADDR_ANY;
922
if(bind(sock_ssl, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
923
traceEvent(TRACE_ERROR, "bind: port %d already in use.", webPort);
924
closeNwSocket(&sock_ssl);
931
if(listen(sock, 5) < 0) {
932
traceEvent(TRACE_WARNING, "listen error.\n");
933
closeNwSocket(&sock);
940
if(listen(sock_ssl, 5) < 0) {
941
traceEvent(TRACE_WARNING, "listen error.\n");
942
closeNwSocket(&sock_ssl);
948
/* Courtesy of Daniel Savard <daniel.savard@gespro.com> */
950
traceEvent(TRACE_INFO, "Waiting for HTTP connections on %s port %d...\n",
953
traceEvent(TRACE_INFO, "Waiting for HTTP connections on port %d...\n",
959
traceEvent(TRACE_INFO, "Waiting for HTTPS (SSL) connections on port %d...\n",
964
createThread(&handleWebConnectionsThreadId, handleWebConnections, NULL);
968
/* **************************************** */
973
if(snprintf(buf, sizeof(buf), "%s v.%s %s [%s] (%s build)",
974
program_name, version, THREAD_MODE, osName, buildDate) < 0)
975
traceEvent(TRACE_ERROR, "Buffer overflow!");
976
traceEvent(TRACE_INFO, "%s\n", buf);
978
traceEvent(TRACE_INFO, "Copyright 1998-2001 by %s\n", author);
979
traceEvent(TRACE_INFO, "Get the freshest ntop from http://www.ntop.org/\n");
980
if(snprintf(buf, sizeof(buf), "Written by %s.", author) < 0)
981
traceEvent(TRACE_ERROR, "Buffer overflow!");
983
traceEvent(TRACE_INFO, "%s\n", buf);
985
if(snprintf(buf, sizeof(buf), "Usage: %s", program_name) < 0)
986
traceEvent(TRACE_ERROR, "Buffer overflow!");
988
traceEvent(TRACE_INFO, "%s\n", buf);
990
traceEvent(TRACE_INFO, " %s\n", "[-c <sticky hosts: idle hosts are not purged from hash>]");
992
traceEvent(TRACE_INFO, " [-r <refresh time (web = %d sec)>]\n", REFRESH_TIME);
994
traceEvent(TRACE_INFO, " [-r <refresh time (interactive = %d sec/web = %d sec)>]\n",
995
ALARM_TIME, REFRESH_TIME);
997
traceEvent(TRACE_INFO, " %s\n", "[-f <traffic dump file (see tcpdump)>]");
999
traceEvent(TRACE_INFO, " %s\n", "[-E <enable lsof/nmap integration (if present)>]");
1001
traceEvent(TRACE_INFO, " %s\n", "[-n (numeric IP addresses)]");
1002
traceEvent(TRACE_INFO, " %s\n", "[-p <IP protocols to monitor> (see man page)]");
1004
traceEvent(TRACE_INFO, " %s\n", "[-i <interface>]");
1006
traceEvent(TRACE_INFO, " %s\n", "[-i <interface index>]");
1008
traceEvent(TRACE_INFO, " %s\n", "[-S <store mode> (store persistently host stats)]");
1009
traceEvent(TRACE_INFO, " %s\n", "[-w <HTTP port>]");
1011
traceEvent(TRACE_INFO, " %s\n", "[-W <HTTPS port>]");
1013
traceEvent(TRACE_INFO, " %s\n", "[-D <Internet domain name>]");
1014
traceEvent(TRACE_INFO, " %s\n", "[-e <max # table rows)]");
1016
traceEvent(TRACE_INFO, " %s\n", "[-d (run ntop in daemon mode)]");
1018
traceEvent(TRACE_INFO, " %s\n", "[-m <local addresses (see man page)>]");
1019
traceEvent(TRACE_INFO, " %s\n", "[-s <max hash size (default 32768)>]");
1020
traceEvent(TRACE_INFO, " %s\n", "[-F <flow specs (see man page)>]");
1021
traceEvent(TRACE_INFO, " %s\n", "[-b <client:port (ntop DB client)>]");
1023
traceEvent(TRACE_INFO, " %s\n", "[-v <username:password:dbName (ntop mySQL client)>]");
1025
traceEvent(TRACE_INFO, " %s\n", "[-R <matching rules file>]");
1026
traceEvent(TRACE_INFO, " %s\n", "[-N <don't use nmap if installed>]");
1027
traceEvent(TRACE_INFO, " %s\n", "[-M <don't merge network interfaces (see man page)>]");
1028
traceEvent(TRACE_INFO, " %s\n", "[-q <create file ntop-suspicious-pkts.XXX.pcap>]");
1029
/* Addition by Ola Lundqvist <opal@debian.org> */
1030
traceEvent(TRACE_INFO, " %s\n", "[-O <path> (base path for suspicious-pkts.XXX.pcap file.");
1031
traceEvent(TRACE_INFO, " %s\n", " Must end with a / if it points to a directory.]");
1032
/* End of Ola Lundqvist addition */
1033
traceEvent(TRACE_INFO, " %s\n", "[-l <path> (dump packets captured on a file: debug only!)]");
1034
traceEvent(TRACE_INFO, " %s\n", "[-P <path for db-files>]");
1035
traceEvent(TRACE_INFO, " %s\n", "[-g <client:port (Cisco NetFlow client)>]");
1036
traceEvent(TRACE_INFO, " %s\n", "[-t (trace level [0-5])]");
1037
traceEvent(TRACE_INFO, " %s\n", "[-A (accuracy level [0-2])]");
1038
traceEvent(TRACE_INFO, " %s\n", "[-u <userid> | <username> (see man page)]");
1039
traceEvent(TRACE_INFO, " %s\n", "[-U <mapper.pl URL> | \"\" for not displaying host location ]");
1040
traceEvent(TRACE_INFO, " %s\n", "[-k <show kernel filter expression in extra frame>]");
1042
traceEvent(TRACE_INFO, " %s\n", "[-K <enable application debug (no fork() is used)>]");
1043
traceEvent(TRACE_INFO, " %s\n", "[-L <use syslog instead of stdout>]");
1045
traceEvent(TRACE_INFO, " %s\n\n", "[ <filter expression (like tcpdump)>]");
1048
/* ******************************************* */
1050
void* handleWebConnections(void* notUsed _UNUSED_) {
1051
#ifndef MULTITHREADED
1052
struct timeval wait_time;
1056
fd_set mask, mask_copy;
1062
FD_SET((unsigned int)sock, &mask);
1065
if(sslInitialized) {
1066
FD_SET(sock_ssl, &mask);
1067
if(sock_ssl > topSock)
1072
memcpy(&mask_copy, &mask, sizeof(fd_set));
1074
#ifndef MULTITHREADED
1075
/* select returns immediately */
1076
wait_time.tv_sec = 0, wait_time.tv_usec = 0;
1077
if(select(topSock+1, &mask, 0, 0, &wait_time) == 1)
1078
handleSingleWebConnection(&mask);
1079
#else /* MULTITHREADED */
1080
while(capturePackets) {
1082
traceEvent(TRACE_INFO, "Select(ing) %d....", topSock);
1084
memcpy(&mask, &mask_copy, sizeof(fd_set));
1085
rc = select(topSock+1, &mask, 0, 0, NULL /* Infinite */);
1087
traceEvent(TRACE_INFO, "select returned: %d\n", rc);
1090
handleSingleWebConnection(&mask);
1093
traceEvent(TRACE_INFO, "Terminating Web connections...");
1099
/* ************************************* */
1101
void handleSingleWebConnection(fd_set *fdmask) {
1102
struct sockaddr_in from;
1103
int from_len = sizeof(from);
1107
if(FD_ISSET(sock, fdmask)) {
1109
traceEvent(TRACE_INFO, "Accepting HTTP request...\n");
1111
newSock = accept(sock, (struct sockaddr*)&from, &from_len);
1116
traceEvent(TRACE_INFO, "Accepting HTTPS request...\n");
1121
newSock = accept(sock_ssl, (struct sockaddr*)&from, &from_len);
1128
traceEvent(TRACE_INFO, "Request accepted (sock=%d) (errno=%d)\n", newSock, errno);
1134
if(FD_ISSET(sock_ssl, fdmask)) {
1135
if(accept_ssl_connection(newSock) == -1) {
1136
traceEvent(TRACE_WARNING, "Unable to accept SSL connection\n");
1137
closeNwSocket(&newSock);
1143
#endif /* HAVE_OPENSSL */
1147
struct request_info req;
1148
request_init(&req, RQ_DAEMON, DAEMONNAME, RQ_FILE, newSock, NULL);
1150
if (!hosts_access(&req)) {
1151
closelog(); /* just in case */
1152
openlog(DAEMONNAME,LOG_PID,SYSLOG_FACILITY);
1153
syslog(deny_severity, "refused connect from %s", eval_client(&req));
1156
handleHTTPrequest(from.sin_addr);
1159
handleHTTPrequest(from.sin_addr);
1160
#endif /* HAVE_LIBWRAP */
1162
closeNwSocket(&newSock);
1164
traceEvent(TRACE_INFO, "Unable to accept HTTP(S) request (errno=%d)", errno);
1168
/* ******************* */
1170
int handlePluginHTTPRequest(char* url) {
1171
FlowFilterList *flows = flowsList;
1173
while(flows != NULL)
1174
if((flows->pluginStatus.pluginPtr != NULL)
1175
&& (flows->pluginStatus.pluginPtr->pluginURLname != NULL)
1176
&& (flows->pluginStatus.pluginPtr->httpFunct != NULL)
1177
&& (strncmp(flows->pluginStatus.pluginPtr->pluginURLname,
1178
url, strlen(flows->pluginStatus.pluginPtr->pluginURLname)) == 0)) {
1181
/* Courtesy of Roberto F. De Luca <deluca@tandar.cnea.gov.ar> */
1182
if(!flows->pluginStatus.activePlugin) {
1183
char buf[BUF_SIZE], name[32];
1185
sendHTTPHeader(HTTP_TYPE_HTML, 0);
1186
strncpy(name, flows->pluginStatus.pluginPtr->pluginURLname, sizeof(name));
1187
name[sizeof(name)-1] = '\0'; /* just in case pluginURLname is too long... */
1188
if((strlen(name) > 6) && (strcasecmp(&name[strlen(name)-6], "plugin") == 0))
1189
name[strlen(name)-6] = '\0';
1190
if(snprintf(buf, sizeof(buf),"Status for the \"%s\" Plugin", name) < 0)
1191
traceEvent(TRACE_ERROR, "Buffer overflow!");
1192
printHTMLheader(buf, HTML_FLAG_NO_REFRESH);
1193
printFlagedWarning("<I>This plugin is currently inactive.</I>");
1198
if(strlen(url) == strlen(flows->pluginStatus.pluginPtr->pluginURLname))
1201
arg = &url[strlen(flows->pluginStatus.pluginPtr->pluginURLname)+1];
1203
/* traceEvent(TRACE_INFO, "Found %s [%s]\n",
1204
flows->pluginStatus.pluginPtr->pluginURLname, arg); */
1205
flows->pluginStatus.pluginPtr->httpFunct(arg);
1208
flows = flows->next;
1210
return(0); /* Plugin not found */