You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
7.2 KiB
Bash
283 lines
7.2 KiB
Bash
#!/bin/sh
|
|
|
|
. /lib/functions.sh
|
|
|
|
SCRIPT=$0
|
|
# the lock is meant for ebtables, and other scripts are also
|
|
# using ebtables. Needs clean up, maybe move to functions.sh, TBD?
|
|
LOCKFILE=/tmp/ebtables.lock
|
|
LOGFILE=/tmp/log/parental_control.log
|
|
PACKAGE=parental_control
|
|
# variable to remember if parental control is enabled
|
|
parental_control_enabled=0
|
|
|
|
# uncomment the next line if matching rules should be logged to syslog
|
|
# (for debugging), needs watchers extension
|
|
#local EBLOG=--log
|
|
|
|
_log()
|
|
{
|
|
if [ ${LOGGING} -eq 1 ]; then
|
|
local ts=$(date)
|
|
echo "$ts $@" >> ${LOGFILE}
|
|
fi
|
|
}
|
|
|
|
_exit()
|
|
{
|
|
local rc=$1
|
|
lock -u ${LOCKFILE}
|
|
exit ${rc}
|
|
}
|
|
|
|
_cron_restart()
|
|
{
|
|
/etc/init.d/cron restart > /dev/null
|
|
}
|
|
|
|
_add_cron_script()
|
|
{
|
|
(crontab -l ; echo "$1") | sort -u | crontab -
|
|
}
|
|
|
|
_rm_cron_script()
|
|
{
|
|
crontab -l | grep -v "$1" | sort -u | crontab -
|
|
}
|
|
|
|
_rm_and_add_cron_script()
|
|
{
|
|
(crontab -l | grep -v "$1"; [ -n "$2" ] && echo "$2") | sort -u | crontab -
|
|
}
|
|
|
|
_format_dow_list()
|
|
{
|
|
local dow=$1
|
|
local flist=""
|
|
local day
|
|
for day in ${dow}
|
|
do
|
|
if [ ! -z ${flist} ]; then
|
|
flist="${flist},"
|
|
fi
|
|
flist="${flist}${day:0:3}"
|
|
done
|
|
echo ${flist}
|
|
}
|
|
|
|
_shift_dow_list_by_one_day()
|
|
{
|
|
local dow=$1
|
|
local flist=""
|
|
local day
|
|
for day in $1
|
|
do
|
|
if [ ! -z ${flist} ]; then
|
|
flist="${flist},"
|
|
fi
|
|
case $day in
|
|
Mon*)
|
|
flist="${flist}Tue"
|
|
;;
|
|
Tue*)
|
|
flist="${flist}Wed"
|
|
;;
|
|
Wed*)
|
|
flist="${flist}Thu"
|
|
;;
|
|
Thu*)
|
|
flist="${flist}Fri"
|
|
;;
|
|
Fri*)
|
|
flist="${flist}Sat"
|
|
;;
|
|
Sat*)
|
|
flist="${flist}Sun"
|
|
;;
|
|
Sun*)
|
|
flist="${flist}Mon"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
echo "$flist"
|
|
}
|
|
|
|
_enable_parental_control()
|
|
{
|
|
local entry=$1
|
|
local enabled starttime stoptime dow
|
|
|
|
config_get enabled $entry enabled 0
|
|
[ "$enabled" -eq 0 ] && return 0
|
|
config_get starttime $entry starttime
|
|
[ -z "$starttime" ] && return 1
|
|
config_get stoptime $entry stoptime
|
|
[ -z "$stoptime" ] && return 1
|
|
config_get dow $entry daysofweek
|
|
[ -z "$dow" ] && return 1
|
|
|
|
local fdow=$(_format_dow_list "$dow")
|
|
|
|
# If it shall stop on the same day at 00:00, 24:00 is the transition to the following day, if this is the case,
|
|
# the days of the weeks have to be incremented by one
|
|
if [ "${stoptime}" == "24:00" ]; then
|
|
fdow_stop=$(_shift_dow_list_by_one_day "$dow")
|
|
stoptime="0:00"
|
|
else
|
|
fdow_stop=${fdow}
|
|
fi
|
|
|
|
local stop_cron_entry="$(echo ${stoptime} | awk -F':' '{print $2, $1}') * * ${fdow_stop} ${SCRIPT} check" # ${entry}"
|
|
echo "${stop_cron_entry}"
|
|
|
|
if [[ $starttime != $stoptime ]]
|
|
then
|
|
local start_cron_entry="$(echo ${starttime} | awk -F':' '{print $2, $1}') * * ${fdow} ${SCRIPT} check" # ${entry}"
|
|
echo "${start_cron_entry}"
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
_create_cron_entries()
|
|
{
|
|
config_foreach _enable_parental_control entry
|
|
}
|
|
|
|
replace_rules() {
|
|
local mac macs="$1"
|
|
ebtables -F i-parental-control
|
|
ebtables -F o-parental-control
|
|
for mac in $macs; do
|
|
ebtables -A i-parental-control -s $mac -j DROP $EBLOG
|
|
ebtables -A o-parental-control -d $mac -j DROP $EBLOG
|
|
done
|
|
}
|
|
|
|
create_chains() {
|
|
ebtables -N i-parental-control -P RETURN 2>/dev/null || return 0
|
|
ebtables -N o-parental-control -P RETURN 2>/dev/null || return 0
|
|
ebtables -A INPUT -i ath+ -j i-parental-control $EBLOG
|
|
ebtables -A FORWARD -i ath+ -j i-parental-control $EBLOG
|
|
ebtables -A FORWARD -o ath+ -j o-parental-control $EBLOG
|
|
ebtables -A OUTPUT -o ath+ -j o-parental-control $EBLOG
|
|
}
|
|
|
|
delete_chains() {
|
|
ebtables -D INPUT -i ath+ -j i-parental-control $EBLOG 2>/dev/null
|
|
ebtables -D FORWARD -i ath+ -j i-parental-control $EBLOG 2>/dev/null
|
|
ebtables -D FORWARD -o ath+ -j o-parental-control $EBLOG 2>/dev/null
|
|
ebtables -D OUTPUT -o ath+ -j o-parental-control $EBLOG 2>/dev/null
|
|
ebtables -X i-parental-control 2>/dev/null
|
|
ebtables -X o-parental-control 2>/dev/null
|
|
}
|
|
|
|
check_cron_status()
|
|
{
|
|
if [ ${parental_control_enabled} -eq 1 ]; then
|
|
_rm_and_add_cron_script "${SCRIPT}" "$(_create_cron_entries)"
|
|
else
|
|
_rm_cron_script "${SCRIPT}"
|
|
fi
|
|
_cron_restart
|
|
}
|
|
|
|
handle_global() {
|
|
local cfg="$1"
|
|
config_get_bool parental_control_enabled "$cfg" enabled 0
|
|
config_get_bool LOGGING "$cfg" logging 0
|
|
}
|
|
|
|
handle_entry() {
|
|
local cfg="$1"; shift
|
|
local curTime="$1"; shift
|
|
local weekday="$1"; shift
|
|
local blocked_var="$1"; shift
|
|
local allowed_var="$1"; shift
|
|
local list_var
|
|
local entry_enabled starttime stoptime stations dow
|
|
|
|
config_get_bool entry_enabled "$cfg" enabled 0
|
|
# Check if current entry is enabled
|
|
[ "$entry_enabled" -eq 0 ] && return 0
|
|
|
|
# lowercase:
|
|
stations="$(config_get "$cfg" stations | tr ABCDEF abcdef)"
|
|
config_get dow "$cfg" daysofweek
|
|
[ -z "$dow" ] && return 1
|
|
config_get starttime "$cfg" starttime
|
|
[ -z "$starttime" ] && return 1
|
|
config_get stoptime "$cfg" stoptime
|
|
[ -z "$stoptime" ] && return 1
|
|
|
|
# Check if current entry is relevant for today
|
|
echo "$dow" | grep "$weekday" > /dev/null || return 0
|
|
|
|
#remove :, so that we can make easy integer comparison
|
|
starttime=${starttime//:}
|
|
stoptime=${stoptime//:}
|
|
|
|
if [ $curTime -ge $starttime ] && [ $curTime -lt $stoptime ]; then
|
|
list_var=$allowed_var
|
|
else
|
|
list_var=$blocked_var
|
|
fi
|
|
|
|
# add or delete rules to the list of stations
|
|
local st
|
|
for st in $stations; do
|
|
! list_contains $list_var $st && append $list_var $st
|
|
done
|
|
}
|
|
|
|
# evaluate if a MAC address is allowed at the current time of day
|
|
check_and_apply_parental_control_state() {
|
|
local curTime=$(date "+%k%M")
|
|
local weekday=$(date "+%A")
|
|
|
|
if [ "$parental_control_enabled" -eq 0 ]; then
|
|
delete_chains
|
|
else
|
|
local blocked_macs allowed_macs st stations
|
|
create_chains
|
|
# collect which MACs are allowed or blocked by a config entry in separate lists
|
|
config_foreach handle_entry entry "$curTime" "$weekday" blocked_macs allowed_macs
|
|
# allowed wins
|
|
for st in $blocked_macs; do
|
|
! list_contains allowed_macs $st && append stations $st
|
|
done
|
|
replace_rules "$stations"
|
|
fi
|
|
}
|
|
|
|
usage()
|
|
{
|
|
echo ""
|
|
echo "$0 cron|check|help"
|
|
echo ""
|
|
echo " UCI Config File: /etc/config/${PACKAGE}"
|
|
echo ""
|
|
echo " cron: Create cronjob entries."
|
|
echo " check: Check if stations should get access to the network or should be blocked"
|
|
echo " help: This description."
|
|
echo ""
|
|
}
|
|
|
|
###############################################################################
|
|
# MAIN
|
|
###############################################################################
|
|
config_load "${PACKAGE}"
|
|
config_foreach handle_global global
|
|
|
|
_log ${SCRIPT} $1 $2
|
|
lock ${LOCKFILE}
|
|
|
|
case "$1" in
|
|
cron) check_cron_status ;;
|
|
check) check_and_apply_parental_control_state;;
|
|
help|--help|-h|*) usage ;;
|
|
esac
|
|
|
|
_exit 0
|