#! /bin/sh # mtrchk - Distinquish few possible states of hosts # Copyright (C) 2010 Matous J. Fialka [ http://mjf.cz/ ] # Released under the terms of The MIT License # USAGE # mtrchk [ LASTHOP1 LASTHOP2 ... LASTHOPN ] [ < FILENAME ] # # ENVIRONMENT # # MTRCHK_RETRIES Number of retries performed (default: 1) # # INPUT # Input either host name or either IPv4 or IPv6 address # or list of addresses on every line. Comments start with # the number sign. # # OUTPUT # The output is generated in the following form: # # := ' ' [ ' ' ] ; # := [ ' ' ] ; # # Status Description # ------- ------- ---------------------------------------- # 0 + Routed AND alive (ICMP replies) # 1 - Routed BUT NOT alive (no ICMP reply) # 2 @ Routed BUT cycled (redirect loop) # 3 ! POSSIBLY NOT routed (if last hops given) # 4 # NOT found (no such host in DNS) # -------------------------------------------------------- # # EXIT CODES # # Program exits with either status obtained from the last # check proceeded or with 127 in case bad option was given # or dependency checking failed. MTRCHK_RETRIES=${MTRCHK_RETRIES-1} for DEPENDENCY in which test mtr grep sed awk sort do if ! which "$DEPENDENCY" &>/dev/null then echo "Error: missing program $DEPENDENCY" 1>&2 exit 1 fi done if ! which [ &>/dev/null then echo "Error: there is no [ link to program test" 1>&2 exit 127 fi IP4="\(25[0-5]\|2[0-4][0-9]\|1[0-9]\{2\}\|[1-9]\?[0-9]\)" IP4="$IP4\(\.$IP4\)\{3\}" H="[0-9A-Fa-f]\{1,4\}" IP6="\(" IP6="$IP6\(\($H:\)\{7\}\($H\|:\)\)\|" IP6="$IP6\(\($H:\)\{6\}\(:$H\|$IP4\|:\)\)\|" IP6="$IP6\(\($H:\)\{5\}\(\(\(:$H\)\{1,2\}\)\|:$IP4\|:\)\)\|" IP6="$IP6\(\($H:\)\{4\}\(\(\(:$H\)\{1,3\}\)\|\(\(:$H\)\?:$IP4\)\|:\)\)\|" IP6="$IP6\(\($H:\)\{3\}\(\(\(:$H\)\{1,4\}\)\|\(\(:$H\)\{0,2\}:$IP4\)\|:\)\)\|" IP6="$IP6\(\($H:\)\{2\}\(\(\(:$H\)\{1,5\}\)\|\(\(:$H\)\{0,3\}:$IP4\)\|:\)\)\|" IP6="$IP6\(\($H:\)\{1\}\(\(\(:$H\)\{1,6\}\)\|\(\(:$H\)\{0,4\}:$IP4\)\|:\)\)\|" IP6="$IP6\(:\(\(\(:$H\)\{1,7\}\)\|\(\(:$H\)\{0,5\}:$IP4\)\|:\)\)" IP6="$IP6\)" IP6="$IP6\(%.\+\)\?" HN="[0-9A-Za-z]\([-0-9A-Za-z]*[0-9A-Za-z]\)\?" DN="\(\($HN\.\)*[A-Za-z][A-Za-z]\{1,3\}\|$HN\)" while [ -n "$1" ] do if echo $1 | grep "^\($IP4\|$IP6\|$DN\)$" >/dev/null then LASTHOPS="$LASTHOPS $1" else echo "Bad option: ill-formed last-hop $1" 1>&2 exit 127 fi shift done cycled() { while [ -n "$1" ] do CURRENT=$1 shift for ITEM in $@ do if [ "$CURRENT" = "$ITEM" ] then return 0 fi done done return 1 } lasthop() { ITEM=$1 while [ -n "$1" ] do shift if [ "$1" = "$ITEM" ] then return 0 fi done return 1 } STATUS=0 set -f 2>/dev/null while read HOSTS do for HOST in `echo "$HOSTS" | sed 's/#.*$//'` do SAVEDHOST=$HOST if ! echo $HOST | grep "^\($IP4\|$IP6\)$" >/dev/null then if ! echo $HOST | grep "^\($DN\)$" >/dev/null then echo "Bad input: invalid host $HOST" 1>&2 continue fi REALHOSTS=`host -R$MTRCHK_RETRIES "$HOST" | awk '/has[ \t]+([^ \t]*[ \t]+)?address/ { print $NF }'` if [ -z "$REALHOSTS" ] then STATUS=4 echo "# $HOST" continue fi else REALHOSTS=`echo $HOST | sed 's/%.\+$//'` fi for HOST in $REALHOSTS do TRACE=`mtr -pnc$MTRCHK_RETRIES $HOST