diff --git a/sysutils/smart/Makefile b/sysutils/smart/Makefile
new file mode 100644
index 000000000..e8e94cc5d
--- /dev/null
+++ b/sysutils/smart/Makefile
@@ -0,0 +1,7 @@
+PLUGIN_NAME= smart
+PLUGIN_VERSION= 1.0
+PLUGIN_COMMENT= SMART tools
+PLUGIN_DEPENDS= smartmontools
+PLUGIN_MAINTAINER= franco@opnsense.org
+
+.include "../../Mk/plugins.mk"
diff --git a/sysutils/smart/src/opnsense/mvc/app/models/OPNsense/Smart/ACL/ACL.xml b/sysutils/smart/src/opnsense/mvc/app/models/OPNsense/Smart/ACL/ACL.xml
new file mode 100644
index 000000000..b8845cb8f
--- /dev/null
+++ b/sysutils/smart/src/opnsense/mvc/app/models/OPNsense/Smart/ACL/ACL.xml
@@ -0,0 +1,10 @@
+
+
+
+ WebCfg - Services: SMART
+ Allow access to the 'Services: SMART' page.
+
+ diag_smart.php*
+
+
+
diff --git a/sysutils/smart/src/opnsense/mvc/app/models/OPNsense/Smart/Menu/Menu.xml b/sysutils/smart/src/opnsense/mvc/app/models/OPNsense/Smart/Menu/Menu.xml
new file mode 100644
index 000000000..11e5ac7ec
--- /dev/null
+++ b/sysutils/smart/src/opnsense/mvc/app/models/OPNsense/Smart/Menu/Menu.xml
@@ -0,0 +1,5 @@
+
diff --git a/sysutils/smart/src/www/diag_smart.php b/sysutils/smart/src/www/diag_smart.php
new file mode 100644
index 000000000..e6a99d5d4
--- /dev/null
+++ b/sysutils/smart/src/www/diag_smart.php
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Highlates the words "PASSED", "FAILED", and "WARNING".
+function add_colors($string)
+{
+ // To add words keep arrayes matched by numbers
+ $patterns[0] = '/PASSED/';
+ $patterns[1] = '/FAILED/';
+ $patterns[2] = '/Warning/';
+ $replacements[0] = '' . gettext("PASSED") . '';
+ $replacements[1] = '' . gettext("FAILED") . '';
+ $replacements[2] = '' . gettext("Warning") . '';
+ ksort($patterns);
+ ksort($replacements);
+ return preg_replace($patterns, $replacements, $string);
+}
+
+// What page, aka. action is being wanted
+// If they "get" a page but don't pass all arguments, smartctl will throw an error
+$action = (isset($_POST['action']) ? $_POST['action'] : $_GET['action']);
+$targetdev = basename($_POST['device']);
+if (!file_exists('/dev/' . $targetdev)) {
+ echo "Device does not exist, bailing.";
+ return;
+}
+switch($action) {
+ // Testing devices
+ case 'test':
+ {
+ $test = $_POST['testType'];
+ if (!in_array($test, $valid_test_types)) {
+ echo "Invalid test type, bailing.";
+ return;
+ }
+ $output = add_colors(shell_exec($smartctl . " -t " . escapeshellarg($test) . " /dev/" . escapeshellarg($targetdev)));
+ echo '' . $output . '
+
+ ';
+ break;
+ }
+
+ // Info on devices
+ case 'info':
+ {
+ $type = $_POST['type'];
+ if (!in_array($type, $valid_info_types)) {
+ echo "Invalid info type, bailing.";
+ return;
+ }
+ $output = add_colors(shell_exec($smartctl . " -" . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
+ echo "$output
";
+ break;
+ }
+
+ // View logs
+ case 'logs':
+ {
+ $type = $_POST['type'];
+ if (!in_array($type, $valid_log_types)) {
+ echo "Invalid log type, bailing.";
+ return;
+ }
+ $output = add_colors(shell_exec($smartctl . " -l " . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
+ echo "$output
";
+ break;
+ }
+
+ // Abort tests
+ case 'abort':
+ {
+ $output = shell_exec($smartctl . " -X /dev/" . escapeshellarg($targetdev));
+ echo "$output
";
+ break;
+ }
+
+ // Default page, prints the forms to view info, test, etc...
+ default:
+ {
+
+ // Get all AD* and DA* (IDE and SCSI) devices currently installed and stores them in the $devs array
+ exec("ls /dev | grep '^\(ad\|da\|ada\)[0-9]\{1,2\}$'", $devs);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
' . gettext("Back") . '';
+}
+?>
+
+
" . $ulmsg . "\n"; ?>
+
+
+
+
+
+
+
+
diff --git a/sysutils/smart/src/www/widgets/include/smart_status.inc b/sysutils/smart/src/www/widgets/include/smart_status.inc
new file mode 100644
index 000000000..3b51107f4
--- /dev/null
+++ b/sysutils/smart/src/www/widgets/include/smart_status.inc
@@ -0,0 +1,4 @@
+
+
+
+
+
+
+
+
+
+ 0) {
+ foreach ($devs as $dev) {
+## for each found drive do
+ $dev_ident = exec("diskinfo -v /dev/$dev | grep ident | awk '{print $1}'"); ## get identifier from drive
+ $dev_state = trim(exec("smartctl -H /dev/$dev | awk -F: '/^SMART overall-health self-assessment test result/ {print $2;exit}
+/^SMART Health Status/ {print $2;exit}'")); ## get SMART state from drive
+ $dev_state_translated = "";
+ switch ($dev_state) {
+ case "PASSED":
+ case "OK":
+ $dev_state_translated = gettext('OK');
+ $color = "#90EE90";
+ break;
+ case "":
+ $dev_state = "Unknown";
+ $dev_state_translated = gettext('Unknown');
+ $color = "#C0B788";
+ break;
+ default:
+ $color = "#F08080";
+ break;
+ }
+?>
+
+ |
+ |
+ |
+
+
+