X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~webstump/git?a=blobdiff_plain;f=probes%2Fmodrelays-probe;h=4ce164856cdaee895cab95243735835a2c7beaea;hb=30b5847971bd2932dc2416e7172d67793f620ac2;hp=1c4ead4ffcdd63c677c81a7a64bb09b67eb4dbe9;hpb=eb3305d6e47dc86dbeba5bb6c9c499c9dee433c9;p=modbot-mtm.git diff --git a/probes/modrelays-probe b/probes/modrelays-probe index 1c4ead4..4ce1648 100755 --- a/probes/modrelays-probe +++ b/probes/modrelays-probe @@ -1,49 +1,80 @@ #!/bin/bash -set -e +set -e$MODRELAYS_PROBE_SET_X + +MODRELAYS=moderators.isc.org +PROBE_TIMEOUT=$(( 20 * 60 )) +PROBE_EXPIRE=$(( 32 * 86400 )) + +shopt -s nullglob + +case "$1" in +received) + mode="$1" + cd "$2" + shift; shift; set "$mode" "$@" + ;; +esac + +. ../global-settings +. ./settings id=$(date +%s)_$$ +statedir=probes/probes +lockfile=$statedir/.lock fail () { printf >&2 "%s\n" "modrelays-probe: error: $1" exit 16 } -record-probing () { - # implicitly uses newsgroup, id, domain - # prints working dir filename +compute-td () { + # implicitly uses GROUP, id, domain + # caller must "local td", which will be set local probeid=$1 - probeid=${probeid//[^=-.,_0-9A-Za-z]/%/} + probeid="$domain,${probeid//[^-=:.,_0-9A-Za-z]/%},$id" case $probeid in - .*|*/*) fail "yikes, sanitisation bug!" ;; + .*|*/*) fail "yikes, sanitisation bug ($probeid) !" ;; esac - local newtd="monitoring/modrelays.probes/$probeid" - mkdir -p $newtd - printf "%s" $newtd + td="$statedir/$probeid" +} + +record-probing () { + compute-td "$@" + mkdir -p $td +} + +record-probing-start () { + record-probing "$@" + if ! [ -e "$td/started" ]; then + date -R >"$td/started" + fi } record-outcome () { local probeid=$1 local outcome=$2 local message=$3 - local td=`record-probing "$probeid"` - printf "%s\n" >"$td"/"$outcome" + local td + record-probing "$probeid" + printf "%s\n" >"$td"/"$outcome" "$message" } -record-success () { record-outcome "$1" ok '' } -record-tempfail () { record-outcome "$1" tempfail "$2" } -record-permfail () { record-outcome "$1" permfail "$2" } +record-success () { record-outcome "$1" ok ''; } +record-tempfail () { record-outcome "$1" tempfail "$2"; } +record-permfail () { record-outcome "$1" permfail "$2"; } probe-addr () { local mx=$1 local addr=$2 - local td=`record-probing "mx=$mx,addr=$addr"` + local td + record-probing-start "mx=$mx,addr=$addr" set +e - swaks --to "${GROUP//./-/}@$domain" \ + swaks --to "${GROUP//./-}@$domain" \ --server $addr \ --tls-optional-strict \ --header 'Subject: test modrelays probe test' \ @@ -61,14 +92,15 @@ probe-addr () { local rhs local prefix local expect_no_5xx='initial connection' - while read <$td/swaks.log prefix rhs; do + exec 4<$td/swaks.log + while read <&4 prefix rhs; do case "$prefix" in '<'*) case "$rhs" in 5*) if [ "x$expect_no_5xx" != x ] && \ [ "x$permfail" = x ]; then - permfail="$rhs ($expect_no_5xx)" ;; + permfail="$rhs ($expect_no_5xx)" fi ;; esac @@ -80,6 +112,7 @@ probe-addr () { esac ;; *) + esac done if [ "x$permfail" = x ]; then @@ -91,7 +124,8 @@ probe-addr () { probe-domain () { local domain=$1 - local td=`record-probing dns` + local td + record-probing-start dns set +e adnshost -Fi -Tn +Do +Dt -t mx $domain >$td/dns @@ -101,13 +135,13 @@ probe-domain () { case $rc in 0) # have a list of MX's - exec <$td/dns + exec 3<$td/dns local pref local mx local statustype local rhs - while read pref mx statustype rhs; do - case $statustype in + while read <&3 pref mx statustype statustypenum rhs; do + case $statustypenum in 0) # have a list of relays case $rhs in @@ -116,9 +150,10 @@ probe-domain () { record-permfail "mx=$mx" \ "dns format $rhs" continue - ;; - rhs=${rhs%%* (} - rhs=${rhs# )} + ;; + esac + rhs=${rhs##* (} + rhs=${rhs% )} local addr for addr in $rhs; do case $addr in @@ -129,11 +164,13 @@ probe-domain () { ;; [123]) # temporary errors - record-tempfail "mx=$mx" "dns $rc $rhs" + record-tempfail "mx=$mx" \ + "dns $rc $statustype $rhs" ;; *) # yikes - record-permfail "mx=$mx" "dns $rc $rhs" + record-permfail "mx=$mx" \ + "dns $rc $statustype $rhs" ;; esac done @@ -141,9 +178,9 @@ probe-domain () { return ;; 6) - permfail, try A + # permfail, try A set +e - adnshost -Fi -Tn +Do +Dt -t a $domain >$td + adnshost -Fi -Tn +Do +Dt -t a $domain >$td/dns rc=$? set -e ;; @@ -152,10 +189,10 @@ probe-domain () { case $rc in 0) # have a list of A's (dealt with MXs above) - exec <$td/dns + exec 3<$td/dns local addr - while read addr; do - probe-addr '' $addr + while read <&3 addr; do + probe-addr 'NONE' $addr done record-success dns return @@ -176,24 +213,174 @@ probe-domain () { no_args () { case $1 in 0) return ;; - *) fail + *) fail "no arguments to $mode allowed" ;; + esac +} -mode_all () { +acquire_lock () { + local lock_mode="$1" + if [ x"$WEBSTUMP_PROBE_LOCK" = x"$lockfile" ]; then return; fi + WEBSTUMP_PROBE_LOCK=$lockfile \ + exec with-lock-ex $lock_mode "$lockfile" "$0" "$mode" "$@" +} + +maybe-report () { + local outcome=$1 + + if $found_to_report; then return; fi + if ! [ -e "$attempt/$outcome" ]; then return; fi + found_to_report=true + + read <"$attempt/$outcome" message + + local reported + if [ -e "$attempt/reported" ]; then + read <"$attempt/reported" reported + fi + if [ "x$outcome" = "x$reported" ]; then return; fi + + if [ x"$outcome" = x"ok" ] && [ x"$reported" = x ]; then + echo ok >"$attempt/reported" + return + fi + + local info=${attempt##*/} + info=${info//,/ } + + delim=`od -N 50 -An -x -w50 "$email" <>"$email" <>"$email" <>"$email" <>"$email" <>"$email" <>"$email" <>"$email" <"$log" + echo >>"$email" + done + + cat >>"$email" <"$attempt"/reported +} + +mode_report () { + acquire_lock -w "$@" + + local attempt + for attempt in $statedir/*; do + + local now=$(date +%s) + local age=$(stat -c %Y "$attempt") + age=$(( $now - $age )) + + local found_to_report=false + maybe-report ok + maybe-report permfail + maybe-report tempfail + + if ! [ -e $attempt/reported ] && \ + [ $age -gt $PROBE_TIMEOUT ]; then + echo >"$attempt"/timeout \ + "Message did not arrive after ${PROBE_TIMEOUT}s" + fi + + maybe-report timeout + + if [ -e $attempt/reported ] && \ + [ $age -gt $PROBE_EXPIRE ]; then + rm -rf "$attempt" + fi + done +} + +mode_received () { no_args $# - for domain in $MODRELAYS; do - probe $domain + + local hn group id domain mx addr + while read hn group id domain mx addr; do + if [ x"$hn" != x"X-WebSTUMP-Relay-Probe:" ]; then continue; fi + if [ x"$group" != x"$GROUP" ]; then continue; fi + case " $id $domain $mx $addr" in + */*|' '.*) fail "bad syntax" ;; + esac + local td + compute-td "mx=$mx,addr=$addr" + >"$td/ok" ||: + return done } -mode_auto () { +mode_all () { no_args $# - xxx do something to cause sleeping - mode_all + for domain in $MODRELAYS; do + probe-domain $domain + done } -mode_relay () { - relay="$1" - probe "$relay" +mode_domain () { + for domain in "$@"; do + probe-domain $domain + done } mode=$1; shift||: