diff --git a/plist b/plist
index adfb24c63..da952c1b7 100644
--- a/plist
+++ b/plist
@@ -293,6 +293,7 @@
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/NetflowController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/NetworkinsightController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/PacketCaptureController.php
+/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/PingController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/SystemController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/SystemhealthController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/TrafficController.php
@@ -303,12 +304,14 @@
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/NetflowController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/NetworkinsightController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/PacketCaptureController.php
+/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/PingController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/SystemController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/SystemhealthController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/TrafficController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/dns_diagnostics.xml
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/netflow_capture.xml
/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/packetcapture.xml
+/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/ping.xml
/usr/local/opnsense/mvc/app/controllers/OPNsense/Firewall/AliasController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Firewall/AliasUtilController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/AliasController.php
@@ -579,6 +582,8 @@
/usr/local/opnsense/mvc/app/models/OPNsense/Diagnostics/Netflow.xml
/usr/local/opnsense/mvc/app/models/OPNsense/Diagnostics/PacketCapture.php
/usr/local/opnsense/mvc/app/models/OPNsense/Diagnostics/PacketCapture.xml
+/usr/local/opnsense/mvc/app/models/OPNsense/Diagnostics/Ping.php
+/usr/local/opnsense/mvc/app/models/OPNsense/Diagnostics/Ping.xml
/usr/local/opnsense/mvc/app/models/OPNsense/Dnsmasq/ACL/ACL.xml
/usr/local/opnsense/mvc/app/models/OPNsense/Dnsmasq/Menu/Menu.xml
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/Alias.php
@@ -688,6 +693,7 @@
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/netflow.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/networkinsight.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/packetcapture.volt
+/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/ping.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/routes.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/systemactivity.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/traffic.volt
@@ -890,6 +896,7 @@
/usr/local/opnsense/scripts/interfaces/list_sockstat.py
/usr/local/opnsense/scripts/interfaces/macinfo.py
/usr/local/opnsense/scripts/interfaces/mpd.script
+/usr/local/opnsense/scripts/interfaces/ping.py
/usr/local/opnsense/scripts/interfaces/ppp-linkdown.sh
/usr/local/opnsense/scripts/interfaces/ppp-linkup.sh
/usr/local/opnsense/scripts/interfaces/ppp-uptime.sh
@@ -1898,7 +1905,6 @@
/usr/local/www/diag_confbak.php
/usr/local/www/diag_defaults.php
/usr/local/www/diag_logs_settings.php
-/usr/local/www/diag_ping.php
/usr/local/www/diag_testport.php
/usr/local/www/diag_traceroute.php
/usr/local/www/fbegin.inc
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/PingController.php b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/PingController.php
new file mode 100644
index 000000000..d8cce12ad
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/PingController.php
@@ -0,0 +1,131 @@
+getModel();
+ $result['result'] = 'ok';
+ $result['uuid'] = $mdl->settings->generateUUID();
+ @mkdir(self::$ping_dir);
+ $nodes = $mdl->settings->getNodes();
+ foreach ($nodes as $key => $value) {
+ if (is_array($value)) {
+ $items = [];
+ foreach ($value as $itemkey => $itemval) {
+ if (!empty($itemval['selected'])) {
+ $items[] = $itemkey;
+ }
+ }
+ $nodes[$key] = implode(',', $items);
+ }
+ }
+ file_put_contents(
+ sprintf('%s/%s.json', self::$ping_dir, $result['uuid']),
+ json_encode($nodes)
+ );
+ }
+ return $result;
+ }
+
+ /**
+ * start ping job
+ */
+ public function startAction($jobid)
+ {
+ $result = ['status' => 'failed'];
+ if ($this->request->isPost()) {
+ $this->sessionClose();
+ $payload = json_decode((new Backend())->configdpRun('interface ping start', [$jobid]) ?? '', true);
+ if (!empty($payload)) {
+ $result = $payload;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * stop ping job
+ */
+ public function stopAction($jobid)
+ {
+ $result = ['status' => 'failed'];
+ if ($this->request->isPost()) {
+ $this->sessionClose();
+ $payload = json_decode((new Backend())->configdpRun('interface ping stop', [$jobid]) ?? '', true);
+ if (!empty($payload)) {
+ $result = $payload;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * remove ping job
+ */
+ public function removeAction($jobid)
+ {
+ $result = ['status' => 'failed'];
+ if ($this->request->isPost()) {
+ $this->sessionClose();
+ $payload = json_decode((new Backend())->configdpRun('interface ping remove', [$jobid]) ?? '', true);
+ if (!empty($payload)) {
+ $result = $payload;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * search current ping jobs
+ */
+ public function searchJobsAction()
+ {
+ $this->sessionClose();
+ $data = json_decode((new Backend())->configdRun('interface ping list') ?? '', true);
+ $records = (!empty($data) && !empty($data['jobs'])) ? $data['jobs'] : [];
+ return $this->searchRecordsetBase($records);
+ }
+}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/PingController.php b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/PingController.php
new file mode 100644
index 000000000..3488d9a89
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/PingController.php
@@ -0,0 +1,46 @@
+view->pick('OPNsense/Diagnostics/ping');
+ $this->view->pingForm = $this->getForm("ping");
+ }
+}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/ping.xml b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/ping.xml
new file mode 100644
index 000000000..bb95ccf27
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/forms/ping.xml
@@ -0,0 +1,41 @@
+
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 8e2e19fcc..6f9a49c05 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml
@@ -166,7 +166,8 @@
Diagnostics: Ping
- diag_ping.php*
+ ui/diagnostics/ping
+ api/diagnostics/ping/*
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 758ea4dcc..fd1eaf5dd 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml
@@ -134,7 +134,7 @@
-
+
diff --git a/src/opnsense/mvc/app/models/OPNsense/Diagnostics/Ping.php b/src/opnsense/mvc/app/models/OPNsense/Diagnostics/Ping.php
new file mode 100644
index 000000000..9126487c0
--- /dev/null
+++ b/src/opnsense/mvc/app/models/OPNsense/Diagnostics/Ping.php
@@ -0,0 +1,36 @@
+
+ :memory:
+ 1.0.0
+
+ OPNsense Ping Diagnostics
+
+
+
+
+ Y
+ Provide a valid hostname or address to ping
+
+
+ Y
+ ip
+
+ IPv4
+ IPv6
+
+
+
+ N
+ N
+ Provide a valid source address
+
+
+ 1
+ 65535
+
+
+ 0
+
+
+ N
+ /^(.){1,255}$/u
+ Description should be a string between 1 and 255 characters
+
+
+
+
diff --git a/src/opnsense/mvc/app/views/OPNsense/Diagnostics/ping.volt b/src/opnsense/mvc/app/views/OPNsense/Diagnostics/ping.volt
new file mode 100644
index 000000000..f72c70791
--- /dev/null
+++ b/src/opnsense/mvc/app/views/OPNsense/Diagnostics/ping.volt
@@ -0,0 +1,138 @@
+{#
+ # Copyright (c) 2023 Deciso B.V.
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or withoutmodification,
+ # 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.
+ #}
+
+
+
+
+
+
+
+
+
+ {{ partial("layout_partials/base_form",['fields':pingForm,'id':'frm_PingSettings', 'apply_btn_id':'btn_start_new'])}}
+
+
+
+
+
+
+ | |
+ {{ lang._('ID') }} |
+ {{ lang._('Description') }} |
+ {{ lang._('Hostname') }} |
+ {{ lang._('Source') }} |
+ {{ lang._('Send') }} |
+ {{ lang._('Received') }} |
+ {{ lang._('Min') }} |
+ {{ lang._('Max') }} |
+ {{ lang._('Avg') }} |
+ {{ lang._('loss') }} |
+ {{ lang._('Error') }} |
+ {{ lang._('Commands') }} |
+
+
+
+
+
+
+
diff --git a/src/opnsense/scripts/interfaces/ping.py b/src/opnsense/scripts/interfaces/ping.py
new file mode 100755
index 000000000..302c5c5b1
--- /dev/null
+++ b/src/opnsense/scripts/interfaces/ping.py
@@ -0,0 +1,190 @@
+#!/usr/local/bin/python3
+
+"""
+ Copyright (c) 2023 Ad Schellevis
+ 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.
+
+"""
+
+TEMP_DIR = '/tmp/ping/'
+
+import argparse
+import collections
+import glob
+import subprocess
+import os
+import ujson
+import sys
+sys.path.insert(0, "/usr/local/opnsense/site-python")
+from log_helper import reverse_log_reader
+
+
+def ping_pids(jobid):
+ """ search for capture pids using output filename
+ :param jobid: job uuid number
+ :return: list of pids
+ """
+ pids = []
+ args = ['/bin/pgrep', '-af', "ping_%s" % jobid]
+ for line in subprocess.run(args, capture_output=True, text=True).stdout.split():
+ if line.isdigit():
+ pids.append(line)
+ return pids
+
+
+def load_settings(filename):
+ try:
+ return ujson.load(open(filename, 'r'))
+ except ValueError:
+ return {}
+
+
+def read_latest_stats(filename):
+ result = {
+ 'loss': None,
+ 'send': None,
+ 'received': None,
+ 'min': None,
+ 'max': None,
+ 'avg': None,
+ 'std-dev': None,
+ 'last_error': None
+ }
+ next_break = False
+ if os.path.isfile(filename):
+ items = collections.deque(maxlen=5)
+ for line in reverse_log_reader(filename):
+ line = line['line']
+ if line.startswith('ping:'):
+ result['last_error'] = line[6:].strip()
+ if next_break:
+ break
+ items.append(line)
+ if line.endswith('packet loss'):
+ if next_break:
+ break
+ # IPv6
+ for item in items:
+ parts = item.split()
+ if item.endswith('packet loss') and len(parts) >=6:
+ result['loss'] = parts[6]
+ result['send'] = int(parts[0])
+ result['received'] = int(parts[3])
+ elif item.startswith('round-trip') and len(parts) >= 4 and parts[3].count('/') == 3:
+ stats = parts[3].split('/')
+ result['min'] = float(stats[0])
+ result['avg'] = float(stats[1])
+ result['max'] = float(stats[2])
+ result['std-dev'] = float(stats[3])
+ next_break=True
+ elif line.find('packets received') > -1:
+ if next_break:
+ break
+ # IPv4
+ parts = items[-1].split()
+ if parts[0].find('/') > 0:
+ result['send'] = int(parts[0].split('/')[1])
+ result['received'] = int(parts[0].split('/')[0])
+ if len(parts) >= 12:
+ if parts[5] == 'min':
+ result['min'] = float(parts[4])
+ if parts[8] == 'avg':
+ result['avg'] = float(parts[7])
+ if parts[11] == 'max':
+ result['max'] = float(parts[10])
+ if result['send']:
+ loss = (result['send']-result['received']) / result['send'] * 100.0
+ result['loss'] = "%0.2f %%" % loss
+ next_break=True
+ return result
+
+
+if __name__ == '__main__':
+ result = dict()
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--job', help='job id', default=None)
+ parser.add_argument('action', help='action to perfom', choices=['list', 'start', 'stop', 'remove', 'view'])
+ cmd_args = parser.parse_args()
+
+ all_jobs = {}
+ if os.path.exists(TEMP_DIR):
+ for filename in glob.glob("%s*.json" % TEMP_DIR):
+ all_jobs[os.path.basename(filename).split('.')[0]] = filename
+
+ if cmd_args.action == 'list':
+ result['jobs'] = []
+ result['status'] = 'ok'
+ for jobid in all_jobs:
+ this_pids = ping_pids(jobid)
+ if len(this_pids) > 0:
+ with open("%s.pid" % all_jobs[jobid][:-5], 'r') as f_in:
+ subprocess.run(['kill', '-s', 'INFO', f_in.read().strip()])
+ settings = load_settings(all_jobs[jobid])
+ settings['id'] = jobid
+ settings['status'] = "running" if len(this_pids) > 0 else "stopped"
+ # merge stats
+ settings.update(read_latest_stats("%s.log" % all_jobs[jobid][:-5]))
+ result['jobs'].append(settings)
+ elif cmd_args.action == 'start' and cmd_args.job in all_jobs:
+ this_pids = ping_pids(cmd_args.job)
+ if len(this_pids) > 0:
+ result['status'] = 'failed'
+ result['status_msg'] = 'already active (pids: %s)' % ','.join(this_pids)
+ else:
+ result['status'] = 'ok'
+ settings = load_settings(all_jobs[cmd_args.job])
+ log_target = "%s%s.log" % (TEMP_DIR, cmd_args.job)
+ args = [
+ '/usr/sbin/daemon',
+ '-o', log_target,
+ '-p', "%s%s.pid" % (TEMP_DIR, cmd_args.job),
+ '-t', 'ping_%s' % cmd_args.job,
+ '/sbin/ping',
+ '-4' if settings.get('fam', 'ip') == 'ip' else '-6'
+ ]
+ if settings.get('packetsize', '') != '':
+ args.append('-s')
+ args.append(settings['packetsize'])
+ if settings.get('disable_frag', '0') == '1':
+ args.append('-D')
+ args.append(settings.get('hostname', ''))
+ if os.path.isfile(log_target):
+ os.remove(log_target)
+ subprocess.run(args)
+ elif cmd_args.action == 'stop' and cmd_args.job in all_jobs:
+ result['status'] = 'ok'
+ result['stopped_processes'] = 0
+ for pid in ping_pids(cmd_args.job):
+ subprocess.run(['kill', pid])
+ result['stopped_processes'] += 1
+ elif cmd_args.action == 'remove' and cmd_args.job in all_jobs:
+ result['status'] = 'ok'
+ result['stopped_processes'] = 0
+ for pid in ping_pids(cmd_args.job):
+ subprocess.run(['kill', pid])
+ result['stopped_processes'] += 1
+ for filename in glob.glob("%s%s*" % (TEMP_DIR, cmd_args.job)):
+ os.remove(filename)
+
+ print (ujson.dumps(result))
diff --git a/src/opnsense/service/conf/actions.d/actions_interface.conf b/src/opnsense/service/conf/actions.d/actions_interface.conf
index 0c53bd9d2..e6899117e 100644
--- a/src/opnsense/service/conf/actions.d/actions_interface.conf
+++ b/src/opnsense/service/conf/actions.d/actions_interface.conf
@@ -237,3 +237,33 @@ command:/usr/local/opnsense/scripts/interfaces/macinfo.py
parameters: %s
type:script_output
message:fetch mac info for %s
+
+[ping.list]
+command:/usr/local/opnsense/scripts/interfaces/ping.py list
+parameters:
+type:script_output
+message:Show current ping jobs
+
+[ping.start]
+command:/usr/local/opnsense/scripts/interfaces/ping.py
+parameters: --job %s start
+type:script_output
+message:Start ping jobid %s
+
+[ping.stop]
+command:/usr/local/opnsense/scripts/interfaces/ping.py
+parameters: --job %s stop
+type:script_output
+message:Stop ping jobid %s
+
+[ping.remove]
+command:/usr/local/opnsense/scripts/interfaces/ping.py
+parameters: --job %s remove
+type:script_output
+message:Remove ping jobid %s
+
+[ping.view]
+command:/usr/local/opnsense/scripts/interfaces/ping.py
+parameters: --job %s --detail %s view
+type:script_output
+message:View ping jobid %s (%s)
diff --git a/src/www/diag_ping.php b/src/www/diag_ping.php
deleted file mode 100644
index 154cf2982..000000000
--- a/src/www/diag_ping.php
+++ /dev/null
@@ -1,157 +0,0 @@
-
- * Copyright (C) 2016 Deciso B.V.
- * Copyright (C) 2003-2005 Bob Zoller
- * Copyright (C) 2003-2005 Manuel Kasper
- * 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("system.inc");
-require_once("interfaces.inc");
-
-$cmd_output = false;
-if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- // set form defaults
- $pconfig = array();
- $pconfig['count'] = isset($_GET['count']) ? $_GET['count'] : 3;
- $pconfig['host'] = isset($_GET['host']) ? $_GET['host'] : null;
- $pconfig['interface'] = isset($_GET['interface']) ? $_GET['interface'] : null;
-} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
- // validate formdata and schedule action
- $pconfig = $_POST;
- $input_errors = array();
- /* input validation */
- $reqdfields = explode(" ", "host count");
- $reqdfieldsn = array(gettext("Host"),gettext("Count"));
- do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
-
- if (count($input_errors) == 0) {
- $args = [];
- switch ($pconfig['ipproto']) {
- case 'ipv6':
- list ($ifaddr) = interfaces_primary_address6($pconfig['interface']);
- $args[] = '-6';
- break;
- case 'ipv6-ll':
- $args[] = '-6';
- list ($ifaddr) = interfaces_scoped_address6($pconfig['interface']);
- break;
- default:
- $args[] = '-4';
- list ($ifaddr) = interfaces_primary_address($pconfig['interface']);
- break;
- }
- if (!empty($ifaddr)) {
- $args[] = exec_safe('-S %s ', $ifaddr);
- }
- $args[] = exec_safe('-c %s %s', [$pconfig['count'], $pconfig['host']]);
- // execute ping command and catch both stdout and stderr
- $cmd_action = '/sbin/ping ' . implode(' ', $args);
- $process = proc_open($cmd_action, array(array("pipe", "r"), array("pipe", "w"), array("pipe", "w")), $pipes);
- if (is_resource($process)) {
- $cmd_output = "# $cmd_action\n";
- $cmd_output .= stream_get_contents($pipes[1]);
- $cmd_output .= stream_get_contents($pipes[2]);
- }
- }
-}
-
-legacy_html_escape_form_data($pconfig);
-include("head.inc"); ?>
-
-
-
-
-
-
-
- 0) print_input_errors($input_errors); ?>
-
-
-
-
- =htmlspecialchars($cmd_output);?>
-
-
-
-
-
-