chiark / gitweb /
6c78c62bde0e14cc6ad40d8b04513ce5969bf072
[modbot-mtm.git] / probes / modrelays-probe
1 #!/bin/bash
2
3 set -e
4
5 . settings
6
7 id=$(date +%s)_$$
8
9 fail () {
10         printf >&2 "%s\n" "modrelays-probe: error: $1"
11         exit 16
12 }
13
14 record-probing () {
15         # implicitly uses newsgroup, id, domain
16         # caller must "local td", which will be set
17         local probeid=$1
18
19         probeid="$domain,${probeid//[^-=.,_0-9A-Za-z]/%/},$id"
20         case $probeid in
21         .*|*/*) fail "yikes, sanitisation bug!" ;;
22         esac
23
24         td="probes/probes/$probeid"
25         mkdir -p $td
26 }
27
28 record-outcome () {
29         local probeid=$1
30         local outcome=$2
31         local message=$3
32         local td
33         record-probing "$probeid"
34         printf "%s\n" >"$td"/"$outcome" "$message"
35 }
36
37 record-success () { record-outcome "$1" ok ''; }
38 record-tempfail () { record-outcome "$1" tempfail "$2"; }
39 record-permfail () { record-outcome "$1" permfail "$2"; }
40
41 probe-addr () {
42         local mx=$1
43         local addr=$2
44
45         local td
46         record-probing "mx=$mx,addr=$addr"
47
48         set +e
49         swaks   --to "${GROUP//./-/}@$domain" \
50                 --server $addr \
51                 --tls-optional-strict \
52                 --header 'Subject: test modrelays probe test' \
53                 --header \
54         "X-WebSTUMP-Relay-Probe: $GROUP $id $domain $mx $addr" \
55                 -n >$td/swaks.log 2>$td/swaks.err
56         rc=$?
57         set -e
58
59         case $rc in
60         0) return ;; # record-success done by receiver
61         esac
62         local permfail=''
63
64         local rhs
65         local prefix
66         local expect_no_5xx='initial connection'
67         exec <$td/swaks.log
68         while read prefix rhs; do
69                 case "$prefix" in
70                 '<'*)
71                         case "$rhs" in
72                         5*)
73                                 if [ "x$expect_no_5xx" != x ] && \
74                                    [ "x$permfail" = x ]; then
75                                         permfail="$rhs ($expect_no_5xx)"
76                                 fi
77                                 ;;
78                         esac
79                         ;;
80                 *'>')
81                         case "$rhs" in
82                         EHLO*|STARTTLS*) expect_no_5xx='' ;;
83                         *) expect_no_5xx="after $rhs" ;;
84                         esac
85                         ;;
86                 *)
87                 esac
88         done
89
90         if [ "x$permfail" = x ]; then
91                 record-tempfail "mx=$mx,addr=$addr" "see swaks.log / swaks.err"
92         else
93                 record-permfail "mx=$mx,addr=$addr" "$permfail"
94         fi
95 }
96
97 probe-domain () {
98         local domain=$1
99         local td
100         record-probing dns
101         
102         set +e
103         adnshost -Fi -Tn +Do +Dt -t mx $domain >$td/dns
104         rc=$?
105         set -e
106
107         case $rc in
108         0)
109                 # have a list of MX's
110                 exec <$td/dns
111                 local pref
112                 local mx
113                 local statustype
114                 local rhs
115                 while read pref mx statustype statustypenum rhs; do
116                         case $statustypenum in
117                         0)
118                                 # have a list of relays
119                                 case $rhs in
120                                 *" ( "*")") ;;
121                                 *)
122                                         record-permfail "mx=$mx" \
123                                                 "dns format $rhs"
124                                         continue
125                                         ;;
126                                 esac
127                                 rhs=${rhs##* (}
128                                 rhs=${rhs% )}
129                                 local addr
130                                 for addr in $rhs; do
131                                         case $addr in
132                                         INET|INET6) continue ;;
133                                         esac
134                                         probe-addr $mx $addr
135                                 done
136                                 ;;
137                         [123])
138                                 # temporary errors
139                                 record-tempfail "mx=$mx" \
140                                         "dns $rc $statustype $rhs"
141                                 ;;
142                         *)
143                                 # yikes
144                                 record-permfail "mx=$mx" \
145                                         "dns $rc $statustype $rhs"
146                                 ;;
147                         esac
148                 done
149                 record-success dns
150                 return
151                 ;;
152         6)
153                 # permfail, try A
154                 set +e
155                 adnshost -Fi -Tn +Do +Dt -t a $domain >$td/dns
156                 rc=$?
157                 set -e
158                 ;;
159         esac
160
161         case $rc in
162         0)
163                 # have a list of A's (dealt with MXs above)
164                 exec <$td/dns
165                 local addr
166                 while read addr; do
167                         probe-addr 'NONE' $addr
168                 done
169                 record-success dns
170                 return
171                 ;;
172         [123])
173                 local emsg
174                 read <$td/dns emsg
175                 record-tempfail dns "dns <no-mx> $emsg"
176                 ;;
177         *)
178                 local emsg
179                 read <$td/dns emsg
180                 record-permfail dns "dns <no-mx> $emsg"
181                 ;;
182         esac
183 }
184
185 no_args () {
186         case $1 in
187         0) return ;;
188         *) fail "no arguments to $mode allowed" ;;
189         esac
190 }
191
192 mode_all () {
193         no_args $#
194         for domain in $MODRELAYS; do
195                 probe-domain $domain
196         done
197 }
198
199 mode_auto () {
200         no_args $#
201         xxx do something to cause sleeping
202         mode_all
203 }
204
205 mode_domain () {
206         for domain in "$@"; do
207                 probe-domain $domain
208         done
209 }
210
211 mode=$1; shift||:
212
213 "mode_$mode" "$@"