Compare commits

..

6 Commits

Author SHA1 Message Date
jokob-sk
491c202eba ARPSCAN DURATION #1172
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-05 15:38:17 +11:00
jokob-sk
611911b5dd ICMP docs
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-05 15:37:34 +11:00
jokob-sk
e242de0ddf ARPSCAN DURATION #1172
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-05 15:37:17 +11:00
jokob-sk
086cd30355 Prevent Internet root node flipping w/ SYNC plugin enabled #1207
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-05 14:36:03 +11:00
jokob-sk
9b76f3c273 LOG_LEVEL not respected #1217
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-05 14:21:29 +11:00
jokob-sk
d05ddafdd3 logger not repsecting new lines #1217
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-05 14:02:00 +11:00
9 changed files with 62 additions and 15 deletions

View File

@@ -64,7 +64,8 @@
"name": "subnets",
"type": "setting",
"value": "SCAN_SUBNETS",
"base64": true
"base64": true,
"timeoutMultiplier": true
}
],
"settings": [
@@ -387,6 +388,34 @@
"string": "Arguments to run arps-scan with. Recommended and tested only with the setting: <br/> <code>sudo arp-scan --ignoredups --retry=6</code>."
}
]
},
{
"function": "DURATION",
"type": {
"dataType": "integer",
"elements": [
{
"elementType": "input",
"elementOptions": [{ "type": "number" }],
"transformers": []
}
]
},
"default_value": 0,
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Discovery duration"
}
],
"description": [
{
"language_code": "en_us",
"string": "If <code>DURATION</code> is not <code>0</code>, the scan runs repeatedly per interface for that many seconds. <strong>Important:</strong> <code>RUN_TIMEOUT</code> must be greater than <code>DURATION</code>, otherwise the scan will fail."
}
]
}
],
"database_column_definitions": [

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
import os
import time
import pathlib
import argparse
import sys
@@ -46,7 +47,7 @@ def main():
plugin_objects = Plugin_Objects(RESULT_FILE)
# Print a message to indicate that the script is starting.
mylog('verbose', ['[ARP Scan] In script '])
mylog('verbose', [f'[{pluginName}] In script '])
# holds a list of user-submitted subnets.
# mylog('verbose', ['[ARP Scan] values.userSubnets: ', values.userSubnets])
@@ -150,16 +151,28 @@ def execute_arpscan_on_interface(interface):
# Prepare command arguments
arpscan_args = get_setting_value('ARPSCAN_ARGS').split() + interface.split()
# Execute command
# Optional duration in seconds (0 = run once)
try:
# try running a subprocess safely
result = subprocess.check_output(arpscan_args, universal_newlines=True)
except subprocess.CalledProcessError as e:
# An error occurred, handle it
error_type = type(e).__name__ # Capture the error type
result = ""
scan_duration = int(get_setting_value('ARPSCAN_DURATION'))
except Exception:
scan_duration = 0 # default: single run
return result
results = []
start_time = time.time()
while True:
try:
result = subprocess.check_output(arpscan_args, universal_newlines=True)
results.append(result)
except subprocess.CalledProcessError as e:
result = ""
# stop looping if duration not set or expired
if scan_duration == 0 or (time.time() - start_time) > scan_duration:
break
time.sleep(2) # short delay between scans
# concatenate all outputs (for regex parsing)
return "\n".join(results)

View File

@@ -2,6 +2,8 @@
Plugin for pinging existing devices via the [ping](https://linux.die.net/man/8/ping) network utility. The devices have to be accessible from the container. You can use this plugin with other suplementing plugins as described in the [subnets docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md).
This plugin can be used if you are getting false offline positives on specific devices. See the [Fix offline detection guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/FIX_OFFLINE_DETECTION.md) for details.
### Usage
- Check the Settings page for details.

View File

@@ -178,7 +178,7 @@ def main():
if file_name != 'last_result.log':
mylog('verbose', [f'[{pluginName}] Processing: "{file_name}"'])
# make sure the file has teh correct name (e.g last_result.encoded.Node_1.1.log) to skip any otehr plugin files
# make sure the file has the correct name (e.g last_result.encoded.Node_1.1.log) to skip any otehr plugin files
if len(file_name.split('.')) > 2:
# Store e.g. Node_1 from last_result.encoded.Node_1.1.log
syncHubNodeName = file_name.split('.')[1]
@@ -210,9 +210,10 @@ def main():
existing_mac_addresses = set(row[0] for row in cursor.fetchall())
# insert devices into the lats_result.log to manage state
# insert devices into the last_result.log and thus CurrentScan table to manage state
for device in device_data:
if device['devPresentLastScan'] == 1:
# only insert devices taht were online and skip the root node to prevent IP flipping on the hub
if device['devPresentLastScan'] == 1 and str(device['devMac']).lower() != 'internet':
plugin_objects.add_object(
primaryId = device['devMac'],
secondaryId = device['devLastIP'],

0
install/proxmox/README.md Normal file → Executable file
View File

0
install/proxmox/netalertx.conf Normal file → Executable file
View File

0
install/proxmox/requirements.txt Normal file → Executable file
View File

View File

@@ -87,13 +87,13 @@ class Logger:
self.reqLvl = self._to_num(requestedDebugLevel)
self.setLvl = self._to_num(currentLevel)
if self.isAbove(requestedDebugLevel):
file_print(*args)
def isAbove(self, requestedDebugLevel):
reqLvl = self._to_num(requestedDebugLevel)
return reqLvl is not None and self.setLvl >= reqLvl
return reqLvl is not None and self.setLvl is not None and self.setLvl >= reqLvl
#-------------------------------------------------------------------------------
# Dedicated thread for writing logs
@@ -125,6 +125,8 @@ def start_log_writer_thread():
def file_print(*args):
result = timeNowTZ().strftime('%H:%M:%S') + ' '
for arg in args:
if isinstance(arg, list):
arg = ' '.join(str(a) for a in arg) # so taht new lines are handled correctly also when passing a list
result += str(arg)
logging.log(custom_to_logging_levels.get(currentLevel, logging.NOTSET), result)

0
test/test_compound_conditions.py Normal file → Executable file
View File