diff options
Diffstat (limited to 'src/usr/local/www/firewall_shaper_layer7.php')
-rw-r--r-- | src/usr/local/www/firewall_shaper_layer7.php | 614 |
1 files changed, 614 insertions, 0 deletions
diff --git a/src/usr/local/www/firewall_shaper_layer7.php b/src/usr/local/www/firewall_shaper_layer7.php new file mode 100644 index 0000000..db350bd --- /dev/null +++ b/src/usr/local/www/firewall_shaper_layer7.php @@ -0,0 +1,614 @@ +<?php +/* $Id$ */ +/* + firewall_shaper_layer7.php +*/ +/* ==================================================================== + * Copyright (c) 2004-2015 Electric Sheep Fencing, LLC. All rights reserved. + * Copyright (c) 2008 Helder Pereira, André Ribeiro + * + * 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. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * "This product includes software developed by the pfSense Project + * for use in the pfSense software distribution. (http://www.pfsense.org/). + * + * 4. The names "pfSense" and "pfSense Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * coreteam@pfsense.org. + * + * 5. Products derived from this software may not be called "pfSense" + * nor may "pfSense" appear in their names without prior written + * permission of the Electric Sheep Fencing, LLC. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * + * "This product includes software developed by the pfSense Project + * for use in the pfSense software distribution (http://www.pfsense.org/). + * + * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 pfSense PROJECT OR + * ITS CONTRIBUTORS 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. + * + * ==================================================================== + * + */ +/* + pfSense_BUILDER_BINARIES: /usr/bin/killall + pfSense_MODULE: shaper +*/ + +##|+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"); +require('classes/Form.class.php'); +require_once("functions.inc"); +require_once("filter.inc"); +require_once("shaper.inc"); + +$dfltmsg = false; + +// Variables protocols (dynamic) and structures (static) +$avail_protos =& generate_protocols_array(); +$avail_structures = array("action", "queue", "limiter"); + +// Available behaviours +$avail_behaviours_action = array("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(gettext("Firewall"), gettext("Traffic Shaper"), gettext("Layer7")); +$shortcut_section = "trafficshaper"; + +$default_layer7shaper_msg = '<br />' . + gettext('You can add new layer7 protocol patterns by simply uploading the file') . + ' <a href="diag_patterns.php">' . gettext('here') . '</a>'; + +read_layer7_config(); + +$sform = new Form(false); + +if($_GET['reset'] != "") { + // kill all ipfw-classifyd processes + mwexec("killall -9 ipfw-classifyd"); + exit; +} + +if ($_GET) { + if ($_GET['container']) { + $name = htmlspecialchars(trim($_GET['container'])); + } + if ($_GET['action']) { + $action = htmlspecialchars($_GET['action']); + } +} + +if ($_POST) { + if ($_POST['container']) { + $name = htmlspecialchars(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(); + $sform = $container->build_form(); //constructs the graphical interface on the right side + unset($container); + break; + case "show": + $show_proto_form = true; + if($container) { + $sform = $container->build_form(); + } + else { + $show_proto_form = false; + $input_errors[] = gettext("Layer7 Rules Container not found!"); + } + break; + default: + echo log_error("Get default"); + $show_proto_form = false; + $dfltmsg = true; + break; + } +} + +//add a new l7rules container +if ($_POST) { + $show_proto_form = true; + unset($input_errors); + + if($_POST['Submit']) { + + if (isset($layer7_rules_list[$name])) { + $l7r = $layer7_rules_list[$name]; + $_POST['divert_port'] = $l7r->GetRPort(); + } else { + $l7r =& new layer7(); + $_POST['divert_port'] = $l7r->gen_divert_port(); + } + for ($i = 0; $_POST['protocol'][$i] <> ""; $i++) { + $_POST['l7rules'][$i]['protocol'] = $_POST['protocol'][$i]; + $_POST['l7rules'][$i]['structure'] = $_POST['structure'][$i]; + $_POST['l7rules'][$i]['behaviour'] = $_POST['behaviour'][$i]; + } + $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(); + if (write_config()) { + mark_subsystem_dirty('shaper'); + } + + read_layer7_config(); + } else { + if (sizeof($dupes) > 0) { + $dupe_error = gettext("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 lose any previous values + //The user will be able to solve the situation + $sform = $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; + $retval = filter_configure(); + $savemsg = get_std_save_message($retval); + + if (stristr($retval, "error") <> true) { + $savemsg = get_std_save_message($retval); + } else { + $savemsg = $retval; + } + + clear_subsystem_dirty('shaper'); + + if($container) { + $sform = $container->build_form(); + } else { + $show_proto_form = false; + $dfltmsg = true; + } + } else if ($_POST['delete']) { + $container->delete_l7c(); + if (write_config()) { + mark_subsystem_dirty('shaper'); + } + unset($container); + + header("Location: firewall_shaper_layer7.php"); + exit; + } else { + $show_proto_form = false; + } +} + +if(!$_GET && !$_POST) { + $show_proto_form = false; + $dfltmsg = true; +} + +// 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>"; + +include("head.inc"); +?> + +<link rel="stylesheet" type="text/css" media="all" href="./tree/tree.css" /> +<script type="text/javascript" src="./tree/tree.js"></script> + +<script type="text/javascript"> +//<![CDATA[ +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 = ['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; + <?php if (!empty($avail_behaviours_altq)) { + foreach ($avail_behaviours_altq as $key => $queue) { ?> + name = "<?= $queue; ?>"; + index = <?= $key; ?>; + a_behav[index] = name; + <?php } + } ?> + return a_behav; +} + +function array_limiter(a_behav) { + var index; + <?php + if (!empty($avail_behaviours_limiter)) { + foreach ($avail_behaviours_limiter as $key => $limiter) { ?> + name = "<?= $limiter; ?>"; + index = <?= $key; ?>; + a_behav[index] = name; + <?php + } + } ?> + return a_behav; +} + +/* Fill the variables with available protocols, structures and behaviours */ +function fillProtocol() { + var protocol = '<select class="form-control" name="protocol[]">'; + var name; + + <?php foreach ($avail_protos as $key => $proto) { ?> + name = "<?= $proto; ?>"; + protocol += "<option value=" + name + ">" + name + "<\/option>"; + <?php } ?> + protocol += "<\/select>"; + + return protocol; +} + +function fillStructure() { + var structure = '<select class="form-control" name="structure[]" onchange="changeBehaviourValues(this.parentNode.parentNode);">'; + var name; + <?php 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 + } + <?php } ?> + structure += "<\/select>"; + + return structure; +} + +//Used by default to fill the values when inserting a new row. +function fillBehaviour() { + var behaviour = '<select class="form-control" name="behaviour[]">'; + var name; + <?php foreach ($avail_behaviours_action as $key => $behav) { ?> + name = "<?= $behav; ?>"; + behaviour += "<option value=" + name + ">" + name + "<\/option>"; + <?php } ?> + behaviour += "<\/select>"; + + return behaviour; +} + +/* Change the values on behaviours select when changing the structure row */ +function changeBehaviourValues(row) { + + var selectedRow = row.rowIndex - 1; // The header is counted as the first row + 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 = '<a class="btn btn-default" onclick="removeRow(\''+table_id+'\',this.parentNode.parentNode)">Remove<\/a>'; + + 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 +// This function creates a table of rule selectors which are then inserted into the form +// using a StaticText class. While not pretty this maintains compatibility with all of +// the above javascript + +function build_l7table() { + global $container, $avail_protos, $avail_structures, $avail_behaviours_altq, $avail_behaviours_limiter, + $avail_behaviours_action; + + $tbl = '<table id="newtbl" class="table table-hover table-condensed">'; // No stripes for this table + $tbl .= '<thead><tr><th>Protocol</th><th>Structure</th><th>Behavior</th></tr></thead>'; + $tbl .= '<tbody>'; + + if($container) { + foreach($container->rsets as $l7rule) { + + $tbl .= '<tr><td>'; + $tbl .= '<select name="protocol[]" class="form-control">'; + + foreach($avail_protos as $proto): + $tbl .= '<option value="' . $proto . '"'; + + if ($proto == $l7rule->GetRProtocol()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $proto . '</option>'; + + endforeach; + + $tbl .= '</select></td><td>'; + $tbl .= '<select name="structure[]" class="form-control" onchange="changeBehaviourValues(this.parentNode.parentNode);">'; + + foreach($avail_structures as $struct) { + if($struct == "queue") { + if(!empty($avail_behaviours_altq)) { + $tbl .= '<option value="' . $struct . '"'; + if ($struct == $l7rule->GetRStructure()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $struct . '</option>'; + } + } + else { + if($struct == "limiter") { + if(!empty($avail_behaviours_limiter)) { + $tbl .= '<option value="' . $struct . '"'; + if ($struct == $l7rule->GetRStructure()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $struct . '</option>'; + } + } + else { + if($struct == "action") { + $tbl .= '<option value="' . $struct . '"'; + if ($struct == $l7rule->GetRStructure()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $struct . '</option>'; + } + } + } + } + + $tbl .= '</select></td><td>'; + + $tbl .= '<select name="behaviour[]" class="form-control">'; + + if($l7rule->GetRStructure() == "action"): + foreach($avail_behaviours_action as $behaviour): + $tbl .= '<option value="' . $behaviour . '"'; + if ($behaviour == $l7rule->GetRBehaviour()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $behaviour . '</option>'; + + endforeach; + + $tbl .= '</select>'; + + endif; + + if($l7rule->GetRStructure() == "queue"): + foreach($avail_behaviours_altq as $behaviour): + + $tbl .= '<option value="' . $behaviour . '"'; + if ($behaviour == $l7rule->GetRBehaviour()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $behaviour . '</option>'; + + endforeach; + + $tbl .= '</select>'; + + endif; + + if($l7rule->GetRStructure() == "limiter"): + foreach($avail_behaviours_limiter as $behaviour): + $tbl .= '<option value="' . $behaviour . '"'; + if ($behaviour == $l7rule->GetRBehaviour()) + $tbl .= ' selected="selected"'; + + $tbl .= '>' . $behaviour . '</option>'; + + endforeach; + + $tbl .= '</select>'; + + endif; + + $tbl .= '</td><td>'; + $tbl .= '<a type="button" class="btn btn-default" onclick="removeRow(\'newtbl\',this.parentNode.parentNode); return false;" href="#">'; + $tbl .= gettext('Remove') . '</a>'; + $tbl .= '</td></tr>'; + + + } //end foreach + } //end if + + $tbl .= '</tbody></table>'; + + $tbl .= '<a id="addrow" type="button" onclick="javascript:addRow(\'newtbl\'); return false;" href="#" class="btn btn-sm btn-success">' . gettext('Add row') . + '</a>'; + + return($tbl); +} + +if ($input_errors) + print_input_errors($input_errors); + +if ($savemsg) + print_info_box($savemsg, 'success'); + +if (is_subsystem_dirty('shaper')) + print_info_box_np(gettext("The traffic shaper configuration has been changed") . ".<br />" . gettext("You must apply the changes in order for them to take effect.")); + +$tab_array = array(); +$tab_array[] = array(gettext("By Interface"), false, "firewall_shaper.php"); +$tab_array[] = array(gettext("By Queue"), false, "firewall_shaper_queues.php"); +$tab_array[] = array(gettext("Limiter"), false, "firewall_shaper_vinterface.php"); +$tab_array[] = array(gettext("Layer7"), true, "firewall_shaper_layer7.php"); +$tab_array[] = array(gettext("Wizards"), false, "firewall_shaper_wizards.php"); +display_top_tabs($tab_array); + +// Create a StaticText control and populate it with the rules table +if(!$dfltmsg) { + $section = new Form_Section('Add one (or more) rules'); + + $section->addInput(new Form_StaticText( + 'Rule(s)', + build_l7table() + )); + + $sform->add($section); +} +?> + + <div class="panel panel-default"> + <div class="panel-heading" align="center"><h2 class="panel-title">Layer 7</h2></div> + <div class="panel-body"> + <div class="form-group"> + <div class="col-sm-2 "> + <?=$tree?> + <br /> + <a href="firewall_shaper_layer7.php?action=add" class="btn btn-sm btn-success"> + <?=gettext("Create new L7<br />rule group")?> + </a> + </div> + <div class="col-sm-10"> +<?php +if($dfltmsg) + print_info_box($output_form = $dn_default_shaper_msg . $default_layer7shaper_msg); +else + print($sform); +?> + </div> + </div> + </div> + </div> + + +<?php +include("foot.inc");
\ No newline at end of file |