diff --git a/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/FilterBaseController.php b/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/FilterBaseController.php
index 3162d985f..56cfeff77 100644
--- a/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/FilterBaseController.php
+++ b/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/FilterBaseController.php
@@ -30,6 +30,7 @@ namespace OPNsense\Firewall\Api;
use OPNsense\Base\ApiMutableModelControllerBase;
use OPNsense\Core\Backend;
use OPNsense\Core\Config;
+use OPNsense\Firewall\Alias;
use OPNsense\Firewall\Category;
/**
@@ -79,6 +80,44 @@ abstract class FilterBaseController extends ApiMutableModelControllerBase
return $response;
}
+ /**
+ * list of available network options
+ * @return array
+ */
+ public function listNetworkSelectOptionsAction()
+ {
+ $result = [
+ 'single' => [
+ 'label' => gettext("Single host or Network")
+ ],
+ 'aliases' => [
+ 'label' => gettext("Aliases"),
+ 'items' => []
+ ],
+ 'networks' => [
+ 'label' => gettext("Networks"),
+ 'items' => [
+ 'any' => gettext('any'),
+ '(self)' => gettext("This Firewall")
+ ]
+ ]
+ ];
+ foreach ((Config::getInstance()->object())->interfaces->children() as $ifname => $ifdetail) {
+ $descr = htmlspecialchars(!empty($ifdetail->descr) ? $ifdetail->descr : strtoupper($ifname));
+ $result['networks']['items'][$ifname] = $descr . " " . gettext("net");
+ if (!isset($ifdetail->virtual)) {
+ $result['networks']['items'][$ifname . "ip"] = $descr . " " . gettext("address");
+ }
+ }
+ foreach ((new Alias())->aliases->alias->iterateItems() as $alias) {
+ if (strpos((string)$alias->type, "port") === false) {
+ $result['aliases']['items'][(string)$alias->name] = (string)$alias->name;
+ }
+ }
+
+ return $result;
+ }
+
public function applyAction($rollback_revision = null)
{
diff --git a/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogNptRule.xml b/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogNptRule.xml
index abfe782df..fc9f7c66f 100644
--- a/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogNptRule.xml
+++ b/net/firewall/src/opnsense/mvc/app/controllers/OPNsense/Firewall/forms/dialogNptRule.xml
@@ -18,11 +18,13 @@
rule.source_net
+
text
rule.destination_net
+
text
diff --git a/net/firewall/src/opnsense/mvc/app/views/OPNsense/Firewall/filter.volt b/net/firewall/src/opnsense/mvc/app/views/OPNsense/Firewall/filter.volt
index 34622514c..d8caac9e6 100644
--- a/net/firewall/src/opnsense/mvc/app/views/OPNsense/Firewall/filter.volt
+++ b/net/firewall/src/opnsense/mvc/app/views/OPNsense/Firewall/filter.volt
@@ -102,6 +102,62 @@
$("#category_filter").change(function(){
$('#grid-rules').bootgrid('reload');
});
+
+ // replace all "net" selectors with details retrieved from "list_network_select_options" endpoint
+ ajaxGet('/api/firewall/{{ruleController}}/list_network_select_options', [], function(data, status){
+ // fetch options
+ let options = [];
+ if (data.single) {
+ Object.keys(data).forEach((key, idx) => {
+ if (data[key].items !== undefined) {
+ let optgrp = $("").attr('label', data[key].label);
+ Object.keys(data[key].items).forEach((key2, idx2) => {
+ let this_item = data[key].items[key2];
+ optgrp.append($("").val(key2).text(this_item));
+ });
+ options.push(optgrp);
+ } else {
+ options.push($("").val('').text(data[key].label));
+ }
+ });
+ }
+ if (options.length == 0) {
+ // unable to fetch options.
+ return;
+ }
+ $(".net_selector").each(function(){
+ let $items = $("#network_select").clone().show();
+ let $this_input = $items.find('input');
+ let $this_select = $items.find('select');
+ for (i=0; i < options.length; ++i) {
+ $this_select.append(options[i].clone());
+ }
+ $this_select.attr('for', $(this).attr('id')).selectpicker();
+ $this_select.change(function(){
+ let $value = $(this).val();
+ if ($value !== '') {
+ $this_input.val($value);
+ $this_input.hide();
+ } else {
+ $this_input.show();
+ }
+ });
+ $this_input.attr('id', $(this).attr('id'));
+ $this_input.change(function(){
+ $this_select.val($(this).val());
+ if ($this_select.val() === null || $this_select.val() == '') {
+ $this_select.val('');
+ $this_input.show();
+ } else {
+ $this_input.hide();
+ }
+ $this_select.selectpicker('refresh');
+ });
+ $this_input.show();
+ $(this).replaceWith($items);
+ });
+
+ });
});
@@ -169,4 +225,20 @@
+
+
{{ partial("layout_partials/base_dialog",['fields':formDialogFilterRule,'id':'DialogFilterRule','label':lang._('Edit rule')])}}