mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-04-30 18:52:14 +02:00
Changing from 'Global' Flood to 'Unscoped' flood as '*' doesn't actually mean wildcard, it means unscoped. Region keys should still only be forwaded if they're whitelisted. UI changes pending
This commit is contained in:
@@ -152,12 +152,12 @@ def save_config(config_data: Dict[str, Any], config_path: Optional[str] = None)
|
||||
return False
|
||||
|
||||
|
||||
def update_global_flood_policy(allow: bool, config_path: Optional[str] = None) -> bool:
|
||||
def update_unscoped_flood_policy(allow: bool, config_path: Optional[str] = None) -> bool:
|
||||
"""
|
||||
Update the global flood policy in the configuration.
|
||||
Update the unscoped flood policy in the configuration.
|
||||
|
||||
Args:
|
||||
allow: True to allow flooding globally, False to deny
|
||||
allow: True to allow unscoped flooding, False to deny
|
||||
config_path: Path to config file (uses default if None)
|
||||
|
||||
Returns:
|
||||
@@ -173,12 +173,13 @@ def update_global_flood_policy(allow: bool, config_path: Optional[str] = None) -
|
||||
|
||||
# Set global flood policy
|
||||
config["mesh"]["global_flood_allow"] = allow
|
||||
config["mesh"]["unscoped_flood_allow"] = allow
|
||||
|
||||
# Save updated config
|
||||
return save_config(config, config_path)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to update global flood policy: {e}")
|
||||
logger.error(f"Failed to update unscoped flood policy: {e}")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -623,10 +623,10 @@ class RepeaterHandler(BaseHandler):
|
||||
route_type = packet.header & PH_ROUTE_MASK
|
||||
|
||||
if route_type == ROUTE_TYPE_FLOOD:
|
||||
# Check if global flood policy blocked it
|
||||
global_flood_allow = self.config.get("mesh", {}).get("global_flood_allow", True)
|
||||
if not global_flood_allow:
|
||||
return "Global flood policy disabled"
|
||||
# Check if unscoped flood policy blocked it
|
||||
unscoped_flood_allow = self.config.get("mesh", {}).get("unscoped_flood_allow", self.config.get("mesh", {}).get("global_flood_allow", True))
|
||||
if not unscoped_flood_allow:
|
||||
return "Unscoped flood policy disabled"
|
||||
|
||||
if route_type == ROUTE_TYPE_DIRECT:
|
||||
hash_size = packet.get_path_hash_size()
|
||||
@@ -800,19 +800,20 @@ class RepeaterHandler(BaseHandler):
|
||||
if not packet.drop_reason:
|
||||
packet.drop_reason = "Marked do not retransmit"
|
||||
return None
|
||||
|
||||
# Check unscoped flood policy
|
||||
unscoped_flood_allow = self.config.get("mesh", {}).get("unscoped_flood_allow", self.config.get("mesh", {}).get("global_flood_allow", True))
|
||||
route_type = packet.header & PH_ROUTE_MASK
|
||||
if route_type == ROUTE_TYPE_FLOOD:
|
||||
if not unscoped_flood_allow:
|
||||
packet.drop_reason = "Unscoped flood policy disabled"
|
||||
return None
|
||||
|
||||
# Check global flood policy
|
||||
global_flood_allow = self.config.get("mesh", {}).get("global_flood_allow", True)
|
||||
if not global_flood_allow:
|
||||
route_type = packet.header & PH_ROUTE_MASK
|
||||
if route_type == ROUTE_TYPE_FLOOD or route_type == ROUTE_TYPE_TRANSPORT_FLOOD:
|
||||
|
||||
allowed, check_reason = self._check_transport_codes(packet)
|
||||
if not allowed:
|
||||
packet.drop_reason = check_reason
|
||||
return None
|
||||
else:
|
||||
packet.drop_reason = "Global flood policy disabled"
|
||||
#Check transport scopes flood policy
|
||||
if route_type == ROUTE_TYPE_TRANSPORT_FLOOD:
|
||||
allowed, check_reason = self._check_transport_codes(packet)
|
||||
if not allowed:
|
||||
packet.drop_reason = "Transport code not allowed to flood"
|
||||
return None
|
||||
|
||||
mode = self._get_loop_detect_mode()
|
||||
@@ -1134,7 +1135,7 @@ class RepeaterHandler(BaseHandler):
|
||||
"web": self.config.get("web", {}), # Include web configuration
|
||||
"mesh": {
|
||||
"loop_detect": self.config.get("mesh", {}).get("loop_detect", "off"),
|
||||
"global_flood_allow": self.config.get("mesh", {}).get("global_flood_allow", True),
|
||||
"unscoped_flood_allow": self.config.get("mesh", {}).get("unscoped_flood_allow", self.config.get("mesh", {}).get("global_flood_allow", True)),
|
||||
"path_hash_mode": self.config.get("mesh", {}).get("path_hash_mode", 0),
|
||||
},
|
||||
"letsmesh": self.config.get("letsmesh", {}),
|
||||
|
||||
@@ -15,7 +15,7 @@ from repeater.companion.identity_resolve import (
|
||||
find_companion_index,
|
||||
heal_companion_empty_names,
|
||||
)
|
||||
from repeater.config import update_global_flood_policy
|
||||
from repeater.config import update_unscoped_flood_policy
|
||||
|
||||
from .auth.middleware import require_auth
|
||||
from .auth_endpoints import AuthAPIEndpoints
|
||||
@@ -93,8 +93,8 @@ logger = logging.getLogger("HTTPServer")
|
||||
# DELETE /api/transport_key?key_id=X - Delete transport key
|
||||
|
||||
# Network Policy
|
||||
# GET /api/global_flood_policy - Get global flood policy
|
||||
# POST /api/global_flood_policy - Update global flood policy
|
||||
# GET /api/unscoped_flood_policy - Get unscoped flood policy
|
||||
# POST /api/unscoped_flood_policy - Update unscoped flood policy
|
||||
# POST /api/ping_neighbor - Ping a neighbor node
|
||||
|
||||
# Identity Management
|
||||
@@ -2153,57 +2153,57 @@ class APIEndpoints:
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
@cherrypy.tools.json_in()
|
||||
def global_flood_policy(self):
|
||||
def unscoped_flood_policy(self):
|
||||
"""
|
||||
Update global flood policy configuration
|
||||
Update unscoped flood policy configuration
|
||||
|
||||
POST /global_flood_policy
|
||||
Body: {"global_flood_allow": true/false}
|
||||
POST /unscoped_flood_policy
|
||||
Body: {"unscoped_flood_allow": true/false}
|
||||
"""
|
||||
if cherrypy.request.method == "POST":
|
||||
try:
|
||||
data = cherrypy.request.json or {}
|
||||
global_flood_allow = data.get("global_flood_allow")
|
||||
unscoped_flood_allow = data.get("unscoped_flood_allow")
|
||||
|
||||
if global_flood_allow is None:
|
||||
return self._error("Missing required field: global_flood_allow")
|
||||
if unscoped_flood_allow is None:
|
||||
return self._error("Missing required field: unscoped_flood_allow")
|
||||
|
||||
if not isinstance(global_flood_allow, bool):
|
||||
return self._error("global_flood_allow must be a boolean value")
|
||||
if not isinstance(unscoped_flood_allow, bool):
|
||||
return self._error("unscoped_flood_allow must be a boolean value")
|
||||
|
||||
# Update the running configuration first (like CAD settings)
|
||||
if "mesh" not in self.config:
|
||||
self.config["mesh"] = {}
|
||||
self.config["mesh"]["global_flood_allow"] = global_flood_allow
|
||||
self.config["mesh"]["unscoped_flood_allow"] = unscoped_flood_allow
|
||||
|
||||
# Get the actual config path from daemon instance (same as CAD settings)
|
||||
config_path = getattr(self, "_config_path", "/etc/pymc_repeater/config.yaml")
|
||||
if self.daemon_instance and hasattr(self.daemon_instance, "config_path"):
|
||||
config_path = self.daemon_instance.config_path
|
||||
|
||||
logger.info(f"Using config path for global flood policy: {config_path}")
|
||||
logger.info(f"Using config path for unscoped flood policy: {config_path}")
|
||||
|
||||
# Update the configuration file using ConfigManager
|
||||
try:
|
||||
saved = self.config_manager.save_to_file()
|
||||
if saved:
|
||||
logger.info(
|
||||
f"Updated running config and saved global flood policy to file: {'allow' if global_flood_allow else 'deny'}"
|
||||
f"Updated running config and saved unscoped flood policy to file: {'allow' if unscoped_flood_allow else 'deny'}"
|
||||
)
|
||||
else:
|
||||
logger.error("Failed to save global flood policy to file")
|
||||
logger.error("Failed to save unscoped flood policy to file")
|
||||
return self._error("Failed to save configuration to file")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save global flood policy to file: {e}")
|
||||
logger.error(f"Failed to save unscoped flood policy to file: {e}")
|
||||
return self._error(f"Failed to save configuration to file: {e}")
|
||||
|
||||
return self._success(
|
||||
{"global_flood_allow": global_flood_allow},
|
||||
message=f"Global flood policy updated to {'allow' if global_flood_allow else 'deny'} (live and saved)",
|
||||
{"unscoped_flood_allow": unscoped_flood_allow},
|
||||
message=f"Unscoped flood policy updated to {'allow' if unscoped_flood_allow else 'deny'} (live and saved)",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating global flood policy: {e}")
|
||||
logger.error(f"Error updating unscoped flood policy: {e}")
|
||||
return self._error(e)
|
||||
else:
|
||||
return self._error("Method not supported")
|
||||
|
||||
Reference in New Issue
Block a user