#
# MAC violation trigger (#1320)
# Licensed under the GPLv2
# Olivier Bilodeau <obilodeau@inverse.ca>
#
# old_revision [79f9a51108298a97126498dbec4bcfec36dabfff]
#
# add_file "pf/db/upgrade-3.0.2-3.1.0.sql"
#  content [27473f91ac8f1d89d0365f0b8fdb35378e0aa230]
# 
# patch "pf/conf/violations.conf"
#  from [f0b1ba224259ba39c9b9a9e67fceff4558100b5b]
#    to [086b525719451984602433bf3f444c25f30d0631]
# 
# patch "pf/lib/pf/config.pm"
#  from [bc2636adc3f2fcb03a80c04f5b2aab7a74c37adb]
#    to [7d1bbe10f869919d35e23dd7214efd5aea0b650a]
# 
# patch "pf/lib/pf/node.pm"
#  from [ba7b12a6f288f1356bb3f4b459d469c96aa7263f]
#    to [313efdee2575a2966fae1e7bf3babdf7cddfa7dc]
# 
# patch "pf/lib/pf/util.pm"
#  from [6c8d40a7f2620ee276e6bffc42d004cca16838d0]
#    to [8fe36dc9d40ec5bb951e1c1d89f9ef94ee32f0ec]
#
============================================================
--- pf/db/upgrade-3.0.2-3.1.0.sql	27473f91ac8f1d89d0365f0b8fdb35378e0aa230
+++ pf/db/upgrade-3.0.2-3.1.0.sql	27473f91ac8f1d89d0365f0b8fdb35378e0aa230
@@ -0,0 +1,9 @@
+--
+-- Swapping from integer to varchar on the trigger ids.
+-- We can still do ranges because MySQL appropriately casts stuff.
+--
+
+ALTER TABLE `trigger`
+	MODIFY `tid_start` varchar(255) NOT NULL,
+	MODIFY `tid_end` varchar(255) NOT NULL
+;
============================================================
--- pf/conf/violations.conf	f0b1ba224259ba39c9b9a9e67fceff4558100b5b
+++ pf/conf/violations.conf	086b525719451984602433bf3f444c25f30d0631
@@ -96,6 +96,19 @@ enabled=N
 actions=trap,email,log
 enabled=N
 
+#
+# Example config to be alerted of the presence of one specific MAC address in the network.
+# Useful for stolen devices if you happen to know the MAC of a stolen device.
+# Trigger format: The number is a decimal representation of the MAC.
+# To generate such a representation you can use perl -e 'print hex("f04da2cbd9c5"),"\n";'. Ignore the warning.
+#
+[1100008]
+desc=MAC isolation example
+url=/remediation.php?template=banned_devices
+trigger=MAC::264216234416581
+actions=email,log
+enabled=N
+
 [1100010]
 desc=Rogue DHCP
 url=/remediation.php?template=roguedhcp
============================================================
--- pf/lib/pf/config.pm	bc2636adc3f2fcb03a80c04f5b2aab7a74c37adb
+++ pf/lib/pf/config.pm	7d1bbe10f869919d35e23dd7214efd5aea0b650a
@@ -116,7 +116,7 @@ $dhcp_fingerprints_url = 'http://www.pac
 $oui_url               = 'http://standards.ieee.org/regauth/oui/oui.txt';
 $dhcp_fingerprints_url = 'http://www.packetfence.org/dhcp_fingerprints.conf';
 
-Readonly our @VALID_TRIGGER_TYPES => ( "scan", "detect", "internal", "os", "vendormac", "useragent" );
+Readonly our @VALID_TRIGGER_TYPES => ( "scan", "detect", "internal", "os", "vendormac", "mac", "useragent" );
 
 $portscan_sid = 1200003;
 $default_pid  = 1;
============================================================
--- pf/lib/pf/node.pm	ba7b12a6f288f1356bb3f4b459d469c96aa7263f
+++ pf/lib/pf/node.pm	313efdee2575a2966fae1e7bf3babdf7cddfa7dc
@@ -74,6 +74,7 @@ use pf::util;
 use pf::nodecategory;
 use pf::scan qw($SCAN_VID);
 use pf::util;
+use pf::violation;
 
 # The next two variables and the _prepare sub are required for database handling magic (see pf::db)
 our $node_db_prepared = 0;
@@ -859,10 +860,13 @@ sub node_mac_wakeup {
     my $logger = Log::Log4perl::get_logger('pf::node');
 
     # Is there a violation for the Vendor of this MAC?
-    require pf::violation;
-    my $dec_oui = get_decimal_oui_from_mac($mac);
-    $logger->debug( "sending MAC::$dec_oui ($mac) trigger" );
+    my $dec_oui = macoui2nb($mac);
+    $logger->debug( "sending VENDORMAC::$dec_oui trigger" );
     pf::violation::violation_trigger( $mac, $dec_oui, "VENDORMAC" );
+
+    my $dec_mac = mac2nb($mac);
+    $logger->debug( "sending MAC::$dec_mac trigger" );
+    pf::violation::violation_trigger( $mac, $dec_mac, "MAC" );
 }
 
 =item * is_node_voip
============================================================
--- pf/lib/pf/util.pm	6c8d40a7f2620ee276e6bffc42d004cca16838d0
+++ pf/lib/pf/util.pm	8fe36dc9d40ec5bb951e1c1d89f9ef94ee32f0ec
@@ -33,7 +33,7 @@ BEGIN {
     @ISA = qw(Exporter);
     @EXPORT = qw(
         valid_date valid_ip reverse_ip clean_ip 
-        clean_mac valid_mac get_decimal_oui_from_mac whitelisted_mac trappable_mac format_mac_for_acct
+        clean_mac valid_mac mac2nb macoui2nb whitelisted_mac trappable_mac format_mac_for_acct
         trappable_ip reggable_ip
         inrange_ip ip2gateway ip2interface ip2device isinternal pfmailer isenabled
         isdisabled getlocalmac ip2int int2ip 
@@ -205,28 +205,48 @@ sub valid_mac {
     }
 }
 
-=item * get_decimal_oui_from_mac
+=item * macoui2nb
 
 Extract the OUI (Organizational Unique Identifier) from a MAC address then
-converts it into a decimal value. To be used to generate mac address violations.
+converts it into a decimal value. To be used to generate vendormac violations.
 
-in: mac address (xx:xx:xx:xx:xx)
+in: MAC address (of xx:xx:xx:xx:xx format)
 
-out: an int
+Returns a number.
 
 =cut
-
-sub get_decimal_oui_from_mac {
+sub macoui2nb {
     my ($mac) = @_;
 
-    return (0) if ( !valid_mac($mac) );
-    $mac = clean_mac($mac);
-
     my $oui = substr($mac, 0, 8);
     $oui =~ s/://g;
     return hex($oui);
 }
 
+=item * mac2nb
+
+Converts a MAC address into a decimal value. To be used to generate mac violations.
+
+in: MAC address (of xx:xx:xx:xx:xx format)
+
+Returns a number.
+
+=cut
+sub mac2nb {
+    my ($mac) = @_;
+    my $nb;
+
+    $mac =~ s/://g;
+    # disabling warnings in this scope because a MAC address (48bit) is larger than an int on 32bit systems
+    # and perl warns about it but gives the right value.
+    {
+        no warnings;
+        $nb = hex($mac);
+    }
+
+    return $nb;
+}
+
 sub whitelisted_mac {
     my ($mac) = @_;
     my $logger = Log::Log4perl::get_logger('pf::util');
