From 19f42e60ba0257fc2868c6cc55ed9e0f33c2adc0 Mon Sep 17 00:00:00 2001 From: Jokob-sk Date: Mon, 18 Sep 2023 08:31:41 +1000 Subject: [PATCH] vendor_update plugin --- front/plugins/db_cleanup/config.json | 6 +- front/plugins/vendor_update/README.md | 7 + front/plugins/vendor_update/config.json | 408 ++++++++++++++++++++++++ front/plugins/vendor_update/script.py | 120 +++++++ pialert/README.md | 1 - pialert/README_ES.md | 1 - pialert/__main__.py | 8 - pialert/const.py | 2 +- pialert/database.py | 3 +- pialert/device.py | 50 ++- pialert/mac_vendor.py | 113 ------- 11 files changed, 586 insertions(+), 133 deletions(-) create mode 100755 front/plugins/vendor_update/README.md create mode 100755 front/plugins/vendor_update/config.json create mode 100755 front/plugins/vendor_update/script.py delete mode 100755 pialert/mac_vendor.py diff --git a/front/plugins/db_cleanup/config.json b/front/plugins/db_cleanup/config.json index 9dc23e20..aa2917f5 100755 --- a/front/plugins/db_cleanup/config.json +++ b/front/plugins/db_cleanup/config.json @@ -125,15 +125,15 @@ }], "description": [{ "language_code":"en_us", - "string" : "Only enabled if you select schedule in the CSVBCKP_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes." + "string" : "Only enabled if you select schedule in the DBCLNP_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes." }, { "language_code":"es_es", - "string" : "Solo está habilitado si selecciona schedule en la configuración CSVBCKP_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." + "string" : "Solo está habilitado si selecciona schedule en la configuración DBCLNP_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." }, { "language_code":"de_de", - "string" : "Nur aktiviert, wenn Sie schedule in der CSVBCKP_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." + "string" : "Nur aktiviert, wenn Sie schedule in der DBCLNP_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." }] }, { diff --git a/front/plugins/vendor_update/README.md b/front/plugins/vendor_update/README.md new file mode 100755 index 00000000..03fa70f4 --- /dev/null +++ b/front/plugins/vendor_update/README.md @@ -0,0 +1,7 @@ +## Overview + +Plugin to run regular database cleanup tasks. It is strongly recommended to have an hourly or at least daily schedule running. + +### Usage + +- Check the Settings page for details. diff --git a/front/plugins/vendor_update/config.json b/front/plugins/vendor_update/config.json new file mode 100755 index 00000000..096eff43 --- /dev/null +++ b/front/plugins/vendor_update/config.json @@ -0,0 +1,408 @@ +{ + "code_name": "vendor_update", + "unique_prefix": "VNDRPDT", + "enabled": true, + "data_source": "script", + "show_ui": true, + "localized": ["display_name", "description", "icon"], + + "display_name": [ + { + "language_code": "en_us", + "string": "Vendor update" + } + ], + "icon": [ + { + "language_code": "en_us", + "string": "" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "A plugin to schedule vendor database updates for mac based vendor resolution." + } + ], + "params" : [ + ], + + "settings": [ + { + "function": "RUN", + "type": "text.select", + "default_value":"schedule", + "options": ["disabled", "once", "schedule", "always_after_scan"], + "localized": ["name", "description"], + "name" :[{ + "language_code":"en_us", + "string" : "When to run" + }, + { + "language_code":"es_es", + "string" : "Cuándo ejecutar" + }, + { + "language_code":"de_de", + "string" : "Wann laufen" + }], + "description": [{ + "language_code":"en_us", + "string" : "When the cleanup should be performed. An overnight weekly SCHEDULE is recommended." + }] + }, + { + "function": "CMD", + "type": "readonly", + "default_value": "python3 /home/pi/pialert/front/plugins/vendor_update/script.py", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Command" + }, + { + "language_code": "es_es", + "string": "Comando" + }, + { + "language_code": "de_de", + "string": "Befehl" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Command to run. This can not be changed" + }, + { + "language_code": "es_es", + "string": "Comando a ejecutar. Esto no se puede cambiar" + }, + { + "language_code": "de_de", + "string": "Befehl zum Ausführen. Dies kann nicht geändert werden" + } + ] + }, + { + "function": "RUN_SCHD", + "type": "text", + "default_value":"0 4 * * *", + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code":"en_us", + "string" : "Schedule" + }, + { + "language_code":"es_es", + "string" : "Schedule" + }, + { + "language_code":"de_de", + "string" : "Schedule" + }], + "description": [{ + "language_code":"en_us", + "string" : "Only enabled if you select schedule in the VNDRPDT_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes." + }, + { + "language_code":"es_es", + "string" : "Solo está habilitado si selecciona schedule en la configuración VNDRPDT_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." + }, + { + "language_code":"de_de", + "string" : "Nur aktiviert, wenn Sie schedule in der VNDRPDT_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." + }] + }, + { + "function": "RUN_TIMEOUT", + "type": "integer", + "default_value": 300, + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Run timeout" + }, + { + "language_code": "es_es", + "string": "Tiempo límite de ejecución" + }, + { + "language_code": "de_de", + "string": "Zeitüberschreitung" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted." + }, + { + "language_code": "es_es", + "string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela." + }, + { + "language_code": "de_de", + "string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen." + } + ] + } + ], + + "database_column_definitions": + [ + { + "column": "Index", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }, + { + "language_code":"es_es", + "string" : "N/A" + }] + } , + { + "column": "Plugin", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }, + { + "language_code":"es_es", + "string" : "N/A" + }] + }, + { + "column": "Object_PrimaryID", + "mapped_to_column": "cur_MAC", + "css_classes": "col-sm-2", + "show": true, + "type": "device_mac", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "MAC address" + }, + { + "language_code":"es_es", + "string" : "Dirección MAC" + }] + }, + { + "column": "Object_SecondaryID", + "mapped_to_column": "cur_IP", + "css_classes": "col-sm-2", + "show": true, + "type": "device_ip", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "IP" + }, + { + "language_code":"es_es", + "string" : "IP" + }] + } , + { + "column": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Created" + }, + { + "language_code":"es_es", + "string" : "Creado" + }] + }, + { + "column": "DateTimeChanged", + "mapped_to_column": "cur_DateTime", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Changed" + }, + { + "language_code":"es_es", + "string" : "Cambiado" + }] + }, + { + "column": "Dummy", + "mapped_to_column": "cur_ScanMethod", + "mapped_to_column_data": { + "value": "VNDRPDT" + }, + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Scan method" + }, + { + "language_code":"es_es", + "string" : "Método de escaneo" + }] + } , + { + "column": "Watched_Value1", + "mapped_to_column": "cur_Vendor", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Vendor" + }] + }, + { + "column": "Watched_Value2", + "mapped_to_column": "cur_Name", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Hostname" + }, + { + "language_code":"es_es", + "string" : "Nombre de host" + }] + }, + { + "column": "Watched_Value3", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }] + } , + { + "column": "Watched_Value4", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }] + } , + { + "column": "UserData", + "css_classes": "col-sm-2", + "show": false, + "type": "textbox_save", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Comments" + }, + { + "language_code":"es_es", + "string" : "Comentarios" + }] + }, + { + "column": "Extra", + "css_classes": "col-sm-3", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }] + }, + { + "column": "Status", + "css_classes": "col-sm-1", + "show": true, + "type": "replace", + "default_value":"", + "options": [ + { + "equals": "watched-not-changed", + "replacement": "
" + }, + { + "equals": "watched-changed", + "replacement": "
" + }, + { + "equals": "new", + "replacement": "
" + }, + { + "equals": "missing-in-last-scan", + "replacement": "
" + } + ], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Status" + }, + { + "language_code":"es_es", + "string" : "Estado" + }] + } + ] +} diff --git a/front/plugins/vendor_update/script.py b/front/plugins/vendor_update/script.py new file mode 100755 index 00000000..b72d1598 --- /dev/null +++ b/front/plugins/vendor_update/script.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# test script by running: +# /home/pi/pialert/front/plugins/db_cleanup/script.py pluginskeephistory=250 hourstokeepnewdevice=48 daystokeepevents=90 + +import os +import pathlib +import argparse +import sys +import hashlib +import csv +import sqlite3 +from io import StringIO +from datetime import datetime + +sys.path.append("/home/pi/pialert/front/plugins") +sys.path.append('/home/pi/pialert/pialert') + +from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64 +from logger import mylog, append_line_to_file +from helper import timeNowTZ +from const import logPath, pialertPath +from device import query_MAC_vendor + + +CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) +LOG_FILE = os.path.join(CUR_PATH, 'script.log') +RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') + +def main(): + + mylog('verbose', ['[VNDRPDT] In script']) + + # Get newest DB + update_vendor_database() + + # Resolve missing vendors + plugin_objects = Plugin_Objects(RESULT_FILE) + + plugin_objects = update_vendors('/home/pi/pialert/db/pialert.db', plugin_objects) + + plugin_objects.write_result_file() + + mylog('verbose', ['[VNDRPDT] Update complete']) + + return 0 + +#=============================================================================== +# Update device vendors database +#=============================================================================== +def update_vendor_database(): + + # Update vendors DB (iab oui) + mylog('verbose', [' Updating vendors DB (iab & oui)']) + update_args = ['sh', pialertPath + '/back/update_vendors.sh'] + + # Execute command + try: + # try runnning a subprocess safely + update_output = subprocess.check_output (update_args) + except subprocess.CalledProcessError as e: + # An error occured, handle it + mylog('none', [' FAILED: Updating vendors DB, set LOG_LEVEL=debug for more info']) + mylog('none', [e.output]) + + +# resolve missing vendors +def update_vendors (dbPath, plugin_objects): + + # Connect to the PiAlert SQLite database + conn = sqlite3.connect(dbPath) + cursor = conn.cursor() + + # Initialize variables + recordsToUpdate = [] + ignored = 0 + notFound = 0 + + # All devices loop + mylog('verbose', [' Searching devices vendor']) + + for device in cursor.execute ("""SELECT * FROM Devices + WHERE dev_Vendor = '(unknown)' + OR dev_Vendor ='' + OR dev_Vendor IS NULL""") : + # Search vendor in HW Vendors DB + vendor = query_MAC_vendor (device['dev_MAC']) + if vendor == -1 : + notFound += 1 + elif vendor == -2 : + ignored += 1 + else : + plugin_objects.add_object( + primaryId = device['dev_MAC'], # MAC (Device Name) + secondaryId = device['dev_LastIP'], # IP Address (always 0.0.0.0) + watched1 = vendor, + watched2 = device['dev_Name'], + watched3 = "", + watched4 = "", + extra = "", + foreignKey = device['dev_MAC'] + ) + + # Print log + mylog('verbose', [" Devices Ignored: ", ignored]) + mylog('verbose', [" Vendors Not Found:", notFound]) + mylog('verbose', [" Vendors updated: ", len(plugin_objects) ]) + + conn.commit() + # Close the database connection + conn.close() + + return plugin_objects + + + +#=============================================================================== +# BEGIN +#=============================================================================== +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/pialert/README.md b/pialert/README.md index 41c5399d..5d6ff197 100755 --- a/pialert/README.md +++ b/pialert/README.md @@ -17,7 +17,6 @@ The original pilaert.py code is now moved to this new folder and split into diff |```helper.py```| Helper as the name suggest contains multiple little functions and methods used in many of the other modules and helps keep things clean | |```initialise.py```| Initiatlise sets up the environment and makes everything ready to go | |```logger.py```| Logger is there the keep all the logs organised and looking identical. | -|```mac_vendor.py```| This module runs and manages the ``` update_vendors.sh ``` script from within Pi.Alert | |```networscan.py```| Networkscan orchestrates the actual scanning of the network, calling the individual scanners and managing the results | |```plugin.py```| This is where the plugins get integrated into the backend of Pi.Alert | |```reporting.py```| Reporting generates the email, html and json reports to be sent by the publishers | diff --git a/pialert/README_ES.md b/pialert/README_ES.md index a9a6510b..664ce689 100755 --- a/pialert/README_ES.md +++ b/pialert/README_ES.md @@ -18,7 +18,6 @@ El código pilaert.py original ahora se mueve a esta nueva carpeta y se divide e |```helper.py```| Helper como su nombre indica contiene múltiples pequeñas funciones y métodos utilizados en muchos de los otros módulos y ayuda a mantener las cosas limpias | |```initialise.py```| Initiatlise prepara el entorno y deja todo listo para funcionar | |```logger.py```| Logger está ahí para mantener todos los registros organizados y con el mismo aspecto | -|```mac_vendor.py```| Este módulo ejecuta y gestiona el ``` update_vendors.sh ``` script desde Pi.Alert | |```networscan.py```| El escaneado de red organiza el escaneado real de la red, llamando a los escáneres individuales y gestionando los resultados | |```plugin.py```| Aquí es donde los plugins se integran en el backend de Pi.Alert | |```reporting.py```| La generación de informes genera los informes de correo electrónico, html y json que deben enviar los editores | diff --git a/pialert/__main__.py b/pialert/__main__.py index e96bef15..c4b8d772 100755 --- a/pialert/__main__.py +++ b/pialert/__main__.py @@ -28,7 +28,6 @@ from helper import filePermissions, isNewVersion, timeNowTZ, updateState, get from api import update_api from networkscan import process_scan from initialise import importConfigs -from mac_vendor import update_devices_MAC_vendors from database import DB, get_all_devices from reporting import check_and_run_event, send_notifications from plugin import run_plugin_scripts @@ -146,13 +145,6 @@ def main (): conf.cycle = 'internet_IP' last_internet_IP_scan = loop_start_time check_internet_IP(db) - - # Update vendors once a week - if conf.last_update_vendors + datetime.timedelta(days = 7) < loop_start_time: - conf.last_update_vendors = loop_start_time - conf.cycle = 'update_vendors' - mylog('verbose', ['[MAIN] cycle:',conf.cycle]) - update_devices_MAC_vendors(db) # Run splugin scripts which are set to run every timne after a scans finished pluginsState = run_plugin_scripts(db,'always_after_scan', pluginsState) diff --git a/pialert/const.py b/pialert/const.py index d2a01d01..932b6e14 100755 --- a/pialert/const.py +++ b/pialert/const.py @@ -18,7 +18,7 @@ fullDbPath = pialertPath + dbPath -vendorsDB = '/usr/share/arp-scan/ieee-oui.txt' +vendorsDB = '/usr/share/arp-scan/ieee-oui.txt' diff --git a/pialert/database.py b/pialert/database.py index 088811b8..6953c2b4 100755 --- a/pialert/database.py +++ b/pialert/database.py @@ -362,8 +362,7 @@ class DB(): # indicates, if CurrentScan table is available self.sql.execute("DROP TABLE IF EXISTS CurrentScan;") - self.sql.execute(""" CREATE TABLE CurrentScan ( - cur_ScanCycle INTEGER, + self.sql.execute(""" CREATE TABLE CurrentScan ( cur_MAC STRING(50) NOT NULL COLLATE NOCASE, cur_IP STRING(50) NOT NULL COLLATE NOCASE, cur_Vendor STRING(250), diff --git a/pialert/device.py b/pialert/device.py index ffb6d602..16c872b9 100755 --- a/pialert/device.py +++ b/pialert/device.py @@ -6,7 +6,7 @@ import re from helper import timeNowTZ, get_setting, get_setting_value,resolve_device_name_dig, resolve_device_name_pholus from scanners.internet import check_IP_format, get_internet_IP from logger import mylog, print_log -from mac_vendor import query_MAC_vendor +from const import vendorsDB #------------------------------------------------------------------------------- @@ -23,8 +23,8 @@ def save_scanned_devices (db): # TESTING - Force IP # internet_IP = "" if internet_IP != "" : - sql.execute (f"""INSERT INTO CurrentScan (cur_ScanCycle, cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) - VALUES ( 1, 'Internet', '{internet_IP}', Null, 'queryDNS') """) + sql.execute (f"""INSERT INTO CurrentScan (cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) + VALUES ( 'Internet', '{internet_IP}', Null, 'queryDNS') """) # #76 Add Local MAC of default local interface # BUGFIX #106 - Device that pialert is running @@ -50,7 +50,7 @@ def save_scanned_devices (db): # Check if local mac has been detected with other methods sql.execute (f"SELECT COUNT(*) FROM CurrentScan WHERE cur_MAC = '{local_mac}'") if sql.fetchone()[0] == 0 : - sql.execute (f"""INSERT INTO CurrentScan (cur_ScanCycle, cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) VALUES ( 1, '{local_mac}', '{local_ip}', Null, 'local_MAC') """) + sql.execute (f"""INSERT INTO CurrentScan (cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) VALUES ( '{local_mac}', '{local_ip}', Null, 'local_MAC') """) #------------------------------------------------------------------------------- def print_scan_stats(db): @@ -311,3 +311,45 @@ def check_mac_or_internet(input_str): return True else: return False + + +#=============================================================================== +# Lookup unknown vendors on devices +#=============================================================================== + +#------------------------------------------------------------------------------- +def query_MAC_vendor (pMAC): + try : + # BUGFIX #6 - Fix pMAC parameter as numbers + pMACstr = str(pMAC) + + # Check MAC parameter + mac = pMACstr.replace (':','') + if len(pMACstr) != 17 or len(mac) != 12 : + return -2 + + # Search vendor in HW Vendors DB + mac = mac[0:6] + grep_args = ['grep', '-i', mac, vendorsDB] + + # Execute command + if conf.LOG_LEVEL == 'debug': + # try runnning a subprocess + grep_output = subprocess.check_output (grep_args) + else: + try: + # try runnning a subprocess + grep_output = subprocess.check_output (grep_args) + except subprocess.CalledProcessError as e: + # An error occured, handle it + mylog('none', ["[Mac Vendor Check] Error: ", e.output]) + grep_output = " There was an error, check logs for details" + + # Return Vendor + vendor = grep_output[7:] + vendor = vendor.rstrip() + return vendor + + # not Found + except subprocess.CalledProcessError : + return -1 diff --git a/pialert/mac_vendor.py b/pialert/mac_vendor.py deleted file mode 100755 index 8b4aafad..00000000 --- a/pialert/mac_vendor.py +++ /dev/null @@ -1,113 +0,0 @@ - -import subprocess -import conf - -from const import pialertPath, vendorsDB -from helper import timeNowTZ, updateState -from logger import mylog - - -#=============================================================================== -# UPDATE DEVICE MAC VENDORS -#=============================================================================== - - - -def update_devices_MAC_vendors (db, pArg = ''): - sql = db.sql # TO-DO - # Header - updateState("Upkeep: Vendors") - mylog('verbose', ['[', timeNowTZ(), '] Upkeep - Update HW Vendors:' ]) - - # Update vendors DB (iab oui) - mylog('verbose', [' Updating vendors DB (iab & oui)']) - update_args = ['sh', pialertPath + '/back/update_vendors.sh', pArg] - - # Execute command - if conf.LOG_LEVEL == 'debug': - # try runnning a subprocess - update_output = subprocess.check_output (update_args) - else: - try: - # try runnning a subprocess safely - update_output = subprocess.check_output (update_args) - except subprocess.CalledProcessError as e: - # An error occured, handle it - mylog('none', [' FAILED: Updating vendors DB, set LOG_LEVEL=debug for more info']) - mylog('none', [e.output]) - - # Initialize variables - recordsToUpdate = [] - ignored = 0 - notFound = 0 - - # All devices loop - mylog('verbose', [' Searching devices vendor']) - for device in sql.execute ("""SELECT * FROM Devices - WHERE dev_Vendor = '(unknown)' - OR dev_Vendor ='' - OR dev_Vendor IS NULL""") : - # Search vendor in HW Vendors DB - vendor = query_MAC_vendor (device['dev_MAC']) - if vendor == -1 : - notFound += 1 - elif vendor == -2 : - ignored += 1 - else : - recordsToUpdate.append ([vendor, device['dev_MAC']]) - - # Print log - mylog('verbose', [" Devices Ignored: ", ignored]) - mylog('verbose', [" Vendors Not Found:", notFound]) - mylog('verbose', [" Vendors updated: ", len(recordsToUpdate) ]) - - - # update devices - sql.executemany ("UPDATE Devices SET dev_Vendor = ? WHERE dev_MAC = ? ", - recordsToUpdate ) - - # Commit DB - db.commitDB() - - if len(recordsToUpdate) > 0: - return True - else: - return False - -#------------------------------------------------------------------------------- -def query_MAC_vendor (pMAC): - try : - # BUGFIX #6 - Fix pMAC parameter as numbers - pMACstr = str(pMAC) - - # Check MAC parameter - mac = pMACstr.replace (':','') - if len(pMACstr) != 17 or len(mac) != 12 : - return -2 - - # Search vendor in HW Vendors DB - mac = mac[0:6] - grep_args = ['grep', '-i', mac, vendorsDB] - - # Execute command - if conf.LOG_LEVEL == 'debug': - # try runnning a subprocess - grep_output = subprocess.check_output (grep_args) - else: - try: - # try runnning a subprocess - grep_output = subprocess.check_output (grep_args) - except subprocess.CalledProcessError as e: - # An error occured, handle it - mylog('none', ["[Mac Vendor Check] Error: ", e.output]) - grep_output = " There was an error, check logs for details" - - # Return Vendor - vendor = grep_output[7:] - vendor = vendor.rstrip() - return vendor - - # not Found - except subprocess.CalledProcessError : - return -1 -