./PaxHeaders.3873/unix0000644000000000000000000000013212607712676013060 xustar000000000000000030 mtime=1444910526.814381211 30 atime=1444910526.834382301 30 ctime=1444910526.814381211 unix/0000755000000000000000000000000012607712676012055 5ustar00rootroot00000000000000unix/PaxHeaders.3873/SunOS0000644000000000000000000000013212607712676013732 xustar000000000000000030 mtime=1444910526.838382519 30 atime=1444910525.218294272 30 ctime=1444910526.838382519 unix/SunOS/0000755000000000000000000000000012607712676013064 5ustar00rootroot00000000000000unix/SunOS/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017460 xustar000000000000000030 mtime=1444910526.838382519 30 atime=1444910526.838382519 30 ctime=1444910526.838382519 unix/SunOS/pandora_agent.conf0000644000000000000000000001212312607712676016534 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, Solaris Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name xxxxxx # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # timeout in seconds for file transfer programs execution (30 by default) #transfer_timeout 30 # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) #remote_config 1 # If set to 1 start Drone Agent's Proxy Mode #proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) #proxy_max_connection 10 # Proxy timeout (by default 1s) #proxy_timeout 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_transfer_timeout 30 #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information module_begin module_name disk_root_free module_type generic_data module_exec df -k / | tail -1 | tr -d "%" | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name proctotal module_type generic_data module_exec ps -Alf | wc -l | awk '{ print $1 }' module_end module_begin module_name sshDaemon module_type generic_proc module_exec ps -Af | grep sshd | grep -v "grep" | wc -l | awk '{ print $1 }' module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end module_begin module_name Swap_Free module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $4 }' module_description Unused swap memory module_end module_begin module_name RAM_Free module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $5 }' module_description Unused RAM memory module_end module_begin module_name CPU_User module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $20 }' module_description % of USER CPU module_end module_begin module_name CPU_System module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $21 }' module_description % of system CPU module_end module_begin module_name Disk_Seek_Operations module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $14 }' module_description Disk Seek operations module_end module_begin module_name Pandora_Agent_RAM module_type generic_data module_exec ps -Afly | grep perl | grep -v grep | awk '{ print $9 }' module_description Return size in KB of memory used by process Pandora module_end module_plugin grep_log /var/adm/syslog Syslog . unix/SunOS/PaxHeaders.3873/make_solaris_package0000644000000000000000000000013212573660551020052 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861801.561395235 30 ctime=1441751401.987006935 unix/SunOS/make_solaris_package/0000755000000000000000000000000012573660551017204 5ustar00rootroot00000000000000unix/SunOS/make_solaris_package/PaxHeaders.3873/prototype0000644000000000000000000000013212573660551022117 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444862004.172359759 30 ctime=1441751401.987006935 unix/SunOS/make_solaris_package/prototype0000644000000000000000000000220312573660551021171 0ustar00rootroot00000000000000i pkginfo i copyright f none usr/bin/pandora_agent 0755 root root f none usr/bin/tentacle_client 0755 root root f none usr/bin/tentacle_server 0755 root root f none usr/bin/pandora_agent_exec 0755 root root d none usr/share/pandora_agent 0755 root root d none usr/share/pandora_agent/plugins 0755 root root f none usr/share/pandora_agent/plugins/files_indir 0755 root root f none usr/share/pandora_agent/plugins/grep_log 0755 root root f none usr/share/pandora_agent/plugins/inventory 0755 root root f none usr/share/pandora_agent/plugins/pandora_df 0755 root root f none usr/share/pandora_agent/plugins/nagios_plugin_wrapper 0755 root root f none usr/share/pandora_agent/plugins/pandora_update 0755 root root d none etc/pandora/ 0755 root root f none etc/pandora/pandora_agent.conf 0755 root root f none usr/man/man1/pandora_agent.1 0644 root root f none usr/man/man1/tentacle_client.1 0644 root root d none var/spool/pandora 0755 root root d none var/spool/pandora/data_out 0755 root root d none var/log/pandora 0755 root root f none etc/init.d/pandora_agent_daemon 0755 root root s none etc/rc2.d/S90pandora_agent_daemon=../init.d/pandora_agent_daemon unix/SunOS/make_solaris_package/PaxHeaders.3873/README0000644000000000000000000000013212573660551021007 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444862004.172359759 30 ctime=1441751401.987006935 unix/SunOS/make_solaris_package/README0000644000000000000000000000053712573660551020071 0ustar00rootroot00000000000000This directory contains Pandora FMS agent package builder for Solaris. To make the Solaris package, execute: ./make_solaris_package.sh It works with x86/SPARC Solaris 9,10 or 11. The package file, named "PandoraFMS-agent-X.X.X.pkg", will be created. You can install it to Solaris 9,10 or 11 like this: pkgadd -d ./PandoraFMS-agent-X.X.X.pkg unix/SunOS/make_solaris_package/PaxHeaders.3873/make_solaris_package.sh0000644000000000000000000000013212573660551024607 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444862004.172359759 30 ctime=1441751401.987006935 unix/SunOS/make_solaris_package/make_solaris_package.sh0000755000000000000000000000427612573660551023700 0ustar00rootroot00000000000000#!/bin/sh # ********************************************************************** # Pandora FMS Agent package builder for Solaris # (c) 2010-2013 Junichi Satoh # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License # as published by the Free Software Foundation; version 2 # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # ********************************************************************** AGENT_VERSION="5.0dev" PKGFILE="PandoraFMS-agent-$AGENT_VERSION.pkg" # make pkginfo file DATE=`date '+%Y%m%d%H'` echo "PKG=PandoraAgent" > pkginfo echo "NAME=Pandora FMS agent" >> pkginfo echo "ARCH=all" >> pkginfo echo "CATEGORY=application" >> pkginfo echo "VERSION=$AGENT_VERSION" >> pkginfo echo "VENDOR=http://pandorafms.org/" >> pkginfo echo "PSTAMP=$DATE" >> pkginfo echo "CLASSES=none" >> pkginfo echo "BASEDIR=/" >> pkginfo # make work directory. mkdir -p /tmp/pandora/usr/bin mkdir -p /tmp/pandora/usr/man/man1 mkdir -p /tmp/pandora/etc/pandora mkdir -p /tmp/pandora/etc/init.d mkdir -p /tmp/pandora/usr/share/pandora_agent/plugins # copy executables cp ../../pandora_agent /tmp/pandora/usr/bin cp ../../tentacle_client /tmp/pandora/usr/bin cp ../../tentacle_server /tmp/pandora/usr/bin cp ../../pandora_agent_daemon /tmp/pandora/etc/init.d cp ../../pandora_agent_exec /tmp/pandora/usr/bin # copy plugin files cp ../../plugins/* /tmp/pandora/usr/share/pandora_agent/plugins # copy configuration file cp ../pandora_agent.conf /tmp/pandora/etc/pandora # copy man pages cp ../../man/man1/pandora_agent.1.gz /tmp/pandora/usr/man/man1 gunzip /tmp/pandora/usr/man/man1/pandora_agent.1.gz cp ../../man/man1/tentacle_client.1.gz /tmp/pandora/usr/man/man1 gunzip /tmp/pandora/usr/man/man1/tentacle_client.1.gz # make package. pkgmk -o -r /tmp/pandora -d /tmp/pandora CURRENT_DIR=`pwd` pkgtrans -s /tmp/pandora $CURRENT_DIR/$PKGFILE PandoraAgent # delete work files rm -rf /tmp/pandora echo "" echo "pkg file is created: $PKGFILE" unix/SunOS/make_solaris_package/PaxHeaders.3873/copyright0000644000000000000000000000013212573660551022062 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444862004.172359759 30 ctime=1441751401.987006935 unix/SunOS/make_solaris_package/copyright0000644000000000000000000000012612573660551021136 0ustar00rootroot00000000000000Licensed under GPL license v2. Copyright (c) 2003-2010 Artica Soluciones Tecnologicas unix/PaxHeaders.3873/COPYING0000644000000000000000000000013212573660551014027 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444861867.824980919 30 ctime=1441751401.955005142 unix/COPYING0000644000000000000000000003503312573660551013110 0ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONSunix/PaxHeaders.3873/pandora_agent_installer0000644000000000000000000000013212573660551017576 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/pandora_agent_installer0000755000000000000000000004224012573660551016660 0ustar00rootroot00000000000000#!/bin/sh # ********************************************************************** # Pandora FMS Agent Installer for Unix (generic installer) # (c) 2008-2010 Artica ST # (c) 2008-2010 Sancho Lerena # # This is a generic installer for all Unix-like systems.(AIX, HP-UX, SunOS, Linux, FreeBSD, NetBSD) # Please see http://www.pandorafms.org. This code is licensed under GPL 2.0 license. # ********************************************************************** PI_VERSION=4.0 PI_BUILD=110923 OS_NAME=`uname -s` FORCE=0 LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` PREFIX=/usr if [ "$OS_NAME" = "FreeBSD" ] || [ "$OS_NAME" = "NetBSD" ] then PREFIX=/usr/local fi PANDORA_HOME=$PREFIX/share/pandora_agent PANDORA_BIN=$PREFIX/bin/pandora_agent PANDORA_EXEC_BIN=$PREFIX/bin/pandora_agent_exec PANDORA_REVENT_BIN=$PREFIX/bin/pandora_revent PANDORA_TEMP=/var/spool/pandora PANDORA_CFG=/etc/pandora PANDORA_LOG_DIR=/var/log/pandora PANDORA_LOG=pandora_agent.log TENTACLE=$PREFIX/bin/tentacle_client TENTACLE_SERVER=$PREFIX/bin/tentacle_server PANDORA_MAN=$PREFIX/share/man PANDORA_STARTUP=/etc/init.d/pandora_agent_daemon DAEMON_SCRIPT=pandora_agent_daemon PANDORA_USER="root" PANDORA_PERL_PATH="perl" WITHOUT_TENTACLE_SERVER=0 FAKEROOT=0 # defaults for each platforms case $OS_NAME in AIX) PANDORA_STARTUP=/etc/rc.pandora_agent_daemon ;; HP-UX) PANDORA_STARTUP=/sbin/init.d/pandora_agent_daemon ;; FreeBSD) PANDORA_CFG=$PREFIX/etc/pandora PANDORA_MAN=$PREFIX/man PANDORA_STARTUP=$PREFIX/etc/rc.d/pandora_agent DAEMON_SCRIPT=$OS_NAME/pandora_agent PANDORA_PERL_PATH=/usr/local/bin/perl ;; NetBSD) PANDORA_CFG=/usr/local/etc/pandora PANDORA_STARTUP=/etc/rc.d/pandora_agent DAEMON_SCRIPT=$OS_NAME/pandora_agent PANDORA_PERL_PATH=/usr/pkg/bin/perl ;; esac MODE=$1 # options while : do case "$2" in "--no-tentacle-server") WITHOUT_TENTACLE_SERVER=1;; "--fakeroot") FAKEROOT=1;; *) break;; esac shift done PANDORA_BASE=`echo $2 | sed -e 's|/$||'` if [ "$3" != "" ] then PANDORA_USER=$3 if [ -z "$PANDORA_BASE" ] then echo "When specifying a custom user the agent must be installed to a custom location where that user has write permissions!" exit 1 fi fi [ "$4" ] && PANDORA_PERL_PATH=$4 # Check for Perl 5.6.x or higher available PERL_VERSION=`$PANDORA_PERL_PATH -v | egrep 'v5.[6-9]|v5.[12][0-9]' | grep perl` if [ -z "$PERL_VERSION" ] then echo "Perl 5.6.x or higher is not detected. This is required for Pandora FMS" echo "Detected: $PERL_VERSION " echo "Aborting install..." exit 2 fi if [ -z "`echo Linux HP-UX SunOS AIX Solaris Darwin BSD bsd FreeBSD NetBSD | grep \"$OS_NAME\"`" ] then echo "This system: '$OS_NAME' is not supported by this script" echo "Please make the install yourself as it's described in documentation" exit 1 fi # check for root to do the install if [ $FAKEROOT -ne 1 ] && [ -z "`id | grep \"uid=0(root)\"`" ] then echo "You need to be root to do the install. Please made a manual install" echo "if you want to install Pandora FMS agent without root" echo " " echo "Aborting install" exit 2 fi help () { echo "Syntax": echo " " echo " ./pandora_agent_installer < --mode > [ --option ] [ destination_path ] [ user_to_run_as ] [custom_perl_path]" echo " " echo "Modes:" echo " " echo " --force-install To force installation if already installed on system" echo " --install To install Pandora FMS Agent on this system" echo " --uninstall To uninstall/remove Pandora FMS Agent on this System" echo " " echo "Option:" echo " " echo " --no-tentacle-server Skip tentacle server installation (by default tentalce server installed)" echo " --fakeroot treate \"destination_path\" as root directory" echo " " echo "Some exaples of how to use the installer:" echo " " echo " ./pandora_agent_installer --install" echo " ./pandora_agent_installer --install /opt/pandora" echo " ./pandora_agent_installer --install \"\" pandora" echo " ./pandora_agent_installer --install /opt/pandora root /opt/pandora/perl5/usr/local/bin/perl" echo " ./pandora_agent_installer --uninstall /opt/pandora" echo " " } uninstall () { if [ "$OS_NAME" = "Darwin" ] then launchctl remove com.pandorafms.pandorafms rm /Library/LaunchDaemons/com.pandorafms.pandorafms.plist 2> /dev/null fi echo "Removing Pandora FMS Agent..." rm -Rf $PANDORA_BASE$PANDORA_BIN 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_EXEC_BIN 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_REVENT_BIN 2> /dev/null #Test if exist Pandora Server in this machine if [ -d $PANDORA_BASE$PANDORA_TEMP/data_in ] then echo "You have a Pandora Server in this machine. Then don't delete "$PANDORA_TEMP rm -Rf $PANDORA_BASE$PANDORA_TEMP/data_out 2> /dev/null else rm -Rf $PANDORA_BASE$PANDORA_TEMP 2> /dev/null rm -Rf $PANDORA_BASE$TENTACLE_SERVER 2> /dev/null fi rm -Rf $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf 2> /dev/null rm -Rf $PANDORA_BASE/etc/init.d/pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/sbin/init.d/pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc.pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/sbin/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc?.d/S90pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE/sbin/rc?.d/S90pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE/usr/local/etc/rc.d/pandora_agent 2> /dev/null if [ $FAKEROOT -ne 1 ] then rm -Rf /etc/init.d/pandora_agent_daemon 2> /dev/null rm -Rf /sbin/init.d/pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc.pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf /sbin/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc?.d/S90pandora_agent 2> /dev/null rm -Rf /sbin/rc?.d/S90pandora_agent 2> /dev/null rm -Rf /etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null rm -Rf /usr/local/etc/rc.d/pandora_agent 2> /dev/null fi rm -Rf $PANDORA_BASE$PANDORA_HOME 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG 2> /dev/null rm -Rf $PANDORA_BASE$TENTACLE 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_MAN/{man1,cat1}/tentacle_client.1.gz 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_MAN/{man1,cat1}/pandora_agent.1.gz 2> /dev/null # Skip delete of /etc/pandora if exists configuration of a server or satellite if [ ! -f $PANDORA_BASE/$PANDORA_CFG/pandora_server.conf -a ! -f $PANDORA_BASE/$PANDORA_CFG/satellite_server.conf ] then rm -Rf $PANDORA_BASE/$PANDORA_CFG 2> /dev/null fi if [ ! -z "$PANDORA_BASE" ] then echo "Please delete manually $PANDORA_BASE for complete uninstall" fi echo " " echo "Done" } # # install_perl_script [OPTIONS] SRCFILE DESTFILE # Install perl script. If PANDORA_PERL_DECODED_PATH is set, path of the perl # in shebang line is replaced with PANDORA_PERL_DECODED_PATH value. # OPTIONS: # -o OWNER owner of the installed script # -g GROUP group of the installed script # -m PREM mode of the installed script # install_perl_script () { OWNER=""; GROUP=""; PERM="" while : do case $1 in -o) OWNER=$2;; -g) GROUP=$2;; -m) PERM=$2;; *) break;; esac shift;shift done SRC="$1" DEST="$2" # do install if echo $PANDORA_PERL_PATH | grep "/" > /dev/null && [ "$PANDORA_PERL_PATH" != "/usr/bin/perl" ] then sed -e "s:^#\!.*:#\!$PANDORA_PERL_PATH:g" $SRC > $DEST else cp $SRC $DEST fi # set owner, group and permissions [ "$OWNER" ] && chown $OWNER $DEST 2>/dev/null [ "$GROUP" ] && chgrp $GROUP $DEST 2>/dev/null [ "$PERM" ] && chmod $PERM $DEST } install () { OS_VERSION=`uname -r` OLDFILENAMETMP=`date +"%Y-%m-%d"` echo "Detecting Unix distribution: $OS_NAME version $OS_VERSION" if [ -f $PANDORA_BASE$PANDORA_HOME ] && [ "$FORCE" = "0" ] then echo "Seems that default dir already exists. Please use --force-install to" echo "force installer to install on $PANDORA_BASE$PANDORA_HOME" exit else echo "Checking default dir $PANDORA_BASE$PANDORA_HOME..." fi if [ -f $PANDORA_BASE$PANDORA_BIN ] && [ "$FORCE" = "0" ] then echo "Seems that $PANDORA_BASE$PANDORA_BIN already exists. Please use --force-install to" echo "force installer to reinstall overwriting it" echo " " exit else echo "Checking Pandora FMS Agent on $PANDORA_BASE$PANDORA_BIN...." fi # Alter dynamically the daemon launcher and setup the new path # if PANDORA_BASE is customized. if [ "$PANDORA_BASE" ] && [ $FAKEROOT -ne 1 ] then DAEMON_TEMP=pandora_agent_daemon_temp # Backup the daemon script cp -f "$DAEMON_SCRIPT" "${DAEMON_SCRIPT}.bak" AGENT_CFG=$OS_NAME/pandora_agent.conf AGENT_CFG_TEMP=$OS_NAME/pandora_agent.conf.temp # Backup the configuration file cp -f "$AGENT_CFG" "${AGENT_CFG}.bak" if [ "$OS_NAME" = "FreeBSD" ] || [ "$OS_NAME" = "NetBSD" ] then sed -e "\|^PATH=|s|=|=$PANDORA_BASE$PREFIX/bin:|" \ -e "s|/usr/local/etc/pandora|$PANDORA_BASE$PANDORA_CFG|g" \ -e "s|/usr/local/bin/pandora_agent|$PANDORA_BASE$PANDORA_BIN|g" \ $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT else sed -e "\|^PATH=|s|=|=$PANDORA_BASE/usr/bin:|" \ -e "\|^PANDORA_PATH=|s|=|=$PANDORA_BASE|" \ -e "\|^LOGFILE=|s|=|=$PANDORA_BASE|" \ -e "\|^DAEMON=|s|=|=$PANDORA_BASE|" \ -e "\|^DAEMON_TENTACLE=|s|=|=$PANDORA_BASE|" \ -e "s/^PANDORA_USER=.*/PANDORA_USER=$PANDORA_USER/" \ $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT fi sed -e "s|^temporal[ \t][ \t]*|temporal $PANDORA_BASE|" \ -e "s|^logfile[ \t][ \t]*|logfile $PANDORA_BASE|" \ $AGENT_CFG > $AGENT_CFG_TEMP mv $AGENT_CFG_TEMP $AGENT_CFG fi echo "Creating Pandora FMS Agent home directory at $PANDORA_BASE$PANDORA_HOME" if [ "$PANDORA_BASE" ] then mkdir -p $PANDORA_BASE 2> /dev/null mkdir -p $PANDORA_BASE/var/log 2> /dev/null mkdir -p $PANDORA_BASE/$PANDORA_MAN/man1 2> /dev/null mkdir -p $PANDORA_BASE$PREFIX/bin 2> /dev/null fi mkdir -p $PANDORA_BASE$PANDORA_HOME 2> /dev/null # Create directories based on PANDORA_BASE mkdir -p $PANDORA_BASE/tmp 2> /dev/null mkdir -p $PANDORA_BASE$PANDORA_TEMP/data_out 2> /dev/null mkdir -p $PANDORA_BASE$PANDORA_CFG 2> /dev/null mkdir -p $PANDORA_BASE$PANDORA_LOG_DIR 2> /dev/null # Set the user the agent will run as if [ "$PANDORA_USER" != "root" ] then sed -e "s/.*pandora_user .*/pandora_user $PANDORA_USER/" $AGENT_CFG > $AGENT_CFG_TEMP 2> /dev/null && \ mv $AGENT_CFG_TEMP $AGENT_CFG chmod 755 pandora_agent_daemon chown -R $PANDORA_USER $PANDORA_BASE 2>/dev/null fi # Create logfile if [ ! -z "`touch $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG`" ] then echo "Seems to be a problem generating logfile ($PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG) please check it"; else echo "Created logfile at $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG..." fi echo "$LOG_TIMESTAMP Pandora FMS installer has created this file at startup" > $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG # Copying agent and securing it echo "Copying Pandora FMS Agent to $PANDORA_BASE$PANDORA_BIN..." install_perl_script -m 755 -o $PANDORA_USER -g 0 pandora_agent $PANDORA_BASE$PANDORA_BIN install_perl_script -m 755 -o $PANDORA_USER -g 0 pandora_agent_exec $PANDORA_BASE$PANDORA_EXEC_BIN install_perl_script -m 755 -o $PANDORA_USER -g 0 pandora_revent $PANDORA_BASE$PANDORA_REVENT_BIN echo "Copying Pandora FMS Agent configuration file to $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf..." if [ -f $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf ] then cp $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf.$OLDFILENAMETMP echo "Backing up old configuration file to $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf.$OLDFILENAMETMP" fi echo "Copying Pandora FMS Agent plugins to $PANDORA_BASE$PANDORA_HOME/plugins..." [ -d $PANDORA_BASE$PANDORA_HOME/plugins ] || mkdir -p $PANDORA_BASE$PANDORA_HOME/plugins >/dev/null 2>&1 for PLUGIN in plugins/* do if grep '^#!.*/perl' $PLUGIN >/dev/null 2>&1 then install_perl_script $PLUGIN $PANDORA_BASE$PANDORA_HOME/$PLUGIN else cp $PLUGIN $PANDORA_BASE$PANDORA_HOME/plugins fi done chmod -R 700 $PANDORA_BASE$PANDORA_HOME/plugins PANDORA_BASE_REAL="$PANDORA_BASE" [ $FAKEROOT -eq 1 ] && PANDORA_BASE_REAL="" ln -s $PANDORA_BASE_REAL$PANDORA_HOME/plugins $PANDORA_BASE$PANDORA_CFG echo "Copying Pandora FMS Agent collections to $PANDORA_BASE$PANDORA_HOME/collections..." cp -r collections $PANDORA_BASE$PANDORA_HOME chmod -R 700 $PANDORA_BASE$PANDORA_HOME/collections ln -s $PANDORA_BASE_REAL$PANDORA_HOME/collections $PANDORA_BASE$PANDORA_CFG if [ $WITHOUT_TENTACLE_SERVER -eq 0 ] then echo "Copying tentacle server to $PANDORA_BASE$TENTACLE_SERVER" install_perl_script -m 755 -o $PANDORA_USER -g 0 tentacle_server $PANDORA_BASE$TENTACLE_SERVER fi echo "Copying tentacle client to $PANDORA_BASE$TENTACLE" install_perl_script -m 755 -o $PANDORA_USER -g 0 tentacle_client $PANDORA_BASE$TENTACLE echo "Installing the Pandora Agent and Tentacle Client manuals" cp man/man1/tentacle_client.1.gz $PANDORA_BASE/$PANDORA_MAN/man1 chmod 644 $PANDORA_BASE/$PANDORA_MAN/man1/tentacle_client.1.gz cp man/man1/pandora_agent.1.gz $PANDORA_BASE/$PANDORA_MAN/man1 chmod 644 $PANDORA_BASE/$PANDORA_MAN/man1/pandora_agent.1.gz echo "Setting secure permissions and ownership for all Pandora FMS Agent files..." chown -R $PANDORA_USER $PANDORA_BASE$PANDORA_HOME 2>/dev/null chmod -R 700 $PANDORA_BASE$PANDORA_TEMP/data_out chmod 711 $PANDORA_BASE$PANDORA_LOG_DIR chmod 640 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG 2>/dev/null if [ "$OS_NAME" = "FreeBSD" ] || [ "$OS_NAME" = "NetBSD" ] then chown $PANDORA_USER:daemon $PANDORA_BASE$PANDORA_TEMP 2>/dev/null chmod -R 770 $PANDORA_BASE$PANDORA_TEMP chmod 775 $PANDORA_BASE$PANDORA_TEMP fi echo "Copying default agent configuration to $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf" cp $OS_NAME/pandora_agent.conf $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf chmod 600 $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf chown $PANDORA_USER $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf 2>/dev/null echo "Linking start-up daemon script '$DAEMON_SCRIPT' on $OS_NAME"; if [ "$OS_NAME" = "Darwin" ] then # Specific service install on Darwin/macOSX launchctl load -F Darwin/com.pandorafms.pandorafms.plist echo "Start Pandora FMS service with 'launchctl start com.pandorafms.pandorafms'" echo "This service has been scheduled to launch on each system startup" else DESTDIR="" [ "$PANDORA_BASE" ] && [ $FAKEROOT -eq 1 ] && DESTDIR=$PANDORA_BASE cp $DAEMON_SCRIPT $DESTDIR$PANDORA_STARTUP chmod 755 $DESTDIR$PANDORA_STARTUP chown root:0 $DESTDIR$PANDORA_STARTUP 2>/dev/null RCDIRS="" MSG="" if [ "$OS_NAME" = "AIX" ] then RCDIRS=/etc/rc.d/rc2.d MSG="Pandora FMS agent has been included in $DESTDIR/etc/rc.d/rc2.d/S90pandora_agent_daemon" elif [ "$OS_NAME" = "HP-UX" ] then RCDIRS="/sbin/rc2.d /sbin/rc3.d" MSG="Pandora FMS agent has been included in $DESTDIR/sbin/rcX.d/S90pandora_agent_daemon" elif [ "$OS_NAME" = "SunOS" ] then RCDIRS=/etc/rc2.d MSG="Pandora FMS agent has been included in $DESTDIR/etc/rc2.d/S90pandora_agent_daemon" elif [ "$OS_NAME" = "Linux" ] then if [ -d /etc/rc.d/ ] then RCDIRS="/etc/rc.d/rc2.d /etc/rc.d/rc3.d" else RCDIRS="/etc/rc2.d /etc/rc3.d" fi fi [ "$RCDIRS" ] && for RCDIR in $RCDIRS do [ $FAKEROOT -eq 1 ] && [ ! -d $DESTDIR$RCDIR ] && mkdir -p $DESTDIR$RCDIR >/dev/null 2>&1 ln -s $PANDORA_STARTUP $DESTDIR$RCDIR/S90pandora_agent 2> /dev/null done [ "$MSG" ] && echo "$MSG" fi echo "Done." echo " " echo "You have your startup script ready at $PANDORA_STARTUP" echo " " echo "Tentacle is the default transfer mode since 2.0 version." echo " " echo "If you want to use SSH, firstly you need to copy your public SSH keys " echo " ($HOME/.ssh/id_dsa) under /home/pandora/.ssh/authorized_keys " echo "on your Pandora FMS Server host" echo " " echo "You also need to setup your $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf config file" echo " " if [ "$OS_NAME" = "FreeBSD" ] then echo "Define 'pandora_agent_enable=\"YES\"' in /etc/rc.conf to enable the daemon." elif [ "$OS_NAME" = "NetBSD" ] then echo "Define 'pandora_agent=\"YES\"' in /etc/rc.conf to enable the daemon." else echo "Check your startup configuration to be sure Pandora FMS Agent is ready " echo "to start automatically when system restarts": fi # Restore the daemon script cp -f "$DAEMON_SCRIPT.bak" "$DAEMON_SCRIPT" >/dev/null 2>&1 rm -f "$DAEMON_SCRIPT.bak" >/dev/null 2>&1 # Restore the configuration file cp -f "$AGENT_CFG.bak" "$AGENT_CFG" >/dev/null 2>&1 rm -f "$AGENT_CFG.bak" >/dev/null 2>&1 } if [ ! -f "pandora_agent" ] then echo " " echo "Execute installer from the directory where you have your files. " help exit 1 fi # Script banner at start echo " " echo "Pandora FMS Agent UNIX Installer $PI_VERSION $PI_BUILD (c) 2008-2010 ArticaST" echo "This program is licensed under GPL2 Terms. http://pandorafms.com" echo " " case "$MODE" in '--force-install') FORCE=1 install exit ;; '--install') install exit ;; '--uninstall') uninstall exit ;; *) help ;; esac unix/PaxHeaders.3873/tentacle_client0000644000000000000000000000013212607655076016060 xustar000000000000000030 mtime=1444895294.619817018 30 atime=1444895304.200332924 30 ctime=1444895294.619817018 unix/tentacle_client0000755000000000000000000005350712607655076015152 0ustar00rootroot00000000000000#!/usr/bin/perl ################################################################################ # # Copyright (c) 2007-2008 Ramon Novoa # Copyright (c) 2007-2008 Artica Soluciones Tecnologicas S.L. # # tentacle_client.pl Tentacle Client. See http://www.openideas.info/wiki for # protocol description. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ################################################################################ package tentacle::client; =head1 NAME tentacle_client - Tentacle Client =head1 VERSION Version 0.4.0 =head1 USAGE tentacle_client [options] [file] [file] ... =head1 DESCRIPTION B is a client for B, a B file transfer protocol that aims to be: =over =item * Secure by design. =item * Easy to use. =item * Versatile and cross-platform. =back Tentacle was created to replace more complex tools like SCP and FTP for simple file transfer/retrieval, and switch from authentication mechanisms like .netrc, interactive logins and SSH keys to X.509 certificates. Simple password authentication over a SSL secured connection is supported too. The client and server (B) are designed to be run from the command line or called from a shell script, and B. If IO::Socket::INET6 is installed, the tentacle client supports IPv6. =cut use strict; use File::Basename; use Getopt::Std; use IO::Select; use Socket (qw(SOCK_STREAM AF_INET AF_INET6)); my $SOCKET_MODULE = eval { require IO::Socket::INET6 } ? 'IO::Socket::INET6' : eval { require IO::Socket::INET } ? 'IO::Socket::INET' : die $@; if ($SOCKET_MODULE eq 'IO::Socket::INET') { print_log ("IO::Socket::INET6 is not found. IPv6 is disabled."); } # Program version our $VERSION = '0.4.0'; # Server address my $t_address = '127.0.0.1'; # Block size for socket read/write operations in bytes my $t_block_size = 1024; # Log messages, 1 enabled, 0 disabled my $t_log = 0; # Server port my $t_port = 41121; # Do not output error messages, 1 enabled, 0 disabled my $t_quiet = 0; # Proxy address my $t_proxy_address = ''; # Proxy user my $t_proxy_user = ''; # Proxy password my $t_proxy_pass = ''; # Proxy port my $t_proxy_port = 0; # Server password my $t_pwd = ''; # Receive mode, 1 enabled, 0 disabled my $t_recv = 0; # Retries for socket read/write operations my $t_retries = 3; # Select handler my $t_select; # Server socket my $t_socket; # Use SSL, 1 true, 0 false my $t_ssl = 0; # SSL ca certificate file my $t_ssl_ca = ''; # SSL certificate file my $t_ssl_cert = ''; # SSL private key file my $t_ssl_key = ''; # SSL private key file password my $t_ssl_pwd = ''; # Timeout for socket read/write operations in seconds my $t_timeout = 1; ################################################################################ ## SUB print_help ## Print help screen. ################################################################################ sub print_help { print ("Usage: $0 [options] [file] [file] ...\n\n"); print ("Tentacle client v$VERSION. See http://www.openideas.info/wiki for protocol description.\n\n"); print ("Options:\n"); print ("\t-a address\tServer address (default $t_address).\n"); print ("\t-c\t\tEnable SSL without a client certificate.\n"); print ("\t-e cert\t\tOpenSSL certificate file. Enables SSL.\n"); print ("\t-f ca\t\tVerify that the peer certificate is signed by a ca.\n"); print ("\t-g\t\tGet files from the server.\n"); print ("\t-h\t\tShow help.\n"); print ("\t-k key\t\tOpenSSL private key file.\n"); print ("\t-p port\t\tServer port (default $t_port).\n"); print ("\t-q\t\tQuiet. Do now print error messages.\n"); print ("\t-r number\tNumber of retries for network operations (default $t_retries).\n"); print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n"); print ("\t-v\t\tBe verbose.\n"); print ("\t-w\t\tPrompt for OpenSSL private key password.\n"); print ("\t-x pwd\t\tServer password.\n"); print ("\t-y proxy\tProxy server string (user:password\@address:port).\n\n"); } ################################################################################ ## SUB parse_options ## Parse command line options and initialize global variables. ################################################################################ sub parse_options { my %opts; my $tmp; # Get options if (getopts ('a:ce:f:ghk:p:qr:t:vwx:y:', \%opts) == 0 || defined ($opts{'h'})) { print_help (); exit 1; } # Address if (defined ($opts{'a'})) { $t_address = $opts{'a'}; if (($t_address !~ /^[a-zA-Z\.][a-zA-Z0-9\.\-]+$/ && ($t_address !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) && ($t_address !~ /^[0-9a-f:]+$/o)) { error ("Address $t_address is not valid."); } } # Enable SSL without a client certificate if (defined ($opts{'c'})) { require IO::Socket::SSL; $t_ssl = 1; } # Enable SSL if (defined ($opts{'e'})) { if (defined ($opts{'c'})) { error ("Flags -c and -e can not be used at the same time."); } require IO::Socket::SSL; $t_ssl_cert = $opts{'e'}; if (! -f $t_ssl_cert) { error ("File $t_ssl_cert does not exist."); } $t_ssl = 1; } # Verify peer certificate if (defined ($opts{'f'})) { if (! defined ($opts{'e'})) { error ("Flag -e must be set to enable peer certificate verify."); } $t_ssl_ca = $opts{'f'}; if (! -f $t_ssl_ca) { error ("File $t_ssl_ca does not exist."); } } # Get files if (defined ($opts{'g'})) { $t_recv = 1; } # SSL private key file if (defined ($opts{'k'})) { if (! defined ($opts{'e'})) { error ("Flag -e must be set to use a private key file."); } $t_ssl_key = $opts{'k'}; if (! -f $t_ssl_key) { error ("File $t_ssl_key does not exist."); } } # Port if (defined ($opts{'p'})) { $t_port = $opts{'p'}; if ($t_port !~ /^\d+$/ || $t_port < 1 || $t_port > 65535) { error ("Port $t_port is not valid."); } } # Quiet mode if (defined ($opts{'q'})) { $t_quiet = 1; } # Retries if (defined ($opts{'r'})) { $t_retries = $opts{'r'}; if ($t_retries !~ /^\d+$/ || $t_retries < 1) { error ("Invalid number of retries for network operations."); } } # Timeout if (defined ($opts{'t'})) { $t_timeout = $opts{'t'}; if ($t_timeout !~ /^\d+$/ || $t_timeout < 1) { error ("Invalid timeout for network operations."); } } # Be verbose if (defined ($opts{'v'})) { $t_log = 1; } # SSL private key password if (defined ($opts{'w'})) { if (! defined ($opts{'e'})) { error ("Flag -k must be set to provide a private key password."); } $t_ssl_pwd = ask_passwd ("Enter private key file password: ", "Enter private key file password again for confirmation: "); } # Server password if (defined ($opts{'x'})) { $t_pwd = $opts{'x'}; } # Proxy server if (defined ($opts{'y'})) { if ($opts{'y'} !~ /^((.*):(.*)@){0,1}(\S+):(\d+)$/) { error ("Invalid proxy string: " . $opts{'y'}); } ($t_proxy_user, $t_proxy_pass, $t_proxy_address, $t_proxy_port) = ($2, $3, $4, $5); $t_proxy_user = '' unless defined ($t_proxy_user); $t_proxy_pass = '' unless defined ($t_proxy_pass); if ($t_proxy_port < 1 || $t_proxy_port > 65535) { error ("Proxy port $t_proxy_port is not valid."); } } } ################################################################################ ## SUB start_client ## Open the server socket. ################################################################################ sub start_client { # Connect to server if ($SOCKET_MODULE ne 'IO::Socket::INET') { $t_socket = $SOCKET_MODULE->new ( Domain => AF_INET6, PeerAddr => $t_address, PeerPort => $t_port, Type => SOCK_STREAM ); } if (! defined ($t_socket)) { $t_socket = $SOCKET_MODULE->new ( Domain => AF_INET, PeerAddr => $t_address, PeerPort => $t_port, Type => SOCK_STREAM ); } if (! defined ($t_socket)) { error ("Cannot connect to $t_address on port $t_port: $!."); } # Add server socket to select queue $t_select = IO::Select->new (); $t_select->add ($t_socket); print_log ("Connected to $t_address port $t_port"); } ################################################################################ ## SUB start_client_proxy ## Open the server socket. Connects to the Tentacle server through an HTTP proxy. ################################################################################ sub start_client_proxy { # Connect to proxy if ($SOCKET_MODULE ne 'IO::Socket::INET') { $t_socket = $SOCKET_MODULE->new ( Domain => AF_INET6, PeerAddr => $t_proxy_address, PeerPort => $t_proxy_port, ); } if (! defined ($t_socket)) { $t_socket = $SOCKET_MODULE->new ( Domain => AF_INET, PeerAddr => $t_proxy_address, PeerPort => $t_proxy_port, ); } if (! defined ($t_socket)) { error ("Cannot connect to proxy server $t_proxy_address on port $t_proxy_port: $!."); } # Add server socket to select queue $t_select = IO::Select->new (); $t_select->add ($t_socket); print_log ("Connected to proxy server $t_proxy_address port $t_proxy_port"); # Try to CONNECT to the Tentacle server send_data ("CONNECT " . $t_address . ":" . $t_port . " HTTP/1.0\r\n"); # Authenticate to the proxy if ($t_proxy_user ne '') { send_data ("Proxy-Authorization: Basic " . base64 ($t_proxy_user . ":" . $t_proxy_pass) . "\r\n"); } send_data ("\r\n"); # Check for an HTTP 200 response my $response = recv_data ($t_block_size); if ($response !~ m/HTTP.* 200 /) { my $error = (split (/\r\n/, $response))[0]; error ("CONNECT error: $error"); } print_log ("Connected to $t_address port $t_port"); } ################################################################################ ## SUB stop_client ## Close the server socket. ################################################################################ sub stop_client { $t_socket->close (); } ################################################################################ ## SUB start_ssl ## Convert the server socket to an IO::Socket::SSL socket. ################################################################################ sub start_ssl { my $err; if ($t_ssl_cert eq ''){ IO::Socket::SSL->start_SSL ( $t_socket, SSL_verify_mode => '0x00', ); } elsif ($t_ssl_ca eq '') { IO::Socket::SSL->start_SSL ( $t_socket, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_use_cert =>'1', # No authentication SSL_verify_mode => '0x00', ); } else { IO::Socket::SSL->start_SSL ( $t_socket, SSL_ca_file => $t_ssl_ca, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_use_cert =>'1', # Verify peer SSL_verify_mode => '0x01', ); } $err = IO::Socket::SSL::errstr (); if ($err ne '') { error ($err); } } ################################################################################ ## SUB auth_pwd ## Authenticate client with server password. ################################################################################ sub auth_pwd { my $command; my $pwd_digest; require Digest::MD5; $pwd_digest = Digest::MD5::md5 ($t_pwd); $pwd_digest = Digest::MD5::md5_hex ($pwd_digest); send_data ("PASS $pwd_digest\n"); $command = recv_command ($t_block_size); if ($command !~ /^PASS OK$/) { error ("Authentication failed."); } } ################################################################################ ## SUB base64 ## Returns the base 64 encoding of a string. ################################################################################ my @alphabet = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'); sub base64 { my $str = shift; my $str64; # Pre-processing my $msg = unpack ("B*", pack ("A*", $str)); my $bit_len = length ($msg); # Process the message in successive 24-bit chunks for (my $i = 0; $i < $bit_len; $i += 24) { my $chunk_len = length (substr ($msg, $i, 24)); $str64 .= $alphabet[ord (pack ("B8", "00" . substr ($msg, $i, 6)))]; $str64 .= $alphabet[ord (pack ("B8", "00" . substr ($msg, $i+6, 6)))]; $str64 .= ($chunk_len <= 12) ? "=" : $alphabet[ord (pack ("B8", "00" . substr ($msg, $i+12, 6)))]; $str64 .= ($chunk_len <= 18) ? "=" : $alphabet[ord (pack ("B8", "00" . substr ($msg, $i+18, 6)))]; } return $str64; } ################################################################################ ## SUB recv_file ## Receive a file from the server ################################################################################ sub recv_file { my $data = ''; my $file = $_[0]; my $response; my $size; # Request file send_data ("RECV <$file>\n"); # Wait for server response $response = recv_command (); if ($response !~ /^RECV SIZE (\d+)$/) { error ("Server responded $response."); } $size = $1; send_data ("RECV OK\n"); # Receive file $data = recv_data_block ($size); # Write it to disk open (FILE, "> $file") || error ("Cannot open file '$file' for writing."); binmode (FILE); print (FILE $data); close (FILE); print_log ("Received file '$file'"); } ################################################################################ ## SUB send_file ## Send a file to the server ################################################################################ sub send_file { my $base_name; my $data = ''; my $response = ''; my $retries; my $file = $_[0]; my $size; my $written; $base_name = basename ($file); $size = -s $file; # Request to send file send_data ("SEND <$base_name> SIZE $size\n"); print_log ("Request to send file '$base_name' size ${size}b"); # Wait for server response $response = recv_command (); # Server rejected the file if ($response ne "SEND OK") { send_data ("QUIT\n"); error ("Server responded $response."); } print_log ("Server responded SEND OK"); # Send the file open (FILE, $file) || error ("Cannot open file '$file' for reading."); binmode (FILE); while ($data = ) { send_data ($data); } close (FILE); # Wait for server response $response = recv_command (); if ($response ne "SEND OK") { send_data ("QUIT\n"); error ("Server responded $response."); } print_log ("File sent"); } ################################################################################ # Common functions ################################################################################ ################################################################################ ## SUB print_log ## Print log messages. ################################################################################ sub print_log { if ($t_log == 1) { print (STDOUT "[log] $_[0]\n"); } } ################################################################################ ## SUB error ## Print an error and exit the program. ################################################################################ sub error { if ($t_quiet == 0) { print (STDERR "[err] $_[0]\n"); } exit 1; } ################################################################################ ## SUB recv_data ## Read data from the client socket. Returns the number of bytes read and the ## string of bytes as a two element array. ################################################################################ sub recv_data { my $data; my $read; my $retries = 0; my $size = $_[0]; while (1) { # Try to read data from the socket if ($t_select->can_read ($t_timeout)) { # Read at most $size bytes $read = sysread ($t_socket, $data, $size); # Read error if (! defined ($read)) { error ("Read error from " . $t_socket->sockhost () . ": $!."); } # EOF if ($read == 0) { error ("Connection from " . $t_socket->sockhost () . " unexpectedly closed."); } return ($read, $data); } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB send_data ## Write data to the client socket. ################################################################################ sub send_data { my $data = $_[0]; my $retries = 0; my $size; my $total = 0; my $written; $size = length ($data); while (1) { # Try to write data to the socket if ($t_select->can_write ($t_timeout)) { $written = syswrite ($t_socket, $data, $size - $total, $total); # Read error if (! defined ($written)) { error ("Connection error from " . $t_socket->sockhost () . ": $!."); } # EOF if ($written == 0) { error ("Connection from " . $t_socket->sockhost () . " unexpectedly closed."); } $total += $written; # All data was written if ($total == $size) { return; } # Retry } else { $retries++; if ($retries > $t_retries) { error ("Connection from " . $t_socket->sockhost () . " timed out."); } } } } ################################################################################ ## SUB recv_command ## Read a command from the client, ended by a new line character. ################################################################################ sub recv_command { my $buffer; my $char; my $command = ''; my $read; my $total = 0; while (1) { ($read, $buffer) = recv_data ($t_block_size); $command .= $buffer; $total += $read; # Check if the command is complete $char = chop ($command); if ($char eq "\n") { return $command; } $command .= $char; # Avoid overflow if ($total > $t_block_size) { error ("Received too much data from " . $t_socket->sockhost ()); } } } ################################################################################ ## SUB recv_data_block ## Read $_[0] bytes of data from the client. ################################################################################ sub recv_data_block { my $buffer = ''; my $data = ''; my $read; my $size = $_[0]; my $total = 0; while (1) { ($read, $buffer) = recv_data ($size - $total); $data .= $buffer; $total += $read; # Check if all data has been read if ($total == $size) { return $data; } } } ################################################################################ ## SUB ask_passwd ## Asks the user for a password. ################################################################################ sub ask_passwd { my $msg1 = $_[0]; my $msg2 = $_[1]; my $pwd1; my $pwd2; require Term::ReadKey; # Disable keyboard echo Term::ReadKey::ReadMode('noecho'); # Promt for password print ($msg1); $pwd1 = Term::ReadKey::ReadLine(0); print ("\n$msg2"); $pwd2 = Term::ReadKey::ReadLine(0); print ("\n"); # Restore original settings Term::ReadKey::ReadMode('restore'); if ($pwd1 ne $pwd2) { # Call print to bypass quiet mode. print ("[err] Passwords do not match.\n"); exit 1; } # Remove the trailing new line character chop $pwd1; return $pwd1; } ################################################################################ # Main ################################################################################ my $file; # Parse command line options parse_options (); # Check command line arguments if ($t_recv == 0 && $#ARGV == -1) { error ("No files to send."); } # Connect to the server if ($t_proxy_address eq '') { start_client (); } else { start_client_proxy (); } # Start SSL if ($t_ssl == 1) { start_ssl (); } # Authenticate with server if ($t_pwd ne '') { auth_pwd (); } if ($t_recv == 0) { # Check that all files exist before trying to send them foreach $file (@ARGV) { if (! -f $file) { error ("File '$file' does not exist."); } } # Send the files foreach $file (@ARGV) { send_file ($file); } } else { # Send the files foreach $file (@ARGV) { recv_file ($file); } } # Tell the server that we are finished send_data ("QUIT\n"); stop_client (); exit 0; __END__ =head1 OPTIONS =over =item I<-a address> B (default 127.0.0.1). =item I<-c> Enable B without a client certificate. =item I<-e cert> B file. Enables SSL. =item I<-f ca> Verify that the peer certificate is signed by a B (Certificate Authority). =item I<-g> B files from the server. =item I<-h> Show B. =item I<-k key> B file. =item I<-p port> B (default I<41121>). =item I<-q> B. Do now print error messages. =item I<-r number> B for network operations (default I<3>). =item I<-t time> B for network operations in seconds (default I<1s>). =item I<-v> Be B. =item I<-w> Prompt for B. =item I<-x pwd> B. =back =head1 EXIT STATUS =over =item 0 on Success =item 1 on Error =back =head1 CONFIGURATION Tentacle doesn't use any configurationf files, all the configuration is done by the options passed when it's started. =head1 DEPENDENCIES L, L, L, L =head1 LICENSE This is released under the GNU Lesser General Public License. =head1 SEE ALSO L, L, L, L Protocol description and more info at: L<< http://openideas.info/wiki/index.php?title=Tentacle >> =head1 COPYRIGHT Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut unix/PaxHeaders.3873/pandora_revent0000644000000000000000000000013212573660551015726 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/pandora_revent0000755000000000000000000002046212573660551015012 0ustar00rootroot00000000000000#!/usr/bin/perl ############################################################################### # Pandora FMS - Remote Event Tool (via WEB API) ############################################################################### # Copyright (c) 2013 Artica Soluciones Tecnologicas S.L # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License version 2 ############################################################################### # Includes list use strict; use LWP::Simple; # Init tool_api_init(); # Main tool_api_main(); ############################################################################## # Print a help screen and exit. ############################################################################## sub help_screen{ print "Options to create event: \t$0 -p -create event Where options:\n -u -create_event -name : Free text -group : Group ID (use 0 for 'all') -type : unknown, alert_fired, alert_recovered, alert_ceased alert_manual_validation, system, error, new_agent configuration_change, going_unknown, going_down_critical, going_down_warning, going_up_normal Optional parameters: [-agent ] : Agent ID [-user ] : User comment (use in combination with -comment option) [-status ] : 0 New, 1 Validated, 2 In process [-am ] : ID Agent Module linked to event [-alert ] : ID Alert Module linked to event [-criticity ] : 0 Maintance, 1 Informative, 2 Normal, 3 Warning, 4 Crit, 5 Minor, 6 Major [-comment ] : Free text for comment [-tag ] : Tag (must exist in the system to be imported) [-source ] : (By default 'Pandora') [-c_instructions ] [-w_instructions ] [-u_instructions ] [-owner ] : Use the login name, not the descriptive \n\n"; print "Credential/API syntax: \n\n\t"; print ": API credentials separated by comma: ,,\n\n"; print "Example of event generation:\n\n"; print "\t$0 -p http://192.168.70.160/pandora_console/include/api.php -u pot12,admin,pandora \ \t-create_event -name \"Sample event executed from commandline\" -group 2 -type \"system\" -agent 2 \ \t-user \"admin\" -status 0 -am 0 -alert 9 -criticity 3 -comment \"User comments\" -tag \"tags\" \ \t-source \"Commandline\" -c_instructions \"Critical instructions\" \ \t-w_instructions \"Warning instructions\" -u_instructions \"Unknown instructions\" -owner \"other\" "; print "\n\nOptions to validate event: \n\n\t"; print "$0 -p -u -validate_event -id \n\n"; print "Sample of event validation: \n\n\t"; print "$0 -p http://localhost/pandora/include/api.php -u pot12,admin,pandora -validate_event -id 234"; print "\n\n\n"; exit; } ############################################################################## # Init screen ############################################################################## sub tool_api_init () { print "\nPandora FMS Remote Event Tool Copyright (c) 2013 Artica ST\n"; print "This program is Free Software, licensed under the terms of GPL License v2\n"; print "You can download latest versions and documentation at http://www.pandorafms.org\n\n"; if ($#ARGV < 0) { help_screen(); } if (($ARGV[0] eq '-h') || ($ARGV[0] eq '-help')) { help_screen(); } } ############################################################################### ############################################################################### # MAIN ############################################################################### ############################################################################### sub tool_api_main () { my $api_path; my $event_name; my $id_group; my $event_type; my $data_event; my $credentials; my $api_pass; my $db_user; my $db_pass; my @db_info; my $id_agent; my $agent_name; my $id_user = ''; my $status = ''; my $id_agent_module = ''; my $module_name = ''; my $id_alert_am = ''; my $criticity = ''; my $user_comment = ''; my $tags = ''; my $source = ''; my $id_extra = ''; my $critical_instructions = ''; my $warning_instructions = ''; my $unknown_instructions = ''; my $owner_user = ''; my $id_event; my $option = $ARGV[4]; my $call_api; #~ help or api path (required) if ($ARGV[0] eq '-h') { print "HELP!\n"; help_screen(); } elsif ($ARGV[0] ne '-p') { print "[ERROR] Missing API path! Read help info:\n\n"; help_screen (); } else { $api_path = $ARGV[1]; } #~ credentials of database if ($ARGV[2] eq '-u') { $credentials = $ARGV[3]; @db_info = split(',', $credentials); if ($#db_info < 2) { print "[ERROR] Invalid database credentials! Read help info:\n\n"; help_screen(); } else { $api_pass = $db_info[0]; $db_user = $db_info[1]; $db_pass = $db_info[2]; } } else { print "[ERROR] Missing database credentials! Read help info:\n\n"; help_screen (); } if ($ARGV[4] eq '-create_event') { #~ event name (required) if ($ARGV[5] ne '-name') { print "[ERROR] Missing event name! Read help info:\n\n"; help_screen (); } else { $event_name = $ARGV[6]; } #~ id group (required) if ($ARGV[7] ne '-group') { print "[ERROR] Missing event group! Read help info:\n\n"; help_screen (); } else { $id_group = $ARGV[8]; } #~ id group (required) if ($ARGV[9] ne '-type') { print "[ERROR] Missing event type! Read help info:\n\n"; help_screen (); } else { $event_type = $ARGV[10]; } # -agent_name, -module_name and -extra are not supported by api. Maybe in the future my $i = 0; foreach (@ARGV) { my $line = $_; if ($line eq '-agent') { $id_agent = $ARGV[$i+1]; } if ($line eq '-agent_name') { $agent_name = $ARGV[$i+1]; } if ($line eq '-user') { $id_user = $ARGV[$i+1]; } if ($line eq '-status') { $status = $ARGV[$i+1]; } if ($line eq '-am') { $id_agent_module = $ARGV[$i+1]; } if ($line eq '-module_name') { $module_name = $ARGV[$i+1]; } if ($line eq '-alert') { $id_alert_am = $ARGV[$i+1]; } if ($line eq '-criticity') { $criticity = $ARGV[$i+1]; } if ($line eq '-comment') { $user_comment = $ARGV[$i+1]; } if ($line eq '-tag') { $tags = $ARGV[$i+1]; } if ($line eq '-source') { $source = $ARGV[$i+1]; } if ($line eq '-extra') { $id_extra = $ARGV[$i+1]; } if ($line eq '-c_instructions') { $critical_instructions = $ARGV[$i+1]; } if ($line eq '-w_instructions') { $warning_instructions = $ARGV[$i+1]; } if ($line eq '-u_instructions') { $unknown_instructions = $ARGV[$i+1]; } if ($line eq '-owner') { $owner_user = $ARGV[$i+1]; } $i++; } $data_event .= $event_name.",".$id_group.",".$id_agent.",".$status.",".$id_user.",".$event_type.",".$criticity.",".$id_agent_module.",".$id_alert_am.",".$critical_instructions.",".$warning_instructions.",".$unknown_instructions.",".$user_comment.",".$owner_user.",".$source.",".$tags.","; $call_api = $api_path.'?op=set&op2=create_event&id='.$event_name.'&other='.$data_event.'&other_mode=url_encode_separator_,&apipass='.$api_pass.'&user='.$db_user.'&pass='.$db_pass; } elsif ($ARGV[4] eq '-validate_event') { #~ id event(required) if ($ARGV[5] ne '-id') { print "[ERROR] Missing id event! Read help info:\n\n"; help_screen (); } else { $id_event = $ARGV[6]; } $call_api = $api_path.'?op=set&op2=validate_event_by_id&id='.$id_event.'&apipass='.$api_pass.'&user='.$db_user.'&pass='.$db_pass; } my @args = @ARGV; my $ltotal=$#args; if ($ltotal < 0) { print "[ERROR] No valid arguments. Read help info:\n\n"; help_screen (); exit; } else { my $content = get($call_api); if ($option eq '-create_event') { if ($content eq undef) { print "[ERROR] Not respond or bad syntax. Read help info:\n\n"; help_screen(); } else { print "Event ID: $content"; } } elsif ($option eq '-validate_event') { print "[RESULT] $content"; } } print "\nExiting!\n\n"; exit; } unix/PaxHeaders.3873/collections0000644000000000000000000000013212573660551015235 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861801.561395235 30 ctime=1441751401.987006935 unix/collections/0000755000000000000000000000000012573660551014367 5ustar00rootroot00000000000000unix/collections/PaxHeaders.3873/.empty0000644000000000000000000000013212573660551016451 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/collections/.empty0000644000000000000000000000000212573660551015516 0ustar00rootroot00000000000000 unix/PaxHeaders.3873/HP-UX0000644000000000000000000000013212607712676013564 xustar000000000000000030 mtime=1444910526.842382736 30 atime=1444910525.218294272 30 ctime=1444910526.842382736 unix/HP-UX/0000755000000000000000000000000012607712676012716 5ustar00rootroot00000000000000unix/HP-UX/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017312 xustar000000000000000030 mtime=1444910526.838382519 30 atime=1444910526.838382519 30 ctime=1444910526.842382736 unix/HP-UX/pandora_agent.conf0000644000000000000000000001152012607712676016366 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, HP-UX Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name xxxxxx # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). # server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). # server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). # server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent # delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) # pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. # cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) # remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. # secondary_mode on_error # secondary_server_ip localhost # secondary_server_path /var/spool/pandora/data_in # secondary_server_port 41121 # secondary_transfer_mode tentacle # secondary_server_pwd mypassword # secondary_server_ssl no # secondary_server_opts # Module Definition # ================= # System information # All this commands has been tested on a Standard HP-UX B.11.31 module_begin module_name disk_usage_/ module_type generic_data module_exec df -P | grep -e "/$" | awk '{print $5}' | tr -d % module_description Disk usage on / (%) module_end module_begin module_name disk_usage_/var module_type generic_data module_exec df -P | grep -e "/var$" | awk '{print $5}' | tr -d % module_description Disk usage on / var(%) module_end module_begin module_name proctotal module_type generic_data module_exec ps -ex | wc -l | awk '{ print $1 }' module_end module_begin module_name sshDaemon module_type generic_proc module_exec ps -e | grep "sshd" | grep -v "grep" | wc -l | awk '{ print $1 }' module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end module_begin module_name Swap_Free module_type generic_data module_exec /usr/sbin/swapinfo -t | grep memory | tr -d "%" | awk '{ print 100-$5 }' module_description Unused swap memory module_end module_begin module_name RAM_Free module_type generic_data module_exec /usr/sbin/swapinfo -t | grep memory | awk '{print $4}' module_description Unused RAM memory module_end module_begin module_name CPU_User module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $16 }' module_description % of USER CPU module_end module_begin module_name CPU_System module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $17 }' module_description % of system CPU module_end module_plugin grep_log /var/adm/syslog/syslog.log Syslog . unix/PaxHeaders.3873/README0000644000000000000000000000013212573660551013654 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/README0000644000000000000000000000341712573660551012736 0ustar00rootroot00000000000000Pandora FMS : The Flexible Monitoring System ============================================ http://www.pandorafms.org How to install -------------- Run this command to see available options: ./pandora_agent_installer What is Pandora FMS? -------------------- Pandora FMS is a monitoring application to watch systems and applications. Pandora FMS allows to know the status of any element of your bussiness systems. Pandora FMS watches your hardware, your software, your multilayer system and, of course, your Operating System. Pandora FMS can detect a network interface down or the movement of any NASDAQ new technology market value. If you wish, Pandora FMS can send a SMS message when your system or your application fails... or when Google stock value drops below 330 US$. Pandora FMS will adjust, like an octopus, to your systems and requirements, because it has been designed to be open, modular, multiplattform and easy to customize. Pandora FMS is developed for system administrators. About the generic Unix agent ---------------------------- This agent is build on Perl and needs the following minimal requisites: PERL version 5.8 or higher. By default this minimum OS has all the requisites to run "standalone": - Linux: Redhat 6, SUSE 5, Debian 2.x and any distro with Perl 5.6 - IBM AIX: 5.1 - Hewlett Packard HPUX: 11.10 or higher. 11.0 comes with Perl 4.0 :( - Sun Solaris: 2.9. With 2.8 you can install BlastWare Perl 5.8 package, see more information in our FAQ about how to install Blashware packages. - Other Unix: TRU, IRIX, etc not tested, if you want to port the agent to this unixes, please contact with us, we'll glad to port them !!! License ------- The project is distributed under the GPL License v2 or later. Copyright (C) 2004-2011 Pandora FMS development team unix/PaxHeaders.3873/pandora_agent.redhat.spec0000644000000000000000000000013212607712676017724 xustar000000000000000030 mtime=1444910526.658372714 30 atime=1444910526.658372714 30 ctime=1444910526.658372714 unix/pandora_agent.redhat.spec0000644000000000000000000000776212607712676017015 0ustar00rootroot00000000000000# #Pandora FMS Linux Agent # %define name pandorafms_agent_unix %define version 6.0 %define release 1 Summary: Pandora FMS Linux agent, PERL version Name: %{name} Version: %{version} Release: %{release} License: GPL Vendor: ArticaST Source0: %{name}-%{version}.tar.gz URL: http://pandorafms.org Group: System/Monitoring Packager: Sancho Lerena Prefix: /usr/share BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildArch: noarch PreReq: /bin/sed /bin/grep /usr/sbin/useradd Requires: coreutils unzip AutoReq: 0 Provides: %{name}-%{version} %description Pandora FMS agent for unix. Pandora FMS is an OpenSource full-featured monitoring software. %prep rm -rf $RPM_BUILD_ROOT %setup -q -n unix %build %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{prefix}/pandora_agent/ mkdir -p $RPM_BUILD_ROOT/usr/bin/ mkdir -p $RPM_BUILD_ROOT/usr/sbin/ mkdir -p $RPM_BUILD_ROOT/etc/pandora/ mkdir -p $RPM_BUILD_ROOT/etc/init.d/ mkdir -p $RPM_BUILD_ROOT/var/log/pandora/ mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf * $RPM_BUILD_ROOT%{prefix}/pandora_agent/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/tentacle_client $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_exec $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/pandora_agent.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/tentacle_client.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/Linux/pandora_agent.conf $RPM_BUILD_ROOT/usr/share/pandora_agent/pandora_agent.conf.rpmnew if [ -f $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec ] ; then rm $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec fi %clean rm -Rf $RPM_BUILD_ROOT %pre getent passwd pandora >/dev/null || \ /usr/sbin/useradd -d %{prefix}/pandora -s /bin/false -M -g 0 pandora exit 0 %post if [ ! -d /etc/pandora ] ; then mkdir -p /etc/pandora fi if [ ! -f /usr/share/pandora_agent/pandora_agent.conf ] ; then cp /usr/share/pandora_agent/pandora_agent.conf.rpmnew /usr/share/pandora_agent/pandora_agent.conf fi if [ ! -f /etc/pandora/pandora_agent.conf ] ; then ln -s /usr/share/pandora_agent/pandora_agent.conf /etc/pandora/pandora_agent.conf else ln -s /usr/share/pandora_agent/pandora_agent.conf.rpmnew /etc/pandora/pandora_agent.conf.rpmnew fi if [ ! -e /etc/pandora/plugins ]; then ln -s /usr/share/pandora_agent/plugins /etc/pandora fi if [ ! -e /etc/pandora/collections ]; then ln -s /usr/share/pandora_agent/collections /etc/pandora fi mkdir -p /var/spool/pandora/data_out /sbin/chkconfig --add pandora_agent_daemon /sbin/chkconfig pandora_agent_daemon on %preun # Upgrading if [ "$1" = "1" ]; then exit 0 fi /sbin/chkconfig --del pandora_agent_daemon /etc/init.d/pandora_agent_daemon stop rm /etc/init.d/pandora_agent_daemon /usr/sbin/userdel pandora rm -Rf /etc/pandora/pandora_agent.conf rm -Rf /var/log/pandora/pandora_agent* 2> /dev/null rm -Rf /usr/share/pandora_agent rm -Rf /usr/share/man/man1/pandora_agent.1.gz rm -Rf /usr/share/man/man1/tentacle_client.1.gz exit 0 %files %defattr(750,pandora,root) /usr/bin/pandora_agent /usr/bin/pandora_agent_exec %defattr(-,pandora,root,770) /var/log/pandora/ %defattr(755,pandora,root) /usr/bin/tentacle_client /etc/init.d/pandora_agent_daemon %docdir %{prefix}/pandora_agents/docs %{prefix}/pandora_agent %defattr(644,pandora,root) /usr/share/man/man1/pandora_agent.1.gz /usr/share/man/man1/tentacle_client.1.gz unix/PaxHeaders.3873/Linux0000644000000000000000000000013212607712676014022 xustar000000000000000030 mtime=1444910526.842382736 30 atime=1444910525.218294272 30 ctime=1444910526.842382736 unix/Linux/0000755000000000000000000000000012607712676013154 5ustar00rootroot00000000000000unix/Linux/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017550 xustar000000000000000030 mtime=1444910526.842382736 30 atime=1444910526.842382736 30 ctime=1444910526.842382736 unix/Linux/pandora_agent.conf0000644000000000000000000001662312607712676016635 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2014 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # Optional. UDP Server to receive orders from outside # By default is disabled, set 1 to enable # Set port (41122 by default) # Set address to restrict who can order a agent restart (0.0.0.0 = anybody) # udp_server 0 udp_server_port 41122 udp_server_auth_address 0.0.0.0 #process_xeyes_start xeyes #process_xeyes_stop killall xeyes # By default, agent takes machine name #agent_name adama # To define agent name by specific command, define 'agent_name_cmd'. # (In the following example, agent name is 'hostname_IP') #agent_name_cmd LANG=C; /bin/echo -n `hostname`; /bin/echo -n "_"; /bin/echo `/sbin/ifconfig eth0 | /bin/grep 'inet addr' | /usr/bin/awk '{print $2;}' | /usr/bin/cut -d: -f2` #Parent agent_name #parent_agent_name caprica # Agent description #description This is a demo agent for Linux # Group assigned for this agent (descriptive, p.e: Servers) group Servers # address: Enforce to server a ip address to this agent # You can also try to detect the first IP using "auto", for example address auto # or setting a fixed IP address, like for example: #address 192.168.36.73 # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature #autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # gis_exec: Call a script that returns a string with a fixed # format of latitude,longitude,altitude # i.e.: 41.377,-5.105,2.365 #gis_exec /tmp/gis.sh # This sets the GIS coordinates as fixed values: # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #GPS Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. #encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # timeout in seconds for file transfer programs execution (30 by default) #transfer_timeout 30 # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) remote_config 0 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user pandora # Enable or disable XML buffer. # If you are in a secured environment and want to enable the XML buffer you # should consider changing the temporal directory, since /tmp is world writable. xml_buffer 1 # Minimum available bytes in the temporal directory to enable the XML buffer temporal_min_size 1024 # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_transfer_timeout 30 #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on linux distro and vmstat command version, please check before use it module_begin module_name CPU Load module_type generic_data module_interval 1 module_exec vmstat 1 2 | tail -1 | awk '{ print $13 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_min_warning 70 module_max_warning 90 module_min_critical 91 module_max_critical 100 module_unit % module_end # vmstat syntax depends on linux distro and vmstat command version, please check before use it module_begin module_name CPU IOWait module_type generic_data module_interval 1 module_exec vmstat 1 2 | tail -1 | awk '{ print $16 }' module_min_warning 10 module_min_critical 16 module_unit % module_end #Get load average module_begin module_name Load Average module_type generic_data module_exec cat /proc/loadavg | cut -d' ' -f1 module_description Average process in CPU (Last minute) module_end #IO Wait CPU ticks /sec module_begin module_name IOWaitCPU module_type generic_data_inc module_exec vmstat -s | grep "IO-wait cpu ticks" | awk '{ print $1 }' module_unit ticks/sec module_description Too much IOwait means IO bottleneck and performance problems. Check also LoadAVG. module_end #Connected users module_begin module_name Connected users module_type generic_data module_exec who | wc -l module_end #Count total number of processes module_begin module_name Number processes module_type generic_data module_exec ps aux | wc -l module_description Total processes module_unit processes module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_description Monitor last user loggin module_end # This plugin detects all disk and report free space (%) module_plugin pandora_df_free # This plugin detects system free memory and free swap (in %) module_plugin pandora_mem # This plugin will get the network usage (bytes/sec) module_plugin pandora_netusage # This parses /var/log/syslog file, under the module name "Syslog_error" # And search for "ERROR" string into it, sending only that information. module_plugin grep_log /var/log/syslog Syslog_error ERROR # Plugin for inventory on the agent (Only Enterprise) # module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users route # Log collection modules. Only for enterprise version, this will collect log files for forensic analysis. # This is for LOG monitoring, only on enterprise version #module_plugin grep_log_module /var/log/messages Syslog \.\* unix/PaxHeaders.3873/NetBSD0000644000000000000000000000013212607712676014002 xustar000000000000000030 mtime=1444910526.846382955 30 atime=1444910525.218294272 30 ctime=1444910526.846382955 unix/NetBSD/0000755000000000000000000000000012607712676013134 5ustar00rootroot00000000000000unix/NetBSD/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017530 xustar000000000000000030 mtime=1444910526.846382955 30 atime=1444910526.846382955 30 ctime=1444910526.846382955 unix/NetBSD/pandora_agent.conf0000644000000000000000000001307012607712676016606 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, NetBSD Version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name adama #Parent agent_name #parent_agent_name parent_name # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # timeout in seconds for file transfer programs execution (30 by default) #transfer_timeout 30 # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) #remote_config 1 # If set to 1 start Drone Agent's Proxy Mode #proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) #proxy_max_connection 10 # Proxy timeout (by default 1s) #proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_transfer_timeout 30 #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on system configuration, please check before use it module_begin module_name cpu_user module_type generic_data module_interval 1 module_exec vmstat 1 2 | tail -1 | awk '{ print $16 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_end module_begin module_name cpu_system module_type generic_data module_interval 1 module_exec vmstat 1 2 | tail -1 | awk '{ print $17 }' module_max 100 module_min 0 module_description System CPU Usage (%) module_end module_begin module_name cpu_idle module_type generic_data module_interval 1 module_exec vmstat 1 2 | tail -1 | awk '{ print $18 }' module_max 100 module_min 0 module_description CPU Idle (%) module_end module_begin module_name Load Average module_type generic_data module_exec uptime | cut -d "," -f 4 | cut -d ":" -f 2 | sed "s/ //g" module_description Average process in CPU (Last minute) module_end module_begin module_name disk_root_free module_type generic_data module_exec df -kh / | tail -1 | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name memfree module_type generic_data module_exec vmstat -t 1 2 | tail -1 | awk '{print $12}' module_description Unused RAM memory module_end module_begin module_name proctotal module_type generic_data module_exec ps -A | wc -l | sed "s/ //g" module_end # Process information module_begin module_name sshDaemon module_type generic_proc module_exec ps -A | grep sshd | grep -v "grep" | wc -l | sed "s/ //g" module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end # Plugin example # This parses /var/log/auth.log file, under the module name "syslog" # And search for "sshd" string into it, sending only that information. module_plugin grep_log /var/log/auth.log Syslog sshd # Plugin for inventory on the agent (Only Enterprise) # module_plugin inventory 1 cpu ram video nic hd cdrom software unix/NetBSD/PaxHeaders.3873/pandora_agent0000644000000000000000000000013212573660551016600 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/NetBSD/pandora_agent0000755000000000000000000000176712573660551015673 0ustar00rootroot00000000000000#!/bin/sh # ********************************************************************** # Pandora FMS Agent Daemon launcher for NetBSD # (c) 2013 Hiroki SHIMIZU # # ********************************************************************** # PROVIDE: pandora_agent # REQUIRE: LOGIN # KEYWORD: shutdown # Add the following line to /etc/rc.conf to enable `pandora_agent': # # pandora_agent="YES" # . "/etc/rc.subr" name="pandora_agent" rcvar=${name} # read configuration and set defaults pandora_agent=${pandora_agent:-"NO"} load_rc_config "$name" PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin command=/usr/local/bin/pandora_agent command_args="/usr/local/etc/pandora &" pidfile=/var/run/$name.pid required_files="/usr/local/etc/pandora/pandora_agent.conf" start_postcmd=start_postcmd stop_postcmd=stop_postcmd procname="/usr/pkg/bin/perl" start_postcmd() { sleep 1 PANDORA_PID=`pgrep -f none $name` echo $PANDORA_PID > $pidfile } stop_postcmd() { rm -f $pidfile } run_rc_command "$1" unix/PaxHeaders.3873/OpenWRT0000644000000000000000000000013212573660551014215 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861801.561395235 30 ctime=1441751401.987006935 unix/OpenWRT/0000755000000000000000000000000012573660551013347 5ustar00rootroot00000000000000unix/OpenWRT/PaxHeaders.3873/INSTALL0000644000000000000000000000013212573660551015323 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/OpenWRT/INSTALL0000644000000000000000000000336512573660551014407 0ustar00rootroot00000000000000Perl Agent =========== Dependencies ------------ This is the generic Unix package, developed in Perl. In order to use it, you need to install a few packages first. This will be done using opkg (command line packager tool): opkg install perl opkg install perlbase-autoloader opkg install perlbase-base opkg install perlbase-config opkg install perlbase-errno opkg install perlbase-essential opkg install perlbase-fcntl opkg install perlbase-file opkg install perlbase-hostname opkg install perlbase-io opkg install perlbase-posix opkg install perlbase-selectsaver opkg install perlbase-socket opkg install perlbase-symbol opkg install perlbase-sys opkg install perlbase-tie opkg install perlbase-xsloader opkg install coreutils-nohup opkg install perlbase-getopt Install procedure ----------------- Step 1 - Get the latest package and copy to /tmp, you can get the latest package at: http://sourceforge.net/projects/pandora/files/Pandora%20FMS%203.2/Stable%20release/Unix%20%28Tarball%29/pandorafms_agent_unix-3.2.tar.gz/download Note: You will get a special version of the launcher, you can get it from our SVN repository and replace the perl daemon launcher with this special version for OpenWRT. Just replace it after do the package install for the Unix/Perl generic agent. Step 2 - Install it cd /tmp tar xvzf pandorafms_agent_unix-3.2.tar.gz cd unix ./pandora_agent --install Step 3 - Create the startup link to run pandora agent when device restarts ln -s /etc/init.d/pandora_agent_daemon /etc/rc.d/S99pandora_agent Step 4 - Customize the agent name and server_ip for this device vi /etc/pandora/pandora_agent.conf Alter line "agent_name" for the devicename you want Step 5 - Start it manually: /etc/init.d/pandora_agent_daemon start unix/OpenWRT/PaxHeaders.3873/pandora_agent_daemon0000644000000000000000000000013212573660551020342 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/OpenWRT/pandora_agent_daemon0000755000000000000000000000314212573660551017422 0ustar00rootroot00000000000000#!/bin/sh # Pandora FMS Embedded Agent, startup script # Copyright (c) 2011 Artica ST, # Tested on Busybox 1.13 # v4.0 Build 110122 # http://www.pandorafms.com PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin PANDORA_PATH=/etc/pandora DAEMON=/usr/bin/pandora_agent LOGFILE=/dev/null # This function replace pidof # not working in the same way in different linux distros pidof_pandora() { COLUMNS=250 PANDORA_PID=`ps | grep $DAEMON | grep -v grep | head -1 | awk '{ print $1 }'` echo $PANDORA_PID } if [ ! -f $DAEMON ] then echo "Pandora FMS Agent not found at $DAEMON, please check setup" exit fi case "$1" in start) PANDORA_PID=`pidof_pandora` if [ ! -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is currently running on this machine with PID $PANDORA_PID" echo "Cannot launch again. Aborting." exit 1 fi nohup $DAEMON $PANDORA_PATH 2> $LOGFILE & sleep 1 PANDORA_PID=`pidof_pandora` echo "Pandora FMS Agent is now running with PID $PANDORA_PID" ;; stop) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running, cannot stop it. Aborting now..." exit 1 else echo "Stopping Pandora FMS Agent." kill $PANDORA_PID > /dev/null 2>&1 fi ;; status) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running." else echo "Pandora FMS Agent is running with PID $PANDORA_PID." fi exit 0 ;; force-reload|restart) $0 stop sleep 2 $0 start ;; *) echo "Usage: /etc/init.d/pandora_agent_daemon {start|stop|restart|status|force-reload}" exit 1 esac unix/PaxHeaders.3873/pandora_agent_daemon0000644000000000000000000000013212573660551017044 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/pandora_agent_daemon0000755000000000000000000000655212573660551016134 0ustar00rootroot00000000000000#!/bin/sh # ********************************************************************** # Pandora FMS Agent Daemon launcher for Unix (AIX, HP-UX, SunOS, Linux) # (c) 2008-2010 Artica ST # (c) 2008-2010 Sancho Lerena # # Please see http://www.pandorafms.org # v3.2 Build 101115 # This code is licensed under GPL 2.0 license. # ********************************************************************** ### BEGIN INIT INFO # Provides: pandora_agent # Required-Start: $network # Required-Stop: $network # Default-Start: 2 3 5 # Default-Stop: 0 1 6 # Short-Description: Startup script daemon for Pandora FMS agent # Description: Startup script daemon for Pandora FMS agent (linux) ### END INIT INFO PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin PANDORA_PATH=/etc/pandora DAEMON=/usr/bin/pandora_agent DAEMON_TENTACLE=/usr/bin/tentacle_server LOGFILE=/var/log/pandora/pandora_agent.log PANDORA_USER=root # This function replace pidof, not working in the same way in different linux distros pidof_pandora () { COLUMNS=400 OS_NAME=`uname -s` if [ $OS_NAME = "HP-UX" ] then PANDORA_PID=`ps -ef | grep "/usr/bin/perl $DAEMON" | grep -v grep | awk '{print $2}'` elif [ "$OS_NAME" = "SunOS" ] then ZONENAME_CMD="/bin/zonename" TRUNCATED_DAEMON=`echo "$DAEMON $PANDORA_PATH" | cut -c1-20` if [ -x $ZONENAME_CMD ] then ZONE=`$ZONENAME_CMD` else ZONE= fi if [ "$ZONE" = "global" ] then PANDORA_PID=`ps -f -z global | grep "$TRUNCATED_DAEMON" | grep -v grep | awk '{ print $2 }'` else PANDORA_PID=`ps -Af | grep "$TRUNCATED_DAEMON" | grep -v grep | awk '{ print $2 }'` fi elif [ "$OS_NAME" = "Linux" ] && [ -x /usr/sbin/vzpid ] then # Virtuozzo/OpenVZ local _pid _ctid _pids _pids=`ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | awk '{ print $2 }'` [ "$_pids" ] && for _pid in $_pids do _ctid=`/usr/sbin/vzpid $_pid | awk '$1 == '$_pid' { print $2 }'` if [ "X$_ctid" = "X0" ] then PANDORA_PID=$_pid break fi done else PANDORA_PID=`ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | awk '{ print $2 }'` fi echo $PANDORA_PID } if [ ! -f $DAEMON ] then echo "Pandora FMS Agent not found at $DAEMON, please check setup" exit fi case "$1" in start) PANDORA_PID=`pidof_pandora` if [ ! -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is currently running on this machine with PID $PANDORA_PID" echo "Cannot launch again. Aborting." exit 1 fi su $PANDORA_USER -c "PATH=$PATH nohup $DAEMON $PANDORA_PATH >/dev/null 2>$LOGFILE &" sleep 2 PANDORA_PID=`pidof_pandora` if [ "$PANDORA_PID" = "" ] then echo "Pandora FMS Agent could not be started. Please check the file $LOGFILE." exit 1 else echo "Pandora FMS Agent is now running with PID $PANDORA_PID" fi ;; stop) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running, cannot stop it. Aborting now..." exit 1 else echo "Stopping Pandora Agent." su $PANDORA_USER -c "kill $PANDORA_PID >/dev/null 2>&1" fi ;; status) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running." exit 3 else echo "Pandora FMS Agent is running with PID $PANDORA_PID." exit 0 fi ;; force-reload|restart) $0 stop sleep 2 $0 start ;; *) echo "Usage: /etc/init.d/pandora_agent_daemon {start|stop|restart|status}" exit 1 esac unix/PaxHeaders.3873/man0000644000000000000000000000013212461452004013456 xustar000000000000000030 mtime=1422283780.850535191 30 atime=1444861801.561395235 30 ctime=1422283780.850535191 unix/man/0000755000000000000000000000000012461452004012610 5ustar00rootroot00000000000000unix/man/PaxHeaders.3873/man10000644000000000000000000000013212573660551014326 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861801.561395235 30 ctime=1441751401.987006935 unix/man/man1/0000755000000000000000000000000012573660551013460 5ustar00rootroot00000000000000unix/man/man1/PaxHeaders.3873/tentacle_client.1.gz0000644000000000000000000000013212573660551020241 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/man/man1/tentacle_client.1.gz0000644000000000000000000000232312573660551017316 0ustar00rootroot00000000000000‹’†êKtentacle_client.1¥VïoÛ6ý®¿â/³‡F޲uk»ah’¹k€Äñ ck-Ÿm"©’”ì¯ß;Ò¿’¦Š!€bSwïîÞ½;ú»Û# YŽç÷ßÓdɤ¦vÅTkÃä—¶«g4·®b Óš‚¥),¨uÜ:[±÷ÖÁ/º_+C­Z°˜S`TU³¼Éò¶ÊòÉ{š G“³‹«á§‹«K|¤‚ŽNOŠ“ã“—ÇEqDG'ùi~‚ÿµ†;Íu¨N?g‡6ØÊÖ€+ßÓèìz˜mƒ|ª’Ãí1R«þË9ú–G7ãò²ŒYKÅK®[ªlÓ(3‹…gù9=Ï~µmÐÖøßäådó’2íw1žÝ ÁžMa©)ÝøÄâ'eÔ”zoû¿d5ÕyvüvxÏU‡C@ÀsáìÁ§GŽõ6G»òÁn¨Ruí©7ïL³§•žñŒ¦ˆÈtÇÎp݇Ǖž:å¾tYë°ÔfˆfßG‚Ã,ÛÕºVž*Ç*%@µ‚.ëX2kk¾Ç¹x­ï˜Ê‹1 ¡ï&ã( ¯Åä1;Ç¡Vª~m=r©–4w¶!Õ!t¥$Mj¸Z*£}³Ï \«¤M`§PŠˆÖ.4 ¤¾ã‡Hö‡üåÉkªØ=8ö9•)›Vy¿¶nö4š•F* \‘GCJ®¬1)#4Ýwmk]¢Âæš@öF{±’¤…Þ,ˆ!ýX§EŸÈš±× “XÄ8¹Î¤Š¥_‡2”ÆK·`™ÙÈÀWN·!1f¬$6׋Υ̅_Ãf!?è ò6vãÌx®ºúéœ4–6ò¹ž=¦ó±Ù8ŽAŒá‡³ëñÕ·ä§ç—O/Ä[\·Šn©x}š?½Ê‹¼ 9[á9˜j3˜*¿ÌÊg–~”=5ê^7]“^yý()ÈF,®Ï¿5æ=ž»Mþ-I|mý÷Œ ›ÅßÿßÉ0ž2cy‹ [îðDvߟdÃ>—í—K".ɯ‘Ú8º™ ‡»Åæøs§±§Ò‚~™¿’;f©KÄ÷¢PŸËáήʛý¯¬4é½¢ÿ!ãåðÜÌœdÿ‚V’Y unix/man/man1/PaxHeaders.3873/pandora_agent.1.gz0000644000000000000000000000013212573660551017706 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.828981136 30 ctime=1441751401.987006935 unix/man/man1/pandora_agent.1.gz0000644000000000000000000000134512573660551016766 0ustar00rootroot00000000000000‹\éKpandora_agent.1…TÛN1}÷WŒòRZ%»IR…zQ€"‘‹Ø<•*òzg³Ûµ½¤HýøŽ× Vˆ—•Ïœ9çÌLÞÝuÀ³„¾>À²Bà¹~@¨¥Bp•nêJm‚ÏkðrŠcÑX-Ð9m)¯MŸr†¯1„«B[Ú´á%F°dy‹áìb~3\ /G³%  ó±?è÷ú'½Á ã$|w10žfp‰ -¯á\o6„êB¡†×˜]Ál81‹­¨¸òp×{ªÒ.ý–[b^Û¤ìv6_d“Œ%g6Φ¹Téû,´*庱ÜK­V¥¬ñ+K­Ð`’mTê¼6 "«Ö¯½H¥’>)!WÇVÀ~„°ËþÄ·>-ÆËÏ–åÅ(;¿™,–“ùŒ…×—¢†­R`Ò…f ­{9wX7¦–¢åÜ…m%EEë…w 5fÓ¾…7j-ÈW÷轆‚{Á¢.¸À‹Þ:ÐÎ@ÂØÄCãÐEvæš”ÛC~eÀmÅýq)±Ä¯ÒÛ¾F óÏ¢²½’ö•y´»1à„•ÆA¾Ù± W+o5Í?µž|C^”í-Î\(’Æ—Âã[[ØÓ‰‹W¢–;‹¼åÊ•h_êëBNþ Ú$^»]ÈFRø¿>4.Èä;¡ÁûØFbjáh6κMϺ1à=]h¢h/ÇË‘¼ÕM[$ضѴ³á[aº,¥¾ÅÜÉÐkÊXå½9MSmPɹKBfº•÷’,,ðwb*óÍK_ã—«ã¤z¡E³ ´Û„*îî|9ÊØÿcmñW#i`Aƒ 'ɧ@¼’kêzðm«í½c-ÂxrM¯¬p’[öVoŸƒ^ÇX*`xÍŸþlâT ÈÛ}séÂþcA»ÅOunix/PaxHeaders.3873/pandora_agent.spec0000644000000000000000000000013212607712676016456 xustar000000000000000030 mtime=1444910526.642371842 30 atime=1444910526.642371842 30 ctime=1444910526.642371842 unix/pandora_agent.spec0000644000000000000000000000776412607712676015551 0ustar00rootroot00000000000000# #Pandora FMS Linux Agent # %define name pandorafms_agent_unix %define version 6.0 %define release 1 Summary: Pandora FMS Linux agent, PERL version Name: %{name} Version: %{version} Release: %{release} License: GPL Vendor: ArticaST Source0: %{name}-%{version}.tar.gz URL: http://pandorafms.org Group: System/Monitoring Packager: Sancho Lerena Prefix: /usr/share BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildArch: noarch PreReq: %fillup_prereq %insserv_prereq /usr/bin/sed /usr/bin/grep /usr/sbin/useradd Requires: coreutils unzip AutoReq: 0 Provides: %{name}-%{version} %description Pandora FMS agent for unix. Pandora FMS is an OpenSource full-featured monitoring software. %prep rm -rf $RPM_BUILD_ROOT %setup -q -n unix %build %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{prefix}/pandora_agent/ mkdir -p $RPM_BUILD_ROOT/usr/bin/ mkdir -p $RPM_BUILD_ROOT/usr/sbin/ mkdir -p $RPM_BUILD_ROOT/etc/pandora/ mkdir -p $RPM_BUILD_ROOT/etc/init.d/ mkdir -p $RPM_BUILD_ROOT/var/log/pandora/ mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf * $RPM_BUILD_ROOT%{prefix}/pandora_agent/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/tentacle_client $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_exec $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/pandora_agent.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/tentacle_client.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/Linux/pandora_agent.conf $RPM_BUILD_ROOT/usr/share/pandora_agent/pandora_agent.conf.rpmnew #if [ -f $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec ] ; then # rm $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec #fi %clean rm -Rf $RPM_BUILD_ROOT %pre if [ "`id pandora | grep uid | wc -l`" = 0 ] then /usr/sbin/useradd -d %{prefix}/pandora -s /bin/false -M -g 0 pandora fi %post if [ ! -d /etc/pandora ] ; then mkdir -p /etc/pandora fi if [ ! -f /usr/share/pandora_agent/pandora_agent.conf ] ; then cp /usr/share/pandora_agent/pandora_agent.conf.rpmnew /usr/share/pandora_agent/pandora_agent.conf fi if [ ! -f /etc/pandora/pandora_agent.conf ] ; then ln -s /usr/share/pandora_agent/pandora_agent.conf /etc/pandora/pandora_agent.conf else ln -s /usr/share/pandora_agent/pandora_agent.conf.rpmnew /etc/pandora/pandora_agent.conf.rpmnew fi if [ ! -e /etc/pandora/plugins ]; then ln -s /usr/share/pandora_agent/plugins /etc/pandora fi if [ ! -e /etc/pandora/collections ]; then ln -s /usr/share/pandora_agent/collections /etc/pandora fi mkdir -p /var/spool/pandora/data_out chkconfig pandora_agent_daemon on %preun # Upgrading if [ "$1" = "1" ]; then exit 0 fi chkconfig --del pandora_agent_daemon /etc/init.d/pandora_agent_daemon stop rm /etc/init.d/pandora_agent_daemon /usr/sbin/userdel pandora rm -Rf /etc/pandora/pandora_agent.conf rm -Rf /var/log/pandora/pandora_agent* 2> /dev/null rm -Rf /usr/share/pandora_agent rm -Rf /usr/share/man/man1/pandora_agent.1.gz rm -Rf /usr/share/man/man1/tentacle_client.1.gz exit 0 %files %defattr(750,pandora,root) /usr/bin/pandora_agent /usr/bin/pandora_agent_exec %defattr(-,pandora,root,770) /var/log/pandora/ %defattr(755,pandora,root) /usr/bin/tentacle_client /etc/init.d/pandora_agent_daemon %docdir %{prefix}/pandora_agents/docs %{prefix}/pandora_agent %defattr(644,pandora,root) /usr/share/man/man1/pandora_agent.1.gz /usr/share/man/man1/tentacle_client.1.gz unix/PaxHeaders.3873/DEBIAN0000644000000000000000000000013212607712676013645 xustar000000000000000030 mtime=1444910526.678373803 30 atime=1444910526.834382301 30 ctime=1444910526.678373803 unix/DEBIAN/0000755000000000000000000000000012607712676012777 5ustar00rootroot00000000000000unix/DEBIAN/PaxHeaders.3873/make_deb_package.sh0000644000000000000000000000013212607712676017460 xustar000000000000000030 mtime=1444910526.674373585 30 atime=1444910526.674373585 30 ctime=1444910526.678373803 unix/DEBIAN/make_deb_package.sh0000644000000000000000000000726512607712676016547 0ustar00rootroot00000000000000#!/bin/bash #Pandora FMS- http:#pandorafms.com # ================================================== # Copyright (c) 2005-2010 Artica Soluciones Tecnologicas # Please see http:#pandorafms.org for full contribution list # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License # as published by the Free Software Foundation; version 2 # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. pandora_version="6.0" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null if [ $? = 1 ] then echo "No found \"dpkg-deb\" aplication, please install." exit 1 else echo "Found \"dpkg-debs\"." fi cd .. echo "Make a \"temp_package\" temp dir for job." mkdir -p temp_package/usr mkdir -p temp_package/usr/share/pandora_agent/ mkdir -p temp_package/usr/bin/ mkdir -p temp_package/usr/sbin/ mkdir -p temp_package/etc/pandora/plugins mkdir -p temp_package/etc/pandora/collections mkdir -p temp_package/etc/init.d/ mkdir -p temp_package/var/log/pandora/ mkdir -p temp_package/var/spool/pandora/data_out mkdir -p temp_package/usr/share/man/man1/ mkdir -p temp_package/usr/share/pandora_agent/plugins mkdir -p temp_package/tmp echo "Make directory system tree for package." cp DEBIAN temp_package -R chmod 755 -R temp_package/DEBIAN #Next lines is same to #cp -aRf * temp_package/usr/share/pandora_agent/ #but don't copy recursive the temp_package into temp_package for item in `ls | grep -v NT4 | grep -v AIX | grep -v FreeBSD | grep -v HP-UX | grep -v SunOS | grep -v temp_package` do #if [ \( $item != 'temp_package' \) -a \( $item != 'NT4' \) ] #then cp -aRf $item temp_package/usr/share/pandora_agent/ #fi done cp -aRf tentacle_client temp_package/usr/bin/ cp -aRf pandora_agent temp_package/usr/bin/ cp -aRf pandora_agent_exec temp_package/usr/bin/pandora_agent_exec cp -aRf pandora_agent_daemon temp_package/etc/init.d/pandora_agent_daemon cp Linux/pandora_agent.conf temp_package/etc/pandora/ cp -aRf man/man1/* temp_package/usr/share/man/man1/ # Relocate plugins to the final dir and delete mv temp_package/usr/share/pandora_agent/plugins/* temp_package/etc/pandora/plugins echo "Official plugins are placed on /etc/pandora/plugins" > temp_package/usr/share/pandora_agent/plugins/README #Disabled, now the package overwrite the previous files. ##Create a temp file for to update files of plugins dir but don't crush dir. ##cp -aRf temp_package/usr/share/pandora_agent/plugins temp_package/tmp ##rm -rf temp_package/usr/share/pandora_agent/plugins/* echo "Remove the SVN files and other temp files." for item in `find temp_package` do echo -n "." echo $item | grep "svn" > /dev/null #last command success if [ $? -eq 0 ] then rm -rf $item fi echo $item | grep "make_deb_package.sh" > /dev/null #last command success if [ $? -eq 0 ] then rm -rf $item fi done echo "END" echo "Calcule md5sum for md5sums file control of package" for item in `find temp_package` do echo -n "." if [ ! -d $item ] then echo $item | grep "DEBIAN" > /dev/null #last command success if [ $? -eq 1 ] then md5=`md5sum $item | cut -d" " -f1` #delete "temp_package" in the path final_path=${item#temp_package} echo $md5" "$final_path >> temp_package/DEBIAN/md5sums fi fi done echo "END" echo "Make the package \"Pandorafms console\"." dpkg-deb --build temp_package mv temp_package.deb pandorafms.agent_unix_$pandora_version.deb echo "Delete the \"temp_package\" temp dir for job." rm -rf temp_package unix/DEBIAN/PaxHeaders.3873/control0000644000000000000000000000013212607712676015325 xustar000000000000000030 mtime=1444910526.678373803 30 atime=1444910526.678373803 30 ctime=1444910526.678373803 unix/DEBIAN/control0000644000000000000000000000141412607712676014402 0ustar00rootroot00000000000000package: pandorafms-agent-unix Version: 6.0 Architecture: all Priority: optional Section: admin Installed-Size: 260 Maintainer: Miguel de Dios Homepage: http://pandorafms.org/ Depends: coreutils, perl, unzip Description: Pandora FMS agents are based on native languages in every platform: scripts that can be written in any language. It’s possible to reproduce any agent in any programming language and can be extended without difï¬culty the existing ones in order to cover aspects not taken into account up to the moment. These scripts are formed by modules that each one gathers a "chunk" of information. Thus, every agent gathers several "chunks" of information; this one is organized in a data set and stored in a single ï¬le, called data ï¬le. unix/DEBIAN/PaxHeaders.3873/md5sums0000644000000000000000000000013212573660551015236 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444862064.559628075 30 ctime=1441751401.955005142 unix/DEBIAN/md5sums0000755000000000000000000000000012573660551014304 0ustar00rootroot00000000000000unix/DEBIAN/PaxHeaders.3873/conffiles0000644000000000000000000000013212573660551015611 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444861867.820980704 30 ctime=1441751401.955005142 unix/DEBIAN/conffiles0000755000000000000000000000004012573660551014663 0ustar00rootroot00000000000000/etc/pandora/pandora_agent.conf unix/DEBIAN/PaxHeaders.3873/postinst0000644000000000000000000000013212573660551015524 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444861867.820980704 30 ctime=1441751401.955005142 unix/DEBIAN/postinst0000755000000000000000000000165412573660551014612 0ustar00rootroot00000000000000#!/bin/bash PANDORA_LOG=/var/log/pandora/pandora_agent.log PANDORA_BIN=/usr/bin/pandora_agent PANDORA_EXEC_BIN=/usr/bin/pandora_agent PANDORA_HOME=/usr/share/pandora_agent PANDORA_CFG=/etc/pandora LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` echo "Start log of agent." echo "$LOG_TIMESTAMP Pandora FMS installer has created this file at startup" > $PANDORA_LOG echo "Setting secure permissions and ownership for all Pandora FMS Agent files..." chmod 700 $PANDORA_BIN chmod 700 $PANDORA_EXEC_BIN #~ chmod 600 $PANDORA_HOME/pandora_agent.conf chmod -R 700 $PANDORA_HOME/plugins chown -R root $PANDORA_HOME chmod 640 $PANDORA_LOG chgrp root $PANDORA_LOG chown -R root:root $PANDORA_BIN chown -R root:root $PANDORA_EXEC_BIN echo "Linking start-up daemon script to /etc/rc$INITLV.d"; update-rc.d pandora_agent_daemon defaults echo "Please, now setup the $PANDORA_HOME/pandora_agent.conf and before start the /etc/init.d/pandora_agent_daemon" unix/DEBIAN/PaxHeaders.3873/prerm0000644000000000000000000000013212573660551014766 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444861867.820980704 30 ctime=1441751401.955005142 unix/DEBIAN/prerm0000755000000000000000000000033612573660551014050 0ustar00rootroot00000000000000#!/bin/bash echo Stop Pandora agent daemon /etc/init.d/pandora_agent_daemon stop PANDORA_CFG=/etc/pandora #rm -rf $PANDORA_CFG/plugins #rm -rf $PANDORA_CFG/pandora_agent.conf update-rc.d -f pandora_agent_daemon remove unix/PaxHeaders.3873/pandora_agent_exec0000644000000000000000000000013212573660551016525 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/pandora_agent_exec0000755000000000000000000000332012573660551015603 0ustar00rootroot00000000000000#!/usr/bin/perl ########################################################################## # pandora_agent_exec # # Executes the given command and prints its output to stdout. If the # execution times out or the command does not exist nothing is printed # to stdout. This is part of Pandora FMS Plugin server, do not delete!. # # Usage: pandora_agent_exec ########################################################################## # Copyright (c) 2008-2010 Ramon Novoa, rnovoa@gmail.com # (c) 2008-2010 Artica Soluciones Tecnologicas S.L # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## use strict; use warnings; # Check command line parameters if ($#ARGV < 1) { exit 1; } my @opts = @ARGV; my $timeout = shift(@opts); my $command = join(' ', @opts); my $output = ''; my $ReturnCode = 0; # Execute the command eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm $timeout; $output = `$command`; $ReturnCode = ($? >> 8) & 0xff; alarm 0; }; # Timeout if ($@ eq "alarm\n") { exit 3; } print $output; exit $ReturnCode; unix/PaxHeaders.3873/AIX0000644000000000000000000000013212607712676013344 xustar000000000000000030 mtime=1444910526.846382955 30 atime=1444910525.218294272 30 ctime=1444910526.846382955 unix/AIX/0000755000000000000000000000000012607712676012476 5ustar00rootroot00000000000000unix/AIX/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017072 xustar000000000000000030 mtime=1444910526.846382955 30 atime=1444910526.846382955 30 ctime=1444910526.846382955 unix/AIX/pandora_agent.conf0000644000000000000000000001006412607712676016150 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, AIX version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name xxxxxx # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). # server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). # server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). # server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent # delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) # pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. # cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) # remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. # secondary_mode on_error # secondary_server_ip localhost # secondary_server_path /var/spool/pandora/data_in # secondary_server_port 41121 # secondary_transfer_mode tentacle # secondary_server_pwd mypassword # secondary_server_ssl no # secondary_server_opts # Module Definition # ================= # System information module_begin module_name disk_root_free module_type generic_data module_exec df -k / | tail -1 | awk '{ print 100-$4 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name proctotal module_type generic_data module_exec ps aux | wc -l | awk '{ print $1 }' module_end # Process information module_begin module_name InetdDaemon module_type generic_proc module_exec ps -Af | grep inetd | grep -v "grep" | wc -l | awk '{ print $1 }' module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end module_begin module_name Pandora_Agent_RAM module_type generic_data module_exec ps axu | grep perl | grep -v grep | awk '{ print $4 }' | tr "," "." module_end module_plugin grep_log /var/adm/syslog Syslog . unix/PaxHeaders.3873/Darwin0000644000000000000000000000013212607712676014147 xustar000000000000000030 mtime=1444910526.850383172 30 atime=1444910525.218294272 30 ctime=1444910526.850383172 unix/Darwin/0000755000000000000000000000000012607712676013301 5ustar00rootroot00000000000000unix/Darwin/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017675 xustar000000000000000030 mtime=1444910526.850383172 30 atime=1444910526.846382955 30 ctime=1444910526.850383172 unix/Darwin/pandora_agent.conf0000644000000000000000000001417112607712676016756 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2012 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # Optional. UDP Server to receive orders from outside # By default is disabled, set 1 to enable # Set port (41122 by default) # Set address to restrict who can order a agent restart (0.0.0.0 = anybody) # udp_server 0 udp_server_port 41122 udp_server_auth_address 0.0.0.0 # By default, agent takes machine name #agent_name adama #Parent agent_name #parent_agent_name caprica # Agent description #description This is a demo agent for Mac OS X. # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # address: Enforce to server a ip address to this agent # You can also try to detect the first IP using "auto", for example #address auto # or setting a fixed IP address, like for example: #address 192.168.36.73 # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature #autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # gis_exec: Call a script that returns a string with a fixed # format of latitude,longitude,altitude # i.e.: 41.377,-5.105,2.365 #gis_exec /tmp/gis.sh # This sets the GIS coordinates as fixed values: # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #GPS Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. #encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) #remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user root # Enable or disable XML buffer. # If you are in a secured environment and want to enable the XML buffer you # should consider changing the temporal directory, since /tmp is world writable. #xml_buffer 0 # Minimum available bytes in the temporal directory to enable the XML buffer #temporal_min_size 1024 # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on linux distro and vmstat command version, please check before use it module_begin module_name cpu_user module_type generic_data module_interval 1 module_exec sar 1 2 | tail -1 | awk '{ print $2 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_min_warning 70 module_max_warning 90 module_min_critical 91 module_max_critical 100 module_end #Get load average module_begin module_name Load Average module_type generic_data module_exec uptime | sed 's/.*load averages: //'|awk '{print $1}' module_description Average process in CPU (Last minute) module_end #Get free memory in MB module_begin module_name Cache mem free module_type generic_data module_exec vm_stat | grep 'Pages free'| awk '{print $3/256}' module_description Free cache memory in MB module_min_warning 500 module_max_warning 600 module_min_critical 100 module_max_critical 499 module_end #Count total number of processes module_begin module_name proctotal module_type generic_data module_exec ps -A | tail -n +2 | wc -l | sed 's/ //g' module_description Total processes module_min_warning 150 module_max_warning 249 module_min_critical 250 module_max_critical 300 module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 | awk '{print $1}' module_description Monitor last user loggin module_end # Get disk space free in % module_begin module_name disk_root_free module_type generic_data module_exec df -kh / | tail -1 | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_min_warning 70 module_max_warning 90 module_min_critical 91 module_max_critical 100 module_end unix/Darwin/PaxHeaders.3873/com.pandorafms.pandorafms.plist0000644000000000000000000000013212573660551022335 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444861867.824980919 30 ctime=1441751401.955005142 unix/Darwin/com.pandorafms.pandorafms.plist0000644000000000000000000000116312573660551021413 0ustar00rootroot00000000000000 Label com.pandorafms.pandorafms ProgramArguments /usr/bin/pandora_agent /etc/pandora RunAtLoad ServiceDescription PandoraFMS agent UserName root unix/PaxHeaders.3873/AUTHORS0000644000000000000000000000013212573660551014044 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444861867.824980919 30 ctime=1441751401.955005142 unix/AUTHORS0000644000000000000000000000015712573660551013124 0ustar00rootroot00000000000000Sancho Lerena Manuel Arostegui Ramon Novoa unix/PaxHeaders.3873/FreeBSD0000644000000000000000000000013212607712676014135 xustar000000000000000030 mtime=1444910526.850383172 30 atime=1444910525.218294272 30 ctime=1444910526.850383172 unix/FreeBSD/0000755000000000000000000000000012607712676013267 5ustar00rootroot00000000000000unix/FreeBSD/PaxHeaders.3873/pandora_agent.conf0000644000000000000000000000013212607712676017663 xustar000000000000000030 mtime=1444910526.850383172 30 atime=1444910526.850383172 30 ctime=1444910526.850383172 unix/FreeBSD/pandora_agent.conf0000644000000000000000000001360612607712676016746 0ustar00rootroot00000000000000# Base config file for Pandora FMS agents # Version 6.0, FreeBSD Version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name adama # To define agent name by specific command, define 'agent_name_cmd'. # (In the following example, agent name is 'hostname_IP') #agent_name_cmd /bin/echo -n `hostname` ; /bin/echo -n "_" ; /bin/echo `/sbin/ifconfig bce0 | /usr/bin/grep 'inet' | /usr/bin/awk '{print $2;}' | cut -d: -f2` #Parent agent_name #parent_agent_name parent_name # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # timeout in seconds for file transfer programs execution (30 by default) #transfer_timeout 30 # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) #remote_config 1 # If set to 1 start Drone Agent's Proxy Mode #proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) #proxy_max_connection 10 # Proxy timeout (by default 1s) #proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user root #Secondary server configuration #============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_transfer_timeout 30 #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on system configuration, please check before use it module_begin module_name cpu_user module_type generic_data module_interval 1 module_exec vmstat -n0 1 2 | tail -1 | awk '{ print $15 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_end module_begin module_name cpu_system module_type generic_data module_interval 1 module_exec vmstat -n0 1 2 | tail -1 | awk '{ print $16 }' module_max 100 module_min 0 module_description System CPU Usage (%) module_end module_begin module_name cpu_idle module_type generic_data module_interval 1 module_exec vmstat -n0 1 2 | tail -1 | awk '{ print $17 }' module_max 100 module_min 0 module_description CPU Idle (%) module_end module_begin module_name Load Average module_type generic_data module_exec uptime | cut -d "," -f 4 | cut -d ":" -f 2 | sed "s/ //g" module_description Average process in CPU (Last minute) module_end module_begin module_name disk_root_free module_type generic_data module_exec df -kh / | tail -1 | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name memfree module_type generic_data module_exec vmstat -H 1 2 | tail -1 | awk '{print $5}' module_description Unused RAM memory module_end module_begin module_name proctotal module_type generic_data module_exec ps -A | wc -l | sed "s/ //g" module_end # Process information module_begin module_name sshDaemon module_type generic_proc module_exec ps -Af | grep sshd | grep -v "grep" | wc -l | sed "s/ //g" module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end # Plugin example # This parses /var/log/auth.log file, under the module name "syslog" # And search for "sshd" string into it, sending only that information. module_plugin grep_log /var/log/auth.log Syslog sshd # Plugin for inventory on the agent (Only Enterprise) # module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users route unix/FreeBSD/PaxHeaders.3873/pandora_agent0000644000000000000000000000013212573660551016733 xustar000000000000000030 mtime=1441751401.955005142 30 atime=1444862004.176359976 30 ctime=1441751401.955005142 unix/FreeBSD/pandora_agent0000755000000000000000000000201212573660551016006 0ustar00rootroot00000000000000#!/bin/sh # ********************************************************************** # Pandora FMS Agent Daemon launcher for FreeBSD # (c) 2010 Junichi Satoh # (c) 2014 Koichiro Kikuchi # # ********************************************************************** # PROVIDE: pandora_agent # REQUIRE: LOGIN # KEYWORD: shutdown # Add the following line to /etc/rc.conf to enable `pandora_agent': # # pandora_agent_enable="YES" # . "/etc/rc.subr" name="pandora_agent" rcvar=pandora_agent_enable # read configuration and set defaults pandora_agent_enable=${pandora_agent_enable:-"NO"} load_rc_config "$name" PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin pidfile=/var/run/$name.pid required_files="/usr/local/etc/pandora/pandora_agent.conf" stop_postcmd=stop_postcmd command=/usr/sbin/daemon command_interpreter=/usr/local/bin/perl procname=/usr/local/bin/pandora_agent command_args="-cfp $pidfile $procname /usr/local/etc/pandora" stop_postcmd() { rm -f $pidfile } run_rc_command "$1" unix/PaxHeaders.3873/pandora_agent0000644000000000000000000000013212607712676015525 xustar000000000000000030 mtime=1444910526.814381211 30 atime=1444910526.810380994 30 ctime=1444910526.814381211 unix/pandora_agent0000644000000000000000000022456112607712676014614 0ustar00rootroot00000000000000#!/usr/bin/perl # ********************************************************************** # Pandora FMS Generic Unix/Perl Agent # (c) 2009-2015 Artica Soluciones Tecnológicas # with the help of many people. Please see http://pandorafms.org # This code is licensed under GPL 2.0 license. # ********************************************************************** =head1 NAME pandora_agent - Pandora FMS Agent =head1 VERSION Version 6.0 =head1 USAGE << pandora_agent F >> =cut use strict; use warnings; use POSIX qw(strftime floor); use Sys::Hostname; use File::Basename; use File::Copy; use IO::Socket; use Sys::Syslog; # Agent XML data my $Xml; # Semaphore used to acces $Xml my $Sem = undef; # Semaphore used to control the number of threads my $ThreadSem = undef; use constant AGENT_VERSION => '6.0'; use constant AGENT_BUILD => '151015'; # Commands to retrieve total memory information in kB use constant TOTALMEMORY_CMDS => { linux => 'cat /proc/meminfo | grep MemTotal: | awk \'{ print $2 }\'', solaris => '/usr/sbin/prtconf | awk \'/Memory/ { print $3 * 1024 }\'', hpux => 'swapinfo -t | grep memory | awk \'{print $2}\'', freebsd => '/sbin/sysctl hw.physmem | awk \'{print $2 / 1024}\'', }; # Commands to retrieve free memory information in kB use constant FREEMEMORY_CMDS => { linux => 'cat /proc/meminfo | grep MemFree: | awk \'{ print $2 }\'', solaris => 'vmstat 1 2 | tail -1 | awk \'{ print $5 }\'', hpux => 'swapinfo -t | grep memory | awk \'{print $4}\'', freebsd => '/sbin/sysctl -n vm.stats.vm.v_page_size vm.stats.vm.v_free_count | tr "\n" " " | awk \'{ print $1 * $2 / 1024 }\'', }; # Commands to retrieve cpu information use constant CPUUSAGE_CMDS => { linux => 'vmstat 1 2 | tail -1 | awk \'{ print $13 }\'', solaris => 'vmstat 1 2 | tail -1 | awk \'{ print $21 }\'', hpux => 'vmstat 1 2 | tail -1 | awk \'{ print $16 }\'', freebsd => 'vmstat -n 0 1 2 | tail -1 | awk \'{ print $15 }\'' }; # Commands to retrieve process information use constant PROC_CMDS => { # cpu usage, memory usage, command name linux => 'ps aux | awk \'NR > 1 {ps = ""; for (i = 11; i <= NF; ++i) {ps = (ps " " $i) }; print $3, $6, ps}\'', solaris => 'prstat 1 1 | awk \'NR > 1 {split ($10, ps, "/"); cpu = substr ($9, 1, length ($9) - 1); mem = substr ($3, 1, length ($3) - 1); print cpu, mem, ps[1]}\'', hpux => 'ps -elf | awk \'NR > 1 {ps = ""; for (i = 15; i <= NF; ++i) {ps = (ps " " $i) }; print 0, $10, ps}\'', aix => 'ps aux | awk \'NR > 1 {print $3, $6, $11}\'', freebsd => 'ps axww -o %cpu= -o %mem= -o command= | sed -e "s/^ *//"', }; # Commands to retrieve partition information in kB use constant PART_CMDS => { # total, available, mount point linux => 'df -P | awk \'NR > 1 {print $2, $4, $6}\'', solaris => 'df -k | awk \'NR > 1 {print $2, $4, $6}\'', hpux => 'df -P | awk \'NR > 1 {print $2, $4, $6}\'', aix => 'df -kP | awk \'NR > 1 {print $2, $4, $6}\'', freebsd => 'df -k | awk \'NR > 1 {print $2, $4, $6}\'' }; # Commands to call df with POSIX output format use constant DF_CMDS => { # total, available, mount point linux => 'df -P', solaris => 'df -k', hpux => 'df -P', aix => 'df -kP', freebsd => 'df -k' }; # OS and OS version my $OS = $^O; my $OS_VERSION; # Used to calculate the MD5 checksum of a string use constant MOD232 => 2**32; # Directory where pandora_agent.conf is located my $ConfDir = ''; # Pandora FMS agent configuration file my $ConfFile = 'pandora_agent.conf'; # Set to 1 if broker agents are enabled. my $BrokerEnabled = 0; # Broker agent configuration files my @BrokerPid; # Configuration tokens my %DefaultConf = ( 'server_ip' => 'localhost', 'server_path' => '/var/spool/pandora/data_in', 'logfile' =>'/var/log/pandora/pandora_agent.log', 'temporal' => '/var/spool/pandora', 'interval' => 300, 'debug' => 0, 'agent_name' => hostname (), 'agent_name_cmd' => '', 'description' => '', 'group' => '', 'encoding' => 'UTF-8', 'server_port' => 41121, 'transfer_mode' => 'tentacle', 'transfer_timeout' => 30, 'server_user' => 'pandora', 'server_pwd' => '', 'server_ssl' => 'no', 'server_opts' => '', 'delayed_startup' => 0, 'pandora_nice' => 10, 'cron_mode' => 0, 'remote_config' => 0, 'secondary_mode' => 'never', 'secondary_server_ip' => 'localhost', 'secondary_server_path' => '/var/spool/pandora/data_in', 'secondary_server_port' => 41121, 'secondary_transfer_mode' => 'tentacle', 'secondary_transfer_timeout' => 30, 'secondary_server_user' => 'pandora', 'secondary_server_pwd' => '', 'secondary_server_ssl' => 'no', 'secondary_server_opts' => '', 'autotime' => 0, 'temporal_min_size' => 1, 'timezone_offset' => 0, 'pandora_exec' => 'pandora_agent_exec', 'agent_threads' => 1, 'udp_server_port' => 41122, 'udp_server_auth_address' => '0.0.0.0', 'udp_server' => 0, 'proxy_mode' => 0, 'proxy_max_connection' => 10, 'proxy_timeout' => 1, 'intensive_interval' => 0, 'timestamp' => 0, 'xml_buffer' => 0, 'custom_id' => '', 'url_address' => '', ); my %Conf = %DefaultConf; # Modules my @Modules; # Logfile file handle my $LogFileFH; # Agent name MD5; my $AgentMD5; # Remote configuration file name my $RemoteConfFile; # Remote md5 file name my $RemoteMD5File; # Process data my %Procs = ( '__utimestamp__' => 0 ); # Partition data my %Parts = ( '__utimestamp__' => 0 ); # Collections my %Collections; # Custom fields my %Customfields; # $DevNull my $DevNull = '/dev/null'; # Shell command separator my $CmdSep = ';'; # Global macros my %Macros; # PID of tentacle proxy, used in proxy mode my $tentacle_pid = undef; ################################################################################ # Print usage information and exit. ################################################################################ sub print_usage () { print "\nUsage: $0 \n\n"; print "\tPandora home is the directory where pandora_agent.conf is located,\n"; print "\tby default /etc/pandora.\n\n"; exit 1; } ################################################################################ # Print an error message and exit. ################################################################################ sub error ($) { my $msg = shift; print ("[ERROR] $msg\n\n"); `logger -i -t pandora_agent_daemon [ERROR] $msg 2>/dev/null`; exit 1; } ################################################################################ # Check a regular expression. Returns 1 if its valid, 0 otherwise. ################################################################################ sub valid_regexp ($) { my $regexp = shift; eval { '' =~ /$regexp/; }; # Something went wrong return 0 if ($@); return 1; } ################################################################################ # Recursively delete files and directories. ################################################################################ sub rmrf { my $path = shift; local *DIR; if (-d $path) { opendir (DIR, $path) || return; while (defined (my $file_name = readdir(DIR))) { next if ($file_name eq '.' || $file_name eq '..'); rmrf ("$path/$file_name"); } closedir (DIR); rmdir ($path); } else { unlink ($path); } } ################################################################################ # Recursively set file permissions. ################################################################################ sub chmodr { my ($perm, $path) = @_; local *DIR; if (-d $path) { opendir (DIR, $path) || return; while (defined (my $file_name = readdir(DIR))) { next if ($file_name eq '.' || $file_name eq '..'); chmodr ($perm, "$path/$file_name"); } closedir (DIR); } chmod ($perm, $path); } ################################################################################ # Open the agent logfile and start logging. ################################################################################ sub start_log (;$) { my $quiet = shift; # Get the logfile $Conf{'logfile'} = read_config ('logfile'); $Conf{'logfile'} = '/var/log/pandora/pandora_agent.log' unless defined ($Conf{'logfile'}); # Open it if ($Conf{'logfile'} eq 'syslog') { openlog('pandora_agent', 'nowait', 'daemon'); } else { open ($LogFileFH, "> $Conf{'logfile'}") or error ("Could not open log file $Conf{'logfile'} for writing: $!."); print "Logging to $Conf{'logfile'}\n" if (!defined ($quiet)); } } ################################################################################ # Close the agent logfile and stop logging. ################################################################################ sub stop_log () { if ($Conf{'logfile'} eq 'syslog') { closelog(); } else { close ($LogFileFH); } } ################################################################################ # Log a message to the agent logfile. ################################################################################ sub log_message ($$;$) { my ($source, $msg, $dest) = @_; if (defined ($dest)) { print $dest strftime ('%Y/%m/%d %H:%M:%S', localtime ()) . " - [$source] - $msg\n"; } elsif ($Conf{'logfile'} eq 'syslog') { syslog('info', $msg); } else { #Trying to write into log file to test its writable syswrite ($LogFileFH, ""); #If no error, the file is writable if (!$!) { print $LogFileFH strftime ('%Y/%m/%d %H:%M:%S', localtime ()) . " - [$source] - $msg\n"; } else { #If error then log into syslog! `logger -i -t pandora_agent_daemon [ERROR] $msg 2>/dev/null`; } } } ################################################################################ # Parse configuration file (modules, plugins and collections) ################################################################################ sub parse_conf_modules($) { my ($param) = @_; # Mark the start of a module definition my $module_begin = 0; # Skeleton for modules my $module = {}; foreach my $line (@{$param}) { next if ($line =~ m/^\s*#/) or ($line =~ m/^\s*$/); # Module definition if ($line =~ /^\s*module_begin\s*$/) { $module_begin = 1; init_module ($module); } elsif ($line =~ /^\s*module_name\s+(.+)$/) { $module->{'name'} = $1; $module->{'name'} =~ s/\s+$//g; $module->{'name'} =~ s/^\s+//g; } elsif ($line =~ /^\s*module_description\s+(.+)$/) { $module->{'description'} = $1; } elsif ($line =~ /^\s*module_type\s+(\S+)\s*$/) { $module->{'type'} = $1; }elsif ($line =~ /^\s*module_precondition\s+(.*)$/) { my $action = $1; # Numeric comparison if ($action =~ /^\s*([<>!=]+)\s+(\d+(?:\.\d*)?)\s+(.*)$/) { push (@{$module->{'precondition'}}, {'operator' => $1, 'value_1' => $2, 'command' => $3}); # Interval } elsif ($action =~ /^\s*[(]\s*(\d+(?:\.\d*)?)\s*,\s*(\d+(?:\.\d*)?)\s*[)]\s+(.*)$/) { push (@{$module->{'precondition'}}, {'operator' => '()', 'value_1' => $1, 'value_2' => $2, 'command' => $3}); # Regular expression } elsif ($action =~ /^\s*=~\s+(\S*)\s+(.*)$/) { if (valid_regexp ($1)) { push (@{$module->{'precondition'}}, {'operator' => '=~', 'value_1' => $1, 'command' => $2}); } else { log_message ('setup', "Invalid regular expression in module precondition: $line"); } } } elsif ($line =~ /^\s*module_exec\s+(.+)$/) { $module->{'func'} = \&module_exec; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_cpuusage\s+(.*)$/) { $module->{'func'} = \&module_cpuusage; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freememory\s+(.*)$/) { $module->{'func'} = \&module_freememory; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freepercentmemory\s+(.*)$/) { $module->{'func'} = \&module_freepercentmemory; $module->{'params'} = $1; } elsif ($line =~ /^\s*(module_proc|module_service)\s+(.+)$/) { $module->{'func'} = \&module_proc; $module->{'params'} = $2; } elsif ($line =~ /^\s*module_cpuproc\s+(.+)$/) { $module->{'func'} = \&module_cpuproc; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_memproc\s+(.+)$/) { $module->{'func'} = \&module_memproc; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freedisk\s+(.*)$/) { $module->{'func'} = \&module_freedisk; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freepercentdisk\s+(.*)$/) { $module->{'func'} = \&module_freepercentdisk; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_occupiedpercentdisk\s+(.*)$/) { $module->{'func'} = \&module_occupiedpercentdisk; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_max\s+(.*)\s*$/) { $module->{'max'} = $1; } elsif ($line =~ /^\s*module_min\s+(.*)\s*$/) { $module->{'min'} = $1; } elsif ($line =~ /^\s*module_postprocess\s+(.*)\s*$/) { $module->{'post_process'} = $1; } elsif ($line =~ /^\s*module_interval\s+(\d+)\s*$/) { $module->{'interval'} = $1; } elsif ($line =~ /^\s*module_timeout\s+(\d+)\s*$/) { $module->{'timeout'} = $1; } elsif ($line =~ /^\s*module_save\s+(\w+)$/) { $module->{'save'} = $1; } elsif ($line =~ /^\s*module_condition\s+(.*)$/) { my $action = $1; # Numeric comparison if ($action =~ /^\s*([<>!=]+)\s+(\d+(?:\.\d*)?)\s+(.*)$/) { push (@{$module->{'conditions'}}, {'operator' => $1, 'value_1' => $2, 'command' => $3}); # Interval } elsif ($action =~ /^\s*[(]\s*(\d+(?:\.\d*)?)\s*,\s*(\d+(?:\.\d*)?)\s*[)]\s+(.*)$/) { push (@{$module->{'conditions'}}, {'operator' => '()', 'value_1' => $1, 'value_2' => $2, 'command' => $3}); # Regular expression } elsif ($action =~ /^\s*=~\s+(\S*)\s+(.*)$/) { if (valid_regexp ($1)) { push (@{$module->{'conditions'}}, {'operator' => '=~', 'value_1' => $1, 'command' => $2}); } else { log_message ('setup', "Invalid regular expression in module condition: $line"); } } } elsif ($line =~ /^\s*module_intensive_condition\s+(.*)$/) { my $action = $1; $module->{'is_intensive'} = 1; # Numeric comparison if ($action =~ /^\s*([<>!=]+)\s+(\d+(?:\.\d*)?)\s*$/) { push (@{$module->{'intensive_conditions'}}, {'operator' => $1, 'value_1' => $2}); # Interval } elsif ($action =~ /^\s*[(]\s*(\d+(?:\.\d*)?)\s*,\s*(\d+(?:\.\d*)?)\s*[)]\s*$/) { push (@{$module->{'intensive_conditions'}}, {'operator' => '()', 'value_1' => $1, 'value_2' => $2}); # Regular expression } elsif ($action =~ /^\s*=~\s+(\S*)\s*$/) { if (valid_regexp ($1)) { push (@{$module->{'intensive_conditions'}}, {'operator' => '=~', 'value_1' => $1}); } else { log_message ('setup', "Invalid regular expression in intensive condition: $line"); } } } elsif ($line =~ /^\s*module_crontab\s+(((\*|(\d+(-\d+){0,1}))\s*){5}).*$/) { $module->{'cron'} = $1; } elsif ($line =~ /^\s*module_cron_interval\s+(\d+).*$/) { $module->{'cron_interval'} = $1; } elsif ($line =~ /^\s*module_end\s*$/) { $module_begin = 0; # Check for invalid modules next unless (($module->{'name'} ne '' && $module->{'func'} != 0) || $module->{'func'} == \&module_plugin); # Set the intensive interval if ($module->{'is_intensive'} == 1) { $module->{'intensive_interval'} = $module->{'interval'}; } else { $module->{'intensive_interval'} = $module->{'interval'} * ($Conf{'interval'} / $Conf{'intensive_interval'}); } # Make the module run the first time $module->{'counter'} = $module->{'intensive_interval'}; # Replace macros replace_macros ($module); push (@Modules, {%{$module}}); # Plugin } elsif ($line =~ /^\s*module_plugin\s+(.+)$/) { # Single line plugin definition if ($module_begin == 0) { # Set default values for the module configuration init_module ($module); # Configure the plugin $module->{'func'} = \&module_plugin; $module->{'params'} = $1; # Set the intensive interval if ($module->{'is_intensive'} == 1) { $module->{'intensive_interval'} = $module->{'interval'}; } else { $module->{'intensive_interval'} = $module->{'interval'} * ($Conf{'interval'} / $Conf{'intensive_interval'}); } # Make the module run the first time $module->{'counter'} = $module->{'intensive_interval'}; # Replace macros replace_macros ($module); push (@Modules, {%{$module}}); } else { $module->{'func'} = \&module_plugin; $module->{'params'} = $1; } # Module proc command redefinition } elsif ($line =~ /^\s*module_proc_cmd\s+(.+)$/) { PROC_CMDS->{$OS} = $1; # Module freedisk command redefinition } elsif ($line =~ /^\s*module_freedisk_cmd\s+(.+)$/) { PART_CMDS->{$OS} = $1; # Collection } elsif ($line =~ /^\s*file_collection\s+(.+)$/) { my $collection = $1; # Prevent path traversal attacks if ($collection !~ m/(\.\.)|\//) { $Collections{$collection} = 0; } # Min critical } elsif ($line =~ /^\s*module_min_critical\s+(.*)\s*$/) { $module->{'min_critical'} = $1; # Max critical } elsif ($line =~ /^\s*module_max_critical\s+(.*)\s*$/) { $module->{'max_critical'} = $1; # Min warning } elsif ($line =~ /^\s*module_min_warning\s+(.*)\s*$/) { $module->{'min_warning'} = $1; # Max warning } elsif ($line =~ /^\s*module_max_warning\s+(.*)\s*$/) { $module->{'max_warning'} = $1; # Disabled } elsif ($line =~ /^\s*module_disabled\s+(.*)\s*$/) { $module->{'disabled'} = $1; # Min ff event } elsif ($line =~ /^\s*module_min_ff_event\s+(.*)\s*$/) { $module->{'min_ff_event'} = $1; # Unit } elsif ($line =~ /^\s*module_unit\s+(.*)\s*$/) { $module->{'unit'} = $1; # Module_group } elsif ($line =~ /^\s*module_group\s+(.*?)\s*$/) { $module->{'module_group'} = $1; # Custom id } elsif ($line =~ /^\s*module_custom_id\s+(.*)\s*$/) { $module->{'custom_id'} = $1; # Str warning } elsif ($line =~ /^\s*module_str_warning\s+(.*)\s*$/) { $module->{'str_warning'} = $1; # Str critical } elsif ($line =~ /^\s*module_str_critical\s+(.*)\s*$/) { $module->{'str_critical'} = $1; # Critical instructions } elsif ($line =~ /^\s*module_critical_instructions\s+(.*)\s*$/) { $module->{'critical_instructions'} = $1; # Warning instructions } elsif ($line =~ /^\s*module_warning_instructions\s+(.*)\s*$/) { $module->{'warning_instructions'} = $1; # Unknown instructions } elsif ($line =~ /^\s*module_unknown_instructions\s+(.*)\s*$/) { $module->{'unknown_instructions'} = $1; # Tags } elsif ($line =~ /^\s*module_tags\s+(.*)\s*$/) { $module->{'tags'} = $1; # Critical inverse } elsif ($line =~ /^\s*module_critical_inverse\s+(\S+)\s*$/) { $module->{'critical_inverse'} = $1; # Warning inverse } elsif ($line =~ /^\s*module_warning_inverse\s+(\S+)\s*$/) { $module->{'warning_inverse'} = $1; # Quiet } elsif ($line =~ /^\s*module_quiet\s+(\S+)\s*$/) { $module->{'quiet'} = $1; # FF interval } elsif ($line =~ /^\s*module_ff_interval\s+(\S+)\s*$/) { $module->{'module_ff_interval'} = $1; # Macros } elsif ($line =~ /^\s*module_macro(\S+)\s+(.*)\s*$/) { $module->{'macros'}{$1} = $2; } } return; } ################################################################################ # Create configuration file for broker agents. ################################################################################ sub write_broker_conf($){ my ($broker_agent) = @_; my $content = ''; # I don't think the following should be copied either: proxy_* my %ignored_tokens = ( 'broker_agent' => 1, 'agent_name_cmd' => 1, 'udp_server' => 1, 'cron_mode' => 1 ); open (CONF_FILE, "$ConfDir/$ConfFile") or error ("Could not open file '$ConfDir/$ConfFile': $!."); open (BROKER_FILE, ">$ConfDir/${broker_agent}.conf") or error ("Could not write configuration file: $!"); while (my $line = ) { my ( $token ) = $line =~ m/^\s*(\S+)(\s.*)?$/; # Skip tokens which should not be copied to broker configuration next if defined $ignored_tokens{$token}; # Change the agent name if ($line =~ m/^\s*#*\s*agent_name\s+/) { $line = "agent_name $broker_agent\n"; } # Change the logfile elsif ($line =~ m/^\s*logfile\s+(.*)/) { $line = 'logfile ' . dirname ($1) . "/$broker_agent.log\n"; } print BROKER_FILE $line; } close (BROKER_FILE); close (CONF_FILE); } ################################################################################ # Read configuration file. Exit on error. ################################################################################ sub read_config (;$) { my $token = shift; my @found_tokens; my $module; error ("File '$ConfDir/$ConfFile' not found.") unless (-e "$ConfDir/$ConfFile"); open (CONF_FILE, "$ConfDir/$ConfFile") or error ("Could not open file '$ConfDir/$ConfFile': $!."); my @file = ; close(CONF_FILE); foreach my $line (@file){ # Skip comments and empty lines next if ($line =~ m/^\s*#/) or ($line =~ m/^\s*$/); # Replace CRLF with LF $line =~ s/\r\n/\n/g; # Token search if (defined ($token)) { if ($line =~ /^\s*(\S+)\s+(.*)$/ && $1 eq $token) { # Multiple value token if (wantarray ()) { push (@found_tokens, $2); } # Single value token else { return $2; } } next; } # Store the custom fields if (($line =~ m/^(custom_field\d+_name)\s+(.*)/) or ($line =~ m/^(custom_field\d+_value)\s+(.*)/)) { $Customfields{$1} = $2; next; } # Save global macros if ($line =~ m/^macro(\S+)\s+(.*)/) { $Macros{$1} = $2; next; } next if ($line =~ /^module\s*\w*/); #Configuration token if ($line =~ /^\s*(\S+)\s+(.*)$/) { log_message ('setup', "$1 is $2"); $Conf{$1} = $2; # Look for broker agents. if ($1 eq 'broker_agent') { $BrokerEnabled = 1; } # Remove trailing spaces $Conf{$1} =~ s/\s*$//; } } # Token search if (defined ($token)) { # Multiple value token if (wantarray ()) { return @found_tokens; } # Single value token not found. return undef; } # Set the intensive interval if ($Conf{'intensive_interval'} == 0) { $Conf{'intensive_interval'} = $Conf{'interval'}; } # Search for includes after all other variables have been set foreach my $line (@file) { # Skip comments and empty lines next if ($line =~ m/^\s*#/) or ($line =~ m/^\s*$/); # Replace CRLF with LF $line =~ s/\r\n/\n/g; # Additional configuration file if ($line =~ /^include\s+(.*)\s*/) { $Conf{'include'} = $Conf{'include'} ? "$Conf{'include'} $1" : $1; foreach my $file_name (glob("$1")) { open (FILE, "$file_name") or next; log_message ('setup', "reading $file_name"); my @file_conf = ; parse_conf_modules(\@file_conf); close (FILE); } next; } } # Module, plugin and collection definitions parse_conf_modules(\@file); # If agent_name_cmd is defined, agent_name is set by command result. if ($Conf{'agent_name_cmd'} ne '') { my $result = `$Conf{'agent_name_cmd'}`; # Use only the first line. my ($temp_agent_name, $remain) = split(/\n/, $result); chomp ($temp_agent_name); # Remove white spaces of the first and last. $temp_agent_name =~ s/^ *(.*?) *$/$1/; $Conf{'agent_name'} = $temp_agent_name if ($temp_agent_name ne ''); } # Update the agent MD5 since agent_name may have changed $AgentMD5 = md5 ($Conf{'agent_name'}); $RemoteConfFile = "$AgentMD5.conf"; $RemoteMD5File = "$AgentMD5.md5"; # Load thread support if agent_threads is greater than 1. if ($Conf{'agent_threads'} > 1) { eval { local $SIG{__DIE__}; require threads; require threads::shared; require Thread::Semaphore; }; if (!$@) { $Sem = Thread::Semaphore->new; $ThreadSem = Thread::Semaphore->new ($Conf{'agent_threads'}); threads::shared::share (\$Xml); threads::shared::share (\$Sem); log_message ('log', 'Using thread library.'); } else { log_message ('log', 'Thread library is not available. agent_threads is set to 1 (disabled).'); $Conf{'agent_threads'} = 1; $Sem = undef; $ThreadSem = undef; } } else { $Sem = undef; $ThreadSem = undef; log_message ('log', 'Thread is disabled.'); } # Set tentacle client options if ($Conf{'transfer_mode'} eq 'tentacle') { $Conf{'server_opts'} = '-x \'' . $Conf{'server_pwd'} . '\' ' . $Conf{'server_opts'} if ($Conf{'server_pwd'} ne ''); $Conf{'server_opts'} = '-c ' . $Conf{'server_opts'} if ($Conf{'server_ssl'} eq 'yes'); } # Set tentacle client options for secondary server if ($Conf{'secondary_transfer_mode'} eq 'tentacle') { $Conf{'secondary_server_opts'} = '-x \'' . $Conf{'secondary_server_pwd'} . '\' ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_pwd'} ne ''); $Conf{'secondary_server_opts'} = '-c ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_ssl'} eq 'yes'); } } ################################################################################# ## Remove any trailing / from directory names. ################################################################################# sub fix_directory ($) { my $dir = shift; my $char = chop ($dir); return $dir if ($char eq '/'); return $dir . $char; } ################################################################################ # Sends a file to the server. ################################################################################ #sub send_file ($;$) { sub send_file { my ($file, $secondary) = @_; my $output; eval { local $SIG{'ALRM'} = sub {die}; alarm ($Conf{'transfer_timeout'}); if ($Conf{'transfer_mode'} eq 'tentacle') { $output = `tentacle_client -v -a $Conf{'server_ip'} -p $Conf{'server_port'} $Conf{'server_opts'} "$file" 2>&1 >$DevNull`; } elsif ($Conf{'transfer_mode'} eq 'ssh') { $output = `scp -P $Conf{'server_port'} "$file" pandora@"$Conf{'server_ip'}:$Conf{'server_path'}" 2>&1 >$DevNull`; } elsif ($Conf{'transfer_mode'} eq 'ftp') { my $base = basename ($file); my $dir = dirname ($file); $output = `ftp -n $Conf{'server_opts'} $Conf{'server_ip'} $Conf{'server_port'} 2>&1 >$DevNull <&1 >$DevNull`; } alarm (0); }; if ($@) { $output = "File transfer command is not responding."; } # Get the errorlevel my $rc = $? >> 8; if ($rc != 0 || $@) { log_message ('error', "Error sending file '$file': $output"); } return $rc unless (defined ($secondary)); # Send the file to the secondary server return $rc unless ($Conf{'secondary_mode'} eq 'always' || ($Conf{'secondary_mode'} eq 'on_error' && $rc != 0)); swap_servers (); $rc = send_file ($file); swap_servers (); return $rc; } ################################################################################ # Send buffered XML files. ################################################################################ sub send_buffered_xml_files () { # Read XML files from the temporal directory opendir(TEMPORAL, $Conf{'temporal'}) or return; while (my $xml_file = readdir(TEMPORAL)) { # Skip non data files and symlinks next if ($xml_file !~ m/^$Conf{'agent_name'}\.[0-9]+\.data$/ || -l "$Conf{'temporal'}/$xml_file"); my $rc = send_file ("$Conf{'temporal'}/$xml_file", 1); if ($rc == 0) { if ($Conf{'debug'} eq '1') { rename "$Conf{'temporal'}/$xml_file", "$Conf{'temporal'}/$xml_file". "sent"; } else { unlink ("$Conf{'temporal'}/$xml_file"); } } } } ################################################################################ # Swap primary and secondary servers. ################################################################################ sub swap_servers () { ($Conf{'server_ip'}, $Conf{'secondary_server_ip'}) = ($Conf{'secondary_server_ip'}, $Conf{'server_ip'}); ($Conf{'server_path'}, $Conf{'secondary_server_path'}) = ($Conf{'secondary_server_path'}, $Conf{'server_path'}); ($Conf{'server_port'}, $Conf{'secondary_server_port'}) = ($Conf{'secondary_server_port'}, $Conf{'server_port'}); ($Conf{'transfer_mode'}, $Conf{'secondary_transfer_mode'}) = ($Conf{'secondary_transfer_mode'}, $Conf{'transfer_mode'}); ($Conf{'transfer_timeout'}, $Conf{'secondary_transfer_timeout'}) = ($Conf{'secondary_transfer_timeout'}, $Conf{'transfer_timeout'}); ($Conf{'server_user'}, $Conf{'secondary_server_user'}) = ($Conf{'secondary_server_user'}, $Conf{'server_user'}); ($Conf{'server_pwd'}, $Conf{'secondary_server_pwd'}) = ($Conf{'secondary_server_pwd'}, $Conf{'server_pwd'}); ($Conf{'server_ssl'}, $Conf{'secondary_server_ssl'}) = ($Conf{'secondary_server_ssl'}, $Conf{'server_ssl'}); ($Conf{'server_opts'}, $Conf{'secondary_server_opts'}) = ($Conf{'secondary_server_opts'}, $Conf{'server_opts'}); } ################################################################################ # Receive a file from the server. ################################################################################ sub recv_file ($) { my $file = shift; my $output; eval { local $SIG{'ALRM'} = sub {die}; alarm ($Conf{'transfer_timeout'}); if ($Conf{'transfer_mode'} eq 'tentacle') { $output = `cd "$Conf{'temporal'}"$CmdSep tentacle_client -v -g -a $Conf{'server_ip'} -p $Conf{'server_port'} $Conf{'server_opts'} $file 2>&1 >$DevNull` } elsif ($Conf{'transfer_mode'} eq 'ssh') { $output = `scp -P $Conf{'server_port'} pandora@"$Conf{'server_ip'}:$Conf{'server_path'}/$file" $Conf{'temporal'} 2>&1 >$DevNull`; } elsif ($Conf{'transfer_mode'} eq 'ftp') { my $base = basename ($file); my $dir = dirname ($file); $output = `ftp -n $Conf{'server_opts'} $Conf{'server_ip'} $Conf{'server_port'} 2>&1 >$DevNull <&1 >$DevNull`; } alarm (0); }; if ($@) { $output = "File transfer command is not responding."; } # Get the errorlevel my $rc = $? >> 8; if ($rc != 0 || $@) { log_message ('error', "Error retrieving file: $output"); } return $rc; } ################################################################################ # Check the server for a remote configuration. ################################################################################ sub check_remote_config () { return unless ($Conf{'remote_config'} eq '1'); # Calculate the configuration file MD5 digest open (CONF_FILE, "$ConfDir/$ConfFile") or error ("Could not open file '$ConfDir/$ConfFile': $!."); binmode(CONF_FILE); my $conf_md5 = md5 (join ('', )); close (CONF_FILE); # Remove temporary files if they exist as symlink to avoid symlink attack for my $file ("$Conf{'temporal'}/$RemoteMD5File", "$Conf{'temporal'}/$RemoteConfFile") { error ("File '$file' already exists as a symlink and could not be removed: $!") if (-l $file && ! unlink($file)); } # Get the remote MD5 file if (recv_file ($RemoteMD5File) != 0) { open (MD5_FILE, "> $Conf{'temporal'}/$RemoteMD5File") || error ("Could not open file '$ConfDir/$RemoteMD5File' for writing: $!."); print MD5_FILE $conf_md5; close (MD5_FILE); copy ("$ConfDir/$ConfFile", "$Conf{'temporal'}/$RemoteConfFile"); send_file ("$Conf{'temporal'}/$RemoteConfFile"); send_file ("$Conf{'temporal'}/$RemoteMD5File"); log_message ('remote config', 'Uploading configuration for the first time.'); unlink ("$Conf{'temporal'}/$RemoteConfFile"); unlink ("$Conf{'temporal'}/$RemoteMD5File"); return; } open (MD5_FILE, "< $Conf{'temporal'}/$RemoteMD5File") || error ("Could not open file '$ConfDir/$RemoteMD5File' for writing: $!."); my $remote_conf_md5 = ; close (MD5_FILE); # No changes return if ($remote_conf_md5 eq $conf_md5); # Get the new configuration file return if (recv_file ($RemoteConfFile) != 0); log_message ('remote config', 'Configuration has changed!'); # Save the new configuration move ("$Conf{'temporal'}/$RemoteConfFile", "$ConfDir/$ConfFile"); # Empty macros, modules, plugins and collections %Macros = (); @Modules = (); %Collections = (); %Conf = %DefaultConf; # Reload the new configuration read_config (); # Log file may have changed stop_log (); start_log ('quiet'); #Set nice of the pandora_agent my $PID = $$; `renice "$Conf{'pandora_nice'}" "$PID"`; } ################################################################################ # SUB launch_tentacle_proxy # Launchs tentacle server in proxy mode. ################################################################################ sub launch_tentacle_proxy () { # Check if proxy server ip is right. if ($Conf{'server_ip'} ne "localhost") { #Create a new process and launch tentacle. $tentacle_pid = fork(); if ($tentacle_pid == 0) { #Execute tentacle server as a daemon my $new_process = "tentacle_server -b ".$Conf{'server_ip'}." -g ".$Conf{'server_port'}." -c ".$Conf{'proxy_max_connection'}." -t ".$Conf{'proxy_timeout'}; $new_process .= ' -C' if ($Conf{'server_ssl'} eq 'yes'); log_message ('setup', 'Proxy mode enabled'); exec ($new_process); } } else { log_message ('error', 'You can not proxy to localhost'); exit 1; } } ################################################################################ # Delete old collections and download new collections. ################################################################################ sub check_collections () { # Delete old collections if there are no broker agents if ($BrokerEnabled == 0) { opendir (DIR, "$ConfDir/collections") || return; while (defined (my $file_name = readdir(DIR))) { next if ($file_name eq '.' || $file_name eq '..'); # Do not delete md5 files associated to a collection $file_name =~ s/\.md5$//; if (! defined ($Collections{$file_name})) { rmrf ("$ConfDir/collections/$file_name"); unlink ("$ConfDir/collections/$file_name.md5"); } } closedir (DIR); } # Download new collections while (my ($collection, $in_path) = each (%Collections)) { my $collection_file = $collection . ".zip"; my $collection_md5_file = $collection . ".md5"; # Add the collection directory to the PATH if ($in_path == 0) { $Collections{$collection} = 1; $ENV{'PATH'} .= ":$ConfDir/collections/$collection"; } # Get remote md5 error ("File '$Conf{'temporal'}/$collection_md5_file' already exists as a symlink and could not be removed: $!.") if (-l "$Conf{'temporal'}/$collection_md5_file" && !unlink("$Conf{'temporal'}/$collection_md5_file")); next unless (recv_file ($collection_md5_file) == 0); open (MD5_FILE, "< $Conf{'temporal'}/$collection_md5_file") || error ("Could not open file '$Conf{'temporal'}/$collection_md5_file' for reading: $!."); my $remote_collection_md5 = ; close (MD5_FILE); unlink ("$Conf{'temporal'}/$collection_md5_file"); # Read local md5 my $local_collection_md5 = ''; if (defined (open (MD5_FILE, "< $ConfDir/collections/$collection_md5_file"))) { $local_collection_md5 = ; close MD5_FILE; } # Check for changes $local_collection_md5 = $remote_collection_md5 unless defined ($local_collection_md5); next if ($local_collection_md5 eq $remote_collection_md5); # Download and unzip next unless (recv_file ($collection_file) == 0); rmrf ("$ConfDir/collections/$collection"); `unzip -d "$ConfDir/collections/$collection" "$Conf{'temporal'}/$collection_file" 2>$DevNull`; unlink ("$Conf{'temporal'}/$collection_file"); # Save the new md5 open (MD5_FILE, "> $ConfDir/collections/$collection_md5_file") || error ("Could not open file '$ConfDir/collections/$collection_md5_file' for writing: $!."); print MD5_FILE "$remote_collection_md5"; close (MD5_FILE); # Set proper file permissions chmodr (0750, "$ConfDir/collections/$collection"); } } ############################################################################### # MD5 leftrotate function. See http://en.wikipedia.org/wiki/MD5#Pseudocode. ############################################################################### sub leftrotate ($$) { my ($x, $c) = @_; return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c)); } ############################################################################### # Initialize some variables needed by the MD5 algorithm. # See http://en.wikipedia.org/wiki/MD5#Pseudocode. ############################################################################### my (@R, @K); sub md5_init () { # R specifies the per-round shift amounts @R = (7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21); # Use binary integer part of the sines of integers (radians) as constants for (my $i = 0; $i < 64; $i++) { $K[$i] = floor(abs(sin($i + 1)) * MOD232); } } ############################################################################### # Return the MD5 checksum of the given string. # Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode. ############################################################################### sub md5 ($) { my $str = shift; # Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating # Initialize variables my $h0 = 0x67452301; my $h1 = 0xEFCDAB89; my $h2 = 0x98BADCFE; my $h3 = 0x10325476; # Pre-processing my $msg = unpack ("B*", pack ("A*", $str)); my $bit_len = length ($msg); # Append "1" bit to message $msg .= '1'; # Append "0" bits until message length in bits ≡ 448 (mod 512) $msg .= '0' while ((length ($msg) % 512) != 448); # Append bit /* bit, not byte */ length of unpadded message as 64-bit little-endian integer to message $msg .= unpack ("B64", pack ("VV", $bit_len)); # Process the message in successive 512-bit chunks for (my $i = 0; $i < length ($msg); $i += 512) { my @w; my $chunk = substr ($msg, $i, 512); # Break chunk into sixteen 32-bit little-endian words w[i], 0 <= i <= 15 for (my $j = 0; $j < length ($chunk); $j += 32) { push (@w, unpack ("V", pack ("B32", substr ($chunk, $j, 32)))); } # Initialize hash value for this chunk my $a = $h0; my $b = $h1; my $c = $h2; my $d = $h3; my $f; my $g; # Main loop for (my $y = 0; $y < 64; $y++) { if ($y <= 15) { $f = $d ^ ($b & ($c ^ $d)); $g = $y; } elsif ($y <= 31) { $f = $c ^ ($d & ($b ^ $c)); $g = (5 * $y + 1) % 16; } elsif ($y <= 47) { $f = $b ^ $c ^ $d; $g = (3 * $y + 5) % 16; } else { $f = $c ^ ($b | (0xFFFFFFFF & (~ $d))); $g = (7 * $y) % 16; } my $temp = $d; $d = $c; $c = $b; $b = ($b + leftrotate (($a + $f + $K[$y] + $w[$g]) % MOD232, $R[$y])) % MOD232; $a = $temp; } # Add this chunk's hash to result so far $h0 = ($h0 + $a) % MOD232; $h1 = ($h1 + $b) % MOD232; $h2 = ($h2 + $c) % MOD232; $h3 = ($h3 + $d) % MOD232; } # Digest := h0 append h1 append h2 append h3 #(expressed as little-endian) return unpack ("H*", pack ("V", $h0)) . unpack ("H*", pack ("V", $h1)) . unpack ("H*", pack ("V", $h2)) . unpack ("H*", pack ("V", $h3)); } ################################################################################ # Try to guess the OS version. ################################################################################ sub guess_os_version ($) { my $os = shift; my $os_version; # Linux if ($os eq 'linux') { $os_version = `lsb_release -sd 2>$DevNull`; # AIX } elsif ($os eq 'aix') { $os_version = "$2.$1" if (`uname -rv` =~ /\s*(\d)\s+(\d)\s*/); # Windows } elsif ($os =~ /win/i) { $os_version = `ver`; $DevNull = '/Nul'; $CmdSep = '\&'; $OS = "windows"; # Solaris, HP-UX, BSD and others } else { $os_version = `uname -r`; } # Something went wrong return '' unless defined ($os_version); # Remove any trailing new lines chomp ($os_version); return $os_version; } ################################################################################ # Execute the given module. ################################################################################ sub exec_module ($) { my $module = shift; # Need something to execute if ($module->{'func'} == 0) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Check module interval if (++($module->{'counter'}) < $module->{'intensive_interval'}) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Check module cron if (check_module_cron ($module) != 1) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Check module preconditions if (evaluate_module_preconditions ($module) == 0) { return; } # Reset module counter $module->{'counter'} = 0; # Temporarily disable strict refs no strict 'refs'; # Run my @value = &{$module->{'func'}}($module); if (defined ($value[0])) { # Evaluate intensive conditions if ($module->{'is_intensive'} == 1) { my $intensive_match = evaluate_module_intensive_conditions ($module, $value[0]); if ($intensive_match == $module->{'intensive_match'} && $module->{'timestamp'} + $module->{'interval'} * $Conf{'interval'} > time ()) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Update the time reference $module->{'timestamp'} = time () if ($module->{'timestamp'} + $module->{'interval'} * $Conf{'interval'} <= time ()); # Update the intensive match status $module->{'intensive_match'} = $intensive_match; } # Evaluate module conditions evaluate_module_conditions ($module, $value[0]); # Write the module XML write_module_xml ($module, @value); } # Save the module value if needed (only works for the first returned value) if ($module->{'save'} ne '') { if (defined ($value[0])) { $ENV{$module->{'save'}} = $value[0] ; } else { $ENV{$module->{'save'}} = ''; } } $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); } ################################################################################ # Load process information. ################################################################################ sub load_procs () { my $utimestamp = time (); # Do we know hoy to get process information in this OS? return unless defined (PROC_CMDS->{$OS}); # Update at most once every interval return if ($Procs{'__utimestamp__'} > ($utimestamp - $Conf{'interval'})); # Get process information my $cmd = PROC_CMDS->{$OS}; my @procs = `$cmd`; return undef unless ($? eq 0); # Clear past process infomation %Procs = (); # Parse process information foreach my $proc (@procs) { chomp ($proc); my @proc_info = split (/\s+/, $proc); next unless ($#proc_info >= 2); # Process command my $proc_cmd = join (' ', @proc_info[2..$#proc_info]); # Process command $Procs{$proc_cmd} = (); # Process CPU usage $Procs{$proc_cmd}{'cpu'} = $proc_info[0]; # Process virtual size $Procs{$proc_cmd}{'size'} = $proc_info[1]; } $Procs{'__utimestamp__'} = $utimestamp; } ################################################################################ # Load partition information. ################################################################################ sub load_parts () { my $utimestamp = time (); # Do we know hoy to get partition information in this OS? return unless defined (PART_CMDS->{$OS}); # Update at most once every interval return if ($Parts{'__utimestamp__'} > ($utimestamp - $Conf{'interval'})); # Get partition information my $cmd = PART_CMDS->{$OS}; my @parts = `$cmd`; return undef unless ($? eq 0); # Parse partition information foreach my $part (@parts) { chomp ($part); my @part_info = split (/\s+/, $part); next unless ($#part_info >= 2); my $part = join (' ', @part_info[2..$#part_info]); # Mount point $Parts{$part} = (); # Total space in kB $Parts{$part}{'total'} = $part_info[0]; # Available space in kB $Parts{$part}{'avail'} = $part_info[1]; } $Parts{'__utimestamp__'} = $utimestamp; } ################################################################################ # Execute the given command. ################################################################################ sub module_exec ($) { my $module = shift; my @data; my $exe; # Check module parameters return () unless ($module->{'params'} ne ''); my $params = $module->{'params'}; # Execute the command if ($module->{'timeout'} == 0) { @data = `$params 2> $DevNull`; log_message ('debug', "Executing module " . $module->{'name'} . " ($params 2> $DevNull)") if ($Conf{'debug'} eq '1'); } else { my $cmd = quotemeta ($params); @data = `$Conf{'pandora_exec'} $module->{'timeout'} $cmd 2> $DevNull`; log_message ('debug', "Executing module " . $module->{'name'} . ' (' . $Conf{'pandora_exec'} . ' ' . $module->{'timeout'} . " $cmd 2> $DevNull)") if ($Conf{'debug'} eq '1'); } # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); return @data; } ################################################################################ # Get the status of a process. 1 running, 0 not running. ################################################################################ sub module_proc ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_procs (); return (1) if defined ($Procs{$module->{'params'}}); return (0); } ################################################################################ # Get the CPU usage of a process. ################################################################################ sub module_cpuproc ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_procs (); return () unless defined ($Procs{$module->{'params'}}) and defined ($Procs{$module->{'params'}}{'cpu'}); return ($Procs{$module->{'params'}}{'cpu'}); } ################################################################################ # Get the memory usage of a process in Mbytes. ################################################################################ sub module_memproc ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_procs (); return () unless defined ($Procs{$module->{'params'}}) and defined ($Procs{$module->{'params'}}{'size'}); return (sprintf ("%d", $Procs{$module->{'params'}}{'size'} / 1024)); } ################################################################################ # Get the free space in a partition in Mbytes. ################################################################################ sub module_freedisk ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_parts (); return () unless defined ($Parts{$module->{'params'}}) and defined ($Parts{$module->{'params'}}{'avail'}); my $avail = sprintf("%d", $Parts{$module->{'params'}}{'avail'} / 1024); return ($avail); } ################################################################################ # Get the free space in a partition in %. ################################################################################ sub module_freepercentdisk ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_parts (); return () unless defined ($Parts{$module->{'params'}}) and defined ($Parts{$module->{'params'}}{'avail'}); my $availp = sprintf("%d", $Parts{$module->{'params'}}{'avail'} * 100 / $Parts{$module->{'params'}}{'total'}); return ($availp); } ################################################################################ # Get the occupied space in a partition in %. ################################################################################ sub module_occupiedpercentdisk ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_parts (); return () unless defined ($Parts{$module->{'params'}}) and defined ($Parts{$module->{'params'}}{'avail'}); my $occupiedp = sprintf("%d", ($Parts{$module->{'params'}}{'total'} - $Parts{$module->{'params'}}{'avail'}) * 100 / $Parts{$module->{'params'}}{'total'}); return ($occupiedp); } ################################################################################ # Get the CPU usage %. ################################################################################ sub module_cpuusage ($) { my $module = shift; # Do we know hoy to get CPU usage in this OS? return unless defined (CPUUSAGE_CMDS->{$OS}); # Get CPU usage my $cmd = CPUUSAGE_CMDS->{$OS}; my @data = `$cmd 2> $DevNull`; # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); return ($data[0]); } ################################################################################ # Get the free space in a partition in Mbytes. ################################################################################ sub module_freememory ($) { my $module = shift; # Do we know hoy to get memory information in this OS? return () unless defined (FREEMEMORY_CMDS->{$OS}); # Get available memory my $cmd = FREEMEMORY_CMDS->{$OS}; my @data = `$cmd 2> $DevNull`; # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); return (sprintf ("%d", $data[0] / 1024)); } ################################################################################ # Get the free space in a partition in %. ################################################################################ sub module_freepercentmemory ($) { my $module = shift; # Do we know hoy to get memory information in this OS? return unless defined (TOTALMEMORY_CMDS->{$OS}); # Get CPU usage my $cmd = TOTALMEMORY_CMDS->{$OS}; my @data = `$cmd 2> $DevNull`; # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); # Get total memory in MB my $total = sprintf ("%d", $data[0] / 1024); # Get available memory in MB my ($avail) = module_freememory ($module); return () unless defined ($avail); return sprintf (("%d", $avail * 100 / $total)); } ################################################################################ # Evaluate and execute module preconditions. ################################################################################ sub evaluate_module_preconditions ($) { my ($module) = @_; # Evaluate preconditions foreach my $precondition (@{$module->{'precondition'}}) { my $data = `$precondition->{'command'} 2> $DevNull`; return 0 if (evaluate_condition ($precondition, $data) == 0); } return 1; } ################################################################################ # Evaluate a module condition. Returns 1 if the condition matches, 0 otherwise. ################################################################################ sub evaluate_condition ($$) { my ($condition, $data) = @_; { no warnings; if (($condition->{'operator'} eq '>' && $data > $condition->{'value_1'}) || ($condition->{'operator'} eq '<' && $data < $condition->{'value_1'}) || ($condition->{'operator'} eq '=' && $data == $condition->{'value_1'}) || ($condition->{'operator'} eq '!=' && $data != $condition->{'value_1'}) || ($condition->{'operator'} eq '=~' && $data =~ /$condition->{'value_1'}/) || ($condition->{'operator'} eq '()' && $data > $condition->{'value_1'} && $data < $condition->{'value_2'})) { return 1; } } return 0; } ################################################################################ # Evaluate and execute module conditions. ################################################################################ sub evaluate_module_conditions ($$) { my ($module, $data) = @_; # Evaluate conditions foreach my $condition (@{$module->{'conditions'}}) { if (evaluate_condition ($condition, $data) == 1) { `$condition->{'command'} 2> $DevNull`; } } } ################################################################################ # Evaluate intensive conditions. ################################################################################ sub evaluate_module_intensive_conditions ($$) { my ($module, $data) = @_; # Evaluate conditions foreach my $condition (@{$module->{'intensive_conditions'}}) { return 0 if (evaluate_condition ($condition, $data) == 0); } return 1; } ################################################################################ # Checks the module's cron string. Returns 1 if the module should be run, 0 if # not. ################################################################################ sub check_module_cron ($) { my $module = shift; # No cron string defined return 1 unless ($module->{'cron'} ne ''); # Check if the module was already executed return 0 unless (time() >= $module->{'cron_utimestamp'}); # Get cron configuration my @cron_params = split (/\s/, $module->{'cron'}); # Get current time my $current_time = time(); my @time = localtime($current_time); # Minutes, hours, day of the month, month and day of the week my @time_params = @time[1, 2, 3, 4, 6]; # Fix month (localtime retuns 0..11 and we need 1..12) $time_params[3] += 1; # Check cron parameters for (my $i = 0; $i < 5; $i++) { # Wildcard next if ($cron_params[$i] eq '*'); # Get interval my ($bottom, $top) = split (/-/, $cron_params[$i]); $top = $bottom unless defined ($top); # Check interval if ($bottom <= $top) { return 0 if ($time_params[$i] < $bottom || $time_params[$i] > $top); } else { return 0 if ($time_params[$i] < $bottom && $time_params[$i] > $top); } } # Do not check in the next minute, hour, day or month. my $offset = 0; if ($module->{'cron_interval'} >= 0) { $offset = $module->{'cron_interval'}; } elsif($cron_params[0] ne '*') { # 1 minute $offset = 60; } elsif($cron_params[1] ne '*') { # 1 hour $offset = 3600; } elsif($cron_params[2] ne '*' || $cron_params[4] ne '*') { # 1 day $offset = 86400; } elsif($cron_params[3] ne '*') { # 31 days $offset = 2678400; } $module->{'cron_utimestamp'} = $current_time + $offset; return 1; } ################################################################################ # Write module data in XML format. ################################################################################ sub write_module_xml ($@) { my ($module, @data) = @_; # No data return unless (defined $data[0]); # Is it a plugin? if ($module->{'func'} == \&module_plugin) { $Sem->down () if (defined ($Sem)); $Xml .= $data[0]; $Sem->up () if (defined ($Sem)); return; } # Critical section $Sem->down () if (defined ($Sem)); $Xml .= "\n" . " {'name'} . "]]>\n" . " {'description'} . "]]>\n" . " " . $module->{'type'} . "\n"; # Interval $Xml .= " " . $module->{'interval'} . "\n"; # Min $Xml .= " " . $module->{'min'} . "\n" if (defined ($module->{'min'})); # Max $Xml .= " " . $module->{'max'} . "\n" if (defined ($module->{'max'})); # Post process $Xml .= " " . $module->{'post_process'} . "\n" if (defined ($module->{'post_process'})); # Min critical $Xml .= " " . $module->{'min_critical'} . "\n" if (defined ($module->{'min_critical'})); # Max critical $Xml .= " " . $module->{'max_critical'} . "\n" if (defined ($module->{'max_critical'})); # Min warning $Xml .= " " . $module->{'min_warning'} . "\n" if (defined ($module->{'min_warning'})); # Max warning $Xml .= " " . $module->{'max_warning'} . "\n" if (defined ($module->{'max_warning'})); # Disabled $Xml .= " " . $module->{'disabled'} . "\n" if (defined ($module->{'disabled'})); # Min ff event $Xml .= " " . $module->{'min_ff_event'} . "\n" if (defined ($module->{'min_ff_event'})); # Unit $Xml .= " {'unit'} . "]]>\n" if (defined ($module->{'unit'})); # Module group $Xml .= " " . $module->{'module_group'} . "\n" if (defined ($module->{'module_group'})); # Custom ID $Xml .= " {'custom_id'} . "]]>\n" if (defined ($module->{'custom_id'})); # Str warning $Xml .= " {'str_warning'} . "]]>\n" if (defined ($module->{'str_warning'})); # Str critical $Xml .= " {'str_critical'} . "]]>\n" if (defined ($module->{'str_critical'})); # Critical instructions $Xml .= " {'critical_instructions'} . "]]>\n" if (defined ($module->{'critical_instructions'})); # Warning instructions $Xml .= " {'warning_instructions'} . "]]>\n" if (defined ($module->{'warning_instructions'})); # Unknown instructions $Xml .= " {'unknown_instructions'} . "]]>\n" if (defined ($module->{'unknown_instructions'})); # Tags $Xml .= " {'tags'} . "]]>\n" if (defined ($module->{'tags'})); # Critical inverse $Xml .= " " . $module->{'critical_inverse'} . "\n" if (defined ($module->{'critical_inverse'})); # Warning inverse $Xml .= " " . $module->{'warning_inverse'} . "\n" if (defined ($module->{'warning_inverse'})); # Quiet $Xml .= " " . $module->{'quiet'} . "\n" if (defined ($module->{'quiet'})); # Module FF interval $Xml .= " " . $module->{'module_ff_interval'} . "\n" if (defined ($module->{'module_ff_interval'})); # Data list if ($#data > 0) { $Xml .= " \n"; # Single data } else { chomp ($data[0]); $Xml .= " \n"; } $Xml .= "\n"; $Sem->up () if (defined ($Sem)); } ################################################################################ # Receive a UDP server signal to restart agent ################################################################################ sub udp_server_signal () { log_message ('udp server', 'Received signal to restart the agent.'); } ################################################################################ # Basic UDP server to restart agent on UDP signal received ################################################################################ sub udp_server ($$) { my $udp_port = shift; my $udp_auth_address = shift; my $parent_pid = getppid(); my @udp_auth_list = split(',', $udp_auth_address); my($sock, $oldmsg, $newmsg, $hisaddr, $hishost, $MAXLEN); $MAXLEN = 1024; log_message ('udp server', 'Starting UDP server listening on '.$udp_auth_address.":".$udp_port); $sock = IO::Socket::INET->new(LocalPort => $udp_port, Proto => 'udp') or die "socket: $@"; while ($sock->recv($newmsg, $MAXLEN)) { my $hishost = $sock->peerhost(); my $address_found = 0; foreach my $single_address (@udp_auth_list) { $address_found = $address_found || ($hishost eq $single_address); } if (($udp_auth_address eq "0.0.0.0") || $address_found){ if ($newmsg =~ /REFRESH AGENT/){ # Send signal to restart agent log_message ('udp server', 'Received signal from '.$hishost); kill 'SIGINT' , $parent_pid; } elsif ($newmsg =~ /START PROCESS (.*)/){ my $process_name = $1; $process_name =~ s/^\s*//g; $process_name =~ s/\s*$//g; if (defined($Conf{"process_${process_name}_start"})) { log_message ('udp server', "Process $process_name started from $hishost"); if (fork() == 0) { `$Conf{"process_${process_name}_start"} 2>$DevNull`; exit 0; } } else { log_message ('udp server', "Attempt to start unknown process $process_name from $hishost"); } } elsif ($newmsg =~ /STOP PROCESS (.*)/){ my $process_name = $1; $process_name =~ s/^\s*//g; $process_name =~ s/\s*$//g; if (defined($Conf{"process_${process_name}_stop"})) { log_message ('udp server', "Process $process_name stopped from $hishost"); if (fork() == 0) { `$Conf{"process_${process_name}_stop"} 2>$DevNull`; exit 0; } } else { log_message ('udp server', "Attempt to stop unknown process $process_name from $hishost"); } } } } } ################################################################################ # Execute the given plugin. ################################################################################ sub module_plugin ($) { my $plugin = shift; my $command = $plugin->{'params'}; # Empty plugin return () if ($command eq ''); # Execute the plugin my $output = ""; if ($plugin->{'timeout'} == 0) { $output = `$command 2>$DevNull`; log_message ('debug', "Executing plugin: " . $command) if ($Conf{'debug'} eq '1'); } else { $output = `$Conf{'pandora_exec'} $plugin->{'timeout'} $command 2> $DevNull`; log_message ('debug', "Executing plugin: (" . $command . ") with timeout: " . $plugin->{'timeout'} . "s") if ($Conf{'debug'} eq '1'); } # Do not save the output if there was an error if ($? != 0) { return (); } return ($output); } ################################################################################ # TERM Handler ################################################################################ sub kill_signal_handler (){ # Kill tentacle server if it was launched if (defined ($tentacle_pid)) { print "kill -9 $tentacle_pid\n"; `kill -9 $tentacle_pid`; } exit (0); } ################################################################################ # Get the free disk space in the temporal directory (in bytes). ################################################################################ sub temporal_freedisk () { # Call df return 0 unless defined (DF_CMDS->{$OS}); my $cmd = DF_CMDS->{$OS} . ' ' . $Conf{'temporal'} . ' | awk \'NR > 1 {print $4}\''; my $temporal_freedisk = `$cmd`; # Check for errors return 0 unless ($? eq 0); # Convert to bytes return 1024 * int ($temporal_freedisk); } ################################################################################ # Replace module macros. ################################################################################ sub replace_macros ($) { my $module = shift; # Replace macros foreach my $token (keys (%{$module})) { # No need to skip macros for now, since it's a hash ref and only array refs # are searched for macros. #if ($token eq 'macros') { # next; #} # No defined value for conf token if (! defined ($module->{$token})) { next; } # Simple configuration token if(ref($module->{$token}) eq ''){ # Module macros while (my ($macro, $subst) = each (%{$module->{'macros'}})) { eval { $module->{$token} =~ s/$macro/$subst/g; }; } # Global macros while (my ($macro, $subst) = each (%Macros)) { eval { $module->{$token} =~ s/$macro/$subst/g; }; } } # Hash array elsif (ref($module->{$token}) eq 'ARRAY'){ for (my $i = 0; $i <= $#{$module->{$token}}; $i++) { # Array of configuration tokens foreach my $key (keys (%{$module->{$token}->[$i]})) { # Module macros (each configuration token is a hash) while (my ($macro, $subst) = each (%{$module->{'macros'}})) { eval { $module->{$token}->[$i]->{$key} =~ s/$macro/$subst/g; } } # Global macros (each configuration token is a hash) while (my ($macro, $subst) = each (%Macros)) { eval { $module->{$token}->[$i]->{$key} =~ s/$macro/$subst/g; } } } } } } } ################################################################################ # Initialize a module with default values. ################################################################################ sub init_module ($) { my $module = shift; $module->{'name'} = ''; $module->{'type'} = 'generic_data'; $module->{'description'} = ''; $module->{'func'} = 0; $module->{'params'} = ''; $module->{'interval'} = 1; $module->{'timeout'} = 0; $module->{'counter'} = 0; $module->{'max'} = undef; $module->{'min'} = undef; $module->{'post_process'} = undef; $module->{'min_critical'} = undef; $module->{'max_critical'} = undef; $module->{'min_warning'} = undef; $module->{'max_warning'} = undef; $module->{'disabled'} = undef; $module->{'min_ff_event'} = undef; $module->{'save'} = ''; $module->{'conditions'} = []; $module->{'cron'} = ''; $module->{'cron_utimestamp'} = 0; $module->{'cron_interval'} = -1; $module->{'precondition'} = []; $module->{'is_intensive'} = 0; $module->{'intensive_conditions'} = []; $module->{'intensive_match'} = 0; $module->{'timestamp'} = 0; $module->{'unit'} = undef; $module->{'module_group'} = undef; $module->{'custom_id'} = undef; $module->{'str_warning'} = undef; $module->{'str_critical'} = undef; $module->{'critical_instructions'} = undef; $module->{'warning_instructions'} = undef; $module->{'unknown_instructions'} = undef; $module->{'tags'} = undef; $module->{'critical_inverse'} = undef; $module->{'warning_inverse'} = undef; $module->{'quiet'} = undef; $module->{'module_ff_interval'} = undef; $module->{'macros'} = {}; } ################################################################################ # Main. ################################################################################ #Handler TERM signal. $SIG{'TERM'} = \&kill_signal_handler; # Check command line arguments print_usage unless ($#ARGV == 0); $ConfDir = fix_directory ($ARGV[0]); error ("Directory '$ConfDir' does not exist.") unless (-d "$ConfDir"); #Pandora home path $ENV{'PANDORA_HOME'}=$ConfDir; # Get user to run as my $pandora_user = read_config ('pandora_user'); if (defined ($pandora_user)) { # Change the EUID my $pandora_user_uid = getpwnam ($pandora_user); if (!defined ($pandora_user_uid)) { error ("Cannot get uid for user $pandora_user. Does the user exist and can we read /etc/passwd?"); } $> = $pandora_user_uid; if ($> != $pandora_user_uid) { error ("Cannot run as $pandora_user: Insufficient permissions."); } } # Guess the OS version $OS_VERSION = guess_os_version ($OS); # Initialize MD5 variables md5_init (); # Start logging start_log (); log_message ('log', 'Running as user ' . getpwuid ($>)); # Read configuration file read_config (); $ENV{'PANDORA_AGENT'}=$Conf{'agent_name'}; # Fix directory names $Conf{'temporal'} = fix_directory ($Conf{'temporal'}); error ("Temporal directory '" . $Conf{'temporal'} . "' does not exist.") unless (-d "$Conf{'temporal'}"); $Conf{'server_path'} = fix_directory ($Conf{'server_path'}); $Conf{'secondary_server_path'} = fix_directory ($Conf{'secondary_server_path'}); # Startup delay log_message ('log', 'Sleeping for ' . $Conf{'delayed_startup'} . ' seconds.') if ($Conf{'delayed_startup'} > 0); sleep ($Conf{'delayed_startup'}); #Set nice of the pandora_agent my $PID = $$; `renice "$Conf{'pandora_nice'}" "$PID"`; #Launch tentacle server in proxy mode if configured if ($Conf{'proxy_mode'}) { #Check if user is root if ($> != 0) { launch_tentacle_proxy(); } else { log_message ('error', 'Proxy mode can not be launched as root'); exit 1; } } # Add the plugins directory to the PATH $ENV{'PATH'} .= ":$ConfDir/plugins"; # Start UDP server if configured if ($Conf{'udp_server'} == 1){ my $pid = fork(); if ($pid == 0){ udp_server ($Conf{'udp_server_port'}, $Conf{'udp_server_auth_address'}); exit; } } # Must be set to 0 if the agent is a broker agent my $main_agent = -1; # base time to start eatch iteration with the same interval. my $iter_base_time = time(); # Loop while (1) { # Ignore signals from UDP and Tentacle server while processing execution if ($Conf{'udp_server'} == 1 || $Conf{'proxy_mode'}){ $SIG{'INT'} = 'DEFAULT'; } # Check for a new configuration check_remote_config () unless ($Conf{'debug'} eq '1'); # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); # Launch broker agents @BrokerPid = (); my @broker_agents = read_config ('broker_agent'); foreach my $broker_agent (@broker_agents) { # Create broker conf file if it does not exist if (! -e "$ConfDir/${broker_agent}.conf") { write_broker_conf($broker_agent); } $main_agent = fork (); # Broker agent if ($main_agent == 0) { # Set the configuration file $ConfFile = "${broker_agent}.conf"; # Log to a new file stop_log (); start_log ('quiet'); # Read configuration file %Macros = (); @Modules = (); %Collections = (); %Conf = %DefaultConf; read_config (); # Check for a new configuration check_remote_config () unless ($Conf{'debug'} eq '1'); # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); # Execute last; } else { push (@BrokerPid, $main_agent); } } my $address; if(defined($Conf{'address'})) { # Check if address is auto to get the local ip if ($Conf{'address'} eq 'auto') { # Tested on Ubuntu, debian, Suse, Solaris 10 and AIX 5.1 my @address_list = `ifconfig -a 2>$DevNull | grep -v '127.0.0' | grep '[0-9]*\\.[0-9]*\\.[0-9]*' | awk '{ print \$2 }' | awk -F':' '{ print \$2 }'`; if ($#address_list < 0) { # Tested on Red Hat 7 @address_list = `ip addr show 2>$DevNull | grep -v '127.0.0' | grep '[0-9]*\\.[0-9]*\\.[0-9]*' | awk '{print \$2}' | cut -d/ -f1`; } for (my $i = 0; $i <= $#address_list; $i++) { chomp($address_list[$i]); if ($i > 0) { $address .= ','; } $address .= $address_list[$i]; } } else { $address = $Conf{'address'}; } } # Clear the XML $Xml = ""; # Custom fields my @customfieldskeys = keys(%Customfields); if ($#customfieldskeys > -1) { $Xml .= "\n"; foreach my $customfieldkey (@customfieldskeys) { if($customfieldkey =~ m/^(custom_field\d+_)name/) { if(defined($Customfields{$1."value"})) { $Xml .= " \n"; $Xml .= " \n"; $Xml .= " \n"; $Xml .= " \n"; } } } $Xml .= "\n"; } # Execute modules foreach my $module (@Modules) { # Execute the module in a separate thread if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1) { $ThreadSem->down (); my $thr = threads->create (\&exec_module, $module); if (! defined ($thr)) { $ThreadSem->up (); } else { $thr->detach(); } # Execute the module } else { exec_module($module); } } # Wait for all the threads $ThreadSem->down ($Conf{'agent_threads'}) if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); $ThreadSem->up ($Conf{'agent_threads'}) if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); if ($Xml ne "" || $Conf{'timestamp'} + $Conf{'interval'} <= time ()) { # Update the time reference $Conf{'timestamp'} = time () if ($Conf{'timestamp'} + $Conf{'interval'} <= time ()); # Compose the XML my $xml_header = "\n" . ""; # Save XML data file my $temp_file = $Conf{'temporal'} . '/' . $Conf{'agent_name'} . '.' . time () . '.data'; error ("File '$temp_file' already exists as a symlink and could not be removed: $!") if (-l $temp_file && !unlink($temp_file)); open (TEMP_FILE, "> $temp_file") || error ("Could not write XML data file: $!"); print TEMP_FILE $Xml; close (TEMP_FILE); # Debug mode if ($Conf{'debug'} eq '1') { log_message ('debug', "Wrote XML data file '$temp_file'"); log_message ('debug', "Wrote XML data file '$temp_file'", *STDOUT); } # Send the XML data file my $rc = send_file ($temp_file, 1); if ($rc == 0 || $Conf{'xml_buffer'} == 0 || temporal_freedisk () < $Conf{'temporal_min_size'}) { if ($Conf{'debug'} eq '1') { rename $temp_file, $temp_file . "sent"; } else { unlink ($temp_file); } } # Send buffered XML data files if ($Conf{'xml_buffer'} == 1) { send_buffered_xml_files (); } } # Enable signal capture to break the Sleep interval on UDP signal if ($Conf{'udp_server'} == 1) { $SIG{'INT'} = \&udp_server_signal; } # Sleep if main agent if ($main_agent != 0) { foreach my $broker_pid (@BrokerPid) { waitpid ($broker_pid, 0); } # Cron mode last if ($Conf{'cron_mode'} == 1); $iter_base_time += $Conf{'intensive_interval'}; my $now = time(); my $interval_remain = $iter_base_time - $now; if ($interval_remain >= 0) { sleep ($interval_remain); } else { # don't sleep if iteraion took more than "intensive_interval" seconds $iter_base_time = $now; # use current time as base time } } # Finish if broker agent else { exit (0); } } __END__ =head1 EXIT STATUS =over =item 0 on Success =item 1 on Error =back =head1 CONFIGURATION By default pandora_agent uses F as B. There is the F file with all the configuration of the agent. =head1 DEPENDENCIES =head1 LICENSE This is released under the GNU Lesser General Public License. =head1 SEE ALSO =head1 COPYRIGHT Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut unix/PaxHeaders.3873/tentacle_server0000644000000000000000000000013212607655076016110 xustar000000000000000030 mtime=1444895294.619817018 30 atime=1444895304.228334433 30 ctime=1444895294.619817018 unix/tentacle_server0000755000000000000000000010717312607655076015201 0ustar00rootroot00000000000000#!/usr/bin/perl ########################################################################## # Tentacle Server # See http://www.openideas.info/wiki for protocol description. # Tentacle have IANA assigned port tpc/41121 as official port. ########################################################################## # Copyright (c) 2007-2008 Ramon Novoa # Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L # # tentacle_server.pl Tentacle Server. See http://www.openideas.info/wiki for # protocol description. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## package tentacle::server; =head1 NAME tentacle_server - Tentacle Server =head1 VERSION Version 0.5.0 =head1 USAGE tentacle_server B<< -s F >> [I] =head1 DESCRIPTION B is a server for B, a B file transfer protocol that aims to be: =over =item * Secure by design. =item * Easy to use. =item * Versatile and cross-platform. =back Tentacle was created to replace more complex tools like SCP and FTP for simple file transfer/retrieval, and switch from authentication mechanisms like .netrc, interactive logins and SSH keys to X.509 certificates. Simple password authentication over a SSL secured connection is supported too. The client and server (B) are designed to be run from the command line or called from a shell script, and B. =cut use strict; use warnings; use Getopt::Std; use IO::Select; use threads; use Thread::Semaphore; use POSIX ":sys_wait_h"; use Time::HiRes qw(usleep); # Constants for Win32 services. use constant WIN32_SERVICE_STOPPED => 0x01; use constant WIN32_SERVICE_RUNNING => 0x04; my $t_libwrap_installed = eval { require Authen::Libwrap } ? 1 : 0; if ($t_libwrap_installed) { Authen::Libwrap->import( qw( hosts_ctl STRING_UNKNOWN ) ); } # Log messages, 1 enabled, 0 disabled my $t_log = 0; my $SOCKET_MODULE = eval { require IO::Socket::INET6 } ? 'IO::Socket::INET6' : eval { require IO::Socket::INET } ? 'IO::Socket::INET' : die $@; # Service name for Win32. my $SERVICE_NAME="Tentacle Server"; # Service parameters. my $SERVICE_PARAMS=join(' ', @ARGV); # Program version our $VERSION = '0.5.0'; # IPv4 address to listen on my @t_addresses = ('0', '0.0.0.0'); # Block size for socket read/write operations in bytes my $t_block_size = 1024; # Client socket my $t_client_socket; # Run as daemon, 1 true, 0 false my $t_daemon = 0; # Storage directory my $t_directory = ''; # Filters my @t_filters; # String containing quoted invalid file name characters my $t_invalid_chars = '\?\[\]\/\\\=\+\<\>\:\;\'\,\*\~'; # Maximum number of simultaneous connections my $t_max_conn = 10; # Maximum file size allowed by the server in bytes my $t_max_size = 2000000; # File overwrite, 1 enabled, 0 disabled my $t_overwrite = 0; # Port to listen on my $t_port = 41121; # Server password my $t_pwd = ''; # Do not output error messages, 1 enabled, 0 disabled my $t_quiet = 0; # Number of retries for socket read/write operations my $t_retries = 3; # Select handler my $t_select; # Semaphore my $t_sem :shared; # Server socket my @t_server_sockets; # Server select handler my $t_server_select; # Use SSL, 1 true, 0 false my $t_ssl = 0; # SSL ca certificate file my $t_ssl_ca = ''; # SSL certificate file my $t_ssl_cert = ''; # SSL private key file my $t_ssl_key = ''; # SSL private key password my $t_ssl_pwd = ''; # Timeout for socket read/write operations in seconds my $t_timeout = 1; # Address to proxy client requests to my $t_proxy_ip = undef; # Port to proxy client requests to my $t_proxy_port = 41121; # Proxy socket my $t_proxy_socket; # Proxy selected handler my $t_proxy_select; # Use libwrap, 1 true, 0 false my $t_use_libwrap = 0; # Program name for libwrap my $t_program_name = $0; $t_program_name =~ s/.*\///g; ################################################################################ ## SUB print_help ## Print help screen. ################################################################################ sub print_help { $" = ','; print ("Usage: $0 -s [options]\n\n"); print ("Tentacle server v$VERSION. See http://www.openideas.info/wiki for protocol description.\n\n"); print ("Options:\n"); print ("\t-a ip_addresses\tIP addresses to listen on (default @t_addresses).\n"); print ("\t \t(Multiple addresses separated by comma can be defined.)\n"); print ("\t-c number\tMaximum number of simultaneous connections (default $t_max_conn).\n"); print ("\t-d\t\tRun as daemon.\n"); print ("\t-e cert\t\tOpenSSL certificate file. Enables SSL.\n"); print ("\t-f ca_cert\tVerify that the peer certificate is signed by a ca.\n"); print ("\t-h\t\tShow help.\n"); print ("\t-i\t\tFilters.\n"); print ("\t-k key\t\tOpenSSL private key file.\n"); print ("\t-m size\t\tMaximum file size in bytes (default ${t_max_size}b).\n"); print ("\t-o\t\tEnable file overwrite.\n"); print ("\t-p port\t\tPort to listen on (default $t_port).\n"); print ("\t-q\t\tQuiet. Do now print error messages.\n"); print ("\t-r number\tNumber of retries for network opertions (default $t_retries).\n"); print ("\t-S (install|uninstall|run) Manage the win32 service.\n"); print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n"); print ("\t-v\t\tBe verbose.\n"); print ("\t-w\t\tPrompt for OpenSSL private key password.\n"); print ("\t-x pwd\t\tServer password.\n"); print ("\t-b ip_address\tProxy requests to the given address.\n"); print ("\t-g port\t\tProxy requests to the given port.\n"); print ("\t-T\t\tEnable tcpwrappers support.\n"); print ("\t \t\t(To use this option, 'Authen::Libwrap' should be installed.)\n\n"); } ################################################################################ ## SUB daemonize ## Turn the current process into a daemon. ################################################################################ sub daemonize { my $pid; require POSIX; chdir ('/') || error ("Cannot chdir to /: $!."); umask 0; open (STDIN, '/dev/null') || error ("Cannot read /dev/null: $!."); # Do not be verbose when running as a daemon open (STDOUT, '>/dev/null') || error ("Cannot write to /dev/null: $!."); open (STDERR, '>/dev/null') || error ("Cannot write to /dev/null: $!."); # Fork $pid = fork (); if (! defined ($pid)) { error ("Cannot fork: $!."); } # Parent if ($pid != 0) { exit; } # Child POSIX::setsid () || error ("Cannot start a new session: $!."); } ################################################################################ ## SUB parse_options ## Parse command line options and initialize global variables. ################################################################################ sub parse_options { my %opts; my $tmp; my @t_addresses_tmp; # Get options if (getopts ('a:b:c:de:f:g:hi:k:m:op:qr:s:S:t:Tvwx:', \%opts) == 0 || defined ($opts{'h'})) { print_help (); exit 1; } # The Win32 service must be installed/uninstalled without checking other parameters. if (defined ($opts{'S'})) { my $service_action = $opts{'S'}; if ($^O ne 'MSWin32') { error ("Windows services are only available on Win32."); } else { eval "use Win32::Daemon"; die($@) if ($@); if ($service_action eq 'install') { install_service(); } elsif ($service_action eq 'uninstall') { uninstall_service(); } } } # Address if (defined ($opts{'a'})) { @t_addresses = (); @t_addresses_tmp = split(/,/, $opts{'a'}); foreach my $t_address (@t_addresses_tmp) { $t_address =~ s/^ *(.*?) *$/$1/; if (($t_address ne '0') && ($t_address !~ /^[a-zA-Z\.]+$/ && ($t_address !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) && ($t_address !~ /^[0-9a-f:]+$/o)) { error ("Address $t_address is not valid."); } push @t_addresses, $t_address; } } # Maximum simultaneous connections if (defined ($opts{'c'})) { $t_max_conn = $opts{'c'}; if ($t_max_conn !~ /^\d+$/ || $t_max_conn < 1) { error ("Invalid number of maximum simultaneous connections."); } } # Run as daemon if (defined ($opts{'d'})) { if ($^ eq 'MSWin32') { error ("-d flag not available for this OS."); } $t_daemon = 1; } # Enable SSL if (defined ($opts{'e'})) { require IO::Socket::SSL; $t_ssl_cert = $opts{'e'}; if (! -f $t_ssl_cert) { error ("File $t_ssl_cert does not exist."); } $t_ssl = 1; } # Verify peer certificate if (defined ($opts{'f'})) { $t_ssl_ca = $opts{'f'}; if (! -f $t_ssl_ca) { error ("File $t_ssl_ca does not exist."); } } # Filters (regexp:dir;regexp:dir...) if (defined ($opts{'i'})) { my @filters = split (';', $opts{'i'}); foreach my $filter (@filters) { my ($regexp, $dir) = split (':', $filter); next unless defined ($regexp) && defined ($dir); # Remove any trailing / my $char = chop ($dir); $dir .= $char if ($char) ne '/'; push(@t_filters, [$regexp, $dir]); } } # SSL private key file if (defined ($opts{'k'})) { $t_ssl_key = $opts{'k'}; if (! -f $t_ssl_key) { error ("File $t_ssl_key does not exist."); } } # Maximum file size if (defined ($opts{'m'})) { $t_max_size = $opts{'m'}; if ($t_max_size !~ /^\d+$/ || $t_max_size < 1) { error ("Invalid maximum file size."); } } # File overwrite if (defined ($opts{'o'})) { $t_overwrite = 1; } # Port if (defined ($opts{'p'})) { $t_port = $opts{'p'}; if ($t_port !~ /^\d+$/ || $t_port < 1 || $t_port > 65535) { error ("Port $t_port is not valid."); } } # Quiet mode if (defined ($opts{'q'})) { $t_quiet = 1; } # Retries if (defined ($opts{'r'})) { $t_retries = $opts{'r'}; if ($t_retries !~ /^\d+$/ || $t_retries < 1) { error ("Invalid number of retries for network operations."); } } # Storage directory if (defined ($opts{'s'})) { $t_directory = $opts{'s'}; # Check that directory exists if (! -d $t_directory) { error ("Directory $t_directory does not exist."); } # Check directory permissions if (! -w $t_directory) { error ("Cannot write to directory $t_directory."); } # Remove the trailing / if present $tmp = chop ($t_directory); if ($tmp ne '/') { $t_directory .= $tmp; } } else { if (! defined($opts{'b'})) { print_help (); exit 1; } } # Timeout if (defined ($opts{'t'})) { $t_timeout = $opts{'t'}; if ($t_timeout !~ /^\d+$/ || $t_timeout < 1) { error ("Invalid timeout for network operations."); } } # Be verbose if (defined ($opts{'v'})) { $t_log = 1; } # SSL private key password if (defined ($opts{'w'})) { $t_ssl_pwd = ask_passwd ("Enter private key file password: ", "Enter private key file password again for confirmation: "); } # Server password if (defined ($opts{'x'})) { $t_pwd = $opts{'x'}; } #Proxy IP address if (defined ($opts{'b'})) { $t_proxy_ip = $opts{'b'}; if ($t_proxy_ip !~ /^[a-zA-Z\.]+$/ && ($t_proxy_ip !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255) && $t_proxy_ip !~ /^[0-9a-f:]+$/o) { error ("Proxy address $t_proxy_ip is not valid."); } } # Proxy Port if (defined ($opts{'g'})) { $t_proxy_port = $opts{'g'}; if ($t_proxy_port !~ /^\d+$/ || $t_proxy_port < 1 || $t_proxy_port > 65535) { error ("Proxy port $t_port is not valid."); } } # TCP wrappers support if (defined ($opts{'T'})) { if ($t_libwrap_installed) { $t_use_libwrap = 1; } else { error ("Authen::Libwrap is not installed."); } } # Win32 service management if (defined ($opts{'S'})) { my $service_action = $opts{'S'}; if ($^O ne 'MSWin32') { error ("Windows services are only available on Win32."); } else { eval "use Win32::Daemon"; die($@) if ($@); if ($service_action eq 'run') { Win32::Daemon::RegisterCallbacks({ start => \&callback_start, running => \&callback_running, stop => \&callback_stop, }); Win32::Daemon::StartService(); exit 0; } else { error("Unknown action: $service_action"); } } } } ################################################################################ ## SUB start_proxy ## Open the proxy server socket. ################################################################################ sub start_proxy { # Connect to server $t_proxy_socket = $SOCKET_MODULE->new ( PeerAddr => $t_proxy_ip, PeerPort => $t_proxy_port, ); if (! defined ($t_proxy_socket)) { error ("Cannot connect to $t_proxy_ip on port $t_proxy_port: $!."); } # Create proxy selector $t_proxy_select = IO::Select->new (); $t_proxy_select->add ($t_proxy_socket); } ################################################################################ ## SUB start_server ## Open the server socket. ################################################################################ sub start_server { my $t_server_socket; foreach my $t_address (@t_addresses) { $t_server_socket = $SOCKET_MODULE->new ( Listen => $t_max_conn, LocalAddr => $t_address, LocalPort => $t_port, Proto => 'tcp', ReuseAddr => 1, ); if (! defined ($t_server_socket)) { print_log ("Cannot open socket for address $t_address on port $t_port: $!."); next; } print_log ("Server listening on $t_address port $t_port (press to stop)"); # Say message if tentacle proxy is enable if (defined ($t_proxy_ip)) { print_log ("Proxy Mode enable, data will be sent to $t_proxy_ip port $t_proxy_port"); } push @t_server_sockets, $t_server_socket; } if (!@t_server_sockets) { error ("Cannot open socket for all addresses on port $t_port: $!."); } $t_server_select = IO::Select->new(); foreach my $t_server_socket (@t_server_sockets){ $t_server_select->add($t_server_socket); } } ################################################################################ ## SUB send_data_proxy ## Send data to proxy socket. ################################################################################ sub send_data_proxy { my $data = $_[0]; my $retries = 0; my $size; my $total = 0; my $written; $size = length ($data); while (1) { # Try to write data to the socket if ($t_proxy_select->can_write ($t_timeout)) { $written = syswrite ($t_proxy_socket, $data, $size - $total, $total); # Write error if (! defined ($written)) { error ("Connection error from " . $t_proxy_socket->sockhost () . ": $!."); } # EOF if ($written == 0) { error ("Connection from " . $t_proxy_socket->sockhost () . " unexpectedly closed."); } } $total += $written; # Check if all data was written if ($total == $size) { return; } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_proxy_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB close_proxy ## Close the proxy socket. ################################################################################ sub close_proxy { $t_proxy_socket->shutdown (2); $t_proxy_socket->close (); } ################################################################################ ## SUB stop_server ## Close the server socket. ################################################################################ sub stop_server { foreach my $t_server_socket (@t_server_sockets) { $t_server_socket->shutdown (2); $t_server_socket->close (); } print_log ("Server going down"); exit 0; } ################################################################################ ## SUB start_ssl ## Convert the client socket to an IO::Socket::SSL socket. ################################################################################ sub start_ssl { my $err; if ($t_ssl_ca eq '') { IO::Socket::SSL->start_SSL ( $t_client_socket, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_server => 1, # Verify peer SSL_verify_mode => 0x01, ); } else { IO::Socket::SSL->start_SSL ( $t_client_socket, SSL_ca_file => $t_ssl_ca, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_server => 1, # Fail verification if no peer certificate exists SSL_verify_mode => 0x03, ); } $err = IO::Socket::SSL::errstr (); if ($err ne '') { error ($err); } print_log ("SSL started for " . $t_client_socket->sockhost ()); } ################################################################################ ## SUB accept_connections ## Manage incoming connections. ################################################################################ sub accept_connections { my $pid; my $t_server_socket; # Ignore SIGPIPE errors (happens on FreeBSD when SSL is enabled ¿?) $SIG{PIPE} = 'IGNORE'; # Start server start_server (); # Initialize semaphore $t_sem = Thread::Semaphore->new ($t_max_conn); while (1) { my @ready = $t_server_select->can_read; foreach $t_server_socket (@ready) { # Accept connection $t_client_socket = $t_server_socket->accept (); if (! defined ($t_client_socket)) { next if ($! ne ''); # EINTR error ("accept: $!."); } print_log ("Client connected from " . $t_client_socket->peerhost ()); if ($t_use_libwrap && (! hosts_ctl($t_program_name, $t_client_socket))) { print_log ("Connection from " . $t_client_socket->peerhost() . " is closed by tcpwrappers."); $t_client_socket->shutdown (2); $t_client_socket->close(); } else { # Create a new thread and serve the client $t_sem->down(); my $thr = threads->create(\&serve_client); if (! defined ($thr)) { error ("Error creating thread: $!."); } $thr->detach(); $t_client_socket->close (); } } usleep (1000); } } ################################################################################ ## SUB serve_client ## Serve a connected client. ################################################################################ sub serve_client() { eval { # Add client socket to select queue $t_select = IO::Select->new (); $t_select->add ($t_client_socket); # Start SSL if ($t_ssl == 1) { start_ssl (); } # Authenticate client if ($t_pwd ne '') { auth_pwd (); } # Check if proxy mode is enable if (defined ($t_proxy_ip)) { serve_proxy_connection (); } else { serve_connection (); } }; $t_client_socket->shutdown (2); $t_client_socket->close (); $t_sem->up(); } ################################################################################ ## SUB serve_proxy_connection ## Actuate as a proxy between its client and other tentacle server. ################################################################################ sub serve_proxy_connection { # We are a proxy! Start a connection to the Tentacle Server. start_proxy(); # Forward data between the client and the server. eval { while (1) { if ($t_select->can_read(0)) { my ($read, $data) = recv_data($t_block_size); send_data_proxy($data); } if ($t_proxy_select->can_read(0)) { my ($read, $data) = recv_data_proxy($t_block_size); send_data($data); } } }; # Close the connection to the Tentacle Server. close_proxy(); } ################################################################################ ## SUB serve_connection ## Read and process commands from the client. ################################################################################ sub serve_connection { my $command; # Read commands while ($command = recv_command ($t_block_size)) { # Client wants to send a file if ($command =~ /^SEND <(.*)> SIZE (\d+)$/) { print_log ("Request to send file '$1' size ${2}b from " . $t_client_socket->sockhost ()); recv_file ($1, $2); } # Client wants to receive a file elsif ($command =~ /^RECV <(.*)>$/) { print_log ("Request to receive file '$1' from " . $t_client_socket->sockhost ()); send_file ($1); } # Quit elsif ($command =~ /^QUIT$/) { print_log ("Connection closed from " . $t_client_socket->sockhost ()); last; } # Unknown command else { print_log ("Unknown command '$command' from " . $t_client_socket->sockhost ()); last; } } } ################################################################################ ## SUB auth_pwd ## Authenticate client with server password. ################################################################################ sub auth_pwd { my $client_digest; my $command; my $pwd_digest; require Digest::MD5; # Wait for password $command = recv_command ($t_block_size); if ($command !~ /^PASS (.*)$/) { error ("Client " . $t_client_socket->sockhost () . " did not authenticate."); } $client_digest = $1; $pwd_digest = Digest::MD5::md5 ($t_pwd); $pwd_digest = Digest::MD5::md5_hex ($pwd_digest); if ($client_digest ne $pwd_digest) { error ("Invalid password from " . $t_client_socket->sockhost () . "."); } print_log ("Client " . $t_client_socket->sockhost () . " authenticated"); send_data ("PASS OK\n"); } ################################################################################ ## SUB recv_file ## Receive a file of size $_[1] and save it in $t_directory as $_[0]. ################################################################################ sub recv_file { my $base_name = $_[0]; my $data = ''; my $file; my $size = $_[1]; # Check file name if ($base_name =~ /[$t_invalid_chars]/) { print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " has an invalid file name"); send_data ("SEND ERR\n"); return; } # Check file size, empty files are not allowed if ($size < 1 || $size > $t_max_size) { print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " is too big"); send_data ("SEND ERR\n"); return; } # Apply filters $file = "$t_directory/" . apply_filters ($base_name) . $base_name; # Check if file exists if (-f $file && $t_overwrite == 0) { print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " already exists"); send_data ("SEND ERR\n"); return; } send_data ("SEND OK\n"); # Receive file $data = recv_data_block ($size); # Write it to disk open (FILE, "> $file") || error ("Cannot open file '$file' for writing."); binmode (FILE); print (FILE $data); close (FILE); send_data ("SEND OK\n"); print_log ("Received file '$base_name' size ${size}b from " . $t_client_socket->sockhost ()); } ################################################################################ ## SUB send_file ## Send a file to the client ################################################################################ sub send_file { my $base_name = $_[0]; my $data = ''; my $file; my $response; my $size; # Check file name if ($base_name =~ /[$t_invalid_chars]/) { print_log ("Requested file '$base_name' from " . $t_client_socket->sockhost () . " has an invalid file name"); send_data ("RECV ERR\n"); return; } # Apply filters $file = "$t_directory/" . apply_filters ($base_name) . $base_name; # Check if file exists if (! -f $file) { print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " does not exist"); send_data ("RECV ERR\n"); return; } $size = -s $file; send_data ("RECV SIZE $size\n"); # Wait for client response $response = recv_command ($t_block_size); if ($response ne "RECV OK") { print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " not sent"); return; } # Send the file open (FILE, $file) || error ("Cannot open file '$file' for reading."); binmode (FILE); while ($data = ) { send_data ($data); } close (FILE); print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " sent"); } ################################################################################ # Common functions ################################################################################ ################################################################################ ## SUB print_log ## Print log messages. ################################################################################ sub print_log { if ($t_log == 1) { print (STDOUT "[log] $_[0]\n"); } } ################################################################################ ## SUB error ## Print an error and exit the program. ################################################################################ sub error { if ($t_quiet == 0) { die("[err] $_[0]\n\n"); } } ################################################################################ ## SUB recv_data_proxy ## Recv data from proxy socket. ################################################################################ sub recv_data_proxy { my $data; my $read; my $retries = 0; my $size = $_[0]; while (1) { # Try to read data from the socket if ($t_proxy_select->can_read ($t_timeout)) { # Read at most $size bytes $read = sysread ($t_proxy_socket, $data, $size); # Read error if (! defined ($read)) { error ("Read error from " . $t_proxy_socket->sockhost () . ": $!."); } # EOF if ($read == 0) { error ("Connection from " . $t_proxy_socket->sockhost () . " unexpectedly closed."); } return ($read, $data); } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_proxy_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB recv_data ## Read data from the client socket. Returns the number of bytes read and the ## string of bytes as a two element array. ################################################################################ sub recv_data { my $data; my $read; my $retries = 0; my $size = $_[0]; while (1) { # Try to read data from the socket if ($t_select->can_read ($t_timeout)) { # Read at most $size bytes $read = sysread ($t_client_socket, $data, $size); # Read error if (! defined ($read)) { error ("Read error from " . $t_client_socket->sockhost () . ": $!."); } # EOF if ($read == 0) { error ("Connection from " . $t_client_socket->sockhost () . " unexpectedly closed."); } return ($read, $data); } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_client_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB send_data ## Write data to the client socket. ################################################################################ sub send_data { my $data = $_[0]; my $retries = 0; my $size; my $total = 0; my $written; $size = length ($data); while (1) { # Try to write data to the socket if ($t_select->can_write ($t_timeout)) { $written = syswrite ($t_client_socket, $data, $size - $total, $total); # Write error if (! defined ($written)) { error ("Connection error from " . $t_client_socket->sockhost () . ": $!."); } # EOF if ($written == 0) { error ("Connection from " . $t_client_socket->sockhost () . " unexpectedly closed."); } } $total += $written; # Check if all data was written if ($total == $size) { return; } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_client_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB recv_command ## Read a command from the client, ended by a new line character. ################################################################################ sub recv_command { my $buffer; my $char; my $command = ''; my $read; my $total = 0; while (1) { ($read, $buffer) = recv_data ($t_block_size); $command .= $buffer; $total += $read; # Check if the command is complete $char = chop ($command); if ($char eq "\n") { return $command; } $command .= $char; # Avoid overflow if ($total > $t_block_size) { error ("Received too much data from " . $t_client_socket->sockhost () . "."); } } } ################################################################################ ## SUB recv_data_block ## Read $_[0] bytes of data from the client. ################################################################################ sub recv_data_block { my $buffer = ''; my $data = ''; my $read; my $size = $_[0]; my $total = 0; while (1) { ($read, $buffer) = recv_data ($size - $total); $data .= $buffer; $total += $read; # Check if all data has been read if ($total == $size) { return $data; } } } ################################################################################ ## SUB ask_passwd ## Asks the user for a password. ################################################################################ sub ask_passwd { my $msg1 = $_[0]; my $msg2 = $_[1]; my $pwd1; my $pwd2; require Term::ReadKey; # Disable keyboard echo Term::ReadKey::ReadMode('noecho'); # Promt for password print ($msg1); $pwd1 = Term::ReadKey::ReadLine(0); print ("\n$msg2"); $pwd2 = Term::ReadKey::ReadLine(0); print ("\n"); # Restore original settings Term::ReadKey::ReadMode('restore'); if ($pwd1 ne $pwd2) { print ("Error: passwords do not match.\n"); exit 1; } # Remove the trailing new line character chop $pwd1; return $pwd1; } ################################################################################ ## SUB apply_filters ## Applies filters to the given file. ################################################################################ sub apply_filters ($) { my ($file_name) = @_; foreach my $filter (@t_filters) { my ($regexp, $dir) = @{$filter}; if ($file_name =~ /$regexp/) { print_log ("File '$file_name' matches filter '$regexp' (changing to directory '$dir')"); return $dir . '/'; } } return ''; } ################################################################################ ## SUB install_service ## Install the Windows service. ################################################################################ sub install_service() { my $service_path = $0; my $service_params = $SERVICE_PARAMS; # Change the service parameter from 'install' to 'run'. $service_params =~ s/\-S\s+\S+/\-S run/; my %service_hash = ( machine => '', name => 'TENTACLESRV', display => $SERVICE_NAME, path => $service_path, user => '', pwd => '', description => 'Tentacle Server http://sourceforge.net/projects/tentacled/', parameters => $service_params ); if (Win32::Daemon::CreateService(\%service_hash)) { print "Successfully added.\n"; exit 0; } else { print "Failed to add service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n"; exit 1; } } ################################################################################ ## SUB uninstall_service ## Install the Windows service. ################################################################################ sub uninstall_service() { if (Win32::Daemon::DeleteService('', 'TENTACLESRV')) { print "Successfully deleted.\n"; exit 0; } else { print "Failed to delete service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n"; exit 1; } } ################################################################################ ## SUB callback_running ## Windows service callback function for the running event. ################################################################################ sub callback_running { if (Win32::Daemon::State() == WIN32_SERVICE_RUNNING) { } } ################################################################################ ## SUB callback_start ## Windows service callback function for the start event. ################################################################################ sub callback_start { # Accept_connections (); my $thr = threads->create(\&accept_connections); if (!defined($thr)) { Win32::Daemon::State(WIN32_SERVICE_STOPPED); Win32::Daemon::StopService(); return; } $thr->detach(); Win32::Daemon::State(WIN32_SERVICE_RUNNING); } ################################################################################ ## SUB callback_stop ## Windows service callback function for the stop event. ################################################################################ sub callback_stop { foreach my $t_server_socket (@t_server_sockets) { $t_server_socket->shutdown (2); $t_server_socket->close (); } Win32::Daemon::State(WIN32_SERVICE_STOPPED); Win32::Daemon::StopService(); } ################################################################################ # Main ################################################################################ # Never run as root if ($> == 0 && $^O ne 'MSWin32') { print ("Error: for safety reasons $0 cannot be run with root privileges.\n"); exit 1; } # Parse command line options parse_options (); # Check command line arguments if ($#ARGV != -1) { print_help (); exit 1; } # Show IPv6 status if ($SOCKET_MODULE eq 'IO::Socket::INET') { print_log ("IO::Socket::INET6 is not found. IPv6 is disabled."); } # Run as daemon? if ($t_daemon == 1 && $^O ne 'MSWin32') { daemonize (); } # Handle ctr-c if ($^O eq 'MSWin32') { no warnings; $SIG{INT2} = \&stop_server; use warnings; } else { $SIG{INT} = \&stop_server; } # Accept connections accept_connections(); __END__ =head1 REQUIRED ARGUMENTES =over =item B<< -s F >> Root directory to store the files received by the server =back =head1 OPTIONS =over =item I<-a ip_address> Address to B on (default I<0.0.0.0>). =item I<-c number> B number of simultaneous B (default I<10>). =item I<-d> Run as B. =item I<-e cert> B file. Enables SSL. =item I<-f ca_cert> Verify that the peer certificate is signed by a B. =item I<-h> Show B. =item I<-i> B. =item I<-k key> B file. =item I<-m size> B in bytes (default I<2000000b>). =item I<-o> Enable file B. =item I<-p port> B on (default I<41121>). =item I<-q> B. Do now print error messages. =item I<-r number> B for network opertions (default I<3>). =item I<-t time> B for network operations in B (default I<1s>). =item I<-v> Be B. =item I<-w> Prompt for B. =item I<-x> pwd B. =back =head1 EXIT STATUS =over =item 0 on Success =item 1 on Error =back =head1 CONFIGURATION Tentacle doesn't use any configurationf files, all the configuration is done by the options passed when it's started. =head1 DEPENDENCIES L, L, L, L, L =head1 LICENSE This is released under the GNU Lesser General Public License. =head1 SEE ALSO L, L, L, L, L Protocol description and more info at: L<< http://openideas.info/wiki/index.php?title=Tentacle >> =head1 COPYRIGHT Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut unix/PaxHeaders.3873/plugins0000644000000000000000000000013212607655076014404 xustar000000000000000030 mtime=1444895294.619817018 30 atime=1444895297.975997748 30 ctime=1444895294.619817018 unix/plugins/0000755000000000000000000000000012607655076013536 5ustar00rootroot00000000000000unix/plugins/PaxHeaders.3873/pandora_df_free0000644000000000000000000000013212607655076017502 xustar000000000000000030 mtime=1444895294.611816587 30 atime=1444895304.232334647 30 ctime=1444895294.611816587 unix/plugins/pandora_df_free0000755000000000000000000000445212607655076016567 0ustar00rootroot00000000000000#!/usr/bin/perl ############################################################################### # # Copyright (c) 2009 Ramon Novoa # Copyright (c) 2009 Artica Soluciones Tecnologicas S.L. # # pandora_df Retrieve filesystem disk usage. By default information for all # filesystems is returned, but one or more filesystems may be # specified as command line parameters. # # Sample usage: ./pandora_df tmpfs /dev/sda1 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################### use strict; # Retrieve information from all filesystems my $all_filesystems = 0; # Check command line parameters if ($#ARGV < 0) { $all_filesystems = 1; } # Parse command line parameters my %filesystems; foreach my $fs (@ARGV) { $filesystems{$fs} = '0%'; } # Retrieve filesystem information # -P use the POSIX output format for portability my @df = `df -P`; shift (@df); # No filesystems? Something went wrong. if ($#df < 0) { exit 1; } # Parse filesystem usage foreach my $row (@df) { my @columns = split (' ', $row); exit 1 if ($#columns < 4); $filesystems{$columns[5]} = $columns[4] if (defined ($filesystems{$columns[5]}) || $all_filesystems == 1); } my $free; while (my ($filesystem, $use) = each (%filesystems)) { # Remove the trailing % chop ($use); $free = 100 - $use; # Print module output print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; } exit 0; unix/plugins/PaxHeaders.3873/pandora_update0000644000000000000000000000013012573660551017364 xustar000000000000000029 mtime=1441751401.99100716 30 atime=1444861867.832981353 29 ctime=1441751401.99100716 unix/plugins/pandora_update0000755000000000000000000001222112573660551016444 0ustar00rootroot00000000000000#!/usr/bin/perl # Update binary tool # Copyright (c) 2010 Artica Soluciones Tecnologicas S.L. # Copyright (c) Sancho Lerena use strict; use warnings; use POSIX qw(strftime); use Cwd 'abs_path'; use File::Basename; use File::Copy; use FindBin; use Digest::MD5 qw(md5); # Time to wait before the service stops use constant SERVICE_STOP_WAIT => 5; # This tool is intented to be used to update pandora agent binaries using # the file collection feature. This will work using a module like this: # Unix # module_begin # module_name Pandora_Update # module_type async_string # module_exec nohup pandora_update fc_1 2> /dev/null && tail -1 nohup.out 2> /dev/null # module_description Module to check new version of pandora agent and update itself # module_end # Windows: # module_begin # module_name Pandora_Update # module_type async_string # module_exec pandora_update.exe fc_1 # module_description Module to check new version of pandora agent and update itself # module_end # This small function return the current base path (where this tool is stored) sub return_basepath () { return $FindBin::Bin; } # Function to compare two binary files. Return 0 if different 1 if equal, 2 error sub compare_twofiles ($$) { my $file1 = $_[0]; my $file2 = $_[1]; my $size1 = -s $file1; my $size2 = -s $file2; # Size matters; if ((!defined($size1)) || (!defined($size2))){ return 2; } if ($size1 != $size2){ return 0; } open FILE1, $file1; binmode FILE1; my $data1 = join ('', ); close FILE1; my $hash1 = md5($data1); open FILE2, $file2; binmode FILE2; my $data2 = join ('', ); close FILE2; my $hash2 = md5($data2); if ($hash1 eq $hash2){ return 1; } return 0; } # Get agent pid sub get_agent_pid ($$) { my $daemon = shift; my $app_path = shift; $ENV{'COLUMNS'}=400; my $os_name=`uname -s`; my $pid = ""; my $cmd = ""; if ($os_name eq "HP-UX") { $cmd ="ps -ex | grep \"$daemon $app_path\" | grep -v grep | head -1 | awk '{ print \$1 }'"; } elsif ($os_name =~ /SunOS/) { my $cmd_aux="echo \"$daemon $app_path\" | cut -c1-40"; my $truncated_daemon = `$cmd_aux`; chop($truncated_daemon); my $zone = `/bin/zonename`; if ( $zone =~ /global/) { $cmd ="ps -f -z global | grep \"$truncated_daemon\" | grep -v grep | head -1 | awk '{ print \$2 }'"; } else { $cmd ="ps -Af | grep \"$truncated_daemon\" | grep -v grep | head -1 | awk '{ print \$2 }'"; } } else { $cmd ="ps -Af | grep \"$daemon $app_path\" | grep -v grep | head -1 | awk '{ print \$2 }'"; } $pid = `$cmd`; return $pid; } # ------------------------------------------------------------------------- # MAIN CODE starts here # Get the required path (relative to basepath) to find pandora agent binary if ($#ARGV < 0) { print "Usage: $0 $local_log"); close (FILE3); my $ppid = get_agent_pid($running_binary, $conf_path); # Kill parent process (a.k.a the Agent) my $output = `kill -9 $ppid`; sleep SERVICE_STOP_WAIT; # Copy the updated agent copy($updated_binary, $running_binary) or unlink $local_log; # Starting the agent again my $log = $opt_dir."/var/log/pandora/pandora_agent.log"; $output = `nohup $running_binary $conf_path >/dev/null 2>$log &` } else { if (-e $local_log){ print "Updated binary from $updated_binary\n"; unlink $local_log; } } exit; unix/plugins/PaxHeaders.3873/pandora_df0000644000000000000000000000013112607655076016500 xustar000000000000000030 mtime=1444895294.611816587 29 atime=1444895304.24033508 30 ctime=1444895294.611816587 unix/plugins/pandora_df0000755000000000000000000000452412607655076015566 0ustar00rootroot00000000000000#!/usr/bin/perl ############################################################################### # # Copyright (c) 2009 Ramon Novoa # Copyright (c) 2009 Artica Soluciones Tecnologicas S.L. # # pandora_df Retrieve filesystem disk usage. By default information for all # filesystems is returned, but one or more filesystems may be # specified as command line parameters. If parameter start with # a '-', the filesystem is excluded from results. # # Sample usage: ./pandora_df tmpfs /dev/sda1 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################### use strict; # Retrieve information from all filesystems my $all_filesystems = 0; # Check command line parameters if ($#ARGV < 0) { $all_filesystems = 1; } # Parse command line parameters my %filesystems; my %excluded_filesystems; my $onlyexclude = 1; foreach my $fs (@ARGV) { if (substr($fs,0,1) eq '-') { $excluded_filesystems{substr($fs,1,)} = '-1%'; } else { $filesystems{$fs} = '-1%'; $onlyexclude = 0; } } if ($onlyexclude) { $all_filesystems = 1; } # Retrieve filesystem information # -P use the POSIX output format for portability my @df = `df -P`; shift (@df); # No filesystems? Something went wrong. if ($#df < 0) { exit 1; } # Parse filesystem usage foreach my $row (@df) { my @columns = split (' ', $row); exit 1 if ($#columns < 4); if (defined ($filesystems{$columns[0]}) || ($all_filesystems == 1 && !defined ($excluded_filesystems{$columns[0]}))) { $filesystems{$columns[0]} = $columns[4] ; } } while (my ($filesystem, $use) = each (%filesystems)) { # Remove the trailing % chop ($use); # Print module output print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; } exit 0; unix/plugins/PaxHeaders.3873/pandora_mem0000644000000000000000000000013012573660551016660 xustar000000000000000029 mtime=1441751401.99100716 30 atime=1444861867.832981353 29 ctime=1441751401.99100716 unix/plugins/pandora_mem0000755000000000000000000000453012573660551015744 0ustar00rootroot00000000000000#!/usr/bin/perl # Pandora FMS Plugin to get memory information on Linux # (c) 2014 Sancho Lerena \n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; unix/plugins/PaxHeaders.3873/top.sh0000644000000000000000000000013112607655076015616 xustar000000000000000030 mtime=1444895294.619817018 29 atime=1444895304.24033508 30 ctime=1444895294.619817018 unix/plugins/top.sh0000755000000000000000000000026212607655076014677 0ustar00rootroot00000000000000echo ""; echo ""; echo ""; echo "" echo "" unix/plugins/PaxHeaders.3873/pandora_netusage0000644000000000000000000000013112607655076017722 xustar000000000000000030 mtime=1444895294.611816587 29 atime=1444895304.24033508 30 ctime=1444895294.611816587 unix/plugins/pandora_netusage0000755000000000000000000000071512607655076017006 0ustar00rootroot00000000000000#!/bin/bash OUT=`netstat -as | grep "OutOctets" | awk '{ print $2 }'` IN=`netstat -as | grep "InOctets" | awk '{ print $2 }'` TOTAL=`expr $OUT + $IN` echo "" echo " " echo " " echo " " echo " " echo " " echo "" unix/plugins/PaxHeaders.3873/grep_log0000644000000000000000000000013212573660551016176 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/plugins/grep_log0000755000000000000000000001574612573660551015273 0ustar00rootroot00000000000000#!/usr/bin/perl ############################################################################### # # Copyright (c) 2008 Ramon Novoa # Copyright (c) 2008 Artica Soluciones Tecnologicas S.L. # # grep_log Perl script to search log files for a matching pattern. The last # searched position is saved in an index file so that consecutive # runs do not return the same results. The log file inode number is # also saved to detect log rotation. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################### use strict; use File::Basename; # Output format (module or log_module). my $Output = 'module'; # Be verbose my $Verbose = 0; # Index file storage directory, with a trailing '/' my $Idx_dir='/tmp/'; # Log file my $Log_file = ''; # Module name my $Module_name = "default_log"; # Index file my $Idx_file = ''; # Log file position index my $Idx_pos = 0; # Log file inode number my $Idx_ino = ''; # Log file size my $Idx_size = 0; # Regular expression to be matched my $Reg_exp = ''; ############################################################################### # SUB error_msg # Print an error message and exit. ############################################################################### sub error_msg ($) { my $err_msg = $_[0]; if (! -z $err_msg) { print(stderr "[error] $err_msg.\n"); } exit 1; } ############################################################################### # SUB print_help # Print a help message. ############################################################################### sub print_help () { print "Usage: $0 \n"; } ############################################################################### # SUB log_msg # Print a log message. ############################################################################### sub log_msg ($) { my $log_msg = $_[0]; if (! -z $log_msg && $Verbose == 1) { print(stdout "[log] $log_msg.\n"); } } ############################################################################### # SUB load_idx # Load index file. ############################################################################### sub load_idx () { my $line; my $current_ino; my $current_size; log_msg("Loading index file $Idx_file"); open(IDXFILE, $Idx_file) || error_msg("Error opening file $Idx_file: " . $!); # Read position and date $line = ; ($Idx_pos, $Idx_ino, $Idx_size) = split(' ', $line); close(IDXFILE); # Reset the file index if the file has changed $current_ino = (stat($Log_file))[1]; $current_size = -s "$Log_file"; if ($current_ino != $Idx_ino || $current_size < $Idx_size) { log_msg("File changed, resetting index"); $Idx_pos = 0; $Idx_ino = $current_ino; } $Idx_size = $current_size; return; } ############################################################################### # SUB save_idx # Save index file. ############################################################################### sub save_idx () { log_msg("Saving index file $Idx_file"); open(IDXFILE, "> $Idx_file") || error_msg("Error opening file $Idx_file: " . $!); print (IDXFILE $Idx_pos . " " . $Idx_ino . " " . $Idx_size); close(IDXFILE); return; } ############################################################################### # SUB create_idx # Create index file. ############################################################################### sub create_idx () { my $first_line; log_msg("Creating index file $Idx_file"); open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " . $!); # Go to EOF and save the position seek(LOGFILE, 0, 2); $Idx_pos = tell(LOGFILE); close(LOGFILE); # Save the file inode number $Idx_ino = (stat($Log_file))[1]; # Save the index file save_idx(); return; } ############################################################################### # SUB parse_log # Parse log file starting from position $Idx_pos. ############################################################################### sub parse_log () { my $line; log_msg("Parsing log file $Log_file"); # Open log file for reading open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " . $!); # Go to starting position. seek(LOGFILE, $Idx_pos, 0); # Parse log file my @data; while ($line = ) { if ($line =~ m/$Reg_exp/i) { push (@data, $line); } } $Idx_pos = tell(LOGFILE); close(LOGFILE); # Save the index file save_idx(); return @data; } ############################################################################### # SUB parse_log # Print log data to stdout. ############################################################################### sub print_log (@) { my @data = @_; # No data if ($#data < 0) { return; } # Log module if ($Output eq 'log_module') { my $output = "\n"; $output .= "\n"; $output .= ""; $output .= "\n"; print stdout $output; } # Regular module else { my $output = "\n"; $output .= "\n"; $output .= "\n"; $output .= "\n"; foreach my $line (@data) { $output .= "\n"; } $output .= "\n"; $output .= "\n"; print stdout $output; } } ############################################################################### ############################################################################### ## Main ############################################################################### ############################################################################### # Check command line parameters if ($#ARGV != 2) { print_help(); exit 1; } $Log_file = $ARGV[0]; $Module_name = $ARGV[1]; $Reg_exp = $ARGV[2]; # Create index file storage directory if ( ! -d $Idx_dir) { mkdir($Idx_dir) || error_msg("Error creating directory $Idx_dir: " . $!); } # Check that log file exists if (! -e $Log_file) { error_msg("File $Log_file does not exist"); } # Create index file if it does not exist $Idx_file=$Idx_dir . $Module_name . "_" . basename($Log_file) . ".idx"; if (! -e $Idx_file) { create_idx(); exit 0; } # Load index file load_idx(); # Parse log file my @data = parse_log(); # Print output to stdout print_log (@data); exit 0; unix/plugins/PaxHeaders.3873/grep_log_module0000644000000000000000000000013212573660551017543 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/plugins/grep_log_module0000755000000000000000000001600212573660551016622 0ustar00rootroot00000000000000#!/usr/bin/perl ############################################################################### # # Copyright (c) 2012 Ramon Novoa # Copyright (c) 2012 Artica Soluciones Tecnologicas S.L. # # grep_log_module Perl script to search log files for a matching pattern. The # last searched position is saved in an index file so that # consecutive runs do not return the same results. The log file # inode number is also saved to detect log rotation. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################### use strict; use File::Basename; # Output format (module or log_module). my $Output = 'log_module'; # Be verbose my $Verbose = 0; # Index file storage directory, with a trailing '/' my $Idx_dir='/tmp/'; # Log file my $Log_file = ''; # Module name my $Module_name = "default_log"; # Index file my $Idx_file = ''; # Log file position index my $Idx_pos = 0; # Log file inode number my $Idx_ino = ''; # Log file size my $Idx_size = 0; # Regular expression to be matched my $Reg_exp = ''; ############################################################################### # SUB error_msg # Print an error message and exit. ############################################################################### sub error_msg ($) { my $err_msg = $_[0]; if (! -z $err_msg) { print(stderr "[error] $err_msg.\n"); } exit 1; } ############################################################################### # SUB print_help # Print a help message. ############################################################################### sub print_help () { print "Usage: $0 \n"; } ############################################################################### # SUB log_msg # Print a log message. ############################################################################### sub log_msg ($) { my $log_msg = $_[0]; if (! -z $log_msg && $Verbose == 1) { print(stdout "[log] $log_msg.\n"); } } ############################################################################### # SUB load_idx # Load index file. ############################################################################### sub load_idx () { my $line; my $current_ino; my $current_size; log_msg("Loading index file $Idx_file"); open(IDXFILE, $Idx_file) || error_msg("Error opening file $Idx_file: " . $!); # Read position and date $line = ; ($Idx_pos, $Idx_ino, $Idx_size) = split(' ', $line); close(IDXFILE); # Reset the file index if the file has changed $current_ino = (stat($Log_file))[1]; $current_size = -s "$Log_file"; if ($current_ino != $Idx_ino || $current_size < $Idx_size) { log_msg("File changed, resetting index"); $Idx_pos = 0; $Idx_ino = $current_ino; } $Idx_size = $current_size; return; } ############################################################################### # SUB save_idx # Save index file. ############################################################################### sub save_idx () { log_msg("Saving index file $Idx_file"); open(IDXFILE, "> $Idx_file") || error_msg("Error opening file $Idx_file: " . $!); print (IDXFILE $Idx_pos . " " . $Idx_ino . " " . $Idx_size); close(IDXFILE); return; } ############################################################################### # SUB create_idx # Create index file. ############################################################################### sub create_idx () { my $first_line; log_msg("Creating index file $Idx_file"); open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " . $!); # Go to EOF and save the position seek(LOGFILE, 0, 2); $Idx_pos = tell(LOGFILE); close(LOGFILE); # Save the file inode number $Idx_ino = (stat($Log_file))[1]; # Save the index file save_idx(); return; } ############################################################################### # SUB parse_log # Parse log file starting from position $Idx_pos. ############################################################################### sub parse_log () { my $line; log_msg("Parsing log file $Log_file"); # Open log file for reading open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " . $!); # Go to starting position. seek(LOGFILE, $Idx_pos, 0); # Parse log file my @data; while ($line = ) { if ($line =~ m/$Reg_exp/i) { push (@data, $line); } } $Idx_pos = tell(LOGFILE); close(LOGFILE); # Save the index file save_idx(); return @data; } ############################################################################### # SUB parse_log # Print log data to stdout. ############################################################################### sub print_log (@) { my @data = @_; # No data if ($#data < 0) { return; } # Log module if ($Output eq 'log_module') { my $output = "\n"; $output .= "\n"; $output .= ""; $output .= "\n"; print stdout $output; } # Regular module else { my $output = "\n"; $output .= "\n"; $output .= "\n"; $output .= "\n"; foreach my $line (@data) { $output .= "\n"; } $output .= "\n"; $output .= "\n"; print stdout $output; } } ############################################################################### ############################################################################### ## Main ############################################################################### ############################################################################### # Check command line parameters if ($#ARGV != 2) { print_help(); exit 1; } $Log_file = $ARGV[0]; $Module_name = $ARGV[1]; $Reg_exp = $ARGV[2]; # Create index file storage directory if ( ! -d $Idx_dir) { mkdir($Idx_dir) || error_msg("Error creating directory $Idx_dir: " . $!); } # Check that log file exists if (! -e $Log_file) { error_msg("File $Log_file does not exist"); } # Create index file if it does not exist $Idx_file=$Idx_dir . $Module_name . "_" . basename($Log_file) . ".idx"; if (! -e $Idx_file) { create_idx(); exit 0; } # Load index file load_idx(); # Parse log file my @data = parse_log(); # Print output to stdout print_log (@data); exit 0; unix/plugins/PaxHeaders.3873/files_indir0000644000000000000000000000013112607655076016672 xustar000000000000000030 mtime=1444895294.611816587 29 atime=1444895304.24033508 30 ctime=1444895294.611816587 unix/plugins/files_indir0000755000000000000000000000203512607655076015753 0ustar00rootroot00000000000000#!/bin/sh # Syntax: # # Directory_Name : Directory to check if [ -z "$1" ] then echo "You need too pass target directory to monitor" echo "Plugin will report CRITICAL if previous number" echo "of files in directory is greater than actual number" exit fi DIRE=$1 if [ `uname -s` = "FreeBSD" ];then DIRETMP=`echo $DIRE | /sbin/md5`; else DIRETMP=`echo $DIRE | md5sum | awk '{ print $1 }'` fi DIRETMP=/tmp/$DIRETMP CURRENT=`ls -la ${DIRE} | wc -l | tr -d ' '` if [ -e $DIRETMP ] then ANTERIOR=`cat $DIRETMP` else ANTERIOR=0 fi if [ $ANTERIOR -gt $CURRENT ] then DISPARA=0 else DISPARA=1 fi echo $CURRENT > $DIRETMP echo " " unix/plugins/PaxHeaders.3873/nagios_plugin_wrapper0000644000000000000000000000013112607655076021001 xustar000000000000000030 mtime=1444895294.611816587 29 atime=1444895304.24033508 30 ctime=1444895294.611816587 unix/plugins/nagios_plugin_wrapper0000755000000000000000000000466412607655076020074 0ustar00rootroot00000000000000#!/usr/bin/perl ########################################################################## # nagios_plugin_wrapper # # Executes the given nagios plugin and produces an XML with data for pandora # to be used as agent plugin. This allows to have DATA based on the errorlevel # and use the descriptive information on description for the module # # Usage: nagios_plugin_wrapper ########################################################################## # Copyright (c) 2010 Artica Soluciones Tecnologicas S.L # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## use strict; use warnings; my $command = ""; my @opts = @ARGV; my $module_name = shift(@opts); $command = join(' ', @opts); if ($command ne ""){ my $module_data = `$command`; my $module_description = $module_data; my $ReturnCode = ($? >> 8) & 0xff; # Get the errorlevel if is a Nagios plugin type (parsing the errorlevel) # Nagios errorlevels: #('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); # By default is unknown $module_data = ""; if ($ReturnCode == 2){ $module_data = 0; } elsif ($ReturnCode == 3){ $module_data = ''; # not defined = Uknown } elsif ($ReturnCode == 0){ $module_data = 1; } elsif ($ReturnCode == 1){ $module_data = 2; # need to be managed on module thresholds } elsif ($ReturnCode == 4){ $module_data = 3; # need to be managed on module thresholds } print ""; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; } unix/plugins/PaxHeaders.3873/inventory0000644000000000000000000000013212573660551016435 xustar000000000000000030 mtime=1441751401.987006935 30 atime=1444861867.832981353 30 ctime=1441751401.987006935 unix/plugins/inventory0000755000000000000000000002730512573660551015524 0ustar00rootroot00000000000000#!/usr/bin/perl ############################################################################### # # Copyright (c) 2009 Artica Soluciones Tecnologicas S.L. # # inventory Generate a hardware/software inventory. # # Sample usage: ./inventory [cpu] [ram] [video] [nic] [hd] [cdrom] [software] [init_services] [filesystem] [process] [users] # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################### use strict; use constant TSTAMP_FILE => '/tmp/pandora_inventory.tstamp'; # Operation mode (LSHW or HWINFO) my $Mode; # Item separator my $Separator; # Parse module information sub get_module_data ($$$$) { my ($name, $hwinfo, $keys, $modules) = @_; my %module; # Store keys foreach my $key (@{$keys}) { push (@{$module{'_keys'}}, $key); } # Parse module data while (my $line = shift (@{$hwinfo})) { if ($line =~ /$Separator/) { unshift (@{$hwinfo}, $line); last; } foreach my $key (@{$keys}) { if ($line =~ /$key:\s+(.+)/) { $module{$key} = $1; # Replace semicolon by comma to avoid parse errors $module{$key} =~ s/;/,/g; } } } # No data found my @data = keys (%module); return unless ($#data >= 0); push (@{$modules->{$name}}, \%module); } # Get a list of information file system in machine sub get_file_system($$) { my ($name, $modules) = @_; my @fileSystems = `df -hP | tail -n +2`; #remove the titles of columns foreach my $row (@fileSystems) { next unless ($row =~ /^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+\S+\s+(\S+)/); my %module; $module{'filesystem'} = $1; $module{'used'} = $2; $module{'avail'} = $3; $module{'mount'} = $4; $module{'_keys'} = ['filesystem', 'used','avail', 'mount']; push (@{$modules->{$name}}, \%module); } } # Get a list of services init in machine sub get_servicies_init_machine($$) { my ($name, $modules) = @_; my $runlevel = `who -r | awk '{print \$2}'`; #ini trim($runlevel) $runlevel =~ s/^\s*//; #ltrim $runlevel =~ s/\s*$//; #rtrim #end trim($runlevel) my $script = ""; if (-e "/etc/rc" . $runlevel .".d/") { $script = "ls /etc/rc" . $runlevel .".d/ -l | grep \"^l.*\" | awk \"{print \\\$NF}\" | sed -e \"s/\\.\\.\\///g\" | sed -e \"s/.*init\\.d\\///g\""; } else { $script = "ls /etc/rc.d/rc" . $runlevel .".d/ -l | grep \"^l.*\" | grep \" S.* \" | awk \"{print \\\$NF}\" | sed -e \"s/\\.\\.\\///g\" | sed -e \"s/.*init\\.d\\///g\""; } my @services = `$script`; foreach my $row (@services) { my %module; $row =~ s/\n//; $module{'service'} = $row; $module{'_keys'} = ['service']; push (@{$modules->{$name}}, \%module); } } # Get a list of running processes sub get_processes ($$) { my ($name, $modules) = @_; my $script = "ps -eo command"; my @services = `$script`; foreach my $row (@services) { my %module; # Remove carriage returns $row =~ s/[\n\l\f]//g; # Replace semicolon by comma to avoid parse errors $row =~ s/;/,/g; $module{'service'} = $row; $module{'_keys'} = ['service']; push (@{$modules->{$name}}, \%module); } } # Get a list of valid users in the system sub get_users ($$) { my ($name, $modules) = @_; my $script = "cat /etc/passwd"; my $user = ""; my $estado = ""; my @services = `$script`; foreach my $row (@services) { my %module; next unless ($row =~ /^([A-Za-z0-9\-\_]*)/); $user = $1; $script = `passwd -S $user`; if ( $script =~ /^(\S+)\sP./){ $module{'user'} = $user; $module{'_keys'} = ['user']; push (@{$modules->{$name}}, \%module); } } } # Show Kernel Information sub get_kernel_info ($$) { my ($name, $modules) = @_; my $script = `uname -a | tr -d \";\"`; my %module; $module{'Kernel'} = $script; $module{'_keys'} = ['Kernel']; push (@{$modules->{$name}}, \%module); } # Get a list of installed programs sub get_software_module_data ($$) { my ($name, $modules) = @_; # Guess the current distribution my $distrib_id = ""; if ( -e "/etc/SuSE-release"){ $distrib_id = "SUSE"; } elsif ( -e "/etc/redhat-release"){ $distrib_id = "REDHAT"; } else { $distrib_id = "DEBIAN"; } # List installed programs my @soft; if ($distrib_id eq 'DEBIAN') { @soft = `dpkg -l | grep ii`; } else { # Sometimes rpm return data splitted in two lines, and with dupes. Thats bad for our inventory system @soft = `rpm -q -a --qf "ii %{NAME} %{VERSION} %{SUMMARY}\n" | grep "^ii" | sort -u`; } # Parse data foreach my $row (@soft) { next unless ($row =~ /^ii\s+(\S+)\s+(\S+)\s+([^\n]+)/); my %module; $module{'program'} = $1; $module{'version'} = $2; $module{'description'} = $3; # Replace semicolon by comma to avoid parse errors $module{'program'} =~ s/;/,/g; $module{'version'} =~ s/;/,/g; $module{'description'} =~ s/;/,/g; $module{'_keys'} = ['program', 'version','description']; push (@{$modules->{$name}}, \%module); } } #Get the list of interfaces with the ip assigned sub get_ips ($$) { my ($name, $modules) = @_; my $ifconfig = `ifconfig`; my @ifconfig_array = split("\n", $ifconfig); for(my $i = 0; $i<$#ifconfig_array; $i++) { #Check for an interface if ($ifconfig_array[$i] =~ /Link/) { my %info; my @line_split = split(" ", $ifconfig_array[$i]); #Get interface name $info{'interface'} = $line_split[0]; #Get IP address my $line = $ifconfig_array[$i+1]; $line =~ s/\s+//g; @line_split = split(":", $line); if($line_split[1] =~ /(\d+\.\d+\.\d+\.\d+).+/) { $info{'ip'} = $1; } $info{'_keys'} = ['interface', 'ip']; push (@{$modules->{$name}}, \%info); } } } #Get route table sub get_route_table ($$) { my ($name, $modules) = @_; my $route_table = `route`; my @table_split = split("\n", $route_table); for (my $i=2; $i<=$#table_split; $i++) { my @split = split(" ", $table_split[$i]); my %info; $info{'destination'} = $split[0]; $info{'gateway'} = $split[1]; $info{'mask'} = $split[2]; $info{'flags'} = $split[3]; $info{'metric'} = $split[4]; $info{'ref'} = $split[5]; $info{'use'} = $split[6]; $info{'interface'} = $split[7]; $info{'_keys'} = ['destination', 'gateway', 'mask', 'flags', 'metric', 'use', 'interface']; push (@{$modules->{$name}}, \%info); } } # Print module data sub print_module ($$) { my ($name, $module) = @_; print " \n"; print " \n"; print " \n"; foreach my $item (@{$module}) { # Compose module data my $data = undef; foreach my $key (@{$item->{'_keys'}}) { $data = (!defined($data) ? '' : "$data;"); if (defined($item->{$key})) { $data .= $item->{$key}; } } print " \n"; } print " \n"; print " \n"; } # Check command line parameters if ($#ARGV < 0) { print "Usage: $0 [cpu] [ram] [video] [nic] [hd] [cdrom] [software] [init_services] [filesystem] [users] [process] [ip] [route] [kernel] \n\n"; exit 1; } # Parse command line parameters my %enabled; my $interval = 1; my $enable_all = 0; $interval = $ARGV[0]; if ($#ARGV == 0){ $enable_all = 1; } foreach my $module (@ARGV) { if ($module eq "all"){ $enable_all = 1; } $enabled{$module} = 1; } # Check execution interval if (-f TSTAMP_FILE) { open (FILE, '<' . TSTAMP_FILE) || exit 1; my $last_execution = ; close (FILE); exit 0 if ($last_execution + 86400 * $interval > time ()); } open (FILE, '>' . TSTAMP_FILE) || exit 1; print FILE time (); close (FILE); # Retrieve hardware information $Mode = 'LSHW'; $Separator = '\s+\*\-'; my @hwinfo = `lshw 2>/dev/null`; if ($? != 0) { $Mode = 'HWINFO'; $Separator = 'Hardware Class:'; @hwinfo = `hwinfo --cpu --memory --gfxcard --netcard --cdrom --disk 2>/dev/null`; } # Parse hardware information my %modules; while (my $line = shift (@hwinfo)) { chomp ($line); # CPU if (($line =~ /\*\-cpu/ || $line =~ /Hardware Class: cpu/) && ($enable_all == 1 || $enabled{'cpu'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('CPU', \@hwinfo, ['product', 'vendor', 'capacity'], \%modules); } else { get_module_data ('CPU', \@hwinfo, ['Model', 'Vendor', 'Clock'], \%modules); } } # RAM if (($line =~ /\*\-bank/ || $line =~ /Hardware Class: memory/) && ($enable_all == 1 || $enabled{'ram'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('RAM', \@hwinfo, ['description', 'size'], \%modules); } else { get_module_data ('RAM', \@hwinfo, ['Model', 'Memory Size'], \%modules); } } # VIDEO if (($line =~ /\*\-display/ || $line =~ /Hardware Class: graphics card/) && ($enable_all == 1 || $enabled{'video'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('VIDEO', \@hwinfo, ['product', 'description', 'vendor'], \%modules); } else { # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor get_module_data ('VIDEO', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); } } # NIC if (($line =~ /\*\-network/ || $line =~ /Hardware Class: network/) && ($enable_all == 1 || $enabled{'nic'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('NIC', \@hwinfo, ['product', 'description', 'vendor', 'serial'], \%modules); } else { # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor get_module_data ('NIC', \@hwinfo, ['Model', ' Device', ' Vendor', 'HW Address'], \%modules); } } # CDROM if (($line =~ /\*\-cdrom/ || $line =~ /Hardware Class: cdrom/) && ($enable_all == 1 || $enabled{'cdrom'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('CDROM', \@hwinfo, ['product', 'description', 'vendor'], \%modules); } else { # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor get_module_data ('CDROM', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); } } # HD if (($line =~ /\*\-disk/ || $line =~ /Hardware Class: disk/) && ($enable_all == 1 || $enabled{'hd'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('HD', \@hwinfo, ['product', 'description', 'size'], \%modules); } else { get_module_data ('HD', \@hwinfo, ['Model', 'Serial ID', 'Size'], \%modules); } } } # Software if ($enable_all == 1 || $enabled{'software'} == 1) { get_software_module_data ('Software', \%modules); } #init_services if ($enable_all == 1 || $enabled{'init_services'} == 1) { get_servicies_init_machine ('Init services', \%modules); } #filesystem if ($enable_all == 1 || $enabled{'filesystem'} == 1) { get_file_system('File system', \%modules); } #processes if ($enable_all == 1 || $enabled{'process'} == 1) { get_processes('Process', \%modules); } #users if ($enable_all == 1 || $enabled{'users'} == 1){ get_users ('Users', \%modules); } #ip if ($enable_all == 1 || $enabled{'ip'} == 1) { get_ips('IP', \%modules); } #route if ($enable_all == 1 || $enabled{'route'} == 1) { get_route_table('Routes', \%modules); } #kernel if ($enable_all == 1 || $enabled{'kernel'} == 1){ get_kernel_info ('Kernel', \%modules); } # Print module data print "\n"; while (my ($name, $module) = each (%modules)) { print_module ($name, $module); } print "\n"; exit 0; unix/plugins/PaxHeaders.3873/who.sh0000644000000000000000000000013112607655076015611 xustar000000000000000030 mtime=1444895294.619817018 29 atime=1444895304.24033508 30 ctime=1444895294.619817018 unix/plugins/who.sh0000755000000000000000000000035412607655076014674 0ustar00rootroot00000000000000#!/bin/sh echo ""; echo ""; echo ""; echo "" echo ""