#!/bin/bash

###########################################################################
#
# MODULE:       InitScript
# COPYRIGHT:    (C) 2009-2025 by CacheGuard Technologies Ltd (UK)
# COPYRIGHT:    (C) 2026-2026 by CacheGuard Technologies SAS (FR)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###########################################################################

source /lib/lsb/init-functions

CACHEGUARD_DIR=/etc/sysconfig/cacheguard
source ${CACHEGUARD_DIR}/constant

TC_CONFIG=/etc/sysconfig/tc

test -x /sbin/tc || exit
test -L ${TC_CONFIG} || exit

DEBUG=no

TC_CMD=tc
IP_CMD=ip
SERV=QoS

cd /sys/class/net
IFBS=$(ls -d ifb* 2> /dev/null)

declare -A INTERFACE_EXISTS

RETVAL=0

get-service()
(
    test -n "${1}" || return 1
    local file=${1}

    source ${file}
    echo ${SERVICE}
)

init-interface-exists()
{
    local dev

    while read -r _ dev _
    do
	 dev=${dev%:}
	INTERFACE_EXISTS["${dev}"]=1
    done < <(ip -o link show 2> /dev/null)
}

interface-exist()
{
    test -n "${1}" || return 1
    local interface=${1}

    [[ ${INTERFACE_EXISTS[${interface}]+yes} ]]
}

link-ifb()
{
    local ifb

    case "${1}" in
	start)
	    for ifb in ${IFBS}
	    do
		${IP_CMD} link set up dev ${ifb} 2> /dev/null 1>&2
	    done
	    ;;
	stop)
	    for ifb in ${IFBS}
	    do
		${IP_CMD} link set down dev ${ifb} 2> /dev/null 1>&2
	    done
	    ;;
	*)
    esac
}

show-tc-status()
{
    local ret

    if test -z "${1}" ; then
	${TC_CMD} -s -d qdisc show
	ret=${?}
    else
	local dev=${1}
	if test -z "${2}" ; then
	    ${TC_CMD} -s -d qdisc show dev ${dev}
	    ret=${?}
	else
	    local in_handle=${2}
	    local dummy qdisc handle rest
	    local found=0
	    ${TC_CMD} -s -d qdisc show dev ${dev} | \
		while read dummy qdisc handle rest
		do
		    if test ${handle} == ${in_handle} ; then
			echo ${dummy} ${qdisc} ${handle} ${rest}
			found=1
		    elif test ${found} -eq 1 ; then
			echo ${dummy} ${qdisc} ${handle} ${rest}
			break
		    fi
		done
	    ret=${PIPESTATUS[0]}
	fi
    fi

    return ${ret}
}

start-tc()
{
    log_info_msg "Starting ${SERV}..."

    local modifier action keyword dev rest
    local line retval=0 i=0

    while read -r modifier action keyword dev rest
    do
	((i++))

	test -n "${modifier}" || continue
	test "${modifier:0:1}" != "#" || continue

	test "${keyword}" == dev || continue
	interface-exist ${dev} || continue

	line="${modifier} ${action} ${keyword} ${dev} ${rest}"

	if [ "${DEBUG}" == yes ] ; then
	    ${TC_CMD} ${line}
	else
	    ${TC_CMD} ${line} 2> /dev/null 1>&2
	fi

	if [ ${?} -ne 0 ] ; then
	    ((retval++))
	    [ "${DEBUG}" != yes ] || echo "*** Error on line ${i}: ${line}"
	fi
    done < ${TC_CONFIG}

    link-ifb start
    [ ${?} -eq 0 ] || ((retval++))

    [ "${DEBUG}" != yes -o ${retval} -eq 0 ] || echo "*** Number of errors ${retval}"
    [ ${retval} -eq 0 ]
    evaluate_retval
    return ${retval}
}

stop-tc()
{
    log_info_msg "Stopping ${SERV}... "

    local file interface retval
    local files=$(ls /etc/sysconfig/ifconfig.{eth,bond}* 2>/dev/null)

    for file in ${files}
    do
	interface=$(basename ${file})
	interface=${interface/ifconfig\./}
        test "${interface/\:*}" == "${interface}" || continue

	ls ${file}.* > /dev/null 2>&1
	test ${?} -ne 0 || continue
	SERVICE=$(get-service ${file})
	test "${SERVICE/* }" != 'ipv4-pppoe' || interface=${EXTERNAL_PPPOE_IF}

	interface-exist ${interface} || continue

	${TC_CMD} qdisc del dev ${interface} root > /dev/null 2>&1
	${TC_CMD} qdisc del dev ${interface} ingress > /dev/null 2>&1

    done

    for IFB in ${IFBS}
    do
	${TC_CMD} qdisc del dev ${IFB} root 2> /dev/null 1>&2
    done

    link-ifb stop
    retval=${?}

    rm -f ${RUN_DIR}/${QOS_DIFF_TRAFFIC_FILENAME} ${RUN_DIR}/${QOS_TRAFFIC_FILENAME}{,.old}
    [ ${retval} -eq 0 ]
    evaluate_retval
    return ${retval}
}

init-interface-exists

case "${1}" in
    start)
	start-tc
	;;
    stop)
	stop-tc
	;;
    restart)
	${0} stop
	${0} start
	;;
    status)
	shift
	show-tc-status "${@}"
	RETVAL=${?}
	exit ${RETVAL}
	;;
    *)
	echo "Usage: ${0} {start|stop|restart|status}"
	exit 1
	;;
esac
