#
# $Id: functions.network,v 1.66 2001/11/19 13:00:56 zagrodzki Exp $
# 
# This is not a shell script; it provides functions to network scripts
# that source it.

# This will work only after starting interface to which LDAP server is connected
find_ldap_interfaces()
{
typeset BSWITH QUERY
is_no "$USE_LDAP" && return 0

if [ -n "$LDAP_BASE_DN" ] ; then
	BSWITCH="-b$LDAP_BASE_DN" 
else
	BSWITH=""
fi

QUERY="(&(objectclass=pldinterface)(if_onboot=yes))"
ldapsearch "$BSWITCH" "$QUERY" if_device | \
	awk ' (/^if_device=/) { gsub(/^if_device=/,NIL); print $0; } '
}

# find aliases for device
find_ldap_aliases()
{
typeset BSWITH QUERY
is_no "$USE_LDAP" && return 0

if [ -n "$LDAP_BASE_DN" ] ; then
	BSWITCH="-b$LDAP_BASE_DN" 
else
	BSWITH=""
fi

QUERY="(&(objectclass=pldinterface)(if_onboot=yes)(if_device~=$1:*))"
ldapsearch "$BSWITCH" "$QUERY" if_device | \
	grep "^if_device=" | awk ' { gsub(/^if_device=/,NIL); print $0; } '
}

get_ldap_config ()
{
typeset BSWITH QUERY IPV6_ADDR IPADDR_ALIASES FIELD VALUE VAR
is_no "$USE_LDAP" && return 0

# Initialise fields which  can have multiple values:
IPV6_ADDR=""
IPADDR_ALIASES=""

QUERY="(&(objectclass=pldinterface)(if_device=$1))"
if [ -n "$LDAP_BASE_DN" ] ; then
	BSWITCH="-b$LDAP_BASE_DN" 
else
	BSWITH=""
fi

ldapsearch "$BSWITCH" "$QUERY" | awk ' (/=/) { gsub(/=/," "); print $0; } ' | {
	while read FIELD VALUE ; do
		# Field, which have name compatible with other 
		# LDAP object
		if [ "$FIELD" = "iphostnumber" ] ; then
			VAR="IPADDR";
		else # Other fields
			VAR=$(echo "$FIELD" | awk '(/^if_/) { data=toupper($0); gsub(/IF_/,NIL,data); print data; }')
		fi
		# Fields which can have multiple values:
		if   [ "$VAR" = "IPV6_ADDR" \
		    -o "$VAR" = "IPADDR_ALIASES" ]  && \
		     [ -n "`eval echo \$$VAR`" ] ; then
			echo "$VAR=\"\$$VAR $VALUE\"" ;

		# single value fields, or the first value
		elif [ -n "$VAR" ] ; then
			eval "$VAR=\"$VALUE\""
			echo "$VAR=\"$VALUE\""
		fi
	done
}
}

source_config ()
{
DEVNAME=$(basename "$CONFIG" | awk ' { gsub(/^ifcfg-/,NIL); print $0; } ')
        
if echo "$CONFIG"|egrep "^/" >/dev/null 2>&1 ; then
	if [ -f "$CONFIG" ] ; then
		. "$CONFIG"
	fi
elif [ -f "/etc/sysconfig/interfaces/$CONFIG" ] ; then
	. "/etc/sysconfig/interfaces/$CONFIG"
elif is_yes "$USE_LDAP"; then
	eval `get_ldap_config $DEVNAME`
fi
if [ -n "${PREFIX}" ] && ! $(echo $IPADDR | grep "/" 2>&1 >/dev/null) ; then
	IPADDR="$IPADDR/$PREFIX"
fi
}

do_netreport ()
{
# Notify programs that have requested notification
( cd /var/run/netreport || exit
for i in * ; do
	[ -f $i ] && \
		kill -SIGIO $i >/dev/null 2>&1 || \
		rm -f $i >/dev/null 2>&1
done
)
}

need_hostname()
{
if [ "`hostname`" = "(none)" -o "`hostname`" = "localhost" -o \
	"`hostname`" = "localhost.localdomain" ]; then
	NEEDHOSTNAME=yes
else
	unset NEEDHOSTNAME
fi
}

set_hostname()
{
typeset hostname domain
hostname=$(echo $1 | awk ' { gsub(/\..*$/,NIL); print $0; } ')
domain=$(echo $1 | awk ' { sub(/^[^\.]*\./,NIL); print $0; } ')

if [ -n "$hostname" ] ; then
	echo "$hostname" > /etc/HOSTNAME
	hostname $hostname
fi	

if [ -n "$domain" ] ; then
	>/etc/resolv.conf.new
	if ! grep -q "search $domain" /etc/resolv.conf ; then
		echo "search $domain" >> /etc/resolv.conf.new
	fi
	echo "domain $domain" >> /etc/resolv.conf.new
	grep -v "^domain " /etc/resolv.conf >> /etc/resolv.conf.new
	mv -f /etc/resolv.conf.new /etc/resolv.conf
fi
}

# PLD Linux network functions
# Copyright (C) 1999, 2000 Arkadiusz Mikiewicz <misiek@pld.org.pl>

# Setup Network Address Translation (NAT)
setup_nat()
{
typeset src via dst
if [ -r /etc/sysconfig/static-nat ]; then
	grep "^[0-9]" /etc/sysconfig/static-nat | while read src via dst; do
		if [ "$1" = "on" ]; then
			/sbin/ip route add nat $dst via $src
			/sbin/ip rule add from $src nat $dst
		elif [ "$1" = "off" ]; then
			/sbin/ip rule del from $src nat $dst
			/sbin/ip route del nat $dst via $src
	fi
	done
fi
}

# Setup static ARP
static_arp()
{
typeset rc arpdev host hwaddr flags neflags
if is_yes "$STATIC_ARP" && [ -r /etc/ethers ]; then
	if [ -x /sbin/arp ]; then
		run_cmd "Setting static ARP entries" /sbin/arp -f /etc/ethers
	else
		show "Setting static ARP entries"; busy
		rc=0
		arpdev=$(ip link show | awk -F':' '(/UP/) && ! (/NOARP/) && ! (/lo:/) && ! (/NONE:/) { print $2; exit }')
		if [ -z "$arpdev" ]; then
			rc=1
		else
			# ip supports only ip addresses
			grep "^[0-9]" /etc/ethers | \
			while read host hwaddr flags; do
				case "$flags" in
				  *temp*)
				  neflags="nud stale"
				  ;;
				  *)
				  neflags="nud permanent"
				  ;;
				esac
				if ! /sbin/ip neigh add $host lladdr $hwaddr $neflags dev $arpdev; then
					rc=1
				fi
			done
		fi
		if [ "$rc" -gt 0 ]; then
			fail
		fi
	fi
fi
}

static_rarp()
{
if is_yes "$STATIC_RARP"; then
	if [ ! -e /proc/net/rarp ]; then
		_modprobe single -k rarp
	fi
	if [ -r /etc/ethers -a -x /sbin/rarp ]; then
		run_cmd "Setting static RARP entries" /sbin/rarp -f /etc/ethers
	fi
fi
}

vlan_setup()
{
if [ -x /sbin/vconfig -a -e /proc/net/vlan/config ] && `echo $DEVICE | grep -q ^eth`; then
	/sbin/vconfig set_name_type DEV_PLUS_VID_NO_PAD 2>&1 > /dev/null
	ETH_VLANS="yes"
else
	ETH_VLANS="no"
fi
}

setup_forwarding ()
{
if is_yes "$IPV4_NETWORKING" && is_yes "$IPV4_FORWARDING" && [ -f /proc/sys/net/ipv4/ip_forward ];
then
	if [ "$1" = "on" ]; then
		run_cmd "Enabling IPv4 packet forwarding" sysctl -w net.ipv4.ip_forward=1
	else
		run_cmd "Disabling IPv4 packet forwarding" sysctl -w net.ipv4.ip_forward=0
	fi
fi

if is_yes "$IPV6_NETWORKING" && is_yes "$IPV6_FORWARDING" && [ -f /proc/sys/net/ipv6/conf/all/forwarding ];
then
	if [ "$1" = "on" ]; then
		run_cmd "Enabling IPv6 packet forwarding" sysctl -w net.ipv6.conf.all.forwarding=1
	else
		run_cmd "Disabling IPv6 packet forwarding" sysctl -w net.ipv6.conf.all.forwarding=0
	fi
fi
}

# Set up all IP && IP parameter variables
setup_ip_param ()
{
# detect network device type (ie. dummy, eth for dummy0, eth0 ..)
if [ -z "$DEVICETYPE" ]; then
	DEVICETYPE=$(echo $DEVICE | awk ' { gsub(/[0-9]*\.?[0-9]*$/,NUL); print $0 } ')
fi

# real name of device (ie. is eth0 for eth0,eth0:1,eth0:alias)
DEVICE=$(echo $DEVICE | awk ' { gsub(/:.*$/,NUL); print $0 } ')

eval IP4ADDR="\$IPADDR${IP4_PRIM_IF:-}"
if echo "${IP4ADDR}" | grep -q ":" ; then
	IP6ADDR=${IP4ADDR}
	IP4ADDR=""
else
	eval IP4ADDROPT="\$IP_AOPTS${IP4_PRIM_IF:-}"
	eval IP4ROUTEOPT="\$IP_ROPTS${IP4_PRIM_IF:-}"
fi
if [ -n "${IP6_PRIM_IF}" ] ; then
	eval IP6ADDR="\$IPADDR${IP6_PRIM_IF:-}"
	eval IP6ADDROPT="\$IPV6_AOPTS${IP6_PRIM_IF:-}"
fi
if [ -n "${IP4_SRC_IF}" ] ; then
	eval IP4SRCADDR="\$IPADDR${IP4_SRC_IF}"
	IP4SRCADDR="src $IP4SRCADDR"
fi
if [ -n "${IP6_SRC_IF}" ] ; then
	eval IP6SRCADDR="\$IPADDR${IP6_SRC_IF}"
	IP6SRCADDR="src $IP6SRCADDR"
fi

# If tunnel device then add onlink option in routing
[ -n "$MODE" ] && TNLOPTS="onlink"

# new rc-scripts 0.4.x option
if [ -z "$HANDLING" ]; then
	HANDLING=0
fi

# set handling for bridge
case "$DEVICETYPE" in
	br|atm|lec)
		HANDLING=1
		;;
esac
		
# Multicast ready devices
if is_yes "$MULTICAST"; then
	MULTICAST="on"
else
	case "$DEVICETYPE" in
		eth|br)
			MULTICAST="on"
			;;
		*)
			MULTICAST="off"
			;;
	esac
fi

# ARP ready devices
if [ -n "$ARP" ] ; then
	if is_yes "$ARP"; then
		ARP="arp on"
	else
		ARP="arp off"
	fi
fi
				
}

check_device_down ()
{
	if (ip link show dev ${DEVICE} 2> /dev/null | grep -q UP); then
		return 1
	else
		return 0
	fi
}

setup_ip_gw_ro () 
{
# IPv4 gateway
if is_yes "$IPV4_NETWORKING"; then
	if [ -z "${GATEWAYDEV}" -o "${GATEWAYDEV}" = "${DEVICE}" ]; then
	    # set up default gateway
	    if [ -n "${GATEWAY}" ]; then
	  	ip -4 route add default via ${GATEWAY} dev ${DEVICE} ${IP4SRCADDR} ${TNLOPTS} onlink
	    	DEFGW=${GATEWAY}
	    elif [ "${GATEWAYDEV}" = "${DEVICE}" ]; then
	 	ip -4 route add default dev ${DEVICE} ${IP4SRCADDR} ${TNLOPTS}
	    fi
	fi
fi

# IPv6 gateway && IPv6 globalroute
if is_yes "$IPV6_NETWORKING"; then
	if is_no "${IPV6_FORWARDING}" ; then
    	    if [ -z "${GATEWAY6DEV}" -o "${GATEWAY6DEV}" = "${DEVICE}" ]; then
	    	# set up default gateway
	    	if [ -n "${GATEWAY6}" ]; then
	    		ip -6 route add default via ${GATEWAY6} dev ${DEVICE} ${IP6SRCADDR} onlink
			DEFGW6=${GATEWAY6}
	    	elif [ "${GATEWAY6DEV}" = "${DEVICE}" ]; then
	    		ip -6 route add default dev ${DEVICE} ${IP6SRCADDR}
	    	fi
	    fi
        else
            if [ -z "${IPV6_GLOBALROUTEDEV}" -o "${IPV6_GLOBALROUTEDEV}" = "${DEVICE}" ]; then
	    	# set up default route
	    	if [ -n "${IPV6_GLOBALROUTEGW}" ]; then
	    	    ip -6 route add 2000::/3 via ${IPV6_GLOBALROUTEGW} dev ${DEVICE} ${IP6SRCADDR}
	    	elif [ "${IPV6_GLOBALROUTEDEV}" = "${DEVICE}" ]; then
	            ip -6 route add 2000::/3 dev ${DEVICE} ${IP6SRCADDR}
		fi
	    fi
        fi
fi
}

is_wireless_device () {
    if [ -x /sbin/iwconfig ]; then
        LC_ALL=C iwconfig "${1}" 2>&1 | grep -q "no wireless extensions" || return 0
    fi
    return 1
}

#
# following function sets up routes not associated to any device
# eg. unreachable or blackhole routes
# (c) 1999 Jacek Konieczny <jajcus@pld.org.pl>
#
setup_routes()
{
typeset args
if [ -f /etc/sysconfig/static-routes ]; then
	if [ "$1" = "on" -o "$1" = "yes" ] ; then
		egrep "^(none)|(any)[[:blank:]]" /etc/sysconfig/static-routes | while read device args; do
			/sbin/ip route add $args
		done
	else
		egrep "^(none)|(any)[[:blank:]]" /etc/sysconfig/static-routes | while read device args; do
			/sbin/ip route del $args 2>/dev/null
		done
	fi
fi
}

# Add ONLY IPv4 address (IPv6 address is added automaticly)
set_up_loopback()
{
if is_yes "$IPV4_NETWORKING"; then
	ip addr add 127.0.0.1/8 dev lo
fi
ip link set dev lo up
}

set_down_loopback()
{
ip addr flush dev lo 2>&1 | grep -v "Nothing to flush"
ip link set dev lo down
}

modprobe_net()
{
if is_yes "$IPV6_NETWORKING" && is_module "ipv6"; then
	_modprobe single -k ipv6
fi

if is_yes "$IPX" && is_module "ipx"; then
	_modprobe single -k ipx
fi
}

#
# folowing function calculates network prefix from given network mask
# (c) 1999 Grzegorz Stanislawski <stangrze@open.net.pl>
#
calcprefix()
{
typeset OISF len olen bad prefix
OISF=$IFS
IFS="."
prefix=0
olen=8
bad=0

for i in $1; do
	len=0
	case $i in
	255)	len=8 ;;
	254)	len=7 ;;
	252)	len=6 ;;
	248)	len=5 ;;
	240)	len=4 ;;
	224)	len=3 ;;
	192)	len=2 ;;
	128)	len=1 ;;
	0)	len=0 ;;
	*)	len=300 ;;
	esac

	if [ "$len" -gt "$olen" ] ; then bad=1; fi
	prefix=$(($prefix + $len))
	olen=$len
done

IFS=$OIFS
if [ "$bad" = "0" ]; then
	echo "$prefix"
else
	echo "32"
fi
return
}

#
# folowing function calculates network mask from given prefix
# (c) 1999 Grzegorz Stanislawski <stangrze@open.net.pl>
#
calcnetmask()
{
typeset prefix a MASK
MASK=""
if [ "`echo "${1}" | grep "^[0-9]"`" = "" ]; then
	prefix=32
else
	typeset -i prefix=$1
fi
for i in 1 2 3 4; do
	case $prefix in
	7) a=254 ;;
	6) a=252 ;;
	5) a=248 ;;
	4) a=240 ;;
	3) a=224 ;;
	2) a=192 ;;
	1) a=128 ;;
	*)
		if [ $prefix -ge 8 ]; then a=255; fi 
		if [ $prefix -le 0 ]; then a=0; fi
		;;
	esac

	prefix="$(( $prefix - 8))"
	if [ -z "$MASK" ]; then
		MASK=$a
	else
		MASK=$MASK.$a
	fi
done

echo $MASK
return
}

# Retrievies PPPD PID and real interface name from /var/run/ppp-*.pid
get_ppp_device_and_pid () {
	
if [ -f "/var/run/ppp-$DEVICE.pid" ] ; then
	eval `{
	         read PID ; echo "PID='$PID'" 
		 read REALDEVICE ; echo "REALDEVICE=$REALDEVICE"
	      } < "/var/run/ppp-$DEVICE.pid"`
fi
if [ -z "$REALDEVICE" ] ; then
	REALDEVICE=$DEVICE
fi
}

# This must be last line !
# vi:syntax=sh:tw=78:ts=8:sw=4

