#!/bin/sh # # This file is part of the FreeWRT project. FreeWRT is copyrighted # material, please see the LICENCE file in the top-level directory # or at http://www.freewrt.org/licence for details. # # Christian Fischer # built_in() { local what=$1 local alias=$(alias $what) unalias $what alias $(echo $alias|sed 's/'\''//g') shift $what $@ } config() { [ x"$1" != x"0" ] } __ifupdown() { local environ=$(cat $ENVFILE) IFUPDOWN_ENV=$(echo -n $IFUPDOWN_ENV|sed 's/\(MDENT=\)[^ ]*[[:space:]]*//g';\ echo " PARENT_IFACE_TYPE=$IFACE_TYPE"; \ echo " PARENT_IFACE=$IFACE"; \ echo " MDENT=$MDENT") \ busybox "$@" retval=$? echo $environ > $ENVFILE return $retval } __exit() { [ x"$1" != x"0" ] && echo "RT_ERR=1" >> $ENVFILE exit $1 } iface_exists() { grep -q "${1:-$IFACE}:" /proc/net/dev } is_up() { local iface=${1:-$IFACE} if iface_exists $iface then ip a|grep ${iface}:[[:space:]]|grep -q UP && return ### ifupdown netlink bug workaround ### # suppress "ip: RTNETLINK answers: File exists" message in the case of # iface is down but an ip address is assigned ip a|grep ${iface}$|grep -q inet && ip addr flush dev $iface >/dev/null 2>&1 ### end workaround ### fi return 1 } main_env_update() { local t_mdent lastmatch= # get submode from calling hook script SUBMODE=$(echo ${0%/*} |sed '{ s/\(.*\/\)*//; s/\.d$//}') # create env file if ! [ -f "$ENVFILE" ] then [ -d ${ENVFILE%/*} ] || mkdir -p ${ENVFILE%/*} echo "MDENT=0" >> $ENVFILE echo "LASTLOG=0" >> $ENVFILE is_up && IFACE_STATE="up" || IFACE_STATE="down" echo "IFACE_STATE=$IFACE_STATE" >> $ENVFILE if [ x"$IFACE" != x"lo" ] then # search for existing lib files end evaluate iface type by using the appropriate # function from lib file for lib in ${LIBDIR}/iftypes/* do [ -f $lib ] && (. $lib; iface_type 2>&-) || continue if [ -n "$lastmatch" ] then if [ ${lib##*/} = ${lastmatch##*/} ] then mprint -s "Warning: $lib overlays $lastmatch" else mprint -s "Error: iface type $lib overlays $lastmatch" fi fi lastmatch=$lib done fi # if iface type isn't evaluated type "iface" is default [ -n "$lastmatch" ] && IFACE_TYPE=${lastmatch##*/} || IFACE_TYPE="iface" # update env echo "IFACE_TYPE=${IFACE_TYPE}" >> $ENVFILE fi . $ENVFILE t_mdent=$MDENT # expand $IFUPDOWN_ENV for var in $IFUPDOWN_ENV; do eval $var done [ $t_mdent -gt $MDENT ] && MDENT=$t_mdent main_pos_update } main_pos_update() { [ x"$MDENT" = x"0" ] && STARTCOL= || STARTCOL="[$(expr ${MDENT:-0} \* ${TAB})C" sed 's/MDENT=[0-9]*/'MDENT=$MDENT'/' -i $ENVFILE } main_preup() { config $RT_PREUP_PRINTING_OFF || mstart if ! config $RT_PREUP_IFUP_CHECK_OFF && is_up then if ! config $RT_PREUP_PRINTING_OFF then mup mstate 1 minfo "Interface already up" fi exit 1 fi if_preup 2>&- retval=$? [ x"$retval" != x"0" -a x"$retval" != x"127" ] && { fail_preup 2>&- || exit 1 } config $RT_PREUP_PRINTING_OFF && return mup } main_up() { [ x"$METHOD" = x"manual" ] && ip link set up dev $IFACE if ! config $RT_UP_IFUP_CHECK_OFF then is_up retval=$? config $RT_UP_PRINTING_OFF || mstate $retval [ x"$retval" != x"0" ] && exit 1 fi if_up 2>&- retval=$? [ x"$retval" != x"0" -a x"$retval" != x"127" ] && { fail_up 2>&- || exit 1 } if [ -d /tmp/ifupdown/pcode/${IFACE} ] then for dir in /tmp/ifupdown/pcode/${IFACE}/* do [ -f ${dir}/postup ] || continue . ${dir}/postup done fi } main_down() { config $RT_DOWN_PRINTING_OFF || mstop if [ -d /tmp/ifupdown/pcode/${IFACE} ] then for dir in /tmp/ifupdown/pcode/${IFACE}/* do [ -f ${dir}/predown ] || continue . ${dir}/predown done fi if_down 2>&- retval=$? [ x"$retval" != x"0" -a x"$retval" != x"127" ] && { fail_down 2>&- || exit 1 } config $RT_DOWN_PRINTING_OFF && return mdown } main_postdown() { [ x"$METHOD" = x"manual" ] && { ip addr flush dev %ifac ip link set down dev $IFACE } if ! config $RT_POSTDOWN_IFDOWN_CHECK_OFF then if [ $IFACE_STATE = "down" ] then if ! config $RT_POSTDOWN_PRINTING_OFF then mdown mstate 1 minfo "Interface already down" fi else is_up && retval=1 || retval=0 config $RT_POSTDOWN_PRINTING_OFF || mstate $retval [ "$retval" != "0" ] && exit 1 fi fi if_postdown 2>&- retval=$? [ x"$retval" != x"0" -a x"$retval" != x"127" ] && { fail_postdown 2>&- || exit 1 } # pcode cleanup rm -rf /tmp/ifupdown/pcode/*/$IFACE 2>&- 1>&- } main_exec_dirhooks() { for hook in ${LIBDIR}/${1}/${2} do [ -f $hook ] || continue . $hook eval $3 2>&- retval=$? [ x"$retval" != x"0" -a x"$retval" != x"127" ] && exit 1 return done } main_exec_plugins() { for plugin in ${LIBDIR}/plugins/*; do [ -f $plugin ] || continue . $plugin eval "${plugin##*/}_${1}" 2>&- retval=$? [ x"$retval" != x"0" -a x"$retval" != x"127" ] && exit 1 done } main_exec_inlinehooks() { case $SUBMODE in if-pre-up) [ -n "$IF_PRE_UP" ] && eval $IF_PRE_UP ;; if-up) [ -n "$IF_UP" ] && eval $IF_UP ;; if-down) [ -n "$IF_DOWN" ] && eval $IF_DOWN ;; if-post-down) [ -n "$IF_POST_DOWN" ] && eval $IF_POST_DOWN ;; esac } ### main entry point ### FWIFUPDOWN_PRINTING_OFF=0 FWIFUPDOWN_SYSLOG_OFF=0 FWIFUPDOWN_FANCY=0 FWIFUPDOWN_DEBUG=0 . /etc/rc.conf config $FWIFUPDOWN_DEBUG && set -x RT_PREUP_PRINTING_OFF=0 RT_UP_PRINTING_OFF=0 RT_DOWN_PRINTING_OFF=0 RT_POSTDOWN_PRINTING_OFF=0 RT_PREUP_IFUP_CHECK_OFF=0 RT_UP_IFUP_CHECK_OFF=0 RT_POSTDOWN_IFDOWN_CHECK_OFF=0 RT_BB_NOEXEC=0 RT_ERR=0 readonly ENVFILE="/tmp/ifupdown/env" readonly LIBDIR="/etc/network" IFACE_TYPE="none" alias exit="__exit" alias ifup="__ifupdown ifup" alias ifdown="__ifupdown ifdown" [ -z "$KSH_VERSION" ] || alias which='whence -p' if ! [ -f /etc/network/mfunctions.sh ] then logger -t ifupdown "/etc/network/mfunctions.sh not found" exit 1 fi . /etc/network/mfunctions.sh main_env_update config $RT_ERR && built_in exit 1 if [ x"$IFACE_TYPE" != x"iface" ] then if [ -f "${LIBDIR}/iftypes/${IFACE_TYPE}" ] then . ${LIBDIR}/iftypes/$IFACE_TYPE else mprint -s "Error: libfile $IFACE_TYPE not found" fi fi case $SUBMODE in if-pre-up) main_preup main_exec_dirhooks methods $METHOD method_preup main_exec_plugins preup # bypass execution of further busybox ifupdown.c code config $RT_BB_NOEXEC && built_in exit 1 ;; if-up) main_exec_plugins up main_exec_dirhooks methods $METHOD method_up main_up ;; if-down) main_down main_exec_dirhooks methods $METHOD method_down main_exec_plugins down # bypass execution of further busybox ifupdown.c code config $RT_BB_NOEXEC && built_in exit 1 ;; if-post-down) main_exec_plugins postdown main_exec_dirhooks methods $METHOD method_postdown main_postdown ;; esac exit 0 # vim:ts=4