#!/bin/bash

if [ -z "${__net_sh_functions-}" ]; then
__net_sh_functions=1

net_confdir=/etc/network
net_autoconfdir=/.initrd/network/auto
net_statedir=/.initrd/network/state
net_event_list='link addr route hostname resolvconf'

. shell-error

ip_cmd()
{
	local v="-${ip_version:-4}"
	message "run: ip $v $*"
	ip $v "$@"
}

. uevent-sh-functions

net_event()
{
	local event
	event="$(make_event network)"
	printf '%s\n' "NET_IF=$2" > "$event"
	release_event "$1" "$event"
}

cat_config()
{
	local fn eof='' s=''
	fn="$1"; shift
	[ -f "$fn" ] ||
		return 0
	while [ -z "$eof" ]; do
		s=
		read -r s || eof=1
		[ -n "$s" ] && [ -n "${s##\#*}" ] || continue
		"$@" $s
	done < "$fn"
}

tac_config()
{
	local fn eof='' i=0 s=''
	fn="$1"; shift
	[ -f "$fn" ] ||
		return 0
	while [ -z "$eof" ]; do
		s=
		read -r s || eof=1
		[ -n "$s" ] && [ -n "${s##\#*}" ] || continue
		eval "local _tac_$i; _tac_$i=\"\$s\""
		i=$(($i+1))
	done < "$fn"

	i=$(($i-1))

	while [ $i -ge 0 ]; do
		eval "s=\"\$_tac_$i\""
		"$@" $s
		i=$(($i-1))
	done
}

iface_state_changed()
{
	set -- "$confdir/$2" "$net_statedir/ifaces/$1/$2"
	[ ! -e "$1" ] || [ ! -e "$2" ] || ! cmp -s "$1" "$2"
}

add_iface_state()
{
	[ -e "$confdir/$2" ] ||
		return 0
	mkdir -p -- "$net_statedir/ifaces/$1"
	cp -f -- "$confdir/$2" "$net_statedir/ifaces/$1/"
}

del_iface_state()
{
	[ ! -e "$net_statedir/ifaces/$1/$2" ] ||
		rm -f -- "$net_statedir/ifaces/$1/$2"
}

get_iface_confdir()
{
	local d
	[ -z "${NET_IF-}" ] ||
		for d in "$net_autoconfdir" "$net_confdir"; do
			confdir="$d/ifaces/$NET_IF"
			[ ! -d "$confdir" ] ||
				return 0
		done
	confdir="$net_confdir/default"
	[ -d "$confdir" ] ||
		return 1
}

ipv4_enabled()
{
	[ -d /proc/sys/net/ipv4 ] ||
		return 1
}

ipv6_enabled()
{
	[ -d /proc/sys/net/ipv6 ] ||
		return 1

	local n f v=0

	if [ -n "${NET_IF-}" ]; then
		f="/proc/sys/net/ipv6/conf/$NET_IF/disable_ipv6"
		[ ! -f "$f" ] ||
			read -r v < "$f"
		[ "$v" = 0 ] ||
			return 1
	fi

	for n in disable disable_ipv6; do
		f="/sys/module/ipv6/parameters/$n"
		[ ! -f "$f" ] ||
			read -r v < "$f"
		[ "$v" = 0 ] ||
			return 1
	done
}

load_ipv6()
{
	! ipv6_enabled ||
		return 0
	modprobe ipv6
	local i=10
	while [ ! -d /proc/sys/net/ipv6 ] && [ $i -ge 0 ]; do
		sleep 0.1
		i=$(($i-1))
	done
}

IFF_UP=$((1<<0))
IFF_BROADCAST=$((1<<1))
IFF_DEBUG=$((1<<2))
IFF_LOOPBACK=$((1<<3))
IFF_POINTOPOINT=$((1<<4))
IFF_NOTRAILERS=$((1<<5))
IFF_RUNNING=$((1<<6))
IFF_NOARP=$((1<<7))
IFF_PROMISC=$((1<<8))
IFF_ALLMULTI=$((1<<9))
IFF_MASTER=$((1<<10))
IFF_SLAVE=$((1<<11))
IFF_MULTICAST=$((1<<12))
IFF_PORTSEL=$((1<<13))
IFF_AUTOMEDIA=$((1<<14))
IFF_DYNAMIC=$((1<<15))

is_set()
{
	[ $(($1 & $2)) -eq $(($2)) ] ||
		return 1
}

is_loopback()
{
	local state=0
	{ read -r state < "/sys/class/net/$1/flags" ||:; } >/dev/null 2>&1

	is_set "$state" "$IFF_LOOPBACK"
}

is_link_up()
{
	local state=0
	{ read -r state < "/sys/class/net/$1/flags" ||:; } >/dev/null 2>&1

	is_set "$state" "$IFF_UP"
}

wait_for_link_up()
{
	local i=30
	while [ $i -ge 0 ]; do
		! is_link_up "$1" || return 0
		i=$(($i-1))
		sleep 0.1
	done
	return 1
}

fi
