Viewing: lc_servip
#!/usr/bin/bash
#
# lc_servip - 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=`grep -E "[[: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