├── BSD-license.txt ├── ChangeLog ├── README ├── README.plugins ├── bin ├── RebuildHierarchy.pl ├── nfsen ├── nfsend └── testPlugin ├── contrib └── PortTracker │ ├── INSTALL │ ├── PortTracker.php │ └── PortTracker.pm ├── etc └── nfsen-dist.conf ├── html ├── alerting.php ├── colour_palette.html ├── colour_picker.html ├── css │ ├── alerting.css │ ├── detail.css │ ├── lookup.css │ ├── nfsen.css │ └── profileadmin.css ├── details.php ├── icons │ ├── EmptyGraph.png │ ├── Error.png │ ├── ErrorGraph.png │ ├── arrow.blue.down.png │ ├── arrow.blue.right.png │ ├── arrow.yellow.down.png │ ├── arrow.yellow.right.png │ ├── cancel.png │ ├── close.png │ ├── cursor-line.png │ ├── cursor-start.png │ ├── cursor-stop.png │ ├── edit.png │ ├── help.png │ ├── invisible.png │ ├── minus.png │ ├── ok.png │ ├── plus.png │ ├── progress.png │ ├── save.png │ ├── shade.gif │ ├── shade.png │ ├── shadeactive.png │ ├── space.png │ ├── spyglas.png │ ├── trash.png │ └── trigger.png ├── js │ ├── ColorPicker2.js │ ├── alerting.js │ ├── detail.js │ ├── global.js │ ├── menu.js │ └── profileadmin.js ├── lookup.php ├── navigator.php ├── nfsen.php ├── nfsenutil.php ├── overview.php ├── pic.php ├── process.php ├── profileadmin.php └── rrdgraph.php ├── install.pl ├── installer-items ├── CopyRecursive.pm └── RRDconvertv1.pm ├── libexec ├── AbuseWhois.pm ├── Log.pm ├── Lookup.pm ├── NfAlert.pm ├── NfConf.pm ├── NfProfile.pm ├── NfSen.pm ├── NfSenRC.pm ├── NfSenRRD.pm ├── NfSenSim.pm ├── Nfcomm.pm ├── Nfsources.pm ├── Nfsync.pm └── Notification.pm └── plugins ├── PluginTemplate.pm ├── backend ├── demoplugin.pm └── smily.jpg └── frontend └── demoplugin.php /BSD-license.txt: -------------------------------------------------------------------------------- 1 | * 2 | * The nfdump project is distributed under the BSD license: 3 | * 4 | * Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * * Neither the name of SWITCH nor the names of its contributors may be 16 | * used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2023-02-10 2 | - Fix #5 - CYCLETIME. 3 | 4 | 2022-12-22 5 | - Re-vitalize NfSen on github. Adapt for nfdump-1.7.x 6 | 7 | 2017-01-19 8 | - Fix Security Vulenrability - which may execute arbitrary commands from the web interface. 9 | - Support rrdtools 1.6 10 | 11 | 2014-12-23 12 | - Fix various incompatibilities with newer php and Perl versions 13 | - Fix empty details graph, if too many channels or resources were selected. 14 | - Fix argument bug in selecting the dstmac statistics 15 | - Fix bug in create history profiles: compression flag was not applied properly 16 | - Add periodic reload feature for Perls with mem leak. 17 | 18 | 2012-01-29 1.3.6p1 19 | - Fix UNIVERSAL->import warning for new Perl 5.12 20 | - Fix sem* bugs. semaphore moved into Nfsem - initial installation broken 21 | - Fix IPv6 lookups 22 | - Fix lookups of IPs in ICMP listing 23 | - Add default values lifetime/maxsize for new profile - safety measure. 24 | - Add experimental interrupted expire ( only with nfdump patch or nfdump > 1.6.5 ) 25 | 26 | 2011-07-20 1.3.6 27 | - Fix potential XSS bugs 28 | - Fix email address validation in alerting. also allow ..@localhost 29 | - Add option 'all' in rebuild command to rebuild graphs 30 | - Extend lookup box to 400px 31 | - Add missing stat option from v9 into details.php 32 | - Extend too short limits from textareas from 50 to 10240 33 | - Add a total display at the bottom of the statistics table in details.php 34 | - Replace deprecated split functions in php code 35 | - Replace IP lookup code with new AbuseWhois 36 | 37 | 2010-07-24 1.3.5 stable version - bugfix release of nfsen-1.3.4 38 | - fix broken reconfig, when adding new sources 39 | - inherit 'live' channel parameters for new 1:1 profile 40 | 41 | 2010-07-03 1.3.4 stable version - bugfix release of nfsen-1.3.3 42 | - fix installer problems with Module File::Copy make_path/mkpath 43 | - fix optarg bug in NfSenRC.pm 44 | - Add bigger scales in details page 45 | - Allow rrd version 1.4.x 46 | 47 | 2010-05-01 1.3.3 stable version 48 | - Honour profile maxsize and max lifetime while building 49 | Abort build when either limit is reached 50 | - Add cancal button while building a profile 51 | - Add delayed deleting profile. Prevent annoying message 52 | "Can not delete profile while periodic update in progress" 53 | - Add FORMATDIR to config. Defaults to $VARDIR/fmt 54 | - Add FILTERDIR to config. Defaults to $VARDIR/filters 55 | - Add PIDDIR to config. Defaults to $VARDIR/run 56 | - Add INSTALLPATH to installer 57 | - Fix Safari 4 Lookup box issues 58 | - Fix several small bugs/issues 59 | 60 | 2009-06-08 1.3.2 stable release 61 | - Fix security bug - potential remote execution 62 | 63 | 2009-13-03 1.3.1 stable release 64 | - fixing bugs from 1.3 65 | - Add support for RRD 1.3.x 66 | - Add parallel profiling patch 67 | 68 | 2007-11-20 1.3 stable release 69 | - Fix bugs from last 1.3b 70 | - Add compression configuration for nfdump-1.5.6. See nfsen-dist.conf 71 | 72 | 2007-08-24 1.3b-20070824 73 | - Bug fixes from 1.3b-20070719 74 | - Try to better handle Solaris Syslog 75 | - Make install smooth on Solaris 76 | 77 | 2007-07-19 1.3b-20070719 78 | - Release beta 1.3 for testing. 79 | - Number of bug fixes of last snapshot 80 | - Make nfsen clean up orphan data files when starting up. 81 | - Make some changes in default behaviour of netflow processing. Defaults to Top 10 any IP 82 | 83 | 2007-03-06 snapshot-20070306 84 | - Add alerting module: NfAlert.pm, alerting.php, alerting.css alerting.js 85 | - Add shadow profiles. 86 | - Include bug fixes from last snapshot: feedback from users 87 | 88 | 2007-01-26 snapshot-20070126 89 | - Replace plugging END routine by Cleanup due to erroneous calling at the end of the comm server process 90 | - Make Opera work. minor change for in arg parsing 91 | - Fix bug for IPv6 filter checks 92 | - Fix some other small bugs reported back. 93 | 94 | 2007-01-10 snapshot-20070110 95 | - Intermediate snapshot for developers - not for production 96 | - Major change: Add channel based architecture 97 | - Lots of face liftings for NfSen 98 | 99 | 2006-07-28 snapshot-20060412 100 | - Add sub directory hierarchy support 101 | - Add PROFILEDATADIR disk space check 102 | - Fix various small bugs in snapshot-20060412 103 | 104 | 2006-04-12 snapshot-20060412 105 | - Fix bug in profile rebuilder for new style profiles. 106 | 107 | 2006-04-07 snapshot-20060407 108 | - Cleanups reported bugs from snapshot-20060325 109 | - Remove all direct nfsen/nfdump system calls from web frontend. use socket server instead. 110 | - Fix installation problem on Solaris 9/10 Sigh .. 111 | - Add 'type' to source definition, to make nfsen. sflow aware 112 | - Add nfsend socket server. Web server does not need to call nfsen command line directly 113 | 114 | 2006-03-25 snapshot-20060325 115 | Cleanups for snapshot 116 | 117 | 2006-02-15 118 | - More flexible source handling: Add add/delete netflow source option 119 | on a running system. cmd line nfsen understands now 'nfsen reconfig' 120 | - re-arrange RRD DBs: RRDs are now source based and no longer type based. 121 | installer process needs to convert from old to new style layout. 122 | this conversion is a nightmare, but the price for the old design ... 123 | - fork off development tree 124 | 125 | 2006-02-11 v1.2.4 126 | - Add IPv4 in processiing form for flow listings. 127 | 128 | 2006-01-12 v1.2.3 129 | - Update processing form in details page to enable more nfdump 1.5 130 | features and IPv6 output formats. Quick fix till next version becomes ready. 131 | 132 | 2006-01-03 v1.2.2 133 | - Update NfSen to run with nfdump 1.5 tools. 134 | 135 | 2005-09-11 v1.2.1 136 | - Bug fixed in install.pl: permission problem fixed. 137 | Sigh .. always permissions ... 138 | - Bug fixed in install.pl: Initial installation may lock live profile, due to 139 | possible time overlap of installation and first run or Periodic. 140 | - Update details tab to make use of nfdump 1.4 'order by' options. 141 | nfdump 1.4 required now. 142 | 2005-08-31 v1.2 143 | - New flexible directory layout. 144 | - Change 'bytes' to 'traffic' and display bits/s instead of bytes/s. 145 | - Add frontend plugins. 146 | - Switch between sum and rate in the stat data display. 147 | - Add various buttons to the processing tab for more easy working. 148 | - A lot of small changes to make NfSen run on many *nix without changes 149 | - Can work with rrdtool v.1.2.x 150 | - Add peak search to position cursor in details graph 151 | - Fix a few minor bugs. 152 | - Have NfSen to deal better with disk full events. 153 | - Add -X option to nfsen cmd line command to expire the profile right now. 154 | 155 | 2005-04-21 v 1.1 156 | - Fixed some minor code html bugs 157 | - Add php function file_get_contents to be compatible with 158 | php version < 4.3 159 | - Add line/stacked graph radio buttons in detailed view 160 | - Fixed several minor bugs. 161 | 162 | 2005-03-31 v 1.1rc3 163 | - Install privileges fixed. 164 | - Updated docu. 165 | 166 | 2005-03-29 v 1.1rc2 167 | - bug fix in install routine. 168 | - correct spelling errors 169 | 170 | 2005-03-23 v 1.1rc1 171 | First public version. 172 | 173 | 2005-02-21 v 1.0b 174 | Internal testing version 175 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Notes: 2 | ====== 3 | 4 | This is version 1.3.11 of NfSen. It is a compatibility version for 5 | new nfdump-1.7.x. NfSen 1.3.11 works with nfdump 1.6.20 and later 6 | as well with nfdump-1.7.x. 7 | Do not use any earlier nfdump version < 1.6.20 as well as nfdump 1.5.x 8 | 9 | Notes for nfdump-1.7.x users: 10 | nfdump-1.7.x uses a new binary format. Creating profiles from historical 11 | data, collected with nfdump-1.6.x does not work. Profiling works for 12 | all data version 2 from nfdump-1.7. 13 | Update: 1. Update nfdump - 2. Update nfsen. The order is important. 14 | 15 | nfsen-1.3.11 is php 8.1 ready. 16 | 17 | NOTE: *nfsen is no longer under development* 18 | 19 | Legacy notes: 20 | Make sure you have nfdump configured with option --enable-nfprofile 21 | 22 | Upgrade is supported only for NfSen versions v1.2.x. 23 | older NfSen versions need to be upgraded in a first step to NfSen 1.2.4. 24 | 25 | What is NfSen: 26 | ============= 27 | NfSen is a graphical WEB based front end for the nfdump netflow tools. 28 | See 29 | 30 | With NfSen, you can: 31 | - Display your netflow data from many sources: Flows, Packets and Bytes. 32 | - Easily navigate through the netflow data. 33 | - Process the netflow data within the specified time span. 34 | - Create history as well as continuous profiles. 35 | - Set alerts based on various conditions. 36 | - Write your own plug-ins to process and display netflow data on a regular 37 | interval. 38 | 39 | NfSen allows you to keep all the convenient advantages of the command 40 | line using nfdump directly and gives you also a graphical overview over 41 | your netflow data. 42 | 43 | A more detailed documentation is available in the doc directory. 44 | 45 | NfSen is distributed under the BSD license - see BSD-license.txt 46 | 47 | Installation: 48 | ------------- 49 | 50 | 1. Prerequisites: 51 | - PHP and Perl: 52 | NfSen is written in PHP and Perl and should run on any *NIX system. 53 | At least Perl 5.10.1 and PHP > 4.1 with PHP socket extension is required. 54 | NfSen also works with PHP 5 and apache 2. 55 | Perl modules: Mail::Header and Mail::Internet. Install these Perl modules 56 | prior to installing NfSen. 57 | - RRDtools 58 | NfSen requires the RRD tools v1.0.x or > 1.2.11, at least the RRDs Perl 59 | Module. 60 | - nfdump tools 61 | Make sure you have at least version 1.6.1 installed on your system. 62 | Do not use any older nfdump version! 63 | Make sure you have nfdump configured with option --enable-nfprofile 64 | You can download nfdump from sourceforge nfdump.sourceforge.net. 65 | Please note: Each netflow source requires a semaphore in the global 66 | system table. If you have lots of different sources, check the system 67 | documentation about the max number of semaphores, or how to increase the 68 | this number respectively. 69 | 70 | NfSen has a very flexible directory layout. To simplify matters, 71 | the default layout stores everything but the html pages under BASEDIR. 72 | However, you may configure NfSen to fit your local needs. 73 | See the nfsen-dist.conf config file. The netflow data is stored 74 | under PROFILEDATADIR ( BASEDIR/profiles by default ). So make sure you have 75 | enough disk space. 76 | 77 | To update your current NfSen installation goto point 3. 78 | 79 | 2. First installation of NfSen: 80 | If you have installed all prerequisites, change to the etc directory and 81 | copy the NfSen config file nfsen-dist.conf to nfsen.conf. Edit nfsen.conf 82 | according your needs and setup. Make sure you have set the right values 83 | for the netflow sources. For any netflow source, make an entry in the 84 | %sources hash. The comments in nfsen.conf should guide you. When you 85 | are done, run the install.pl script in the distribution directory: 86 | 87 | ./install.pl etc/nfsen.conf 88 | 89 | Running install.pl will: 90 | - Create the NfSen environment with all required directories. 91 | - Copy the php/html files into HTMLDIR. 92 | - Create the live profile. 93 | - Prepares the RRD DBs for the live profile. 94 | 95 | After the installation, you will find the nfsen.conf file in CONFDIR. 96 | 97 | 3. Update your current NfSen installation: 98 | Upgrade is supported only for NfSen v1.2.x. Any NfSen 1.1.x installations should 99 | be upgraded in a first step to NfSen 1.2.4. 100 | If you upgrade from any previous NfSen installation, make sure you have 101 | upgraded nfdump to version 1.5.5 according to this README file. 102 | 103 | To upgrade your 1.2.x NfSen installation: 104 | 105 | 1. Stop old nfsen, due to nfprofile incompatibilities. 106 | ./nfsen.rc stop 107 | 2. Upgrade nfdump to stable 1.6.1. Do not forget to configure nfdump 108 | with --enable-nfprofile option. 109 | This update is required! 110 | 111 | 3. Upgrade NfSen: 112 | 113 | ./install.pl 114 | 115 | This will update your current NfSen installation. and 116 | you're done. 117 | 118 | 4. If you have plugins installed, check the README.plugins file for some 119 | small changes required to be changed for each plugin. 120 | If you have PortTracker installed, you need to update to the PortTracker 121 | version included in the contrib directory, coming with NfSen. You need 122 | not to rebuild your current db files, just rebuild nftrack and replace 123 | the plugin files. See the INSTALL file. 124 | 125 | 5. Start NfSen: 126 | 127 | BINDIR/nfsen start 128 | 129 | When updating from a newer snapshot ( > snapshot-20070110 ) or from early 1.3b 130 | releases the normal update procedure will do: 131 | 132 | ./install.pl 133 | BINDIR/nfsen reload 134 | 135 | 4. NfSen is now ready to use. 136 | 137 | You may want to link the start/stop file BASEDIR/bin/nfsen.rc into your 138 | appropriate rc.d directory. Start NfSen: 139 | 140 | BINDIR/nfsen start 141 | 142 | Point your web browser to nfsen.php. 143 | ( Typically http://yourserver/nfsen/nfsen.php ) 144 | 145 | 146 | Notes for Solaris users: 147 | ------------------------ 148 | To make syslog work for NfSen set the appropriate parameter in nfsen.conf. 149 | See nfsen-dist.conf for the logging socket parameter. 150 | 151 | The Sys::Syslog perl Module on Solaris 10 is badly broken. You may want 152 | to upgrade Sys::Syslog to the latest available on CPAN. 153 | 154 | 155 | Notes on sub directory hierarchy support: 156 | ----------------------------------------- 157 | As of snapshot 20060728 nfsen supports the sub directory hierarchy of nfdump. 158 | When installing or upgrading NfSen, the layout is set to '0' ( see nfcapd(1) ), 159 | which means no layout. If you want to make use of any sub hierarchy layout, 160 | add '$SUBDIRLAYOUT = ;' to the nfsen.conf file. See nfsen-dist.conf for 161 | more information. After changing the layout, run RebuildHierarchy.pl. 162 | in $BINDIR to reorganize the data files to the new layout. Changing the layout 163 | is possible at any other time later on. However, you must run 164 | RebuildHierarchy.pl after changing $SUBDIRLAYOUT the config file. 165 | Note: This process will stop NfSen, as the upgrade requires a silent system. 166 | 167 | More information about NfSen as well as working with NfSen is available in 168 | the documentation provided in the doc directory. 169 | -------------------------------------------------------------------------------- /README.plugins: -------------------------------------------------------------------------------- 1 | NfSen Plugins 2 | ============= 3 | 4 | A detailed plugin guide is available in the doc directory. However, 5 | to upgrade your current plugins, follow the procedure below: 6 | 7 | Plugins of Nfsen version < snapshot-20070110 will be recognized as so called 8 | legacy plugins, and will work with only little modifications: 9 | 10 | Frontend Plugins: 11 | Replace all notification Messages in your plugin: 12 | 13 | Instead of directly setting the message with 14 | 15 | $_SESSION['error'] = '.. '; 16 | 17 | use the new provided function 18 | 19 | SetMessage('error', "..."); 20 | 21 | The same is true for 'warning', 'alert' and 'info' 22 | 23 | Backend Plugins: 24 | Your plugins will continue to work unless you make access to profile 25 | information such as NfSen::ReadProfile. 26 | All Profile functions have been moved from NfSen module to NfProfile. So you 27 | need to replace calls such es NfSen::ReadProfile(..) to NfProfile::ReadProfile 28 | 29 | When accessing profile data, a legacy plugin runs correctly only, when the profile 30 | is not in a subgroup. To access the profilegroup, add another parameter to your run 31 | function: 32 | 33 | sub run { 34 | my $name = shift; 35 | my $timeslot = shift; 36 | 37 | # add here group parameter 38 | my $profilegroup = shift; 39 | 40 | You may also add the $profilegroup parameter to the ReadProfile(..) function in order 41 | to access plugin information in a subgroup 42 | 43 | ** IMPORTANT ** 44 | Replace the default sub END in the plugin by sub Cleanup. This is required as otherwise 45 | Perl will call the standard END block, every time a comm service server exits. This 46 | could cause unexpected results. 47 | 48 | If you are interested in more details, have a look at the demoplugin.pm in the plugin 49 | directory and look into the Plugin Writers guide in the doc dir. 50 | -------------------------------------------------------------------------------- /bin/RebuildHierarchy.pl: -------------------------------------------------------------------------------- 1 | #!%%PERL%% -w 2 | # 3 | # 4 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # * Neither the name of SWITCH nor the names of its contributors may be 16 | # used to endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | # POSSIBILITY OF SUCH DAMAGE. 30 | # 31 | # $Author: peter $ 32 | # 33 | # $Id: RebuildHierarchy.pl 27 2011-12-29 12:53:29Z peter $ 34 | # 35 | # $LastChangedRevision: 27 $ 36 | 37 | require 5.6.0; 38 | 39 | 40 | use strict; 41 | use File::Find; 42 | use POSIX qw(strftime); 43 | use Time::Local; 44 | 45 | ###################################### 46 | # 47 | # Configuration: 48 | # The only parameter to set: 49 | 50 | use lib "%%LIBEXECDIR%%"; 51 | 52 | # 53 | ###################################### 54 | 55 | use NfSen; 56 | use NfProfile; 57 | use NfSenRC; 58 | 59 | my $profiledir; 60 | my $source; 61 | my ($uid, $gid); 62 | 63 | sub ValidISO { 64 | my $time = shift; 65 | 66 | # strinp '-' chars 67 | $time =~ s/\-//g; 68 | 69 | # any non - number char is invalid 70 | return 0 if $time =~ /[^\d]+/; 71 | 72 | # outside required timeframe 73 | return 0 if $time < 197001010000 || $time > 203801191414; 74 | 75 | return 1; 76 | 77 | } # End of ValidISO 78 | 79 | # Convert a an ISO time value into UNIX format 80 | sub ISO2UNIX { 81 | my $isotime = shift; 82 | 83 | if ( !ValidISO($isotime) ) { 84 | return 0; 85 | } 86 | 87 | $isotime =~ s/\-//g; # allow '-' to structure time string 88 | 89 | # 2004 02 13 12 45 / 90 | my $sec = 0; 91 | my ( $year, $mon, $mday, $hour, $min ) = $isotime =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/; 92 | $mon--; 93 | 94 | # round down to nearest 5 min slot 95 | my $diff = $min % 5; 96 | if ( $diff ) { 97 | $min -= $diff; 98 | } 99 | 100 | my $unixtime = Time::Local::timelocal($sec,$min,$hour,$mday,$mon,$year); 101 | 102 | return $unixtime; 103 | 104 | } # End of ISO2UNIX 105 | 106 | sub CreateSubdirHierarchy { 107 | my $t = shift; # UNIX time format 108 | my $channel = shift; 109 | 110 | my $layout = $NfConf::SUBDIRLAYOUT; 111 | if ( !defined $layout || $layout == 0 ) { 112 | return ''; 113 | } 114 | 115 | my @subdir_def = ( 116 | "", 117 | "%Y/%m/%d", 118 | "%Y/%m/%d/%H", 119 | "%Y/%W/%u", 120 | "%Y/%W/%u/%H", 121 | "%Y/%j", 122 | "%Y/%j/%H", 123 | "%F", 124 | "%F/%H" 125 | ); 126 | 127 | if ( $layout > $#subdir_def ) { 128 | return undef; 129 | } 130 | 131 | my $subdirs = strftime $subdir_def[$layout], localtime($t); 132 | 133 | # make sure all required sub directories exist 134 | if ( defined $subdirs && length $subdirs > 0 ) { 135 | if ( ! -d "$channel/$subdirs" ) { 136 | my $path = "$channel"; 137 | foreach my $dir ( split /\//, $subdirs ) { 138 | $path = "$path/$dir"; 139 | if ( !-d $path ) { 140 | mkdir $path || die "mkdir $path failed: $!. Could not create new sub dir layout"; 141 | chmod 0775, $path || die "Can't chmod '$path': $!\n"; 142 | chown $uid, $gid, $path || die "Can't chown '$path': $!\n"; 143 | } 144 | } 145 | } 146 | } else { 147 | die "strftime failed! Could not create new sub dir layout"; 148 | } 149 | 150 | return $subdirs; 151 | 152 | 153 | } # End of SubdirHierarchy 154 | 155 | sub wanted { 156 | my $file = $File::Find::name; 157 | my $dir = $File::Find::dir; 158 | 159 | # return unless -f $_; 160 | # return unless /^nfcapd\.\d+$/; 161 | 162 | if ( -f $_ ) { 163 | #print "FILE: $File::Find::name, NAME: $_\n"; 164 | my ($t_iso) = $_ =~ /nfcapd\.(\d+)/; 165 | return unless defined $t_iso; 166 | my $t_unix = ISO2UNIX($t_iso); 167 | my $subdirs = CreateSubdirHierarchy($t_unix, $profiledir); 168 | if ( $File::Find::name ne "$profiledir/$subdirs/$_" ) { 169 | print "$_ => $subdirs/$_ \r"; 170 | rename $File::Find::name, "$profiledir/$subdirs/$_" || 171 | die "rename failed: $!. Could not create new sub dir layout"; 172 | } else { 173 | print "$File::Find::name old/new file name identical\r"; 174 | } 175 | } 176 | if ( -d $_ ) { 177 | #print "DIR : $File::Find::dir, NAME: $_\n"; 178 | rmdir "$File::Find::dir/$_"; 179 | } 180 | 181 | } # 182 | 183 | ######################## 184 | # 185 | # Main starts here 186 | # 187 | ######################## 188 | 189 | $| = 1; # unbuffered stdout 190 | 191 | if ( !NfConf::LoadConfig() ) { 192 | die "$Log::ERROR\n"; 193 | } 194 | 195 | # need to run as root 196 | if ( !NfSen::root_process() ) { 197 | die "nfsen setup wants to run as root\n"; 198 | } 199 | 200 | 201 | if ( !defined $NfConf::SUBDIRLAYOUT ) { 202 | die "No sub hierarchy layout defined in config file\n"; 203 | } 204 | my $hints = NfSen::LoadHints(); 205 | 206 | my $t = time(); 207 | my $subdirs = NfSen::SubdirHierarchy($t - ($t % 300)); 208 | if ( !defined $subdirs ) { 209 | die "Unknown sub hierarchy layout $NfConf::SUBDIRLAYOUT\n"; 210 | } 211 | 212 | # get confirmation 213 | print "Current old layout is '$$$hints{'subdirlayout'}'\n"; 214 | print "Configured new layout is '$NfConf::SUBDIRLAYOUT'\n"; 215 | print "Apply new layout to all NfSen profiles:\n"; 216 | my @AllProfileGroups = NfProfile::ProfileGroups(); 217 | foreach my $profilegroup ( @AllProfileGroups ) { 218 | my @AllProfiles = NfProfile::ProfileList($profilegroup); 219 | foreach my $profile ( @AllProfiles ) { 220 | print " => $profilegroup/$profile\n"; 221 | } 222 | } 223 | print "This will reorganize all your data files. You may again rebuild your hierarchy any time later\n"; 224 | my $ans; 225 | do { 226 | print "Do you want to continue yes/[no] "; 227 | $ans = ; 228 | chomp $ans; 229 | # Default answer is no 230 | if ( $ans eq '' ) { 231 | $ans = 'no'; 232 | } 233 | } while ( $ans !~ /^yes$/i && $ans !~ /^no$/i ); 234 | 235 | # Exit on answer 'no' 236 | if ( $ans =~ /^no$/i ) { 237 | print "OK - exit $0 - nothing changed.\n"; 238 | exit(0); 239 | } 240 | 241 | $uid = getpwnam($NfConf::USER); 242 | $gid = getgrnam($NfConf::WWWGROUP); 243 | 244 | if ( !defined $uid || !defined $gid ) { 245 | die "Can't get uid/gid from system for $NfConf::USER/$NfConf::WWWGROUP"; 246 | } 247 | 248 | # go ahead 249 | print "Make sure NfSen is not running: shut down NfSen:\n"; 250 | NfSenRC::NfSen_stop(); 251 | 252 | foreach my $profilegroup ( @AllProfileGroups ) { 253 | my @AllProfiles = NfProfile::ProfileList($profilegroup); 254 | foreach my $profile ( @AllProfiles ) { 255 | print "Process profile '$profilegroup/$profile'\n"; 256 | my %profileinfo = NfProfile::ReadProfile($profile, $profilegroup); 257 | my $profilepath = NfProfile::ProfilePath($profile, $profilegroup); 258 | if ( $profileinfo{'status'} eq 'empty' ) { 259 | # it's an error reading this profile 260 | print STDERR "Error reading profile '$profilegroup/$profile'"; 261 | if ( defined $Log::ERROR ) { 262 | print STDERR ": $Log::ERROR"; 263 | } 264 | print STDERR "\n"; 265 | die "Abort $0 - Rebuild incomplete. Fix errors and rerun $0\n"; 266 | } 267 | my @ProfileSources = keys %{$profileinfo{'channel'}}; 268 | foreach $source ( @ProfileSources ) { 269 | print "$source:\n"; 270 | $profiledir = "$NfConf::PROFILEDATADIR/$profilepath/$source"; 271 | find({ wanted => \&wanted, bydepth => 1 }, $profiledir); 272 | print "\n"; 273 | } 274 | print "\n"; 275 | } 276 | } 277 | 278 | print "All profiles converted.\n"; 279 | 280 | $$$hints{'subdirlayout'} = $NfConf::SUBDIRLAYOUT; 281 | NfSen::StoreHints(); 282 | 283 | do { 284 | print "Do you want to start NfSen right now? yes/[no] "; 285 | $ans = ; 286 | chomp $ans; 287 | # Default answer is no 288 | if ( $ans eq '' ) { 289 | $ans = 'no'; 290 | } 291 | } while ( $ans !~ /^yes$/i && $ans !~ /^no$/i ); 292 | 293 | # Exit on answer 'no' 294 | if ( $ans =~ /^no$/i ) { 295 | print "OK - You need to run '$NfConf::BINDIR/nfsen.rc start' manually\n"; 296 | exit(0); 297 | } 298 | 299 | NfSenRC::NfSen_start(); 300 | -------------------------------------------------------------------------------- /bin/testPlugin: -------------------------------------------------------------------------------- 1 | #!%%PERL%% -w 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: testPlugin 27 2011-12-29 12:53:29Z peter $ 33 | # 34 | # $LastChangedRevision: 27 $ 35 | 36 | use strict; 37 | use Getopt::Std; 38 | use Sys::Syslog; 39 | 40 | ###################################### 41 | # 42 | # Configuration: 43 | # The only parameter to set: 44 | 45 | use lib "%%LIBEXECDIR%%"; 46 | 47 | # 48 | ###################################### 49 | 50 | use NfConf; 51 | use NfSen; 52 | use NfProfile; 53 | use Log; 54 | 55 | my $VERSION = '$Id: testPlugin 27 2011-12-29 12:53:29Z peter $'; 56 | 57 | our ( 58 | $opt_h, # Help Info 59 | $opt_p, # plugin to test 60 | $opt_P, # Profile to use for test 61 | $opt_V, # Version of testPlugin 62 | $opt_t, # Timestamp to use for test 63 | ); 64 | 65 | getopts('p:P:Vht:'); 66 | 67 | my %plugin_table ; 68 | 69 | sub usage { 70 | 71 | print "$0 [options]\n", 72 | "\t-h This help\n", 73 | "\n", 74 | "\t-p Plugin to test\n", 75 | "\t-P Profile to use for testing\n", 76 | "\t-t Timestamp to use for test\n", 77 | "\te.g: -p myCoolPlugin -P myCoolProfile -t 200503310000\n", 78 | "\n", 79 | 80 | } # End of usage 81 | 82 | sub load_module { 83 | my $module = shift; 84 | 85 | eval { 86 | require "$module.pm"; 87 | }; 88 | 89 | if ( my $err = $@ ) { 90 | print "Err Loading plugin '$module' failed: $err\n" ; 91 | return 0; 92 | } 93 | print "Load plugin '$module' \t: Success\n" ; 94 | 95 | print "Initialize plugin \t: " ; 96 | my $ret = $module->Init(); 97 | if ( $ret ) { 98 | print "Success\n" ; 99 | return 1; 100 | } else { 101 | print "Suspended: Plugin does not want to run\n" ; 102 | return 0; 103 | } 104 | 105 | } # End of load_module 106 | 107 | ################### 108 | # Main starts here 109 | ################### 110 | 111 | if ( defined $opt_V ) { 112 | print "$0: $VERSION\n"; 113 | exit; 114 | } 115 | 116 | if ( defined $opt_h || !defined $opt_p || !defined $opt_P || !defined $opt_t ) { 117 | usage(); 118 | exit; 119 | } 120 | 121 | my %opts; 122 | $opts{'profile'} = $opt_P; 123 | 124 | my $plugin = $opt_p; 125 | 126 | my ($profile, $profilegroup); 127 | my $ret = NfProfile::ProfileDecode(\%opts, \$profile, \$profilegroup); 128 | 129 | if ( $ret ne 'ok' ) { 130 | die "Can't decode profile: $ret"; 131 | } 132 | 133 | if ( !NfConf::LoadConfig() ) { 134 | die "$Log::ERROR\n"; 135 | } 136 | 137 | # That's were we find all the plugins 138 | unshift @INC, "$NfConf::BACKEND_PLUGINDIR"; 139 | 140 | openlog("testPlugin", 'cons,pid', $NfConf::syslog_facility); 141 | 142 | if ( !NfProfile::ProfileExists($profile, '.') ) { 143 | print "Err No such profile '$profile'\n"; 144 | exit; 145 | } 146 | 147 | my %profileinfo = NfProfile::ReadProfile($profile, '.') ; 148 | 149 | if ( $profileinfo{'status'} eq 'empty' ) { 150 | print "Err Can't read profile '$profile': $Log::ERROR\n"; 151 | exit; 152 | } 153 | 154 | my $timeslot = $opt_t; 155 | if ( !NfSen::ValidISO($timeslot) ) { 156 | print "Err Invalid timeslot '$timeslot'\n"; 157 | exit; 158 | } 159 | 160 | my $unixtime = NfSen::ISO2UNIX($timeslot); 161 | 162 | if ( $unixtime < $profileinfo{'tstart'} || $unixtime > $profileinfo{'tend'} ) { 163 | my $iso_start = NfSen::UNIX2ISO($profileinfo{'tstart'}); 164 | my $iso_end = NfSen::UNIX2ISO($profileinfo{'tend'}); 165 | print "Err Timeslot out of range. Must be between '$iso_start' and '$iso_end'\n"; 166 | exit; 167 | } 168 | 169 | if ( !load_module($plugin) ) { 170 | exit; 171 | } 172 | 173 | print "Run plugin '$plugin' with profile '$profile' at '$timeslot'\n"; 174 | my $sub = "${plugin}::run"; 175 | no strict 'refs'; 176 | &$sub( { 177 | 'profile' => $profile, 178 | 'profilegroup' => $profilegroup, 179 | 'timeslot' => $timeslot 180 | }); 181 | use strict 'refs'; 182 | $plugin->Cleanup(); 183 | print "Plugin run successfully, at least as far as I can tell ...\n" ; 184 | 185 | closelog(); 186 | -------------------------------------------------------------------------------- /contrib/PortTracker/INSTALL: -------------------------------------------------------------------------------- 1 | 2 | Please note: This is prototype software. Use it at you own risk :) 3 | To install PortTracker, follow the steps below: 4 | 5 | *** The sources for nftrack are now included in nfdump and are no longer 6 | included in this contrib directory. *** 7 | 8 | 1. Get nfdump. You need at least version 1.6.5 or 1.5.8-NSEL. 9 | PortTracker does *NOT* work with nfdump-1.5.x! 10 | 11 | 2. When building nfdump add --enable-nftrack as configure parameter 12 | A command may look like: ./configure --enable-nfprofile --enable-nftrack 13 | make; make install will generate the binaries incl. nftrack 14 | 15 | 3. Create the port DBs in a directory with at least 10GB disk space: 16 | This directory needs to be writable by the user $USER configured in nfsen.conf 17 | 18 | 4. Edit Porttracker.pm: 19 | Set $PORTSDBDIR to the port DBs directory. 20 | 21 | 5. Copy PortTracker.pm to the NfSen backend plugin dir. 22 | Copy PortTracker.php to the NfSen frontend plugin dir. 23 | 24 | 6. Edit nfsen.conf: Add the plugin for profile 'live': 25 | Example: 26 | @plugins = ( 27 | [ 'live', 'PortTracker'], 28 | ); 29 | 30 | 7. Initialize the ports-db: 31 | As $USER run 'nftrack -I -d ' 32 | This takes some minutes or so ... have a coffee 33 | 34 | 8. Restart NfSen: 35 | Run './nfsen reload' 36 | Have a look at the syslog file to see if PortTracker loaded successfully: 37 | 38 | 9. After the next 5min update cycle: Point your browser to the NfSen page 39 | and select the Plugin Tab. 40 | -------------------------------------------------------------------------------- /contrib/PortTracker/PortTracker.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: PortTracker.pm 59 2013-08-09 14:01:13Z peter $ 33 | # 34 | # $LastChangedRevision: 59 $ 35 | 36 | # Demo plugin for NfSen 37 | # 38 | # This plugin demonstrates the use of plugins 39 | 40 | package PortTracker; 41 | 42 | use strict; 43 | use NfSen; 44 | use NfConf; 45 | 46 | # 47 | # The plugin may send any messages to syslog 48 | # Do not initialize syslog, as this is done by 49 | # the main process nfsen-run 50 | use Sys::Syslog; 51 | 52 | our $VERSION = 130; 53 | 54 | our %cmd_lookup = ( 55 | 'get-portgraph' => \&GetPortGraph, 56 | 'get-topN' => \&GetTopN, 57 | ); 58 | 59 | my ( $nftrack, $PROFILEDATADIR ); 60 | 61 | my $PORTSDBDIR = "/data/ports-db"; 62 | 63 | my $EODATA = ".\n"; 64 | 65 | # colours used in graphs 66 | # the same colours are used again 67 | my @colour = ( 68 | '#ff2b00', '#ffaa00', '#aaff00', '#00ffaa', '#00d5ff', '#0055ff', '#ff00ff', '#ff0080', 69 | '#ff5500', '#ffd500', '#2aff00', '#00ffd4', '#00aaff', '#002aff', '#ff00d4', '#ff0055', 70 | '#ff8000', '#ffff00', '#00ff80', '#00ffff', '#007fff', '#8000ff', '#ff00aa', '#ff002b' 71 | ); 72 | my $NumColour = scalar @colour; 73 | 74 | sub GetTopN { 75 | my $socket = shift; 76 | my $opts = shift; 77 | 78 | my $interval; 79 | if ( !exists $$opts{'interval'} ) { 80 | $interval = 1; 81 | } else { 82 | $interval = $$opts{'interval'}; 83 | } 84 | print $socket ".Get topN ports\n"; 85 | 86 | my $statfile = $interval == 24 ? 'portstat24.txt' : 'portstat.txt'; 87 | print $socket ".topN ports $PORTSDBDIR/$statfile\n"; 88 | if ( !open STAT, "$PORTSDBDIR/$statfile" ) { 89 | print $socket $EODATA; 90 | print $socket "ERR Open statfile '$PORTSDBDIR/$statfile': $!\n"; 91 | return; 92 | } 93 | 94 | print $socket ".topN read ports\n"; 95 | while ( ) { 96 | chomp; 97 | print $socket "_topN=$_\n"; 98 | } 99 | print $socket $EODATA; 100 | print $socket "OK Command completed\n", 101 | 102 | } # End of GetPortGraph 103 | 104 | sub GetPortGraph { 105 | my $socket = shift; 106 | my $opts = shift; 107 | 108 | # get all arguments: 109 | # Example: 110 | # proto typw logscale light tstart tend topN track_list 111 | # tcp flows 0 0 1116495000 1116581400 '22 445 135 1433' '80 143' 112 | if ( !exists $$opts{'arg'} ) { 113 | print $socket $EODATA; 114 | print $socket "ERR Missing Arguments.\n"; 115 | } 116 | my $ARGS = $$opts{'arg'}; 117 | my $proto = shift @$ARGS; # 'tcp' or 'udp' 118 | my $type = shift @$ARGS; # 'flows', 'packets' or 'bytes' 119 | my $logscale = shift @$ARGS; # 0 or 1 120 | my $stacked = shift @$ARGS; # 0 or 1 121 | my $light = shift @$ARGS; # 0 or 1 122 | my $tstart = shift @$ARGS; # start time - UNIX format 123 | my $tend = shift @$ARGS; # end time - UNIX format 124 | my $topN = shift @$ARGS; # TopN port list: string: ' ' separated port list 125 | my $track_list = shift @$ARGS; # Static track port list: string: ' ' separated port list 126 | my $skip_list = shift @$ARGS; # Static skip port list: string: ' ' separated port list 127 | 128 | if ( !defined $proto || !defined $type || !defined $logscale || !defined $stacked || 129 | !defined $light || !defined $tstart || !defined $tend || !defined $topN || 130 | !defined $track_list || !defined $skip_list ) { 131 | print $socket $EODATA; 132 | print $socket "ERR Argument Error.\n"; 133 | return; 134 | } 135 | my @skipPorts = split '-', $skip_list; 136 | 137 | my @topN = split '-', $topN; 138 | my @track_list = split '-', $track_list; 139 | 140 | # remove the common ports in both lists from the dynamic topN list 141 | my %_tmp; 142 | @_tmp{@track_list} = @track_list; 143 | delete @_tmp{@topN}; 144 | @track_list = sort keys %_tmp; 145 | 146 | # %_tmp = (); 147 | # @_tmp{@topN} = @topN; 148 | # delete @_tmp{@skipPorts}; 149 | # @topN = keys %_tmp; 150 | 151 | %_tmp = (); 152 | my @_tmp; 153 | @_tmp{@skipPorts} = @skipPorts; 154 | foreach my $port ( @topN ) { 155 | push @_tmp, $port unless exists $_tmp{$port}; 156 | } 157 | @topN = @_tmp; 158 | 159 | my $datestr = scalar localtime($tstart) . " - " . scalar localtime($tend); 160 | my $title = uc($proto) . " " . ucfirst($type); 161 | 162 | my @DEFS = (); 163 | 164 | # Compile rrd args 165 | my @rrdargs = (); 166 | push @rrdargs, "-"; # output graphics to stdout 167 | 168 | foreach my $port ( @topN, @track_list ) { 169 | # assemble filename 170 | my $fileident = $port >> 10; 171 | my $rrdfile = "$PORTSDBDIR/${proto}-${type}-$fileident.rrd"; 172 | # which ident in this rrd file 173 | my $ident = $port & 1023; # 0x0000001111111111 mask 174 | push @rrdargs, "DEF:Port${port}=$rrdfile:p${ident}:AVERAGE"; 175 | } 176 | 177 | push @rrdargs, "--start", "$tstart"; 178 | push @rrdargs, "--end", "$tend"; 179 | push @rrdargs, "--title", "$datestr - $title" unless $light; 180 | push @rrdargs, "--vertical-label", "$title" unless $light; 181 | 182 | # lin or log graph? 183 | push @rrdargs, "--logarithmic" if $logscale; 184 | 185 | if ( $light ) { 186 | push @rrdargs, "-w"; 187 | push @rrdargs, "288"; 188 | push @rrdargs, "-h"; 189 | push @rrdargs, "150"; 190 | push @rrdargs, "--no-legend"; # no legend in small pictures 191 | } else { 192 | push @rrdargs, "-w"; 193 | push @rrdargs, "576"; 194 | push @rrdargs, "-h"; 195 | push @rrdargs, "300"; 196 | } 197 | 198 | 199 | my $i=0; 200 | my $area_set = 0; 201 | my $n = scalar @topN; 202 | push @rrdargs, "COMMENT:Top $n Ports\\n"; 203 | if ( $stacked && scalar @topN ) { 204 | my $port = shift @topN; 205 | push @rrdargs, "AREA:Port${port}$colour[$i % $NumColour]:Port ${port}"; 206 | $i++; 207 | $area_set = 1; 208 | foreach my $port ( @topN ) { 209 | push @rrdargs, "STACK:Port${port}$colour[$i % $NumColour]:Port ${port}"; 210 | $i++; 211 | } 212 | 213 | } else { 214 | foreach my $port ( @topN ) { 215 | push @rrdargs, "LINE1:Port${port}$colour[$i % $NumColour]:Port ${port}"; 216 | $i++; 217 | } 218 | } 219 | 220 | if ( scalar @track_list) { 221 | push @rrdargs, "COMMENT:\\n"; 222 | push @rrdargs, "COMMENT:\\n"; 223 | push @rrdargs, "COMMENT:Tracked Ports\\n"; 224 | } 225 | if ( $stacked && scalar @track_list) { 226 | if ( !$area_set ) { 227 | my $port = shift @track_list; 228 | push @rrdargs, "AREA:Port${port}$colour[$i % $NumColour]:Port ${port}"; 229 | $i++; 230 | } 231 | foreach my $port ( @track_list ) { 232 | push @rrdargs, "STACK:Port${port}$colour[$i % $NumColour]:Port ${port}"; 233 | $i++; 234 | } 235 | 236 | } else { 237 | foreach my $port ( @track_list ) { 238 | push @rrdargs, "LINE2:Port${port}$colour[$i % $NumColour]:Port ${port}"; 239 | $i++; 240 | } 241 | } 242 | if ( scalar @skipPorts) { 243 | push @rrdargs, "COMMENT:\\n"; 244 | push @rrdargs, "COMMENT:\\n"; 245 | my $portlist = join ',', @skipPorts; 246 | push @rrdargs, "COMMENT:Skipped Ports $portlist\\n"; 247 | } 248 | my ($averages,$xsize,$ysize) = RRDs::graph( @rrdargs ); 249 | 250 | if (my $ERROR = RRDs::error) { 251 | print "ERROR: $ERROR\n"; 252 | } 253 | 254 | } # End of GenPortGraph 255 | 256 | 257 | sub nftrack_execute { 258 | my $command = shift; 259 | 260 | syslog('debug', $command); 261 | 262 | my $ret = system($command); 263 | if ( $ret == - 1 ) { 264 | syslog('err', "Failed to execute nftrack: $!\n"); 265 | } elsif ($ret & 127) { 266 | syslog('err', "nftrack died with signal %d, %s coredump\n", ($ret & 127), ($ret & 128) ? 'with' : 'without'); 267 | } else { 268 | syslog('debug', "nftrack exited with value %d\n", $ret >> 8); 269 | } 270 | 271 | } # End of nftrack_execute 272 | 273 | # 274 | # Periodic function 275 | # input: hash reference including the items: 276 | # 'profile' profile name 277 | # 'profilegroup' profile group 278 | # 'timeslot' time of slot to process: Format yyyymmddHHMM e.g. 200503031200 279 | sub run { 280 | my $argref = shift; 281 | 282 | my $profile = $$argref{'profile'}; 283 | my $profilegroup = $$argref{'profilegroup'}; 284 | my $timeslot = $$argref{'timeslot'}; 285 | 286 | syslog('debug', "PortTracker run: Profile: $profile, Time: $timeslot"); 287 | 288 | my %profileinfo = NfProfile::ReadProfile($profile); 289 | my $netflow_sources = "$PROFILEDATADIR/$profile/$profileinfo{'sourcelist'}"; 290 | 291 | # 292 | # process all sources of this profile at once 293 | my $command = "$nftrack -L $NfConf::syslog_facility -M $netflow_sources -r nfcapd.$timeslot -d $PORTSDBDIR -A -t $timeslot -s -p -w $PORTSDBDIR/portstat.txt"; 294 | nftrack_execute($command); 295 | 296 | $command = "$nftrack -d $PORTSDBDIR -S -p -w $PORTSDBDIR/portstat24.txt"; 297 | nftrack_execute($command); 298 | 299 | # 300 | # Process the output and notify the duty team 301 | 302 | syslog('debug', "PortTracker run: Done."); 303 | 304 | } # End of run 305 | 306 | sub Init { 307 | syslog("info", "PortTracker: Init"); 308 | 309 | # Init some vars 310 | $nftrack = "$NfConf::PREFIX/nftrack"; 311 | $PROFILEDATADIR = "$NfConf::PROFILEDATADIR"; 312 | 313 | return 1; 314 | } 315 | 316 | sub Cleanup { 317 | syslog("info", "PortTracker Cleanup"); 318 | # not used here 319 | } 320 | 321 | 1; 322 | -------------------------------------------------------------------------------- /etc/nfsen-dist.conf: -------------------------------------------------------------------------------- 1 | ############################## 2 | # 3 | # NfSen master config file 4 | # 5 | # $Id: nfsen-dist.conf 22 2007-11-20 12:27:38Z phaag $ 6 | # 7 | # Configuration of NfSen: 8 | # Set all the values to fit your NfSen setup and run the 'install.pl' 9 | # script from the nfsen distribution directory. 10 | # 11 | # The syntax must conform to Perl syntax. 12 | # 13 | ############################## 14 | # 15 | # NfSen default layout: 16 | # Any scripts, modules or profiles are installed by default under $BASEDIR. 17 | # However, you may change any of these settings to fit your requested layout. 18 | 19 | # 20 | # Required for default layout 21 | $BASEDIR = "/data/nfsen"; 22 | 23 | # 24 | # Where to install the NfSen binaries 25 | $BINDIR="${BASEDIR}/bin"; 26 | 27 | # 28 | # Where to install the NfSen Perl modules 29 | $LIBEXECDIR="${BASEDIR}/libexec"; 30 | 31 | # 32 | # Where to install the config files 33 | $CONFDIR="${BASEDIR}/etc"; 34 | 35 | # 36 | # NfSen html pages directory: 37 | # All php scripts will be installed here. 38 | # URL: Entry point for nfsen: http:///nfsen/nfsen.php 39 | $HTMLDIR = "/var/www/nfsen/"; 40 | 41 | # 42 | # Where to install the docs 43 | $DOCDIR="${HTMLDIR}/doc"; 44 | 45 | # 46 | # Var space for NfSen 47 | $VARDIR="${BASEDIR}/var"; 48 | 49 | # directory for all pid files 50 | # $PIDDIR="$VARDIR/run"; 51 | # 52 | # Filter directory 53 | # FILTERDIR="${VARDIR}/filters"; 54 | # 55 | 56 | # FORMATDIR for custom printing formats 57 | # FORMATDIR="${VARDIR}/fmt"; 58 | # 59 | 60 | # 61 | # The Profiles stat directory, where all profile information 62 | # RRD DBs and png pictures of the profile are stored 63 | $PROFILESTATDIR="${BASEDIR}/profiles-stat"; 64 | 65 | # 66 | # The Profiles directory, where all netflow data is stored 67 | $PROFILEDATADIR="${BASEDIR}/profiles-data"; 68 | 69 | # 70 | # Where go all the backend plugins 71 | $BACKEND_PLUGINDIR="${BASEDIR}/plugins"; 72 | 73 | # 74 | # Where go all the frontend plugins 75 | $FRONTEND_PLUGINDIR="${HTMLDIR}/plugins"; 76 | 77 | # 78 | # nfdump tools path 79 | $PREFIX = '/usr/local/bin'; 80 | 81 | # 82 | # nfsend communication socket 83 | # $COMMSOCKET = "$PIDDIR/nfsen.comm"; 84 | 85 | # BASEDIR unrelated vars: 86 | # 87 | # Run nfcapd as this user 88 | # This may be a different or the same uid than your web server. 89 | # Note: This user must be in group $WWWGROUP, otherwise nfcapd 90 | # is not able to write data files! 91 | $USER = "netflow"; 92 | 93 | # user and group of the web server process 94 | # All netflow processing will be done with this user 95 | $WWWUSER = "www"; 96 | $WWWGROUP = "www"; 97 | 98 | # Receive buffer size for nfcapd - see man page nfcapd(1) 99 | $BUFFLEN = 200000; 100 | 101 | # list of extensions for each collector. See argument -T 102 | # for nfcapd(1) for more detailes. 103 | # defaults to empty -> compatible to nfdump-1.5.8 104 | # $EXTENSIONS = ''; 105 | # Example: 106 | # $EXTENSIONS = 'all'; 107 | # $EXTENSIONS = '+3,+4'; 108 | # 109 | # Directory sub hierarchy layout: 110 | # Possible layouts: 111 | # 112 | # 0 default no hierarchy levels - flat layout - compatible with pre NfSen versions 113 | # 1 %Y/%m/%d year/month/day 114 | # 2 %Y/%m/%d/%H year/month/day/hour 115 | # 3 %Y/%W/%u year/week_of_year/day_of_week 116 | # 4 %Y/%W/%u/%H year/week_of_year/day_of_week/hour 117 | # 5 %Y/%j year/day-of-year 118 | # 6 %Y/%j/%H year/day-of-year/hour 119 | # 7 %Y-%m-%d year-month-day 120 | # 8 %Y-%m-%d/%H year-month-day/hour 121 | $SUBDIRLAYOUT = 1; 122 | 123 | # Compress flows while collecting 0 or 1 124 | $ZIPcollected = 1; 125 | 126 | # Compress flows in profiles. Set to any value accepted by nfcapd/nfdump 127 | # e.g. "-z=lz4", "-z=zstd:5" 128 | # the value 1 is accepted for compatibility and set to "-z=lz4" 129 | # the value "" means no compression 130 | $ZIPprofiles = "-z=lz4"; 131 | 132 | # Interrupt expire -- not yet enabled as not yet fully tested 133 | #$InterruptExpire = 0; 134 | 135 | # number of nfprofile processes to spawn during the profiling phase 136 | # depends on how busy your system is and how many CPUs you have 137 | # on very busy systems increase it to a higher value 138 | $PROFILERS = 2; 139 | 140 | # if the PROFILEDATADIR is filled up to this percentage, a warning message will be printed. 141 | # set to 0 to disable the test 142 | $DISKLIMIT = 98; 143 | 144 | # Some Perl Versions/Builds have memory leaks for unknown reason. 145 | # Therefore nfsend will increase its memory footprint over time. 146 | # In order to reset nfsend, it automatically reloads after 1 day 147 | # if PERL_HAS_MEMLEAK is set to 1 148 | # $PERL_HAS_MEMLEAK=0; 149 | 150 | # Netflow sources 151 | # Define an ident string, port and colour per netflow source 152 | # 153 | # Required parameters: 154 | # ident identifies this netflow source. e.g. the router name, 155 | # Upstream provider name etc. 156 | # port nfcapd listens on this port for netflow data for this source 157 | # set port to '0' if you do not want a collector to be started 158 | # col colour in nfsen graphs for this source 159 | # 160 | # Optional parameters 161 | # type Collector type needed for this source. Can be 'netflow' or 'sflow'. Default is netflow 162 | # optarg Optional args to the collector at startup 163 | # 164 | # Syntax: 165 | # 'ident' => { 'port' => '', 'col' => '', 'type' => '' } 166 | # Ident strings must be 1 to 19 characters long only, containing characters [a-zA-Z0-9_]. 167 | 168 | %sources = ( 169 | 'upstream1' => { 'port' => '9995', 'col' => '#0000ff', 'type' => 'netflow' }, 170 | 'peer1' => { 'port' => '9996', 'IP' => '172.16.17.18' }, 171 | 'peer2' => { 'port' => '9996', 'IP' => '172.16.17.19' }, 172 | ); 173 | 174 | # 175 | # Low water mark: When expiring files, delete files until 176 | # size = $low_water % of max_size 177 | # typically 90 178 | $low_water = 90; 179 | 180 | # 181 | # syslog facility for periodic jobs 182 | # nfsen uses level 'debug', 'info', 'warning' and 'err' 183 | # Note: nfsen is very chatty for level 'debug' and 'info' 184 | # For normal operation, you may set the logging level in syslog.conf 185 | # to warning or error unless you want to debug NfSen 186 | $syslog_facility = 'local3'; 187 | 188 | # 189 | # SYSLOG mess 190 | # Log socket type: Most *NIX such as LINUX and *BSD are fine with 'unix' 191 | # which is the default. You need to change that to 'stream' or 'inet' for 192 | # some Solaris version 8/9, AIX and others .. 193 | # You may set it to undef to prevent calling Sys::Syslog::setlogsock at all 194 | # ( works for Solaris 10 and newer Sys::Syslog module 195 | # 196 | # If not defined at all, 'unix' is assumed unless for Solaris, which defaults to 'stream' 197 | # $LogSocket = 'unix'; 198 | 199 | # 200 | # Plugins 201 | # Plugins extend NfSen for the purpose of: 202 | # Periodic data processing, alerting-condition and alerting-action 203 | # For data processing a plugin may run for any profile or for a specific profile only. 204 | # Syntax: [ 'profile list', 'module' ] 205 | # profile list: ',' separated list of profiles ( 'profilegroup/profilename' ), 206 | # or '*' for any profile, '!' for no profile 207 | # module: Perl Module name, equal to plugin name 208 | # The profile list '!' make sense for plugins, which only provide alerting functions 209 | # 210 | # The module follows the standard Perl module conventions, with at least one 211 | # function: Init(). See demoplugin.pm for a simple template. 212 | # 213 | # A file with the same name in the FRONTEND_PLUGINDIR and .php extension is automatically 214 | # recognized as frontend plugin. 215 | # 216 | # Plugins are installed under 217 | # $BACKEND_PLUGINDIR and $FRONTEND_PLUGINDIR 218 | 219 | @plugins = ( 220 | # profile # module 221 | # [ '*', 'demoplugin' ], 222 | ); 223 | 224 | %PluginConf = ( 225 | # For plugin demoplugin 226 | demoplugin => { 227 | # scalar 228 | param2 => 42, 229 | # hash 230 | param1 => { 'key' => 'value' }, 231 | }, 232 | # for plugin otherplugin 233 | otherplugin => [ 234 | # array 235 | 'mary had a little lamb' 236 | ], 237 | ); 238 | 239 | # 240 | # Alert module: email alerting: 241 | # Use this from address 242 | $MAIL_FROM = 'your@from.example.net'; 243 | 244 | # Use this SMTP server 245 | $SMTP_SERVER = 'localhost'; 246 | 247 | # Use this email body: 248 | # You may have multiple lines of text. 249 | # Var substitution: 250 | # @alert@ replaced by alert name 251 | # @timeslot@ replaced by timeslot alert triggered 252 | $MAIL_BODY = q{ 253 | Alert '@alert@' triggered at timeslot @timeslot@ 254 | }; 255 | 256 | ###################################################### 257 | # 258 | # For the NfSen simulator include the section below. 259 | # 260 | ###################################################### 261 | # 262 | # Nfsen Simulator 263 | # The simulator requires, that you have already installed 264 | # and configured NfSen. The simulation is based on already 265 | # pre-colleted data, which you may get from another live 266 | # NfSen system. 267 | # 268 | # Steps to setup the NfSen simulator: 269 | # 1. Configure the sources of the live profile with the 270 | # same names of the NfSen system, you take netflow data 271 | # for the simulation. Set the port for each netflow source 272 | # to 0 to prevent a collector to be started. 273 | # Install NfSen with this config in a separate directory 274 | # 2. Copy the pre-collected data into the appropriate 275 | # netflow directory of the live profile. 276 | # 3. Configure the simulator using the parameters below 277 | # Enable Simulation mode => $SIMmode = 1 278 | # Configure the time window of the pre-collected data. 279 | # tstart => Start of time window. yyyymmddhhmm 280 | # tbegin => Optional parameter. Start of simulation 281 | # profile exists already between tstart - tbegin 282 | # tend => End of time window. yyyymmddhhmm 283 | # cycletime => simulation time in seconds of a 5min slot 284 | # Setting cycletime = 0 processes the cycles as fast as 285 | # possible. Please note, if you test plugings, your 286 | # cycletime needs to be at least the time required to 287 | # process all plugins. 288 | # 4. Start nfsen: ../nfsen start 289 | # Simulation starts 290 | # 291 | # The simulator runs from tstart to tend and stops when tend 292 | # is reached. You may stop the simulation at any given time 293 | # using ./nfsen stop. To continue the simulation start NfSen 294 | # again: ./nfsen start. You may reset the simulator at any 295 | # given time using ./nfsen abort-reset. This stops the simulation 296 | # and rolls back to tstart. All profiles/alerts are deleted, 297 | # so you may start from scratch again. 298 | # 299 | # Configure simulator parameters 300 | # 301 | # $SIMmode = 1; 302 | # %sim = ( 303 | # 'tstart' => '200707100000', # Simulation data available from July 10th 2007 00:00 304 | # 'tbegin' => '200707110000', # Simulation begins at July 11th 2007 00:00 305 | # 'tend' => '200707112355', # Simulation ends at July 11th 2007 23:55 306 | # 'cycletime' => '30', # 30s per 5min slot 307 | # ); 308 | 309 | 1; 310 | -------------------------------------------------------------------------------- /html/colour_picker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Default Colour Palette 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 94 | 98 |
14 |
15 | 16 | 92 | 93 |
Current Colour
99 | 100 | 101 | -------------------------------------------------------------------------------- /html/css/alerting.css: -------------------------------------------------------------------------------- 1 | 2 | CAPTION.ALERTTABLE { 3 | background-color:#EEEEEE; 4 | color:black; 5 | border-style:solid; 6 | border-width:2px; 7 | border-color:black; 8 | } 9 | 10 | TABLE.ALERTTABLE { 11 | font-family:arial; 12 | font-size:10pt; 13 | border-style:solid; 14 | border-color:black; 15 | border-width:2px; 16 | } 17 | 18 | TH.ALERTTABLE { 19 | font-size:12pt; 20 | color:black; 21 | text-align:left; 22 | vertical-align: top; 23 | padding-left: 5px; 24 | background-color:#EEEEEE; 25 | } 26 | 27 | TR.ALERTTABLE { 28 | } 29 | 30 | TD.ALERTTABLE { 31 | font-size:10pt; 32 | background-color:#CCCCCC; 33 | color:black; 34 | border-style:solid; 35 | border-width:1px; 36 | font-size:10pt; 37 | font-weight:bold; 38 | text-align:left; 39 | } 40 | 41 | TD.MYVALUE { 42 | font-size:10pt; 43 | background-color:#FFFFFF; 44 | color:black; 45 | border-style:solid; 46 | border-width:0px; 47 | font-size:10pt; 48 | text-align:left; 49 | padding-top: 4px; 50 | padding-bottom: 4px; 51 | padding-left: 5px; 52 | padding-right: 5px; 53 | } 54 | 55 | TD.ALERTTITLE { 56 | font-size:12pt; 57 | background-color:#EEEEEE; 58 | color:black; 59 | border-style:solid; 60 | border-width:0px; 61 | font-weight:bold; 62 | text-align:left; 63 | } 64 | 65 | 66 | CAPTION.ALERTLIST { 67 | background-color:#EEEEEE; 68 | color:black; 69 | border-style:solid; 70 | border-width:2px; 71 | border-color:black; 72 | } 73 | 74 | TABLE.ALERTLIST { 75 | font-family:arial; 76 | font-size:10pt; 77 | background-color:#EEEEEE; 78 | border-style:solid; 79 | border-color:black; 80 | border-width:2px; 81 | } 82 | 83 | TH.ALERTLIST { 84 | font-size:12pt; 85 | color:black; 86 | text-align:left; 87 | vertical-align: top; 88 | } 89 | 90 | TR.ALERTLIST { 91 | } 92 | 93 | TD.ALERTLIST { 94 | font-size:10pt; 95 | background-color:#AAAAAA; 96 | color:black; 97 | border-style:solid; 98 | border-width:1px; 99 | font-size:10pt; 100 | font-weight:bold; 101 | text-align:left; 102 | padding-left: 5px; 103 | padding-right: 5px; 104 | } 105 | 106 | table.ALERTDETAILS { 107 | font: normal 75%/150% Verdana, Arial, Helvetica, sans-serif; 108 | border-width: 1px 1px 1px 1px; 109 | border-spacing: 2px; 110 | border-style: outset outset outset outset; 111 | border-color: green green green green; 112 | border-collapse: collapse; 113 | background-color: white; 114 | } 115 | table.ALERTDETAILS th { 116 | border-width: 1px 1px 1px 1px; 117 | padding: 2px 4px 2px 4px; 118 | border-style: dotted dotted dotted dotted; 119 | border-color: gray gray gray gray; 120 | background-color: rgb(255, 255, 240); 121 | } 122 | table.ALERTDETAILS td { 123 | border-width: 1px 1px 1px 1px; 124 | padding: 2px 4px 2px 4px; 125 | border-style: dotted dotted dotted dotted; 126 | border-color: gray gray gray gray; 127 | background-color: rgb(255, 255, 240); 128 | } 129 | 130 | -------------------------------------------------------------------------------- /html/css/detail.css: -------------------------------------------------------------------------------- 1 | /* css styles for netflow processing tbales */ 2 | 3 | .TDnfprocLabel { 4 | padding-left: 5px; 5 | padding-right: 10px; 6 | font-weight: bold; 7 | background-color: #DDDDDD; 8 | } 9 | 10 | .TDnfprocControl { 11 | padding-left: 10px; 12 | padding-right: 10px; 13 | font-weight: bold; 14 | } 15 | 16 | .NfProcessing { 17 | margin-top: 30px; 18 | margin-bottom: 5px; 19 | } 20 | 21 | #lookupbox{ /*CSS for pop up hint box */ 22 | position:absolute; 23 | top: 0; 24 | background-color: lightyellow; 25 | width: 400px; /*Default width of hint.*/ 26 | height: 180px; /*Default height of hint.*/ 27 | padding: 3px; 28 | border:1px solid black; 29 | font:normal 10px Verdana; 30 | line-height:18px; 31 | z-index:100; 32 | border-right: 3px solid black; 33 | border-bottom: 3px solid black; 34 | visibility: hidden; 35 | } 36 | 37 | .flowlist { 38 | color: black; 39 | font-family:"Courier New", Courier, monospace; 40 | font-size: 14px; 41 | } 42 | .flowlist a { 43 | text-decoration: none; 44 | color: black; 45 | font-family:Courier,monospace; 46 | font-size: 14px; 47 | } 48 | .flowlist a:visited { 49 | text-decoration: none; 50 | color: black; 51 | font-family:Courier,monospace; 52 | font-size: 14px; 53 | } 54 | .flowlist a:active { 55 | text-decoration: none; 56 | font-family:Courier,monospace; 57 | font-size: 14px; 58 | } 59 | .flowlist a:hover { 60 | background: mediumspringgreen; 61 | font-family:Courier,monospace; 62 | font-size: 14px; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /html/css/lookup.css: -------------------------------------------------------------------------------- 1 | /* css styles for lookup box content */ 2 | 3 | body { 4 | background-color:lightyellow; 5 | font-family: Verdana; 6 | font-size: 10px; 7 | font-weight: normal; 8 | } 9 | 10 | pre { 11 | font-family: Courier; 12 | font-size: 10px; 13 | font-weight: normal; 14 | } 15 | 16 | h3 { 17 | font-family: Verdana; 18 | font-size: 12px; 19 | font-weight: bold; 20 | margin:0px; 21 | margin-top:10px; 22 | margin-bottom:6px; 23 | } 24 | -------------------------------------------------------------------------------- /html/css/nfsen.css: -------------------------------------------------------------------------------- 1 | /*Credits: Dynamic Drive CSS Library */ 2 | /*URL: http://www.dynamicdrive.com/style/ */ 3 | 4 | .shadetabs { 5 | border-bottom: 1px solid gray; 6 | width: 95%; 7 | background-image: url(../icons/shade.png); 8 | background-repeat: repeat-x; 9 | /* width: 90%; width of menu. Uncomment to change to a specific width */ 10 | /* margin-bottom: 1em; */ 11 | } 12 | 13 | .shadetabs ul { 14 | padding: 3px 0; 15 | margin-left: 10px; 16 | margin-top: 1px; 17 | margin-bottom: 0; 18 | font-size: 12px; 19 | font-weight: bold; 20 | font-family: Verdana,sans-serif; 21 | list-style-type: none; 22 | text-align: left; /*set to left, center, or right to align the menu as desired*/ 23 | } 24 | 25 | .shadetabs li { 26 | display: inline; 27 | margin: 0; 28 | } 29 | 30 | .shadetabs li a { 31 | text-decoration: none; 32 | padding: 3px 5px; 33 | margin-right: 1px; 34 | border: 1px solid #778; 35 | color: #2d2b2b; 36 | background: white url(../icons/shade.png) top left repeat-x; 37 | } 38 | 39 | .shadetabs li a:visited { 40 | color: #2d2b2b; 41 | background-color: #FFFFFF; 42 | } 43 | 44 | .shadetabs li a:hover { 45 | text-decoration: underline; 46 | color: #2d2b2b; 47 | background-color: #FFFFFF; 48 | } 49 | 50 | .shadetabs li.selected { 51 | position: relative; 52 | top: 0px; 53 | } 54 | 55 | .shadetabs li.selected a { /*selected main tab style */ 56 | text-decoration: none; 57 | padding: 3px 5px; 58 | margin-right: 1px; 59 | border: 1px solid #778; 60 | color: #2d2b2b; 61 | background: white url(../icons/shadeactive.png) top left repeat-x; 62 | border-bottom-color: white; 63 | } 64 | 65 | .shadetabs li.selected a:hover { /*selected main tab style */ 66 | text-decoration: none; 67 | } 68 | 69 | /* Text in the nevigator */ 70 | .navigator { 71 | text-decoration: none; 72 | padding: 0px 5px; 73 | color: #2d2b2b; 74 | font-family: Verdana; 75 | font-size: 12px; 76 | font-weight: bold; 77 | } 78 | 79 | /* hierarchical profile selector */ 80 | 81 | .select_pulldown { 82 | padding:3px 5px; 83 | border: 1px solid #2d2b2b; 84 | background: #EEEEEE; 85 | color: #2d2b2b; 86 | font-family: Verdana; 87 | font-size: 12px; 88 | } 89 | 90 | .select_pullup { 91 | padding: 3px 5px; 92 | border: 1px solid #778; 93 | margin-left:10px; 94 | background: white url(../icons/shade.png) top left repeat-x; 95 | text-decoration: none; 96 | color: #2d2b2b; 97 | font-family: Verdana; 98 | font-size: 12px; 99 | font-weight: bold; 100 | } 101 | 102 | A.select_pulldown { 103 | text-decoration:none; 104 | } 105 | 106 | A.select_inner { 107 | text-decoration: none; 108 | color: #2d2b2b; 109 | } 110 | 111 | A.select_inner:hover { 112 | text-decoration: none; 113 | color:#FFFFFF; 114 | } 115 | 116 | .select_inner_div_group { 117 | padding: 1px; 118 | color: #2d2b2b; 119 | cursor:pointer; 120 | text-align:right; 121 | font-weight: bold; 122 | } 123 | 124 | .select_inner_div { 125 | padding: 1px; 126 | color: #2d2b2b; 127 | cursor:pointer; 128 | text-align:right; 129 | } 130 | 131 | .select_inner_active { 132 | border:1px solid #6666CC; 133 | background:#000066; 134 | color: #FFFFFF; 135 | cursor:pointer; 136 | text-align:right; 137 | } 138 | 139 | /* other nfsen styles */ 140 | 141 | .infostring { 142 | margin-left: 20px; 143 | margin-right: 50px; 144 | font-style: italic; 145 | background-color: #75FF50; 146 | } 147 | 148 | .errstring { 149 | margin-left: 20px; 150 | margin-right: 50px; 151 | font-style: italic; 152 | background-color: #FF1122; 153 | } 154 | 155 | .warnstring { 156 | margin-left: 20px; 157 | margin-right: 50px; 158 | font-style: italic; 159 | background-color: #FFCB20; 160 | } 161 | 162 | .alertstring { 163 | margin-left: 20px; 164 | margin-right: 50px; 165 | font-style: italic; 166 | background-color: #FF9936; 167 | } 168 | 169 | #StartDragHandle { 170 | cursor:w-resize; 171 | } 172 | 173 | #StopDragHandle { 174 | cursor:e-resize; 175 | } 176 | 177 | #CursorDragHandle { 178 | cursor:move; 179 | } 180 | 181 | #hintbox{ 182 | position:absolute; 183 | top: 0; 184 | background-color: lightyellow; 185 | width: 150px; 186 | padding: 3px; 187 | border:1px solid black; 188 | font:normal 10px Verdana; 189 | line-height:18px; 190 | z-index:100; 191 | border-right: 3px solid black; 192 | border-bottom: 3px solid black; 193 | visibility: hidden; 194 | } 195 | 196 | .footer { 197 | font-family: Verdana; 198 | font-size: 10px; 199 | font-weight: normal; 200 | } 201 | 202 | 203 | -------------------------------------------------------------------------------- /html/css/profileadmin.css: -------------------------------------------------------------------------------- 1 | 2 | CAPTION.STATTABLE { 3 | background-color:#EEEEEE; 4 | color:black; 5 | border-style:solid; 6 | border-width:2px; 7 | border-color:black; 8 | } 9 | 10 | TABLE.STATTABLE { 11 | font-family:arial; 12 | font-size:10pt; 13 | background-color:#EEEEEE; 14 | width:460px; 15 | border-style:solid; 16 | border-color:black; 17 | border-width:2px; 18 | } 19 | 20 | TH.STATTABLE { 21 | font-size:12pt; 22 | color:black; 23 | text-align:left; 24 | vertical-align: top; 25 | } 26 | 27 | TR.STATTABLE { 28 | } 29 | 30 | TD.STATTABLE { 31 | font-size:10pt; 32 | background-color:#CCCCCC; 33 | color:black; 34 | border-style:solid; 35 | border-width:1px; 36 | font-size:10pt; 37 | font-weight:bold; 38 | text-align:left; 39 | } 40 | 41 | TD.MYVALUE { 42 | font-size:10pt; 43 | background-color:#FFFFFF; 44 | color:black; 45 | border-style:solid; 46 | border-width:1px; 47 | font-size:10pt; 48 | text-align:left; 49 | } 50 | 51 | TD.CHANNELTITLE { 52 | font-size:12pt; 53 | background-color:#EEEEEE; 54 | color:black; 55 | border-style:solid; 56 | border-width:0px; 57 | font-weight:bold; 58 | text-align:left; 59 | } 60 | 61 | 62 | CAPTION.CHANNELLIST { 63 | background-color:#EEEEEE; 64 | color:black; 65 | border-style:solid; 66 | border-width:2px; 67 | border-color:black; 68 | } 69 | 70 | TABLE.CHANNELLIST { 71 | font-family:arial; 72 | font-size:10pt; 73 | background-color:#EEEEEE; 74 | width:100%; 75 | border-style:solid; 76 | border-color:black; 77 | border-width:2px; 78 | } 79 | 80 | TH.CHANNELLIST { 81 | font-size:12pt; 82 | color:black; 83 | text-align:left; 84 | vertical-align: top; 85 | } 86 | 87 | TR.CHANNELLIST { 88 | } 89 | 90 | TD.CHANNELLIST { 91 | font-size:10pt; 92 | background-color:#AAAAAA; 93 | color:black; 94 | border-style:solid; 95 | border-width:1px; 96 | font-size:10pt; 97 | font-weight:bold; 98 | text-align:left; 99 | } 100 | 101 | .helptext { 102 | display:inline; 103 | font-size:10pt; 104 | font-weight:normal; 105 | margin-top:5px; 106 | margin-left:0px; 107 | background-color:#A5FF89; 108 | } 109 | 110 | .hrule { 111 | width:100%; 112 | size:1; 113 | text-align:left; 114 | } 115 | 116 | .progressbar { 117 | text-align:left; 118 | font-size:9pt; 119 | background-image: url(../icons/progress.png); 120 | background-repeat: repeat-x; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /html/icons/EmptyGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/EmptyGraph.png -------------------------------------------------------------------------------- /html/icons/Error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/Error.png -------------------------------------------------------------------------------- /html/icons/ErrorGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/ErrorGraph.png -------------------------------------------------------------------------------- /html/icons/arrow.blue.down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/arrow.blue.down.png -------------------------------------------------------------------------------- /html/icons/arrow.blue.right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/arrow.blue.right.png -------------------------------------------------------------------------------- /html/icons/arrow.yellow.down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/arrow.yellow.down.png -------------------------------------------------------------------------------- /html/icons/arrow.yellow.right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/arrow.yellow.right.png -------------------------------------------------------------------------------- /html/icons/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/cancel.png -------------------------------------------------------------------------------- /html/icons/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/close.png -------------------------------------------------------------------------------- /html/icons/cursor-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/cursor-line.png -------------------------------------------------------------------------------- /html/icons/cursor-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/cursor-start.png -------------------------------------------------------------------------------- /html/icons/cursor-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/cursor-stop.png -------------------------------------------------------------------------------- /html/icons/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/edit.png -------------------------------------------------------------------------------- /html/icons/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/help.png -------------------------------------------------------------------------------- /html/icons/invisible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/invisible.png -------------------------------------------------------------------------------- /html/icons/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/minus.png -------------------------------------------------------------------------------- /html/icons/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/ok.png -------------------------------------------------------------------------------- /html/icons/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/plus.png -------------------------------------------------------------------------------- /html/icons/progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/progress.png -------------------------------------------------------------------------------- /html/icons/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/save.png -------------------------------------------------------------------------------- /html/icons/shade.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/shade.gif -------------------------------------------------------------------------------- /html/icons/shade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/shade.png -------------------------------------------------------------------------------- /html/icons/shadeactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/shadeactive.png -------------------------------------------------------------------------------- /html/icons/space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/space.png -------------------------------------------------------------------------------- /html/icons/spyglas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/spyglas.png -------------------------------------------------------------------------------- /html/icons/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/trash.png -------------------------------------------------------------------------------- /html/icons/trigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/html/icons/trigger.png -------------------------------------------------------------------------------- /html/js/ColorPicker2.js: -------------------------------------------------------------------------------- 1 | // =================================================================== 2 | // Author: Matt Kruse 3 | // WWW: http://www.mattkruse.com/ 4 | // 5 | // NOTICE: You may use this code for any purpose, commercial or 6 | // private, without any further permission from the author. You may 7 | // remove this notice from your final code if you wish, however it is 8 | // appreciated by the author if at least my web site address is kept. 9 | // 10 | // You may *NOT* re-distribute this code in any way except through its 11 | // use. That means, you can include it in your product, or your web 12 | // site, or any other form where the code is actually being used. You 13 | // may not put the plain javascript up on your site for download or 14 | // include it in your javascript libraries for download. 15 | // If you wish to share this code with others, please just point them 16 | // to the URL instead. 17 | // Please DO NOT link directly to my .js files from your site. Copy 18 | // the files to your server and use them there. Thank you. 19 | // =================================================================== 20 | 21 | /* SOURCE FILE: AnchorPosition.js */ 22 | function getAnchorPosition(anchorname){var useWindow=false;var coordinates=new Object();var x=0,y=0;var use_gebi=false, use_css=false, use_layers=false;if(document.getElementById){use_gebi=true;}else if(document.all){use_css=true;}else if(document.layers){use_layers=true;}if(use_gebi && document.all){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_gebi){var o=document.getElementById(anchorname);x=AnchorPosition_getPageOffsetLeft(o);y=AnchorPosition_getPageOffsetTop(o);}else if(use_css){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_layers){var found=0;for(var i=0;i screen.availHeight){this.y = screen.availHeight - this.height;}}if(screen && screen.availWidth){if((this.x + this.width) > screen.availWidth){this.x = screen.availWidth - this.width;}}var avoidAboutBlank = window.opera ||( document.layers && !navigator.mimeTypes['*']) || navigator.vendor == 'KDE' ||( document.childNodes && !document.all && !navigator.taintEnabled);this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");}this.refresh();}} 37 | function PopupWindow_hidePopup(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.visibility = "hidden";}else if(this.use_css){document.all[this.divName].style.visibility = "hidden";}else if(this.use_layers){document.layers[this.divName].visibility = "hidden";}}else{if(this.popupWindow && !this.popupWindow.closed){this.popupWindow.close();this.popupWindow = null;}}} 38 | function PopupWindow_isClicked(e){if(this.divName != null){if(this.use_layers){var clickX = e.pageX;var clickY = e.pageY;var t = document.layers[this.divName];if((clickX > t.left) &&(clickX < t.left+t.clip.width) &&(clickY > t.top) &&(clickY < t.top+t.clip.height)){return true;}else{return false;}}else if(document.all){var t = window.event.srcElement;while(t.parentElement != null){if(t.id==this.divName){return true;}t = t.parentElement;}return false;}else if(this.use_gebi && e){var t = e.originalTarget;while(t.parentNode != null){if(t.id==this.divName){return true;}t = t.parentNode;}return false;}return false;}return false;} 39 | function PopupWindow_hideIfNotClicked(e){if(this.autoHideEnabled && !this.isClicked(e)){this.hidePopup();}} 40 | function PopupWindow_autoHide(){this.autoHideEnabled = true;} 41 | function PopupWindow_hidePopupWindows(e){for(var i=0;i0){this.type="DIV";this.divName = arguments[0];}else{this.type="WINDOW";}this.use_gebi = false;this.use_css = false;this.use_layers = false;if(document.getElementById){this.use_gebi = true;}else if(document.all){this.use_css = true;}else if(document.layers){this.use_layers = true;}else{this.type = "WINDOW";}this.offsetX = 0;this.offsetY = 0;this.getXYPosition = PopupWindow_getXYPosition;this.populate = PopupWindow_populate;this.setUrl = PopupWindow_setUrl;this.setWindowProperties = PopupWindow_setWindowProperties;this.refresh = PopupWindow_refresh;this.showPopup = PopupWindow_showPopup;this.hidePopup = PopupWindow_hidePopup;this.setSize = PopupWindow_setSize;this.isClicked = PopupWindow_isClicked;this.autoHide = PopupWindow_autoHide;this.hideIfNotClicked = PopupWindow_hideIfNotClicked;} 44 | 45 | 46 | /* SOURCE FILE: ColorPicker2.js */ 47 | 48 | ColorPicker_targetInput = null; 49 | function ColorPicker_writeDiv(){document.writeln("");} 50 | function ColorPicker_show(anchorname){this.showPopup(anchorname);} 51 | function ColorPicker_pickColor(color,obj){obj.hidePopup();pickColor(color);} 52 | function pickColor(color){if(ColorPicker_targetInput==null){alert("Target Input is null, which means you either didn't use the 'select' function or you have no defined your own 'pickColor' function to handle the picked color!");return;}ColorPicker_targetInput.value = color;} 53 | function ColorPicker_select(inputobj,linkname){if(inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea"){alert("colorpicker.select: Input object passed is not a valid form input object");window.ColorPicker_targetInput=null;return;}window.ColorPicker_targetInput = inputobj;this.show(linkname);} 54 | function ColorPicker_highlightColor(c){var thedoc =(arguments.length>1)?arguments[1]:window.document;var d = thedoc.getElementById("colorPickerSelectedColor");d.style.backgroundColor = c;d = thedoc.getElementById("colorPickerSelectedColorValue");d.innerHTML = c;} 55 | function ColorPicker(){var windowMode = false;if(arguments.length==0){var divname = "colorPickerDiv";}else if(arguments[0] == "window"){var divname = '';windowMode = true;}else{var divname = arguments[0];}if(divname != ""){var cp = new PopupWindow(divname);}else{var cp = new PopupWindow();cp.setSize(225,250);}cp.currentValue = "#FFFFFF";cp.writeDiv = ColorPicker_writeDiv;cp.highlightColor = ColorPicker_highlightColor;cp.show = ColorPicker_show;cp.select = ColorPicker_select;var colors = new Array("#000000","#000033","#000066","#000099","#0000CC","#0000FF","#330000","#330033","#330066","#330099","#3300CC", 56 | "#3300FF","#660000","#660033","#660066","#660099","#6600CC","#6600FF","#990000","#990033","#990066","#990099", 57 | "#9900CC","#9900FF","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#FF0000","#FF0033","#FF0066", 58 | "#FF0099","#FF00CC","#FF00FF","#003300","#003333","#003366","#003399","#0033CC","#0033FF","#333300","#333333", 59 | "#333366","#333399","#3333CC","#3333FF","#663300","#663333","#663366","#663399","#6633CC","#6633FF","#993300", 60 | "#993333","#993366","#993399","#9933CC","#9933FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF", 61 | "#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#006600","#006633","#006666","#006699","#0066CC", 62 | "#0066FF","#336600","#336633","#336666","#336699","#3366CC","#3366FF","#666600","#666633","#666666","#666699", 63 | "#6666CC","#6666FF","#996600","#996633","#996666","#996699","#9966CC","#9966FF","#CC6600","#CC6633","#CC6666", 64 | "#CC6699","#CC66CC","#CC66FF","#FF6600","#FF6633","#FF6666","#FF6699","#FF66CC","#FF66FF","#009900","#009933", 65 | "#009966","#009999","#0099CC","#0099FF","#339900","#339933","#339966","#339999","#3399CC","#3399FF","#669900", 66 | "#669933","#669966","#669999","#6699CC","#6699FF","#999900","#999933","#999966","#999999","#9999CC","#9999FF", 67 | "#CC9900","#CC9933","#CC9966","#CC9999","#CC99CC","#CC99FF","#FF9900","#FF9933","#FF9966","#FF9999","#FF99CC", 68 | "#FF99FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#33CC00","#33CC33","#33CC66","#33CC99", 69 | "#33CCCC","#33CCFF","#66CC00","#66CC33","#66CC66","#66CC99","#66CCCC","#66CCFF","#99CC00","#99CC33","#99CC66", 70 | "#99CC99","#99CCCC","#99CCFF","#CCCC00","#CCCC33","#CCCC66","#CCCC99","#CCCCCC","#CCCCFF","#FFCC00","#FFCC33", 71 | "#FFCC66","#FFCC99","#FFCCCC","#FFCCFF","#00FF00","#00FF33","#00FF66","#00FF99","#00FFCC","#00FFFF","#33FF00", 72 | "#33FF33","#33FF66","#33FF99","#33FFCC","#33FFFF","#66FF00","#66FF33","#66FF66","#66FF99","#66FFCC","#66FFFF", 73 | "#99FF00","#99FF33","#99FF66","#99FF99","#99FFCC","#99FFFF","#CCFF00","#CCFF33","#CCFF66","#CCFF99","#CCFFCC", 74 | "#CCFFFF","#FFFF00","#FFFF33","#FFFF66","#FFFF99","#FFFFCC","#FFFFFF");var total = colors.length;var width = 18;var cp_contents = "";var windowRef =(windowMode)?"window.opener.":"";if(windowMode){cp_contents += "Select Color";cp_contents += "
";}cp_contents += "";var use_highlight =(document.getElementById || document.all)?true:false;for(var i=0;i   ';if( ((i+1)>=total) ||(((i+1) % width) == 0)){cp_contents += "";}}if(document.getElementById){var width1 = Math.floor(width/2);var width2 = width = width1;cp_contents += "";}cp_contents += "
 #FFFFFF
";if(windowMode){cp_contents += "
";}cp.populate(cp_contents+"\n");cp.offsetY = 25;cp.autoHide();return cp;} 75 | 76 | 77 | -------------------------------------------------------------------------------- /html/js/alerting.js: -------------------------------------------------------------------------------- 1 | var process_dialog = true; 2 | var HitCR = false; 3 | 4 | function SetConditionRow(row_num) { 5 | 6 | var comp = document.getElementById("comp_" + row_num ); 7 | var comp_type = document.getElementById("comp_type_" + row_num); 8 | var plus_label = document.getElementById("plus-label_" + row_num); 9 | var minus_label = document.getElementById("minus-label_" + row_num); 10 | var plusminus_label = document.getElementById("plusminus-label_" + row_num); 11 | var scale = document.getElementById("scale_" + row_num); 12 | if ( comp.value == 2 && comp_type.value == 0 ) { 13 | comp_type.value = 1; 14 | } 15 | if ( comp_type.value == 0 ) { 16 | plus_label.style.display = 'none'; 17 | minus_label.style.display = 'none'; 18 | plusminus_label.style.display = 'none'; 19 | if ( comp.value == 2 ) 20 | comp.value = 0; 21 | if ( scale.value == 5 ) 22 | scale.value = 0; 23 | scale.options[5].disabled = 1; 24 | } else { 25 | scale.options[5].disabled = 0; 26 | switch (comp.value) { 27 | case '0': 28 | plus_label.style.display = ''; 29 | minus_label.style.display = 'none'; 30 | plusminus_label.style.display = 'none'; 31 | break; 32 | case '1': 33 | plus_label.style.display = 'none'; 34 | minus_label.style.display = ''; 35 | plusminus_label.style.display = 'none'; 36 | break; 37 | case '2': 38 | plus_label.style.display = 'none'; 39 | minus_label.style.display = 'none'; 40 | plusminus_label.style.display = ''; 41 | break; 42 | } 43 | } 44 | } // End of SetConditionRow 45 | 46 | function SetupCondition(offset, which) { 47 | 48 | switch (which) { 49 | case 0: 50 | EnableDisableCondition(0, offset, 1); 51 | EnableDisableCondition(offset, 2*offset, 0); 52 | document.getElementById("plugin_condition_select").style.display = 'none'; 53 | break; 54 | case 1: 55 | EnableDisableCondition(0, offset, 0); 56 | EnableDisableCondition(offset, 2*offset, 1); 57 | document.getElementById("plugin_condition_select").style.display = 'none'; 58 | break; 59 | case 2: 60 | EnableDisableCondition(0, offset, 0); 61 | EnableDisableCondition(offset, 2*offset, 0); 62 | document.getElementById("plugin_condition_select").style.display = ''; 63 | break; 64 | } 65 | 66 | } // End of SetupCondition 67 | 68 | function EnableDisableCondition (from, to, enabled) { 69 | 70 | // Make sure row 0 is enabled 71 | var row_num = from; 72 | if ( enabled ) 73 | document.getElementById("visible_" + row_num).value = 1; 74 | 75 | for ( row_num = from; row_num < to; row_num++ ) { 76 | row = document.getElementById("row_" + row_num); 77 | if ( enabled ) { 78 | if ( document.getElementById("visible_" + row_num ).value > 0) 79 | row.style.display = ''; 80 | else 81 | row.style.display = 'none'; 82 | } else { 83 | row.style.display = 'none'; 84 | } 85 | } 86 | 87 | } // End of EnableDisableCondition 88 | 89 | function DeleteRow(row_num) { 90 | 91 | document.getElementById("row_" + row_num ).style.display = 'none'; 92 | document.getElementById("visible_" + row_num ).value = 0; 93 | row_num--; 94 | document.getElementById("add_row_" + row_num ).style.display = ''; 95 | 96 | } // DeleteRow 97 | 98 | function EnableRow(row_num) { 99 | 100 | document.getElementById("row_" + row_num ).style.display = ''; 101 | document.getElementById("visible_" + row_num ).value = 1; 102 | row_num--; 103 | document.getElementById("add_row_" + row_num ).style.display = 'none'; 104 | 105 | } // EnableRow 106 | 107 | function SetAction(action) { 108 | var checked = document.getElementById("action_" + action ).checked; 109 | 110 | if ( checked && action == 0 ) { 111 | // everything else off 112 | for ( var i=1; i<4; i++ ) { 113 | document.getElementById("action_" + i ).checked = 0; 114 | } 115 | document.getElementById("action_email").disabled = 1; 116 | document.getElementById("action_subject").disabled = 1; 117 | document.getElementById("action_system").disabled = 1; 118 | document.getElementById("alert_plugin").disabled = 1; 119 | } 120 | if ( checked && action > 0 ) { 121 | // switch off 'no action' 122 | document.getElementById("action_0").checked = 0; 123 | } 124 | 125 | switch (action) { 126 | case 1: 127 | document.getElementById("action_email").disabled = checked ? 0 : 1; 128 | document.getElementById("action_subject").disabled = checked ? 0 : 1; 129 | break; 130 | case 2: 131 | document.getElementById("action_system").disabled = checked ? 0 : 10; 132 | break; 133 | case 3: 134 | document.getElementById("action_plugin").disabled = checked ? 0 : 1; 135 | break; 136 | } 137 | 138 | // make sure at least 'no action' is selected if nothing else 139 | checked = 0; 140 | for ( var i=1; i<4; i++ ) { 141 | if ( document.getElementById("action_" + i ).checked > 0 ) 142 | checked = 1; 143 | } 144 | if ( checked == 0 ) { 145 | document.getElementById("action_0").checked = 1; 146 | } 147 | 148 | } // End of SetAction 149 | 150 | function EnableEdit(condition_plugins, action_plugins) { 151 | 152 | // Enable Filter Table 153 | document.getElementById("channellist").disabled = false; 154 | document.getElementById("filter").disabled = false; 155 | 156 | // radio buttons 157 | document.getElementById("type0").disabled = false; 158 | document.getElementById("type1").disabled = false; 159 | if ( condition_plugins > 0 ) 160 | document.getElementById("type2").disabled = false; 161 | 162 | // Enable SumStatTable 163 | var i=0; 164 | while ( document.getElementById("row_" + i) ) { 165 | if ( document.getElementById("op_" + i) ) 166 | document.getElementById("op_" + i).disabled = false; 167 | document.getElementById("type_" + i).disabled = false; 168 | document.getElementById("comp_" + i).disabled = false; 169 | document.getElementById("comp_type_" + i).disabled = false; 170 | document.getElementById("stat_type_" + i).disabled = false; 171 | document.getElementById("comp_value_" + i).disabled = false; 172 | document.getElementById("scale_" + i).disabled = false; 173 | 174 | if ( document.getElementById("visible_" + i ).value ) { 175 | var elem = document.getElementById("delete_row_" + i); 176 | if ( elem ) 177 | elem.style.display = ''; 178 | 179 | var next = document.getElementById("visible_" + (i+1) ); 180 | if ( next && next.value == 0 ) { 181 | elem = document.getElementById("add_row_" + i); 182 | if ( elem ) 183 | elem.style.display = ''; 184 | } 185 | } 186 | i++; 187 | } 188 | 189 | // plugin condition table 190 | if ( condition_plugins > 0 ) 191 | document.getElementById("plugin_condition").disabled = false; 192 | 193 | // trigger table 194 | document.getElementById("trigger_type").disabled = false; 195 | document.getElementById("trigger_number").disabled = false; 196 | document.getElementById("trigger_blocks").disabled = false; 197 | 198 | // action table 199 | for ( var i=0; i<3; i++ ) { 200 | document.getElementById("action_" + i ).disabled = 0; 201 | } 202 | if ( action_plugins > 0 ) 203 | document.getElementById("action_3" ).disabled = 0; 204 | 205 | if ( document.getElementById("action_1").checked ) { 206 | document.getElementById("action_email").disabled = 0; 207 | document.getElementById("action_subject").disabled = 0; 208 | } 209 | if ( document.getElementById("action_2").checked ) { 210 | document.getElementById("action_system").disabled = 0; 211 | } 212 | if ( document.getElementById("action_3").checked ) { 213 | document.getElementById("action_plugin").disabled = 0; 214 | } 215 | // Controls 216 | document.getElementById("row_controls").style.display = ''; 217 | document.getElementById("EventTable").style.display = 'none'; 218 | 219 | 220 | } // End of EnableEdit 221 | 222 | function ConfirmDeleteAlert(alert) { 223 | answer = confirm("Are you sure to delete alert: '" + alert + "'?"); 224 | process_dialog = answer; 225 | if ( answer ) 226 | SetAlertName(alert); 227 | } 228 | 229 | function SetAlertName(alert) { 230 | document.getElementById("alert").value = alert; 231 | } // End of SetAlertName 232 | 233 | function NoCRSubmit() { 234 | HitCR = true; 235 | } // End of NoCRSubmit 236 | 237 | function ProcessForm() { 238 | if ( HitCR == true ) { 239 | HitCR = false; 240 | return false; 241 | } 242 | 243 | if ( !process_dialog ) { 244 | process_dialog = true; 245 | return false; 246 | } else { 247 | return true; 248 | } 249 | 250 | } // End of ProcessForm 251 | 252 | function SetAlertStatus(type, alertname, arg) { 253 | document.getElementById("avg_frame").src="rrdgraph.php?cmd=get-alertgraph&alert=" + alertname + "&arg=" + type + "+" + arg; 254 | SetCookieValue("avg_type", type); 255 | } // End of SetAlertStatus 256 | 257 | function ChangeAVGtype ( elem ) { 258 | 259 | } // End of ChangeAVGtype 260 | 261 | -------------------------------------------------------------------------------- /html/js/global.js: -------------------------------------------------------------------------------- 1 | /* nfsen global used javascript functions */ 2 | 3 | function GetCookieValue(varname) { 4 | 5 | var Cookie = document.cookie; 6 | if ( Cookie == null ) 7 | return null; 8 | 9 | // alert("Cookie: " + document.cookie); 10 | 11 | cookie_vars = Cookie.split("; "); 12 | for (i=0; i= 0; i--) { 264 | orderSelector.options[i] = null; 265 | } 266 | 267 | var which = signSelector.selectedIndex; 268 | if ( which == 0 ) { 269 | if ( !init ) { 270 | num_neg--; 271 | num_pos++; 272 | } 273 | j = num_pos; 274 | } else { 275 | if ( !init ) { 276 | num_neg++; 277 | num_pos--; 278 | } 279 | j = num_neg; 280 | } 281 | 282 | for (i = 0; i < j; i++) { 283 | orderSelector.options[i] = new Option(i+1); 284 | orderSelector.options[i].value = i+1; 285 | } 286 | 287 | orderSelector.options[preset-1].selected = true; 288 | } 289 | 290 | function ValidateEditForm() { 291 | 292 | // If user presses Cancel 293 | if ( abort_dialog ) 294 | return true; 295 | 296 | if ( document.getElementById("name").value.length == 0 ) { 297 | alert("Enter a channel name first!"); 298 | return false; 299 | } 300 | 301 | // select all sources to be set in POST request 302 | var SourceSelector = document.getElementById('channel_sources'); 303 | 304 | if ( confirm_delete == 1 ) { 305 | channelname_element = document.getElementById('name'); 306 | answer = confirm("Are you sure to delete channel '" + channelname_element.value + "'"); 307 | confirm_delete = 0; 308 | return answer; 309 | } 310 | 311 | // Verify colour syntax in colour field 312 | if ( Validate_colour() == false ) 313 | return false; 314 | 315 | // at least one element must be selected 316 | var num_items = SourceSelector.options.length; 317 | /* 318 | for (i = 0; i < SourceSelector.options.length; i++) { 319 | if (SourceSelector.options[i].selected) 320 | num_items--; 321 | } 322 | */ 323 | if ( num_items == 0 ) { 324 | alert("At least 1 source must be selected"); 325 | return false; 326 | } 327 | 328 | for (i=0; i < SourceSelector.options.length; i++) { 329 | SourceSelector.options[i].selected = true; 330 | } 331 | 332 | return true; 333 | } 334 | 335 | var cancelAction = false; 336 | 337 | function ValidateNewprofileForm () { 338 | 339 | if ( cancelAction ) { 340 | return true; 341 | } 342 | 343 | var profile = document.getElementById('profile').value; 344 | 345 | if ( profile.length == 0 ) { 346 | alert("Enter a profile name first!"); 347 | return false; 348 | } 349 | 350 | re = /[^A-Za-z0-9\-+_]+/; 351 | if ( re.test(profile) ) { 352 | alert("Invalid characters in profile name '" + profile + "'"); 353 | return false; 354 | } 355 | 356 | var groupselect = document.getElementById('groupselect'); 357 | var inputbox = document.getElementById('profilegroup'); 358 | var which = groupselect.selectedIndex; 359 | 360 | var profilegroup = groupselect[which].value; 361 | 362 | if ( profilegroup == 'New group ...' ) { 363 | profilegroup = inputbox.value; 364 | } 365 | if ( profilegroup == '(nogroup)' ) { 366 | profilegroup = '.'; 367 | } else if ( re.test(profilegroup) ) { 368 | alert("Invalid characters in group '" + profilegroup + "'"); 369 | return false; 370 | } 371 | 372 | document.getElementById('newprofileswitch').value = profilegroup + '/' + profile; 373 | 374 | return true; 375 | 376 | } // End of ValidateNewprofileForm 377 | 378 | /* called, when the type if the profile ('classic' or 'individual') is changed by clicking on 379 | * the radio buttons. 380 | * toggles the display status of the filter and source selector 381 | */ 382 | function ChannelWizard(type) { 383 | 384 | if ( type == "classic" ) { 385 | document.getElementById('select_sources_element').style.display = ''; 386 | document.getElementById('filter_element').style.display = ''; 387 | } 388 | if ( type == "individual" ) { 389 | document.getElementById('select_sources_element').style.display = 'none'; 390 | document.getElementById('filter_element').style.display = 'none'; 391 | } 392 | } // ChannelWizard 393 | 394 | function HandleGroupSelect() { 395 | 396 | var groupselect = document.getElementById('groupselect'); 397 | var which = groupselect.selectedIndex; 398 | 399 | var group = groupselect[which].value; 400 | var inputbox = document.getElementById('profilegroup'); 401 | inputbox.value = ''; 402 | if ( group == 'New group ...' ) { 403 | inputbox.style.display = ''; 404 | } else { 405 | inputbox.style.display = 'none'; 406 | } 407 | // orderSelector.options[preset-1].selected = true; 408 | 409 | } // End of HandleGroupSelect 410 | 411 | function ConfirmNewType( current_type ) { 412 | var type_selector = document.profiletypeform.profile_type; 413 | var new_type = 0; 414 | for ( i=0; i<=3; i++ ) { 415 | if ( type_selector[i].checked ) 416 | new_type = type_selector[i].value; 417 | } 418 | 419 | current_shadow = (current_type & 4) > 0; 420 | new_shadow = (new_type & 4) > 0; 421 | current_type = current_type & 3; 422 | new_type = new_type & 3; 423 | 424 | var text = ''; 425 | // text = current_shadow + " " + new_shadow + " " + current_type + " " + new_type; 426 | 427 | if ( !current_shadow && new_shadow ) { 428 | text = "Please note:\nChanging the profile to a shadow profile will delete all profile data of this profile!"; 429 | } 430 | if ( current_type == 2 && new_type == 1 ) { 431 | text = text + "\nChanging the profile to a history profile will stop profiling data for this profile"; 432 | } 433 | if ( text != '' ) { 434 | text = text + "\nIs this ok?"; 435 | return confirm(text); 436 | } else { 437 | return true; 438 | } 439 | 440 | } // End of ConfirmNewType 441 | -------------------------------------------------------------------------------- /html/lookup.php: -------------------------------------------------------------------------------- 1 | 44 | 45 | 46 | 47 | Lookup: '<?php echo $lookup;?>' 48 | 49 | 50 | 51 | 52 | 53 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /html/navigator.php: -------------------------------------------------------------------------------- 1 | 0 ? ' / shadow' : ''; 29 | 30 | 31 | ?> 32 |
33 |

34 | 35 | 36 | 49 | 52 | 55 | 56 | 61 | 62 |
37 | 48 | 57 | 60 |
63 | 64 |
65 | 66 | 71 |

72 | 73 | 74 | 87 | 88 |
75 | 86 |
89 |
90 | 96 |

97 |

No plugins available!

98 |
99 | 102 |

103 | 104 | 105 | 118 | 119 |
106 | 117 |
120 |
121 | \n"; 125 | print "\n"; 156 | print "\n"; 157 | $bk = base64_decode(urldecode($_SESSION['bookmark'])); 158 | 159 | } // End of navigator 160 | 161 | -------------------------------------------------------------------------------- /html/overview.php: -------------------------------------------------------------------------------- 1 | Overview Profile: $profile, Group: (nogroup)\n"; 12 | else 13 | print "

Overview Profile: $profile, Group $profilegroup

\n"; 14 | 15 | if ( $_SESSION['profileinfo']['graphs'] != 'ok' ) { 16 | print "

No data available!

\n"; 17 | return; 18 | } 19 | 20 | $profileswitch = "$profilegroup/$profile"; 21 | print " flows-day\n"; 22 | print " packets-day\n"; 23 | print " traffic-day\n"; 24 | print "
"; 25 | print " flows-week\n"; 26 | print " packets-week\n"; 27 | print " traffic-week\n"; 28 | print "
"; 29 | print " flows-month\n"; 30 | print " packets-month\n"; 31 | print " traffic-month\n"; 32 | print "
"; 33 | print " flows-year\n"; 34 | print " packets-year\n"; 35 | print " traffic-year\n"; 36 | 37 | } // End of DisplayOverview 38 | 39 | function DisplayGraphs ($type) { 40 | 41 | global $self; 42 | 43 | $profile = $_SESSION['profile']; 44 | $profilegroup = $_SESSION['profilegroup']; 45 | 46 | if ( $profilegroup == '.' ) 47 | print "

Profile: $profile, Group: (nogroup) - $type

\n"; 48 | else 49 | print "

Profile: $profile, Group: $profilegroup - $type

\n"; 50 | 51 | if ( $_SESSION['profileinfo']['graphs'] != 'ok' ) { 52 | print "

No data available!

\n"; 53 | return; 54 | } 55 | 56 | $profileswitch = "$profilegroup/$profile"; 57 | print " \n"; 58 | print "
"; 59 | print " \n"; 60 | print "
"; 61 | print " \n"; 62 | print "
"; 63 | print " \n"; 64 | print "
"; 65 | 66 | } # End of DisplayHistory 67 | 68 | ?> 69 | -------------------------------------------------------------------------------- /html/pic.php: -------------------------------------------------------------------------------- 1 | 132 | -------------------------------------------------------------------------------- /html/process.php: -------------------------------------------------------------------------------- 1 | 0 ) 50 | return ' -A ' . implode(',', $aggregate); 51 | else 52 | return ''; 53 | 54 | } // End of CompileAggregateFormat 55 | 56 | function CompileOutputFormat($process_form) { 57 | 58 | global $is_bidir; 59 | 60 | $format = $process_form['output']; 61 | if ( $format == 'custom ...' ) { 62 | $formatdef = $process_form['customfmt']; 63 | } else { 64 | $formatdef = $_SESSION['formatlist'][$format]; 65 | } 66 | if ( $format == 'auto') 67 | return ""; 68 | if ( $format == $formatdef ) { 69 | if ( $is_bidir ) 70 | return " -o bi$format"; 71 | else 72 | return " -o $format"; 73 | } else { 74 | $formatdef = escapeshellarg("fmt:$formatdef"); 75 | return " -o $formatdef"; 76 | } 77 | 78 | } // End of CompileOutputFormat 79 | 80 | function CompileCommand($mode) { 81 | 82 | global $ListNOption; 83 | global $TopNOption; 84 | global $IPStatOption; 85 | global $IPStatOrder; 86 | global $IPStatArg; 87 | global $LimitScale; 88 | global $OutputFormatArg; 89 | 90 | $process_form = $_SESSION['process_form'] ; 91 | $profile = $_SESSION['profile']; 92 | $profilegroup = $_SESSION['profilegroup']; 93 | 94 | // get the sources selected for processing 95 | $args = ''; 96 | 97 | // From the argument checks, we know at least one source is selected 98 | // multiple sources 99 | if ( $_SESSION['tleft'] == $_SESSION['tright'] ) { 100 | // a single 5 min timeslice 101 | $tslot1 = UNIX2ISO($_SESSION['tleft']); 102 | $subdirs = SubdirHierarchy($_SESSION['tleft']); 103 | if ( strlen($subdirs) == 0 ) 104 | $args .= " -r nfcapd.$tslot1"; 105 | else 106 | $args .= " -r $subdirs/nfcapd.$tslot1"; 107 | 108 | } else { 109 | // several 5 min timeslices 110 | $tslot1 = UNIX2ISO($_SESSION['tleft']); 111 | $subdirs1 = SubdirHierarchy($_SESSION['tleft']); 112 | $tslot2 = UNIX2ISO($_SESSION['tright']); 113 | $subdirs2 = SubdirHierarchy($_SESSION['tright']); 114 | if ( strlen($subdirs1) == 0 ) 115 | $args .= " -R nfcapd.$tslot1:nfcapd.$tslot2"; 116 | else 117 | $args .= " -R $subdirs1/nfcapd.$tslot1:$subdirs2/nfcapd.$tslot2"; 118 | } 119 | 120 | // process list request 121 | if ( $mode == 0 ) { 122 | $_tmp = CompileAggregateFormat($process_form); 123 | if ( $_tmp != '' ) { 124 | $args .= " -a $_tmp"; 125 | } 126 | // process list request 127 | $args .= CompileOutputFormat($process_form); 128 | // IPv6 long listing 129 | $args .= $process_form['IPv6_long'] == 'checked' ? " -6" : ''; 130 | // sort the flows from all sources 131 | $args .= $process_form['timesorted'] == 'checked' ? " -m" : ''; 132 | // list this number of flows 133 | $args .= " -c " . $ListNOption[$process_form['listN']]; 134 | } 135 | 136 | // process stat request 137 | if ( $mode == 1 ) { 138 | $args .= " -n " . $TopNOption[$process_form['topN']]; 139 | // -s record 140 | $type_index = $process_form['stattype']; 141 | $order_index = $process_form['statorder']; 142 | $args .= ' ' . $IPStatArg[$type_index] . '/' . $IPStatOrder[$order_index]; 143 | 144 | if ( $process_form['stattype'] == 0 ) { 145 | $args .= CompileAggregateFormat($process_form); 146 | $args .= CompileOutputFormat($process_form); 147 | } 148 | // IPv6 long listing 149 | $args .= $process_form['IPv6_long'] == 'checked' ? " -6" : ''; 150 | 151 | // limits -L/-l 152 | if ( $process_form['limitoutput'] == 'checked' ) { 153 | $args .= $process_form['limitwhat'] == 1 ? " -L " : " -l "; 154 | if ( $process_form['limithow'] == 1 ) 155 | $args .= '-'; 156 | $args .= $process_form['limitsize']; 157 | if ( $process_form['limitscale'] > 0 ) 158 | $args .= $LimitScale[$process_form['limitscale']]; 159 | } 160 | } 161 | 162 | return "$args"; 163 | 164 | } // End of CompileCommand 165 | 166 | 167 | ?> 168 | -------------------------------------------------------------------------------- /html/rrdgraph.php: -------------------------------------------------------------------------------- 1 | $dummy ) { 51 | if ( array_key_exists($getparam, $_GET) ) { 52 | $opts[$getparam] = $_GET[$getparam]; 53 | } 54 | } 55 | if ( array_key_exists('argref', $_GET) ) { 56 | $ref = urldecode($_GET['argref']); 57 | ReportLog("rrdgraph argref $ref found"); 58 | $arglist = explode(' ', $_SESSION[$ref]); 59 | } else { 60 | $arglist = explode(' ', urldecode($_GET['arg'])); 61 | } 62 | $opts['.silent'] = 1; 63 | foreach ( $arglist as $arg ) { 64 | $opts['arg'][] = $arg; 65 | } 66 | 67 | header("Content-type: image/png"); 68 | nfsend_query("@$command", $opts, 1); 69 | nfsend_disconnect(); 70 | unset($_SESSION['nfsend']); 71 | CloseLogFile(); 72 | 73 | ?> 74 | -------------------------------------------------------------------------------- /installer-items/CopyRecursive.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # 4 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # * Neither the name of SWITCH nor the names of its contributors may be 16 | # used to endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | # POSSIBILITY OF SUCH DAMAGE. 30 | # 31 | # $Author: peter $ 32 | # 33 | # $Id: CopyRecursive.pm 27 2011-12-29 12:53:29Z peter $ 34 | # 35 | # $LastChangedRevision: 27 $ 36 | 37 | package CopyRecursive; 38 | 39 | use strict; 40 | use warnings; 41 | 42 | use Carp; 43 | use File::Copy; 44 | use File::Spec; #not really needed because File::Copy already gets it, but for good measure :) 45 | 46 | require Exporter; 47 | our @ISA = qw(Exporter); 48 | our @EXPORT_OK = qw(fcopy rcopy dircopy); 49 | our $VERSION = '0.06'; 50 | sub VERSION { $VERSION; } 51 | 52 | our $MaxDepth = 0; 53 | our $KeepMode = 1; 54 | our $UID = undef; 55 | our $GID = undef; 56 | our $MODE = undef; 57 | our $CopyLink = eval { symlink '',''; 1 } || 0; 58 | 59 | sub fcopy { 60 | if(-l $_[0] && $CopyLink) { 61 | symlink readlink(shift()), shift() or return; 62 | } else { 63 | copy(@_) or return; 64 | chmod scalar((stat($_[0]))[2]), $_[1] if $KeepMode; 65 | chown $UID, $GID, $_[1] if ( defined $UID and defined $GID ); 66 | chmod $MODE, $_[1] if defined $MODE; 67 | } 68 | return wantarray ? (1,0,0) : 1; # use 0's in case they do math on them and in case rcopy() is called in list context = no uninit val warnings 69 | } 70 | 71 | sub rcopy { -d $_[0] ? dircopy(@_) : fcopy(@_) } 72 | 73 | sub dircopy { 74 | croak "$_[0] and $_[1] are the same" if $_[0] eq $_[1]; 75 | croak "$_[0] is not a directory" if !-d $_[0]; 76 | croak "$_[1] is not a directory" if -e $_[1] && !-d $_[1]; 77 | 78 | if ( ! -d $_[1] ) { 79 | mkdir $_[1]; 80 | chown $UID, $GID, $_[1] if ( defined $UID and defined $GID ); 81 | } 82 | if ( ! -d $_[1] ) { 83 | my @dirs = split '/', $_[1]; 84 | my $mkpath = ''; 85 | foreach my $dir ( @dirs ) { 86 | $mkpath = "$mkpath$dir/"; 87 | if ( ! -d $mkpath ) { 88 | mkdir $mkpath unless -d $mkpath; 89 | chown $UID, $GID, $mkpath if ( defined $UID and defined $GID ); 90 | } 91 | } 92 | } 93 | return if !-d $_[1]; 94 | 95 | my $baseend = $_[1]; 96 | my $level = 0; 97 | my $filen = 0; 98 | my $dirn = 0; 99 | 100 | my $recurs; #must be my()ed before sub {} since it calls itself 101 | $recurs = sub { 102 | my ($str,$end,$buf) = @_; 103 | $filen++ if $end eq $baseend; 104 | $dirn++ if $end eq $baseend; 105 | if ( ! -d $end ) { 106 | mkdir $end or return if !-d $end; 107 | chown $UID, $GID, $end if ( defined $UID and defined $GID ); 108 | chmod scalar((stat($str))[2]), $end if $KeepMode; 109 | } 110 | if($MaxDepth && $MaxDepth =~ m/^\d+$/ && $level >= $MaxDepth) { 111 | return ($filen,$dirn,$level) if wantarray; 112 | return $filen; 113 | } 114 | $level++; 115 | 116 | opendir DIRH, $str or return; 117 | my @files = grep( $_ ne "." && $_ ne "..", readdir(DIRH)); 118 | closedir DIRH; 119 | 120 | for(@files) { 121 | my $org = File::Spec->catfile($str,$_); 122 | my $new = File::Spec->catfile($end,$_); 123 | unlink $new; 124 | if(-d $org) { 125 | $recurs->($org,$new,$buf) if defined $buf; 126 | $recurs->($org,$new) if !defined $buf; 127 | $filen++; 128 | $dirn++; 129 | } elsif(-l $org && $CopyLink) { 130 | if ( !symlink readlink($org), $new ) { 131 | warn "symlink failed for '$org': $!\n"; 132 | return; 133 | } 134 | } else { 135 | copy($org,$new,$buf) or return if defined $buf; 136 | copy($org,$new) or return if !defined $buf; 137 | chmod scalar((stat($org))[2]), $new if $KeepMode; 138 | chown $UID, $GID, $new if ( defined $UID and defined $GID ); 139 | chmod $MODE, $new if defined $MODE; 140 | $filen++; 141 | } 142 | } 143 | }; 144 | 145 | $recurs->(@_); 146 | return ($filen,$dirn,$level) if wantarray; 147 | return $filen; 148 | } 149 | 1; 150 | __END__ 151 | 152 | =head1 NAME 153 | 154 | File::Copy::Recursive - Perl extension for recursively copying files and directories 155 | 156 | =head1 SYNOPSIS 157 | 158 | use File::Copy::Recursive qw(fcopy rcopy dircopy); 159 | 160 | fcopy($orig,$new[,$buf]) or die $!; 161 | rcopy($orig,$new[,$buf]) or die $!; 162 | dircopy($orig,$new[,$buf]) or die $!; 163 | 164 | =head1 DESCRIPTION 165 | 166 | This module copies directories recursively (or single files, well... singley) to an optional depth and attempts to preserve each file or directory's mode. 167 | 168 | =head2 EXPORT 169 | 170 | None by default. But you can export all the functions as in the example above. 171 | 172 | =head2 fcopy() 173 | 174 | This function uses File::Copy's copy() function to copy a file but not a directory. 175 | One difference to File::Copy::copy() is that fcopy attempts to preserve the mode (see Preserving Mode below) 176 | The optional $buf in the synopsis if the same as File::Copy::copy()'s 3rd argument 177 | returns the same as File::Copy::copy() in scalar context and 1,0,0 in list context to accommodate rcopy()'s list context on regular files. (See below for more info) 178 | 179 | =head2 dircopy() 180 | 181 | This function recursively traverses the $orig directory's structure and recursively copies it to the $new directory. 182 | $new is created if necessary. 183 | It attempts to preserve the mode (see Preserving Mode below) and 184 | by default it copies all the way down into the directory, (see Managing Depth) below. 185 | If a directory is not specified it croaks just like fcopy croaks if its not a file that is specified. 186 | 187 | returns true or false, for true in scalar context it returns the number of files and directories copied, 188 | In list context it returns the number of files and directories, number of directories only, depth level traversed. 189 | 190 | my $num_of_files_and_dirs = dircopy($orig,$new); 191 | my($num_of_files_and_dirs,$num_of_dirs,$depth_traversed) = dircopy($orig,$new); 192 | 193 | =head2 rcopy() 194 | 195 | This function will allow you to specify a file *or* directory. It calls fcopy() if its a file and dircopy() if its a directory. 196 | If you call rcopy() (or fcopy() for that matter) on a file in list context, the values will be 1,0,0 since no directories and no depth are used. 197 | This is important because if its a directory in list context and there is only the initial directory the return value is 1,1,1. 198 | 199 | =head2 Preserving Mode 200 | 201 | By default a quiet attempt is made to change the new file or directory to the mode of the old one. 202 | To turn this behavior off set 203 | $File::Copy::Recursive::KeepMode 204 | to false; 205 | 206 | =head2 Managing Depth 207 | 208 | You can set the maximum depth a directory structure is recursed by setting: 209 | $File::Copy::Recursive::MaxDepth 210 | to a whole number greater than 0. 211 | 212 | =head2 SymLinks 213 | 214 | If your system supports symlinks then symlinks will be copied as symlinks instead of as the target file. 215 | Perl's symlink() is used instead of File::Copy's copy() 216 | You can customize this behavior by setting $File::Copy::Recursive::CopyLink to a true or false value. 217 | It is already set to true or false dending on your system's support of symlinks so you can check it with an if statement to see how it will behave: 218 | 219 | 220 | if($File::Copy::Recursive::CopyLink) { 221 | print "Symlinks will be preserved\n"; 222 | } else { 223 | print "Symlinks will not be preserved because your system does not support it\n"; 224 | } 225 | 226 | =head1 SEE ALSO 227 | 228 | L L 229 | 230 | =head1 AUTHOR 231 | 232 | Daniel Muey, L 233 | 234 | =head1 COPYRIGHT AND LICENSE 235 | 236 | Copyright 2004 by Daniel Muey 237 | 238 | This library is free software; you can redistribute it and/or modify 239 | it under the same terms as Perl itself. 240 | 241 | =cut 242 | 243 | -------------------------------------------------------------------------------- /installer-items/RRDconvertv1.pm: -------------------------------------------------------------------------------- 1 | # Redistribution and use in source and binary forms, with or without 2 | # modification, are permitted provided that the following conditions are met: 3 | # 4 | # * Redistributions of source code must retain the above copyright notice, 5 | # this list of conditions and the following disclaimer. 6 | # * Redistributions in binary form must reproduce the above copyright notice, 7 | # this list of conditions and the following disclaimer in the documentation 8 | # and/or other materials provided with the distribution. 9 | # * Neither the name of SWITCH nor the names of its contributors may be 10 | # used to endorse or promote products derived from this software without 11 | # specific prior written permission. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 17 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | # POSSIBILITY OF SUCH DAMAGE. 24 | # 25 | # $Author: peter $ 26 | # 27 | # $Id: RRDconvertv1.pm 27 2011-12-29 12:53:29Z peter $ 28 | # 29 | # $LastChangedRevision: 27 $ 30 | 31 | package RRDconvertv1; 32 | 33 | use strict; 34 | use warnings; 35 | use Data::Dumper; 36 | use RRDs; 37 | use NfSenRRD; 38 | 39 | ########################## 40 | # 41 | # Main 42 | # 43 | ########################## 44 | 45 | my $rrdtool = ''; 46 | 47 | my %rrd_array; 48 | my @timevec; 49 | my @progress = ( '|', '/', '-', '\\' ); 50 | 51 | sub ConvertDBs { 52 | my $profilename = shift; 53 | 54 | my $index = 0; 55 | 56 | %rrd_array = (); 57 | @timevec = (); 58 | 59 | my $j = 0; 60 | $| = 1; 61 | foreach my $rrd_db ( @NfSenRRD::RRD_DS ) { 62 | print "Convert DBs: ", $progress[$index & 0x3], "\r"; 63 | $index++; 64 | 65 | open DB, "$NfConf::PROFILESTATDIR/$profilename/$rrd_db.xml" or die "Can't open rrd DB '${rrd_db}.xml': $!\n"; 66 | 67 | # wait for tag 68 | while () { 69 | next unless $_ =~ //; 70 | last; 71 | } 72 | 73 | # parse all available 74 | my @DS; 75 | my $in_ds = 0; 76 | while () { 77 | last if $_ =~ //; # last if we found the rra section 78 | if ( $in_ds ) { 79 | if ( $_ =~ /\s*([^\s]+)\s*<\/name>/ ) { 80 | push @DS, $1; 81 | next; 82 | } 83 | next unless $_ =~ /<\/ds>/; 84 | # found 85 | $in_ds = 0; 86 | } else { 87 | next unless $_ =~ //; 88 | # found 89 | $in_ds = 1; 90 | } 91 | } 92 | # foreach my $ds ( @DS ) { 93 | # print "$ds\n"; 94 | # } 95 | 96 | my $in_database = 0; 97 | 98 | while () { 99 | if ( $in_database ) { 100 | if ( $_ =~ /<\/database>/ ) { 101 | $in_database = 0; 102 | next; 103 | } 104 | # 105 | my ($time, $row); 106 | ($time) = $_ =~ /\/\s+(\d+)\s+-->/; 107 | next unless $time; 108 | 109 | # 1.4246717527e+07 6.2968940970e+07 6.5416970767e+06 7.089098 1553e+07 110 | # NaN NaN NaN NaN 111 | ($row) = $_ =~ /\s*(.+)\s*<\/row>/; 112 | next unless $row; 113 | 114 | # remove value tags 115 | $row =~ s/|<\/v>/ /g; 116 | $row =~ s/^\s*//; 117 | $row =~ s/\s*$//; 118 | 119 | # split values 120 | my @values; 121 | @values = split /\s+/, $row; 122 | 123 | # collect time values during first loop 124 | # skip rows not containing a number 125 | my $all_NaN = 1; 126 | foreach my $val ( @values) { 127 | $all_NaN = 0 if $val ne 'NaN' 128 | } 129 | next if $all_NaN; 130 | 131 | # rearrange values 132 | for(my $i=0; $i< scalar @values; $i++ ) { 133 | my $ds = $DS[$i]; 134 | next if defined $rrd_array{$ds}{$time}[$j]; 135 | 136 | if ( $j == 0 ) { 137 | push @timevec, $time; 138 | } 139 | 140 | if ( $values[$i] ne 'NaN' ) { 141 | $rrd_array{$ds}{$time}[$j] = sprintf("%.0f", 300 * $values[$i]); # rounded value 142 | } 143 | } 144 | } else { 145 | if ( $_ =~ // ) { 146 | $in_database = 1; 147 | next; 148 | } 149 | } 150 | } 151 | close DB; 152 | $j++; 153 | } 154 | @timevec = sort {$a <=> $b} @timevec; 155 | 156 | print "Convert DBs: done.\n"; 157 | 158 | } # End of ConvertDBs 159 | 160 | sub CreateNewRRD { 161 | my $profilename = shift; 162 | 163 | my $index = 0; 164 | 165 | my ($login,$pass,$uid,$gid) = getpwnam($NfConf::WWWUSER); 166 | if ( !defined $login ) { 167 | die "NFSEN user '$NfConf::WWWUSER' not found on this system\n"; 168 | } 169 | 170 | if ( defined $NfConf::WWWGROUP ) { 171 | $gid = getgrnam($NfConf::WWWGROUP) || 172 | die "NFSEN group '$NfConf::WWWGROUP' not found on this system\n"; 173 | } 174 | 175 | my %profileinfo = NfProfile::ReadProfile($profilename); 176 | if ( $profileinfo{'status'} eq 'empty' ) { 177 | print "Error Reading profile '$profilename'. Abort conversion\n"; 178 | return 0; 179 | } 180 | 181 | # sort entries in profileinfo 182 | my @ProfileSources = keys %{$profileinfo{'channel'}}; 183 | 184 | my $start_time = $timevec[0]; 185 | foreach my $source ( @ProfileSources ) { 186 | if ( !exists($rrd_array{$source}) ) { 187 | print "==> Configured source '$source' does not exist in RRD\n"; 188 | print "Abort creating DBs\n"; 189 | return 0; 190 | } 191 | NfSenRRD::SetupRRD("$NfConf::PROFILESTATDIR/$profilename", $source, $start_time - 300, 1); 192 | chown $uid, $gid, "$NfConf::PROFILESTATDIR/$profilename/$source.rrd"; 193 | } 194 | 195 | $| = 1; 196 | my $num = 0; 197 | foreach my $ds ( @ProfileSources ) { 198 | my $lasttime = $timevec[0] - 1; 199 | 200 | for ( my $i=0; $i < scalar @timevec; $i++ ) { 201 | my $time = $timevec[$i]; 202 | next if ( $time <= $lasttime ); 203 | 204 | if ( ( $num & 0xFF ) == 0 ) { 205 | print "Writing new DBs: ", $progress[$index & 0x3], "\r"; 206 | $index++; 207 | } 208 | $num++; 209 | 210 | # timegap - need to feed rrd with intermediate values 211 | my $values = $rrd_array{$ds}{$time}; 212 | 213 | if ( ($time - $lasttime) > 300 ) { 214 | my $t = $lasttime + 300; 215 | my $_ds = join(':',@NfSenRRD::RRD_DS); 216 | my $_val = join(':', @$values); 217 | while ( $t < $time ) { 218 | my $err = NfSenRRD::UpdateDB("$NfConf::PROFILESTATDIR/$profilename", $ds, $t, $_ds , $_val); 219 | if ( $Log::ERROR ) { 220 | print("ERROR Update RRD: $Log::ERROR\n"); 221 | } 222 | $t += 300; 223 | 224 | if ( ( $num & 0xFF ) == 0 ) { 225 | print "Writing new DBs: ", $progress[$index & 0x3], "\r"; 226 | $index++; 227 | } 228 | $num++; 229 | 230 | } 231 | } 232 | my $err = NfSenRRD::UpdateDB("$NfConf::PROFILESTATDIR/$profilename", $ds, $time, 233 | join(':',@NfSenRRD::RRD_DS) , join(':', @$values)); 234 | if ( $Log::ERROR ) { 235 | print("ERROR Update RRD: $Log::ERROR\n"); 236 | } 237 | $lasttime = $time; 238 | } 239 | 240 | } 241 | print "Writing new DBs: done.\n"; 242 | 243 | return 1; 244 | 245 | } # End of CreateNewRRD 246 | 247 | sub UpdateProfile { 248 | my $profilename = shift; 249 | my $rrdtool = shift; 250 | 251 | # backport from snapshot 252 | my $index = 0; 253 | print "Update profile '$profilename' \n"; 254 | 255 | foreach my $rrd_db ( @NfSenRRD::RRD_DS ) { 256 | print "Dump RRD: ", $progress[$index & 0x3], "\r"; 257 | $index++; 258 | system("$rrdtool dump $NfConf::PROFILESTATDIR/$profilename/$rrd_db.rrd > $NfConf::PROFILESTATDIR/$profilename/$rrd_db.xml"); 259 | my $exit_value = $? >> 8; 260 | my $signal_num = $? & 127; 261 | my $dumped_core = $? & 128; 262 | if ( $exit_value != 0 ) { 263 | print "\nrrdtool exec error: exit: $exit_value, signal: $signal_num, coredump: $dumped_core\n"; 264 | return 0; 265 | } 266 | } 267 | print "Dump RRD: done\n"; 268 | my $ret = 0; 269 | ConvertDBs($profilename); 270 | $ret = CreateNewRRD($profilename); 271 | 272 | foreach my $rrd_db ( @NfSenRRD::RRD_DS ) { 273 | unlink "$NfConf::PROFILESTATDIR/$profilename/$rrd_db.xml"; 274 | unlink "$NfConf::PROFILESTATDIR/$profilename/$rrd_db.rrd" if $ret; 275 | } 276 | 277 | return $ret; 278 | 279 | } # End of UpdateProfile 280 | 281 | 1; 282 | 283 | -------------------------------------------------------------------------------- /libexec/Log.pm: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011, Peter Haag 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # * Neither the name of the author nor the names of its contributors may be 14 | # used to endorse or promote products derived from this software without 15 | # specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | # POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # $Author: peter $ 30 | # 31 | # $Id: Log.pm 27 2011-12-29 12:53:29Z peter $ 32 | # 33 | # $LastChangedRevision: 27 $ 34 | 35 | package Log; 36 | 37 | use strict; 38 | use warnings; 39 | 40 | use Sys::Syslog; 41 | 42 | use NfConf; 43 | 44 | our $ERROR; 45 | 46 | my $log_book = undef; 47 | 48 | sub LogInit { 49 | 50 | Sys::Syslog::setlogsock($NfConf::LogSocket) if defined $NfConf::LogSocket; 51 | openlog("nfsen", 'cons,pid', $NfConf::syslog_facility); 52 | 53 | } # End of LogInit 54 | 55 | sub LogEnd { 56 | closelog(); 57 | 58 | } # End of LogEnd 59 | 60 | sub StartLogBook { 61 | $log_book = shift; 62 | } # End of SetLogBook 63 | 64 | sub EndLogBook { 65 | $log_book = undef; 66 | } # End of EndLogBook 67 | 68 | sub TIEHANDLE { 69 | my $class = shift; 70 | my $name = shift; 71 | 72 | my %self; 73 | $self{'facility'} = $NfConf::syslog_facility; 74 | 75 | bless \%self, $class; 76 | 77 | } # End of TIEHANDLE 78 | 79 | sub PRINT { 80 | my $self = shift; 81 | my $msg = join '', @_; 82 | 83 | if ( defined $log_book ) { 84 | push @{$log_book}, $msg; 85 | } 86 | syslog('warning', "$msg"); 87 | } 88 | 89 | sub UNTIE { 90 | my $self = shift; 91 | 92 | } # End of UNTIE 93 | 94 | 1; 95 | -------------------------------------------------------------------------------- /libexec/Lookup.pm: -------------------------------------------------------------------------------- 1 | #!%%PERL%% 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: Lookup.pm 61 2014-04-03 09:33:20Z peter $ 33 | # 34 | # $LastChangedRevision: 61 $ 35 | 36 | package Lookup; 37 | 38 | use strict; 39 | use warnings; 40 | use Socket; 41 | use IO::Socket::INET; 42 | use Socket; 43 | use AbuseWhois; 44 | use Log; 45 | 46 | sub Lookup { 47 | my $socket = shift; 48 | my $opts = shift; 49 | 50 | if ( !exists $$opts{'lookup'} ) { 51 | print $socket "

Missing lookup parameter

\n"; 52 | return; 53 | } 54 | my $lookup = $$opts{'lookup'}; 55 | 56 | my ($ip, $port); 57 | # IPv4/port 58 | if ( $lookup =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/ ) { 59 | $ip = $1; 60 | $port = $2; 61 | # IPv4 ICMP 62 | } elsif ( $lookup =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+\.\d+)/ ) { 63 | $ip = $1; 64 | $port = $2; 65 | # IPv4 66 | } elsif ( $lookup =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ ) { 67 | $ip = $1; 68 | $port = 0; 69 | # IPv6/port 70 | } elsif ( $lookup =~ /^([0-9a-f]+[0-9a-f:]+)\.(\d{1,5})/ ) { 71 | $ip = $1; 72 | # IPv6 ICMP 73 | } elsif ( $lookup =~ /^([0-9a-f]+[0-9a-f:]+)\.(\d+\.\d+)/ ) { 74 | $ip = $1; 75 | # IPv6 76 | } elsif ( $lookup =~ /^([0-9a-f]+[0-9a-f:]+)/ ) { 77 | $ip = $1; 78 | $port = 0; 79 | } elsif ( $lookup =~ /^([0-9a-f]+[0-9a-f:]+\.\.[0-9a-f:]+)/ ) { 80 | print $socket "Use IPv6 long format for IPv6lookup
"; 81 | return; 82 | } else { 83 | print $socket "Can not decode IP address
"; 84 | return; 85 | } 86 | 87 | # print $socket "Port: $port
"; 88 | 89 | AbuseWhois::Query($socket, $ip); 90 | 91 | } # End of Lookup 92 | 93 | 1; 94 | -------------------------------------------------------------------------------- /libexec/NfConf.pm: -------------------------------------------------------------------------------- 1 | #!%%PERL%% 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: NfConf.pm 69 2014-06-23 19:27:50Z peter $ 33 | # 34 | # $LastChangedRevision: 69 $ 35 | 36 | package NfConf; 37 | 38 | use strict; 39 | use Log; 40 | use Scalar::Util qw(looks_like_number); 41 | 42 | our $BASEDIR; 43 | our $BINDIR; 44 | our $LIBEXECDIR; 45 | our $CONFDIR; 46 | our $DOCDIR; 47 | our $VARDIR; 48 | our $PROFILEDATADIR; 49 | our $PROFILESTATDIR; 50 | our $PLUGINDIR; 51 | our $PREFIX; 52 | our $USER; 53 | our $GROUP; 54 | our $WWWUSER; 55 | our $WWWGROUP; 56 | our $BUFFLEN; 57 | our $SUBDIRLAYOUT; 58 | our $DISKLIMIT; 59 | our $PROFILERS; 60 | our $COMMSOCKET; 61 | our %sources; 62 | our %sim; 63 | our %plugins; 64 | our %PluginConf; 65 | our $HTMLDIR; 66 | our $low_water; 67 | our $syslog_facility; 68 | our $ZIPcollected; 69 | our $ZIPprofiles; 70 | our $InterruptExpire; 71 | our $EXTENSIONS; 72 | our $PIDDIR; 73 | our $FILTERDIR; 74 | our $FORMATDIR; 75 | our $DEBUG; 76 | our $AllowsSystemCMD; 77 | our $SIMmode; 78 | our $Refresh; 79 | our $PERL_HAS_MEMLEAK; 80 | our $BACKEND_PLUGINDIR; 81 | our $PICDIR; 82 | our $NFPROFILEOPTS; 83 | our $NFEXPIREOPTS; 84 | 85 | # Alerting email vars 86 | our $MAIL_FROM; 87 | our $MAIL_BODY; 88 | our $SMTP_SERVER; 89 | 90 | our $RRDoffset; 91 | our $UID; 92 | our $GID; 93 | our $LogSocket; 94 | 95 | our $CYCLETIME; 96 | 97 | # 98 | # Loads the config from nfsen.conf file 99 | # returns 1 on success. 100 | # returns undef if failed. Set Log:ERROR 101 | sub LoadConfig { 102 | my $InitConfigFile = shift; 103 | 104 | my $CONFFILE = defined $InitConfigFile ? $InitConfigFile : "%%CONFDIR%%/nfsen.conf"; 105 | $CONFFILE = "./$CONFFILE" unless substr($CONFFILE, 0, 1) eq "/"; 106 | if ( !-f "$CONFFILE" ) { 107 | $Log::ERROR = "No NFSEN config file found."; 108 | return undef; 109 | } 110 | 111 | # preset default values: 112 | $CYCLETIME = 300; 113 | $DEBUG = 0; 114 | $BASEDIR = undef; 115 | $BINDIR = undef; 116 | $LIBEXECDIR = undef; 117 | $CONFDIR = undef; 118 | $DOCDIR = undef; 119 | $VARDIR = undef; 120 | $PROFILEDATADIR = undef; 121 | $PROFILESTATDIR = undef; 122 | $PLUGINDIR = undef; 123 | $PREFIX = '/usr/local/bin'; 124 | $USER = 'nobody'; 125 | $GROUP = undef; 126 | $WWWUSER = $USER; 127 | $WWWGROUP = 'www'; 128 | $BUFFLEN = undef; 129 | $EXTENSIONS = undef; 130 | $SUBDIRLAYOUT = 0; 131 | $DISKLIMIT = 98; 132 | $PROFILERS = 1; 133 | $COMMSOCKET = undef; 134 | %sources = (); 135 | %sim = (); 136 | %PluginConf = (); 137 | $HTMLDIR = "/var/www/htdocs/nfsen"; 138 | $low_water = 90; 139 | $syslog_facility = 'local3'; 140 | $RRDoffset = 0; 141 | $SIMmode = 0; 142 | $Refresh = $CYCLETIME; 143 | $AllowsSystemCMD = 0; 144 | $PICDIR = undef; 145 | $FILTERDIR = undef; 146 | $FORMATDIR = undef; 147 | 148 | $MAIL_FROM = undef; 149 | $MAIL_BODY = q{Alert '@alert@' triggered at timeslot @timeslot@}; 150 | $SMTP_SERVER = ''; 151 | 152 | $ZIPcollected = "-z=lz4"; 153 | $ZIPprofiles = "-z=lz4"; 154 | $InterruptExpire = 0; 155 | 156 | $NFPROFILEOPTS = ''; 157 | $NFEXPIREOPTS = ''; 158 | 159 | $PERL_HAS_MEMLEAK = 0; 160 | 161 | my $log_type = $^V =~ /5.10/ ? 'native' : 'unix'; 162 | 163 | $LogSocket = $^O eq "solaris" ? 'stream' : $log_type; 164 | 165 | # Read Configuration 166 | if ( ! open( TMP, $CONFFILE) ) { 167 | die "Can't read config file '$CONFFILE': $!\n"; 168 | } 169 | close TMP; 170 | 171 | if ( !do $CONFFILE ) { 172 | $Log::ERROR = "Errors in config file: $@"; 173 | return undef; 174 | } 175 | 176 | if ( defined $BASEDIR && ! -d $BASEDIR && defined $InitConfigFile ) { 177 | mkdir $BASEDIR or 178 | $Log::ERROR = "Can not create BASEDIR '$BASEDIR': $!", 179 | return undef; 180 | } 181 | 182 | if ( defined $BASEDIR && ! -d $BASEDIR ) { 183 | $Log::ERROR = "Config seems to be buggy. BASEDIR '$BASEDIR' not found!"; 184 | return undef; 185 | } 186 | 187 | if ( !defined $VARDIR ) { 188 | $VARDIR = "$BASEDIR/var"; 189 | } 190 | 191 | if ( !defined $PIDDIR ) { 192 | $PIDDIR = "$VARDIR/run"; 193 | } 194 | 195 | if ( !defined $FILTERDIR ) { 196 | $FILTERDIR = "$VARDIR/filters"; 197 | } 198 | 199 | if ( !defined $FORMATDIR ) { 200 | $FORMATDIR = "$VARDIR/fmt"; 201 | } 202 | 203 | if ( !defined $COMMSOCKET ) { 204 | $COMMSOCKET = "$PIDDIR/nfsen.comm"; 205 | } 206 | 207 | if ( !defined $PICDIR ) { 208 | $PICDIR = $BACKEND_PLUGINDIR; 209 | } 210 | 211 | if ( !defined $EXTENSIONS ) { 212 | $EXTENSIONS = ''; 213 | } else { 214 | $EXTENSIONS = "-T $EXTENSIONS"; 215 | } 216 | 217 | my ($login,$pass,$uid,$gid) = getpwnam($USER); 218 | if ( !defined $login ) { 219 | $Log::ERROR = "NFSEN user '$USER' not found on this system "; 220 | return undef; 221 | } 222 | 223 | $UID = $uid; 224 | if ( defined $WWWGROUP ) { 225 | $gid = getgrnam($WWWGROUP); 226 | if ( !defined $gid ) { 227 | $Log::ERROR = "NFSEN group '$WWWGROUP' not found on this system "; 228 | return undef; 229 | } 230 | } 231 | $GID = $gid; 232 | 233 | if ( !defined $ZIPprofiles ) { 234 | $ZIPprofiles = ""; 235 | } elsif ( looks_like_number($ZIPprofiles)) { 236 | # in case $ZIPprofiles = 1; 237 | $ZIPprofiles = "-z=lz4"; 238 | } 239 | 240 | if ( !defined $ZIPcollected ) { 241 | $ZIPcollected = ""; 242 | } elsif ( looks_like_number($ZIPcollected)) { 243 | # in case $ZIPcollected = 1; 244 | $ZIPcollected = "-z=lz4"; 245 | } 246 | 247 | $Log::ERROR = undef ; 248 | return 1; 249 | 250 | } # End of LoadConfig 251 | 252 | 1; 253 | -------------------------------------------------------------------------------- /libexec/NfSenRC.pm: -------------------------------------------------------------------------------- 1 | #!%%PERL%% 2 | # 3 | # Copyright (c) 2022, Peter Haag 4 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # * Neither the name of SWITCH nor the names of its contributors may be 16 | # used to endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | # POSSIBILITY OF SUCH DAMAGE. 30 | # 31 | 32 | package NfSenRC; 33 | 34 | use strict; 35 | use warnings; 36 | use NfSen; 37 | use Nfsources; 38 | use Log; 39 | 40 | # public map for collector mappings - more may be added in future 41 | our %CollectorMap = ( 42 | 'netflow' => 'nfcapd', 43 | 'sflow' => 'sfcapd', 44 | 'pcap' => 'nfpcapd', 45 | ); 46 | 47 | sub StartCollector { 48 | my $port = shift; 49 | 50 | # sim mode 51 | if ( $port == 0 ) { 52 | print "[no collector]"; 53 | return; 54 | } 55 | my @SourceList; 56 | my $type = undef; 57 | foreach my $source ( sort keys %NfConf::sources ) { 58 | my $_port = $NfConf::sources{$source}{'port'}; 59 | if ( $_port == $port ) { 60 | push @SourceList, $source; 61 | my $_type = exists $NfConf::sources{$source}{'type'} ? $NfConf::sources{$source}{'type'}: 'netflow'; 62 | if ( defined $type ) { 63 | if ( $type ne $_type ) { 64 | print "Can not start different type '$type' and '$_type' on same port!\n"; 65 | return; 66 | } 67 | } else { 68 | $type = $_type; 69 | } 70 | } 71 | } 72 | 73 | print "("; 74 | print join ' ', @SourceList; 75 | print ")"; 76 | 77 | # prepare args with first source 78 | my $collector = $CollectorMap{$type}; 79 | 80 | my $uid = $NfConf::USER; 81 | my $gid = $NfConf::WWWGROUP ? "$NfConf::WWWGROUP" : ""; 82 | my $nfdump_version = $$NfSen::hints{'nfdump'}; 83 | my $buffer_opts = $NfConf::BUFFLEN ? "-B $NfConf::BUFFLEN" : ""; 84 | my $subdirlayout = $NfConf::SUBDIRLAYOUT ? "-S $NfConf::SUBDIRLAYOUT" : ""; 85 | my $pidfile = "$NfConf::PIDDIR/p${port}.pid"; 86 | my $twin = "-t 300"; 87 | my $extensions = ""; 88 | if ( $nfdump_version == 6 ) { 89 | $extensions = $NfConf::EXTENSIONS ? $NfConf::EXTENSIONS : ""; 90 | } 91 | 92 | my $pid = CollectorStatus($port); 93 | if ( $pid > 0 ) { 94 | print "\nError( Port: $port ): a collector with pid[$pid] is already running\n"; 95 | return; 96 | } 97 | 98 | my $ziparg = $NfConf::ZIPcollected; 99 | if ( defined $NfConf::CYCLETIME ) { 100 | $twin = "-t " . $NfConf::CYCLETIME; 101 | } 102 | my $common_args = "-D -p $port -u $uid -g $gid $buffer_opts $subdirlayout -P $pidfile $ziparg $extensions $twin"; 103 | my $src_args; 104 | my $optargs = ''; 105 | if ( scalar @SourceList > 1 ) { 106 | # multiple sources per collector 107 | foreach my $ident ( @SourceList ) { 108 | my $IP = $NfConf::sources{$ident}{'IP'}; 109 | if ( !defined $IP ) { 110 | print "\nError( Port: $port ): Missing flow source IP address for '$ident'\n"; 111 | return; 112 | } 113 | $src_args .= "-n $ident,$IP,$NfConf::PROFILEDATADIR/live/$ident "; 114 | $optargs = exists $NfConf::sources{$ident}{'optarg'} ? "$optargs $NfConf::sources{$ident}{'optarg'}" : ''; 115 | } 116 | } else { 117 | # single source 118 | my $ident = shift @SourceList; 119 | my $profiledir = "$NfConf::PROFILEDATADIR/live/$ident"; 120 | $optargs = exists $NfConf::sources{$ident}{'optarg'} ? $NfConf::sources{$ident}{'optarg'} : ''; 121 | $src_args = $nfdump_version == 7 ? "-I $ident -w $profiledir" : "-I $ident -l $profiledir "; 122 | } 123 | 124 | my $args = "$common_args $src_args $optargs"; 125 | # print "\nRun: $NfConf::PREFIX/$collector $args\n"; 126 | 127 | system("$NfConf::PREFIX/$collector $args"); 128 | my $child_exit = defined $main::child_exit ? $main::child_exit : 0; 129 | my $exit_value = $child_exit >> 8; 130 | my $signal_num = $child_exit & 127; 131 | my $dumped_core = $child_exit & 128; 132 | if ( $exit_value != 0 ) { 133 | print "$collector exec error: exit: $exit_value, signal: $signal_num, coredump: $dumped_core\n"; 134 | } else { 135 | my $dowait = 5; 136 | while ( $dowait && ! -f $pidfile ) { 137 | sleep 1; 138 | $dowait--; 139 | } 140 | if ( $dowait ) { 141 | $pid = CollectorStatus($port); 142 | print "[$pid]"; 143 | } else { 144 | print ": collector did not start - see logfile" 145 | } 146 | } 147 | 148 | } # End of StartCollector 149 | 150 | sub StopCollector { 151 | my $port = shift; 152 | 153 | # sim mode 154 | if ( $port == 0 ) { 155 | print "[no collector]"; 156 | return; 157 | } 158 | 159 | my @SourceList; 160 | foreach my $source ( sort keys %{$$NfSen::hints{'sources'}} ) { 161 | my $_port = $$NfSen::hints{'sources'}{$source}; 162 | if ( $_port == $port ) { 163 | push @SourceList, $source; 164 | } 165 | } 166 | 167 | print "("; 168 | print join ' ', @SourceList; 169 | print ")"; 170 | 171 | my $pid = CollectorStatus($port); 172 | if ( $pid == 0 ) { 173 | print "[no collector]"; 174 | return; 175 | } 176 | 177 | if ( $pid == - 1 ) { 178 | print "[collector died unexpectedly]"; 179 | return; 180 | } 181 | 182 | print "[$pid]"; 183 | kill 'TERM', $pid || warn "Can't signal nfcapd: $! "; 184 | my $timeout = 10; 185 | while ( $timeout && -f "$NfConf::PIDDIR/p${port}.pid") { 186 | print "."; 187 | sleep 1; 188 | $timeout--; 189 | } 190 | if ( -f "$NfConf::PIDDIR/p${port}.pid") { 191 | print " Process [$pid] does not want to terminate!\n"; 192 | } 193 | 194 | } # End of StopCollector 195 | 196 | sub NfSen_start { 197 | 198 | if ( ! -d "$NfConf::PIDDIR" ) { 199 | print "PIDDIR '$NfConf::PIDDIR' not found! NfSen installation problem!\n"; 200 | return; 201 | } 202 | 203 | if ( -f "$NfConf::PIDDIR/nfsend.pid" && -z "$NfConf::PIDDIR/nfsend.pid" ) { 204 | print "Unclean shutdown - zero size pid file\n"; 205 | unlink "$NfConf::PIDDIR/nfsend.pid"; 206 | } 207 | 208 | # Check if NfSen is already running 209 | if ( -f "$NfConf::PIDDIR/nfsend.pid" ) { 210 | open PID, "$NfConf::PIDDIR/nfsend.pid" || 211 | die "Can't read pid file '$NfConf::PIDDIR/nfsend.pid': $!\n"; 212 | my $pid = ; 213 | chomp $pid; 214 | close PID; 215 | if ( kill( 0, $pid) == 1 ) { 216 | print "NfSen is already running!\n"; 217 | return; 218 | } else { 219 | print "Unclean shutdown - run stop sequence first to clean up!\n"; 220 | NfSen_stop(); 221 | } 222 | } 223 | 224 | # Delete all possible remains from old runs. 225 | NfSen::CleanOrphans(); 226 | 227 | # Decide how many collectors to start. 228 | # nfcapd can handle several sources at the same port 229 | my %AllCollectors; 230 | foreach my $source ( sort keys %NfConf::sources ) { 231 | my $port = $NfConf::sources{$source}{'port'}; 232 | push @{$AllCollectors{$port}}, $source; 233 | } 234 | 235 | if ( !Nfsources::ValidateSources() ) { 236 | print "Fix errors for %source in your config file and retry!\n"; 237 | return; 238 | } 239 | print "Starting nfcapd:"; 240 | foreach my $port ( keys %AllCollectors ) { 241 | StartCollector($port); 242 | print " "; 243 | select(undef, undef, undef, 0.2); 244 | } 245 | print "\n"; 246 | 247 | print "Starting nfsend"; 248 | system "$NfConf::BINDIR/nfsend"; 249 | my $child_exit = defined $main::child_exit ? $main::child_exit : 0; 250 | my $exit_value = $child_exit >> 8; 251 | my $signal_num = $child_exit & 127; 252 | my $dumped_core = $child_exit & 128; 253 | if ( $exit_value != 0 ) { 254 | print ": exec error: exit: $exit_value, signal: $signal_num, coredump: $dumped_core\n"; 255 | } 256 | print ".\n"; 257 | 258 | } # End of NfSen_start 259 | 260 | sub NfSen_stop { 261 | 262 | # Check how many collectors to stop 263 | # nfcapd 1.6.x can handle several sources at the same port 264 | my %AllCollectors; 265 | foreach my $source ( sort keys %NfConf::sources ) { 266 | my $port = $NfConf::sources{$source}{'port'}; 267 | push @{$AllCollectors{$port}}, $source; 268 | } 269 | 270 | print "Shutdown nfcapd: "; 271 | foreach my $port ( keys %AllCollectors ) { 272 | StopCollector($port); 273 | print ' '; 274 | } 275 | print ".\n"; 276 | 277 | print "Shutdown nfsend:"; 278 | if ( -f "$NfConf::PIDDIR/nfsend.pid" ) { 279 | open PID, "$NfConf::PIDDIR/nfsend.pid" || 280 | die "Can't read pid file '$NfConf::PIDDIR/nfsend.pid': $!\n"; 281 | my $pid = ; 282 | chomp $pid; 283 | close PID; 284 | print "[$pid]"; 285 | if ( kill( 0, $pid) == 0 ) { 286 | print "[No such process]"; 287 | unlink "$NfConf::PIDDIR/nfsend.pid"; 288 | } else { 289 | kill 'TERM', $pid || warn "Can't signal nfsend: $! "; 290 | my $timeout = $NfConf::CYCLETIME; 291 | while ( $timeout && -f "$NfConf::PIDDIR/nfsend.pid") { 292 | print "."; 293 | sleep 1; 294 | $timeout--; 295 | } 296 | } 297 | if ( -f "$NfConf::PIDDIR/nfsend.pid") { 298 | print " Process [$pid] does not want to terminate!\n"; 299 | } 300 | } else { 301 | print "[no pid file found!]"; 302 | } 303 | print "\n"; 304 | 305 | } # End of NfSen_stop 306 | 307 | sub NfSen_status { 308 | 309 | print "Version nfSen: $$NfSen::hints{'version'}, nfdump: $$NfSen::hints{'nfdump'}\n"; 310 | if ( $NfConf::SIMmode ) { 311 | print "NfSen status: Simulation mode\n"; 312 | } else { 313 | print "NfSen status:\n"; 314 | } 315 | 316 | # Check how many collectors to stop 317 | # nfcapd 1.6.x can handle several sources at the same port 318 | my %AllCollectors; 319 | foreach my $source ( sort keys %NfConf::sources ) { 320 | my $port = $NfConf::sources{$source}{'port'}; 321 | push @{$AllCollectors{$port}}, $source; 322 | } 323 | 324 | foreach my $port ( keys %AllCollectors ) { 325 | my $identref = $AllCollectors{$port}; 326 | my $pid = CollectorStatus($port); 327 | print "Collector for ("; 328 | print join ' ', @$identref; 329 | print ") port $port"; 330 | 331 | if ( $pid == -1 ) { 332 | print " died for unknown reason."; 333 | } elsif ( $pid == 0 ) { 334 | print " is not running."; 335 | } else { 336 | print " is running [$pid]."; 337 | } 338 | print "\n"; 339 | } 340 | 341 | print "nfsen daemon: "; 342 | if ( -f "$NfConf::PIDDIR/nfsend.pid" ) { 343 | open PID, "$NfConf::PIDDIR/nfsend.pid" || 344 | die "Can't read pid file '$NfConf::PIDDIR/nfsend.pid': $!\n"; 345 | my $pid = ; 346 | chomp $pid; 347 | close PID; 348 | print " pid: [$pid] "; 349 | if ( kill( 0, $pid) == 0 ) { 350 | print "died for unknown reason."; 351 | unlink "$NfConf::PIDDIR/nfsend.pid"; 352 | } else { 353 | print "is running."; 354 | } 355 | } else { 356 | print "is not running."; 357 | } 358 | print "\n"; 359 | 360 | } # End of NfSen_status 361 | 362 | sub CollectorStatus { 363 | my $port = shift; 364 | 365 | my $pidfile = "$NfConf::PIDDIR/p${port}.pid"; 366 | if ( -f "$pidfile" ) { 367 | open PID, "$pidfile" || 368 | die "Can't read pid file '$pidfile': $!\n"; 369 | my $pid = ; 370 | chomp $pid; 371 | close PID; 372 | if ( kill( 0, $pid) == 0 ) { 373 | unlink "$pidfile"; 374 | return -1; 375 | } else { 376 | return $pid; 377 | } 378 | } else { 379 | return 0; 380 | } 381 | 382 | } # End of CollectorStatus 383 | 384 | sub NfSen_reload { 385 | 386 | if ( -f "$NfConf::PIDDIR/nfsend.pid" ) { 387 | print "Restart nfsend:"; 388 | open PID, "$NfConf::PIDDIR/nfsend.pid" || 389 | die "Can't read pid file '$NfConf::PIDDIR/nfsend.pid': $!\n"; 390 | my $pid = ; 391 | chomp $pid; 392 | close PID; 393 | print "[$pid]\n"; 394 | kill 'USR1', $pid || warn "Can't restart nfsend: $! "; 395 | } else { 396 | print STDERR "No pid file found for nfsend - please restart manually\n"; 397 | } 398 | 399 | } # End of NfSen_reload 400 | 401 | 1; 402 | -------------------------------------------------------------------------------- /libexec/NfSenSim.pm: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # * Neither the name of SWITCH nor the names of its contributors may be 14 | # used to endorse or promote products derived from this software without 15 | # specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | # POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # $Author: peter $ 30 | # 31 | # $Id: NfSenSim.pm 69 2014-06-23 19:27:50Z peter $ 32 | # 33 | # $LastChangedRevision: 69 $ 34 | 35 | 36 | package NfSenSim; 37 | 38 | use NfConf; 39 | use NfProfile; 40 | use NfSenRC; 41 | use NfSenRRD; 42 | use NfAlert; 43 | 44 | sub ResetNfSen { 45 | 46 | my $tstart = NfSen::ISO2UNIX($NfConf::sim{'tstart'}); 47 | 48 | print "Reset NfSen:\n"; 49 | if ( -f "$NfConf::PIDDIR/nfsend.pid" ) { 50 | print "Stop NfSen while resetting ...\n"; 51 | NfSenRC::NfSen_stop(); 52 | } 53 | 54 | if ( !NfSen::DropPriv($NfConf::USER) ) { 55 | die "$Log::ERROR\n"; 56 | } 57 | 58 | my @AllProfileGroups = NfProfile::ProfileGroups(); 59 | foreach my $profilegroup ( @AllProfileGroups ) { 60 | my @AllProfiles = NfProfile::ProfileList($profilegroup); 61 | foreach my $profilename ( @AllProfiles ) { 62 | next if $profilename eq 'live' && $profilegroup eq '.'; 63 | 64 | print "Clear profile '$profilename' in group '$profilegroup'\n"; 65 | 66 | my @dirs; 67 | push @dirs, "$NfConf::PROFILESTATDIR"; 68 | if ( "$NfConf::PROFILESTATDIR" ne "$NfConf::PROFILEDATADIR" ) { 69 | push @dirs, "$NfConf::PROFILEDATADIR"; 70 | } 71 | 72 | foreach my $dir ( @dirs ) { 73 | my $command = "/bin/rm -rf $dir/$profilegroup/$profilename"; 74 | system($command); 75 | } 76 | } 77 | } 78 | 79 | foreach my $alertname ( NfAlert::AlertList() ) { 80 | 81 | print "Clear alert '$alertname'\n"; 82 | 83 | my @dirs; 84 | push @dirs, "$NfConf::PROFILESTATDIR"; 85 | if ( "$NfConf::PROFILESTATDIR" ne "$NfConf::PROFILEDATADIR" ) { 86 | push @dirs, "$NfConf::PROFILEDATADIR"; 87 | } 88 | 89 | foreach my $dir ( @dirs ) { 90 | my $command = "/bin/rm -rf $dir/~$alertname"; 91 | system($command); 92 | } 93 | } 94 | 95 | print "Remove filters ..."; 96 | my $command = "/bin/rm -rf $NfConf::FILTERDIR/*"; 97 | system($command); 98 | print "done.\n"; 99 | 100 | print "Reset profile 'live'\n"; 101 | my %profileinfo = NfProfile::ReadProfile('live', '.'); 102 | $profileinfo{'tcreate'} = $tstart; 103 | $profileinfo{'tbegin'} = $tstart; 104 | $profileinfo{'tstart'} = $tstart; 105 | $profileinfo{'tend'} = $tstart; 106 | $profileinfo{'updated'} = $tstart - $NfConf::CYCLETIME; 107 | $profileinfo{'expire'} = 0; 108 | $profileinfo{'maxsize'} = 0; 109 | $profileinfo{'size'} = 0; 110 | $profileinfo{'filter'} = ""; 111 | $profileinfo{'type'} = 0; 112 | $profileinfo{'locked'} = 0; 113 | $profileinfo{'status'} = 'OK'; 114 | 115 | foreach my $db ( keys %NfConf::sources ) { 116 | NfSenRRD::SetupRRD("$NfConf::PROFILESTATDIR/live", $db, $tstart - $NfConf::CYCLETIME, 1); 117 | } 118 | if ( $Log::ERROR ) { 119 | die "Error setup RRD DBs: $Log::ERROR\n"; 120 | } 121 | 122 | if ( exists $NfConf::sim{'tbegin'} ) { 123 | print "Preset profile 'live'\n"; 124 | my $tbegin = NfSen::ISO2UNIX($NfConf::sim{'tbegin'}); 125 | foreach my $channel ( NfProfile::ProfileChannels(\%profileinfo) ) { 126 | for ( my $t = $tstart; $t <= $tbegin; $t += $NfConf::CYCLETIME ) { 127 | my $t_iso = NfSen::UNIX2ISO($t); 128 | my $subdirs = NfSen::SubdirHierarchy($t); 129 | my ($statinfo, $exit_code, $err ) = NfProfile::ReadStatInfo(\%profileinfo, $channel, $subdirs, $t_iso, undef); 130 | if ( $exit_code != 0 ) { 131 | warn "$t_iso: $err"; 132 | next; 133 | } 134 | 135 | my @_values = (); 136 | foreach my $ds ( @NfSenRRD::RRD_DS ) { 137 | if ( !defined $$statinfo{$ds} || $$statinfo{$ds} == - 1 ) { 138 | push @_values, 0; 139 | } else { 140 | push @_values, $$statinfo{$ds}; 141 | } 142 | } 143 | $err = NfSenRRD::UpdateDB("$NfConf::PROFILESTATDIR/live", $channel, $t, 144 | join(':',@NfSenRRD::RRD_DS) , join(':', @_values)); 145 | if ( $Log::ERROR ) { 146 | die "ERROR Update RRD time: '$t_iso', db: '$channel', profile: '$profilename' group '$profilegroup' : $Log::ERROR"; 147 | } 148 | } 149 | } 150 | $profileinfo{'tend'} = $tbegin; 151 | $profileinfo{'updated'} = $tbegin - $NfConf::CYCLETIME; 152 | NfSenRRD::UpdateGraphs('live', '.', $tbegin - $NfConf::CYCLETIME, 1); 153 | } else { 154 | NfSenRRD::UpdateGraphs('live', '.', $tstart - $NfConf::CYCLETIME, 1); 155 | } 156 | 157 | NfProfile::WriteProfile(\%profileinfo); 158 | delete $$NfSen::hints{'sim'}; 159 | NfSen::StoreHints(); 160 | print "Reset NfSen completed.\n"; 161 | 162 | } # End of ResetNfSen 163 | 164 | sub NewSlots { 165 | my $timeslot = shift; 166 | 167 | my $t_iso = NfSen::UNIX2ISO($timeslot); 168 | my %profileinfo = NfProfile::ReadProfile('live', '.'); 169 | 170 | my $failed = 0; 171 | foreach my $channel ( NfProfile::ProfileChannels(\%profileinfo) ) { 172 | my $subdirs = NfSen::SubdirHierarchy($timeslot); 173 | my ($statinfo, $exit_code, $err ) = NfProfile::ReadStatInfo(\%profileinfo, $channel, $subdirs, $t_iso, undef); 174 | if ( $exit_code != 0 ) { 175 | $failed = 1; 176 | next; 177 | } 178 | } 179 | return $failed ? 0 : 1; 180 | 181 | } # End of NewSlots 182 | 1; 183 | -------------------------------------------------------------------------------- /libexec/Nfsources.pm: -------------------------------------------------------------------------------- 1 | #!%%PERL%% 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: Nfsources.pm 69 2014-06-23 19:27:50Z peter $ 33 | # 34 | # $LastChangedRevision: 69 $ 35 | 36 | package Nfsources; 37 | 38 | use strict; 39 | use warnings; 40 | use Log; 41 | 42 | use NfSenRC; 43 | 44 | sub ValidateSources { 45 | 46 | # Bundle the sources in the number of collectors since 47 | # nfcapd 1.6.x can handle several sources at the same port 48 | my %AllCollectors; 49 | foreach my $source ( sort keys %NfConf::sources ) { 50 | my $port = $NfConf::sources{$source}{'port'}; 51 | push @{$AllCollectors{$port}}, $source; 52 | } 53 | 54 | foreach my $port ( keys %AllCollectors ) { 55 | # no collector 56 | if ( $port == 0 ) { 57 | next; 58 | } 59 | 60 | my $identref = $AllCollectors{$port}; 61 | my $ident = $$identref[0]; 62 | my $type = exists $NfConf::sources{$ident}{'type'} ? $NfConf::sources{$ident}{'type'}: 'netflow'; 63 | my $collector = $NfSenRC::CollectorMap{$type}; 64 | 65 | if ( !defined $NfSenRC::CollectorMap{$type} ) { 66 | print "Source '$ident': unknown collector for type '$type'"; 67 | return 0; 68 | } elsif ( ! -f "$NfConf::PREFIX/$collector" ) { 69 | print "Source '$ident': missing collector '$collector' for type '$type'"; 70 | return 0; 71 | } 72 | 73 | foreach $ident ( @$identref ) { 74 | my $len = length($ident); 75 | if ( $len < 1 || $len > 19 ) { 76 | print "Error Ident: '$ident': Source identifiers must be between 1 and 19 chars long!\n"; 77 | return 0; 78 | } 79 | if ( $ident =~ /[^a-z0-9_]+/i ) { 80 | print "Error Ident: '$ident': Source identifiers must contain only characters [a-zA-Z0-9_] !\n"; 81 | return 0; 82 | } 83 | 84 | if ( exists $NfConf::sources{$ident}{'type'} && $NfConf::sources{$ident}{'type'} ne $type ) { 85 | print "\nError: $ident has different type than $$identref[0] for same collector.\n"; 86 | return 0; 87 | } 88 | if ( scalar @$identref > 1 && !exists $NfConf::sources{$ident}{'IP'} ) { 89 | print "\nError: $ident missing parameter 'IP' for multiple sources collector.\n"; 90 | return 0; 91 | } 92 | my $IP = $NfConf::sources{$ident}{'IP'}; 93 | } 94 | } 95 | 96 | return 1; 97 | 98 | } # End of ValidateSources 99 | 100 | sub CheckReconfig { 101 | 102 | if ( !ValidateSources() ) { 103 | return 2; 104 | } 105 | # profile 'live' contains by definition all netflow sources currently in use. 106 | my %profileinfo = NfProfile::ReadProfile('live', '.'); 107 | if ( $profileinfo{'status'} eq 'empty' ) { 108 | # it's an error reading this profile 109 | print STDERR "Error reading profile 'live'"; 110 | if ( defined $Log::ERROR ) { 111 | print STDERR ": $Log::ERROR"; 112 | } 113 | print STDERR "\n"; 114 | return 2; 115 | } 116 | 117 | my @current_sources = NfProfile::ProfileChannels(\%profileinfo); 118 | my %_tmp; 119 | @_tmp{@current_sources} = 1; 120 | 121 | # Building source lists 122 | foreach my $source ( keys %NfConf::sources ) { 123 | if ( exists $_tmp{$source} ) { 124 | delete $_tmp{$source}; 125 | } else { 126 | return 0; 127 | } 128 | } 129 | 130 | if ( scalar keys %_tmp > 0 ) { 131 | return 0; 132 | } 133 | 134 | return 1; 135 | 136 | } # End of CheckReconfig 137 | 138 | sub Reconfig { 139 | 140 | if ( scalar(keys %NfConf::sources) == 0 ) { 141 | print STDERR "Error: No sources defined!"; 142 | return; 143 | } 144 | 145 | # profile 'live' contains by definition all netflow sources currently in use. 146 | my %profileinfo = NfProfile::ReadProfile('live', '.'); 147 | if ( $profileinfo{'status'} eq 'empty' ) { 148 | # it's an error reading this profile 149 | print STDERR "Error reading profile 'live'"; 150 | if ( defined $Log::ERROR ) { 151 | print STDERR ": $Log::ERROR"; 152 | } 153 | print STDERR "\n"; 154 | return; 155 | } 156 | 157 | my @current_sources = NfProfile::ProfileChannels(\%profileinfo); 158 | 159 | my %_tmp; 160 | @_tmp{@current_sources} = 1; 161 | 162 | # Building source lists 163 | my @AddSourceList; 164 | my @DeleteSourceList; 165 | foreach my $source ( sort keys %NfConf::sources ) { 166 | if ( exists $_tmp{$source} ) { 167 | delete $_tmp{$source}; 168 | } else { 169 | push @AddSourceList, $source; 170 | } 171 | } 172 | @DeleteSourceList = keys %_tmp; 173 | 174 | # Nothing to do ? 175 | if ( (scalar @AddSourceList) == 0 && (scalar @DeleteSourceList) == 0 ) { 176 | print "Reconfig: No changes found!\n"; 177 | $profileinfo{'locked'} = 0; 178 | if ( !NfProfile::WriteProfile(\%profileinfo) ) { 179 | print STDERR "Error writing profile 'live': $Log::ERROR\n"; 180 | } 181 | return; 182 | } 183 | 184 | foreach my $source ( @AddSourceList ) { 185 | my $ret = NfSen::ValidFilename($source); 186 | if ( $ret ne "ok" ) { 187 | print STDERR "Error checking source name: $ret\n"; 188 | return; 189 | } 190 | } 191 | 192 | # Confirm add/delete sources 193 | print "New sources to configure : ", join(' ', @AddSourceList), "\n" if scalar @AddSourceList; 194 | print "Remove configured sources: ", join(' ', @DeleteSourceList), "\n" if scalar @DeleteSourceList; 195 | if ( NfSen::UserInput("Continue?") ne 'y') { 196 | print "Faire enough! - Nothing changed!\n"; 197 | $profileinfo{'locked'} = 0; 198 | if ( !NfProfile::WriteProfile(\%profileinfo) ) { 199 | print STDERR "Error writing profile 'live': $Log::ERROR\n"; 200 | } 201 | return; 202 | } 203 | print "\n"; 204 | 205 | my %StopCollectorList; 206 | my %StartCollectorList; 207 | my %AllCollectors; 208 | foreach my $source ( sort keys %NfConf::sources ) { 209 | my $port = $NfConf::sources{$source}{'port'}; 210 | push @{$AllCollectors{$port}}, $source; 211 | } 212 | 213 | 214 | # lock live profile 215 | %profileinfo = NfProfile::LockProfile('live', '.'); 216 | if ( $profileinfo{'status'} eq 'empty' ) { 217 | # profile already locked and in use 218 | if ( $profileinfo{'locked'} == 1 ) { 219 | print STDERR "Profile 'live' is locked. Try later\n"; 220 | return; 221 | } 222 | 223 | # it's an error reading this profile 224 | if ( defined $Log::ERROR ) { 225 | print STDERR "Error profile 'live': $Log::ERROR\n"; 226 | return; 227 | } 228 | } 229 | 230 | # Add all new netflow sources 231 | if ( scalar @AddSourceList > 0 ) { 232 | # Add sources 233 | my $now = time(); 234 | my $tstart = $now - ( $now % $NfConf::CYCLETIME ); 235 | foreach my $source ( @AddSourceList ) { 236 | print "Add source '$source'"; 237 | my $ret = NfProfile::AddChannel(\%profileinfo, $source, '+', 0, $NfConf::sources{$source}{'col'}, $source, []); 238 | if ( $ret eq "ok" ) { 239 | my $port = $NfConf::sources{$source}{'port'}; 240 | # Do we need to start/restart a collector on that port? 241 | if ( NfSenRC::CollectorStatus($port) > 0 ) { 242 | # we already have a collector running - need to restart with new source added 243 | $StopCollectorList{$port} = 1; # mark to be started 244 | $StartCollectorList{$port} = 1; # mark to be stopped 245 | } else { 246 | # no collector is running - start a new one 247 | $StartCollectorList{$port} = 1; # mark to be started 248 | } 249 | } else { 250 | print "Error while setting up channel '$source': $ret"; 251 | print "No collector started! "; 252 | } 253 | print "\n"; 254 | } 255 | print "\n"; 256 | } 257 | 258 | # Delete sources, no longer configured 259 | if ( scalar @DeleteSourceList > 0 ) { 260 | print "Delete source(s): ", join(' ', @DeleteSourceList), ":\n"; 261 | # Delete sources 262 | foreach my $source ( @DeleteSourceList ) { 263 | print "Delete source '$source' "; 264 | # Stop this collector if not already done 265 | my $port = $$NfSen::hints{'sources'}{$source}; 266 | if ( NfSenRC::CollectorStatus($port) > 0 ) { 267 | # Properly stop collector before deleting the channel 268 | print "Stop running collector on port '$port' "; 269 | NfSenRC::StopCollector($port); 270 | $StopCollectorList{$port} = 2; # mark as already stopped 271 | } 272 | 273 | # Do we need to restart the collector on this for for other 274 | # still existing sources? 275 | if ( exists $AllCollectors{$port} ) { 276 | $StartCollectorList{$port} = 1; # mark to be started 277 | } 278 | 279 | my $ret = NfProfile::DeleteChannel(\%profileinfo, $source); 280 | if ( $ret ne "ok" ) { 281 | print "\nError while removing channel '$source': $ret\n"; 282 | } 283 | print " \n"; 284 | } 285 | } 286 | 287 | # Unlock/Write profile 288 | $profileinfo{'locked'} = 0; 289 | if ( !NfProfile::WriteProfile(\%profileinfo) ) { 290 | print STDERR "Error writing profile 'live': $Log::ERROR\n"; 291 | } 292 | 293 | if ( !-f "$NfConf::PIDDIR/nfsend.pid") { 294 | # NfSen is not running - we are done 295 | print "Reconfig done!\n"; 296 | delete $$NfSen::hints{'sources'}; 297 | foreach my $source ( sort keys %NfConf::sources ) { 298 | $$NfSen::hints{'sources'}{$source} = $NfConf::sources{$source}{'port'}; 299 | } 300 | return; 301 | } 302 | 303 | # Collector Jojo ... 304 | my $port; 305 | foreach $port ( keys %StopCollectorList ) { 306 | # Stop running collectors if not already done so 307 | if ( ($StopCollectorList{$port} == 1) && (NfSenRC::CollectorStatus($port) > 0) ) { 308 | print "Stop running collector on port '$port' "; 309 | NfSenRC::StopCollector($port); 310 | print "\n"; 311 | } 312 | } 313 | foreach $port ( keys %StartCollectorList ) { 314 | if ( NfSenRC::CollectorStatus($port) > 0) { 315 | # Ups .. should not happen - something fishy! 316 | print STDERR "A collector on port '$port' is already running! Unclean reconfig\n"; 317 | # give it another try to die 318 | NfSenRC::StopCollector($port); 319 | } 320 | print "Start/restart collector on port '$port' for "; 321 | NfSenRC::StartCollector($port); 322 | print "\n"; 323 | } 324 | 325 | print "\n"; 326 | 327 | delete $$NfSen::hints{'sources'}; 328 | foreach my $source ( sort keys %NfConf::sources ) { 329 | $$NfSen::hints{'sources'}{$source} = $NfConf::sources{$source}{'port'}; 330 | } 331 | 332 | NfSenRC::NfSen_reload(); 333 | 334 | } # End of Reconfig 335 | 336 | 1; 337 | -------------------------------------------------------------------------------- /libexec/Nfsync.pm: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011, Peter Haag 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # * Neither the name of the author nor the names of its contributors may be 14 | # used to endorse or promote products derived from this software without 15 | # specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | # POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # $Author: peter $ 30 | # 31 | # $Id: Nfsync.pm 27 2011-12-29 12:53:29Z peter $ 32 | # 33 | # $LastChangedRevision: 27 $ 34 | 35 | package Nfsync; 36 | 37 | use strict; 38 | use warnings; 39 | 40 | use IPC::SysV qw(IPC_CREAT); 41 | use IPC::SysV qw(IPC_NOWAIT); 42 | use IPC::SysV qw(IPC_PRIVATE); 43 | use IPC::SysV qw(IPC_RMID); 44 | 45 | my $semlock; 46 | 47 | sub seminit { 48 | $semlock = semget(IPC_PRIVATE, 1, 0600 | IPC_CREAT ) || die "Can not get semaphore: $!"; 49 | semsignal($semlock); 50 | } # End of seminit 51 | 52 | sub semclean { 53 | semctl($semlock, 0, &IPC_RMID, 0); 54 | } # End of semclean 55 | 56 | sub semwait { 57 | my $sem=$semlock; 58 | semop($sem, pack("s3", 0, -1, 0)) || warn "semopt(): $!\n"; 59 | } # End of semwait 60 | 61 | sub semnowait { 62 | my $sem=$semlock; 63 | return semop($sem, pack("s3", 0, -1, IPC_NOWAIT)); 64 | } # End of semnowait 65 | 66 | sub semsignal { 67 | my $sem=$semlock; 68 | semop($sem, pack("s3", 0, +1, 0)) || warn "semopt(): $!\n"; 69 | } # End of semsignal 70 | 71 | 1; 72 | -------------------------------------------------------------------------------- /libexec/Notification.pm: -------------------------------------------------------------------------------- 1 | #!%%PERL%% 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: Notification.pm 27 2011-12-29 12:53:29Z peter $ 33 | # 34 | # $LastChangedRevision: 27 $ 35 | 36 | package Notification; 37 | 38 | use strict; 39 | 40 | # What we import 41 | use Sys::Syslog; 42 | 43 | use Mail::Header; 44 | use Mail::Internet; 45 | use Date::Format qw(time2str); 46 | 47 | # What we export 48 | 49 | use vars qw(@ISA @EXPORT); 50 | use Exporter; 51 | @ISA = qw(Exporter); 52 | @EXPORT = qw(notify); 53 | 54 | # 55 | # notify: 56 | # input: Subject of the Mail 57 | # body_ref: Reference to the mail body 58 | # Example: notify('Notification email', \@BodyText); 59 | # 60 | sub notify { 61 | my $subject = shift; 62 | my $body_ref = shift; 63 | my $rcpt_to = $NfConf::RCPT_TO ; 64 | my $email_date = time2str('%a, %d %b %Y %H:%M:%S %z', time); 65 | if ( scalar @_ == 1 ) { 66 | $rcpt_to = shift; 67 | } 68 | 69 | syslog('debug', "notify: $subject"); 70 | 71 | my @mail_head = ( 72 | "From: $NfConf::MAIL_FROM", 73 | "To: $rcpt_to", 74 | "Date: $email_date", 75 | "Subject: $subject" 76 | ); 77 | 78 | my $mail_header = new Mail::Header( \@mail_head ) ; 79 | 80 | my $mail = new Mail::Internet( 81 | Header => $mail_header, 82 | Body => $body_ref 83 | ); 84 | 85 | my @sent_to = $mail->smtpsend( 86 | Host => $NfConf::SMTP_SERVER , 87 | Hello => $NfConf::SMTP_SERVER, 88 | MailFrom => $NfConf::MAIL_FROM 89 | ); 90 | 91 | # Do we have failed recipients? 92 | # build the difference between array @$NfConf::RCPT_TO and @sent_to 93 | my %_tmp; 94 | my @_recv = split /\*s,\*s/, $rcpt_to; 95 | @_tmp{@_recv} = 1; 96 | delete @_tmp{@sent_to}; 97 | my @Failed = keys %_tmp; 98 | 99 | if ( scalar @Failed > 0 ) { 100 | foreach my $rcpt ( @Failed ) { 101 | syslog('err', "notify: Failed to send notification to: $rcpt"); 102 | } 103 | } else { 104 | syslog('info', "notify: Successful sent mail: '$subject'"); 105 | } 106 | 107 | } 108 | 109 | 1; 110 | -------------------------------------------------------------------------------- /plugins/PluginTemplate.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: PluginTemplate.pm 27 2011-12-29 12:53:29Z peter $ 33 | # 34 | # $LastChangedRevision: 27 $ 35 | 36 | # Template for NfSen plugin 37 | # See the demoplugin for an working example 38 | package PluginTemplate; 39 | 40 | use strict; 41 | use NfSen; 42 | use NfConf; 43 | 44 | # 45 | # The plugin may send any messages to syslog 46 | # Do not initialize syslog, as this is done by 47 | # the main process nfsend 48 | use Sys::Syslog; 49 | 50 | sub run { 51 | my $profile = shift; 52 | my $timeslot = shift; 53 | 54 | syslog('debug', "plugin run: Profile: $profile, Time: $timeslot"); 55 | 56 | # 57 | # Do something and process the output and notify the duty team 58 | # .... 59 | 60 | } 61 | 62 | sub Init { 63 | syslog("info", "plugin: Init"); 64 | 65 | # Init some vars 66 | return 1; 67 | } 68 | 69 | sub BEGIN { 70 | syslog("info", "plugin BEGIN"); 71 | # Standard BEGIN Perl function - See Perl documentation 72 | # not used here 73 | } 74 | 75 | sub END { 76 | syslog("info", "plugin END"); 77 | # Standard END Perl function - See Perl documentation 78 | # not used here 79 | } 80 | 81 | 1; 82 | -------------------------------------------------------------------------------- /plugins/backend/demoplugin.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # * Neither the name of SWITCH nor the names of its contributors may be 15 | # used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | # 30 | # $Author: peter $ 31 | # 32 | # $Id: demoplugin.pm 41 2012-01-15 14:20:42Z peter $ 33 | # 34 | # $LastChangedRevision: 41 $ 35 | 36 | # Demo plugin for NfSen 37 | 38 | # Name of the plugin 39 | package demoplugin; 40 | 41 | use strict; 42 | use NfProfile; 43 | use NfConf; 44 | 45 | # 46 | # The plugin may send any messages to syslog 47 | # Do not initialize syslog, as this is done by 48 | # the main process nfsen-run 49 | use Sys::Syslog; 50 | 51 | our %cmd_lookup = ( 52 | 'try' => \&RunProc, 53 | ); 54 | 55 | # This string identifies the plugin as a version 1.3.0 plugin. 56 | our $VERSION = 130; 57 | 58 | my $EODATA = ".\n"; 59 | 60 | my ( $nfdump, $PROFILEDIR ); 61 | 62 | # 63 | # Define a nice filter: 64 | # We like to see flows containing more than 500000 packets 65 | my $nf_filter = 'packets > 500000'; 66 | 67 | sub RunProc { 68 | my $socket = shift; # scalar 69 | my $opts = shift; # reference to a hash 70 | 71 | # error checking example 72 | if ( !exists $$opts{'colours'} ) { 73 | Nfcomm::socket_send_error($socket, "Missing value"); 74 | return; 75 | } 76 | 77 | # retrieve values passed by frontend 78 | # two scalars 79 | my $colour1 = $$opts{'colour1'}; 80 | my $colour2 = $$opts{'colour2'}; 81 | 82 | # one array as arrayref 83 | my $colours = $$opts{'colours'}; 84 | 85 | my @othercolours = ( 'red', 'blue' ); 86 | 87 | # Prepare answer 88 | my %args; 89 | $args{'string'} = "Greetings from backend plugin. Got colour values: '$colour1' and '$colour2'"; 90 | $args{'othercolours'} = \@othercolours; 91 | 92 | Nfcomm::socket_send_ok($socket, \%args); 93 | 94 | } # End of RunProc 95 | 96 | # 97 | # Periodic data processing function 98 | # input: hash reference including the items: 99 | # 'profile' profile name 100 | # 'profilegroup' profile group 101 | # 'timeslot' time of slot to process: Format yyyymmddHHMM e.g. 200503031200 102 | sub run { 103 | my $argref = shift; 104 | my $profile = $$argref{'profile'}; 105 | my $profilegroup = $$argref{'profilegroup'}; 106 | my $timeslot = $$argref{'timeslot'}; 107 | 108 | syslog('debug', "demoplugin run: Profilegroup: $profilegroup, Profile: $profile, Time: $timeslot"); 109 | 110 | my %profileinfo = NfProfile::ReadProfile($profile, $profilegroup); 111 | my $profilepath = NfProfile::ProfilePath($profile, $profilegroup); 112 | my $all_sources = join ':', keys %{$profileinfo{'channel'}}; 113 | my $netflow_sources = "$PROFILEDIR/$profilepath/$all_sources"; 114 | 115 | syslog('debug', "demoplugin args: '$netflow_sources'"); 116 | 117 | } # End of run 118 | 119 | # 120 | # Alert condition function. 121 | # if defined it will be automatically listed as available plugin, when defining an alert. 122 | # Called after flow filter is applied. Resulting flows stored in $alertflows file 123 | # Should return 0 or 1 if condition is met or not 124 | sub alert_condition { 125 | my $argref = shift; 126 | 127 | my $alert = $$argref{'alert'}; 128 | my $alertflows = $$argref{'alertfile'}; 129 | my $timeslot = $$argref{'timeslot'}; 130 | 131 | syslog('info', "Alert condition function called: alert: $alert, alertfile: $alertflows, timeslot: $timeslot"); 132 | 133 | # add your code here 134 | 135 | return 1; 136 | } 137 | 138 | # 139 | # Alert action function. 140 | # if defined it will be automatically listed as available plugin, when defining an alert. 141 | # Called when the trigger of an alert fires. 142 | # Return value ignored 143 | sub alert_action { 144 | my $argref = shift; 145 | 146 | my $alert = $$argref{'alert'}; 147 | my $timeslot = $$argref{'timeslot'}; 148 | 149 | syslog('info', "Alert action function called: alert: $alert, timeslot: $timeslot"); 150 | 151 | return 1; 152 | } 153 | 154 | # 155 | # The Init function is called when the plugin is loaded. It's purpose is to give the plugin 156 | # the possibility to initialize itself. The plugin should return 1 for success or 0 for 157 | # failure. If the plugin fails to initialize, it's disabled and not used. Therefore, if 158 | # you want to temporarily disable your plugin return 0 when Init is called. 159 | # 160 | sub Init { 161 | syslog("info", "demoplugin: Init"); 162 | 163 | # Init some vars 164 | $nfdump = "$NfConf::PREFIX/nfdump"; 165 | $PROFILEDIR = "$NfConf::PROFILEDATADIR"; 166 | 167 | return 1; 168 | } 169 | 170 | # 171 | # The Cleanup function is called, when nfsend terminates. It's purpose is to give the 172 | # plugin the possibility to cleanup itself. It's return value is discard. 173 | sub Cleanup { 174 | syslog("info", "demoplugin Cleanup"); 175 | # not used here 176 | } 177 | 178 | 1; 179 | -------------------------------------------------------------------------------- /plugins/backend/smily.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phaag/nfsen/d75d5322fe46c80151e82bf25e97a7c3d83bc5be/plugins/backend/smily.jpg -------------------------------------------------------------------------------- /plugins/frontend/demoplugin.php: -------------------------------------------------------------------------------- 1 | Hello I'm the demo plugin with id $plugin_id\n"; 37 | print "Query backend plugin for function try
\n"; 38 | 39 | // the command to be executed in the backend plugin 40 | $command = 'demoplugin::try'; 41 | 42 | // two scalar values 43 | $colour1 = '#72e3fa'; 44 | $colour2 = '#2a6f99'; 45 | 46 | // one array 47 | $colours = array ( '#12af7d', '#56fc7b'); 48 | 49 | // prepare arguments 50 | $opts = array(); 51 | $opts['colour1'] = $colour1; 52 | $opts['colour2'] = $colour2; 53 | $opts['colours'] = $colours; 54 | 55 | // call command in backend plugin 56 | $out_list = nfsend_query($command, $opts); 57 | 58 | // get result 59 | if ( !is_array($out_list) ) { 60 | SetMessage('error', "Error calling backend plugin"); 61 | return FALSE; 62 | } 63 | $string = $out_list['string']; 64 | print "Backend reported: $string
\n"; 65 | 66 | print "

Picture sent from the backend

\n"; 67 | print "Smily\n"; 68 | 69 | } // End of demoplugin_Run 70 | 71 | 72 | ?> 73 | --------------------------------------------------------------------------------