Skip to content

Commit 26d9fe2

Browse files
committed
net-mgmt/pfSense-pkg-ANDwatch: Add ANDwatch package. Implement #16070.
1 parent a4ac863 commit 26d9fe2

File tree

13 files changed

+906
-0
lines changed

13 files changed

+906
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
PORTNAME= pfSense-pkg-ANDwatch
3+
PORTVERSION= 2.1
4+
CATEGORIES= net-mgmt
5+
MASTER_SITES= # empty
6+
DISTFILES= # empty
7+
8+
MAINTAINER= dennypage@me.com
9+
COMMENT= pfSense package ANDwatch
10+
WWW= https://github.com/dennypage/andwatch
11+
12+
LICENSE= APACHE20
13+
14+
RUN_DEPENDS= andwatch>=2.1.0:net-mgmt/andwatch
15+
16+
NO_BUILD= yes
17+
NO_MTREE= yes
18+
19+
SUB_FILES= pkg-install pkg-deinstall
20+
SUB_LIST= PORTNAME=${PORTNAME}
21+
22+
do-extract:
23+
${MKDIR} ${WRKSRC}
24+
25+
do-install:
26+
${MKDIR} ${STAGEDIR}${PREFIX}/pkg
27+
${MKDIR} ${STAGEDIR}/etc/inc/priv
28+
${MKDIR} ${STAGEDIR}${PREFIX}/www/shortcuts
29+
${MKDIR} ${STAGEDIR}${DATADIR}
30+
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/andwatch.xml \
31+
${STAGEDIR}${PREFIX}/pkg
32+
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/andwatch.inc \
33+
${STAGEDIR}${PREFIX}/pkg
34+
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/andwatch-notify.php \
35+
${STAGEDIR}${PREFIX}/pkg
36+
${INSTALL_DATA} ${FILESDIR}/etc/inc/priv/andwatch.priv.inc \
37+
${STAGEDIR}/etc/inc/priv
38+
${INSTALL_DATA} ${FILESDIR}${DATADIR}/info.xml \
39+
${STAGEDIR}${DATADIR}
40+
${INSTALL_DATA} ${FILESDIR}${PREFIX}/www/shortcuts/pkg_andwatch.inc \
41+
${STAGEDIR}${PREFIX}/www/shortcuts
42+
${INSTALL_DATA} ${FILESDIR}${PREFIX}/www/andwatch.php \
43+
${STAGEDIR}${PREFIX}/www
44+
${INSTALL_DATA} ${FILESDIR}${PREFIX}/www/status_andwatch.php \
45+
${STAGEDIR}${PREFIX}/www
46+
${CHMOD} 555 ${STAGEDIR}${PREFIX}/pkg/andwatch-notify.php
47+
48+
@${REINPLACE_CMD} -i '' -e "s|%%PKGVERSION%%|${PKGVERSION}|" \
49+
${STAGEDIR}${DATADIR}/info.xml
50+
51+
.include <bsd.port.mk>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/*
3+
* andwatch.priv.inc
4+
*
5+
* part of pfSense (https://www.pfsense.org)
6+
* Copyright (c) 2025 Denny Page
7+
* All rights reserved.
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
*/
21+
22+
global $priv_list;
23+
24+
$priv_list['page-services-andwatch'] = array();
25+
$priv_list['page-services-andwatch']['name'] = "WebCfg - Services: ANDwatch";
26+
$priv_list['page-services-andwatch']['descr'] = "Access the ANDwatch package configuration";
27+
$priv_list['page-services-andwatch']['match'] = array();
28+
$priv_list['page-services-andwatch']['match'][] = "andwatch.php";
29+
30+
$priv_list['page-status-andwatch'] = array();
31+
$priv_list['page-status-andwatch']['name'] = "WebCfg - Status: ANDwatch Database";
32+
$priv_list['page-status-andwatch']['descr'] = "Access the ANDwatch package database";
33+
$priv_list['page-status-andwatch']['match'] = array();
34+
$priv_list['page-status-andwatch']['match'][] = "status_andwatch.php*";
35+
36+
?>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
/usr/local/bin/php -f /etc/rc.packages %%PORTNAME%% ${2}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
3+
if [ "${2}" != "POST-INSTALL" ]; then
4+
exit 0
5+
fi
6+
7+
${PKG_ROOTDIR}/usr/local/bin/php -f ${PKG_ROOTDIR}/etc/rc.packages %%PORTNAME%% ${2}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env php
2+
<?php
3+
require_once("notices.inc");
4+
5+
$timestamp=$argv[1];
6+
$ifname=convert_real_interface_to_friendly_descr($argv[2]);
7+
$hostname=$argv[3];
8+
$ipaddr=$argv[4];
9+
$new_hwaddr=$argv[5];
10+
$new_hwaddr_org=$argv[6];
11+
$old_hwaddr=$argv[7];
12+
$old_hwaddr_org=$argv[8];
13+
14+
$msg = "\nANDwatch notificaton\n\n";
15+
$msg .= sprintf("%22s: %s\n", "timestamp", $timestamp);
16+
$msg .= sprintf("%22s: %s\n", "interface", $ifname);
17+
$msg .= sprintf("%22s: %s\n", "hostname", $hostname);
18+
$msg .= sprintf("%22s: %s\n", "ip address", $ipaddr);
19+
$msg .= sprintf("%22s: %s\n", "new ethernet address", $new_hwaddr);
20+
$msg .= sprintf("%22s: %s\n", "new ethernet org", $new_hwaddr_org);
21+
$msg .= sprintf("%22s: %s\n", "old ethernet address", $old_hwaddr);
22+
$msg .= sprintf("%22s: %s\n", "old ethernet org", $old_hwaddr_org);
23+
24+
notify_all_remote($msg);
25+
?>
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<?php
2+
/*
3+
* andwatch.inc
4+
*
5+
* part of pfSense (https://www.pfsense.org)
6+
* Copyright (c) 2025 Denny Page
7+
* All rights reserved.
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
*/
21+
22+
require_once("config.inc");
23+
require_once("functions.inc");
24+
require_once("util.inc");
25+
require_once("service-utils.inc");
26+
27+
const ANDWATCH_SVC_NAME = 'andwatchd';
28+
const ANDWATCH_RC_FILE = '/usr/local/etc/rc.d/andwatch.sh';
29+
const ANDWATCHD_CMD = '/usr/local/bin/andwatchd';
30+
const ANDWATCHD_NOTIFY_CMD = '/usr/local/pkg/andwatch-notify.php';
31+
const ANDWATCHD_PID_PREFIX = '/var/run/andwatch-';
32+
const ANDWATCH_MA_DB_FILE = '/var/db/andwatch/ma_db.sqlite';
33+
const ANDWATCH_UPDATE_MA_CMD = '/usr/local/bin/andwatch-update-ma';
34+
const ANDWATCH_QUERY_CMD = '/usr/local/bin/andwatch-query';
35+
36+
$shortcut_section = 'andwatch';
37+
38+
// Is ANDwatch enabled?
39+
function andwatch_enabled() {
40+
return (config_get_path('installedpackages/andwatch/enable', false));
41+
}
42+
43+
44+
// Write the rc file
45+
function andwatch_write_rcfile() {
46+
// Get the current configuration
47+
$current_config = config_get_path('installedpackages/andwatch');
48+
49+
// Get the real interface names
50+
$interfaces = array();
51+
foreach (explode(',', array_get_path($current_config, 'active_interfaces', '')) as $interface) {
52+
$interfaces[$interface] = get_real_interface($interface);
53+
}
54+
55+
// Ensure the assignments database exists
56+
$start = "if [ \! -f " . ANDWATCH_MA_DB_FILE . " ]\n";
57+
$start .= "\tthen\n";
58+
$start .= "\t\techo Updating MAC Assignments database\n";
59+
$start .= "\t\t" . ANDWATCH_UPDATE_MA_CMD . "\n";
60+
$start .= "\tfi\n\n";
61+
62+
// Individual daemons
63+
$start .= "\techo Starting ANDwatch daemons";
64+
foreach ($interfaces as $interface => $real_interface) {
65+
// Basic configuration with syslog and pid file
66+
$cmd = ANDWATCHD_CMD . " -s -p " . ANDWATCHD_PID_PREFIX . "${real_interface}.pid";
67+
68+
// Notifications
69+
if (array_get_path($current_config, "interfaces/{$interface}/notifications", false)) {
70+
$cmd .= " -n " . ANDWATCHD_NOTIFY_CMD;
71+
}
72+
73+
// Expiration (andwatchd default is 30)
74+
$expiration = array_get_path($current_config, "interfaces/{$interface}/expiration", '30');
75+
if ($expiration != '30') {
76+
$cmd .= " -O ${expiration}";
77+
}
78+
79+
// PCAP filter
80+
$filter = null;
81+
switch (array_get_path($current_config, "interfaces/{$interface}/pcap_filter", 'none')) {
82+
case 'link-local':
83+
$filter = 'not net fe80::0/10';
84+
break;
85+
case 'link-local-private':
86+
$filter = 'not net fe80::0/10 and not net fc00::0/7';
87+
break;
88+
case 'custom':
89+
$filter = trim(array_get_path($current_config, "interfaces/{$interface}/custom_filter"));
90+
break;
91+
}
92+
if (!empty($filter)) {
93+
$cmd .= " -F '${filter}'";
94+
}
95+
96+
$cmd .= " ${real_interface}";
97+
$start .= "\n\t${cmd}";
98+
}
99+
100+
// Write the rc file
101+
$stop = '/usr/bin/killall ' . ANDWATCH_SVC_NAME;
102+
write_rcfile(array(
103+
"file" => "andwatch.sh",
104+
"start" => $start,
105+
"stop" => $stop
106+
)
107+
);
108+
}
109+
110+
111+
// Sync the config
112+
function andwatch_sync_config() {
113+
// Stop the service if it is currently running
114+
if (is_service_running(ANDWATCH_SVC_NAME)) {
115+
log_error("Stopping service ANDwatch");
116+
stop_service(ANDWATCH_SVC_NAME);
117+
}
118+
119+
// If the service is now disabled, remove the cron job and rc file
120+
if (!andwatch_enabled()) {
121+
install_cron_job(ANDWATCH_UPDATE_MA_CMD, false);
122+
unlink_if_exists(ANDWATCH_RC_FILE);
123+
return;
124+
}
125+
126+
// Set a cron job to update the MAC registration database
127+
install_cron_job(ANDWATCH_UPDATE_MA_CMD, true, rand(0,59), rand(0,23), '1,15', '*', '*', 'root', true);
128+
129+
// Write the rc file
130+
andwatch_write_rcfile();
131+
132+
// Take no further action during platform boot
133+
if (is_platform_booting()) {
134+
return;
135+
}
136+
137+
// Start the service
138+
log_error("Starting service ANDwatch");
139+
start_service(ANDWATCH_SVC_NAME);
140+
}
141+
142+
143+
// Clean up on deinstall
144+
function andwatch_deinstall_command() {
145+
if (is_service_running(ANDWATCH_SVC_NAME)) {
146+
log_error("Stopping service ANDwatch");
147+
stop_service(ANDWATCH_SVC_NAME);
148+
}
149+
150+
unlink_if_exists(ANDWATCH_RC_FILE);
151+
}
152+
153+
154+
// Run a query
155+
function andwatch_query_interface($ifname, $all = false)
156+
{
157+
$entries = array();
158+
159+
// Build the query command
160+
$cmd = ANDWATCH_QUERY_CMD;
161+
if ($all) {
162+
$cmd .= ' -a';
163+
}
164+
$cmd .= ' ' . get_real_interface($ifname);
165+
166+
// Run the query
167+
$pipe = popen($cmd, 'r');
168+
if ($pipe) {
169+
while ($line = fgets($pipe)) {
170+
list($date, $time, $age, $hostname, $ipaddr, $hwaddr, $org) = sscanf(trim($line), '%s %s %s %s %s %s %[^$]s');
171+
$entry = [
172+
'datetime' => "$date $time",
173+
'age' => $age,
174+
'hostname' => $hostname,
175+
'ipaddr' => $ipaddr,
176+
'hwaddr' => $hwaddr,
177+
'org' => $org
178+
];
179+
$entries[] = $entry;
180+
}
181+
pclose($pipe);
182+
}
183+
184+
return $entries;
185+
}
186+
187+
?>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
3+
<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
4+
<packagegui>
5+
<copyright>
6+
<![CDATA[
7+
/*
8+
* andwatch.xml
9+
*
10+
* part of pfSense (https://www.pfsense.org)
11+
* Copyright (c) 2025 Denny Page
12+
* All rights reserved.
13+
*
14+
* Licensed under the Apache License, Version 2.0 (the "License");
15+
* you may not use this file except in compliance with the License.
16+
* You may obtain a copy of the License at
17+
*
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
*
20+
* Unless required by applicable law or agreed to in writing, software
21+
* distributed under the License is distributed on an "AS IS" BASIS,
22+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23+
* See the License for the specific language governing permissions and
24+
* limitations under the License.
25+
*/
26+
]]>
27+
</copyright>
28+
<name>andwatch</name>
29+
<title>Services: ANDwatch</title>
30+
<savetext>Change</savetext>
31+
<include_file>/usr/local/pkg/andwatch.inc</include_file>
32+
<menu>
33+
<name>ANDwatch</name>
34+
<tooltiptext>ANDwatch Settings</tooltiptext>
35+
<section>Services</section>
36+
<url>/andwatch.php</url>
37+
</menu>
38+
<menu>
39+
<name>ANDwatch Database</name>
40+
<tooltiptext>ANDwatch Database</tooltiptext>
41+
<section>Status</section>
42+
<url>/status_andwatch.php</url>
43+
</menu>
44+
<service>
45+
<name>andwatchd</name>
46+
<rcfile>andwatch.sh</rcfile>
47+
<executable>andwatchd</executable>
48+
<description>ANDwatch Daemon</description>
49+
<starts_on_sync></starts_on_sync>
50+
</service>
51+
<custom_php_resync_config_command>
52+
andwatch_sync_config();
53+
</custom_php_resync_config_command>
54+
<custom_php_pre_deinstall_command>
55+
andwatch_deinstall_command();
56+
</custom_php_pre_deinstall_command>
57+
</packagegui>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0"?>
2+
<pfsensepkgs>
3+
<package>
4+
<name>ANDwatch</name>
5+
<website>https://github.com/dennypage/andwatch/</website>
6+
<descr><![CDATA[ANDwatch monitors Arp and Neighbor Discovery activity, maintains a database of IP to Ethernet address mappings, and sends notifications when a mapping changes.]]></descr>
7+
<version>%%PKGVERSION%%</version>
8+
<configurationfile>andwatch.xml</configurationfile>
9+
</package>
10+
</pfsensepkgs>

0 commit comments

Comments
 (0)