/* * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * http://www.ntop.org * * Copyright (C) 1998-2007 Luca Deri * * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * * 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" #include "globals-report.h" #include "scsiUtils.h" #if defined(MEMORY_DEBUG) && (MEMORY_DEBUG == 4) && defined(HAVE_BACKTRACE) #include #endif char static_ntop; /* * Hello World! This is ntop speaking... */ void welcome (FILE * fp) { fprintf (fp, "Welcome to %s v.%s\n[Configured on %s, built on %s]\n", myGlobals.program_name, version, configureDate, buildDate); fprintf (fp, "Copyright 1998-2007 by %s.\n", author); fprintf (fp, "Get the freshest ntop from http://www.ntop.org/\n"); } /* * Wrong. Please try again accordingly to .... */ void usage(FILE * fp) { char *newLine = ""; #ifdef WIN32 newLine = "\n\t"; #endif welcome(fp); fprintf(fp, "\nUsage: %s [OPTION]\n\n", myGlobals.program_name); fprintf(fp, "Basic options:\n"); fprintf(fp, " [-h | --help] %sDisplay this help and exit\n", newLine); #ifndef WIN32 fprintf(fp, " [-u | --user ] %sUserid/name to run ntop under (see man page)\n", newLine); #endif /* WIN32 */ fprintf(fp, " [-t | --trace-level ] %sTrace level [0-6]\n", newLine); fprintf(fp, " [-P | --db-file-path ] %sPath for ntop internal database files\n", newLine); fprintf(fp, " [-Q | --spool-file-path ] %sPath for ntop spool files\n", newLine); fprintf(fp, " [-w | --http-server ] %sWeb server (http:) port (or address:port) to listen on\n", newLine); #ifdef HAVE_OPENSSL fprintf(fp, " [-W | --https-server ] %sWeb server (https:) port (or address:port) to listen on\n", newLine); #endif fprintf(fp, "\nAdvanced options:\n"); fprintf(fp, " [-4 | --ipv4] %sUse IPv4 connections\n",newLine); fprintf(fp, " [-6 | --ipv6] %sUse IPv6 connections\n",newLine); fprintf(fp, " [-a | --access-log-file ] %sFile for ntop web server access log\n", newLine); fprintf(fp, " [-b | --disable-decoders] %sDisable protocol decoders\n", newLine); fprintf(fp, " [-c | --sticky-hosts] %sIdle hosts are not purged from memory\n", newLine); #ifndef WIN32 fprintf(fp, " [-d | --daemon] %sRun ntop in daemon mode\n", newLine); #endif fprintf(fp, " [-e | --max-table-rows ] %sMaximum number of table rows to report\n", newLine); fprintf(fp, " [-f | --traffic-dump-file ] %sTraffic dump file (see tcpdump)\n", newLine); fprintf(fp, " [-g | --track-local-hosts] %sTrack only local hosts\n", newLine); #ifndef WIN32 fprintf(fp, " [-i | --interface ] %sInterface name or names to monitor\n", newLine); #else fprintf(fp, " [-i | --interface ] %sInterface index number (or name) to monitor\n", newLine); #endif fprintf(fp, " [-j | --create-other-packets] %sCreate file ntop-other-pkts.XXX.pcap file\n", newLine); fprintf(fp, " [-l | --pcap-log ] %sDump packets captured to a file (debug only!)\n", newLine); fprintf(fp, " [-m | --local-subnets ] %sLocal subnetwork(s) (see man page)\n", newLine); fprintf(fp, " [-n | --numeric-ip-addresses] %sNumeric IP addresses - no DNS resolution\n", newLine); fprintf(fp, " [-o | --no-mac] %sntop will trust just IP addresses (no MACs)\n", newLine); fprintf(fp, " [-p | --protocols ] %sList of IP protocols to monitor (see man page)\n", newLine); fprintf(fp, " [-q | --create-suspicious-packets] %sCreate file ntop-suspicious-pkts.XXX.pcap file\n", newLine); fprintf(fp, " [-r | --refresh-time ] %sRefresh time in seconds, default is %d\n", newLine, DEFAULT_NTOP_AUTOREFRESH_INTERVAL); fprintf(fp, " [-s | --no-promiscuous] %sDisable promiscuous mode\n", newLine); fprintf(fp, " [-x ] %sMax num. hash entries ntop can handle (default %u)\n", newLine, myGlobals.runningPref.maxNumHashEntries); fprintf(fp, " [-z | --disable-sessions] %sDisable TCP session tracking\n", newLine); fprintf(fp, " [-A] %sAsk admin user password and exit\n", newLine); fprintf(fp, " [ | --set-admin-password=] %sSet password for the admin user to \n", newLine); fprintf(fp, " [ | --w3c] %sAdd extra headers to make better html\n", newLine); fprintf(fp, " [-B ] | --filter-expression %sPacket filter expression, like tcpdump\n", newLine); fprintf(fp, " [-C ] | --sampling-rate %sPacket capture sampling rate [default: 1 (no sampling)]\n", newLine); fprintf(fp, " [-D | --domain ] %sInternet domain name\n", newLine); fprintf(fp, " [-F | --flow-spec ] %sFlow specs (see man page)\n", newLine); #ifndef WIN32 fprintf(fp, " [-K | --enable-debug] %sEnable debug mode\n", newLine); #ifdef MAKE_WITH_SYSLOG fprintf(fp, " [-L] %sDo logging via syslog\n", newLine); fprintf(fp, " [ | --use-syslog=] %sDo logging via syslog, facility ('=' is REQUIRED)\n", newLine); #endif /* MAKE_WITH_SYSLOG */ #endif fprintf(fp, " [-M | --no-interface-merge] %sDon't merge network interfaces (see man page)\n", newLine); fprintf(fp, " [-N | --wwn-map] %sMap file providing map of WWN to FCID/VSAN\n", newLine); fprintf(fp, " [-O | --pcap-file-path ] %sPath for log files in pcap format\n", newLine); fprintf(fp, " [-U | --mapper ] %sURL (mapper.pl) for displaying host location\n", newLine); fprintf(fp, " [-V | --version] %sOutput version information and exit\n", newLine); fprintf(fp, " [-X ] %sMax num. TCP sessions ntop can handle (default %u)\n", newLine, myGlobals.runningPref.maxNumSessions); /* Please keep long-only options alphabetically ordered */ fprintf(fp, " [--disable-instantsessionpurge] %sDisable instant FIN session purge\n", newLine); fprintf(fp, " [--disable-mutexextrainfo] %sDisable extra mutex info\n", newLine); #ifdef MAKE_WITH_SCHED_YIELD fprintf(fp, " [--disable-schedyield] %sTurn off sched_yield() calls, if ntop is deadlocking on them\n", newLine); #endif fprintf(fp, " [--disable-stopcap] %sCapture packets even if there's no memory left\n", newLine); fprintf(fp, " [--fc-only] %sDisplay only Fibre Channel statistics\n", newLine); fprintf(fp, " [--no-fc] %sDisable processing & Display of Fibre Channel\n", newLine); fprintf(fp, " [--instance] %sSet log name for this ntop instance\n", newLine); fprintf(fp, " [--no-invalid-lun] %sDon't display Invalid LUN information\n", newLine); fprintf(fp, " [--p3p-cp] %sSet return value for p3p compact policy, header\n", newLine); fprintf(fp, " [--p3p-uri] %sSet return value for p3p policyref header\n", newLine); fprintf(fp, " [--skip-version-check] %sSkip ntop version check\n", newLine); #ifdef MAKE_WITH_SSLWATCHDOG_RUNTIME fprintf(fp, " [--ssl-watchdog] %sUse ssl watchdog (NS6 problem)\n", newLine); #endif fprintf(fp, "\n" "NOTE\n" " * You can configure further ntop options via the web\n" " interface [Menu Admin -> Config].\n" " * The command line options are not permanent, i.e. they\n" " are not persistent across ntop initializations.\n" "\n"); #ifdef WIN32 printAvailableInterfaces(); #endif } /* *********************************** */ static void verifyOptions (void) { #ifdef HAVE_OPENSSL if((myGlobals.runningPref.webPort == 0) && (myGlobals.runningPref.sslPort == 0)) { printf("WARNING: both -W and -w are set to 0. The web interface will be disabled.\n"); #else if(myGlobals.runningPref.webPort == 0) { printf("WARNING: -w is set to 0. The web interface will be disabled.\n"); #endif traceEvent(CONST_TRACE_WARNING, "The web interface will be disabled"); traceEvent(CONST_TRACE_INFO, "If enabled, the rrd plugin will collect data"); traceEvent(CONST_TRACE_INFO, "If enabled, the NetFlow and/or sFlow plugins will collect and/or transmit data"); traceEvent(CONST_TRACE_INFO, "This may or may not be what you want"); traceEvent(CONST_TRACE_INFO, "but without the web interface you can't set plugin parameters"); myGlobals.webInterfaceDisabled = 1; } /* * Must start run as root since opening a network interface * in promiscuous mode is a privileged operation. * Verify we're running as root, unless we are reading data from a file */ if(myGlobals.runningPref.rFileName != NULL) { return; } #ifndef WIN32 if ((myGlobals.runningPref.disablePromiscuousMode != 1) && getuid() /* We're not root */ && myGlobals.runningPref.devices && strcmp(myGlobals.runningPref.devices, "none")) { char *theRootPw, *correct, *encrypted; struct passwd *pw = getpwuid(0); myGlobals.userId = getuid(); myGlobals.groupId = getgid(); traceEvent(CONST_TRACE_WARNING, "You need root capabilities to capture network packets."); if(strcmp(pw->pw_passwd, "x") == 0) { #ifdef HAVE_SHADOW_H /* Use shadow passwords */ struct spwd *spw; spw = getspnam("root"); if(spw == NULL) { traceEvent(CONST_TRACE_INFO, "Unable to read shadow passwords. Become root first and start ntop again"); traceEvent(CONST_TRACE_INFO, "or add -s to your startup parameters (you won't be able to capture"); traceEvent(CONST_TRACE_INFO, "from a NIC but you can via NetFlow/sFlow)"); exit (-1); } else correct = spw->sp_pwdp; #else traceEvent(CONST_TRACE_ERROR, "Sorry: I cannot change user as your system uses and unsupported password storage mechanism."); traceEvent(CONST_TRACE_ERROR, "Please restart ntop with root capabilities"); exit (-1); #endif } else correct = pw->pw_passwd; theRootPw = getpass("Please enter the root password: "); encrypted = crypt(theRootPw, correct); if(strcmp(encrypted, correct) == 0) { traceEvent(CONST_TRACE_INFO, "The root password is correct"); if(setuid(0) || setgid(0)) { traceEvent(CONST_TRACE_ERROR, "Sorry I'm unable to become root. Please check whether this application"); traceEvent(CONST_TRACE_ERROR, "has the sticky bit set and the owner is %s. Otherwise", #ifdef DARWIN "root:wheel" #else "root:root" #endif ); traceEvent(CONST_TRACE_FATALERROR, "please run ntop as root."); exit (18); } } else { traceEvent(CONST_TRACE_ERROR, "The specified root password is not correct."); traceEvent(CONST_TRACE_FATALERROR, "Sorry, %s uses network interface(s) in promiscuous mode, " "so it needs root permission to run.\n", myGlobals.program_name); exit(19); } } else if (myGlobals.runningPref.disablePromiscuousMode == 1) traceEvent(CONST_TRACE_WARNING, "-s set so will ATTEMPT to open interface w/o promisc mode " "(this will probably fail below)"); #endif /* WIN32 */ return; } /* ************************************ */ #if defined(MEMORY_DEBUG) && (MEMORY_DEBUG == 4) static void abortfn(enum mcheck_status status) { #ifdef HAVE_BACKTRACE int i; void *array[20]; size_t size; char **strings; /* Grab the backtrace before we do much else... */ size = backtrace(array, 20); strings = (char**)backtrace_symbols(array, size); #endif switch(status) { case MCHECK_HEAD: traceEvent(CONST_TRACE_ERROR, "MCHECK_HEAD: modified before block"); break; case MCHECK_TAIL: traceEvent(CONST_TRACE_ERROR, "MCHECK_TAIL: modified after block"); break; case MCHECK_FREE: traceEvent(CONST_TRACE_ERROR, "MCHECK_FREE: already freed"); break; } #ifdef HAVE_BACKTRACE if (size >= 2) { traceEvent(CONST_TRACE_INFO, "MCHECK: backtrace is:"); for (i=0; i '%s'\n", readBuffer); #endif safe_strncat(cmdLineBuffer, LEN_CMDLINE_BUFFER, " "); safe_strncat(cmdLineBuffer, LEN_CMDLINE_BUFFER, readBuffer); } fclose(fd); } } free(readBuffer); /* Strip trailing spaces */ while((strlen(cmdLineBuffer) > 1) && (cmdLineBuffer[strlen(cmdLineBuffer)-1] == ' ')) { cmdLineBuffer[strlen(cmdLineBuffer)-1] = '\0'; } effective_argv = buildargv(cmdLineBuffer); /* Build a new argv[] from the string */ free(cmdLineBuffer); /* count effective_argv[] */ effective_argc = 0; while (effective_argv[effective_argc] != NULL) { effective_argc++; } #ifdef PARAM_DEBUG for(i=0; i0) ? "," : "", (myGlobals.device[i].humanFriendlyName != NULL) ? myGlobals.device[i].humanFriendlyName : myGlobals.device[i].name); strncat(ifStr, tmpBuf, sizeof(ifStr)-strlen(ifStr)-1)[sizeof(ifStr)-1] = '\0'; } } if((ifStr == NULL) || (ifStr[0] == '\0')) { traceEvent(CONST_TRACE_ERROR, "No interface has been selected. Capture not started..."); createDummyInterface("none"); } else traceEvent(CONST_TRACE_ALWAYSDISPLAY, "Listening on [%s]", ifStr); if(!static_ntop) { traceEvent(CONST_TRACE_ALWAYSDISPLAY, "Loading Plugins"); loadPlugins(); traceEvent(CONST_TRACE_NOISY, "Starting Plugins"); startPlugins(); traceEvent(CONST_TRACE_NOISY, "Plugins started... continuing with initialization"); } /* ******************************* */ #ifndef WIN32 saveNtopPid(); #endif checkUserIdentity(userSpecified); /* ******************************* */ addDefaultAdminUser(); initReports(); traceEvent(CONST_TRACE_NOISY, "MEMORY: Base interface structure (no hashes loaded) is %.2fMB each", xvertDOT00MB(sizeof(NtopInterface))); traceEvent(CONST_TRACE_NOISY, "MEMORY: or %.2fMB for %d interfaces", xvertDOT00MB(myGlobals.numDevices*sizeof(NtopInterface)), myGlobals.numDevices); traceEvent(CONST_TRACE_NOISY, "MEMORY: ipTraffixMatrix structure (no TrafficEntry loaded) is %.2fMB", xvertDOT00MB(myGlobals.ipTrafficMatrixMemoryUsage)); #ifdef NOT_YET traceEvent(CONST_TRACE_NOISY, "MEMORY: fcTrafficMatrix structure (no TrafficEntry loaded) is %.2fMB", xvertDOT00MB(myGlobals.fcTrafficMatrixMemoryUsage)); #endif /* * OK, ntop is up... if we have't failed during init, start running with the actual packet capture... * * A separate thread handles packet sniffing */ startSniffer(); #ifndef WIN32 while(myGlobals.ntopRunState == FLAG_NTOPSTATE_RUN) { ntopSleepWhileSameState(PARM_SLEEP_LIMIT); /* Periodic recheck of the version status */ if((myGlobals.checkVersionStatusAgain > 0) && (time(NULL) > myGlobals.checkVersionStatusAgain) && (myGlobals.ntopRunState == FLAG_NTOPSTATE_RUN)) checkVersion(NULL); } traceEvent(CONST_TRACE_INFO, "THREADMGMT[t%lu]: Main thread shutting down", pthread_self()); endTime = time(NULL) + PARM_SLEEP_LIMIT + 2; while((myGlobals.ntopRunState != FLAG_NTOPSTATE_TERM) && (time(NULL) < endTime)) { sleep(1); } traceEvent(CONST_TRACE_INFO, "THREADMGMT[t%lu]: Main thread terminating", pthread_self()); memset(&buf, 0, sizeof(buf)); runningThreads(buf, sizeof(buf), 0); if(buf[0] != '\0') traceEvent(CONST_TRACE_INFO, "THREADMGMT[t%lu]: Still running threads%s", pthread_self(), buf); traceEvent(CONST_TRACE_INFO, "==================================="); traceEvent(CONST_TRACE_INFO, " ntop is shutdown... "); traceEvent(CONST_TRACE_INFO, "==================================="); #endif return(0); }