chiark / gitweb /
modrelays-probe: wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 10 Oct 2017 13:35:34 +0000 (14:35 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 10 Oct 2017 13:35:34 +0000 (14:35 +0100)
probes/modrelays-probe [new file with mode: 0755]

diff --git a/probes/modrelays-probe b/probes/modrelays-probe
new file mode 100755 (executable)
index 0000000..1c4ead4
--- /dev/null
@@ -0,0 +1,201 @@
+#!/bin/bash
+
+set -e
+
+id=$(date +%s)_$$
+
+fail () {
+       printf >&2 "%s\n" "modrelays-probe: error: $1"
+       exit 16
+}
+
+record-probing () {
+       # implicitly uses newsgroup, id, domain
+       # prints working dir filename
+       local probeid=$1
+
+       probeid=${probeid//[^=-.,_0-9A-Za-z]/%/}
+       case $probeid in
+       .*|*/*) fail "yikes, sanitisation bug!" ;;
+       esac
+
+       local newtd="monitoring/modrelays.probes/$probeid"
+       mkdir -p $newtd
+       printf "%s" $newtd
+}
+
+record-outcome () {
+       local probeid=$1
+       local outcome=$2
+       local message=$3
+       local td=`record-probing "$probeid"`
+       printf "%s\n" >"$td"/"$outcome"
+}
+
+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"`
+
+       set +e
+       swaks   --to "${GROUP//./-/}@$domain" \
+               --server $addr \
+               --tls-optional-strict \
+               --header 'Subject: test modrelays probe test' \
+               --header \
+       "X-WebSTUMP-Relay-Probe: $GROUP $id $domain $mx $addr" \
+               -n >$td/swaks.log 2>$td/swaks.err
+       rc=$?
+       set -e
+
+       case $rc in
+       0) return ;; # record-success done by receiver
+       esac
+       local permfail=''
+
+       local rhs
+       local prefix
+       local expect_no_5xx='initial connection'
+       while read <$td/swaks.log 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)" ;;
+                               fi
+                               ;;
+                       esac
+                       ;;
+               *'>')
+                       case "$rhs" in
+                       EHLO*|STARTTLS*) expect_no_5xx='' ;;
+                       *) expect_no_5xx="after $rhs" ;;
+                       esac
+                       ;;
+               *)
+       done
+
+       if [ "x$permfail" = x ]; then
+               record-tempfail "mx=$mx,addr=$addr" "see swaks.log / swaks.err"
+       else
+               record-permfail "mx=$mx,addr=$addr" "$permfail"
+       fi
+}
+
+probe-domain () {
+       local domain=$1
+       local td=`record-probing dns`
+       
+       set +e
+       adnshost -Fi -Tn +Do +Dt -t mx $domain >$td/dns
+       rc=$?
+       set -e
+
+       case $rc in
+       0)
+               # have a list of MX's
+               exec <$td/dns
+               local pref
+               local mx
+               local statustype
+               local rhs
+               while read pref mx statustype rhs; do
+                       case $statustype in
+                       0)
+                               # have a list of relays
+                               case $rhs in
+                               *" ( "*")") ;;
+                               *)
+                                       record-permfail "mx=$mx" \
+                                               "dns format $rhs"
+                                       continue
+                               ;;
+                               rhs=${rhs%%* (}
+                               rhs=${rhs# )}
+                               local addr
+                               for addr in $rhs; do
+                                       case $addr in
+                                       INET|INET6) continue ;;
+                                       esac
+                                       probe-addr $mx $addr
+                               done
+                               ;;
+                       [123])
+                               # temporary errors
+                               record-tempfail "mx=$mx" "dns $rc $rhs"
+                               ;;
+                       *)
+                               # yikes
+                               record-permfail "mx=$mx" "dns $rc $rhs"
+                               ;;
+                       esac
+               done
+               record-success dns
+               return
+               ;;
+       6)
+               permfail, try A
+               set +e
+               adnshost -Fi -Tn +Do +Dt -t a $domain >$td
+               rc=$?
+               set -e
+               ;;
+       esac
+
+       case $rc in
+       0)
+               # have a list of A's (dealt with MXs above)
+               exec <$td/dns
+               local addr
+               while read addr; do
+                       probe-addr '<no-mx>' $addr
+               done
+               record-success dns
+               return
+               ;;
+       [123])
+               local emsg
+               read <$td/dns emsg
+               record-tempfail dns "dns <no-mx> $emsg"
+               ;;
+       *)
+               local emsg
+               read <$td/dns emsg
+               record-permfail dns "dns <no-mx> $emsg"
+               ;;
+       esac
+}
+
+no_args () {
+       case $1 in
+       0) return ;;
+       *) fail
+
+mode_all () {
+       no_args $#
+       for domain in $MODRELAYS; do
+               probe $domain
+       done
+}
+
+mode_auto () {
+       no_args $#
+       xxx do something to cause sleeping
+       mode_all
+}
+
+mode_relay () {
+       relay="$1"
+       probe "$relay"
+}
+
+mode=$1; shift||:
+
+"mode_$mode" "$@"