Sophie

Sophie

distrib > Mandriva > 10.2 > i586 > by-pkgid > ea4f0e137a54ee122189d93568404b89 > files > 23

heartbeat-1.2.3-2mdk.i586.rpm

#!/bin/sh
#
#	$Id: IPaddr2.in,v 1.8.2.5 2004/08/30 09:08:24 horms Exp $
#
#	Copyright (C) 2003 Tuomo Soini <tis@foobar.fi>
#
#	This script manages IP alias IP addresses
#
#	It can add an IP alias, or remove one.
#
#	usage: $0 ip-address[/netmaskbits[/interface[:label][/broadcast]]] \
#	    {start|stop|status|monitor}
#
#	The "start" arg adds an IP alias.
#
#	Surprisingly, the "stop" arg removes one.	:-)
#
#
unset LANG
LC_ALL=C
export LC_ALL

prefix=/usr
exec_prefix=/usr
. /etc/ha.d/shellfuncs

IP2UTIL=/sbin/ip
SENDARP=$HA_BIN/send_arp
FINDIF=$HA_BIN/findif
VARLIB=/var/lib/heartbeat
VLDIR=$VARLIB/rsctmp/IPaddr
SENDARPPIDDIR=$VARLIB/rsctmp/send_arp
USAGE="usage: $0 ip-address[/netmaskbits[/interface[:label][/broadcast]]]
{start|stop|status|monitor}\n\nNote: $0 only works on Linux";

#
#	Set BASEIP for use in other parts of script.
#	Find out which interface to use with findif utility and
#	parse findif output.
#
BASEIP=`echo $1 | sed 's%/.*%%'`
NICINFO=`$FINDIF -C $1 2>/dev/null | sed -e 's/netmask\ //;s/broadcast\ //'`
IFACE=`echo "$NICINFO" | cut -f1`
NETMASK=`echo "$NICINFO" | cut -f2`
BROADCAST=`echo "$NICINFO" | cut -f3`

case $IFACE in
    *:*)
	INTERFACE=`echo $IFACE | sed 's/:.*//'`
	IFLABEL=$IFACE
	;;
    *)
	INTERFACE=$IFACE
	;;
esac

#
#	Find out which interface serves the given IP address
#	The argument is an IP address, and its output
#	is an interface name (e.g., "eth0").
#
find_interface() {
    #
    # List interfaces but exclude FreeS/WAN ipsecN virtual interfaces
    #
    iface=`$IP2UTIL -o -f inet addr show | grep "\ $1/" \
	| cut -d ' ' -f2 | grep -v '^ipsec[0-9][0-9]*$'`
    echo $iface
    return 0
}

#
#	Check if ip-address is running.
#	We return stopped or running.
#
status() {
    IFSTATUS=`find_interface $BASEIP`

    if
	[ -z "$IFSTATUS" ]
    then
	echo "stopped"
	RC=3
    else
        case $IFSTATUS in
          lo*)
		#
		# Do we really control loopback interface?
		#
		if
		    [ "$INTERFACE" = "lo" ]
		# Yes, we do.
		then
		    echo "running"
		    RC=0
		# No, this is "Conflicting loopback"
		else
		    echo "loopback"
		    RC=3
		fi
                ;;
          *)
                echo "running"
		RC=0
                ;;
        esac
    fi
    return $RC
}

#
#        Delete an interface
#
delete_interface () {
    ipaddr="$1"
    iface="$2"

    CMD="$IP2UTIL -f inet addr delete $ipaddr dev $iface"

    ha_log "info: $CMD"
    $CMD

    if 
        [ $? -ne 0 ]
    then
        return $?
    fi
    
    CMD="$IP2UTIL -o -f inet addr show $iface"

    ha_log "info: $CMD"
    ADDR=`$CMD`

    if 
        [ $? -ne 0 -o ! -z "$ADDR" ]
    then
        return $?
    fi
    
    CMD="$IP2UTIL link set $iface down"

    ha_log "info: $CMD"
    $CMD
    
    return $?

}


#
#        Add an interface
#
add_interface () {
    ipaddr="$1"
    netmask="$2"
    broadcast="$3"
    iface="$4"
    label="$5"

    CMD="$IP2UTIL -f inet addr add $ipaddr/$netmask brd $broadcast dev $iface"

    if
        [ ! -z "$label" ]
    then
        CMD="$CMD label $label"
    fi

    ha_log "info: $CMD"
    $CMD

    if 
        [ $? -ne 0 ]
    then
        return $?
    fi

    CMD="$IP2UTIL link set $iface up"

    ha_log "info: $CMD"
    $CMD

    return $?
}

#
#        Delete a route
#
delete_route () {
    prefix="$1"
    iface="$2"

    CMD="$IP2UTIL route delete $prefix dev $iface"

    ha_log "info: $CMD"
    $CMD
    
    return $?
}

#      On Linux systems the (hidden) loopback interface may
#      conflict with the requested IP address. If so, this
#      unoriginal code will remove the offending loopback address
#      and save it in VLDIR so it can be added back in later
#      when the IPaddr is released.
#
remove_conflicting_loopback() {
    ipaddr="$1"
    netmask="$2"
    broadcast="$3"
    ifname="$4"

    ha_log "info: Removing conflicting loopback $ifname."
    if
	[ -d "$VLDIR/" ] || mkdir -p "$VLDIR/"
    then
	: Directory $VLDIR now exists
    else
	ha_log "ERROR: Could not create \"$VLDIR/\" conflicting" \
	    " loopback $ifname cannot be restored."
    fi
    if
	echo "$ipaddr $netmask $broadcast $ifname" > "$VLDIR/$ipaddr"
    then
	: Saved loopback information in $VLDIR/$ipaddr
    else
	ha_log "ERROR: Could not save conflicting loopback $ifname." \
	    "it will not be restored."
    fi
    delete_interface "$ipaddr" "$ifname"
    # Forcibly remove the route (if it exists) to the loopback.
    delete_route "$ipaddr" "$ifname"
}       

#
#	On Linux systems the (hidden) loopback interface may
#	need to be restored if it has been taken down previously
#	by remove_conflicting_loopback()
#
restore_loopback() {
    ipaddr="$1"

    if
	[ -s "$VLDIR/$ipaddr" ]
    then
	ifinfo=`cat "$VLDIR/$ipaddr"`
	ha_log "info: Restoring loopback IP Address " \
	    "$ifinfo."
	add_interface $ifinfo
	rm -f "$VLDIR/$ipaddr"
    fi
}

run_send_arp() {
    #
    # Run send_arp to note peers about new mac address
    #
    [ -r ${CONF_D}/arp_config ] && . ${CONF_D}/arp_config
    if [ -r "${CONF_D}/arp_config:${TARGET_INTERFACE}" ]
    then
	. "${CONF_D}/arp_config:${TARGET_INTERFACE}"
    fi

    # Set default values (can be overridden as described above)

    : ${ARP_INTERVAL_MS=200}	# milliseconds between ARPs
    : ${ARP_REPEAT=5}		# repeat count
    : ${ARP_BACKGROUND=yes}	# no to run in foreground
    : ${ARP_NETMASK=ffffffffffff}	# netmask for ARP


    ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $INTERFACE $BASEIP auto $BASEIP $ARP_NETMASK"
    ha_log "$SENDARP $ARGS"
    case $ARP_BACKGROUND in
	yes) 
	    ($SENDARP $ARGS || 
	        ha_log "ERROR: Could not send gratuitous arps") &
	    ;;
	*)
	    $SENDARP $ARGS || ha_log "ERROR: Could not send gratuitous arps"
	    ;;
    esac
}

#
#	Add an IP alias for the requested IP address...
#
#	It could be that we already have taken it, in which case it should
#	do nothing.
#
start() {
    SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$BASEIP"

    #
    #	Do we already service this IP address?
    #
    case `status $1` in
	running)
	    exit 0
	    ;;
	loopback)
            remove_conflicting_loopback $BASEIP 32 255.255.255.255 lo
            ;;
    esac

    #
    #	If there is local_takeip script, run it.
    #
    if
	[ -x $HA_RCDIR/local_takeip ]
    then
	$HA_RCDIR/local_takeip $*
    fi

    add_interface $BASEIP $NETMASK $BROADCAST $INTERFACE $IFLABEL
    rc=$?

    case $rc in
	0)
	    ;;
	*)
	    echo "ERROR: $CMD failed."
	    return $rc
	    ;;
    esac

    case $INTERFACE in
	lo*)
	    : no need to run send_arp on loopback
	    ;;
	*)
	    run_send_arp
	    ;;
    esac
}

#
#	Remove the IP alias for the requested IP address...
#
stop() {
    IF=`find_interface $BASEIP`
    SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$BASEIP"

    if
	[ -f "$SENDARPPIDFILE" ]
    then
	kill `cat "$SENDARPPIDFILE"`
	rc=$?
	case $rc in
	    0)
		ha_log "info: killed previously running send_arp for $BASEIP"
		rm -f "$SENDARPPIDFILE"
		;;
	    *)
		ha_log "WARN: Could not kill previously running send_arp for $BASEIP"
		;;
	esac
    fi

    if
	[ -z "$IF" ]
    then
	: Requested interface not in use
	exit 0
    fi

    #
    #	If there is local_giveip script, run it.
    #
    if
	[ -x $HA_RCDIR/local_giveip ]
    then
	$HA_RCDIR/local_giveip $*
    fi

    delete_interface $BASEIP $IF
    rc=$?

    restore_loopback "$BASEIP"

    case $rc in
	0)
	    ha_log "info: IP Address $BASEIP released"
	    ;;
	*)
	    ha_log "WARN: IP Address $BASEIP NOT released"
	    ;;
    esac
    return $rc
}

#
#	Determine if this IP address is really being served, or not.
#	Note that we don't distinguish if *we're* serving it locally...
#
monitor() {
    OPTS=" -c 1 -w1 -q"
    for j in 1 2 3
    do
	if
	    /bin/ping $OPTS $BASEIP >/dev/null 2>&1
	then
	    echo "OK"
	    return 0
	fi
    done
    echo "down"
    return 1
}

usage() {
  echo -e $USAGE >&2
}

#
#	Add or remove IP alias for the given IP address...
#
if
    [ $# -ne 2 ]
then
    usage
    exit 1
fi

case $2 in
    start)
	start $1
	;;
    stop)
	stop $1
	;;
    status)
	status $1
	;;
    monitor)
	monitor $1
	;;
    *)
	usage
 	exit 1
	;;
esac

# EOF - end of file