#!/bin/sh . /lib/functions.sh day="" next_days="" prev_days="" schedule_added="" ACCESS_RULE="" IP_RULE="" IP_RULE1="" get_next_day() { local weekday="$1" case "$weekday" in "Mon"|"Monday") echo "Tuesday" ;; "Tue"|"Tuesday") echo "Wednesday" ;; "Wed"|"Wednesday") echo "Thursday" ;; "Thu"|"Thursday") echo "Friday" ;; "Fri"|"Friday") echo "Saturday" ;; "Sat"|"Saturday") echo "Sunday" ;; "Sun"|"Sunday") echo "Monday" ;; esac } get_previous_day() { local weekday="$1" case "$weekday" in "Mon"|"Monday") echo "Sunday" ;; "Tue"|"Tuesday") echo "Monday" ;; "Wed"|"Wednesday") echo "Tuesday" ;; "Thu"|"Thursday") echo "Wednesday" ;; "Fri"|"Friday") echo "Thursday" ;; "Sat"|"Saturday") echo "Friday" ;; "Sun"|"Sunday") echo "Saturday" ;; esac } ip_rule_west_zone() { local utc_start_t_h="$1" local utc_stop_t_h="$2" local local_start_t_h="$3" local local_stop_t_h="$4" local utc_start_time="$5" local utc_stop_time="$6" if [ "$utc_start_t_h" -lt "$local_start_t_h" ]; then IP_RULE="$IP_RULE -m time --timestart $utc_start_time --timestop $utc_stop_time" if [ -n "$next_days" ]; then IP_RULE="$IP_RULE --weekdays $next_days" fi else if [ "$utc_stop_t_h" -lt "$local_stop_t_h" ]; then IP_RULE1="$IP_RULE" IP_RULE="$IP_RULE -m time --timestart $utc_start_time --timestop 23:59" IP_RULE1="$IP_RULE1 -m time --timestart 00:00 --timestop $utc_stop_time" if [ -n "$next_days" ]; then IP_RULE1="$IP_RULE1 --weekdays $next_days" fi else IP_RULE="$IP_RULE -m time --timestart $utc_start_time --timestop $utc_stop_time" fi if [ -n "$day" ]; then IP_RULE="$IP_RULE --weekdays $day" fi fi } ip_rule_east_zone() { local utc_start_t_h="$1" local utc_stop_t_h="$2" local local_start_t_h="$3" local local_stop_t_h="$4" local utc_start_time="$5" local utc_stop_time="$6" if [ "$utc_start_t_h" -lt "$local_start_t_h" ]; then IP_RULE="$IP_RULE -m time --timestart $utc_start_time --timestop $utc_stop_time" if [ -n "$day" ]; then IP_RULE="$IP_RULE --weekdays $day" fi else if [ "$utc_stop_t_h" -lt "$local_stop_t_h" ]; then IP_RULE1="$IP_RULE" IP_RULE="$IP_RULE -m time --timestart 00:00 --timestop $utc_stop_time" IP_RULE1="$IP_RULE1 -m time --timestart $utc_start_time --timestop 23:59" if [ -n "$prev_days" ]; then IP_RULE1="$IP_RULE1 --weekdays $prev_days" fi else IP_RULE="$IP_RULE -m time --timestart $utc_start_time --timestop $utc_stop_time" fi if [ -n "$day" ]; then IP_RULE="$IP_RULE --weekdays $day" fi fi } add_access_rule() { local rule="$1" echo "iptables -w -A hosts_forward ${rule}" >> "$ACL_FILE" echo "ip6tables -w -A hosts_forward ${rule}" >> "$ACL_FILE" } handle_day_list() { local value=$1 val=$(echo "$value" | cut -c 1-3) next_day_val=$(get_next_day "$val") prev_day_val=$(get_previous_day "$val") if [ -z $day ]; then day="$val" next_days="$next_day_val" prev_days="$prev_day_val" else day="$day,$val" next_days="$next_days,$next_day_val" prev_days="$prev_days,$prev_day_val" fi } handle_schedule() { local schd_section="$1" local start_time local duration IP_RULE="$ACCESS_RULE" IP_RULE1="" day="" next_days="" prev_days="" config_load schedules local is_enabled config_get is_enabled "$schd_section" "enable" 0 if [ "$is_enabled" == "0" ]; then return fi local all_days="Monday Tuesday Wednesday Thursday Friday Saturday Sunday" local day_config config_get day_config "$schd_section" "day" "$all_days" IFS=" " for d in $day_config; do handle_day_list "$d" done config_get start_time "$schd_section" "start_time" "00:00" config_get duration "$schd_section" "duration" zone=$(date +%z | cut -c 1) local_start_time=$start_time hh=$(echo "$local_start_time" | awk -F: '{ print $1 }') mm=$(echo "$local_start_time" | awk -F: '{ print $2 }') hh_s=`expr $hh \* 3600` mm_s=`expr $mm \* 60` ss=$(( hh_s + mm_s )) local_start_hh=$hh if [ -n "$duration" ]; then stop_ss=$(( ss + duration )) hh=$(( stop_ss / 3600 )) rem_ss=$(( stop_ss % 3600 )) mm=$(( rem_ss / 60 )) ss=$(( rem_ss % 60 )) local_stop_time="$hh:$mm:$ss" local_stop_hh=$hh else # if duartion is not specified, then apply rule to end of the day local_stop_time="23:59:59" local_stop_hh="23" fi utc_start_time=$(date -u -d @$(date "+%s" -d "$local_start_time") +%H:%M) utc_stop_time=$(date -u -d @$(date "+%s" -d "$local_stop_time") +%H:%M) utc_start_hh=$(echo "$utc_start_time" | awk -F: '{ print $1 }') utc_stop_hh=$(echo "$utc_stop_time" | awk -F: '{ print $1 }') if [ "$zone" == "-" ]; then ip_rule_west_zone "$utc_start_hh" "$utc_stop_hh" "$local_start_hh" "$local_stop_hh" "$utc_start_time" "$utc_stop_time" else ip_rule_east_zone "$utc_start_hh" "$utc_stop_hh" "$local_start_hh" "$local_stop_hh" "$utc_start_time" "$utc_stop_time" fi IP_RULE="$IP_RULE -j ACCEPT" if [ -n "$IP_RULE1" ]; then IP_RULE1="$IP_RULE1 -j ACCEPT" fi add_access_rule "$IP_RULE" if [ -n "$IP_RULE1" ]; then add_access_rule "$IP_RULE1" fi # for access rules to be effective for a schedule, need to add DROP rule # to block the access outside the defined schedule if [ "$schedule_added" == "0" ]; then schedule_added="1" fi } handle_access_control() { local ac_section="$1" local is_enabled # default value of Hosts.AccessControl.{i}.Enable is false, # so, if not defined in uci as 1, assume 0 config_get is_enabled "$ac_section" "enable" 0 if [ "$is_enabled" == "0" ]; then return fi local mac_addr config_get mac_addr "$ac_section" "macaddr" if [ -z "$mac_addr" ]; then return else ACCESS_RULE="-m mac --mac-source $mac_addr" fi local access_policy config_get access_policy "$ac_section" "access_policy" if [ -z "$access_policy" ]; then return # since system default is allow so no need to do anything fi # As per Data Model, if access policy is deny, then schedule is to be ignored # and no access is to be provided for the device if [ "$access_policy" == "Deny" ]; then ACCESS_RULE="$ACCESS_RULE -j DROP" add_access_rule "$ACCESS_RULE" return # no need to parse schedule fi schedule_added="0" # check if schedule is defined for this access_control instance # and if yes, create rule accordingly config_list_foreach "$ac_section" access_control_schedule handle_schedule # for access rule to work, need to have default drop rule as last rule if [ "$schedule_added" == "1" ]; then IP_RULE="$ACCESS_RULE -j DROP" add_access_rule "$IP_RULE" fi } ACL_FILE="/tmp/hosts_access_control/access_control.rules" rm -f $ACL_FILE mkdir -p /tmp/hosts_access_control/ touch $ACL_FILE echo "iptables -w -F hosts_forward" >> $ACL_FILE echo "ip6tables -w -F hosts_forward" >> $ACL_FILE hosts_ipv4_forward=$(iptables -w -t filter --list -n | grep hosts_forward) if [ -z "$hosts_ipv4_forward" ]; then echo "iptables -w -t filter -N hosts_forward" >> $ACL_FILE ret=$? [ $ret -eq 0 ] && echo "iptables -w -t filter -I FORWARD -j hosts_forward" >> $ACL_FILE fi hosts_ipv6_forward=$(ip6tables -w -t filter --list -n | grep hosts_forward) if [ -z "$hosts_ipv6_forward" ]; then echo "ip6tables -w -t filter -N hosts_forward" >> $ACL_FILE ret=$? [ $ret -eq 0 ] && echo "ip6tables -w -t filter -I FORWARD -j hosts_forward" >> $ACL_FILE fi # Load /etc/config/hosts UCI file config_load hosts config_foreach handle_access_control access_control # apply the rules sh $ACL_FILE