From 5e7a131b646c9a0d82dad97960a803ce6e4ad3e6 Mon Sep 17 00:00:00 2001 From: Husaam Mehdi Date: Wed, 19 Nov 2025 07:10:59 +0000 Subject: [PATCH] parentalcontrol: remove dhcp.leases usages & add HostRef dm --- parental-control/Makefile | 4 +- .../lib/parentalcontrol/parentalcontrol.sh | 142 +++++++++--------- 2 files changed, 75 insertions(+), 71 deletions(-) diff --git a/parental-control/Makefile b/parental-control/Makefile index 06766b93a..1065dc8f6 100644 --- a/parental-control/Makefile +++ b/parental-control/Makefile @@ -5,13 +5,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=parental-control -PKG_VERSION:=1.4.3 +PKG_VERSION:=1.4.4 LOCAL_DEV:=0 ifneq ($(LOCAL_DEV),1) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://dev.iopsys.eu/network/parental-control.git -PKG_SOURCE_VERSION:=f7ec652c763bf6ffd550bf7d51b2c125774b79af +PKG_SOURCE_VERSION:=d0eabdda9790d1df3cec30589c97214731108367 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz PKG_MIRROR_HASH:=skip endif diff --git a/parental-control/files/lib/parentalcontrol/parentalcontrol.sh b/parental-control/files/lib/parentalcontrol/parentalcontrol.sh index ef0db1def..0225976b7 100644 --- a/parental-control/files/lib/parentalcontrol/parentalcontrol.sh +++ b/parental-control/files/lib/parentalcontrol/parentalcontrol.sh @@ -311,31 +311,6 @@ handle_schedule() { generate_ip_rule "$utc_start_relative_day" "$utc_end_relative_day" "$utc_start_time" "$utc_stop_time" "$target" } -# Function that parses input for MAC addresses or hostnames -parse_macs_or_hostnames() { - local input="$1" - local lease_file="/tmp/dhcp.leases" - - [ -f "$lease_file" ] || lease_file="/etc/parentalcontrol/dhcp.leases" - [ -f "$lease_file" ] || { log "Error: No DHCP lease file found."; return 1; } - - for item in $input; do - case "$item" in - ??:??:??:??:??:??) - # It's a MAC address, print it as is - echo "$item" - ;; - *) - # Assume it's a hostname and search for its MAC address in the leases file - mac=$(awk -v hostname="$item" '$4 == hostname {print $2}' "$lease_file") - if [ -n "$mac" ]; then - echo "$mac" - fi - ;; - esac - done -} - handle_bedtime() { local mac_addresses="$1" local mac @@ -370,38 +345,61 @@ handle_internet_break() { done } +parse_macs() { + local maclist="$1" + local m mac + + for m in $maclist; do + # trim whitespace + mac="$(echo "$m" | tr -d ' \t\r\n')" + + # validate format + if echo "$mac" | grep -qE '^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$'; then + echo "$mac" + else + log "parse_macs(): Invalid MAC in mac list: '$mac'" + fi + done +} + handle_profile() { local profile_section="$1" - local internet_break_enable bedtime_enable hostlist + local internet_break_enable bedtime_enable hostlist maclist - config_get hostlist "$profile_section" "host" + config_get_bool internet_break_enable "$profile_section" "internet_break_enable" 0 + config_get_bool bedtime_enable "$profile_section" "bedtime_enable" 0 - if [ -z "$hostlist" ]; then + if [ $internet_break_enable -eq 0 ] && [ $bedtime_enable -eq 0 ]; then return fi - ACCESS_RULE="" + config_get hostlist "$profile_section" "host" + config_get maclist "$profile_section" "mac" - # convert hostnames to mac addresses if needed - # and replace newlines with space because it messes up the for loops in - # handle_internet_break and handle_bedtime functions - local mac_addresses="$(parse_macs_or_hostnames "${hostlist}" | tr '\n' ' ')" + # If both lists are empty, nothing to do + if [ -z "$hostlist" ] && [ -z "$maclist" ]; then + return + fi - # default value of Hosts.AccessControl.{i}.Enable is false, - # so, if not defined in uci as 1, assume 0 - config_get_bool internet_break_enable "$profile_section" "internet_break_enable" 0 - if [ $internet_break_enable -gt 0 ]; then - handle_internet_break "${mac_addresses}" - # handle_internet_break may have loaded schedules uci - # so, reload parentalcontrol - config_load "parentalcontrol" - fi + ACCESS_RULE="" - config_get_bool bedtime_enable "$profile_section" "bedtime_enable" 0 - if [ $bedtime_enable -gt 0 ]; then - handle_bedtime "${mac_addresses}" - fi + # both uci options contain mac addresses + # one is given directly by the user + # other is resolved by the data model from Hosts.Host object + local mac_addresses="$(parse_macs "${hostlist} ${maclist}" | awk '{ if (NF && !seen[$0]++) { print $0 } }' | tr '\n' ' ')" + # default value of Hosts.AccessControl.{i}.Enable is false, + # so, if not defined in uci as 1, assume 0 + if [ $internet_break_enable -gt 0 ]; then + handle_internet_break "${mac_addresses}" + # handle_internet_break may have loaded schedules uci + # so, reload parentalcontrol + config_load "parentalcontrol" + fi + + if [ $bedtime_enable -gt 0 ]; then + handle_bedtime "${mac_addresses}" + fi } add_internet_schedule_rules() { @@ -567,38 +565,44 @@ remove_internet_schedule_rules() { fi } +get_host_ip_from_mac() { + local mac="$1" + local ip="" + + # Validate MAC format + if ! echo "$mac" | grep -qE '^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$'; then + log "get_host_ip_from_mac(): Invalid MAC address format '$mac'" + return 1 + fi + + # Try to find IP from ARP table + ip="$(cat /proc/net/arp | awk -v mac="$mac" 'tolower($4) == tolower(mac) {print $1; exit}')" + + if [ -n "$ip" ]; then + URLFILTER_IPS="${URLFILTER_IPS} ${ip}" + return 0 + else + log "get_host_ip_from_mac(): No IP found for MAC $mac in ARP table" + return 1 + fi +} + # Global array for resolved IPs URLFILTER_IPS="" -# Resolve hostname or MAC to IP from lease_file -get_host_ip() { - local host="$1" - local ip - local lease_file="/tmp/dhcp.leases" - - [ -f "$lease_file" ] || lease_file="/etc/parentalcontrol/dhcp.leases" - [ -f "$lease_file" ] || { log "Error: get_host_ip(): No DHCP lease file found."; return 1; } - - # try DHCP lease lookup - ip="$(awk -v h="$host" ' - { - mac=$2; ipaddr=$3; name=$4 - if (h == name || h == mac) { print ipaddr; exit } - }' "$lease_file")" - - [ -n "$ip" ] && URLFILTER_IPS="$URLFILTER_IPS $ip" -} - -# Process each profile section resolve_profile_hosts() { local section="$1" - local hostlist + local hostlist maclist h m config_get hostlist "$section" host - [ -z "$hostlist" ] && return + config_get maclist "$section" mac for h in $hostlist; do - get_host_ip "$h" + get_host_ip_from_mac "$h" + done + + for m in $maclist; do + get_host_ip_from_mac "$m" done }