summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelder Pereira <helder.lesi@gmail.com>2008-12-20 23:57:09 +0000
committerHelder Pereira <helder.lesi@gmail.com>2008-12-20 23:57:09 +0000
commitf63d5b66b49abe5190703d9d251b7e2d462e993b (patch)
tree1f58463ec12462516df5cd20fe724bf22862536b
parentadc986ed5e5bb1de0e478dc1e3abf4f493ca1c3f (diff)
downloadpfsense-f63d5b66b49abe5190703d9d251b7e2d462e993b.zip
pfsense-f63d5b66b49abe5190703d9d251b7e2d462e993b.tar.gz
This patch adds the initial support for layer7 protocol inspection gui.
-rw-r--r--etc/inc/shaper.inc390
-rw-r--r--etc/inc/xmlparse.inc4
-rwxr-xr-xusr/local/www/diag_patterns.php130
-rwxr-xr-xusr/local/www/firewall_shaper.php3
-rwxr-xr-xusr/local/www/firewall_shaper_layer7.php592
-rwxr-xr-xusr/local/www/firewall_shaper_queues.php3
-rw-r--r--usr/local/www/firewall_shaper_vinterface.php3
-rwxr-xr-xusr/local/www/firewall_shaper_wizards.php3
8 files changed, 1120 insertions, 8 deletions
diff --git a/etc/inc/shaper.inc b/etc/inc/shaper.inc
index 63a14ff..24b02b4 100644
--- a/etc/inc/shaper.inc
+++ b/etc/inc/shaper.inc
@@ -3032,6 +3032,392 @@ class dnqueue_class extends dummynet_class {
}
}
+// List of layer7 objects
+$layer7_rules_list = array();
+
+class layer7 {
+
+ var $rname; //alias
+ var $rdescription; //alias description
+ var $rport; //divert port
+ var $renabled; //rule enabled
+ var $rsets = array(); //array of l7 associations
+
+ // Auxiliary functions
+
+ function GetRName() {
+ return $this->rname;
+ }
+ function SetRName($rname) {
+ $this->rname = $rname;
+ }
+ function GetRDescription() {
+ return $this->rdescription;
+ }
+ function SetRDescription($rdescription) {
+ $this->rdescription = $rdescription;
+ }
+ function GetRPort() {
+ return $this->rport;
+ }
+ function SetRPort($rport) {
+ $this->rport = $rport;
+ }
+ function GetREnabled() {
+ return $this->renabled;
+ }
+ function SetREnabled($value) {
+ $this->renabled = $value;
+ }
+ function GetRl7() {
+ return $this->rsets;
+ }
+ function SetRl7($rsets) {
+ $this->rsets = $rsets;
+ }
+
+ //Add a tuple (rule,sctructure,element) to the $rsets
+
+ function add_rule($l7set) {
+ $this->rsets[] = $l7set;
+ }
+
+ // Build the layer7 rules
+ function build_l7_rules() {
+ if($this->GetREnabled() == "") {
+ return;
+ }
+ //$l7rules = "#" . $this->rdescription . "\n";
+ foreach ($this->rsets as $rl7) {
+ $l7rules .= $rl7->build_rules();
+ }
+ return $l7rules;
+ }
+
+ // Read the config from array
+ function ReadConfig(&$qname, &$q) {
+ $this->SetRName($qname);
+ $this->SetREnabled($q['enabled']);
+ $this->SetRPort($q['divert_port']);
+ if(isset($q['description']) && $q['description'] <> "")
+ $this->SetRDescription($q['description']);
+ $rsets = $q['l7rules'];
+ //Put individual rules in the array
+ if(is_array($rsets)) {
+ foreach($rsets as $l7r) {
+ $l7obj = new l7rule();
+ $l7obj->SetRProtocol($l7r['protocol']);
+ $l7obj->SetRStructure($l7r['structure']);
+ $l7obj->SetRBehaviour($l7r['behaviour']);
+ $this->add_rule($l7obj);
+ }
+ }
+ }
+
+ //Generate a random port for the divert socket
+ function gen_divert_port() {
+ $dports = get_divert_ports(); //array of used ports
+ $divert_port = rand(40000, 60000);
+ while(true) {
+ foreach($dports as $dport) {
+ $dupe = false;
+ if($dport == $divert_port) {
+ $divert_port = rand(40000, 60000);
+ $dupe = true;
+ break;
+ }
+ }
+ if(!$dupe) {
+ break;
+ }
+ }
+ return $divert_port;
+ }
+
+ //Helps building the left tree
+ function build_tree() {
+ $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&action=show\">";
+ $tree .= $this->GetRName() . "</a>";
+ $tree .= "</li>";
+
+ return $tree;
+ }
+
+ function build_form() {
+ $form = "<tr><td valign=\"top\" class=\"vncellreq\"><br>";
+ $form .= "Enable/Disable";
+ $form .= "</td><td class=\"vncellreq\">";
+ $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\"";
+ if ($this->GetREnabled()) {
+ $form .= "checked = \"CHECKED\"";
+ }
+ $form .= " ><span class=\"vexpl\"> Enable/Disable layer7 Container</span>";
+ $form .= "</td></tr>";
+ $form .= "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
+ $form .= "<td class=\"vncellreq\">";
+ $form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
+ $form .= $this->GetRName()."\">";
+ $form .= "</td></tr>";
+ $form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
+ $form .= "<td class=\"vncellreq\">";
+ $form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
+ $form .= $this->GetRDescription();
+ $form .= "\">";
+ $form .= "<br> <span class=\"vexpl\">";
+ $form .= "You may enter a description here ";
+ $form .= "for your reference (not parsed).</span>";
+ $form .= "</td></tr>";
+
+ return $form;
+ }
+
+ //Write the setting to the $config array
+ function wconfig() {
+ global $config;
+
+ if(!is_array($config['l7shaper']['container'])) {
+ $config['l7shaper']['container'] = array();
+ }
+ //
+ $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
+ // Test if this rule does exists already
+ if(!$cflink) {
+ $cflink =& $config['l7shaper']['container'][];
+ }
+ $cflink['name'] = $this->GetRName();
+ $cflink['enabled'] = $this->GetREnabled();
+ $cflink['description'] = $this->GetRDescription();
+ $cflink['divert_port'] = $this->GetRPort();
+
+ //Destroy previously existent rules
+ if(is_array($cflink['rules'])) {
+ unset($cflink['l7rules']);
+ }
+
+ $cflink['l7rules'] = array();
+
+ $i = 0;
+ foreach($this->rsets as $rulel7) {
+ $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
+ $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
+ $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
+ $i++;
+ }
+ }
+
+ //This function is necessary to help producing the overload options for keep state
+ function get_unique_structures() {
+
+ $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
+ foreach($this->rsets as $l7rule) {
+ if($l7rule->GetRStructure() == "action")
+ $unique_structures['action'] = true;
+ else if($l7rule->GetRStructure() == "limiter")
+ $unique_structures['dummynet'] = true;
+ else
+ $unique_structures['altq'] = true;
+ }
+ //Delete non used structures so we don't have to check this in filter.inc
+ foreach($unique_structures as $key => $value)
+ if(!$value)
+ unset($unique_structures[$key]);
+ return $unique_structures;
+ }
+
+ function validate_input($data, &$input_errors) {
+ $reqfields[] = "container";
+ $reqdfieldsn[] = "Name";
+
+ shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
+
+ if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
+ $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
+ }
+
+ function delete_l7c() {
+ unset_l7_object_by_reference($this->GetRName());
+ cleanup_l7_from_rules($this->GetRName());
+ }
+}
+
+class l7rule {
+
+ var $rprotocol; //protocol
+ var $rstructure; //action, limiter, queue
+ var $rbehaviour; //allow, block, queue_name, pipe_number ...
+
+ //Auxiliary Functions
+
+ function GetRProtocol() {
+ return $this->rprotocol;
+ }
+ function SetRProtocol($rprotocol) {
+ $this->rprotocol = $rprotocol;
+ }
+ function GetRStructure() {
+ return $this->rstructure;
+ }
+ function SetRStructure($rstructure) {
+ $this->rstructure = $rstructure;
+ }
+ function GetRBehaviour() {
+ return $this->rbehaviour;
+ }
+ function SetRBehaviour($rbehaviour) {
+ $this->rbehaviour = $rbehaviour;
+ }
+
+ //XXX Do we need to test any particularity for AltQ queues?
+ function build_rules() {
+ global $dummynet_pipe_list;
+ switch ($this->GetRStructure()) {
+ case "limiter":
+ read_dummynet_config();
+ $dn_list =& get_unique_dnqueue_list();
+ $found = false;
+ if(is_array($dn_list)) {
+ foreach($dn_list as $key => $value) {
+ if($key == $this->GetRBehaviour()) {
+ if($value[0] == "?")
+ $l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
+ else
+ $l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
+ $found = true;
+ }
+ if($found)
+ break;
+ }
+ }
+ break;
+ default: //This is for action and for altq
+ $l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
+ break;
+ }
+ return $l7rule;
+ }
+}
+
+/*
+ * This function allows to return an array with all the used divert socket ports
+ */
+function get_divert_ports() {
+ global $layer7_rules_list;
+ $dports = array();
+
+ foreach($layer7_rules_list as $l7r)
+ $dports[] = $l7r->GetRPort();
+
+ return $dports;
+}
+
+function &get_l7c_reference_to_me_in_config(&$name) {
+ global $config;
+
+ $ptr = NULL;
+
+ if(is_array($config['l7shaper']['container'])) {
+ foreach($config['l7shaper']['container'] as $key => $value) {
+ if($value['name'] == $name)
+ $ptr =& $config['l7shaper']['container'][$key];
+ }
+ }
+ return $ptr;
+// $ptr can be null. has to be checked later
+}
+
+function unset_l7_object_by_reference(&$name) {
+ global $config;
+
+ if(is_array($config['l7shaper']['container'])) {
+ foreach($config['l7shaper']['container'] as $key => $value) {
+ if($value['name'] == $name) {
+ unset($config['l7shaper']['container'][$key]['l7rules']);
+ unset($config['l7shaper']['container'][$key]);
+ break;
+ }
+ }
+ }
+}
+
+function read_layer7_config() {
+ global $layer7_rules_list, $config;
+
+ $l7cs = &$config['l7shaper']['container'];
+
+ $layer7_rules_list = array();
+
+ if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
+ return;
+
+ foreach ($l7cs as $conf) {
+ if (empty($conf['name']))
+ continue; /* XXX: grrrrrr at php */
+ $root =& new layer7();
+ $root->ReadConfig($conf['name'],$conf);
+ $layer7_rules_list[$root->GetRName()] = &$root;
+ }
+}
+
+function generate_layer7_files() {
+ global $layer7_rules_list;
+
+ read_layer7_config();
+
+ if (!empty($layer7_rules_list)) {
+ mwexec("kldload ipdivert.ko");
+ mwexec("killall -9 ipfw-classifyd");
+ }
+
+ foreach($layer7_rules_list as $l7rules) {
+ if($l7rules->GetREnabled()) {
+ $filename = $l7rules->GetRName() . ".l7";
+ $path = "/tmp/" . $filename;
+
+ $rules = $l7rules->build_l7_rules();
+
+ $fp = fopen($path,'w');
+ fwrite($fp,$rules);
+ fclose($fp);
+
+ $ipfw_classifyd_init = "ipfw-classifyd -c " . $path . " -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
+ mwexec($ipfw_classifyd_init);
+ }
+ }
+}
+
+// This function uses /usr/local/share/protocols as a default directory for searching .pat files
+function generate_protocols_array() {
+ $protocols = return_dir_as_array("/usr/local/share/protocols");
+ if(is_array($protocols)) {
+ foreach($protocols as $key => $proto)
+ $protocols[$key] =& str_replace(".pat", "", $proto);
+ sort($protocols);
+ }
+ return $protocols;
+}
+
+function get_l7_unique_list() {
+ global $layer7_rules_list;
+
+ $l7list = array();
+ if(is_array($layer7_rules_list))
+ foreach($layer7_rules_list as $l7c)
+ if($l7c->GetREnabled())
+ $l7list[] = $l7c->GetRName();
+
+ return $l7list;
+}
+
+// Disable a removed l7 container from the filter
+function cleanup_l7_from_rules(&$name) {
+ global $config;
+
+ foreach ($config['filter']['rule'] as $key => $rule) {
+ //We have to change this
+ if ($rule['l7container'] == $name)
+ unset($config['filter']['rule'][$key]['l7container']);
+ }
+}
/*
* XXX: TODO Make a class shaper to hide all these function
@@ -3290,14 +3676,14 @@ $default_shaper_msg = "<tr><td align=\"center\" width=\"80%\" >";
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the pfSense Traffic Shaper.</b><br />";
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
-$default_shaper_ms .= " </p></strong></span>";
+$default_shaper_msg .= " </p></strong></span>";
$default_shaper_msg .= "</td></tr>";
$dn_default_shaper_msg = "<tr><td align=\"center\" width=\"80%\" >";
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the pfSense Traffic Shaper.</b><br />";
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
-$dn_default_shaper_ms .= " </p></strong></span>";
+$dn_default_shaper_msg .= " </p></strong></span>";
$dn_default_shaper_msg .= "</td></tr>";
diff --git a/etc/inc/xmlparse.inc b/etc/inc/xmlparse.inc
index e406f5a..c1caaa7 100644
--- a/etc/inc/xmlparse.inc
+++ b/etc/inc/xmlparse.inc
@@ -36,11 +36,11 @@ function listtags() {
* I know it's a pain, but it's a pain to find stuff too if it's not
*/
$ret = explode(" ",
- "alias aliasurl allowedip authserver bridged ca cacert cert config ".
+ "alias aliasurl allowedip authserver bridged ca cacert cert config container ".
"columnitem depends_on_package disk dnsserver dnsupdate domainoverrides ".
"dyndns earlyshellcmd element encryption-algorithm-option field ".
"fieldname hash-algorithm-option gateway_item gateway_group gif gre ".
- "group hosts member interface_array item key lagg lbaction lbpool ".
+ "group hosts member interface_array item key lagg lbaction lbpool l7rules ".
"lbprotocol member menu tab mobilekey monitor_type mount ntpserver onetoone ".
"openvpn-server openvpn-client openvpn-csc " .
"option ppp package passthrumac phase1 phase2 priv proxyarpnet queue ".
diff --git a/usr/local/www/diag_patterns.php b/usr/local/www/diag_patterns.php
new file mode 100755
index 0000000..551fc44
--- /dev/null
+++ b/usr/local/www/diag_patterns.php
@@ -0,0 +1,130 @@
+<?php
+/* $Id$ */
+/*
+ Exec+ v1.02-000 - Copyright 2001-2003, All rights reserved
+ Created by André Ribeiro and Hélder Pereira
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+##|+PRIV
+##|*IDENT=page-diagnostics-patters
+##|*NAME=Diagnostics: Patterns page
+##|*DESCR=Allow access to the 'Diagnostics: Patterns' page.
+##|*MATCH=patterns.php*
+##|-PRIV
+
+
+require("guiconfig.inc");
+
+//Move the upload file to /usr/local/share/protocols (is_uploaded_file must use tmp_name as argument)
+if (($_POST['submit'] == "Upload") && is_uploaded_file($_FILES['ulfile']['tmp_name'])) {
+ if(fileExtension($_FILES['ulfile']['name'])) {
+ move_uploaded_file($_FILES['ulfile']['tmp_name'], "/usr/local/share/protocols/" . $_FILES['ulfile']['name']);
+ $ulmsg = "Uploaded file to /usr/local/share/protocols/" . htmlentities($_FILES['ulfile']['name']);
+ }
+ else
+ $ulmsg = "Warning: You must upload a file with .pat extension.";
+}
+
+//Check if file has correct extension (.pat)
+function fileExtension($nameFile) {
+ $format = substr($nameFile, -4);
+ return ($format == ".pat");
+}
+
+$pgtitle = array("Diagnostics","Add layer7 pattern");
+include("head.inc");
+?>
+
+
+<style>
+<!--
+
+input {
+ font-family: courier new, courier;
+ font-weight: normal;
+ font-size: 9pt;
+}
+
+pre {
+ border: 2px solid #435370;
+ background: #F0F0F0;
+ padding: 1em;
+ font-family: courier new, courier;
+ white-space: pre;
+ line-height: 10pt;
+ font-size: 10pt;
+}
+
+.label {
+ font-family: tahoma, verdana, arial, helvetica;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+.button {
+ font-family: tahoma, verdana, arial, helvetica;
+ font-weight: bold;
+ font-size: 11px;
+}
+
+-->
+</style>
+</head>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p><strong>You can upload new layer7 patterns to your system!</strong></p>
+<?php if ($ulmsg) echo "<p class=\"red\"><strong>" . $ulmsg . "</strong></p>\n"; ?>
+
+
+<div id="niftyOutter">
+<form action="diag_patterns.php" method="POST" enctype="multipart/form-data" name="frmPattern">
+ <table>
+
+ <tr>
+ <td colspan="2" valign="top" class="vnsepcell">Upload</td>
+ </tr>
+ <tr>
+ <td align="right">File to upload:</td>
+ <td valign="top" class="label">
+ <input name="ulfile" type="file" class="formfld file" id="ulfile">
+ </td></tr>
+ <tr>
+ <td valign="top">&nbsp;&nbsp;&nbsp;</td>
+ <td valign="top" class="label">
+ <input name="submit" type="submit" class="button" id="upload" value="Upload"></td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" height="16"></td>
+ </tr>
+
+ </table>
+</div>
+<?php include("fend.inc"); ?>
+</form>
+</body>
+</html>
+
+<?php
+
+?>
diff --git a/usr/local/www/firewall_shaper.php b/usr/local/www/firewall_shaper.php
index 9f74264..ec803a1 100755
--- a/usr/local/www/firewall_shaper.php
+++ b/usr/local/www/firewall_shaper.php
@@ -424,7 +424,8 @@ include("fbegin.inc");
$tab_array[0] = array("By Interface", true, "firewall_shaper.php");
$tab_array[1] = array("By Queue", false, "firewall_shaper_queues.php");
$tab_array[2] = array("Limiter", false, "firewall_shaper_vinterface.php");
- $tab_array[3] = array("Wizards", false, "firewall_shaper_wizards.php");
+ $tab_array[3] = array("Layer7", false, "firewall_shaper_layer7.php");
+ $tab_array[4] = array("Wizards", false, "firewall_shaper_wizards.php");
display_top_tabs($tab_array);
?>
</td></tr>
diff --git a/usr/local/www/firewall_shaper_layer7.php b/usr/local/www/firewall_shaper_layer7.php
new file mode 100755
index 0000000..71574ec
--- /dev/null
+++ b/usr/local/www/firewall_shaper_layer7.php
@@ -0,0 +1,592 @@
+<?php
+/* $Id$ */
+/*
+ firewall_shaper_layer7.php
+ Copyright (C) 2008 Helder Pereira, André Ribeiro
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+##|+PRIV
+##|*IDENT=page-firewall-trafficshaper-layer7
+##|*NAME=Firewall: Traffic Shaper: Layer7 page
+##|*DESCR=Allow access to the 'Firewall: Traffic Shaper: Layer7' page.
+##|*MATCH=firewall_shaper_layer7.php*
+##|-PRIV
+
+require("guiconfig.inc");
+
+// Variables protocols (dynamic) and structures (static)
+$avail_protos =& generate_protocols_array();
+$avail_structures = array("action","queue","limiter");
+
+// Available behaviours
+$avail_behaviours_action = array("allow","block");
+read_altq_config();
+$avail_behaviours_altq = get_altq_name_list();
+read_dummynet_config();
+$avail_behaviours_limiter = get_dummynet_name_list();
+$show_proto_form = false;
+
+
+//More variables
+$pgtitle = array("Firewall","Traffic Shaper", "Layer7");
+
+$output_form = "";
+
+$default_layer7shaper_msg = "<tr><td colspan=\"4\">";
+$default_layer7shaper_msg .= "<p><span class=\"vexpl\"><span class=\"red\"><strong>Note:<br>";
+$default_layer7shaper_msg .= "</strong></span>You can add new layer7 protocol patterns by simply uploading the file <a href=\"diag_patterns.php\">here.</a><br>";
+$default_layer7shaper_msg .= "</td></tr>";
+
+
+read_layer7_config();
+
+if($_GET['reset'] <> "") {
+ mwexec("killall -9 pfctl php");
+ mwexec("killall -9 ipfw-classifyd"); //kill all ipfw-classifyd processes
+ exit;
+}
+
+if ($_GET) {
+ if ($_GET['container'])
+ $name = trim($_GET['container']);
+ if ($_GET['action'])
+ $action = $_GET['action'];
+}
+
+if($_POST) {
+ if ($_POST['container']) {
+ $name = trim($_POST['container']);
+ }
+}
+
+if ($name) {
+ //Get the object from the 7rules list
+ $container = $layer7_rules_list[$name];
+}
+
+
+if ($_GET) {
+ switch ($action) {
+ case "add":
+ $show_proto_form = true;
+ $container = new layer7();
+ $output_form .= $container->build_form(); //constructs the graphical interface on the right side
+ unset($container);
+ break;
+ case "show":
+ $show_proto_form = true;
+ if($container) {
+ $output_form .= $container->build_form();
+ }
+ else {
+ $show_proto_form = false;
+ $input_errors[] = "Layer7 Rules Container not found!";
+ }
+ break;
+ default:
+ echo log_error("Get default");
+ $show_proto_form = false;
+ $output_form .= "<p class=\"pgtitle\">" . $dn_default_shaper_msg . $default_layer7shaper_msg . "</p>";
+ break;
+ }
+}
+
+//add a new l7rules container
+else if ($_POST) {
+ $show_proto_form = true;
+ unset($input_errors);
+
+ if($_POST['submit']) {
+ $l7r =& new layer7();
+ $_POST['divert_port'] = $l7r->gen_divert_port();
+ for($i=0; $i<100; $i++) {
+ if($_POST['protocol'][$i] <> "") {
+ $_POST['l7rules'][$i]['protocol'] = $_POST['protocol'][$i];
+ $_POST['l7rules'][$i]['structure'] = $_POST['structure'][$i];
+ $_POST['l7rules'][$i]['behaviour'] = $_POST['behaviour'][$i];
+ }
+ else {
+ break;
+ }
+ }
+ $l7r->validate_input($_POST,&$input_errors);
+ $l7r->ReadConfig($_POST['container'], $_POST);
+ //Before writing the results, we need to test for repeated protocols
+ $non_dupes = array();
+ $dupes = array();
+ for($j=0; $j<$i; $j++) {
+ if(!$non_dupes[$_POST['protocol'][$j]])
+ $non_dupes[$_POST['protocol'][$j]] = true;
+ else
+ $dupes[] = $_POST['protocol'][$j];
+ }
+ unset($non_dupes);
+ if(sizeof($dupes) == 0 && !$input_errors) {
+ $l7r->wconfig();
+ write_config();
+ touch($d_shaperconfdirty_path);
+
+ read_layer7_config();
+ }
+ else {
+ if(sizeof($dupes) > 0) {
+ $dupe_error = "Found the following repeated protocol definitions: ";
+ foreach($dupes as $dupe)
+ $dupe_error .= "$dupe ";
+ $input_errors[] .= $dupe_error;
+ }
+ }
+ unset($dupes);
+ unset($dupe_error);
+ //Even if there are repeated protocols, we won't loose any previous values
+ //The user will be able to solve the situation
+ $output_form .= $l7r->build_form();
+ //Necessary to correctly build the proto form
+ $container = $layer7_rules_list[$name];
+ if($input_errors)
+ $container =& $l7r;
+ } else if($_POST['apply']) {
+ write_config();
+
+ $retval = 0;
+ $savemsg = get_std_save_message($retval);
+
+ config_lock();
+ $retval = filter_configure();
+ config_unlock();
+
+ if(stristr($retval, "error") <> true)
+ $savemsg = get_std_save_message($retval);
+ else
+ $savemsg = $retval;
+
+ unlink($d_shaperconfdirty_path);
+
+ if($container) {
+ $output_form .= $container->build_form();
+ } else {
+ $show_proto_form = false;
+ $output_form .= "<p class=\"pgtitle\">" . $dn_default_shaper_msg . $default_layer7shaper_msg . "</p>";
+ }
+ } else if ($_POST['delete']) {
+ $container->delete_l7c();
+ write_config();
+ touch($d_shaperconfdirty_path);
+ unset($container);
+
+ header("Location: firewall_shaper_layer7.php");
+ exit;
+ }
+ else {
+ $show_proto_form = false;
+ }
+}
+else {
+ $show_proto_form = false;
+ $output_form .= "<p class=\"pgtitle\">" . $dn_default_shaper_msg . $default_layer7shaper_msg . "</p>";
+}
+
+// Builds the left tree
+$tree = "<ul class=\"tree\" >";
+if (is_array($layer7_rules_list)) {
+ foreach ($layer7_rules_list as $tmpl7) {
+ $tree .= $tmpl7->build_tree();
+ }
+}
+$tree .= "</ul>";
+
+$output = "<div id=\"shaperarea\" style=\"position:relative\">";
+$output .= $output_form;
+
+include("head.inc");
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" >
+<link rel="stylesheet" type="text/css" media="all" href="./tree/tree.css" />
+<script type="text/javascript" src="./tree/tree.js"></script>
+
+<script language="javascript">
+
+var initial_count = new Array();
+var rows_limit = 0; // Set to 0 to disable limitation
+
+
+/* Build the behaviours arrays in javascript */
+var js_behaviours_action = ['allow', 'block']; //static
+
+var js_behaviours_altq = new Array();
+js_behaviours_altq = array_altq(js_behaviours_altq);
+
+var js_behaviours_limiter = new Array();
+js_behaviours_limiter = array_limiter(js_behaviours_limiter);
+
+function array_altq(a_behav) {
+ var index;
+ <? if (!empty($avail_behaviours_altq)) {
+ foreach ($avail_behaviours_altq as $key => $queue) { ?>
+ name = "<?= $queue; ?>";
+ index = <? echo $key; ?>;
+ a_behav[index] = name;
+ <? }
+ } ?>
+ return a_behav;
+}
+
+function array_limiter(a_behav) {
+ var index;
+ <? if (!empty($avail_behaviours_limiter)) {
+ foreach ($avail_behaviours_limiter as $key => $limiter) { ?>
+ name = "<?= $limiter; ?>";
+ index = <? echo $key; ?>;
+ a_behav[index] = name;
+ <? }
+ } ?>
+ return a_behav;
+}
+
+/* Fill the variables with available protocols, structures and behaviours */
+function fillProtocol() {
+ var protocol = '<select name="protocol[]" id="protocol" style="font-size:8pt">';
+ var name;
+
+ <? foreach ($avail_protos as $key => $proto) { ?>
+ name = "<?= $proto; ?>";
+ protocol += "<option value=" + name + ">" + name + "</option>";
+ <? } ?>
+ protocol += "</select>";
+
+ return protocol;
+}
+
+function fillStructure() {
+ var structure = '<select name="structure[]" id="structure" style="font-size:8pt" onchange="changeBehaviourValues(this.parentNode.parentNode);">';
+ var name;
+ <? foreach ($avail_structures as $key => $struct) { ?>
+ name = "<?= $struct; ?>";
+ if(name == "queue") {
+ if(js_behaviours_altq != "") { structure += "<option value=" + name + ">" + name + "</option>";}
+ }
+ else {
+ if(name == "limiter") {
+ if(js_behaviours_limiter != "") { structure += "<option value=" + name + ">" + name + "</option>";}
+ }
+ else structure += "<option value=" + name + ">" + name + "</option>"; //action
+ }
+ <? } ?>
+ structure += "</select>";
+
+ return structure;
+}
+
+//Used by default to fill the values when inserting a new row.
+function fillBehaviour() {
+ var behaviour = '<select name="behaviour[]" id="behaviour" style="width:80px; font-size:8pt">';
+ var name;
+ <? foreach ($avail_behaviours_action as $key => $behav) { ?>
+ name = "<?= $behav; ?>";
+ behaviour += "<option value=" + name + ">" + name + "</option>";
+ <? } ?>
+ behaviour += "</select>";
+
+ return behaviour;
+}
+
+/* Change the values on behaviours select when changing the structure row */
+function changeBehaviourValues(row) {
+ var selectedRow = row.rowIndex - 2; //because row.rowIndex returns 2, not 0
+ var structureSelected = document.getElementsByName("structure[]")[selectedRow].value;
+
+ //Select the behaviours values to array a_behav
+ var a_behav = new Array();
+ if (structureSelected == "action") {
+ a_behav = js_behaviours_action; //static
+ }
+ else {
+ if (structureSelected == "queue") {
+ a_behav = js_behaviours_altq;
+ }
+ else {
+ a_behav = js_behaviours_limiter;
+ }
+ }
+
+ //Build the html statement with the array values previously selected
+ var new_behav;
+ var name;
+ for(i=0; i<a_behav.length; i++) {
+ new_behav += "<option value=" + a_behav[i] + ">" + a_behav[i] + "</option>";
+ }
+
+ document.getElementsByName("behaviour[]")[selectedRow].innerHTML = new_behav;
+}
+
+/* Add row to the table */
+function addRow(table_id) {
+ var tbl = document.getElementById(table_id);
+ // counting rows in table
+ var rows_count = tbl.rows.length;
+ if (initial_count[table_id] == undefined) {
+ // if it is first adding in this table setting initial rows count
+ initial_count[table_id] = rows_count;
+ }
+ // determining real count of added fields
+ var tFielsNum = rows_count - initial_count[table_id];
+ if (rows_limit!=0 && tFielsNum >= rows_limit) return false;
+
+ var remove = '<input type = "image" src = "/themes/<?echo $g['theme'];?>/images/icons/icon_x.gif" onclick="removeRow(\''+table_id+'\',this.parentNode.parentNode)" value = "Delete" />';
+
+ try {
+ var newRow = tbl.insertRow(rows_count);
+ var newCell = newRow.insertCell(0);
+ newCell.innerHTML = fillProtocol();
+ var newCell = newRow.insertCell(1);
+ newCell.innerHTML = fillStructure();
+ var newCell = newRow.insertCell(2);
+ newCell.innerHTML = fillBehaviour();
+ var newCell = newRow.insertCell(3);
+ newCell.innerHTML = remove;
+ }
+ catch (ex) {
+ //if exception occurs
+ alert(ex);
+ }
+}
+
+/* Remove row from the table */
+function removeRow(tbl,row) {
+ var table = document.getElementById(tbl);
+ try {
+ table.deleteRow(row.rowIndex);
+ } catch (ex) {
+ alert(ex);
+ }
+}
+</script>
+
+<?php
+include("fbegin.inc");
+?>
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+<form action="firewall_shaper_layer7.php" method="post" id="iform" name="iform">
+
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<?php if (file_exists($d_shaperconfdirty_path)): ?><p>
+<?php print_info_box_np("The traffic shaper configuration has been changed.<br>You must apply the changes in order for them to take effect.");?><br>
+<?php endif; ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[0] = array("By Interface", false, "firewall_shaper.php");
+ $tab_array[1] = array("By Queue", false, "firewall_shaper_queues.php");
+ $tab_array[2] = array("Limiter", false, "firewall_shaper_vinterface.php");
+ $tab_array[3] = array("Layer7", true, "firewall_shaper_layer7.php");
+ $tab_array[4] = array("Wizards", false, "firewall_shaper_wizards.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+
+ <?php if (count($layer7_rules_list) > 0): ?>
+ <tr class="tabcont"><td width="25%" align="left">
+ </td><td width="75%"> </td></tr>
+
+ <? endif; ?>
+ <tr>
+ <td width="25%" valign="top" algin="left">
+ <?php
+ echo $tree;
+ ?>
+ <br/><br/>
+ <a href="firewall_shaper_layer7.php?action=add">
+ <img src="./themes/<?=$g['theme']; ?>/images/icons/icon_plus.gif" title="Create new l7 rules group" width="17" height="17" border="0"> Create new l7 rules group
+ </a><br/>
+ </td>
+ <td width="75%" valign="top" align="center">
+ <table>
+ <?
+ echo $output;
+ ?>
+
+ <!-- Layer 7 rules form -->
+ <?php if($show_proto_form): ?>
+ <td width = "22%" valign = "top" class = "vncellreq">
+ <div id = "addressnetworkport">
+ Rule(s)
+ </div>
+ </td>
+
+ <td width = "78%" class = "vtable">
+ <table width="236" id = "maintable">
+ <tbody>
+
+ <tr>
+ <td colspan = "4">
+ <div style = "font-size: 8pt; padding:5px; margin-top: 16px; margin-bottom: 16px; border:1px dashed #000066;"
+ id = "itemhelp">
+ Add one or more rules
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <div style = "font-size: 8pt; padding:5px;"
+ id = "onecolumn">
+ Protocol
+ </div>
+ </td>
+
+ <td>
+ <div style = "font-size: 8pt; padding:5px;"
+ id = "twocolumn">
+ Structure
+ </div>
+ </td>
+
+ <td>
+ <div style = "font-size: 8pt; padding:5px;"
+ id = "threecolumn">
+ Behaviour
+ </div>
+ </td>
+ </tr>
+ <!-- PHP Code to generate the existing rules -->
+ <?php
+ if($container) {
+ foreach($container->rsets as $l7rule) {
+ ?>
+ <tr>
+ <td>
+ <select name="protocol[]" class="formselect" id="protocol" style="font-size:8pt">
+ <?php foreach($avail_protos as $proto): ?>
+ <option value="<?=$proto;?>" <?php if ($proto == $l7rule->GetRProtocol()) echo "selected"; ?>><?=$proto;?></option>
+ <? endforeach; ?>
+ </select>
+ </td>
+ <td>
+ <select name="structure[]" class="formselect" id="structure" style="font-size:8pt" onchange="changeBehaviourValues(this.parentNode.parentNode);">
+ <?php foreach($avail_structures as $struct) {
+ if($struct == "queue") {
+ if(!empty($avail_behaviours_altq)) { ?>
+ <option value="<?=$struct ?>" <?php if ($struct == $l7rule->GetRStructure()) echo "selected"; ?>><?=$struct;?></option>
+ <?php }
+ }
+ else {
+ if($struct == "limiter") {
+ if(!empty($avail_behaviours_limiter)) { ?>
+ <option value="<?=$struct ?>" <?php if ($struct == $l7rule->GetRStructure()) echo "selected"; ?>><?=$struct;?></option>
+ <?php }
+ }
+ else {
+ if($struct == "action") { ?>
+ <option value="<?=$struct ?>" <?php if ($struct == $l7rule->GetRStructure()) echo "selected"; ?>><?=$struct;?></option>
+ <?php }
+ }
+ }
+ } ?>
+ </select>
+ </td>
+ <td>
+ <select name="behaviour[]" class="formselect" id="behaviour" style="width:80px; font-size:8pt">
+ <?php if($l7rule->GetRStructure() == "action"): ?>
+ <?php foreach($avail_behaviours_action as $behaviour): ?>
+ <option value="<?=$behaviour ?>" <?php if ($behaviour == $l7rule->GetRBehaviour()) echo "selected"; ?>><?=$behaviour;?></option>
+ <? endforeach; ?>
+ </select>
+ <? endif; ?>
+ <?php if($l7rule->GetRStructure() == "queue"): ?>
+ <?php foreach($avail_behaviours_altq as $behaviour): ?>
+ <option value="<?=$behaviour ?>" <?php if ($behaviour == $l7rule->GetRBehaviour()) echo "selected"; ?>><?=$behaviour;?></option>
+ <? endforeach; ?>
+ </select>
+ <? endif; ?>
+ <?php if($l7rule->GetRStructure() == "limiter"): ?>
+ <?php foreach($avail_behaviours_limiter as $behaviour): ?>
+ <option value="<?=$behaviour ?>" <?php if ($behaviour == $l7rule->GetRBehaviour()) echo "selected"; ?>><?=$behaviour;?></option>
+ <? endforeach; ?>
+ </select>
+ <? endif; ?>
+ </td>
+ <td>
+ <input type="image" src="/themes/<? echo $g['theme'];?>/images/icons/icon_x.gif" onclick="removeRow('maintable',this.parentNode.parentNode); return false;" value="Delete" />
+ </td>
+ </tr>
+
+ <?php
+ } //end foreach
+ } //end if
+ ?>
+ </tbody>
+
+ <tfoot>
+ </tfoot>
+ </table>
+
+ <a onclick = "javascript:addRow('maintable'); return false;" href="#"> <img border = "0"
+ src = "/themes/<?=$g['theme']; ?>/images/icons/icon_plus.gif"
+ alt = "" title = "add another entry" /> </a>
+ </td>
+ </tr>
+
+ <tr>
+ <td width = "22%" valign = "top">
+ &nbsp;
+ </td>
+
+ <td width = "78%">
+ <input id = "submit"
+ name = "submit" type = "submit" class = "formbtn" value = "Save" />
+
+ <a href= "firewall_shaper_layer7.php">
+ <input id = "cancelbutton"
+ name = "cancelbutton" type = "button" class = "formbtn" value = "Cancel" /></a>
+
+ <?php if($container): ?>
+ <input id = "delete" type="submit" class="formbtn" name="delete" value="Delete"></a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <!-- End of layer7 rules form -->
+ </table>
+
+ </td></tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc");
+?>
+</body>
+</html> \ No newline at end of file
diff --git a/usr/local/www/firewall_shaper_queues.php b/usr/local/www/firewall_shaper_queues.php
index 061314b..342083e 100755
--- a/usr/local/www/firewall_shaper_queues.php
+++ b/usr/local/www/firewall_shaper_queues.php
@@ -188,7 +188,8 @@ include("head.inc");
$tab_array[0] = array("By Interface", false, "firewall_shaper.php");
$tab_array[1] = array("By Queue", true, "firewall_shaper_queues.php");
$tab_array[2] = array("Limiter", false, "firewall_shaper_vinterface.php");
- $tab_array[3] = array("Wizards", false, "firewall_shaper_wizards.php");
+ $tab_array[3] = array("Layer7", false, "firewall_shaper_layer7.php");
+ $tab_array[4] = array("Wizards", false, "firewall_shaper_wizards.php");
display_top_tabs($tab_array);
?>
</td></tr>
diff --git a/usr/local/www/firewall_shaper_vinterface.php b/usr/local/www/firewall_shaper_vinterface.php
index b1bf9a5..75b7e6c 100644
--- a/usr/local/www/firewall_shaper_vinterface.php
+++ b/usr/local/www/firewall_shaper_vinterface.php
@@ -367,7 +367,8 @@ include("fbegin.inc");
$tab_array[0] = array("By Interface", false, "firewall_shaper.php");
$tab_array[1] = array("By Queue", false, "firewall_shaper_queues.php");
$tab_array[2] = array("Limiter", true, "firewall_shaper_vinterface.php");
- $tab_array[3] = array("Wizards", false, "firewall_shaper_wizards.php");
+ $tab_array[3] = array("Layer7", false, "firewall_shaper_layer7.php");
+ $tab_array[4] = array("Wizards", false, "firewall_shaper_wizards.php");
display_top_tabs($tab_array);
?>
</td></tr>
diff --git a/usr/local/www/firewall_shaper_wizards.php b/usr/local/www/firewall_shaper_wizards.php
index a086cc1..2290a3f 100755
--- a/usr/local/www/firewall_shaper_wizards.php
+++ b/usr/local/www/firewall_shaper_wizards.php
@@ -97,7 +97,8 @@ include("fbegin.inc");
$tab_array[0] = array("By Interface", false, "firewall_shaper.php");
$tab_array[1] = array("By Queue", false, "firewall_shaper_queues.php");
$tab_array[2] = array("Limiter", false, "firewall_shaper_vinterface.php");
- $tab_array[3] = array("Wizards", true, "firewall_shaper_wizards.php");
+ $tab_array[3] = array("Layer7", false, "firewall_shaper_layer7.php");
+ $tab_array[4] = array("Wizards", true, "firewall_shaper_wizards.php");
display_top_tabs($tab_array);
?>
</td></tr>
OpenPOWER on IntegriCloud