diff --git a/src/etc/inc/filter.inc b/src/etc/inc/filter.inc
index 24d210cb4..6abd89314 100644
--- a/src/etc/inc/filter.inc
+++ b/src/etc/inc/filter.inc
@@ -256,12 +256,6 @@ function filter_configure_sync($verbose = false, $load_aliases = true)
}
}
- if (!empty($config['nat']['onetoone'])) {
- // register user 1:1 mappings
- foreach ($config['nat']['onetoone'] as $rule) {
- $fw->registerDNatRule(500, $rule);
- }
- }
if (!empty($config['nat']['rule'])) {
// register user forward rules
foreach ($config['nat']['rule'] as $rule) {
diff --git a/src/etc/inc/plugins.inc.d/pf.inc b/src/etc/inc/plugins.inc.d/pf.inc
index da2f18f3a..64ec8bee5 100644
--- a/src/etc/inc/plugins.inc.d/pf.inc
+++ b/src/etc/inc/plugins.inc.d/pf.inc
@@ -180,6 +180,9 @@ function pf_firewall($fw)
foreach ($mdlFilter->snatrules->rule->sortedBy(["sequence"]) as $key => $rule) {
$fw->registerSNatRule(50, $rule->serialize());
}
+ foreach ($mdlFilter->onetoone->rule->sortedBy(["sequence"]) as $key => $rule) {
+ $fw->registerDNatRule(500, $rule->serialize());
+ }
foreach ($mdlFilter->npt->rule->sortedBy(["sequence"]) as $key => $rule) {
$fw->registerNptRule(50, $rule->serialize());
}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/OneToOneController.php b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/OneToOneController.php
new file mode 100644
index 000000000..665d02130
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/OneToOneController.php
@@ -0,0 +1,67 @@
+request->get('category');
+ $filter_funct = function ($record) use ($category) {
+ return empty($category) || array_intersect(explode(',', $record->categories), $category);
+ };
+ return $this->searchBase("onetoone.rule", null, "sequence", $filter_funct);
+ }
+
+ public function setRuleAction($uuid)
+ {
+ return $this->setBase("rule", "onetoone.rule", $uuid);
+ }
+
+ public function addRuleAction()
+ {
+ return $this->addBase("rule", "onetoone.rule");
+ }
+
+ public function getRuleAction($uuid = null)
+ {
+ return $this->getBase("rule", "onetoone.rule", $uuid);
+ }
+
+ public function delRuleAction($uuid)
+ {
+ return $this->delBase("onetoone.rule", $uuid);
+ }
+
+ public function toggleRuleAction($uuid, $enabled = null)
+ {
+ return $this->toggleBase("onetoone.rule", $uuid, $enabled);
+ }
+}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Firewall/OneToOneController.php b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/OneToOneController.php
new file mode 100644
index 000000000..a0087f6c2
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/OneToOneController.php
@@ -0,0 +1,62 @@
+view->pick('OPNsense/Firewall/filter');
+ $this->view->ruleController = "one_to_one";
+ $this->view->gridFields = [
+ [
+ 'id' => 'enabled', 'formatter' => 'rowtoggle' ,'width' => '6em', 'heading' => gettext('Enabled')
+ ],
+ [
+ 'id' => 'sequence','width' => '9em', 'heading' => gettext('Sequence')
+ ],
+ [
+ 'id' => 'interface','width' => '9em', 'heading' => gettext('Interface')
+ ],
+ [
+ 'id' => 'target', 'heading' => gettext('External')
+ ],
+ [
+ 'id' => 'source_net', 'heading' => gettext('Internal')
+ ],
+ [
+ 'id' => 'destination_net', 'heading' => gettext('Destination')
+ ],
+ [
+ 'id' => 'description', 'heading' => gettext('Description')
+ ]
+ ];
+
+ $this->view->formDialogFilterRule = $this->getForm("dialogOneToOneRule");
+ }
+}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogOneToOneRule.xml b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogOneToOneRule.xml
new file mode 100644
index 000000000..3ed678b25
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogOneToOneRule.xml
@@ -0,0 +1,81 @@
+
diff --git a/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml b/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml
index 0aed6b02c..f4c1c402e 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml
@@ -238,18 +238,6 @@
api/firewall/category/*
-
- Firewall: NAT: 1:1
-
- firewall_nat_1to1.php*
-
-
-
- Firewall: NAT: 1:1: Edit
-
- firewall_nat_1to1_edit.php*
-
-
Firewall: NAT: Outbound
diff --git a/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml b/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml
index cdd92bab1..9cc933e06 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml
@@ -133,9 +133,6 @@
-
-
-
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/ACL/ACL.xml b/src/opnsense/mvc/app/models/OPNsense/Firewall/ACL/ACL.xml
index a3360c71e..75ff96451 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Firewall/ACL/ACL.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/ACL/ACL.xml
@@ -20,4 +20,11 @@
api/firewall/npt/*
+
+ Firewall: NAT: 1:1
+
+ ui/firewall/one_to_one/*
+ api/firewall/one_to_one/*
+
+
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.php b/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.php
index 179cbef3b..2b4ca0803 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.php
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.php
@@ -134,6 +134,44 @@ class Filter extends BaseModel
}
}
}
+ /* 1 to 1 mappings */
+ foreach ($this->onetoone->rule->iterateItems() as $rule) {
+ if ($validateFullModel || $rule->isFieldChanged()) {
+ $ipprotos = [];
+ $subnets = [];
+ foreach (['source_net', 'destination_net', 'external'] as $fieldname) {
+ $subnets[$fieldname] = null;
+ if (Util::isSubnet($rule->$fieldname) || Util::isIpAddress($rule->$fieldname)) {
+ $ipprotos[$fieldname] = strpos($rule->$fieldname, ':') === false ? "inet" : "inet6";
+ $subnet_default = $ipprotos[$fieldname] == 'inet' ? '32' : '128';
+ $subnets[$fieldname] = explode('/', $rule->$fieldname . '/'.$subnet_default)[1];
+ }
+ }
+ if (count(array_unique(array_values($ipprotos))) > 1) {
+ foreach (array_keys($ipprotos) as $fieldname) {
+ $messages->appendMessage(new Message(
+ gettext("IP protocol families should match."),
+ $rule->$fieldname->__reference
+ ));
+ }
+ }
+
+ if ($rule->type == 'binat' && !empty((string)$rule->enabled)) {
+ /* binat rules are more strict, when not enabled, we may skip the validations to ease migration */
+ if (empty($ipprotos['source_net'])) {
+ $messages->appendMessage(new Message(
+ gettext("For BINAT rules only addresses or subnets are allowed."),
+ $rule->source_net->__reference
+ ));
+ } elseif ($subnets['external'] != $subnets['source_net']) {
+ $messages->appendMessage(new Message(
+ gettext("External subnet should match internal subnet."),
+ $rule->external->__reference
+ ));
+ }
+ }
+ }
+ }
return $messages;
}
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.xml b/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.xml
index eb45df3ac..fc33921bd 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.xml
@@ -1,6 +1,6 @@
//OPNsense/Firewall/Filter
- 1.0.3
+ 1.0.4
MFP
OPNsense firewall filter rules
@@ -245,5 +245,75 @@
+
+
+
+ 1
+ Y
+
+
+ 0
+ Y
+
+
+ 1
+ 99999
+ provide a valid sequence for sorting
+ Y
+ 1
+
+
+ Y
+ wan
+ Y
+
+
+ binat
+ Y
+
+ BINAT
+ NAT
+
+
+
+ Y
+
+
+ 0
+ Y
+
+
+ Y
+ any
+
+
+ 0
+ Y
+
+
+ Y
+ N
+
+
+
+ default
+ Enable
+ Disable
+
+
+
+
+
+ OPNsense.Firewall.Category
+ categories.category
+ name
+
+
+ Y
+ Related category not found.
+
+
+
+
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/Menu/Menu.xml b/src/opnsense/mvc/app/models/OPNsense/Firewall/Menu/Menu.xml
index c39018399..4c6cb39ad 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Firewall/Menu/Menu.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/Menu/Menu.xml
@@ -9,6 +9,9 @@
+
+
+
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_0_4.php b/src/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_0_4.php
new file mode 100644
index 000000000..a457021c2
--- /dev/null
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_0_4.php
@@ -0,0 +1,107 @@
+
+
+class MFP1_0_4 extends BaseModelMigration
+{
+ public function run($model)
+ {
+ if ($model instanceof Filter) {
+ $sequence = 1;
+ $catmdl = new Category();
+ foreach ((Config::getInstance()->object())->nat->children() as $child) {
+ if ($child->getName() == 'onetoone') {
+ $addr = [] ;
+ foreach (['destination', 'source'] as $fieldname) {
+ if (!empty(((string)$child->$fieldname->any))) {
+ $addr[$fieldname] = 'any';
+ } elseif (Util::isSubnet((string)$child->$fieldname->address)) {
+ $addr[$fieldname] = (string)$child->$fieldname->address;
+ } elseif (Util::isIpAddress((string)$child->$fieldname->address)) {
+ $subn = strpos($child->$fieldname->address, ':') === false ? '32' : '128';
+ $addr[$fieldname] = (string)$child->$fieldname->address . '/' . $subn;
+ } elseif (!empty((string)$child->$fieldname->address)) {
+ $addr[$fieldname] = (string)$child->$fieldname->address;
+ } elseif (!empty((string)$child->$fieldname->network)) {
+ $addr[$fieldname] = (string)$child->$fieldname->network;
+ } else {
+ $addr[$fieldname] = null;
+ }
+ }
+
+ if (!empty($addr['source']) && !empty($addr['destination']) && !empty((string)$child->external)) {
+ $node = $model->onetoone->rule->Add();
+ $node->enabled = empty((string)$child->disabled) ? "1" : "0";
+ $node->log = empty((string)$child->log) ? "0" : "1";
+ $node->sequence = (string)($sequence++);
+ if (!empty((string)$child->category)) {
+ $cats = [];
+ foreach (explode(',', (string)$child->category) as $cat) {
+ $tmp = $catmdl->getByName($cat);
+ if ($tmp != null) {
+ $cats[] = $tmp->getAttributes()['uuid'];
+ }
+ }
+ $node->categories = implode(",", $cats);
+ }
+ $node->interface = (string)$child->interface;
+ $node->type = !empty((string)$child->type) ? (string)$child->type : 'binat';
+ $node->external = (string)$child->external;
+ $node->source_net = $addr['source'];
+ $node->destination_net = $addr['source'];
+ $node->source_not = !empty((string)$child->source->not) ? '1' : '0';
+ $node->destination_not = !empty((string)$child->destination->not) ? '1' : '0';
+
+ $node->description = (string)$child->descr;
+ }
+ }
+ }
+ }
+ }
+
+ public function post($model)
+ {
+ if ($model instanceof Filter) {
+ $cfgObj = Config::getInstance()->object();
+ if (isset($cfgObj->nat->onetoone)) {
+ unset($cfgObj->nat->onetoone);
+ }
+ }
+ }
+}
diff --git a/src/www/firewall_nat_1to1.php b/src/www/firewall_nat_1to1.php
deleted file mode 100644
index c3abd7f1e..000000000
--- a/src/www/firewall_nat_1to1.php
+++ /dev/null
@@ -1,410 +0,0 @@
-
- * 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("interfaces.inc");
-require_once("filter.inc");
-
-$a_1to1 = &config_read_array('nat', 'onetoone');
-
-if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $pconfig = $_POST;
- if (isset($pconfig['id']) && isset($a_1to1[$pconfig['id']])) {
- // id found and valid
- $id = $pconfig['id'];
- }
-
- if (isset($pconfig['apply'])) {
- filter_configure();
- $savemsg = get_std_save_message();
- clear_subsystem_dirty('natconf');
- clear_subsystem_dirty('filter');
- } elseif (isset($pconfig['action']) && $pconfig['action'] == 'del' && isset($id)) {
- // delete single entry
- unset($a_1to1[$id]);
- write_config();
- mark_subsystem_dirty('natconf');
- header(url_safe('Location: /firewall_nat_1to1.php'));
- exit;
- } elseif (isset($pconfig['action']) && $pconfig['action'] == 'del_x' && isset($pconfig['rule']) && count($pconfig['rule']) > 0) {
- // delete selected
- foreach ($pconfig['rule'] as $rulei) {
- unset($a_1to1[$rulei]);
- }
- write_config();
- mark_subsystem_dirty('natconf');
- header(url_safe('Location: /firewall_nat_1to1.php'));
- exit;
- } elseif (isset($pconfig['action']) && in_array($pconfig['action'], array('toggle_enable', 'toggle_disable')) && isset($pconfig['rule']) && count($pconfig['rule']) > 0) {
- foreach ($pconfig['rule'] as $rulei) {
- $a_1to1[$rulei]['disabled'] = $pconfig['action'] == 'toggle_disable';
- }
- write_config();
- mark_subsystem_dirty('natconf');
- header(url_safe('Location: /firewall_nat_1to1.php'));
- exit;
- } elseif (isset($pconfig['action']) && $pconfig['action'] == 'move') {
- // move selected
- if (isset($pconfig['rule']) && count($pconfig['rule']) > 0) {
- // if rule not set/found, move to end
- if (!isset($id)) {
- $id = count($a_1to1);
- }
- $a_1to1 = legacy_move_config_list_items($a_1to1, $id, $pconfig['rule']);
-
- write_config();
- mark_subsystem_dirty('natconf');
- header(url_safe('Location: /firewall_nat_1to1.php'));
- exit;
- }
- } elseif (isset($pconfig['action']) && $pconfig['action'] == 'toggle' && isset($id)) {
- // toggle item
- if(isset($a_1to1[$id]['disabled'])) {
- unset($a_1to1[$id]['disabled']);
- } else {
- $a_1to1[$id]['disabled'] = true;
- }
- write_config('Toggled NAT 1:1 rule');
- mark_subsystem_dirty('natconf');
- header(url_safe('Location: /firewall_nat_1to1.php'));
- exit;
- }
-}
-
-legacy_html_escape_form_data($a_1to1);
-
-include("head.inc");
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-" .
- gettext("You must apply the changes in order for them to take effect."));
-?>
-
-
-
-
-
-
diff --git a/src/www/firewall_nat_1to1_edit.php b/src/www/firewall_nat_1to1_edit.php
deleted file mode 100644
index a933142fd..000000000
--- a/src/www/firewall_nat_1to1_edit.php
+++ /dev/null
@@ -1,475 +0,0 @@
-
- * 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("interfaces.inc");
-
-$a_1to1 = &config_read_array('nat', 'onetoone');
-
-if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- // input record id, if valid
- if (isset($_GET['dup']) && isset($a_1to1[$_GET['dup']])) {
- $configId = $_GET['dup'];
- } elseif (isset($_GET['id']) && isset($a_1to1[$_GET['id']])) {
- $id = $_GET['id'];
- $configId = $id;
- }
-
- $pconfig = array();
- // set defaults
- $pconfig['interface'] = "wan";
- $pconfig['src'] = 'lan';
- $pconfig['dst'] = 'any';
- $pconfig['type'] = 'binat';
- if (isset($configId)) {
- // copy settings from config
- foreach (array('disabled','interface','external','descr','natreflection', 'type', 'category') as $fieldname) {
- if (isset($a_1to1[$configId][$fieldname])) {
- $pconfig[$fieldname] = $a_1to1[$configId][$fieldname];
- } else {
- $pconfig[$fieldname] = null;
- }
- }
- // read settings with some kind of logic
- address_to_pconfig(
- $a_1to1[$configId]['source'], $pconfig['src'],
- $pconfig['srcmask'], $pconfig['srcnot'],
- $pconfig['__unused__'],$pconfig['__unused__']
- );
-
- address_to_pconfig(
- $a_1to1[$configId]['destination'], $pconfig['dst'],
- $pconfig['dstmask'], $pconfig['dstnot'],
- $pconfig['__unused__'],$pconfig['__unused__']
- );
- } else {
- // init form data on new
- foreach (array('disabled','interface','external','descr','natreflection'
- ,'src','srcmask','srcnot','dst','dstmask','dstnot'
- ) as $fieldname) {
- if (!isset($pconfig[$fieldname])) {
- $pconfig[$fieldname] = null;
- }
- }
- }
- $pconfig['category'] = !empty($pconfig['category']) ? explode(",", $pconfig['category']) : [];
-} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $input_errors = array();
- $pconfig = $_POST;
- // input record id, if valid
- if (isset($_POST['id']) && isset($a_1to1[$_POST['id']])) {
- $id = $_POST['id'];
- }
-
- // trim input
- foreach (array('external','src','dst') as $fieldname) {
- if (isset($pconfig[$fieldname])) {
- $pconfig[$fieldname] = trim($pconfig[$fieldname]);
- }
- }
-
- /* input validation */
- $reqdfields = explode(" ", "interface external src dst");
- $reqdfieldsn = array(gettext("Interface"), gettext("External subnet"), gettext("Source address"), gettext("Destination address"));
- do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
-
-
- /* For external, user can enter only ip's */
- $tmpext = explode('/', $pconfig['external']);
- if (!empty($pconfig['external'])) {
- if ($pconfig['type'] == 'binat' && (!is_ipaddr($tmpext[0]) || (count($tmpext) != 1 && $pconfig['srcmask'] != $tmpext[1]))) {
- $input_errors[] = gettext("A valid external subnet must be specified.");
- } elseif ($pconfig['type'] == 'nat' && !is_subnet($pconfig['external'])) {
- $input_errors[] = gettext("A valid external subnet must be specified.");
- }
- }
- /* For src, user can enter only ip's or networks */
- if ($pconfig['type'] == 'binat' && !is_subnet($pconfig['src']) && !is_ipaddr($pconfig['src'])) {
- $input_errors[] = sprintf(gettext("%s is not a valid source IP address."), $pconfig['src']);
- } elseif (!is_specialnet($pconfig['src']) && !is_ipaddroralias($pconfig['src'])) {
- $input_errors[] = sprintf(gettext("%s is not a valid source IP address or alias."), $pconfig['src']);
- }
- if (!empty($pconfig['srcmask']) && !is_numericint($pconfig['srcmask'])) {
- $input_errors[] = gettext("A valid source bit count must be specified.");
- }
- /* For dst, user can enter ip's, networks or aliases */
- 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 (count($input_errors) == 0) {
- $natent = array();
- // 1-on-1 copy
- $natent['external'] = $pconfig['external'];
- $natent['category'] = !empty($pconfig['category']) ? implode(",", $pconfig['category']) : null;
- $natent['descr'] = $pconfig['descr'];
- $natent['interface'] = $pconfig['interface'];
- $natent['type'] = $pconfig['type'];
-
- // copy form data with some kind of logic in it
- $natent['disabled'] = isset($_POST['disabled']) ? true:false;
- pconfig_to_address($natent['source'], $pconfig['src'],
- $pconfig['srcmask'], !empty($pconfig['srcnot']));
-
- pconfig_to_address($natent['destination'], $pconfig['dst'],
- $pconfig['dstmask'], !empty($pconfig['dstnot']));
-
- if (isset($pconfig['natreflection'] ) && ($pconfig['natreflection'] == "enable" || $pconfig['natreflection'] == "disable")) {
- $natent['natreflection'] = $pconfig['natreflection'];
- }
-
- // save data
- if (isset($id)) {
- $a_1to1[$id] = $natent;
- } else {
- $a_1to1[] = $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_1to1.php'));
- exit;
- }
-}
-
-legacy_html_escape_form_data($pconfig);
-
-include("head.inc");
-
-?>
-
-
-
-
-
-
-
-
-
-
-
- 0)
- print_input_errors($input_errors);
-?>
-
-
-
-
-