%PDF- %PDF-
Direktori : /backups/router/usr/local/www/ |
Current File : //backups/router/usr/local/www/firewall_nat_edit.php |
<?php /* * Copyright (C) 2014 Deciso B.V. * Copyright (C) 2009 Janne Enberg <janne.enberg@lietu.net> * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net> * 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. */ require_once("guiconfig.inc"); require_once("filter.inc"); $a_nat = &config_read_array('nat', 'rule'); if ($_SERVER['REQUEST_METHOD'] === 'GET') { // load form data from config if (isset($_GET['id']) && is_numericint($_GET['id']) && isset($a_nat[$_GET['id']])) { $id = $_GET['id']; $configId = $id; // load form data from id } elseif (isset($_GET['dup']) && isset($a_nat[$_GET['dup']])){ $after = $_GET['dup']; $configId = $_GET['dup']; // load form data from id } if (isset($_GET['after']) && isset($a_nat[$_GET['after']])) { $after = $_GET['after']; } // initialize form and set defaults $pconfig = array(); $pconfig['protocol'] = "tcp"; $pconfig['srcbeginport'] = "any"; $pconfig['srcendport'] = "any"; $pconfig['interface'] = ["wan"]; $pconfig['dstbeginport'] = 80 ; $pconfig['dstendport'] = 80 ; $pconfig['local-port'] = 80; $pconfig['associated-rule-id'] = "add-associated"; if (isset($configId)) { // copy 1-on-1 foreach (array('protocol','target','local-port','descr','interface','nosync','log', 'natreflection','created','updated','ipprotocol','tag','tagged','poolopts', 'category') as $fieldname) { if (isset($a_nat[$configId][$fieldname])) { $pconfig[$fieldname] = $a_nat[$configId][$fieldname]; } else { $pconfig[$fieldname] = null; } } // fields with some kind of logic. if (!isset($_GET['dup']) && isset($a_nat[$configId]['associated-rule-id'])) { $pconfig['associated-rule-id'] = $a_nat[$configId]['associated-rule-id']; } $pconfig['disabled'] = isset($a_nat[$configId]['disabled']); $pconfig['nordr'] = isset($a_nat[$configId]['nordr']); $pconfig['interface'] = explode(",", $pconfig['interface']); address_to_pconfig($a_nat[$configId]['source'], $pconfig['src'], $pconfig['srcmask'], $pconfig['srcnot'], $pconfig['srcbeginport'], $pconfig['srcendport']); address_to_pconfig($a_nat[$configId]['destination'], $pconfig['dst'], $pconfig['dstmask'], $pconfig['dstnot'], $pconfig['dstbeginport'], $pconfig['dstendport']); if (empty($pconfig['ipprotocol'])) { if (strpos($pconfig['src'].$pconfig['dst'].$pconfig['target'], ":") !== false) { $pconfig['ipprotocol'] = 'inet6'; } else { $pconfig['ipprotocol'] = 'inet'; } } } elseif (isset($_GET['template']) && $_GET['template'] == 'transparent_proxy') { // new rule for transparent proxy reflection, to use as sample $pconfig['interface'] = ["lan"]; $pconfig['src'] = "lan"; $pconfig['dst'] = "any"; $pconfig['ipprotocol'] = "inet"; if (isset($_GET['https'])){ $pconfig['dstbeginport'] = 443; $pconfig['dstendport'] = 443; if (isset($config['OPNsense']['proxy']['forward']['sslbumpport'])) { $pconfig['local-port'] = $config['OPNsense']['proxy']['forward']['sslbumpport']; } else { $pconfig['local-port'] = 3129; } } else { $pconfig['dstbeginport'] = 80; $pconfig['dstendport'] = 80; // try to read the proxy configuration to determine the current port // this has some disadvantages in case of dependencies, but there isn't // a much better solution available at the moment. if (isset($config['OPNsense']['proxy']['forward']['port'])) { $pconfig['local-port'] = $config['OPNsense']['proxy']['forward']['port']; } else { $pconfig['local-port'] = 3128; } } $pconfig['target'] = '127.0.0.1'; $pconfig['natreflection'] = 'enable'; $pconfig['descr'] = gettext("redirect traffic to proxy"); } else { $pconfig['src'] = "any"; } // init empty fields foreach (array('dst','dstmask','srcmask','dstbeginport','dstendport','target', 'local-port','natreflection','descr','disabled','nosync','ipprotocol', 'tag','tagged','poolopts') as $fieldname) { if (!isset($pconfig[$fieldname])) { $pconfig[$fieldname] = null; } } $pconfig['category'] = !empty($pconfig['category']) ? explode(",", $pconfig['category']) : []; } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { $pconfig = $_POST; $input_errors = array(); // validate id and store if usable if (isset($pconfig['id']) && is_numericint($pconfig['id']) && isset($a_nat[$pconfig['id']])) { $id = $_POST['id']; } if (isset($pconfig['after']) && isset($a_nat[$pconfig['after']])) { // place record after provided sequence number $after = $pconfig['after']; } /* Validate input data */ if ($pconfig['protocol'] == 'tcp' || $pconfig['protocol'] == 'udp' || $pconfig['protocol'] == 'tcp/udp') { $reqdfields = explode(" ", "interface protocol dstbeginport dstendport"); $reqdfieldsn = array(gettext("Interface"),gettext("Protocol"),gettext("Destination port from"),gettext("Destination port to")); } else { $reqdfields = explode(" ", "interface protocol"); $reqdfieldsn = array(gettext("Interface"),gettext("Protocol")); } $reqdfields[] = "src"; $reqdfieldsn[] = gettext("Source address"); $reqdfields[] = "dst"; $reqdfieldsn[] = gettext("Destination address"); if (empty($pconfig['nordr'])) { $reqdfields[] = "target"; $reqdfieldsn[] = gettext("Redirect target IP"); } do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors); if (!isset($pconfig['nordr']) && ($pconfig['target'] && !is_ipaddroralias($pconfig['target']) && !is_subnet($pconfig['target']))) { $input_errors[] = sprintf(gettext("\"%s\" is not a valid redirect target IP address, network or host alias."), $pconfig['target']); } if (!empty($pconfig['srcbeginport']) && $pconfig['srcbeginport'] != 'any' && !is_portoralias($pconfig['srcbeginport'])) $input_errors[] = sprintf(gettext("%s is not a valid start source port. It must be a port alias or integer between 1 and 65535."), $pconfig['srcbeginport']); if (!empty($pconfig['srcendport']) && $pconfig['srcendport'] != 'any' && !is_portoralias($pconfig['srcendport'])) $input_errors[] = sprintf(gettext("%s is not a valid end source port. It must be a port alias or integer between 1 and 65535."), $pconfig['srcendport']); if (!empty($pconfig['dstbeginport']) && $pconfig['dstbeginport'] != 'any' && !is_portoralias($pconfig['dstbeginport'])) $input_errors[] = sprintf(gettext("%s is not a valid start destination port. It must be a port alias or integer between 1 and 65535."), $pconfig['dstbeginport']); if (!empty($pconfig['dstendport']) && $pconfig['dstendport'] != 'any' && !is_portoralias($pconfig['dstendport'])) $input_errors[] = sprintf(gettext("%s is not a valid end destination port. It must be a port alias or integer between 1 and 65535."), $pconfig['dstendport']); if (($pconfig['protocol'] == "tcp" || $pconfig['protocol'] == "udp" || $_POST['protocol'] == "tcp/udp") && (!isset($pconfig['nordr']) && !is_portoralias($pconfig['local-port']))) { $input_errors[] = sprintf(gettext("A valid redirect target port must be specified. It must be a port alias or integer between 1 and 65535."), $pconfig['local-port']); } if (!is_specialnet($pconfig['src']) && !is_ipaddroralias($pconfig['src'])) { $input_errors[] = sprintf(gettext("%s is not a valid source IP address or alias."), $pconfig['src']); } // validate ipv4/v6, addresses should use selected address family foreach (array('src', 'dst', 'target') as $fieldname) { if (is_ipaddrv6($pconfig[$fieldname]) && $pconfig['ipprotocol'] != 'inet6') { $input_errors[] = sprintf(gettext("%s is not a valid IPv4 address."), $pconfig[$fieldname]); } if (is_ipaddrv4($pconfig[$fieldname]) && $pconfig['ipprotocol'] != 'inet') { $input_errors[] = sprintf(gettext("%s is not a valid IPv6 address."), $pconfig[$fieldname]); } } if (!empty($pconfig['srcmask']) && !is_numericint($pconfig['srcmask'])) { $input_errors[] = gettext("A valid source bit count must be specified."); } if (!is_specialnet($pconfig['dst']) && !is_ipaddroralias($pconfig['dst'])) { $input_errors[] = sprintf(gettext("%s is not a valid destination IP address or alias."), $pconfig['dst']); } if (!empty($pconfig['dstmask']) && !is_numericint($pconfig['dstmask'])) { $input_errors[] = gettext("A valid destination bit count must be specified."); } if (!isset($_POST['nordr']) && is_numericint($pconfig['dstbeginport']) && is_numericint($pconfig['dstendport']) && is_numericint($pconfig['local-port']) && (max($pconfig['dstendport'],$pconfig['dstbeginport']) - min($pconfig['dstendport'],$pconfig['dstbeginport']) + $pconfig['local-port']) > 65535) { $input_errors[] = gettext("The target port range must be an integer between 1 and 65535."); } if (count($input_errors) == 0) { $natent = array(); if ($pconfig['protocol'] != 'any') { $natent['protocol'] = $pconfig['protocol']; } $natent['interface'] = !empty($pconfig['interface']) ? implode(",", $pconfig['interface']) : null; $natent['category'] = !empty($pconfig['category']) ? implode(",", $pconfig['category']) : null; $natent['ipprotocol'] = $pconfig['ipprotocol']; $natent['descr'] = $pconfig['descr']; $natent['tag'] = $pconfig['tag']; $natent['tagged'] = $pconfig['tagged']; $natent['poolopts'] = $pconfig['poolopts']; if (!empty($natent['nordr'])) { $natent['associated-rule-id'] = ''; } elseif (!empty($pconfig['associated-rule-id']) && $pconfig['associated-rule-id'] == "pass") { $natent['associated-rule-id'] = "pass"; } elseif (!empty($pconfig['associated-rule-id']) && !in_array($pconfig['associated-rule-id'], ['add-associated', 'add-unassociated'])) { $natent['associated-rule-id'] = $pconfig['associated-rule-id']; } else { $natent['associated-rule-id'] = null; } $natent['disabled'] = !empty($pconfig['disabled']); $natent['nordr'] = !empty($pconfig['nordr']); $natent['nosync'] = !empty($pconfig['nosync']); $natent['log'] = !empty($pconfig['log']); if (empty($natent['nordr'])) { $natent['target'] = $pconfig['target']; $natent['local-port'] = $pconfig['local-port']; } pconfig_to_address($natent['source'], $pconfig['src'], $pconfig['srcmask'], !empty($pconfig['srcnot']), $pconfig['srcbeginport'], $pconfig['srcendport']); pconfig_to_address($natent['destination'], $pconfig['dst'], $pconfig['dstmask'], !empty($pconfig['dstnot']), $pconfig['dstbeginport'], $pconfig['dstendport']); if ($pconfig['natreflection'] == "purenat" || $pconfig['natreflection'] == "disable") { $natent['natreflection'] = $pconfig['natreflection']; } // If we used to have an associated filter rule, but no-longer should have one if (isset($id) && !empty($a_nat[$id]['associated-rule-id']) && ( empty($natent['associated-rule-id']) || $natent['associated-rule-id'] != $a_nat[$id]['associated-rule-id'] ) ) { // Delete the previous rule foreach ($config['filter']['rule'] as $key => $item){ if (isset($item['associated-rule-id']) && $item['associated-rule-id']==$a_nat[$id]['associated-rule-id'] ){ unset($config['filter']['rule'][$key]); break; } } mark_subsystem_dirty('filter'); } // Updating a rule with a filter rule associated if (!empty($natent['associated-rule-id']) || in_array($pconfig['associated-rule-id'], ['add-associated', 'add-unassociated'])) { /* auto-generate a matching firewall rule */ $filterent = ['type' => 'pass']; if (in_array($pconfig['associated-rule-id'], ['add-associated', 'add-unassociated'])) { $filterent['associated-rule-id'] = $natent['associated-rule-id']; } else { $filterent['associated-rule-id'] = $natent['associated-rule-id']; foreach ($config['filter']['rule'] as $key => &$item){ if (isset($item['associated-rule-id']) && $item['associated-rule-id']==$natent['associated-rule-id']) { $filterent = &config_read_array('filter', 'rule', $key); break; } } } pconfig_to_address($filterent['source'], $pconfig['src'], $pconfig['srcmask'], !empty($pconfig['srcnot']), $pconfig['srcbeginport'], $pconfig['srcendport']); // Update interface, protocol and destination $filterent['interface'] = $natent['interface']; $filterent['statetype'] = "keep state"; if (!empty($natent['protocol'])) { $filterent['protocol'] = $natent['protocol']; } elseif (isset($filterent['protocol'])) { unset($filterent['protocol']); } $filterent['ipprotocol'] = $natent['ipprotocol']; if (!isset($filterent['destination'])) { $filterent['destination'] = array(); } $filterent['destination']['address'] = $pconfig['target']; if (count($pconfig['interface']) > 1) { $filterent['floating'] = true; $filterent['quick'] = "yes"; } else { unset($filterent['floating']); unset($filterent['quick']); } if (!empty($pconfig['log'])) { $filterent['log'] = true; } elseif (isset($filterent['log'])) { unset($filterent['log']); } if (!empty($pconfig['disabled'])) { $filterent['disabled'] = true; } else { unset($filterent['disabled']); } if (is_numericint($pconfig['local-port']) && is_numericint($pconfig['dstendport']) && is_numericint($pconfig['dstbeginport'])) { $dstpfrom = $pconfig['local-port']; $dstpto = $dstpfrom + max($pconfig['dstendport'], $pconfig['dstbeginport']) - min($pconfig['dstbeginport'],$pconfig['dstendport']) ; if ($dstpfrom == $dstpto) { $filterent['destination']['port'] = $dstpfrom; } else { $filterent['destination']['port'] = $dstpfrom . "-" . $dstpto; } } else { // if any of the ports is an alias, copy contents of local-port $filterent['destination']['port'] = $pconfig['local-port']; } $filterent['descr'] = $pconfig['descr']; $filterent['category'] = $natent['category']; // If this is a new rule, create an ID and add the rule if ( !empty($pconfig['associated-rule-id']) && in_array($pconfig['associated-rule-id'], ['add-associated', 'add-unassociated']) ) { if ($pconfig['associated-rule-id'] == 'add-associated') { $filterent['associated-rule-id'] = $natent['associated-rule-id'] = uniqid("nat_", true); } $filterent['created'] = make_config_revision_entry(); $config['filter']['rule'][] = $filterent; } mark_subsystem_dirty('filter'); } // Update the NAT entry now $natent['updated'] = make_config_revision_entry(); if (isset($id)) { if (isset($a_nat[$id]['created'])) { $natent['created'] = $a_nat[$id]['created']; } $a_nat[$id] = $natent; } else { $natent['created'] = make_config_revision_entry(); if (isset($after)) { array_splice($a_nat, $after+1, 0, array($natent)); } else { $a_nat[] = $natent; } } OPNsense\Core\Config::getInstance()->fromArray($config); $catmdl = new OPNsense\Firewall\Category(); if ($catmdl->sync()) { $catmdl->serializeToConfig(); $config = OPNsense\Core\Config::getInstance()->toArray(listtags()); } write_config(); mark_subsystem_dirty('natconf'); header(url_safe('Location: /firewall_nat.php')); exit; } } legacy_html_escape_form_data($pconfig); include("head.inc"); ?> <body> <script src="<?= cache_safe('/ui/js/tokenize2.js') ?>"></script> <link rel="stylesheet" type="text/css" href="<?= cache_safe(get_themed_filename('/css/tokenize2.css')) ?>"> <script src="<?= cache_safe('/ui/js/opnsense_ui.js') ?>"></script> <script> $( document ).ready(function() { // show source fields (advanced) $("#showadvancedboxsrc").click(function(){ $(".advanced_opt_src").toggleClass("hidden visible"); }); // on change event protocol change $("#proto").change(function(){ let port_disabled = true; if ($("#proto").val() == "tcp" || $("#proto").val() == "udp" || $("#proto").val() == "tcp/udp") { port_disabled = false; } else { $("#dstbeginport optgroup:last option:first").prop('selected', true); $("#dstendport optgroup:last option:first").prop('selected', true); $("#srcbeginport optgroup:last option:first").prop('selected', true); $("#srcendport optgroup:last option:first").prop('selected', true); port_disabled = true; } $("#srcbeginport").prop('disabled', port_disabled); $("#srcendport").prop('disabled', port_disabled); $("#dstbeginport").prop('disabled', port_disabled); $("#dstendport").prop('disabled', port_disabled); $("#localbeginport").prop('disabled', port_disabled); $("input[for='localbeginport']").prop('disabled', port_disabled); $("#srcbeginport").selectpicker('refresh'); $("#srcendport").selectpicker('refresh'); $("#dstbeginport").selectpicker('refresh'); $("#dstendport").selectpicker('refresh'); $("#localbeginport").selectpicker('refresh'); $("input[for='localbeginport']").prop('disabled', port_disabled); }); // on change event for "No RDR" checkbox $("#nordr").change(function(){ if ($("#nordr").prop('checked')) { $(".act_no_rdr").addClass("hidden"); $(".act_no_rdr :input").prop( "disabled", true ); } else { $(".act_no_rdr").removeClass("hidden"); $(".act_no_rdr :input").prop( "disabled", false ); } $(".act_no_rdr .selectpicker").selectpicker('refresh'); }); // trigger initial form change $("#nordr").change(); // no-rdr $("#proto").change(); // protocol // show source address when selected <?php if (!empty($pconfig['srcnot']) || $pconfig['src'] != "any" || $pconfig['srcbeginport'] != "any" || $pconfig['srcendport'] != "any"): ?> $(".advanced_opt_src").toggleClass("hidden visible"); <?php endif; ?> // select / input combination, link behaviour // when the data attribute "data-other" is selected, display related input item(s) // push changes from input back to selected option value $('[for!=""][for]').each(function(){ var refObj = $("#"+$(this).attr("for")); if (refObj.is("select")) { // connect on change event to select box (show/hide) refObj.change(function(){ if ($(this).find(":selected").attr("data-other") == "true") { // show related controls $('*[for="'+$(this).attr("id")+'"]').each(function(){ if ($(this).hasClass("selectpicker")) { $(this).selectpicker('show'); } else { $(this).removeClass("hidden"); } $(this).prop("disabled", false); }); } else { // hide related controls $('*[for="'+$(this).attr("id")+'"]').each(function(){ if ($(this).hasClass("selectpicker")) { $(this).selectpicker('hide'); } else { $(this).addClass("hidden"); } $(this).prop("disabled", true); }); } }); // update initial refObj.change(); // connect on change to input to save data to selector if ($(this).attr("name") == undefined) { $(this).change(function(){ var otherOpt = $('#'+$(this).attr('for')+' > option[data-other="true"]') ; otherOpt.attr("value",$(this).val()); }); } } }); // align dropdown source from/to port $("#srcbeginport").change(function(){ $('#srcendport').prop('selectedIndex', $("#srcbeginport").prop('selectedIndex') ); $('#srcendport').selectpicker('refresh'); $('#srcendport').change(); }); // align dropdown destination from/to port $("#dstbeginport").change(function(){ $('#dstendport').prop('selectedIndex', $("#dstbeginport").prop('selectedIndex') ); $('#dstendport').selectpicker('refresh'); $('#dstendport').change(); // on new entry, align redirect target port to dst target if ($("#entryid").length == 0) { $('#localbeginport').prop('selectedIndex', $("#dstbeginport").prop('selectedIndex') ); $('#localbeginport').change(); } }); $("input[for='dstbeginport']").change(function(){ // on new entry, align redirect target port to dst target if ($("#entryid").length == 0) { $("input[for='localbeginport']").val($(this).val()); $("input[for='localbeginport']").change(); } }); // IPv4/IPv6 select hook_ipv4v6('ipv4v6net', 'network-id'); formatTokenizersUI(); }); </script> <?php include("fbegin.inc"); ?> <section class="page-content-main"> <div class="container-fluid"> <div class="row"> <?php if (isset($input_errors) && count($input_errors) > 0) print_input_errors($input_errors); ?> <section class="col-xs-12"> <div class="content-box"> <form method="post" name="iform" id="iform"> <table role="presentation" class="table table-striped opnsense_standard_table_form"> <tr> <td style="width:22%"><?=gettext("Edit Redirect entry"); ?></td> <td style="width:78%; text-align:right"> <small><?=gettext("full help"); ?> </small> <i class="fa fa-toggle-off text-danger" style="cursor: pointer;" id="show_all_help_page"></i> </td> </tr> <tr> <td><a id="help_for_disabled" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Disabled"); ?></td> <td> <input name="disabled" type="checkbox" id="disabled" value="yes" <?= !empty($pconfig['disabled']) ? "checked=\"checked\"" : ""; ?> /> <?=gettext("Disable this rule"); ?> <div class="hidden" data-for="help_for_disabled"> <?=gettext("Set this option to disable this rule without removing it from the list."); ?> </div> </td> </tr> <tr> <td><a id="help_for_nordr" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("No RDR (NOT)"); ?></td> <td> <input type="checkbox" name="nordr" id="nordr" <?= !empty($pconfig['nordr']) ? "checked=\"checked\"" : ""; ?> /> <div class="hidden" data-for="help_for_nordr"> <?=gettext("Enabling this option will disable redirection for traffic matching this rule."); ?> <br /><?=gettext("Hint: this option is rarely needed, don't use this unless you know what you're doing."); ?> </div> </td> </tr> <tr> <td><a id="help_for_interface" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Interface"); ?></td> <td> <select name="interface[]" class="selectpicker" data-width="348px" data-live-search="true" multiple="multiple"> <?php foreach (legacy_config_get_interfaces(["enable" => true], ['lo0']) as $iface => $ifdetail): ?> <option value="<?=$iface;?>" <?= in_array($iface, $pconfig['interface'] ?? []) ? "selected=\"selected\"" : ""; ?>> <?=htmlspecialchars($ifdetail['descr']);?> </option> <?php endforeach ?> </select> <div class="hidden" data-for="help_for_interface"> <?=gettext("Choose which interface this rule applies to."); ?><br /> <?=gettext("Hint: in most cases, you'll want to use WAN here."); ?> </div> </td> </tr> <tr> <td><a id="help_for_ipv46" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("TCP/IP Version");?></td> <td> <select name="ipprotocol" class="selectpicker" data-width="348px" data-live-search="true" data-size="5" > <?php foreach (array('inet' => 'IPv4','inet6' => 'IPv6', 'inet46' => 'IPv4+IPv6') as $proto => $name): ?> <option value="<?=$proto;?>" <?= $proto == $pconfig['ipprotocol'] ? "selected=\"selected\"" : "";?>> <?=$name;?> </option> <?php endforeach; ?> </select> <div class="hidden" data-for="help_for_ipv46"> <?=gettext("Select the Internet Protocol version this rule applies to");?> </div> </td> </tr> <tr> <td><a id="help_for_proto" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Protocol"); ?></td> <td> <select id="proto" name="protocol" class="selectpicker" data-live-search="true" data-size="5" data-width="348px"> <?php foreach (get_protocols() as $proto): ?> <option value="<?=strtolower($proto);?>" <?= strtolower($proto) == $pconfig['protocol'] ? "selected=\"selected\"" : ""; ?>> <?= $proto ?> </option> <?php endforeach ?> </select> <div class="hidden" data-for="help_for_proto"> <?=gettext("Choose which IP protocol " ."this rule should match."); ?><br/> <?=gettext("Hint: in most cases, you should specify"); ?> <em><?=gettext("TCP"); ?></em> <?=gettext("here."); ?> </div> </td> </tr> <tr class="advanced_opt_src visible"> <td><?=gettext("Source"); ?></td> <td> <input type="button" class="btn btn-default" value="<?= html_safe(gettext('Advanced')) ?>" id="showadvancedboxsrc" /> <div class="hidden" data-for="help_for_source"> <?=gettext("Show source address and port range"); ?> </div> </td> </tr> <tr class="advanced_opt_src hidden"> <td> <a id="help_for_src_invert" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Source") . " / ".gettext("Invert");?> </td> <td> <input name="srcnot" type="checkbox" id="srcnot" value="yes" <?= !empty($pconfig['srcnot']) ? "checked=\"checked\"" : "";?> /> <div class="hidden" data-for="help_for_src_invert"> <?=gettext("Use this option to invert the sense of the match."); ?> </div> </td> </tr> <tr class="advanced_opt_src hidden"> <td><i class="fa fa-info-circle text-muted"></i> <?=gettext("Source"); ?></td> <td> <table style="max-width: 348px"> <tr> <td> <select name="src" id="src" class="selectpicker" data-live-search="true" data-size="5" data-width="348px"> <option data-other=true value="<?=$pconfig['src'];?>" <?=!is_specialnet($pconfig['src']) && !is_alias($pconfig['src']) ? "selected=\"selected\"" : "";?>><?=gettext("Single host or Network"); ?></option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("network") as $alias): ?> <option value="<?=$alias['name'];?>" <?=$alias['name'] == $pconfig['src'] ? "selected=\"selected\"" : "";?>><?=htmlspecialchars($alias['name']);?></option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Networks");?>"> <?php foreach (get_specialnets(true) as $ifent => $ifdesc): ?> <option value="<?=$ifent;?>" <?= $pconfig['src'] == $ifent ? "selected=\"selected\"" : ""; ?>><?=$ifdesc;?></option> <?php endforeach; ?> </optgroup> </select> </td> </tr> </table> <table style="max-width: 348px"> <tr> <td style="width:285px"> <!-- updates to "other" option in src --> <input type="text" id="src_address" for="src" value="<?=$pconfig['src'];?>" aria-label="<?=gettext("Source address");?>"/> </td> <td> <select name="srcmask" data-network-id="src_address" class="selectpicker ipv4v6net" data-size="5" id="srcmask" data-width="70px" for="src" > <?php for ($i = 128; $i > 0; $i--): ?> <option value="<?=$i;?>" <?= $i == $pconfig['srcmask'] ? "selected=\"selected\"" : ""; ?>><?=$i;?></option> <?php endfor; ?> </select> </td> </tr> </table> </td> </tr> <tr class="hidden advanced_opt_src"> <td><a id="help_for_srcport" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Source port range"); ?></td> <td> <table class="table table-condensed"> <thead> <tr> <th><?=gettext("from:"); ?></th> <th><?=gettext("to:"); ?></th> </tr> </thead> <tbody> <tr> <td> <select id="srcbeginport" name="srcbeginport" class="selectpicker" data-live-search="true" data-size="5" data-width="auto"> <option data-other=true value="<?=$pconfig['srcbeginport'];?>">(<?=gettext("other"); ?>)</option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("port") as $alias): ?> <option value="<?=$alias['name'];?>" <?= $pconfig['srcbeginport'] == $alias['name'] ? "selected=\"selected\"" : ""; ?> ><?=htmlspecialchars($alias['name']);?> </option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Well-known ports");?>"> <option value="any" <?= $pconfig['srcbeginport'] == "any" ? "selected=\"selected\"" : ""; ?>><?=gettext("any"); ?></option> <?php foreach ($wkports as $wkport => $wkportdesc): ?> <option value="<?=$wkport;?>" <?= $wkport == $pconfig['srcbeginport'] ? "selected=\"selected\"" : "" ;?>><?=htmlspecialchars($wkportdesc);?></option> <?php endforeach; ?> </optgroup> </select> </td> <td> <select id="srcendport" name="srcendport" class="selectpicker" data-live-search="true" data-size="5" data-width="auto"> <option data-other=true value="<?=$pconfig['srcendport'];?>">(<?=gettext("other"); ?>)</option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("port") as $alias): ?> <option value="<?=$alias['name'];?>" <?= $pconfig['srcendport'] == $alias['name'] ? "selected=\"selected\"" : ""; ?> ><?=htmlspecialchars($alias['name']);?> </option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Well-known ports");?>"> <option value="any" <?= $pconfig['srcendport'] == "any" ? "selected=\"selected\"" : ""; ?>><?=gettext("any"); ?></option> <?php foreach ($wkports as $wkport => $wkportdesc): ?> <option value="<?=$wkport;?>" <?= $wkport == $pconfig['srcendport'] ? "selected=\"selected\"" : "" ;?>><?=htmlspecialchars($wkportdesc);?></option> <?php endforeach; ?> </optgroup> </select> </td> </tr> <tr> <td> <input type="text" value="<?=$pconfig['srcbeginport'];?>" for="srcbeginport"> <!-- updates to "other" option in srcbeginport --> </td> <td> <input type="text" value="<?=$pconfig['srcendport'];?>" for="srcendport"> <!-- updates to "other" option in srcendport --> </td> </tr> </tbody> </table> <div class="hidden" data-for="help_for_srcport"> <?=gettext("When using the TCP or UDP protocols, specify the source port or port range for this rule"); ?>. <b><?=gettext("This is usually"); ?> <em><?=gettext("random"); ?></em> <?=gettext("and almost never equal to the destination port range (and should usually be 'any')"); ?>. </b> </div> </td> </tr> <tr> <td> <a id="help_for_dst_invert" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Destination") . " / ".gettext("Invert");?> </td> <td> <input name="dstnot" type="checkbox" id="dstnot" value="yes" <?= !empty($pconfig['dstnot']) ? "checked=\"checked\"" : "";?> /> <div class="hidden" data-for="help_for_dst_invert"> <?=gettext("Use this option to invert the sense of the match."); ?> </div> </td> </tr> <tr> <td><i class="fa fa-info-circle text-muted"></i> <?=gettext("Destination"); ?></td> <td> <table style="max-width: 348px"> <tr> <td> <select name="dst" id="dst" class="selectpicker" data-live-search="true" data-size="5" data-width="348px"> <option data-other=true value="<?=$pconfig['dst'];?>" <?=!is_specialnet($pconfig['dst']) && !is_alias($pconfig['dst']) ? "selected=\"selected\"" : "";?>><?=gettext("Single host or Network"); ?></option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("network") as $alias): ?> <option value="<?=$alias['name'];?>" <?=$alias['name'] == $pconfig['dst'] ? "selected=\"selected\"" : "";?>><?=htmlspecialchars($alias['name']);?></option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Networks");?>"> <?php foreach (get_specialnets(true) as $ifent => $ifdesc): ?> <option value="<?=$ifent;?>" <?= $pconfig['dst'] == $ifent ? "selected=\"selected\"" : ""; ?>><?=$ifdesc;?></option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Virtual IPs");?>"> <?php if (isset($config['virtualip']['vip'])): foreach ($config['virtualip']['vip'] as $sn): if (!empty($sn['noexpand'])) continue; if ($sn['mode'] == "proxyarp"): $start = ip2long32(gen_subnet($sn['subnet'], $sn['subnet_bits'])); $end = ip2long32(gen_subnet_max($sn['subnet'], $sn['subnet_bits'])); $len = $end - $start; for ($i = 0; $i <= $len; $i++): $snip = long2ip32($start+$i); ?> <option value="<?=$snip;?>" <?=$snip == $pconfig['dst'] ? "selected=\"selected\"" : "";?>> <?=htmlspecialchars("{$snip} ({$sn['descr']})");?> </option> <?php endfor; else: ?> <option value="<?=$sn['subnet'];?>" <?= $sn['subnet'] == $pconfig['dst'] ? "selected=\"selected\"" : ""; ?>> <?=htmlspecialchars("{$sn['subnet']} ({$sn['descr']})");?> </option> <?php endif; endforeach; endif; ?> </optgroup> </select> </td> </tr> </table> <!-- updates to "other" option in dst --> <table style="max-width: 348px"> <tr> <td style="width: 285px"> <input type="text" id="dst_address" for="dst" value="<?= !is_specialnet($pconfig['dst']) ? $pconfig['dst'] : "";?>" aria-label="<?=gettext("Destination address");?>"/> </td> <td> <select name="dstmask" data-network-id="dst_address" class="selectpicker ipv4v6net" data-size="5" id="dstmask" data-width="70px" for="dst"> <?php for ($i = 128; $i > 0; $i--): ?> <option value="<?=$i;?>" <?= $i == $pconfig['dstmask'] ? "selected=\"selected\"" : ""; ?>><?=$i;?></option> <?php endfor; ?> </select> </td> </tr> </table> </td> </tr> <tr> <td><a id="help_for_dstport" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Destination port range"); ?></td> <td> <table class="table table-condensed"> <thead> <tr> <th><?=gettext("from:"); ?></th> <th><?=gettext("to:"); ?></th> </tr> </thead> <tbody> <tr> <td> <select id="dstbeginport" name="dstbeginport" class="selectpicker" data-live-search="true" data-size="5" data-width="auto"> <option data-other=true value="<?=$pconfig['dstbeginport'];?>">(<?=gettext("other"); ?>)</option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("port") as $alias): ?> <option value="<?=$alias['name'];?>" <?= $pconfig['dstbeginport'] == $alias['name'] ? "selected=\"selected\"" : ""; ?> ><?=htmlspecialchars($alias['name']);?> </option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Well-known ports");?>"> <option value="any" <?= $pconfig['dstbeginport'] == "any" ? "selected=\"selected\"" : ""; ?>><?=gettext("any"); ?></option> <?php foreach ($wkports as $wkport => $wkportdesc): ?> <option value="<?=$wkport;?>" <?= $wkport == $pconfig['dstbeginport'] ? "selected=\"selected\"" : "" ;?>><?=htmlspecialchars($wkportdesc);?></option> <?php endforeach; ?> </optgroup> </select> </td> <td> <select id="dstendport" name="dstendport" class="selectpicker" data-live-search="true" data-size="5" data-width="auto"> <option data-other=true value="<?=$pconfig['dstendport'];?>">(<?=gettext("other"); ?>)</option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("port") as $alias): ?> <option value="<?=$alias['name'];?>" <?= $pconfig['dstendport'] == $alias['name'] ? "selected=\"selected\"" : ""; ?> ><?=htmlspecialchars($alias['name']);?> </option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Well-known ports");?>"> <option value="any" <?= $pconfig['dstendport'] == "any" ? "selected=\"selected\"" : ""; ?>><?=gettext("any"); ?></option> <?php foreach ($wkports as $wkport => $wkportdesc): ?> <option value="<?=$wkport;?>" <?= $wkport == $pconfig['dstendport'] ? "selected=\"selected\"" : "" ;?>><?=htmlspecialchars($wkportdesc);?></option> <?php endforeach; ?> </optgroup> </select> </td> </tr> <tr> <td> <input type="text" value="<?=$pconfig['dstbeginport'];?>" for="dstbeginport"> <!-- updates to "other" option in dstbeginport --> </td> <td> <input type="text" value="<?=$pconfig['dstendport'];?>" for="dstendport"> <!-- updates to "other" option in dstendport --> </td> </tr> </tbody> </table> <div class="hidden" data-for="help_for_dstport"> <?=gettext("When using the TCP or UDP protocols, specify the port or port range for the destination of the packet for this mapping."); ?> </div> </td> </tr> <tr class="act_no_rdr"> <td><a id="help_for_localip" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Redirect target IP"); ?></td> <td> <table style="max-width: 348px"> <tr> <td> <select name="target" id="target" class="selectpicker" data-live-search="true" data-size="5" data-width="348px"> <option data-other=true value="<?=$pconfig['target'];?>" <?=!is_alias($pconfig['target']) ? "selected=\"selected\"" : "";?>><?=gettext("Single host or Network"); ?></option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("network") as $alias):?> <option value="<?=$alias['name'];?>" <?=$alias['name'] == $pconfig['target'] ? "selected=\"selected\"" : "";?>><?=htmlspecialchars($alias['name']);?></option> <?php endforeach; ?> </optgroup> </select> </td> </tr> <tr> <td> <!-- updates to "other" option in target --> <input type="text" id="target_address" for="target" value="<?=$pconfig['target'];?>" aria-label="<?=gettext("Redirect target IP");?>"/> </td> </tr> </table> <div class="hidden" data-for="help_for_localip"> <?=gettext("Enter the internal IP address of " . "the server on which you want to map the ports."); ?><br/> <?=gettext("e.g."); ?> <em>192.168.1.12</em> </div> </tr> <tr class="act_no_rdr"> <td><a id="help_for_localbeginport" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Redirect target port"); ?></td> <td> <table class="table table-condensed"> <tbody> <tr> <td> <select id="localbeginport" name="local-port" class="selectpicker" data-live-search="true" data-size="5" data-width="auto"> <option data-other=true value="<?=$pconfig['local-port'];?>">(<?=gettext("other"); ?>)</option> <optgroup label="<?=gettext("Aliases");?>"> <?php foreach (legacy_list_aliases("port") as $alias): ?> <option value="<?=$alias['name'];?>" <?= $pconfig['local-port'] == $alias['name'] ? "selected=\"selected\"" : ""; ?> ><?=htmlspecialchars($alias['name']);?> </option> <?php endforeach; ?> </optgroup> <optgroup label="<?=gettext("Well-known ports");?>"> <option value="any" <?= $pconfig['local-port'] == "any" ? "selected=\"selected\"" : ""; ?>><?=gettext("any"); ?></option> <?php foreach ($wkports as $wkport => $wkportdesc): ?> <option value="<?=$wkport;?>" <?= $wkport == $pconfig['local-port'] ? "selected=\"selected\"" : "" ;?>><?=htmlspecialchars($wkportdesc);?></option> <?php endforeach; ?> </optgroup> </select> </td> </tr> <tr> <td> <input type="text" value="<?=$pconfig['local-port'];?>" for="localbeginport"> <!-- updates to "other" option in localbeginport --> </td> </tr> </tbody> </table> <div class="hidden" data-for="help_for_localbeginport"> <?=gettext("Specify the port on the machine with the " . "IP address entered above. In case of a port range, specify " . "the beginning port of the range (the end port will be calculated " . "automatically)."); ?><br /> <?=gettext("Hint: this is usually identical to the 'from' port above"); ?> </div> </td> </tr> <tr class="act_no_rdr"> <td><a id="help_for_poolopts" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Pool Options:");?></td> <td> <select name="poolopts" class="selectpicker"> <option value="" <?=empty($pconfig['poolopts']) ? "selected=\"selected\"" : ""; ?>> <?=gettext("Default");?> </option> <option value="round-robin" <?=$pconfig['poolopts'] == "round-robin" ? "selected=\"selected\"" : ""; ?>> <?=gettext("Round Robin");?> </option> <option value="round-robin sticky-address" <?=$pconfig['poolopts'] == "round-robin sticky-address" ? "selected=\"selected\"" : ""; ?>> <?=gettext("Round Robin with Sticky Address");?> </option> <option value="random" <?=$pconfig['poolopts'] == "random" ? "selected=\"selected\"" : ""; ?>> <?=gettext("Random");?> </option> <option value="random sticky-address" <?=$pconfig['poolopts'] == "random sticky-address" ? "selected=\"selected\"" : ""; ?>> <?=gettext("Random with Sticky Address");?> </option> <option value="source-hash" <?=$pconfig['poolopts'] == "source-hash" ? "selected=\"selected\"" : ""; ?>> <?=gettext("Source Hash");?> </option> <option value="bitmask" <?=$pconfig['poolopts'] == "bitmask" ? "selected=\"selected\"" : ""; ?>> <?=gettext("Bitmask");?> </option> </select> <div class="hidden" data-for="help_for_poolopts"> <?=gettext("Only Round Robin types work with Host Aliases. Any type can be used with a Subnet.");?><br /> * <?=gettext("Round Robin: Loops through the translation addresses.");?><br /> * <?=gettext("Random: Selects an address from the translation address pool at random.");?><br /> * <?=gettext("Source Hash: Uses a hash of the source address to determine the translation address, ensuring that the redirection address is always the same for a given source.");?><br /> * <?=gettext("Bitmask: Applies the subnet mask and keeps the last portion identical; 10.0.1.50 -> x.x.x.50.");?><br /> * <?=gettext("Sticky Address: The Sticky Address option can be used with the Random and Round Robin pool types to ensure that a particular source address is always mapped to the same translation address.");?><br /> </div> </td> </tr> <tr> <td><a id="help_for_log" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext('Log') ?></td> <td> <input name="log" type="checkbox" id="log" value="yes" <?= !empty($pconfig['log']) ? 'checked="checked"' : '' ?>/> <?= gettext("Log packets that are handled by this rule") ?> <div class="hidden" data-for="help_for_log"> <?=sprintf(gettext("Hint: the firewall has limited local log space. Don't turn on logging for everything. If you want to do a lot of logging, consider using a %sremote syslog server%s."),'<a href="ui/syslog/">','</a>') ?> </div> </td> </tr> <tr> <td><a id="help_for_category" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Category"); ?></td> <td> <select name="category[]" id="category" multiple="multiple" class="tokenize" data-allownew="true" data-width="348px" data-live-search="true"> <?php foreach ((new OPNsense\Firewall\Category())->iterateCategories() as $category): $catname = htmlspecialchars($category['name'], ENT_QUOTES | ENT_HTML401);?> <option value="<?=$catname;?>" <?=!empty($pconfig['category']) && in_array($catname, $pconfig['category']) ? 'selected="selected"' : '';?> ><?=$catname;?></option> <?php endforeach;?> </select> <div class="hidden" data-for="help_for_category"> <?=gettext("You may enter or select a category here to group firewall rules (not parsed)."); ?> </div> </tr> <tr> <td><a id="help_for_descr" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Description"); ?></td> <td> <input name="descr" type="text" id="descr" size="40" value="<?=$pconfig['descr'];?>" /> <div class="hidden" data-for="help_for_descr"> <?=gettext("You may enter a description here for your reference (not parsed)."); ?> </div> </tr> <tr> <td><a id="help_for_tag" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Set local tag"); ?></td> <td> <input name="tag" type="text" value="<?=$pconfig['tag'];?>" /> <div class="hidden" data-for="help_for_tag"> <?= gettext("You can mark a packet matching this rule and use this mark to match on other NAT/filter rules.") ?> </div> </td> </tr> <tr> <td><a id="help_for_tagged" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Match local tag"); ?> </td> <td> <input name="tagged" type="text" value="<?=$pconfig['tagged'];?>" /> <div class="hidden" data-for="help_for_tagged"> <?=gettext("You can match packet on a mark placed before on another rule.")?> </div> </td> </tr> <tr> <td><a id="help_for_nosync" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("No XMLRPC Sync"); ?></td> <td> <input type="checkbox" value="yes" name="nosync" <?=!empty($pconfig['nosync']) ? "checked=\"checked\"" :"";?> /> <div class="hidden" data-for="help_for_nosync"> <?=gettext("Hint: This prevents the rule on Master from automatically syncing to other CARP members. This does NOT prevent the rule from being overwritten on Slave.");?> </div> </td> </tr> <tr> <td><i class="fa fa-info-circle text-muted"></i> <?=gettext("NAT reflection"); ?></td> <td> <select name="natreflection" class="selectpicker"> <option value="default" <?=$pconfig['natreflection'] != "enable" && $pconfig['natreflection'] != "purenat" && $pconfig['natreflection'] != "disable" ? "selected=\"selected\"" : ""; ?>><?=gettext("Use system default"); ?></option> <option value="purenat" <?=$pconfig['natreflection'] == "purenat" ? "selected=\"selected\"" : ""; ?>><?=gettext("Enable"); ?></option> <option value="disable" <?=$pconfig['natreflection'] == "disable" ? "selected=\"selected\"" : ""; ?>><?=gettext("Disable"); ?></option> </select> </td> </tr> <?php // check if a filter rule is associated and return it. $linkedrule = ""; $linkedrule_descr = ""; if (!empty($pconfig['associated-rule-id'])) { filter_rules_sort(); // XXX: needed? foreach ($config['filter']['rule'] as $filter_id => $filter_rule) { if ( isset($filter_rule['associated-rule-id']) && $filter_rule['associated-rule-id'] == $pconfig['associated-rule-id'] ) { $linkedrule = $filter_rule['associated-rule-id']; $linkedrule_descr = htmlspecialchars('Rule ' . $filter_rule['descr']); } } } ?> <tr class="act_no_rdr"> <td><a id="help_for_fra" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Filter rule association"); ?></td> <td> <select name="associated-rule-id"> <option value="" <?= empty($pconfig['associated-rule-id']) ? " selected=\"selected\"" : ""; ?>><?=gettext("None"); ?></option> <?php if ($linkedrule !== ""):?> <option value="<?=$linkedrule;?>" selected="selected"><?=$linkedrule_descr;?></option> <?php else:?> <option value="add-associated" <?= $pconfig['associated-rule-id'] == "add-associated" ? " selected=\"selected\"" : ""; ?>><?=gettext("Add associated filter rule"); ?></option> <option value="add-unassociated" <?= $pconfig['associated-rule-id'] == "add-unassociated" ? " selected=\"selected\"" : ""; ?>><?=gettext("Add unassociated filter rule"); ?></option> <?php endif;?> <option value="pass" <?= $pconfig['associated-rule-id'] == "pass" ? " selected=\"selected\"" : ""; ?>><?=gettext("Pass"); ?></option> </select> <div class="hidden" data-for="help_for_fra"> <?=gettext("NOTE: The \"pass\" selection does not work properly with Multi-WAN. It will only work on an interface containing the default gateway.")?> </div> </td> </tr> <?php $has_created_time = (isset($pconfig['created']) && is_array($pconfig['created'])); $has_updated_time = (isset($pconfig['updated']) && is_array($pconfig['updated'])); if ($has_created_time || $has_updated_time): ?> <tr> <td colspan="2"> </td> </tr> <tr> <td colspan="2"><?=gettext("Rule Information");?></td> </tr> <?php if ($has_created_time): ?> <tr> <td><?=gettext("Created");?></td> <td> <?= date(gettext('n/j/y H:i:s'), (int)$pconfig['created']['time']) ?> (<?= $pconfig['created']['username'] ?>) </td> </tr> <?php endif; if ($has_updated_time): ?> <tr> <td><?=gettext("Updated");?></td> <td> <?= date(gettext('n/j/y H:i:s'), (int)$pconfig['updated']['time']) ?> (<?= $pconfig['updated']['username'] ?>) </td> </tr> <?php endif; endif; ?> <tr> <td> </td> <td> </td> </tr> <tr> <td> </td> <td> <input name="Submit" type="submit" class="btn btn-primary" value="<?=html_safe(gettext('Save')); ?>" /> <input type="button" class="btn btn-default" value="<?=html_safe(gettext('Cancel'));?>" onclick="window.location.href='/firewall_nat.php'" /> <?php if (isset($id)): ?> <input id="entryid" name="id" type="hidden" value="<?=$id;?>" /> <?php endif; ?> <?php if (isset($after)) : ?> <input name="after" type="hidden" value="<?=$after;?>" /> <?php endif; ?> </td> </tr> </table> </form> </div> </section> </div> </div> </section> <?php include("foot.inc"); ?>