--- /dev/null
+#!/bin/bash
+#
+# lc_servip.sh - script for verifying the service IP and the real
+# interface IP in a remote host are in the same subnet
+#
+###############################################################################
+
+# Usage
+usage() {
+ cat >&2 <<EOF
+
+Usage: `basename $0` <service IPaddr> <hostname>
+
+ service IPaddr the IP address to failover
+ hostname the hostname of the remote node
+
+EOF
+ exit 1
+}
+
+# Check arguments
+if [ $# -lt 2 ]; then
+ usage
+fi
+
+# Remote command
+REMOTE=${REMOTE:-"ssh -x -q"}
+
+# Check whether the reomte command is pdsh
+is_pdsh() {
+ if [ "${REMOTE}" = "${REMOTE#*pdsh}" ]; then
+ return 1
+ fi
+
+ return 0
+}
+
+#
+# inSameIPsubnet serviceIPaddr interfaceIPaddr mask
+#
+# Given two IP addresses and a subnet mask determine if these IP
+# addresses are in the same subnet. If they are, return 0, else return 1.
+#
+inSameIPsubnet() {
+ declare -i n
+ declare -ia mask
+ declare -ia ip1 ip2 # IP addresses given
+ declare -i quad1 quad2 # calculated quad words
+
+ #
+ # Remove '.' characters from dotted decimal notation and save
+ # in arrays. i.e.
+ #
+ # 192.168.1.163 -> array[0] = 192
+ # array[1] = 168
+ # array[2] = 1
+ # array[3] = 163
+ #
+ let n=0
+ for quad in $(echo $1 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
+ do
+ ip1[n]=$quad
+ let n=n+1
+ done
+
+ let n=0
+ for quad in $(echo $2 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
+ do
+ ip2[n]=$quad
+ let n=n+1
+ done
+
+ let n=0
+ for quad in $(echo $3 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
+ do
+ mask[n]=$quad
+ let n=n+1
+ done
+
+ #
+ # For each quad word, logically AND the IP address with the subnet
+ # mask to get the network/subnet quad word. If the resulting
+ # quad words for both IP addresses are the same they are in the
+ # same IP subnet.
+ #
+ for n in 0 1 2 3
+ do
+ let $((quad1=${ip1[n]} & ${mask[n]}))
+ let $((quad2=${ip2[n]} & ${mask[n]}))
+
+ if [ $quad1 != $quad2 ]; then
+ echo >&2 $"`basename $0`: Service IP address $1 and"\
+ "real interface IP address $2 are in"\
+ "different subnets!"
+ return 1 # in different subnets
+ fi
+ done
+
+ return 0 # in the same subnet, all quad words matched
+}
+
+#
+# findInterface IPaddr hostname
+#
+# Given a target IP address and a hostname, find the interface in which
+# this address is configured. If found return 0, if not return 1. The
+# interface name is returned to stdout.
+#
+findInterface() {
+ declare ret_line
+ declare line
+ declare intf
+ declare addr
+ declare state
+
+ declare target=$1
+ declare hostname=$2
+
+ while read ret_line
+ do
+ set -- ${ret_line}
+ is_pdsh && shift
+ intf="$1"
+ shift
+ line="$*"
+
+ while read line
+ do
+ if [ "$line" = "" ]; then # go to next interface
+ continue 2
+ fi
+
+ set - $line
+ addr=
+ while [ $# -gt 0 ]; do
+ case $1 in
+ addr:*)
+ addr=${1##addr:}
+ if [ -n "$addr" -a "$addr" = "$target" ]
+ then
+ echo $intf
+ return 0
+ fi
+ ;;
+ esac
+ shift
+ done
+ done
+ done < <(${REMOTE} $hostname /sbin/ifconfig)
+
+ echo >&2 "`basename $0`: Cannot find the interface in which" \
+ "$target is configured in the host $hostname!"
+ return 1
+}
+
+#
+# findNetmask interface hostname
+#
+# Given an interface find the netmask addresses associated with it.
+# Return 0 when found, else return 1. The netmask is returned to stdout.
+#
+findNetmask() {
+ declare ret_line
+ declare line
+ declare addr
+ declare target=$1
+ declare hostname=$2
+
+ while read ret_line
+ do
+ set -- ${ret_line}
+ is_pdsh && shift
+ line="$*"
+
+ set - $line
+
+ while [ $# -gt 0 ]; do
+ case $1 in
+ Mask:*)
+ echo ${1##*:} # return netmask addr
+ return 0
+ ;;
+ esac
+ shift
+ done
+ done < <(${REMOTE} $hostname /sbin/ifconfig $target)
+
+ echo >&2 "`basename $0`: Cannot find the netmask associated with" \
+ "the interface $target in the host $hostname!"
+ return 1
+}
+
+#
+# check_srvIPaddr serviceIPaddr hostname
+#
+# Given a service IP address and hostname, check whether the service IP address
+# and the real interface IP address of hostname are in the same subnet.
+# If they are, return 0, else return 1.
+#
+check_srvIPaddr() {
+ declare real_IPaddr
+ declare real_intf
+ declare netmask
+ declare srv_IPaddr=$1
+ declare hostname=$2
+
+ # Get the corresponding IP address of the hostname from /etc/hosts table
+ real_IPaddr=`egrep "[[:space:]]$hostname([[:space:]]|$)" /etc/hosts \
+ | awk '{print $1}'`
+ if [ -z "$real_IPaddr" ]; then
+ echo >&2 "`basename $0`: Hostname $hostname does not exist in" \
+ "the local /etc/hosts table!"
+ return 1
+ fi
+
+ if [ ${#real_IPaddr} -gt 15 ]; then
+ echo >&2 "`basename $0`: More than one IP address line" \
+ "corresponding to $hostname in the local" \
+ "/etc/hosts table!"
+ return 1
+ fi
+
+ # Get the interface in which the real IP address is configured
+ real_intf=$(findInterface $real_IPaddr $hostname)
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+ real_intf=${real_intf%%:*}
+
+ # Get the netmask address associated with the real interface
+ netmask=$(findNetmask $real_intf $hostname)
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+
+ # Determine if the service IP address and the real IP address
+ # are in the same subnet
+ inSameIPsubnet $srv_IPaddr $real_IPaddr $netmask
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+
+ return 0
+}
+
+# Check service IP address
+if ! check_srvIPaddr $1 $2; then
+ exit 1
+fi
+exit 0