bug in zyxel
This commit is contained in:
+73
-6
@@ -2,14 +2,18 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
import requests
|
||||
import yaml
|
||||
from Crypto.Cipher import AES, PKCS1_v1_5
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
@@ -145,13 +149,24 @@ class ZyxelRouter:
|
||||
result = self.dal_get(self.hosts_oid)
|
||||
if result.get("result") not in (None, "ZCFG_SUCCESS"):
|
||||
raise ZyxelError(f"lanhosts query failed: {result.get('result')}")
|
||||
objects = result.get("Object", [])
|
||||
if isinstance(objects, dict):
|
||||
objects = [objects]
|
||||
|
||||
def host_records(value: Any):
|
||||
"""Yield host dictionaries from flat and nested DAL response shapes."""
|
||||
if isinstance(value, dict):
|
||||
if any(
|
||||
key in value
|
||||
for key in ("PhysAddress", "physAddress", "MACAddr", "MacAddress")
|
||||
):
|
||||
yield value
|
||||
return
|
||||
for child in value.values():
|
||||
yield from host_records(child)
|
||||
elif isinstance(value, list):
|
||||
for child in value:
|
||||
yield from host_records(child)
|
||||
|
||||
hosts: list[LanHost] = []
|
||||
for item in objects:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
for item in host_records(result.get("Object", [])):
|
||||
raw_mac = next((item.get(key) for key in ("PhysAddress", "physAddress", "MACAddr", "MacAddress") if item.get(key)), None)
|
||||
if not raw_mac:
|
||||
continue
|
||||
@@ -182,3 +197,55 @@ class ZyxelRouter:
|
||||
self._session_key = None
|
||||
self._aes_key = None
|
||||
self.session.close()
|
||||
|
||||
|
||||
def _load_cli_config(path: Path) -> tuple[dict[str, Any], str]:
|
||||
try:
|
||||
with path.open(encoding="utf-8") as stream:
|
||||
root = yaml.safe_load(stream)
|
||||
arrival = root["arrival_detection"]
|
||||
return arrival["zyxel"], str(arrival["device"]["mac"])
|
||||
except (OSError, TypeError, KeyError, yaml.YAMLError) as error:
|
||||
raise ZyxelError(f"could not load configuration from {path}: {error}") from error
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Check whether a MAC address is connected to the configured Zyxel router."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--config",
|
||||
type=Path,
|
||||
default=Path(__file__).resolve().parents[1] / "service.yaml",
|
||||
help="service configuration file (default: project service.yaml)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--mac",
|
||||
help="MAC address to check (default: arrival_detection.device.mac)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
config, configured_mac = _load_cli_config(args.config)
|
||||
mac = normalize_mac(args.mac or configured_mac)
|
||||
router = ZyxelRouter(
|
||||
config["host"],
|
||||
config["username"],
|
||||
config["password"],
|
||||
timeout=float(config.get("timeout", 10)),
|
||||
verify_tls=bool(config.get("verify_tls", True)),
|
||||
hosts_oid=str(config.get("hosts_oid", "lanhosts")),
|
||||
)
|
||||
try:
|
||||
connected = router.is_connected(mac)
|
||||
finally:
|
||||
router.close()
|
||||
print(f"{mac} {'connected' if connected else 'absent'}")
|
||||
return 0
|
||||
except (ValueError, ZyxelError) as error:
|
||||
print(f"error: {error}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
Reference in New Issue
Block a user