diff --git a/ChangeLog b/CHANGELOG similarity index 98% rename from ChangeLog rename to CHANGELOG index f7af12c7..e8d581b8 100644 --- a/ChangeLog +++ b/CHANGELOG @@ -1,5 +1,13 @@ The Cacti Group | spine +1.2.0 +-feature: Allow threads to be set a Data Collector level +-issue#50: make fails on Debian 7 attempting to locate clock_gettime +-issue#53: Improved escaping when updating database records +-issue#54: Spine should always log if ICMP fails +-issue#58: When updating snmp_sysLocation, text can become truncated +-issue#63: Automatically reduce device threads when number of data sources does not require it + 1.1.38 -feature: release to match Cacti release diff --git a/INSTALL b/INSTALL index 20998407..0bd3d2df 100644 --- a/INSTALL +++ b/INSTALL @@ -1,370 +1,136 @@ -Installation Instructions -************************* - -Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, -Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell command `./configure && make && make install' -should configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - - The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type `make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root - privileges. - - 5. Optionally, type `make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type `make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. - -Optional Features -================= +Spine is a high speed poller replacement for cmd.php. It is almost 100% +compatible with the legacy cmd.php processor and provides much more +flexibility, speed and concurrency than cmd.php. + +Make sure that you have the proper development environment to compile Spine. +This includes compilers, header files and things such as libtool. If you +have questions please consult the forums and/or online documentation. + +Development +=========== - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. +DEVELOP branch should generally be considered UNSTABLE, use with caution! - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. +----------------------------------------------------------------------------- + +Unix Installation +================= - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. +These instructions assume the default install location for spine +of /usr/local/spine. If you choose to use another prefix, make +sure you update the commands as required for that new path. - Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. +To compile and install Spine using MySQL versions 5.5 or higher +please do the following: -Particular systems -================== + ./configure + make + make install + chown root:root /usr/local/spine/bin/spine + chmod u+s /usr/local/spine/bin/spine - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: +To compile and install Spine using MySQL versions previous to 5.5 +please do the following: - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + ./configure --with-reentrant + make + make install + chown root:root /usr/local/spine/bin/spine + chmod +s /usr/local/spine/bin/spine -and if that doesn't work, install pre-built binaries of GCC for HP-UX. +Windows Installation +==================== - HP-UX `make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as `configure' are involved. Use GNU `make' -instead. +CYGWIN Prerequisite +------------------- - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try +1. Download Cygwin for Window from https://www.cygwin.com/ - ./configure CC="cc" +2. Install Cygwin by executing the downloaded setup program -and if that doesn't work, try +3. Select _Install from Internet_ - ./configure CC="cc -nodtk" +4. Select Root Directory: _C:\cygwin_ - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. +5. Select a mirror which is close to your location - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: +6. Once on the package selection section make sure to select the following (TIP: use the search!): - ./configure --prefix=/boot/common + * autoconf + * automake + * dos2unix + * gcc-core + * gzip + * help2man + * libmysqlclient + * libmysqlclient-devel + * libtool + * m4 + * make + * net-snmp-devel + * openssl-devel + * wget -Specifying the System Type -========================== +7. Wait for installation to complete, coffee time! - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: +8. Move the cygwin setup to the C:\cygwin\ folder for future usage. - CPU-COMPANY-SYSTEM +Compile Spine +------------- -where SYSTEM can have one of these forms: +1. Open Cygwin shell prompt (C:\Cygwin\cygwin.bat) and brace yourself to use unix commands on Windows. - OS - KERNEL-OS +2. Download the Spine source to the current directory: + http://www.cacti.net/spine_download.php - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. +3. Extract Spine into C:\Cygwin\usr\src\: + tar xzvf cacti-spine-*.tar.gz - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. +4. Change into the Spine directory: + cd /usr/src/cacti-spine-* - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. +5. Run bootstrap to prepare Spine for compilation: + ./bootstrap -Sharing Defaults -================ +6. Follow the instruction which bootstrap outputs. - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. +7. Update the spine.conf file for your installation of Cacti. You can optionally + move it to a better location if you choose to do so, make sure to copy the + spine.conf as well. -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: +8. Ensure that Spine runs well by running with: + /usr/local/spine/spine -R -S -V 3 - ./configure CC=/usr/local2/bin/gcc +9. Update Cacti 'Paths' Setting to point to the Spine binary and update the + 'Poller Type' to Spine. For the spine binary on Windows x64, and using default + locations, that would be: + C:\cygwin64\usr\local\spine\bin\spine.exe -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). +10. If all is good Spine will be run from the poller in place of cmd.php. -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf limitation. Until the limitation is lifted, you can use -this workaround: +-------------------------------------------------------------------------------------- - CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash +Known Issues +============ +1. On Windows, Microsoft does not support a TCP Socket send timeout. Therefore, + if you are using TCP ping on Windows, spine will not perform a second or subsequent + retries to connect and the host will be assumed down on the first failure. -`configure' Invocation -====================== + If this is a problem it is suggested to use another Availability/Reachability + method, or moving to Linux/UNIX. - `configure' recognizes the following options to control how it -operates. +2. Spine takes quite a few MySQL connections. The number of connections is calculated + as follows: -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. + * main poller take one connection + * all threads take one connection each + * all script servers take one connection each -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. + Therefore, if you have 4 processes, with 10 threads each, and 5 script servers each + your spine will take approximately: -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. + total connections = 4 * ( 1 + 10 + 5 ) = 64 -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. +3. On older MySQL versions, different libraries had to be used to make MySQL thread + safe. MySQL versions 5.0 and 5.1 require this flag. If you are using these version + of MySQL, you must use the --with-reentrant configure flag. diff --git a/README.md b/README.md index 9403d4e8..6e2baaa3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Spine: a poller for Cacti ---------------------------- + Spine is a high speed poller replacement for `cmd.php`. It is almost 100% compatible with the legacy cmd.php processor and provides much more flexibility, speed and concurrency than `cmd.php`. @@ -8,6 +8,19 @@ Make sure that you have the proper development environment to compile Spine. This includes compilers, header files and things such as libtool. If you have questions please consult the forums and/or online documentation. +----------------------------------------------------------------------------- + +## 1.2.0 Development + +**PLEASE READ** + +Feature branch for `1.2.x` has been merged into the `develop` branch. This means +things may and will break, but they will eventually be fixed. + +> DEVELOP branch is currently considered UNSTABLE, use with caution! + +----------------------------------------------------------------------------- + ## Unix Installation These instructions assume the default install location for spine @@ -22,7 +35,7 @@ please do the following: make make install chown root:root /usr/local/spine/bin/spine -chmod +s /usr/local/spine/bin/spine +chmod u+s /usr/local/spine/bin/spine ``` To compile and install Spine using MySQL versions previous to 5.5 diff --git a/configure.ac b/configure.ac index b345fd2e..a0cd2de5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.53) -AC_INIT(Spine Poller, 1.1.38, http://www.cacti.net/issues.php) +AC_INIT(Spine Poller, 1.2.0, http://www.cacti.net/issues.php) AC_CONFIG_AUX_DIR(config) AC_SUBST(ac_aux_dir) @@ -10,7 +10,7 @@ AC_PREFIX_DEFAULT(/usr/local/spine) AC_LANG(C) AM_INIT_AUTOMAKE([foreign]) -AM_CONFIG_HEADER(config/config.h) +AC_CONFIG_HEADERS(config/config.h) # static libraries AC_ARG_WITH(static, @@ -67,6 +67,7 @@ case $host_alias in CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS";; *freebsd*) LIBS="$LIBS -pthread" + LDFLAGS="-lexecinfo" AC_DEFINE(HAVE_LIBPTHREAD, 1);; *darwin*) ShLib="dylib";; @@ -80,7 +81,7 @@ AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S -AC_PROG_LIBTOOL +LT_INIT AC_MSG_CHECKING([whether to enable -Wall]) AC_ARG_ENABLE(warnings, @@ -127,11 +128,15 @@ AC_CHECK_LIB(z, deflate) AC_CHECK_LIB(kstat, kstat_close) AC_CHECK_LIB(crypto, CRYPTO_realloc) +# minor adjustments for debian +AC_SEARCH_LIBS([clock_gettime], [rt pthread]) + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(sys/socket.h sys/select.h sys/wait.h sys/time.h) AC_CHECK_HEADERS(assert.h ctype.h errno.h signal.h math.h malloc.h netdb.h) AC_CHECK_HEADERS(signal.h stdarg.h stdio.h syslog.h) +AC_CHECK_HEADERS(execinfo.h) AC_CHECK_HEADERS( netinet/in_systm.h netinet/in.h netinet/ip.h netinet/ip_icmp.h, [], @@ -177,7 +182,7 @@ if test x$ENABLED_SOL_PRIV != xno; then if test x$FOUND_PRIV_H != xno; then AC_MSG_RESULT([yes]) AC_DEFINE([SOLAR_PRIV], [1], - [If upport for Solaris privileges should be enabled] + [If Support for Solaris privileges should be enabled] ) else AC_MSG_RESULT([no]) @@ -470,4 +475,28 @@ if test -z "$HAVE_GETHOSTBYNAME_R"; then HAVE_GETHOSTBYNAME_R=yes fi +# See if we can support backtracing +AC_MSG_CHECKING([if we can support backtracing]) +AC_TRY_LINK( + [ + #include + #include + ],[ + void *array[10]; + size_t size; + + # get void*'s for all entries on the stack + size = backtrace(array, 10); + if (size) { + exit(0); + } else { + exit(1); + } + ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(HAS_EXECINFO_H,1,[Do we have backtracing capabilities?]) + ], + AC_MSG_RESULT(no) +) + AC_OUTPUT(Makefile) diff --git a/error.c b/error.c index 6620209c..0f48cf65 100644 --- a/error.c +++ b/error.c @@ -46,6 +46,11 @@ static void spine_signal_handler(int spine_signal) { signal(spine_signal, SIG_DFL); +#if HAS_EXECINFO_H + // get void*'s for all entries on the stack + set.exit_size = backtrace(set.exit_stack, 10); +#endif + set.exit_code = spine_signal; switch (spine_signal) { @@ -80,6 +85,8 @@ static int spine_fatal_signals[] = { SIGBUS, SIGFPE, SIGQUIT, + SIGSYS, + SIGABRT, 0 }; diff --git a/php.c b/php.c index 1f46b507..76eba9d4 100644 --- a/php.c +++ b/php.c @@ -435,9 +435,10 @@ int php_init(int php_process) { php_processes[php_process].php_state = PHP_BUSY; } } + + free(result_string); } - free(result_string); return TRUE; } diff --git a/ping.c b/ping.c index 7d844540..e54e48f5 100644 --- a/ping.c +++ b/ping.c @@ -59,11 +59,7 @@ int ping_host(host_t *host, ping_t *ping) { if (host->ping_method == PING_ICMP) { if (set.icmp_avail == FALSE) { - if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] DEBUG Falling back to UDP Ping Due to SetUID Issues", host->id)); - } else { - SPINE_LOG_DEBUG(("Device[%i] DEBUG Falling back to UDP Ping Due to SetUID Issues", host->id)); - } + SPINE_LOG(("Device[%i] DEBUG Falling back to UDP Ping Due to SetUID Issues", host->id)); host->ping_method = PING_UDP; } } @@ -387,26 +383,13 @@ int ping_icmp(host_t *host, ping_t *ping) { return HOST_DOWN; } - /* record start time */ - if (total_time == 0) { - /* establish timeout value */ - timeout.tv_sec = rint(host_timeout / 1000); - timeout.tv_usec = rint((int) host_timeout % 1000) * 1000; - - /* set the socket send and receive timeout */ - setsockopt(icmp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); - setsockopt(icmp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); - - begin_time = get_time_as_double(); - } else { - /* decrement the timeout value by the total time */ - timeout.tv_sec = rint((host_timeout - total_time) / 1000); - timeout.tv_usec = ((int) (host_timeout - total_time) % 1000) * 1000; + /* decrement the timeout value by the total time */ + timeout.tv_sec = rint((host_timeout - total_time) / 1000); + timeout.tv_usec = ((int) (host_timeout - total_time) % 1000) * 1000; - /* set the socket send and receive timeout */ - setsockopt(icmp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); - setsockopt(icmp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); - } + /* set the socket send and receive timeout */ + setsockopt(icmp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); + setsockopt(icmp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); /* send packet to destination */ return_code = sendto(icmp_socket, packet, packet_len, 0, (struct sockaddr *) &fromname, sizeof(fromname)); @@ -432,13 +415,14 @@ int ping_icmp(host_t *host, ping_t *ping) { if (return_code < 0) { if (errno == EINTR) { + /* call was interrupted by some system event */ + if (is_debug_device(host->id)) { SPINE_LOG(("Device[%i] DEBUG: Received EINTR", host->id)); } else { SPINE_LOG_DEBUG(("Device[%i] DEBUG: Received EINTR", host->id)); } - /* call was interrupted by some system event */ - // usleep(10000); + goto keep_listening; } } else { @@ -446,7 +430,7 @@ int ping_icmp(host_t *host, ping_t *ping) { pkt = (struct icmp *) (socket_reply + (ip->ip_hl << 2)); if (fromname.sin_addr.s_addr == recvname.sin_addr.s_addr) { - if ((pkt->icmp_type == ICMP_ECHOREPLY)) { + if (pkt->icmp_type == ICMP_ECHOREPLY) { if (is_debug_device(host->id)) { SPINE_LOG(("Device[%i] DEBUG: ICMP Device Alive, Try Count:%i, Time:%.4f ms", host->id, retry_count+1, (total_time))); } else { @@ -591,6 +575,8 @@ int ping_udp(host_t *host, ping_t *ping) { /* set total time */ total_time = 0; + begin_time = get_time_as_double(); + /* remove "udp:" from hostname */ new_hostname = remove_tcp_udp_from_hostname(host->hostname); @@ -644,8 +630,6 @@ int ping_udp(host_t *host, ping_t *ping) { /* set the socket send and receive timeout */ setsockopt(udp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); setsockopt(udp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); - - begin_time = get_time_as_double(); } else { /* decrement the timeout value by the total time */ timeout.tv_sec = rint((host_timeout - total_time) / 1000); @@ -769,6 +753,12 @@ int ping_tcp(host_t *host, ping_t *ping) { /* initilize the socket */ tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + /* initialize total time */ + total_time = 0; + + /* initialize begin time */ + begin_time = get_time_as_double(); + /* hostname must be nonblank */ if ((strlen(host->hostname) != 0) && (tcp_socket != -1)) { /* initialize variables */ @@ -781,26 +771,13 @@ int ping_tcp(host_t *host, ping_t *ping) { retry_count = 0; while (1) { - /* record start time */ - if (total_time == 0) { - /* establish timeout value */ - timeout.tv_sec = rint(host_timeout / 1000); - timeout.tv_usec = ((int) host_timeout % 1000) * 1000; + /* establish timeout value */ + timeout.tv_sec = rint(host_timeout / 1000); + timeout.tv_usec = ((int) host_timeout % 1000) * 1000; - /* set the socket send and receive timeout */ - setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); - setsockopt(tcp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); - - begin_time = get_time_as_double(); - } else { - /* decrement the timeout value by the total time */ - timeout.tv_sec = rint((host_timeout - total_time) / 1000); - timeout.tv_usec = ((int) (host_timeout - total_time) % 1000) * 1000; - - /* set the socket send and receive timeout */ - setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); - setsockopt(tcp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); - } + /* set the socket send and receive timeout */ + setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); + setsockopt(tcp_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); /* make the connection */ return_code = connect(tcp_socket, (struct sockaddr *) &servername, sizeof(servername)); @@ -901,7 +878,7 @@ int init_sockaddr(struct sockaddr_in *name, const char *hostname, unsigned short int rv; buf = malloc(len*sizeof(char)); - memset(buf, 0, sizeof(buf)); + memset(buf, 0, len*sizeof(char)); while (1) { rv = gethostbyname_r(hostname, &result_buf, buf, len, @@ -1107,20 +1084,20 @@ void update_host_status(int status, host_t *host, ping_t *ping, int availability case AVAIL_SNMP_OR_PING: case AVAIL_SNMP_AND_PING: if ((strlen(host->snmp_community) == 0) && (host->snmp_version < 3)) { - snprintf(host->status_last_error, SMALL_BUFSIZE, "%s", ping->ping_response); + snprintf(host->status_last_error, BUFSIZE, "%s", ping->ping_response); } else { - snprintf(host->status_last_error, SMALL_BUFSIZE,"%s, %s",ping->snmp_response,ping->ping_response); + snprintf(host->status_last_error, BUFSIZE,"%s, %s",ping->snmp_response,ping->ping_response); } break; case AVAIL_SNMP: if ((strlen(host->snmp_community) == 0) && (host->snmp_version < 3)) { - snprintf(host->status_last_error, SMALL_BUFSIZE, "%s", "Device does not require SNMP"); + snprintf(host->status_last_error, BUFSIZE, "%s", "Device does not require SNMP"); } else { - snprintf(host->status_last_error, SMALL_BUFSIZE, "%s", ping->snmp_response); + snprintf(host->status_last_error, BUFSIZE, "%s", ping->snmp_response); } break; default: - snprintf(host->status_last_error, SMALL_BUFSIZE, "%s", ping->ping_response); + snprintf(host->status_last_error, BUFSIZE, "%s", ping->ping_response); } /* determine if to send an alert and update remainder of statistics */ diff --git a/poller.c b/poller.c index 01846401..bb4b6fd1 100644 --- a/poller.c +++ b/poller.c @@ -91,7 +91,7 @@ void *child(void *arg) { thread_mutex_lock(LOCK_PEND); pending_threads--; - SPINE_LOG_MEDIUM(("POLLR: Active Threads is %i, Pending is %i", set.threads - a_threads_value, pending_threads)); + SPINE_LOG_MEDIUM(("POLLER: Active Threads is %i, Pending is %i", set.threads - a_threads_value, pending_threads)); thread_mutex_unlock(LOCK_PEND); /* end the thread */ @@ -124,7 +124,7 @@ void *child(void *arg) { */ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data_ids, char *host_time, int *host_errors, double host_time_double) { char query1[BUFSIZE]; - char query2[BUFSIZE]; + char query2[BIG_BUFSIZE]; char *query3 = NULL; char query4[BUFSIZE]; char query5[BUFSIZE]; @@ -157,8 +157,9 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data int php_process; char *poll_result = NULL; - char update_sql[BUFSIZE]; + char update_sql[BIG_BUFSIZE]; char temp_poll_result[BUFSIZE]; + char temp_arg1[BUFSIZE]; char limits[SMALL_BUFSIZE]; int num_snmp_agents = 0; @@ -179,6 +180,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data int last_data_query_id = 0; int perform_assert = TRUE; int new_buffer = TRUE; + int ignore_sysinfo = TRUE; reindex_t *reindex; host_t *host; @@ -189,14 +191,32 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data error_string = malloc(DBL_BUFSIZE); MYSQL mysql; + MYSQL mysqlr; + MYSQL mysqlt; MYSQL_RES *result; MYSQL_ROW row; - db_connect(set.dbdb, &mysql); + db_connect(LOCAL, &mysql); /* Since MySQL 5.7 the sql_mode defaults are too strict for cacti */ - db_insert(&mysql, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); - db_insert(&mysql, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_IN_DATE', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_AUTO_VALUE_ON_ZERO', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'TRADITIONAL', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'STRICT_ALL_TABLES', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES', ''))"); + + if (set.mode == REMOTE_ONLINE) { + db_connect(REMOTE, &mysqlr); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_IN_DATE', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_AUTO_VALUE_ON_ZERO', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'TRADITIONAL', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'STRICT_ALL_TABLES', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES', ''))"); + } /* allocate host and ping structures with appropriate values */ if (!(host = (host_t *) malloc(sizeof(host_t)))) { @@ -214,8 +234,6 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data } memset(reindex, 0, sizeof(reindex_t)); - sysUptime[0] = '\0'; - /* determine the SQL limits using the poller instructions */ if (host_data_ids > 0) { snprintf(limits, SMALL_BUFSIZE, "LIMIT %i, %i", host_data_ids * (host_thread - 1), host_data_ids); @@ -236,7 +254,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data " ORDER BY snmp_port %s", host_id, limits); /* host structure for uptime checks */ - snprintf(query2, BUFSIZE, + snprintf(query2, BIG_BUFSIZE, "SELECT id, hostname, snmp_community, snmp_version, " "snmp_username, snmp_password, snmp_auth_protocol, " "snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id, snmp_port, snmp_timeout, max_oids, " @@ -244,7 +262,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data "status, status_event_count, status_fail_date, " "status_rec_date, status_last_error, " "min_time, max_time, cur_time, avg_time, " - "total_polls, failed_polls, availability, snmp_sysUptimeInstance, snmp_sysDescr, snmp_sysObjectID, " + "total_polls, failed_polls, availability, snmp_sysUpTimeInstance, snmp_sysDescr, snmp_sysObjectID, " "snmp_sysContact, snmp_sysName, snmp_sysLocation" " FROM host" " WHERE id=%i", host_id); @@ -307,7 +325,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data " ORDER BY snmp_port %s", host_id, set.poller_id, limits); /* host structure for uptime checks */ - snprintf(query2, BUFSIZE, + snprintf(query2, BIG_BUFSIZE, "SELECT id, hostname, snmp_community, snmp_version, " "snmp_username, snmp_password, snmp_auth_protocol, " "snmp_priv_passphrase, snmp_priv_protocol, snmp_context, snmp_engine_id, snmp_port, snmp_timeout, max_oids, " @@ -315,7 +333,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data "status, status_event_count, status_fail_date, " "status_rec_date, status_last_error, " "min_time, max_time, cur_time, avg_time, " - "total_polls, failed_polls, availability, snmp_sysUptimeInstance, snmp_sysDescr, snmp_sysObjectID, " + "total_polls, failed_polls, availability, snmp_sysUpTimeInstance, snmp_sysDescr, snmp_sysObjectID, " "snmp_sysContact, snmp_sysName, snmp_sysLocation" " FROM host" " WHERE id=%i", host_id); @@ -384,12 +402,16 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* if the host is a real host. Note host_id=0 is not host based data source */ if (host_id) { /* get data about this host */ - if ((result = db_query(&mysql, query2)) != 0) { + if ((result = db_query(&mysql, LOCAL, query2)) != 0) { num_rows = mysql_num_rows(result); if (num_rows != 1) { mysql_free_result(result); - mysql_close(&mysql); + db_disconnect(&mysql); + + if (set.mode == REMOTE_ONLINE) { + db_disconnect(&mysqlr); + } #ifndef OLD_MYSQL mysql_thread_end(); @@ -487,15 +509,15 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if (row[30] != NULL) host->availability = atof(row[30]); if (row[31] != NULL) host->snmp_sysUpTimeInstance=atoi(row[31]); - if (row[32] != NULL) STRNCOPY(host->snmp_sysDescr, row[32]); - if (row[33] != NULL) STRNCOPY(host->snmp_sysObjectID, row[33]); - if (row[34] != NULL) STRNCOPY(host->snmp_sysContact, row[34]); - if (row[35] != NULL) STRNCOPY(host->snmp_sysName, row[35]); - if (row[36] != NULL) STRNCOPY(host->snmp_sysLocation, row[36]); + if (row[32] != NULL) db_escape(&mysql, host->snmp_sysDescr, sizeof(host->snmp_sysDescr), row[32]); + if (row[33] != NULL) db_escape(&mysql, host->snmp_sysObjectID, sizeof(host->snmp_sysObjectID), row[33]); + if (row[34] != NULL) db_escape(&mysql, host->snmp_sysContact, sizeof(host->snmp_sysContact), row[34]); + if (row[35] != NULL) db_escape(&mysql, host->snmp_sysName, sizeof(host->snmp_sysName), row[35]); + if (row[36] != NULL) db_escape(&mysql, host->snmp_sysLocation, sizeof(host->snmp_sysLocation), row[36]); /* correct max_oid bounds issues */ if ((host->max_oids == 0) || (host->max_oids > 100)) { - SPINE_LOG(("Device[%i] TH[%i] WARNING: Max OIDS is out of range with value of '%i'. Resetting to default of 5", host_id, host_thread, host->max_oids)); + SPINE_LOG(("Device[%i] HT[%i] WARNING: Max OIDS is out of range with value of '%i'. Resetting to default of 5", host_id, host_thread, host->max_oids)); host->max_oids = 5; } @@ -532,9 +554,9 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data update_host_status(HOST_UP, host, ping, host->availability_method); if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] No host availability check possible for '%s'", host->id, host_thread, host->hostname)); + SPINE_LOG(("Device[%i] HT[%i] No host availability check possible for '%s'", host->id, host_thread, host->hostname)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] No host availability check possible for '%s'", host->id, host_thread, host->hostname)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] No host availability check possible for '%s'", host->id, host_thread, host->hostname)); } } else { if (ping_host(host, ping) == HOST_UP) { @@ -545,6 +567,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if ((host->availability_method != AVAIL_PING) && (host->availability_method != AVAIL_NONE)) { if (host->snmp_session != NULL) { get_system_information(host, &mysql, 1); + ignore_sysinfo = FALSE; } } } @@ -558,38 +581,82 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* update host table */ if (host_thread == 1) { - snprintf(update_sql, BUFSIZE, "UPDATE host " - "SET status='%i', status_event_count='%i', status_fail_date='%s'," - " status_rec_date='%s', status_last_error='%s', min_time='%f'," - " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i'," - " failed_polls='%i', availability='%.4f', snmp_sysDescr='%s', " - " snmp_sysObjectID='%s', snmp_sysUpTimeInstance='%u', " - " snmp_sysContact='%s', snmp_sysName='%s', snmp_sysLocation='%s' " - "WHERE id='%i'", - host->status, - host->status_event_count, - host->status_fail_date, - host->status_rec_date, - host->status_last_error, - host->min_time, - host->max_time, - host->cur_time, - host->avg_time, - host->total_polls, - host->failed_polls, - host->availability, - host->snmp_sysDescr, - host->snmp_sysObjectID, - host->snmp_sysUpTimeInstance, - host->snmp_sysContact, - host->snmp_sysName, - host->snmp_sysLocation, - host->id); - - db_insert(&mysql, update_sql); + if (!ignore_sysinfo) { + if (host->ignore_host != TRUE) { + snprintf(update_sql, BIG_BUFSIZE, "UPDATE host " + "SET status='%i', status_event_count='%i', status_fail_date='%s'," + " status_rec_date='%s', status_last_error='%s', min_time='%f'," + " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i'," + " failed_polls='%i', availability='%.4f', snmp_sysDescr='%s', " + " snmp_sysObjectID='%s', snmp_sysUpTimeInstance='%u', " + " snmp_sysContact='%s', snmp_sysName='%s', snmp_sysLocation='%s' " + "WHERE id='%i'", + host->status, + host->status_event_count, + host->status_fail_date, + host->status_rec_date, + host->status_last_error, + host->min_time, + host->max_time, + host->cur_time, + host->avg_time, + host->total_polls, + host->failed_polls, + host->availability, + host->snmp_sysDescr, + host->snmp_sysObjectID, + host->snmp_sysUpTimeInstance, + host->snmp_sysContact, + host->snmp_sysName, + host->snmp_sysLocation, + host->id); + } else { + snprintf(update_sql, BIG_BUFSIZE, "UPDATE host " + "SET status='%i', status_event_count='%i', status_fail_date='%s'," + " status_rec_date='%s', status_last_error='%s', min_time='%f'," + " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i'," + " failed_polls='%i', availability='%.4f' " + "WHERE id='%i'", + host->status, + host->status_event_count, + host->status_fail_date, + host->status_rec_date, + host->status_last_error, + host->min_time, + host->max_time, + host->cur_time, + host->avg_time, + host->total_polls, + host->failed_polls, + host->availability, + host->id); + } + } else { + snprintf(update_sql, BIG_BUFSIZE, "UPDATE host " + "SET status='%i', status_event_count='%i', status_fail_date='%s'," + " status_rec_date='%s', status_last_error='%s', min_time='%f'," + " max_time='%f', cur_time='%f', avg_time='%f', total_polls='%i'," + " failed_polls='%i', availability='%.4f' " + "WHERE id='%i'", + host->status, + host->status_event_count, + host->status_fail_date, + host->status_rec_date, + host->status_last_error, + host->min_time, + host->max_time, + host->cur_time, + host->avg_time, + host->total_polls, + host->failed_polls, + host->availability, + host->id); + } + + db_insert(&mysql, LOCAL, update_sql); } } else { - SPINE_LOG(("Device[%i] TH[%i] ERROR: MySQL Returned a Null Device Result", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: MySQL Returned a Null Device Result", host->id, host_thread)); num_rows = 0; host->ignore_host = TRUE; } @@ -606,16 +673,18 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* do the reindex check for this host if not script based */ if ((!host->ignore_host) && (host_id)) { - if ((result = db_query(&mysql, query4)) != 0) { + if ((result = db_query(&mysql, LOCAL, query4)) != 0) { num_rows = mysql_num_rows(result); if (num_rows > 0) { if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'", host->id, host_thread, num_rows, host->hostname)); + SPINE_LOG(("Device[%i] HT[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'", host->id, host_thread, num_rows, host->hostname)); } else { - SPINE_LOG_DEBUG(("Device[%i] TH[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'", host->id, host_thread, num_rows, host->hostname)); + SPINE_LOG_DEBUG(("Device[%i] HT[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'", host->id, host_thread, num_rows, host->hostname)); } + // Cache uptime in case we need it again + sysUptime[0] = '\0'; while ((row = mysql_fetch_row(result))) { assert_fail = FALSE; reindex_err = FALSE; @@ -633,7 +702,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if (row[2] != NULL) snprintf(reindex->op, sizeof(reindex->op), "%s", row[2]); if (row[3] != NULL) { - db_escape(&mysql, reindex->assert_value, row[3]); + db_escape(&mysql, reindex->assert_value, sizeof(reindex->assert_value), row[3]); } if (row[4] != NULL) snprintf(reindex->arg1, sizeof(reindex->arg1), "%s", row[4]); @@ -650,6 +719,8 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data perform_assert = FALSE; } + poll_result = NULL; + if (perform_assert) { switch(reindex->action) { case POLLER_ACTION_SNMP: /* snmp */ @@ -660,47 +731,34 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* check to see if you are checking uptime */ if (!reindex_err) { - if (strstr(reindex->arg1, ".1.3.6.1.2.1.1.3.0")) { - if (strlen(sysUptime) > 0) { - if (!(poll_result = (char *) malloc(BUFSIZE))) { - die("ERROR: Fatal malloc error: poller.c poll_result"); - } - poll_result[0] = '\0'; - - snprintf(poll_result, BUFSIZE, "%s", sysUptime); - if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] OID: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); - } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] OID: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); - } - } else { - poll_result = snmp_get(host, reindex->arg1); - snprintf(sysUptime, BUFSIZE, "%s", poll_result); - if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] OID: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); - } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] OID: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); - } + if (strstr(reindex->arg1, ".1.3.6.1.2.1.1.3.0") && + (strlen(sysUptime) > 0)) { + if (!(poll_result = (char *) malloc(BUFSIZE))) { + die("ERROR: Fatal malloc error: poller.c poll_result"); } + poll_result[0] = '\0'; + snprintf(poll_result, BUFSIZE, "%s", sysUptime); } else { poll_result = snmp_get(host, reindex->arg1); - if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] OID: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); - } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] OID: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); - } + snprintf(sysUptime, BUFSIZE, "%s", poll_result); + } + + if (is_debug_device(host->id)) { + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE OID: %s, (assert: %s %s output: %s)", host->id, host_thread, reindex->data_query_id, reindex->arg1, reindex->assert_value, reindex->op, poll_result)); + } else { + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE OID: %s, (assert: %s %s output: %s)", host->id, host_thread, reindex->data_query_id, reindex->arg1, reindex->assert_value, reindex->op, poll_result)); } } else { - SPINE_LOG(("WARNING: Device[%i] TH[%i] DataQuery[%i] Reindex Check FAILED: No SNMP Session. If not an SNMP host, don't use Uptime Goes Backwards!", host->id, host_thread, reindex->data_query_id)); + SPINE_LOG(("WARNING: Device[%i] HT[%i] DQ[%i] Reindex Check FAILED: No SNMP Session. If not an SNMP host, don't use Uptime Goes Backwards!", host->id, host_thread, reindex->data_query_id)); } break; case POLLER_ACTION_SCRIPT: /* script (popen) */ poll_result = trim(exec_poll(host, reindex->arg1)); if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] CMD: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE CMD: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] CMD: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE CMD: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } break; @@ -708,9 +766,9 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data php_process = php_get_process(); poll_result = trim(php_cmd(reindex->arg1, php_process)); if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] SERVER: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] SERVER: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } break; @@ -722,9 +780,9 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data snprintf(poll_result, BUFSIZE, "%d", snmp_count(host, reindex->arg1)); if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i]: OID_COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE OID COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i]: OID_COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE OID COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } break; @@ -736,25 +794,29 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data snprintf(poll_result, BUFSIZE, "%d", char_count(exec_poll(host, reindex->arg1), '\n')); if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] CMD Count: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE CMD COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] CMD Count: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE CMD COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); } break; case POLLER_ACTION_PHP_SCRIPT_SERVER_COUNT: /* script (php script server); count number of lines */ - //php_process = php_get_process(); // todo not yet provided by cmd.php! - //sprintf(poll_result, "%d", char_count(php_cmd(reindex->arg1, php_process), '\n')); - //SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Recache DataQuery[%i] SERVER Count: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); if (!(poll_result = (char *) malloc(BUFSIZE))) { die("ERROR: Fatal malloc error: poller.c poll_result"); } poll_result[0] = '\0'; - SPINE_LOG(("Device[%i] TH[%i] Recache DataQuery[%i] *SKIPPING* Script Server Count: %s, (arg_num_indexes required)", host->id, host_thread, reindex->data_query_id, reindex->arg1)); + + php_process = php_get_process(); + sprintf(poll_result, "%d", char_count(php_cmd(reindex->arg1, php_process), '\n')); + if (is_debug_device(host->id)) { + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + } else { + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DQ[%i] RECACHE SERVER COUNT: %s, output: %s", host->id, host_thread, reindex->data_query_id, reindex->arg1, poll_result)); + } break; default: - SPINE_LOG(("Device[%i] TH[%i] ERROR: Unknown Assert Action!", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: Unknown Assert Action!", host->id, host_thread)); } if (!reindex_err) { @@ -766,40 +828,50 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* assume ok if host is up and result wasn't obtained */ if ((IS_UNDEFINED(poll_result)) || (STRIMATCH(poll_result, "No Such Instance"))) { if (is_debug_device(host->id) || set.spine_log_level == 2) { - SPINE_LOG(("Device[%i] TH[%i] ASSERT: '%s' .eq. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s=%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } assert_fail = FALSE; } else if ((!strcmp(reindex->op, "=")) && (strcmp(reindex->assert_value,poll_result))) { if (is_debug_device(host->id) || set.spine_log_level == 2) { - SPINE_LOG(("Device[%i] TH[%i] ASSERT: '%s' .eq. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s=%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } else { if (set.spine_log_level == 1) { errors++; } - SPINE_LOG_HIGH(("Device[%i] TH[%i] ASSERT: '%s' .eq. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s=%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } if (host_thread == 1) { snprintf(query3, BUFSIZE, "REPLACE INTO poller_command (poller_id, time, action,command) values (%i, NOW(), %i, '%i:%i')", set.poller_id, POLLER_COMMAND_REINDEX, host->id, reindex->data_query_id); - db_insert(&mysql, query3); + + if (set.mode == REMOTE_ONLINE) { + db_insert(&mysqlr, REMOTE, query3); + } else { + db_insert(&mysql, LOCAL, query3); + } } assert_fail = TRUE; previous_assert_failure = TRUE; } else if ((!strcmp(reindex->op, ">")) && (strtoll(reindex->assert_value, (char **)NULL, 10) < strtoll(poll_result, (char **)NULL, 10))) { if (is_debug_device(host->id) || set.spine_log_level == 2) { - SPINE_LOG(("Device[%i] TH[%i] ASSERT: '%s' .gt. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s>%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } else { if (set.spine_log_level == 1) { errors++; } - SPINE_LOG_HIGH(("Device[%i] TH[%i] ASSERT: '%s' .gt. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s>%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } if (host_thread == 1) { snprintf(query3, BUFSIZE, "REPLACE INTO poller_command (poller_id, time, action, command) values (%i, NOW(), %i, '%i:%i')", set.poller_id, POLLER_COMMAND_REINDEX, host->id, reindex->data_query_id); - db_insert(&mysql, query3); + + if (set.mode == REMOTE_ONLINE) { + db_insert(&mysqlr, REMOTE, query3); + } else { + db_insert(&mysql, LOCAL, query3); + } } assert_fail = TRUE; previous_assert_failure = TRUE; @@ -807,18 +879,23 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data } else if (strcmp(reindex->assert_value, "0")) { if ((!strcmp(reindex->op, "<")) && (strtoll(reindex->assert_value, (char **)NULL, 10) > strtoll(poll_result, (char **)NULL, 10))) { if (is_debug_device(host->id) || set.spine_log_level == 2) { - SPINE_LOG(("Device[%i] TH[%i] ASSERT: '%s' .lt. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s<%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } else { if (set.spine_log_level == 1) { errors++; } - SPINE_LOG_HIGH(("Device[%i] TH[%i] ASSERT: '%s' .lt. '%s' failed. Recaching host '%s', data query #%i", host->id, host_thread, reindex->assert_value, poll_result, host->hostname, reindex->data_query_id)); + SPINE_LOG(("Device[%i] HT[%i] DQ[%i] RECACHE ASSERT FAILED: '%s<%s'", host->id, host_thread, reindex->data_query_id, reindex->assert_value, poll_result)); } if (host_thread == 1) { snprintf(query3, BUFSIZE, "REPLACE INTO poller_command (poller_id, time, action, command) values (%i, NOW(), %i, '%i:%i')", set.poller_id, POLLER_COMMAND_REINDEX, host->id, reindex->data_query_id); - db_insert(&mysql, query3); + + if (set.mode == REMOTE_ONLINE) { + db_insert(&mysqlr, REMOTE, query3); + } else { + db_insert(&mysql, LOCAL, query3); + } } assert_fail = TRUE; previous_assert_failure = TRUE; @@ -831,43 +908,47 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data * the assert to fail */ if ((assert_fail) || (!strcmp(reindex->op, ">")) || (!strcmp(reindex->op, "<"))) { if (host_thread == 1) { - db_escape(&mysql, temp_poll_result, poll_result); - snprintf(query3, BUFSIZE, "UPDATE poller_reindex SET assert_value='%s' WHERE host_id='%i' AND data_query_id='%i' AND arg1='%s'", temp_poll_result, host_id, reindex->data_query_id, reindex->arg1); - db_insert(&mysql, query3); + db_escape(&mysql, temp_poll_result, sizeof(temp_poll_result), poll_result); + db_escape(&mysql, temp_arg1, sizeof(temp_arg1), reindex->arg1); + snprintf(query3, BUFSIZE, "UPDATE poller_reindex SET assert_value='%s' WHERE host_id='%i' AND data_query_id='%i' AND arg1='%s'", temp_poll_result, host_id, reindex->data_query_id, temp_arg1); + db_insert(&mysql, LOCAL, query3); } if ((assert_fail) && ((!strcmp(reindex->op, "<")) || (!strcmp(reindex->arg1,".1.3.6.1.2.1.1.3.0")))) { spike_kill = TRUE; if (is_debug_device(host->id) || set.spine_log_level == 2) { - SPINE_LOG(("Device[%i] TH[%i] NOTICE: Spike Kill in Effect for '%s'", host_id, host_thread, host->hostname)); + SPINE_LOG(("Device[%i] HT[%i] NOTICE: Spike Kill in Effect for '%s'", host_id, host_thread, host->hostname)); } else { if (set.spine_log_level == 1) { errors++; } - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] NOTICE: Spike Kill in Effect for '%s'", host_id, host_thread, host->hostname)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] NOTICE: Spike Kill in Effect for '%s'", host_id, host_thread, host->hostname)); } } } free(query3); - free(poll_result); + + if (poll_result != NULL) { + free(poll_result); + } } } } } else { if (is_debug_device(host->id)) { - SPINE_LOG(("Device[%i] TH[%i] Device has no information for recache.", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] Device has no information for recache.", host->id, host_thread)); } else { - SPINE_LOG_HIGH(("Device[%i] TH[%i] Device has no information for recache.", host->id, host_thread)); + SPINE_LOG_HIGH(("Device[%i] HT[%i] Device has no information for recache.", host->id, host_thread)); } } /* free the host result */ mysql_free_result(result); } else { - SPINE_LOG(("Device[%i] TH[%i] ERROR: Recache Query Returned Null Result!", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: RECACHE Query Returned Null Result!", host->id, host_thread)); } /* close the host snmp session, we will create again momentarily */ @@ -881,33 +962,33 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data num_rows = 0; if (set.poller_interval == 0) { /* get the number of agents */ - if ((result = db_query(&mysql, query9)) != 0) { + if ((result = db_query(&mysql, LOCAL, query9)) != 0) { num_snmp_agents = mysql_num_rows(result); mysql_free_result(result); /* get the poller items */ - if ((result = db_query(&mysql, query1)) != 0) { + if ((result = db_query(&mysql, LOCAL, query1)) != 0) { num_rows = mysql_num_rows(result); } else { - SPINE_LOG(("Device[%i] TH[%i] ERROR: Unable to Retrieve Rows due to Null Result!", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: Unable to Retrieve Rows due to Null Result!", host->id, host_thread)); } } else { - SPINE_LOG(("Device[%i] TH[%i] ERROR: Agent Count Query Returned Null Result!", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: Agent Count Query Returned Null Result!", host->id, host_thread)); } } else { /* get the number of agents */ - if ((result = db_query(&mysql, query10)) != 0) { + if ((result = db_query(&mysql, LOCAL, query10)) != 0) { num_snmp_agents = (int)mysql_num_rows(result); mysql_free_result(result); /* get the poller items */ - if ((result = db_query(&mysql, query5)) != 0) { + if ((result = db_query(&mysql, LOCAL, query5)) != 0) { num_rows = mysql_num_rows(result); } else { - SPINE_LOG(("Device[%i] TH[%i] ERROR: Unable to Retrieve Rows due to Null Result!", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: Unable to Retrieve Rows due to Null Result!", host->id, host_thread)); } } else { - SPINE_LOG(("Device[%i] TH[%i] ERROR: Agent Count Query Returned Null Result!", host->id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] ERROR: Agent Count Query Returned Null Result!", host->id, host_thread)); } } @@ -993,9 +1074,9 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* log an informative message */ if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] NOTE: There are '%i' Polling Items for this Device", host_id, host_thread, num_rows)); + SPINE_LOG(("Device[%i] HT[%i] NOTE: There are '%i' Polling Items for this Device", host_id, host_thread, num_rows)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] NOTE: There are '%i' Polling Items for this Device", host_id, host_thread, num_rows)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] NOTE: There are '%i' Polling Items for this Device", host_id, host_thread, num_rows)); } i = 0; k = 0; @@ -1036,27 +1117,27 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* some snmp data changed from poller item to poller item. therefore, poll host and store data */ if ((last_snmp_port != poller_items[i].snmp_port) || (last_snmp_version != poller_items[i].snmp_version) || - ((poller_items[i].snmp_version < 3) && + (poller_items[i].snmp_version < 3 && (!STRMATCH(last_snmp_community, poller_items[i].snmp_community))) || - ((poller_items[i].snmp_version > 2) && - (!STRMATCH(last_snmp_username, poller_items[i].snmp_username)) || + (poller_items[i].snmp_version > 2 && + ((!STRMATCH(last_snmp_username, poller_items[i].snmp_username)) || (!STRMATCH(last_snmp_password, poller_items[i].snmp_password)) || (!STRMATCH(last_snmp_auth_protocol, poller_items[i].snmp_auth_protocol)) || (!STRMATCH(last_snmp_priv_passphrase, poller_items[i].snmp_priv_passphrase)) || (!STRMATCH(last_snmp_priv_protocol, poller_items[i].snmp_priv_protocol)) || (!STRMATCH(last_snmp_context, poller_items[i].snmp_context)) || - (!STRMATCH(last_snmp_engine_id, poller_items[i].snmp_engine_id)))) { + (!STRMATCH(last_snmp_engine_id, poller_items[i].snmp_engine_id))))) { if (num_oids > 0) { snmp_get_multi(host, snmp_oids, num_oids); for (j = 0; j < num_oids; j++) { if (host->ignore_host) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname)); SET_UNDEFINED(snmp_oids[j].result); } else if (IS_UNDEFINED(snmp_oids[j].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1077,7 +1158,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data } else if ((STRIMATCH(snmp_oids[j].result, "U")) || (STRIMATCH(snmp_oids[j].result, "Nan"))) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1099,7 +1180,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* detect erroneous non-numeric result */ if (!validate_result(snmp_oids[j].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1119,9 +1200,9 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data snprintf(poller_items[snmp_oids[j].array_position].result, RESULTS_BUFFER, "%s", snmp_oids[j].result); if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); } } @@ -1159,11 +1240,11 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data for (j = 0; j < num_oids; j++) { if (host->ignore_host) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname)); SET_UNDEFINED(snmp_oids[j].result); } else if (IS_UNDEFINED(snmp_oids[j].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1184,7 +1265,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data } else if ((STRIMATCH(snmp_oids[j].result, "U")) || (STRIMATCH(snmp_oids[j].result, "Nan"))) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1206,7 +1287,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* detect erroneous non-numeric result */ if (!validate_result(snmp_oids[j].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1226,12 +1307,12 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data snprintf(poller_items[snmp_oids[j].array_position].result, RESULTS_BUFFER, "%s", snmp_oids[j].result); if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); } - if (poller_items[snmp_oids[j].array_position].result != NULL) { + if (!IS_UNDEFINED(poller_items[snmp_oids[j].array_position].result)) { /* insert a NaN in place of the actual value if the snmp agent restarts */ if ((spike_kill) && (!strstr(poller_items[snmp_oids[j].array_position].result,":"))) { SET_UNDEFINED(poller_items[snmp_oids[j].array_position].result); @@ -1258,7 +1339,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if (IS_UNDEFINED(poll_result)) { SET_UNDEFINED(poller_items[i].result); if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SCRIPT: %s, output: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); } else if (set.spine_log_level == 1) { @@ -1281,7 +1362,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* detect erroneous result. can be non-numeric */ if (!validate_result(poller_items[i].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SCRIPT: %s, output: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); } else if (set.spine_log_level == 1) { @@ -1300,12 +1381,12 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if (poll_result) free(poll_result); if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); } - if (poller_items[i].result != NULL) { + if (!IS_UNDEFINED(poller_items[i].result)) { /* insert a NaN in place of the actual value if the snmp agent restarts */ if ((spike_kill) && (!strstr(poller_items[i].result,":"))) { SET_UNDEFINED(poller_items[i].result); @@ -1322,7 +1403,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if (IS_UNDEFINED(poll_result)) { SET_UNDEFINED(poller_items[i].result); if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SCRIPT: %s, output: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); } else if (set.spine_log_level == 1) { @@ -1345,7 +1426,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* detect erroneous result. can be non-numeric */ if (!validate_result(poller_items[i].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SCRIPT: %s, output: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SCRIPT: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1, poller_items[i].result)); } else if (set.spine_log_level == 1) { @@ -1364,12 +1445,12 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data if (poll_result) free(poll_result); if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] SS[%i] SERVER: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, php_process, poller_items[i].arg1, poller_items[i].result)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] SS[%i] SERVER: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, php_process, poller_items[i].arg1, poller_items[i].result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] DS[%i] SS[%i] SERVER: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, php_process, poller_items[i].arg1, poller_items[i].result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] SS[%i] SERVER: %s, output: %s", host_id, host_thread, poller_items[i].local_data_id, php_process, poller_items[i].arg1, poller_items[i].result)); } - if (poller_items[i].result != NULL) { + if (IS_UNDEFINED(poller_items[i].result)) { /* insert a NaN in place of the actual value if the snmp agent restarts */ if ((spike_kill) && (!STRIMATCH(poller_items[i].result,":"))) { SET_UNDEFINED(poller_items[i].result); @@ -1378,7 +1459,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data break; default: /* unknown action, generate error */ - SPINE_LOG(("Device[%i] TH[%i] DS[%i] ERROR: Unknown Poller Action: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] ERROR: Unknown Poller Action: %s", host_id, host_thread, poller_items[i].local_data_id, poller_items[i].arg1)); break; } @@ -1393,11 +1474,11 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data for (j = 0; j < num_oids; j++) { if (host->ignore_host) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] WARNING: SNMP timeout detected [%i ms], ignoring host '%s'", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_timeout, host->hostname)); SET_UNDEFINED(snmp_oids[j].result); } else if (IS_UNDEFINED(snmp_oids[j].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1418,7 +1499,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data } else if ((STRIMATCH(snmp_oids[j].result, "U")) || (STRIMATCH(snmp_oids[j].result, "Nan"))) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1440,7 +1521,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* detect erroneous non-numeric result */ if (!validate_result(snmp_oids[j].result)) { if (set.spine_log_level == 2) { - SPINE_LOG(("WARNING: Invalid Response, Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", + SPINE_LOG(("WARNING: Invalid Response, Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, snmp_oids[j].result)); @@ -1460,12 +1541,12 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data snprintf(poller_items[snmp_oids[j].array_position].result, RESULTS_BUFFER, "%s", snmp_oids[j].result); if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); + SPINE_LOG(("Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] DS[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s", host_id, host_thread, poller_items[snmp_oids[j].array_position].local_data_id, host->snmp_version, host->hostname, poller_items[snmp_oids[j].array_position].rrd_name, poller_items[snmp_oids[j].array_position].arg1, poller_items[snmp_oids[j].array_position].result)); } - if (poller_items[snmp_oids[j].array_position].result != NULL) { + if (!IS_UNDEFINED(poller_items[snmp_oids[j].array_position].result)) { /* insert a NaN in place of the actual value if the snmp agent restarts */ if ((spike_kill) && (!strstr(poller_items[snmp_oids[j].array_position].result,":"))) { SET_UNDEFINED(poller_items[snmp_oids[j].array_position].result); @@ -1492,6 +1573,15 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data strncat(query12, query11, strlen(query11)); } + int mode; + if (set.mode == REMOTE_ONLINE) { + mysqlt = mysqlr; + mode = REMOTE; + } else { + mysqlt = mysql; + mode = LOCAL; + } + i = 0; while (i < rows_processed) { snprintf(result_string, RESULTS_BUFFER+SMALL_BUFSIZE, " (%i,'%s','%s','%s')", @@ -1508,7 +1598,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data strncat(query3, posuffix, strlen(posuffix)); /* insert the record */ - db_insert(&mysql, query3); + db_insert(&mysqlt, mode, query3); /* re-initialize the query buffer */ query3[0] = '\0'; @@ -1519,7 +1609,7 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* append the suffix */ strncat(query12, posuffix, strlen(posuffix)); - db_insert(&mysql, query12); + db_insert(&mysqlt, mode, query12); query12[0] = '\0'; strncat(query12, query11, strlen(query11)); @@ -1556,14 +1646,14 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data strncat(query3, posuffix, strlen(posuffix)); /* insert records into database */ - db_insert(&mysql, query3); + db_insert(&mysqlt, mode, query3); /* insert the record for boost */ if (set.boost_redirect && set.boost_enabled) { /* append the suffix */ strncat(query12, posuffix, strlen(posuffix)); - db_insert(&mysql, query12); + db_insert(&mysqlt, mode, query12); } } @@ -1590,33 +1680,37 @@ void poll_host(int host_id, int host_thread, int last_host_thread, int host_data /* update poller_items table for next polling interval */ if (host_thread == last_host_thread) { - db_query(&mysql, query6); + db_query(&mysql, LOCAL, query6); } /* record the polling time for the device */ poll_time = get_time_as_double() - poll_time; if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] Total Time: %5.2g Seconds", host_id, host_thread, poll_time)); + SPINE_LOG(("Device[%i] HT[%i] Total Time: %5.2g Seconds", host_id, host_thread, poll_time)); } else { - SPINE_LOG_MEDIUM(("Device[%i] TH[%i] Total Time: %5.2g Seconds", host_id, host_thread, poll_time)); + SPINE_LOG_MEDIUM(("Device[%i] HT[%i] Total Time: %5.2g Seconds", host_id, host_thread, poll_time)); } /* record the total time for the host */ poll_time = get_time_as_double(); query1[0] = '\0'; snprintf(query1, BUFSIZE, "UPDATE host SET polling_time=%.3f - %.3f WHERE id=%i", poll_time, host_time_double, host_id); - db_query(&mysql, query1); + db_query(&mysql, LOCAL, query1); - mysql_close(&mysql); + db_disconnect(&mysql); + + if (set.mode == REMOTE_ONLINE) { + db_disconnect(&mysqlr); + } #ifndef OLD_MYSQL mysql_thread_end(); #endif if (is_debug_device(host_id)) { - SPINE_LOG(("Device[%i] TH[%i] DEBUG: HOST COMPLETE: About to Exit Device Polling Thread Function", host_id, host_thread)); + SPINE_LOG(("Device[%i] HT[%i] DEBUG: HOST COMPLETE: About to Exit Device Polling Thread Function", host_id, host_thread)); } else { - SPINE_LOG_DEBUG(("Device[%i] TH[%i] DEBUG: HOST COMPLETE: About to Exit Device Polling Thread Function", host_id, host_thread)); + SPINE_LOG_DEBUG(("Device[%i] HT[%i] DEBUG: HOST COMPLETE: About to Exit Device Polling Thread Function", host_id, host_thread)); } if (error_len > 0) { @@ -1675,10 +1769,6 @@ int is_multipart_output(char *result) { void get_system_information(host_t *host, MYSQL *mysql, int system) { char *poll_result; - if (!(poll_result = (char *) malloc(BUFSIZE))) { - die("ERROR: Fatal malloc error: poller.c poll_result"); - } - if (set.mibs || system) { if (is_debug_device(host->id)) { SPINE_LOG(("Updating Full System Information Table")); @@ -1688,32 +1778,38 @@ void get_system_information(host_t *host, MYSQL *mysql, int system) { poll_result = snmp_get(host, ".1.3.6.1.2.1.1.1.0"); if (poll_result) { - db_escape(mysql, host->snmp_sysDescr, poll_result); + db_escape(mysql, host->snmp_sysDescr, sizeof(host->snmp_sysDescr), poll_result); } + free(poll_result); poll_result = snmp_get(host, ".1.3.6.1.2.1.1.2.0"); if (poll_result) { - db_escape(mysql, host->snmp_sysObjectID, poll_result); + db_escape(mysql, host->snmp_sysObjectID, sizeof(host->snmp_sysObjectID), poll_result); + free(poll_result); } poll_result = snmp_get(host, ".1.3.6.1.2.1.1.3.0"); if (poll_result) { host->snmp_sysUpTimeInstance = atoi(poll_result); + free(poll_result); } poll_result = snmp_get(host, ".1.3.6.1.2.1.1.4.0"); if (poll_result) { - db_escape(mysql, host->snmp_sysContact, poll_result); + db_escape(mysql, host->snmp_sysContact, sizeof(host->snmp_sysContact), poll_result); + free(poll_result); } poll_result = snmp_get(host, ".1.3.6.1.2.1.1.5.0"); if (poll_result) { - db_escape(mysql, host->snmp_sysName, poll_result); + db_escape(mysql, host->snmp_sysName, sizeof(host->snmp_sysName), poll_result); + free(poll_result); } poll_result = snmp_get(host, ".1.3.6.1.2.1.1.6.0"); if (poll_result) { - db_escape(mysql, host->snmp_sysLocation, poll_result); + db_escape(mysql, host->snmp_sysLocation, sizeof(host->snmp_sysLocation), poll_result); + free(poll_result); } } else { if (is_debug_device(host->id)) { @@ -1725,10 +1821,9 @@ void get_system_information(host_t *host, MYSQL *mysql, int system) { poll_result = snmp_get(host, ".1.3.6.1.2.1.1.3.0"); if (poll_result) { host->snmp_sysUpTimeInstance = atoi(poll_result); + free(poll_result); } } - - free(poll_result); } /*! \fn int validate_result(char *result) diff --git a/snmp.c b/snmp.c index 31d63ce6..27b5b3e7 100644 --- a/snmp.c +++ b/snmp.c @@ -68,6 +68,7 @@ void snmp_spine_init(void) { netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS, 1); #endif +setenv("MIBS", "", 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE, 1); @@ -81,7 +82,7 @@ netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE SPINE_LOG_DEBUG(("DEBUG: SNMP Header Version is %s", PACKAGE_VERSION)); SPINE_LOG_DEBUG(("DEBUG: SNMP Library Version is %s", netsnmp_get_version())); - if(STRMATCH(PACKAGE_VERSION,netsnmp_get_version())) { + if (STRMATCH(PACKAGE_VERSION,netsnmp_get_version())) { init_snmp("spine"); } else { /* report the error and quit spine */ @@ -126,7 +127,8 @@ void *snmp_host_init(int host_id, char *hostname, int snmp_version, char *snmp_c snmp_sess_init(&session); /* Bind to snmp_clientaddr if specified */ - if (NULL != set.snmp_clientaddr && strlen(set.snmp_clientaddr) > 0) { + size_t len = strlen(set.snmp_clientaddr); + if (len > 0 && len <= SMALL_BUFSIZE) { #if SNMP_LOCALNAME == 1 session.localname = strdup(set.snmp_clientaddr); #endif @@ -201,8 +203,8 @@ void *snmp_host_init(int host_id, char *hostname, int snmp_version, char *snmp_c } if (snmp_engine_id && strlen(snmp_engine_id)) { - session.contextEngineID = snmp_engine_id; - session.contextEngineIDLen = strlen(session.contextEngineID); + session.contextEngineID = (unsigned char*) snmp_engine_id; + session.contextEngineIDLen = strlen(snmp_engine_id); } session.securityAuthKeyLen = USM_AUTH_KU_LEN; @@ -362,9 +364,9 @@ char *snmp_get(host_t *current_host, char *snmp_oid) { if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; - snmp_snprint_value(temp_result, RESULTS_BUFFER, vars->name, vars->name_length, vars); + snprint_value(temp_result, RESULTS_BUFFER, vars->name, vars->name_length, vars); - snprintf(result_string, RESULTS_BUFFER, "%s", trim(temp_result)); + snprint_asciistring(result_string, RESULTS_BUFFER, temp_result, strlen(temp_result)); } } } @@ -441,9 +443,9 @@ char *snmp_getnext(host_t *current_host, char *snmp_oid) { vars = response->variables; if (vars != NULL) { - snmp_snprint_value(temp_result, RESULTS_BUFFER, vars->name, vars->name_length, vars); + snprint_value(temp_result, RESULTS_BUFFER, vars->name, vars->name_length, vars); - snprintf(result_string, RESULTS_BUFFER, "%s", trim(strip_alpha(temp_result))); + snprint_asciistring(result_string, RESULTS_BUFFER, temp_result, strlen(temp_result)); } else { SET_UNDEFINED(result_string); status = STAT_ERROR; @@ -667,7 +669,7 @@ void snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) for (i = 0; i < num_oids && vars; i++) { if (!IS_UNDEFINED(snmp_oids[i].result)) { - snmp_snprint_value(temp_result, RESULTS_BUFFER, vars->name, vars->name_length, vars); + snprint_value(temp_result, RESULTS_BUFFER, vars->name, vars->name_length, vars); snprintf(snmp_oids[i].result, RESULTS_BUFFER, "%s", trim(strip_alpha(temp_result))); diff --git a/spine.c b/spine.c index 53f2dbd1..03edcb98 100644 --- a/spine.c +++ b/spine.c @@ -111,6 +111,7 @@ int *debug_devices; static char *getarg(char *opt, char ***pargv); static void display_help(int only_version); +void poller_push_data_to_main(); #ifdef HAVE_LCAP /* This patch is adapted (copied) patch for ntpd from Jarno Huuskonen and @@ -190,7 +191,7 @@ int main(int argc, char *argv[]) { int num_rows = 0; int device_counter = 0; int valid_conf_file = FALSE; - char querybuf[BIG_BUFSIZE], *qp = querybuf; + char querybuf[MEGA_BUFSIZE], *qp = querybuf; char *host_time = NULL; double host_time_double = 0; int itemsPT = 0; @@ -210,7 +211,9 @@ int main(int argc, char *argv[]) { pthread_attr_t attr; int* ids = NULL; + int mode = REMOTE; MYSQL mysql; + MYSQL mysqlr; MYSQL_RES *result = NULL; MYSQL_RES *tresult = NULL; MYSQL_ROW mysql_row; @@ -218,6 +221,7 @@ int main(int argc, char *argv[]) { int host_id = 0; int i; int thread_status = 0; + int total_items = 0; int change_host = TRUE; int current_thread; @@ -241,13 +245,13 @@ int main(int argc, char *argv[]) { /* detect and compensate for stdin/stderr ttys */ if (!isatty(fileno(stdout))) { set.stdout_notty = TRUE; - }else{ + } else { set.stdout_notty = FALSE; } if (!isatty(fileno(stderr))) { set.stderr_notty = TRUE; - }else{ + } else { set.stderr_notty = FALSE; } @@ -265,6 +269,7 @@ int main(int argc, char *argv[]) { /* set the default exit code */ set.exit_code = 0; + set.exit_size = 0; /* get static defaults for system */ config_defaults(); @@ -390,7 +395,7 @@ int main(int argc, char *argv[]) { if (*value) { *value++ = '\0'; - }else{ + } else { die("ERROR: -O requires setting:value"); } @@ -449,7 +454,7 @@ int main(int argc, char *argv[]) { if (set.log_level == POLLER_VERBOSITY_DEBUG) { printf("NOTE: The Shell Command Exists in the current directory\n"); } - }else{ + } else { set.cygwinshloc = 1; if (set.log_level == POLLER_VERBOSITY_DEBUG) { printf("NOTE: The Shell Command Exists in the /bin directory\n"); @@ -471,10 +476,10 @@ int main(int argc, char *argv[]) { if (conf_file) { if ((read_spine_config(conf_file)) < 0) { die("ERROR: Could not read config file: %s", conf_file); - }else{ + } else { valid_conf_file = TRUE; } - }else{ + } else { if (!(conf_file = calloc(CONFIG_PATHS, BUFSIZE))) { die("ERROR: Fatal malloc error: spine.c conf_file!"); } @@ -496,7 +501,7 @@ int main(int argc, char *argv[]) { if (valid_conf_file) { /* read settings table from the database to further establish environment */ read_config_options(); - }else{ + } else { die("FATAL: Unable to read configuration file!"); } @@ -516,20 +521,27 @@ int main(int argc, char *argv[]) { token = strtok(NULL, ","); i++; } - }else{ + } else { debug_devices[0] = '\0'; } /* connect to database */ - db_connect(set.dbdb, &mysql); + db_connect(LOCAL, &mysql); + + if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) { + db_connect(REMOTE, &mysqlr); + mode = REMOTE; + } else { + mode = LOCAL; + } /* Since MySQL 5.7 the sql_mode defaults are too strict for cacti */ - db_insert(&mysql, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); - db_insert(&mysql, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); if (set.log_level == POLLER_VERBOSITY_DEBUG) { SPINE_LOG_DEBUG(("Version %s starting", VERSION)); - }else{ + } else { if (!set.stdout_notty) { printf("SPINE: Version %s starting\n", VERSION); } @@ -540,7 +552,7 @@ int main(int argc, char *argv[]) { if (set.log_level == POLLER_VERBOSITY_DEBUG) { SPINE_LOG(("DEBUG: MySQL is Thread Safe!")); } - }else{ + } else { SPINE_LOG(("WARNING: MySQL is NOT Thread Safe!")); } @@ -565,10 +577,10 @@ int main(int argc, char *argv[]) { } /* determine if the poller_id field exists in the host table */ - result = db_query(&mysql, "SHOW COLUMNS FROM host LIKE 'poller_id'"); + result = db_query(&mysql, LOCAL, "SHOW COLUMNS FROM host LIKE 'poller_id'"); if (mysql_num_rows(result)) { set.poller_id_exists = TRUE; - }else{ + } else { set.poller_id_exists = FALSE; if (set.poller_id > 0) { @@ -578,30 +590,30 @@ int main(int argc, char *argv[]) { db_free_result(result); /* determine if the device_threads field exists in the host table */ - result = db_query(&mysql, "SHOW COLUMNS FROM host LIKE 'device_threads'"); + result = db_query(&mysql, LOCAL, "SHOW COLUMNS FROM host LIKE 'device_threads'"); if (mysql_num_rows(result)) { set.device_threads_exists = TRUE; - }else{ + } else { set.device_threads_exists = FALSE; } db_free_result(result); if (set.device_threads_exists) { SPINE_LOG_MEDIUM(("NOTE: Spine will support multithread device polling.")); - }else{ + } else { SPINE_LOG_MEDIUM(("NOTE: Spine did not detect multithreaded device polling.")); } /* obtain the list of hosts to poll */ if (set.device_threads_exists) { qp += sprintf(qp, "SELECT id, device_threads FROM host"); - }else{ + } else { qp += sprintf(qp, "SELECT id, '1' as device_threads FROM host"); } qp += sprintf(qp, " WHERE disabled=''"); if (!strlen(set.host_id_list)) { qp += append_hostrange(qp, "id"); /* AND id BETWEEN a AND b */ - }else{ + } else { qp += sprintf(qp, " AND id IN(%s)", set.host_id_list); } if (set.poller_id_exists) { @@ -609,10 +621,10 @@ int main(int argc, char *argv[]) { } qp += sprintf(qp, " ORDER BY polling_time DESC"); - result = db_query(&mysql, querybuf); + result = db_query(&mysql, LOCAL, querybuf); if (set.poller_id == 0) { num_rows = mysql_num_rows(result) + 1; /* add 1 for host = 0 */ - }else{ + } else { num_rows = mysql_num_rows(result); /* pollerid 0 takes care of not host based data sources */ } @@ -626,7 +638,11 @@ int main(int argc, char *argv[]) { /* mark the spine process as started */ snprintf(querybuf, BIG_BUFSIZE, "INSERT INTO poller_time (poller_id, pid, start_time, end_time) VALUES (%i, %i, NOW(), '0000-00-00 00:00:00')", set.poller_id, getpid()); - db_insert(&mysql, querybuf); + if (mode == REMOTE) { + db_insert(&mysqlr, REMOTE, querybuf); + } else { + db_insert(&mysql, LOCAL, querybuf); + } /* initialize threads and mutexes */ pthread_attr_init(&attr); @@ -661,7 +677,7 @@ int main(int argc, char *argv[]) { if (set.poller_id == 0) { host_id = 0; change_host = FALSE; - }else{ + } else { change_host = TRUE; } @@ -672,17 +688,29 @@ int main(int argc, char *argv[]) { host_id = atoi(mysql_row[0]); device_threads = atoi(mysql_row[1]); current_thread = 1; - }else{ + } else { current_thread++; } + /* adjust device threads in cases where the host does not have sufficient data sources */ + snprintf(querybuf, BIG_BUFSIZE, "SELECT COUNT(*) FROM poller_item WHERE host_id=%i AND rrd_next_step <=0", host_id); + tresult = db_query(&mysql, LOCAL, querybuf); + mysql_row = mysql_fetch_row(tresult); + + total_items = atoi(mysql_row[0]); + db_free_result(tresult); + + if (total_items < device_threads) { + device_threads = total_items; + } + change_host = (current_thread >= device_threads) ? TRUE : FALSE; /* determine how many items will be polled per thread */ if (device_threads > 1) { if (current_thread == 1) { snprintf(querybuf, BIG_BUFSIZE, "SELECT CEIL(COUNT(*)/%i) FROM poller_item WHERE host_id=%i AND rrd_next_step <=0", device_threads, host_id); - tresult = db_query(&mysql, querybuf); + tresult = db_query(&mysql, LOCAL, querybuf); mysql_row = mysql_fetch_row(tresult); itemsPT = atoi(mysql_row[0]); @@ -692,7 +720,7 @@ int main(int argc, char *argv[]) { host_time = get_host_poll_time(); host_time_double = get_time_as_double(); } - }else{ + } else { itemsPT = 0; if (host_time) free(host_time); host_time = get_host_poll_time(); @@ -719,7 +747,7 @@ int main(int argc, char *argv[]) { SPINE_LOG(("ERROR: Spine Timed Out While Processing Devices Internal")); canexit = TRUE; break; - }else if (errno == EINTR) { + } else if (errno == EINTR) { usleep(10000); goto retry1; } @@ -793,16 +821,25 @@ int main(int argc, char *argv[]) { /* tell Spine that it is now parent */ set.parent_fork = SPINE_PARENT; + /* push data back to the main server */ + if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) { + poller_push_data_to_main(); + } + /* print out stats */ gettimeofday(&now, NULL); /* update the db for |data_time| on graphs */ if (set.poller_id == 1) { - db_insert(&mysql, "REPLACE INTO settings (name,value) VALUES ('date',NOW())"); + db_insert(&mysql, LOCAL, "REPLACE INTO settings (name,value) VALUES ('date',NOW())"); } snprintf(querybuf, BIG_BUFSIZE, "UPDATE poller_time SET end_time=NOW() WHERE poller_id=%i AND pid=%i", set.poller_id, getpid()); - db_insert(&mysql, querybuf); + if (mode == REMOTE) { + db_insert(&mysqlr, REMOTE, querybuf); + } else { + db_insert(&mysql, LOCAL, querybuf); + } /* cleanup and exit program */ pthread_attr_destroy(&attr); @@ -826,7 +863,11 @@ int main(int argc, char *argv[]) { /* close mysql */ db_free_result(result); - mysql_close(&mysql); + db_disconnect(&mysql); + + if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) { + db_disconnect(&mysqlr); + } SPINE_LOG_DEBUG(("DEBUG: MYSQL Free & Close Completed")); @@ -840,7 +881,7 @@ int main(int argc, char *argv[]) { if (set.log_level >= POLLER_VERBOSITY_MEDIUM) { SPINE_LOG(("Time: %.4f s, Threads: %i, Devices: %i", (end_time - begin_time), set.threads, num_rows)); - }else{ + } else { /* provide output if running from command line */ if (!set.stdout_notty) { fprintf(stdout,"SPINE: Time: %.4f s, Threads: %i, Devices: %i\n", (end_time - begin_time), set.threads, num_rows); @@ -895,7 +936,7 @@ static void display_help(int only_version) { "database, but they can be overridden with the --option=S:V", "parameter.", "", - "Spine is distributed under the Terms of the GNU Lessor", + "Spine is distributed under the Terms of the GNU Lesser", "General Public License Version 2.1. (http://www.gnu.org/licenses/lgpl.txt)", "For more information, see http://www.cacti.net", diff --git a/spine.conf.dist b/spine.conf.dist index 0ab15c92..b456932e 100644 --- a/spine.conf.dist +++ b/spine.conf.dist @@ -39,14 +39,23 @@ # | RDB_Pass The remote database password. | # +-------------------------------------------------------------------------+ -DB_Host localhost -DB_Database cacti -DB_User cactiuser -DB_Pass cactiuser -DB_Port 3306 +DB_Host localhost +DB_Database cacti +DB_User cactiuser +DB_Pass cactiuser +DB_Port 3306 +#DB_UseSSL 0 +#RDB_SSL_Key +#RDB_SSL_Cert +#RDB_SSL_CA + +RDB_Host localhost +RDB_Database cacti +RDB_User cactiuser +RDB_Pass cactiuser +RDB_Port 3306 +#RDB_UseSSL 0 +#RDB_SSL_Key +#RDB_SSL_Cert +#RDB_SSL_CA -RDB_Host localhost -RDB_Database cacti -RDB_User cactiuser -RDB_Pass cactiuser -RDB_Port 3306 diff --git a/spine.h b/spine.h index 6f371eea..137c0fb3 100644 --- a/spine.h +++ b/spine.h @@ -42,6 +42,9 @@ #define TRUE 1 #endif +#define LOCAL 0 +#define REMOTE 1 + #ifndef __GNUC__ # define __attribute__(x) /* NOTHING */ #endif @@ -51,6 +54,10 @@ #define DISABLE_STDERR #endif +#ifdef HAS_EXECINFO_H +#include +#endif + /* if a host is legal, return TRUE */ #define HOSTID_DEFINED(x) ((x) >= 0) @@ -124,8 +131,10 @@ #define MEDIUM_BUFSIZE 512 #define BUFSIZE 1024 #define DBL_BUFSIZE 2048 +#define LRG_BUFSIZE 8096 #define BIG_BUFSIZE 65535 #define MEGA_BUFSIZE 1024000 +#define HUGE_BUFSIZE 2048000 #define LOGSIZE 4096 #define BITSINBYTE 8 #define THIRTYTWO 4294967295ul @@ -336,11 +345,16 @@ typedef struct config_struct { int end_host_id; char host_id_list[BIG_BUFSIZE]; /* database connection information */ - char dbhost[SMALL_BUFSIZE]; - char dbdb[SMALL_BUFSIZE]; - char dbuser[SMALL_BUFSIZE]; - char dbpass[SMALL_BUFSIZE]; - unsigned int dbport; + char db_host[SMALL_BUFSIZE]; + char db_db[SMALL_BUFSIZE]; + char db_user[SMALL_BUFSIZE]; + char db_pass[SMALL_BUFSIZE]; + int db_ssl; + char db_ssl_key[BIG_BUFSIZE]; + char db_ssl_cert[BIG_BUFSIZE]; + char db_ssl_ca[BIG_BUFSIZE]; + int d_b; + unsigned int db_port; int dbversion; /* path information */ char path_logfile[SMALL_BUFSIZE]; @@ -376,14 +390,21 @@ typedef struct config_struct { int php_current_server; /* Exit code if we need it */ int exit_code; + size_t exit_size; + void* exit_stack[10]; + /* Remote polling mode */ int mode; /* remote database connection information */ - char rdbhost[SMALL_BUFSIZE]; - char rdbdb[SMALL_BUFSIZE]; - char rdbuser[SMALL_BUFSIZE]; - char rdbpass[SMALL_BUFSIZE]; - unsigned int rdbport; + char rdb_host[SMALL_BUFSIZE]; + char rdb_db[SMALL_BUFSIZE]; + char rdb_user[SMALL_BUFSIZE]; + char rdb_pass[SMALL_BUFSIZE]; + int rdb_ssl; + char rdb_ssl_key[BIG_BUFSIZE]; + char rdb_ssl_cert[BIG_BUFSIZE]; + char rdb_ssl_ca[BIG_BUFSIZE]; + unsigned int rdb_port; int rdbversion; } config_t; @@ -484,12 +505,12 @@ typedef struct host_struct { int snmp_port; int snmp_timeout; int snmp_retries; - char snmp_sysDescr[300]; + char snmp_sysDescr[600]; char snmp_sysObjectID[160]; u_int snmp_sysUpTimeInstance; char snmp_sysContact[300]; char snmp_sysName[300]; - char snmp_sysLocation[300]; + char snmp_sysLocation[600]; int max_oids; int availability_method; int ping_method; @@ -500,7 +521,7 @@ typedef struct host_struct { int status_event_count; char status_fail_date[40]; char status_rec_date[40]; - char status_last_error[SMALL_BUFSIZE]; + char status_last_error[BUFSIZE]; double min_time; double max_time; double cur_time; diff --git a/sql.c b/sql.c index df03fe78..34a8c51e 100644 --- a/sql.c +++ b/sql.c @@ -34,9 +34,10 @@ #include "common.h" #include "spine.h" -/*! \fn int db_insert(MYSQL *mysql, const char *query) +/*! \fn int db_insert(MYSQL *mysql, int type, const char *query) * \brief inserts a row or rows in a database table. * \param mysql the database connection object + * \param type the database to connect to local or remote * \param query the database query to execute * * Unless the SQL_readonly boolean is set to TRUE, the function will execute @@ -45,16 +46,16 @@ * \return TRUE if successful, or FALSE if not. * */ -int db_insert(MYSQL *mysql, const char *query) { +int db_insert(MYSQL *mysql, int type, const char *query) { int error; int error_count = 0; - char query_frag[BUFSIZE]; + char query_frag[LRG_BUFSIZE]; /* save a fragment just in case */ - snprintf(query_frag, BUFSIZE, "%s", query); + snprintf(query_frag, LRG_BUFSIZE, "%s", query); /* show the sql query */ - SPINE_LOG_DEVDBG(("DEVDBG: SQL:'%s'", query_frag)); + SPINE_LOG_DEVDBG(("DEVDBG: SQL:%s", query_frag)); while(1) { if (set.SQL_readonly == FALSE) { @@ -76,10 +77,10 @@ int db_insert(MYSQL *mysql, const char *query) { } continue; - }else if (error == 2006 && errno == EINTR) { + } else if (error == 2006 && errno == EINTR) { db_disconnect(mysql); usleep(50000); - db_connect(set.dbdb, mysql); + db_connect(type, mysql); error_count++; if (error_count > 30) { @@ -87,14 +88,14 @@ int db_insert(MYSQL *mysql, const char *query) { } continue; - }else{ + } else { SPINE_LOG(("ERROR: SQL Failed! Error:'%i', Message:'%s', SQL Fragment:'%s'", error, mysql_error(mysql), query_frag)); return FALSE; } - }else{ + } else { return TRUE; } - }else{ + } else { return TRUE; } } @@ -110,19 +111,19 @@ int db_insert(MYSQL *mysql, const char *query) { * \return MYSQL_RES a MySQL result structure * */ -MYSQL_RES *db_query(MYSQL *mysql, const char *query) { +MYSQL_RES *db_query(MYSQL *mysql, int type, const char *query) { MYSQL_RES *mysql_res = 0; int error = 0; int error_count = 0; - char query_frag[BUFSIZE]; + char query_frag[LRG_BUFSIZE]; /* save a fragment just in case */ - snprintf(query_frag, BUFSIZE, "%s", query); + snprintf(query_frag, LRG_BUFSIZE, "%s", query); /* show the sql query */ - SPINE_LOG_DEVDBG(("DEVDBG: SQL:'%s'", query_frag)); + SPINE_LOG_DEVDBG(("DEVDBG: SQL:%s", query_frag)); while (1) { if (mysql_query(mysql, query)) { @@ -144,10 +145,10 @@ MYSQL_RES *db_query(MYSQL *mysql, const char *query) { } continue; - }else if (error == 2006 && errno == EINTR) { + } else if (error == 2006 && errno == EINTR) { db_disconnect(mysql); usleep(50000); - db_connect(set.dbdb, mysql); + db_connect(type, mysql); error_count++; if (error_count > 30) { @@ -155,10 +156,10 @@ MYSQL_RES *db_query(MYSQL *mysql, const char *query) { } continue; - }else{ + } else { die("FATAL: MySQL Error:'%i', Message:'%s'", error, mysql_error(mysql)); } - }else{ + } else { mysql_res = mysql_store_result(mysql); break; @@ -178,7 +179,7 @@ MYSQL_RES *db_query(MYSQL *mysql, const char *query) { * fails more than 20 times, the function will fail and Spine will terminate. * */ -void db_connect(const char *database, MYSQL *mysql) { +void db_connect(int type, MYSQL *mysql) { int tries; int timeout; int rtimeout; @@ -195,35 +196,29 @@ void db_connect(const char *database, MYSQL *mysql) { * and if it is a socket file, setup mysql to use it. */ if (set.poller_id > 1) { - if (set.mode == REMOTE_OFFLINE || set.mode == REMOTE_RECOVERY) { - if ((hostname = strdup(set.dbhost)) == NULL) { - die("FATAL: malloc(): strdup() failed"); - } + if (type == LOCAL) { + STRDUP_OR_DIE(hostname, set.db_host, "db_host") if (stat(hostname, &socket_stat) == 0) { if (socket_stat.st_mode & S_IFSOCK) { - socket = strdup (set.dbhost); + socket = strdup (set.db_host); hostname = NULL; } - }else if ((socket = strstr(hostname,":"))) { + } else if ((socket = strstr(hostname,":"))) { *socket++ = 0x0; } - }else{ - if ((hostname = strdup(set.rdbhost)) == NULL) { - die("FATAL: malloc(): strdup() failed"); - } - } - }else{ - if ((hostname = strdup(set.dbhost)) == NULL) { - die("FATAL: malloc(): strdup() failed"); + } else { + STRDUP_OR_DIE(hostname, set.rdb_host, "rdb_host") } + } else { + STRDUP_OR_DIE(hostname, set.db_host, "db_host") if (stat(hostname, &socket_stat) == 0) { if (socket_stat.st_mode & S_IFSOCK) { - socket = strdup (set.dbhost); + socket = strdup (set.db_host); hostname = NULL; } - }else if ((socket = strstr(hostname,":"))) { + } else if ((socket = strstr(hostname,":"))) { *socket++ = 0x0; } } @@ -234,53 +229,59 @@ void db_connect(const char *database, MYSQL *mysql) { timeout = 5; rtimeout = 10; wtimeout = 20; + my_bool reconnect = 1; mysql_init(mysql); + if (mysql == NULL) { die("FATAL: MySQL unable to allocate memory and therefore can not connect"); } - options_error = mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *)&rtimeout); - if (options_error < 0) { - die("FATAL: MySQL options unable to set read timeout value"); - } - - options_error = mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (char *)&wtimeout); - if (options_error < 0) { - die("FATAL: MySQL options unable to set read timeout value"); - } - - options_error = mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout); - if (options_error < 0) { - die("FATAL: MySQL options unable to set timeout value"); - } + MYSQL_SET_OPTION(MYSQL_OPT_READ_TIMEOUT, (char *)&rtimeout, "read timeout"); + MYSQL_SET_OPTION(MYSQL_OPT_WRITE_TIMEOUT, (char *)&wtimeout, "write timeout"); + MYSQL_SET_OPTION(MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout, "general timeout"); #ifdef MYSQL_OPT_RECONNECT - my_bool reconnect = 1; - options_error = mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); - if (options_error < 0) { - die("FATAL: MySQL options unable to set reconnect option\n"); - } + MYSQL_SET_OPTION(MYSQL_OPT_RECONNECT, &reconnect, "reconnect"); #endif #ifdef MYSQL_OPT_RETRY_COUNT - options_error = mysql_options(mysql, MYSQL_OPT_RETRY_COUNT, &tries); - if (options_error < 0) { - die("FATAL: MySQL options unable to set retry count option\n"); + MYSQL_SET_OPTION(MYSQL_OPT_RETRY_COUNT, &tries, "retry count"); + #endif + + /* set SSL options if available */ + #ifdef MYSQL_OPT_SSL_KEY + char *ssl_key; + char *ssl_ca; + char *ssl_cert; + + if (set.poller_id > 1 && type == REMOTE) { + STRDUP_OR_DIE(ssl_key, set.rdb_ssl_key, "rdb_ssl_key"); + STRDUP_OR_DIE(ssl_ca, set.rdb_ssl_ca, "rdb_ssl_ca"); + STRDUP_OR_DIE(ssl_cert, set.rdb_ssl_cert, "rdb_ssl_cert"); + } else { + STRDUP_OR_DIE(ssl_key, set.db_ssl_key, "db_ssl_key"); + STRDUP_OR_DIE(ssl_ca, set.db_ssl_ca, "db_ssl_ca"); + STRDUP_OR_DIE(ssl_cert, set.db_ssl_cert, "db_ssl_cert"); } + + if (strlen(ssl_key)) MYSQL_SET_OPTION(MYSQL_OPT_SSL_KEY, ssl_key, "ssl key"); + if (strlen(ssl_ca)) MYSQL_SET_OPTION(MYSQL_OPT_SSL_CA, ssl_ca, "ssl ca"); + if (strlen(ssl_cert)) MYSQL_SET_OPTION(MYSQL_OPT_SSL_CERT, ssl_cert, "ssl cert"); + #endif while (tries > 0) { tries--; if (set.poller_id > 1) { - if (set.mode == REMOTE_OFFLINE || set.mode == REMOTE_RECOVERY) { - connect_error = mysql_real_connect(mysql, hostname, set.dbuser, set.dbpass, database, set.dbport, socket, 0); - }else{ - connect_error = mysql_real_connect(mysql, hostname, set.rdbuser, set.rdbpass, set.rdbdb, set.rdbport, socket, 0); + if (type == LOCAL) { + connect_error = mysql_real_connect(mysql, hostname, set.db_user, set.db_pass, set.db_db, set.db_port, socket, 0); + } else { + connect_error = mysql_real_connect(mysql, hostname, set.rdb_user, set.rdb_pass, set.rdb_db, set.rdb_port, socket, 0); } - }else{ - connect_error = mysql_real_connect(mysql, hostname, set.dbuser, set.dbpass, database, set.dbport, socket, 0); + } else { + connect_error = mysql_real_connect(mysql, hostname, set.db_user, set.db_pass, set.db_db, set.db_port, socket, 0); } if (!connect_error) { @@ -302,11 +303,11 @@ void db_connect(const char *database, MYSQL *mysql) { #ifndef SOLAR_THREAD usleep(2000); #endif - }else{ + } else { tries = 0; success = FALSE; } - }else{ + } else { tries = 0; success = TRUE; } @@ -350,12 +351,12 @@ int append_hostrange(char *obuf, const char *colname) { colname, set.start_host_id, set.end_host_id); - }else{ + } else { return 0; } } -/*! \fn void db_escape(MYSQL *mysql, char *output, const char *input) +/*! \fn void db_escape(MYSQL *mysql, char *output, int max_size, const char *input) * \brief Escapse a text string to make it safe for mysql insert/updates * \param mysql the connection object * \param output a pointer to the output string @@ -367,12 +368,23 @@ int append_hostrange(char *obuf, const char *colname) { * \return void * */ -void db_escape(MYSQL *mysql, char *output, const char *input) { +void db_escape(MYSQL *mysql, char *output, int max_size, const char *input) { if (input == NULL) return; - output[0] = '\0'; + char input_trimmed[BUFSIZE]; + int input_size; + + input_size = strlen(input); + + if (input_size > max_size) { + strncpy(input_trimmed, input, max_size - 10); + input_trimmed[max_size-10] = 0; + } else { + strncpy(input_trimmed, input, input_size); + input_trimmed[input_size] = 0; + } - mysql_real_escape_string(mysql, output, input, strlen(input)); + mysql_real_escape_string(mysql, output, input_trimmed, strlen(input_trimmed)); } void db_free_result(MYSQL_RES *result) { diff --git a/sql.h b/sql.h index f6abbe90..431d42a0 100644 --- a/sql.h +++ b/sql.h @@ -31,11 +31,18 @@ +-------------------------------------------------------------------------+ */ -extern int db_insert(MYSQL *mysql, const char *query); -extern MYSQL_RES *db_query(MYSQL *mysql, const char *query); -extern void db_connect(const char *database, MYSQL *mysql); +extern int db_insert(MYSQL *mysql, int type, const char *query); +extern MYSQL_RES *db_query(MYSQL *mysql, int type, const char *query); +extern void db_connect(int type, MYSQL *mysql); extern void db_disconnect(MYSQL *mysql); -extern void db_escape(MYSQL *mysql, char *output, const char *input); +extern void db_escape(MYSQL *mysql, char *output, int max_size, const char *input); extern void db_free_result(MYSQL_RES *result); extern int append_hostrange(char *obuf, const char *colname); + +#define MYSQL_SET_OPTION(opt, value, desc) \ + options_error = mysql_options(mysql, opt, value); \ + if (options_error < 0) {\ + die("FATAL: MySQL options unable to set %s option", desc);\ + }\ + diff --git a/util.c b/util.c index 4534cdf6..f54d3069 100644 --- a/util.c +++ b/util.c @@ -63,7 +63,7 @@ void set_option(const char *option, const char *value) { opttable[nopts++].val = value; } -/*! \fn static const char *getsetting(MYSQL *psql, const char *setting) +/*! \fn static const char *getsetting(MYSQL *psql, int mode, const char *setting) * \brief Returns a character pointer to a Cacti setting. * * Given a pointer to a database and the name of a setting, return the string @@ -76,7 +76,7 @@ void set_option(const char *option, const char *value) { * \return the database option setting * */ -static const char *getsetting(MYSQL *psql, const char *setting) { +static const char *getsetting(MYSQL *psql, int mode, const char *setting) { char qstring[256]; char *retval; MYSQL_RES *result; @@ -97,7 +97,63 @@ static const char *getsetting(MYSQL *psql, const char *setting) { sprintf(qstring, "SELECT value FROM settings WHERE name = '%s'", setting); - result = db_query(psql, qstring); + result = db_query(psql, mode, qstring); + + if (result != 0) { + if (mysql_num_rows(result) > 0) { + mysql_row = mysql_fetch_row(result); + + if (mysql_row != NULL) { + retval = strdup(mysql_row[0]); + db_free_result(result); + return retval; + }else{ + return 0; + } + }else{ + db_free_result(result); + return 0; + } + }else{ + return 0; + } +} + +/*! \fn static const char *getpsetting(MYSQL *psql, const char *setting) + * \brief Returns a character pointer to a Cacti poller setting. + * + * Given a pointer to a database and the name of a setting, + * return the string which represents the value from the poller table. + * Return NULL if we can't find a setting for whatever reason. + * + * NOTE: if the user has provided one of these options on the command line, + * it's intercepted here and returned, overriding the database setting. + * + * \return the database option setting + * + */ +static const char *getpsetting(MYSQL *psql, int mode, const char *setting) { + char qstring[256]; + char *retval; + MYSQL_RES *result; + MYSQL_ROW mysql_row; + int i; + + assert(psql != 0); + assert(setting != 0); + + /* see if it's in the option table */ + for (i=0; i 0) { @@ -119,7 +175,7 @@ static const char *getsetting(MYSQL *psql, const char *setting) { } } -/*! \fn static int getboolsetting(MYSQL *psql, const char *setting, int dflt) +/*! \fn static int getboolsetting(MYSQL *psql, int mode, const char *setting, int dflt) * \brief Obtains a boolean option from the database. * * Given the parameters for fetching a setting from the database, @@ -129,13 +185,13 @@ static const char *getsetting(MYSQL *psql, const char *setting) { * * \return boolean TRUE or FALSE based upon database setting or the DEFAULT if not found */ -static int getboolsetting(MYSQL *psql, const char *setting, int dflt) { +static int getboolsetting(MYSQL *psql, int mode, const char *setting, int dflt) { const char *rc; assert(psql != 0); assert(setting != 0); - rc = getsetting(psql, setting); + rc = getsetting(psql, mode, setting); if (rc == 0) return dflt; @@ -171,7 +227,7 @@ static int getboolsetting(MYSQL *psql, const char *setting, int dflt) { * \return the database global variable setting * */ -static const char *getglobalvariable(MYSQL *psql, const char *setting) { +static const char *getglobalvariable(MYSQL *psql, int mode, const char *setting) { char qstring[256]; char *retval; MYSQL_RES *result; @@ -191,7 +247,7 @@ static const char *getglobalvariable(MYSQL *psql, const char *setting) { sprintf(qstring, "SHOW GLOBAL VARIABLES LIKE '%s'", setting); - result = db_query(psql, qstring); + result = db_query(psql, mode, qstring); if (result != 0) { if (mysql_num_rows(result) > 0) { @@ -241,37 +297,46 @@ int is_debug_device(int device_id) { */ void read_config_options() { MYSQL mysql; + MYSQL mysqlr; MYSQL_RES *result; int num_rows; + int mode; char web_root[BUFSIZE]; char sqlbuf[SMALL_BUFSIZE], *sqlp = sqlbuf; const char *res; - db_connect(set.dbdb, &mysql); + db_connect(LOCAL, &mysql); + + if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) { + db_connect(REMOTE, &mysqlr); + mode = REMOTE; + } else { + mode = LOCAL; + } /* get the mysql server version */ set.dbversion = 0; - if ((res = getglobalvariable(&mysql, "version")) != 0) { + if ((res = getglobalvariable(&mysql, LOCAL, "version")) != 0) { set.dbversion = atoi(res); free((char *)res); } /* get logging level from database - overrides spine.conf */ - if ((res = getsetting(&mysql, "log_verbosity")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "log_verbosity")) != 0) { const int n = atoi(res); free((char *)res); if (n != 0) set.log_level = n; } /* determine script server path operation and default log file processing */ - if ((res = getsetting(&mysql, "path_webroot")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "path_webroot")) != 0) { snprintf(set.path_php_server, SMALL_BUFSIZE, "%s/script_server.php", res); snprintf(web_root, BUFSIZE, "%s", res); free((char *)res); } /* determine logfile path */ - if ((res = getsetting(&mysql, "path_cactilog")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "path_cactilog")) != 0) { if (strlen(res) != 0) { snprintf(set.path_logfile, SMALL_BUFSIZE, "%s", res); } else { @@ -287,7 +352,7 @@ void read_config_options() { } /* get log separator */ - if ((res = getsetting(&mysql, "default_datechar")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "default_datechar")) != 0) { set.log_datetime_separator = atoi(res); free((char *)res); @@ -297,7 +362,7 @@ void read_config_options() { } /* get log separator */ - if ((res = getsetting(&mysql, "default_datechar")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "default_datechar")) != 0) { set.log_datetime_separator = atoi(res); free((char *)res); @@ -313,7 +378,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The path_cactilog variable is %s", set.path_logfile)); /* determine log file, syslog or both, default is 1 or log file only */ - if ((res = getsetting(&mysql, "log_destination")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "log_destination")) != 0) { set.log_destination = parse_logdest(res, LOGDEST_FILE); free((char *)res); } else { @@ -327,7 +392,7 @@ void read_config_options() { set.logfile_processed = TRUE; /* get PHP Path Information for Scripting */ - if ((res = getsetting(&mysql, "path_php_binary")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "path_php_binary")) != 0) { STRNCOPY(set.path_php, res); free((char *)res); } @@ -336,7 +401,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The path_php variable is %s", set.path_php)); /* set availability_method */ - if ((res = getsetting(&mysql, "availability_method")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "availability_method")) != 0) { set.availability_method = atoi(res); free((char *)res); } @@ -345,7 +410,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The availability_method variable is %i", set.availability_method)); /* set ping_recovery_count */ - if ((res = getsetting(&mysql, "ping_recovery_count")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "ping_recovery_count")) != 0) { set.ping_recovery_count = atoi(res); free((char *)res); } @@ -354,7 +419,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The ping_recovery_count variable is %i", set.ping_recovery_count)); /* set ping_failure_count */ - if ((res = getsetting(&mysql, "ping_failure_count")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "ping_failure_count")) != 0) { set.ping_failure_count = atoi(res); free((char *)res); } @@ -363,7 +428,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The ping_failure_count variable is %i", set.ping_failure_count)); /* set ping_method */ - if ((res = getsetting(&mysql, "ping_method")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "ping_method")) != 0) { set.ping_method = atoi(res); free((char *)res); } @@ -372,7 +437,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The ping_method variable is %i", set.ping_method)); /* set ping_retries */ - if ((res = getsetting(&mysql, "ping_retries")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "ping_retries")) != 0) { set.ping_retries = atoi(res); free((char *)res); } @@ -381,7 +446,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The ping_retries variable is %i", set.ping_retries)); /* set ping_timeout */ - if ( (res = getsetting(&mysql, "ping_timeout")) != 0) { + if ( (res = getsetting(&mysql, LOCAL, "ping_timeout")) != 0) { set.ping_timeout = atoi(res); free((char *)res); } @@ -390,7 +455,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The ping_timeout variable is %i", set.ping_timeout)); /* set snmp_retries */ - if ( (res = getsetting(&mysql, "snmp_retries")) != 0) { + if ( (res = getsetting(&mysql, LOCAL, "snmp_retries")) != 0) { set.snmp_retries = atoi(res); free((char *)res); } @@ -399,37 +464,37 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The snmp_retries variable is %i", set.snmp_retries)); /* set logging option for errors */ - set.log_perror = getboolsetting(&mysql, "log_perror", FALSE); + set.log_perror = getboolsetting(&mysql, LOCAL, "log_perror", FALSE); /* log the log_perror variable */ SPINE_LOG_DEBUG(("DEBUG: The log_perror variable is %i", set.log_perror)); /* set logging option for errors */ - set.log_pwarn = getboolsetting(&mysql, "log_pwarn", FALSE); + set.log_pwarn = getboolsetting(&mysql, LOCAL, "log_pwarn", FALSE); /* log the log_pwarn variable */ SPINE_LOG_DEBUG(("DEBUG: The log_pwarn variable is %i", set.log_pwarn)); /* set option to increase insert performance */ - set.boost_redirect = getboolsetting(&mysql, "boost_redirect", FALSE); + set.boost_redirect = getboolsetting(&mysql, LOCAL, "boost_redirect", FALSE); /* log the boost_redirect variable */ SPINE_LOG_DEBUG(("DEBUG: The boost_redirect variable is %i", set.boost_redirect)); /* set option for determining if boost is enabled */ - set.boost_enabled = getboolsetting(&mysql, "boost_rrd_update_enable", FALSE); + set.boost_enabled = getboolsetting(&mysql, LOCAL, "boost_rrd_update_enable", FALSE); /* log the boost_rrd_update_enable variable */ SPINE_LOG_DEBUG(("DEBUG: The boost_rrd_update_enable variable is %i", set.boost_enabled)); /* set logging option for statistics */ - set.log_pstats = getboolsetting(&mysql, "log_pstats", FALSE); + set.log_pstats = getboolsetting(&mysql, LOCAL, "log_pstats", FALSE); /* log the log_pstats variable */ SPINE_LOG_DEBUG(("DEBUG: The log_pstats variable is %i", set.log_pstats)); /* get Cacti defined max threads override spine.conf */ - if ((res = getsetting(&mysql, "max_threads")) != 0) { + if ((res = getpsetting(&mysql, mode, "threads")) != 0) { set.threads = atoi(res); free((char *)res); if (set.threads > MAX_THREADS) { @@ -441,7 +506,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The threads variable is %i", set.threads)); /* get the poller_interval for those who have elected to go with a 1 minute polling interval */ - if ((res = getsetting(&mysql, "poller_interval")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "poller_interval")) != 0) { set.poller_interval = atoi(res); free((char *)res); } else { @@ -456,7 +521,7 @@ void read_config_options() { } /* get the concurrent_processes variable to determine thread sleep values */ - if ((res = getsetting(&mysql, "concurrent_processes")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "concurrent_processes")) != 0) { set.num_parent_processes = atoi(res); free((char *)res); } else { @@ -467,7 +532,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The number of concurrent processes is %i", set.num_parent_processes)); /* get the script timeout to establish timeouts */ - if ((res = getsetting(&mysql, "script_timeout")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "script_timeout")) != 0) { set.script_timeout = atoi(res); free((char *)res); if (set.script_timeout < 5) { @@ -481,7 +546,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The script timeout is %i", set.script_timeout)); /* get selective_device_debug string */ - if ((res = getsetting(&mysql, "selective_device_debug")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "selective_device_debug")) != 0) { STRNCOPY(set.selective_device_debug, res); free((char *)res); } @@ -490,7 +555,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The selective_device_debug variable is %s", set.selective_device_debug)); /* get spine_log_level */ - if ((res = getsetting(&mysql, "spine_log_level")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "spine_log_level")) != 0) { set.spine_log_level = atoi(res); free((char *)res); } @@ -499,7 +564,7 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The spine_log_level variable is %i", set.spine_log_level)); /* get the number of script server processes to run */ - if ((res = getsetting(&mysql, "php_servers")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "php_servers")) != 0) { set.php_servers = atoi(res); free((char *)res); @@ -537,7 +602,7 @@ void read_config_options() { } sqlp += sprintf(sqlp, " LIMIT 1"); - result = db_query(&mysql, sqlbuf); + result = db_query(&mysql, LOCAL, sqlbuf); num_rows = mysql_num_rows(result); db_free_result(result); @@ -557,7 +622,7 @@ void read_config_options() { } sqlp += sprintf(sqlp, " LIMIT 1"); - result = db_query(&mysql, sqlbuf); + result = db_query(&mysql, LOCAL, sqlbuf); num_rows = mysql_num_rows(result); db_free_result(result); @@ -574,7 +639,7 @@ void read_config_options() { : "Not ")); /* determine the maximum oid's to obtain in a single get request */ - if ((res = getsetting(&mysql, "max_get_size")) != 0) { + if ((res = getsetting(&mysql, LOCAL, "max_get_size")) != 0) { set.snmp_max_get_size = atoi(res); free((char *)res); @@ -589,6 +654,205 @@ void read_config_options() { SPINE_LOG_DEBUG(("DEBUG: The Maximum SNMP OID Get Size is %i", set.snmp_max_get_size)); db_disconnect(&mysql); + + if (set.poller_id > 1 && set.mode == REMOTE_ONLINE) { + db_disconnect(&mysqlr); + } +} + +void poller_push_data_to_main() { + MYSQL mysql; + MYSQL mysqlr; + MYSQL_RES *result; + MYSQL_ROW row; + int num_rows; + int rows; + char sqlbuf[MEGA_BUFSIZE]; + char *sqlp = sqlbuf; + char query[BUFSIZE]; + char prefix[BUFSIZE]; + char suffix[BUFSIZE]; + char tmpstr[SMALL_BUFSIZE]; + + db_connect(LOCAL, &mysql); + db_connect(REMOTE, &mysqlr); + + /* Since MySQL 5.7 the sql_mode defaults are too strict for cacti */ + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); + db_insert(&mysql, LOCAL, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE', ''))"); + db_insert(&mysqlr, REMOTE, "SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY', ''))"); + + SPINE_LOG_MEDIUM(("Pushing Host Status to Main Server")); + + snprintf(query, BUFSIZE, "SELECT id, snmp_sysDescr, snmp_sysObjectID, " + "snmp_sysUpTimeInstance, snmp_sysContact, snmp_sysName, snmp_sysLocation, " + "status, status_event_count, status_fail_date, status_rec_date, " + "status_last_error, min_time, max_time, cur_time, avg_time, polling_time, " + "total_polls, failed_polls, availability, last_updated " + "FROM host " + "WHERE poller_id = %d", set.poller_id); + + snprintf(prefix, BUFSIZE, "INSERT INTO host (id, snmp_sysDescr, snmp_sysObjectID, " + "snmp_sysUpTimeInstance, snmp_sysContact, snmp_sysName, snmp_sysLocation, " + "status, status_event_count, status_fail_date, status_rec_date, " + "status_last_error, min_time, max_time, cur_time, avg_time, polling_time, " + "total_polls, failed_polls, availability, last_updated) VALUES "); + + snprintf(suffix, BUFSIZE, " ON DUPLICATE KEY UPDATE " + "snmp_sysDescr=VALUES(snmp_sysDescr), " + "snmp_sysObjectID=VALUES(snmp_sysObjectID), " + "snmp_sysUpTimeInstance=VALUES(snmp_sysUpTimeInstance), " + "snmp_sysContact=VALUES(snmp_sysContact), " + "snmp_sysName=VALUES(snmp_sysName), " + "snmp_sysLocation=VALUES(snmp_sysLocation), " + "status=VALUES(status), " + "status_event_count=VALUES(status_event_count), " + "status_fail_date=VALUES(status_fail_date), " + "status_rec_date=VALUES(status_rec_date), " + "status_last_error=VALUES(status_last_error), " + "min_time=VALUES(min_time), " + "max_time=VALUES(max_time), " + "cur_time=VALUES(cur_time), " + "avg_time=VALUES(avg_time), " + "polling_time=VALUES(polling_time), " + "total_polls=VALUES(total_polls), " + "failed_polls=VALUES(failed_polls), " + "availability=VALUES(availability), " + "last_updated=VALUES(last_updated);"); + + if ((result = db_query(&mysql, LOCAL, query)) != 0) { + num_rows = mysql_num_rows(result); + rows = 0; + + if (num_rows > 0) { + while ((row = mysql_fetch_row(result))) { + if (rows < 500) { + if (rows == 0) { + sqlp = sqlbuf; + sqlp += sprintf(sqlp, "%s", prefix); + sqlp += sprintf(sqlp, " ("); + } else { + sqlp += sprintf(sqlp, ", ("); + } + + sqlp += sprintf(sqlp, "%s, ", row[0]); // id + + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[1]); // snmp_sysDescr + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[2]); // snmp_sysObjectID + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[3]); // snmp_sysUpTimeInstance + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[4]); // snmp_sysContact + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[5]); // snmp_sysName + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[6]); // snmp_sysLocation + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[7]); // status + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + + sqlp += sprintf(sqlp, "%s, ", row[8]); // status_event_count + + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[9]); // status_event_date + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[10]); // status_rec_date + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[11]); // status_last_error + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + + sqlp += sprintf(sqlp, "%s, ", row[12]); // min_time + sqlp += sprintf(sqlp, "%s, ", row[13]); // max_time + sqlp += sprintf(sqlp, "%s, ", row[14]); // cur_time + sqlp += sprintf(sqlp, "%s, ", row[15]); // avg_time + sqlp += sprintf(sqlp, "%s, ", row[16]); // polling_time + sqlp += sprintf(sqlp, "%s, ", row[17]); // total_polls + sqlp += sprintf(sqlp, "%s, ", row[18]); // failed_polls + sqlp += sprintf(sqlp, "%s, ", row[19]); // availability + + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[20]); // last_updated + sqlp += sprintf(sqlp, "'%s'", tmpstr); + + sqlp += sprintf(sqlp, ")"); + + rows++; + } else { + sqlp += sprintf(sqlp, "%s", suffix); + db_insert(&mysqlr, REMOTE, sqlbuf); + + rows = 0; + } + } + } + + if (rows > 0) { + sqlp += sprintf(sqlp, "%s", suffix); + db_insert(&mysqlr, REMOTE, sqlbuf); + } + } + + db_free_result(result); + + SPINE_LOG_MEDIUM(("Pushing Poller Item RRD Next Step to Main Server")); + + snprintf(query, BUFSIZE, "SELECT local_data_id, host_id, rrd_name, rrd_step, rrd_next_step " + "FROM poller_item " + "WHERE poller_id = %i", set.poller_id); + + snprintf(prefix, BUFSIZE, "INSERT INTO poller_item (local_data_id, host_id, rrd_name, rrd_step, rrd_next_step) VALUES "); + + snprintf(suffix, BUFSIZE, " ON DUPLICATE KEY UPDATE " + "rrd_next_step=VALUES(rrd_next_step);"); + + if ((result = db_query(&mysql, LOCAL, query)) != 0) { + num_rows = mysql_num_rows(result); + rows = 0; + + if (num_rows > 0) { + while ((row = mysql_fetch_row(result))) { + if (rows < 10000) { + if (rows == 0) { + sqlp = sqlbuf; + sqlp += sprintf(sqlp, "%s", prefix); + sqlp += sprintf(sqlp, " ("); + } else { + sqlp += sprintf(sqlp, ", ("); + } + + sqlp += sprintf(sqlp, "%s, ", row[0]); // local_data_id + sqlp += sprintf(sqlp, "%s, ", row[1]); // host_id + + db_escape(&mysql, tmpstr, sizeof(tmpstr), row[2]); // rrd_name + sqlp += sprintf(sqlp, "'%s', ", tmpstr); + + sqlp += sprintf(sqlp, "%s, ", row[3]); // rrd_step + sqlp += sprintf(sqlp, "%s", row[4]); // rrd_next_step + + sqlp += sprintf(sqlp, ")"); + + rows++; + } else { + sqlp += sprintf(sqlp, "%s", suffix); + db_insert(&mysqlr, REMOTE, sqlbuf); + + rows = 0; + } + } + } + + if (rows > 0) { + sqlp += sprintf(sqlp, "%s", suffix); + db_insert(&mysqlr, REMOTE, sqlbuf); + + rows = 0; + } + } + + db_free_result(result); + + db_disconnect(&mysql); + db_disconnect(&mysqlr); } /*! \fn int read_spine_config(char *file) @@ -621,16 +885,24 @@ int read_spine_config(char *file) { if (!feof(fp) && *buff != '#' && *buff != ' ' && *buff != '\n') { sscanf(buff, "%15s %255s", p1, p2); - if (STRIMATCH(p1, "RDB_Host")) STRNCOPY(set.rdbhost, p2); - else if (STRIMATCH(p1, "RDB_Database")) STRNCOPY(set.rdbdb, p2); - else if (STRIMATCH(p1, "RDB_User")) STRNCOPY(set.rdbuser, p2); - else if (STRIMATCH(p1, "RDB_Pass")) STRNCOPY(set.rdbpass, p2); - else if (STRIMATCH(p1, "RDB_Port")) set.rdbport = atoi(p2); - else if (STRIMATCH(p1, "DB_Host")) STRNCOPY(set.dbhost, p2); - else if (STRIMATCH(p1, "DB_Database")) STRNCOPY(set.dbdb, p2); - else if (STRIMATCH(p1, "DB_User")) STRNCOPY(set.dbuser, p2); - else if (STRIMATCH(p1, "DB_Pass")) STRNCOPY(set.dbpass, p2); - else if (STRIMATCH(p1, "DB_Port")) set.dbport = atoi(p2); + if (STRIMATCH(p1, "RDB_Host")) STRNCOPY(set.rdb_host, p2); + else if (STRIMATCH(p1, "RDB_Database")) STRNCOPY(set.rdb_db, p2); + else if (STRIMATCH(p1, "RDB_User")) STRNCOPY(set.rdb_user, p2); + else if (STRIMATCH(p1, "RDB_Pass")) STRNCOPY(set.rdb_pass, p2); + else if (STRIMATCH(p1, "RDB_Port")) set.rdb_port = atoi(p2); + else if (STRIMATCH(p1, "RDB_UseSSL")) set.rdb_ssl = atoi(p2); + else if (STRIMATCH(p1, "RDB_SSL_Key")) STRNCOPY(set.rdb_ssl_key, p2); + else if (STRIMATCH(p1, "RDB_SSL_Cert")) STRNCOPY(set.rdb_ssl_cert, p2); + else if (STRIMATCH(p1, "RDB_SSL_CA")) STRNCOPY(set.rdb_ssl_ca, p2); + else if (STRIMATCH(p1, "DB_Host")) STRNCOPY(set.db_host, p2); + else if (STRIMATCH(p1, "DB_Database")) STRNCOPY(set.db_db, p2); + else if (STRIMATCH(p1, "DB_User")) STRNCOPY(set.db_user, p2); + else if (STRIMATCH(p1, "DB_Pass")) STRNCOPY(set.db_pass, p2); + else if (STRIMATCH(p1, "DB_Port")) set.db_port = atoi(p2); + else if (STRIMATCH(p1, "DB_UseSSL")) set.db_ssl = atoi(p2); + else if (STRIMATCH(p1, "DB_SSL_Key")) STRNCOPY(set.db_ssl_key, p2); + else if (STRIMATCH(p1, "DB_SSL_Cert")) STRNCOPY(set.db_ssl_cert, p2); + else if (STRIMATCH(p1, "DB_SSL_CA")) STRNCOPY(set.db_ssl_ca, p2); else if (STRIMATCH(p1, "Poller")) set.poller_id = atoi(p2); else if (STRIMATCH(p1, "DB_PreG")) { if (!set.stderr_notty) { @@ -647,7 +919,7 @@ int read_spine_config(char *file) { } } - if (strlen(set.dbpass) == 0) *set.dbpass = '\0'; + if (strlen(set.db_pass) == 0) *set.db_pass = '\0'; return 0; } @@ -662,20 +934,20 @@ void config_defaults() { set.threads = DEFAULT_THREADS; /* default server */ - set.dbport = DEFAULT_DB_PORT; + set.db_port = DEFAULT_DB_PORT; - STRNCOPY(set.dbhost, DEFAULT_DB_HOST); - STRNCOPY(set.dbdb, DEFAULT_DB_DB ); - STRNCOPY(set.dbuser, DEFAULT_DB_USER); - STRNCOPY(set.dbpass, DEFAULT_DB_PASS); + STRNCOPY(set.db_host, DEFAULT_DB_HOST); + STRNCOPY(set.db_db, DEFAULT_DB_DB ); + STRNCOPY(set.db_user, DEFAULT_DB_USER); + STRNCOPY(set.db_pass, DEFAULT_DB_PASS); /* remote default server */ - set.rdbport = DEFAULT_DB_PORT; + set.rdb_port = DEFAULT_DB_PORT; - STRNCOPY(set.rdbhost, DEFAULT_DB_HOST); - STRNCOPY(set.rdbdb, DEFAULT_DB_DB ); - STRNCOPY(set.rdbuser, DEFAULT_DB_USER); - STRNCOPY(set.rdbpass, DEFAULT_DB_PASS); + STRNCOPY(set.rdb_host, DEFAULT_DB_HOST); + STRNCOPY(set.rdb_db, DEFAULT_DB_DB ); + STRNCOPY(set.rdb_user, DEFAULT_DB_USER); + STRNCOPY(set.rdb_pass, DEFAULT_DB_PASS); STRNCOPY(config_paths[0], CONFIG_PATH_1); STRNCOPY(config_paths[1], CONFIG_PATH_2); @@ -720,6 +992,20 @@ void die(const char *format, ...) { SPINE_LOG(("%s", flogmessage)); +#ifdef HAS_EXECINFO_H + printf("Generating backtrace...%ld line(s)...\n", set.exit_size); + if (set.exit_size) { + char **exit_strings = backtrace_symbols(set.exit_stack, set.exit_size); + if (exit_strings) { + int row = 0; + for (row = 0; row < set.exit_size; row++) + printf("%3d: %s\n", row, exit_strings[row]); + + free(exit_strings); + } + } +#endif + if (set.parent_fork == SPINE_PARENT) { if (set.php_initialized) { php_close(PHP_INIT); @@ -1490,11 +1776,17 @@ void checkAsRoot() { free(p); #else if (hasCaps() != TRUE) { - if (seteuid(0) == -1) { - SPINE_LOG_DEBUG(("WARNING: Spine NOT running asroot. This is required if using ICMP. Please run \"chown root:root spine;chmod +s spine\" to resolve.")); + SPINE_LOG_DEBUG(("DEBUG: Spine running as %d UID, %d EUID", getuid(), geteuid())); + int ret = seteuid(0); + if (ret != 0) { + SPINE_LOG_DEBUG(("WARNING: Spine NOT able to set effective UID to 0")); + } + + if (geteuid() != 0) { + SPINE_LOG_DEBUG(("WARNING: Spine NOT running as root. This is required if using ICMP. Please run \"chown root:root spine;chmod u+s spine\" to resolve.")); set.icmp_avail = FALSE; } else { - SPINE_LOG_DEBUG(("DEBUG: Spine is running asroot.")); + SPINE_LOG_DEBUG(("DEBUG: Spine is running as root.")); set.icmp_avail = TRUE; if (seteuid(getuid()) == -1) { @@ -1505,6 +1797,7 @@ void checkAsRoot() { SPINE_LOG_DEBUG(("DEBUG: Spine has cap_net_raw capability.")); set.icmp_avail = TRUE; } + SPINE_LOG_DEBUG(("DEBUG: Spine has %sgot ICMP", set.icmp_avail?"":"not ")); #endif #endif } diff --git a/util.h b/util.h index f58b6f3e..9de01cae 100644 --- a/util.h +++ b/util.h @@ -73,6 +73,13 @@ unsigned long long hex2dec(char *str); /* macro to copy string to string with an ending null */ #define STRNCOPY(dst, src) strncopy((dst), (src), sizeof(dst)) +/* macro to duplicate string and die if fails */ +#define STRDUP_OR_DIE(dst, src, reason) \ + if ((dst = strdup(src)) == NULL) {\ + die("FATAL: malloc() failed during strdup() for %s", reason);\ + }\ + + /* get highres time as double */ extern double get_time_as_double(void);