#!/bin/sh
###############################################################################
#                                                                             #
# IPFire.org - A linux based firewall                                         #
# Copyright (C) 2007-2022  IPFire Team  <info@ipfire.org>                     #
#                                                                             #
# 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/>.       #
#                                                                             #
###############################################################################

. /etc/sysconfig/rc
. $rc_functions

eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
eval $(/usr/local/bin/readhash /var/ipfire/dns/settings)

dhcpcd_get_pid() {
		# This function returns the pid of a dhcpcd by a given
		# network device, if a pidfile exists.

		local device="$1"
		local pidfile="/var/run/dhcpcd/${device}.pid"

		# Check if a pid file exists.
		if [ -f "${pidfile}" ] ; then

			# Get the pid from the file.
			local pid="$(<"${pidfile}")"

			echo "${pid}"
		fi
}

dhcpcd_is_running() {
	# This functions checks if a dhcpcd is running by a given pid.

	local pid="$1"

	# Check if a dhcpcd is running.
	if [ -n "${pid}" -a -d "/proc/${pid}" ]; then
		# Return "0" (True) if a dhcpcd is running.
		return 0
	fi

	# Return 1 (False) no dhcpcd is running.
	return 1
}

dhcpcd_start() {
	# This function will start a dhcpcd on a speciefied device.
	local device="$1"
	shift

	local dhcp_start=()

	boot_mesg -n "Starting dhcpcd on the ${device} interface..."

	# Check if a dhcpcd is already running.
	local pid="$(dhcpcd_get_pid "${device}")"

	if  dhcpcd_is_running "${pid}"; then
		boot_mesg "dhcpcd already running!" ${WARNING}
		echo_warning
		exit 2
	fi

	# Check if a DHCP hostname has been set.
	if [ -n "${RED_DHCP_HOSTNAME}" ]; then
		dhcp_start+=( "-h" "${RED_DHCP_HOSTNAME}" )
	fi

	# Tell dhcpcd to use the configured MTU
	if [ -n "${RED_DHCP_FORCE_MTU}" ]; then
		dhcp_start+=( "--static" "mtu=${RED_DHCP_FORCE_MTU}" )
	fi

	# Append any further command line options
	dhcp_start+=( $@ )

	# Start dhcpcd.
	/sbin/dhcpcd "${dhcp_start[@]}" ${device} >/dev/null 2>&1
	ret="$?"

	if [ "${ret}" -eq 0 ]; then
		. /var/ipfire/dhcpc/dhcpcd-"${device}".info

			if [ $ip_address ]; then
			echo ""
			echo_ok
			boot_mesg "           DHCP Assigned Settings for ${device}:"
			boot_mesg_flush
			boot_mesg "           IP Address:      $ip_address"
			boot_mesg_flush

			if [ -n "${RED_DHCP_HOSTNAME}" ]; then
				boot_mesg "           Hostname:        $RED_DHCP_HOSTNAME"
				boot_mesg_flush
			fi

			boot_mesg "           Subnet Mask:     $subnet_mask"
			boot_mesg_flush
			boot_mesg "           Default Gateway: $routers"
			boot_mesg_flush
			boot_mesg "           DNS Server:      $domain_name_servers"
			boot_mesg_flush
		else
			echo ""
			echo_ok
			boot_mesg "DHCP for ${device} still running..."
			boot_mesg_flush
		fi
	else
		echo ""
		$(exit "${ret}")
 		evaluate_retval
	fi
}

dhcpcd_stop() {
	# This function stops a previously started dhcpcd on a given device.

	local device="$1"
	local dhcp_stop="-k"
	local leaseinfo="/var/ipfire/dhcpc/dhcpcd-${device}.info"

	boot_mesg -n "Stopping dhcpcd on the ${device} interface..."

	# Check if a dhcpcd is running.
	local pid="$(dhcpcd_get_pid "${device}")"

	if ! dhcpcd_is_running "${pid}"; then
		boot_mesg "    Not running." ${WARNING}
		echo_warning
		exit 1
	fi

	# Stop dhcpcd.
	/sbin/dhcpcd ${dhcp_stop} ${device} &> /dev/null
	ret="$?"

	# Wait until dhcpd has stopped.
	while [ -d "/proc/${pid}" ]; do
		sleep 1
		# repeat stop if dhcp was still running
		/sbin/dhcpcd ${dhcp_stop} ${device} &> /dev/null
	done

	# Display console message, depended on the exit code
	# of the stopped dhcpcd.
	if [ "${ret}" -eq 0 ]; then
		boot_mesg
		echo_ok
	elif [ "${ret}" -eq 1 ]; then
		boot_mesg "failed to stop dhcpcd!" ${WARNING}
		echo_warning
	else
		boot_mesg
		echo_failure
	fi
}

# QMI stuff

qmi_find_device() {
	local intf="${1}"
	local _intf

	local path
	for path in /dev/cdc-*; do
		if [ -c "${path}" ]; then
			_intf="$(qmi_find_interface "${path}")"

			# Check if the interface matches
			if [ "${intf}" = "${_intf}" ]; then
				echo "${path}"
				return 0
			fi
		fi
	done

	# Nothing found
	return 1
}

qmi_find_interface() {
	local device="${1}"

	qmicli --device="${device}" --device-open-proxy --get-wwan-iface
}

qmi_enable_rawip_mode() {
	local intf="${1}"

	# Shut down the device first
	ip link set "${intf}" down &>/dev/null

	echo "Y" > "/sys/class/net/${intf}/qmi/raw_ip"
}

qmi_configure_apn() {
	local device="${1}"

	# APN settings
	local apn="${2}"
	local auth="${3}"
	local username="${4}"
	local password="${5}"

	local args=(
		# We only support IPv4 right now
		"ip-type=4"
	)

	# Set APN
	if [ -n "${apn}" ]; then
		args+=( "apn=${apn}" )
	fi

	# Set auth
	case "${auth}" in
		PAP|CHAP)
			args+=( "auth=${auth}" )
			;;
	esac

	# Set username
	if [ -n "${username}" ]; then
		args+=( "username=${username}" )
	fi

	# Set password
	if [ -n "${password}" ]; then
		args+=( "password=${password}" )
	fi

	local _args

	local arg
	for arg in ${args[@]}; do
		if [ -n "${_args}" ]; then
			_args="${_args},"
		fi
		_args="${_args}${arg}"
	done

	qmicli --device="${device}" --device-open-proxy \
		--wds-start-network="${_args}" \
		--client-no-release-cid &>/dev/null
}

qmi_reset() {
	local device="${1}"

	qmicli --device="${device}" --device-open-proxy \
		--wds-reset &>/dev/null
}

# Assigns a "static" MAC address
qmi_assign_address() {
	local intf="${1}"

	# Find the device
	local device="$(qmi_find_device "${intf}")"

	# Switch off the raw_ip mode to be able to proper
	# assign the generated MAC address.
	echo "N" > "/sys/class/net/${intf}/qmi/raw_ip"

	local address

	# Generate a "random" MAC address using the device number
	printf -v address "02:ff:ff:ff:ff:%02x" "${device:12}"

	# Change the MAC address
	ip link set "${intf}" address "${address}"
}
