Development

This commit is contained in:
Matthew Grotke 2026-05-31 22:29:05 -04:00
parent 96f6e32c8f
commit 5575b06b64
7 changed files with 126 additions and 63 deletions

View file

@ -308,6 +308,82 @@ def check_blocklist_name_unique(blocklists, name, exclude_idx=None):
return None
# ===================================================================
# DHCP reservation checks (callable independently by action.py)
# ===================================================================
def check_reservation_ip_conflicts(ip, vlan):
"""Return error string if ip conflicts with the VLAN's pool range or server identities, else None."""
if not ip or ip == 'dynamic':
return None
dhcp = vlan.get('dhcp_information', {})
pool_start = dhcp.get('dynamic_pool_start')
pool_end = dhcp.get('dynamic_pool_end')
if pool_start and pool_end:
try:
if (ipaddress.IPv4Address(pool_start) <= ipaddress.IPv4Address(ip)
<= ipaddress.IPv4Address(pool_end)):
return f'{ip} falls within the dynamic pool range ({pool_start}-{pool_end}).'
except Exception:
pass
identity_ips = {s['ip'] for s in vlan.get('server_identities', []) if s.get('ip')}
if ip in identity_ips:
return f'{ip} is already assigned as a server identity IP.'
return None
# ===================================================================
# Host override checks (callable independently by action.py)
# ===================================================================
def check_host_override_ip_in_vlans(ip_str, cfg):
"""Return error string if ip_str is not within any configured VLAN subnet, else None."""
try:
addr = ipaddress.IPv4Address(ip_str)
except ValueError:
return f"'{ip_str}' is not a valid IPv4 address."
nets = []
for v in cfg.get('vlans', []):
subnet = v.get('subnet', '')
mask = v.get('subnet_mask', '')
if subnet and mask:
try:
nets.append(ipaddress.IPv4Network(f'{subnet}/{mask}', strict=False))
except ValueError:
pass
if not nets:
return None
if not any(addr in net for net in nets):
return 'IP address does not fall within any configured VLAN subnet.'
return None
# ===================================================================
# VPN uniqueness checks (callable independently by action.py)
# ===================================================================
def check_vpn_listen_port_unique(vlans, listen_port, exclude_vlan_name=None):
"""Return error string if listen_port is already used by another VPN VLAN, else None."""
for v in vlans:
if not v.get('is_vpn'):
continue
if exclude_vlan_name is not None and v.get('name') == exclude_vlan_name:
continue
if v.get('vpn_information', {}).get('listen_port') == listen_port:
return f'Listen port {listen_port} is already used by another VPN VLAN.'
return None
def check_peer_name_unique(peers, name, exclude_idx=None):
"""Return error string if name is already used by another peer, else None."""
for i, p in enumerate(peers):
if exclude_idx is not None and i == exclude_idx:
continue
if p.get('name') == name:
return f'A peer named "{name}" already exists.'
return None
# ===================================================================
# Physical interface checks (callable independently by action.py)
# ===================================================================