diff --git a/src/opnsense/mvc/app/controllers/OPNsense/IPsec/Api/TunnelController.php b/src/opnsense/mvc/app/controllers/OPNsense/IPsec/Api/TunnelController.php
new file mode 100644
index 000000000..27d9a5ce3
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/IPsec/Api/TunnelController.php
@@ -0,0 +1,123 @@
+request->getPost('rowCount', 'int', 9999));
+ $currentPage = intval($this->request->getPost('current', 'int', 1));
+ $offset = ($currentPage - 1) * $itemsPerPage;
+ $entry_keys = array_keys($records);
+ if ($this->request->hasPost('searchPhrase') && $this->request->getPost('searchPhrase') !== '') {
+ $searchPhrase = (string)$this->request->getPost('searchPhrase');
+ $entry_keys = array_filter($entry_keys, function ($key) use ($searchPhrase, $records) {
+ foreach ($records[$key] as $itemval) {
+ if (stripos($itemval, $searchPhrase) !== false) {
+ return true;
+ }
+ }
+ return false;
+ });
+ }
+ $formatted = array_map(function ($value) use (&$records) {
+ foreach ($records[$value] as $ekey => $evalue) {
+ $item[$ekey] = $evalue;
+ }
+ return $item;
+ }, array_slice($entry_keys, $offset, $itemsPerPage));
+
+ if ($this->request->hasPost('sort') && is_array($this->request->getPost('sort'))) {
+ $keys = array_keys($this->request->getPost('sort'));
+ $order = $this->request->getPost('sort')[$keys[0]];
+ $keys = array_column($formatted, $keys[0]);
+ array_multisort($keys, $order == 'asc' ? SORT_ASC : SORT_DESC, $formatted);
+ }
+
+ return [
+ 'total' => count($entry_keys),
+ 'rowCount' => $itemsPerPage,
+ 'current' => $currentPage,
+ 'rows' => $formatted,
+ ];
+ }
+ public function searchPhase1Action()
+ {
+ $items = [];
+ $this->sessionClose();
+ $config = Config::getInstance()->object();
+ if (!empty($config->ipsec->phase1)) {
+ $idx = 0;
+ $ifs = [];
+ if ($config->interfaces->count() > 0) {
+ foreach ($config->interfaces->children() as $key => $node) {
+ $ifs[(string)$node->if] = !empty((string)$node->descr) ? (string)$node->descr : $key;
+ }
+ if ($config->virtualip->count() > 0) {
+ foreach ($config->virtualip->children() as $node) {
+ if (!empty((string)$node->vhid)) {
+ $key = (string)$node->interface . "_vip". (string)$node->vhid;
+ } else {
+ $key = (string)$node->subnet;
+ }
+ $ifs[$key] = "$node->subnet ({$node->descr})";
+ }
+ }
+ }
+ foreach ($config->ipsec->phase1 as $p1) {
+ $interface = (string)$p1->interface;
+ $ph1type= ['ikev1' => 'IKE', 'ikev2' => 'IKEv2', 'ike' => 'auto'];
+ $item = [
+ "id" => $idx,
+ "disabled" => !empty((string)$p1->disabled),
+ "protocol" => $p1->protocol == "inet" ? "IPv4" : "IPv6",
+ "iketype" => $ph1type[(string)$p1->iketype],
+ "interface" => !empty($ifs[$interface]) ? $ifs[$interface] : $interface,
+ "remote_gateway" => (string)$p1->{"remote-gateway"},
+ "mobile" => !empty((string)$p1->mobile),
+ "mode" => (string)$p1->mode,
+ "description" => (string)$p1->descr
+ ];
+ $item['type'] = "{$item['protocol']} {$item['iketype']}";
+ $items[] = $item;
+ $idx++;
+ }
+ }
+ return $this->search($items);
+ }
+}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/IPsec/TunnelsController.php b/src/opnsense/mvc/app/controllers/OPNsense/IPsec/TunnelsController.php
new file mode 100644
index 000000000..d8d3f71ad
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/IPsec/TunnelsController.php
@@ -0,0 +1,41 @@
+view->pick('OPNsense/IPsec/tunnels');
+ }
+}
diff --git a/src/opnsense/mvc/app/views/OPNsense/IPsec/tunnels.volt b/src/opnsense/mvc/app/views/OPNsense/IPsec/tunnels.volt
new file mode 100644
index 000000000..c15cac51e
--- /dev/null
+++ b/src/opnsense/mvc/app/views/OPNsense/IPsec/tunnels.volt
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+ | ID |
+ {{ lang._('Type') }} |
+ {{ lang._('Remote Gateway') }} |
+ {{ lang._('Mode') }} |
+ {{ lang._('Phase 1 Proposal') }} |
+ {{ lang._('Authentication') }} |
+ {{ lang._('Description') }} |
+ {{ lang._('Commands') }} |
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+ | ID |
+ {{ lang._('Type') }} |
+ {{ lang._('Local Subnet') }} |
+ {{ lang._('Remote Subnet') }} |
+ {{ lang._('Phase 2 Proposal') }} |
+ {{ lang._('Description') }} |
+ {{ lang._('Commands') }} |
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+