#
# Patch for issue 1026
# Violation with action autoreg is only triggered if node is not registered 
#
# Olivier Bilodeau <obilodeau@inverse.ca>
# Code is under the GPL.
#
# patch "pf/lib/pf/action.pm"
#  from [12e000427fbace7f04adcdb3427e264f500fc797]
#    to [3c826d5c6e15b347505a30a5baf6edbc7c220928]
# 
# patch "pf/lib/pf/node.pm"
#  from [a5428d33d0447683867234c82470ca1d5c41e823]
#    to [66513fa2ffa484cb21775541e940ca268a9a63d1]
# 
# patch "pf/lib/pf/violation.pm"
#  from [643f41e2586aac0d9a9e0a2afb3edbf270c50905]
#    to [2ffc74e901d35af82af081653c07320d90096bd7]
#
============================================================
--- pf/lib/pf/action.pm	12e000427fbace7f04adcdb3427e264f500fc797
+++ pf/lib/pf/action.pm	3c826d5c6e15b347505a30a5baf6edbc7c220928
@@ -21,9 +21,18 @@ use Log::Log4perl;
 use strict;
 use warnings;
 use Log::Log4perl;
+use Readonly;
 
 use constant ACTION => 'action';
 
+# Action types constants
+#FIXME port all hard-coded strings to these constants
+Readonly::Scalar our $AUTOREG => 'autoreg';
+Readonly::Scalar our $TRAP => 'trap';
+Readonly::Scalar our $LOG => 'log';
+Readonly::Scalar our $EXTERNAL => 'external';
+Readonly::Scalar our $WINPOPUP => 'winpopup';
+
 BEGIN {
     use Exporter ();
     our ( @ISA, @EXPORT );
@@ -31,7 +40,7 @@ BEGIN {
     @EXPORT = qw(
         $action_db_prepared  action_db_prepare
 
-        action_add 
+        action_add           action_exist
         action_view          action_view_all
         action_delete        action_delete_all 
         action_execute       action_log
============================================================
--- pf/lib/pf/node.pm	a5428d33d0447683867234c82470ca1d5c41e823
+++ pf/lib/pf/node.pm	66513fa2ffa484cb21775541e940ca268a9a63d1
@@ -64,6 +64,7 @@ BEGIN {
         node_update_lastarp
         node_mac_wakeup
         is_node_voip
+        is_node_registered
     );
 }
 
@@ -854,7 +855,26 @@ sub is_node_voip {
     }
 }
 
+=item * is_node_registered
 
+Is given MAC registered or not?
+
+in: mac address
+
+=cut
+sub is_node_registered {
+    my ($mac) = @_;
+    my $logger = Log::Log4perl::get_logger('pf::node');
+
+    $logger->trace("Asked wether node $mac is registered or not");
+    my $node_info = node_view($mac);   
+    if ($node_info->{'status'} eq $STATUS_REGISTERED) {
+        return $TRUE;
+    } else {
+        return $FALSE;
+    }
+}
+
 =item * node_category_handling - assigns category_id based on provided data
 
 expects category_id or category name in the form of category => 'name' or category_id => id
============================================================
--- pf/lib/pf/violation.pm	643f41e2586aac0d9a9e0a2afb3edbf270c50905
+++ pf/lib/pf/violation.pm	2ffc74e901d35af82af081653c07320d90096bd7
@@ -59,6 +59,7 @@ BEGIN {
     );
 }
 
+use pf::action;
 use pf::config;
 use pf::db;
 use pf::node;
@@ -364,8 +365,7 @@ sub violation_add {
         $mac, $vid, $data{start_date}, $data{release_date}, $data{status}, $data{ticket_ref}, $data{notes})
         || return (0);
     $logger->info("violation $vid added for $mac");
-    require pf::action;
-    pf::action::action_execute( $mac, $vid, $data{notes} );
+    action_execute( $mac, $vid, $data{notes} );
     return (1);
 }
 
@@ -443,10 +443,21 @@ sub violation_trigger {
         # we test here AND in violation_add because here we avoid a fork (and violation_add is called from elsewhere)
         my ($remaining_time) = violation_grace( $mac, $vid );
         if ($remaining_time > 0) {
-            $logger->info("$remaining_time grace remaining on violation $vid (trigger ${type}::${tid}) for node $mac. Not adding violation.");
+            $logger->info(
+                "$remaining_time grace remaining on violation $vid (trigger ${type}::${tid}) for node $mac. " . 
+                "Not adding violation."
+            );
             next;
         }
 
+        # if violation is of action autoreg and the node is already registered 
+        if (action_exist($vid, $pf::action::AUTOREG) && is_node_registered($mac)) {
+            $logger->debug(
+                "violation $vid triggered with action $pf::action::AUTOREG but node $mac is already registered. " .
+                "Not adding violation."
+            );
+            next;
+        }
         $logger->info("calling '$bin_dir/pfcmd violation add vid=$vid,mac=$mac' (trigger ${type}::${tid})");
         # forking a pfcmd because it will call a vlan flip if needed
         `$bin_dir/pfcmd violation add vid=$vid,mac=$mac`;
