Cover V12, I01
jan2003.tar

Listing 2 autosniffd

#!/bin/sh

# Allow an unprivileged person (like a customer) trigger a sniff
# tell the customer to "telnet problemhost <bogus-port>" and then
# reproduce the problem they've been complaining about.

# Written by Ed Ravin <eravin@panix.com>
# Courtesy of PANIX, Public Access Networks Corporation, http://www.panix.com
# License is GPL: see http://www.gnu.org/licenses/gpl.html

set -u

USAGE="usage: autosniff [--timeout=seconds] [--comment=xxxx] \
  [--debug | --discard-output ] [ --testonly] jobname mail-address \
  trigger-host trigger-port 'sniff filter'"

############################# load configuration
CONFIGFILE=/etc/autosniff.conf

. $CONFIGFILE
#############################

COMMENT=""
TESTONLY=false  # if true, test filter expressions and exit

while true
do
    case ${1:?$USAGE} in
    -*)
        case $1 in
        --comment=*) COMMENT="${1#*=}" ;;  # on Solaris, need ksh
        --timeout=*) TIMEOUT="${1#*=}" ;;  # for this syntax
        --discard-output) exec >/dev/null 2>&1 ;; # for use with nohup
        --debug) set -x ;;
        --testonly) TESTONLY=true ;;
        -*) echo "Unknown argument: $1"; echo $USAGE; exit 22 ;;
        esac
        shift
    ;;
    *) break ;;
    esac
done

JOBNAME=${1:?$USAGE}
MASTER=${2:?$USAGE}
TRIGGERHOST=${3:?$USAGE}
TRIGGERPORT=${4:?$USAGE}
SNIFFTARGET="( ${5:?$USAGE} )"

if [ ! -d $ARCHIVE ]
then
    mkdir $ARCHIVE
    if [ ! -d $ARCHIVE ]
    then
        echo "$0: $ARCHIVE: cannot create."
        exit 33
    fi
fi

# protect security of sniffer output
chown root $ARCHIVE
chmod 700 $ARCHIVE
umask 077


CAPTUREFILE=$ARCHIVE/$JOBNAME.$$.$SUFFIX

notify_master() {  # "subject" < message
    {
        if [ "$COMMENT" ]
        then
            echo "Jobname: $JOBNAME ($COMMENT)"
        else
            echo "Jobname: $JOBNAME"
        fi
        echo "Host: $HOSTNAME"
        echo
        cat
    } | $MAILER -s "Autosniff - $JOBNAME: $1" $MASTER
}

parse_trace() {  # extract source IP from first packet in tracefile
set `egrep -e '[- ]> ' $TMPFILE | head -1`
eval "echo \${$IPARG} | cut -f1-4 -d." # remove any trailing port number
}

testsniff() {
    if $SNIFF $SNIFFTEST $1 >/dev/null
    then :
    else
        echo "Expression '$1' was rejected by '$SNIFF $SNIFFTEST'"
        exit 42
    fi
}

TRIGGER="tcp and dst host $TRIGGERHOST and dst port $TRIGGERPORT"

if $TESTONLY
then
    testsniff "$TRIGGER"
    testsniff "host 0.0.0.0 and $SNIFFTARGET"
    exit 0
fi

notify_master "waiting for trigger" <<-END
    Host: $HOSTNAME
    Waiting for this trigger:  $TRIGGER
    After trigger, will sniff for $TIMEOUT seconds: host <autodetect> and $SNIFFTARGET

    Instructions for the user:

    1. "telnet $TRIGGERHOST $TRIGGERPORT" or "http://$TRIGGERHOST:$TRIGGERPORT"
    2. You will see an error message - ignore it and proceed to step (3).
    3. Reproduce the network-related problem.
    END

nohup $SNIFF $SNIFFCOUNT $TRIGGER > $TMPFILE
if [ -s $TMPFILE ]
then : # OK, found something
else
    notify_master "trigger failure" <<-END
        command: $SNIFF $SNIFFCOUNT $TRIGGER
        returned status: $?
        END
    exit 1
fi

IP2SNIFF=`parse_trace`

if [ `expr "$IP2SNIFF" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*'` \
  -lt 7 ]  # minimum match is n.n.n.n, 7 chars
then
    notify_master "trigger IP address failure" <<-END
        Invalid IP address: $IP2SNIFF
        Failed to properly parse field $IPARG in $TMPFILE
        END
    exit 2
fi


SNIFFEXPR="host $IP2SNIFF and $SNIFFTARGET"
$SNIFFWRITE $CAPTUREFILE $SNIFFEXPR &
SNIFFPID=$!

(sleep $TIMEOUT; kill $SNIFFPID) &
SLEEPPID=$!

wait

# snoop files are 12 bytes when empty, pcap files are 24 bytes when empty
# 50 bytes should mean at least one packet is in there
FILESIZE=`wc -c $CAPTUREFILE | awk '{print $1}'`
if [  $FILESIZE -gt 50 ] # 
then
    notify_master "success" <<-END
        Trigger was: $TRIGGER
        Sniffed $TIMEOUT seconds for: $SNIFFEXPR
        $FILESIZE bytes captured in $CAPTUREFILE
        END
else
    {
        echo "Sniff triggered, but no output in $CAPTUREFILE."
        echo "Sniff filter was: $SNIFFEXPR"
        echo "Trigger was: $TRIGGER"
        echo "Trigger results shown below"
        echo "---------------------------"
        cat  $TMPFILE
    } | notify_master "failure"
fi

rm -f $TMPFILE