ctdb-tests: Make tcpdump output more verbose
[Samba.git] / ctdb / tests / complex / scripts / local.bash
blob9c41af289b2479e6b40534a40708384677be2a27
1 # Hey Emacs, this is a -*- shell-script -*- !!! :-)
3 # Thanks/blame to Stephen Rothwell for suggesting that this can be
4 # done in the shell. ;-)
5 ipv6_to_hex ()
7 local addr="$1"
9 # Replace "::" by something special.
10 local foo="${addr/::/:@:}"
12 # Join the groups of digits together, 0-padding each group of
13 # digits out to 4 digits, and count the number of (non-@) groups
14 local out=""
15 local count=0
16 local i
17 for i in $(IFS=":" ; echo $foo ) ; do
18 if [ "$i" = "@" ] ; then
19 out="${out}@"
20 else
21 out="${out}$(printf '%04x' 0x${i})"
22 count=$(($count + 4))
24 done
26 # Replace '@' with correct number of zeroes
27 local zeroes=$(printf "%0$((32 - $count))x" 0)
28 echo "${out/@/${zeroes}}"
31 #######################################
33 get_src_socket ()
35 local proto="$1"
36 local dst_socket="$2"
37 local pid="$3"
38 local prog="$4"
40 local pat="^${proto}6?[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+${dst_socket//./\\.}[[:space:]]+ESTABLISHED[[:space:]]+${pid}/${prog}[[:space:]]*\$"
41 out=$(netstat -tanp |
42 egrep "$pat" |
43 awk '{ print $4 }')
45 [ -n "$out" ]
48 wait_until_get_src_socket ()
50 local proto="$1"
51 local dst_socket="$2"
52 local pid="$3"
53 local prog="$4"
55 echo "Waiting for ${prog} to establish connection to ${dst_socket}..."
57 wait_until 5 get_src_socket "$@"
60 #######################################
62 check_tickles ()
64 local node="$1"
65 local test_ip="$2"
66 local test_port="$3"
67 local src_socket="$4"
68 try_command_on_node $node ctdb gettickles $test_ip $test_port
69 # SRC: 10.0.2.45:49091 DST: 10.0.2.143:445
70 [ "${out/SRC: ${src_socket} /}" != "$out" ]
73 check_tickles_all ()
75 local numnodes="$1"
76 local test_ip="$2"
77 local test_port="$3"
78 local src_socket="$4"
80 try_command_on_node all ctdb gettickles $test_ip $test_port
81 # SRC: 10.0.2.45:49091 DST: 10.0.2.143:445
82 local t="${src_socket//./\\.}"
83 local count=$(grep -E -c "SRC: ${t} " <<<"$out" || true)
84 [ $count -eq $numnodes ]
89 #######################################
91 # filename will be in $tcpdump_filename, pid in $tcpdump_pid
92 tcpdump_start ()
94 tcpdump_filter="$1" # global
96 echo "Running tcpdump..."
97 tcpdump_filename=$(mktemp)
98 ctdb_test_exit_hook_add "rm -f $tcpdump_filename"
100 # The only way of being sure that tcpdump is listening is to send
101 # some packets that it will see. So we use dummy pings - the -U
102 # option to tcpdump ensures that packets are flushed to the file
103 # as they are captured.
104 local dummy_addr="127.3.2.1"
105 local dummy="icmp and dst host ${dummy_addr} and icmp[icmptype] == icmp-echo"
106 tcpdump -n -p -s 0 -e -U -w $tcpdump_filename -i any "($tcpdump_filter) or ($dummy)" &
107 ctdb_test_exit_hook_add "kill $! >/dev/null 2>&1"
109 echo "Waiting for tcpdump output file to be ready..."
110 ping -q "$dummy_addr" >/dev/null 2>&1 &
111 ctdb_test_exit_hook_add "kill $! >/dev/null 2>&1"
113 tcpdump_listen_for_dummy ()
115 tcpdump -n -r $tcpdump_filename -c 1 "$dummy" >/dev/null 2>&1
118 wait_until 10 tcpdump_listen_for_dummy
121 # By default, wait for 1 matching packet.
122 tcpdump_wait ()
124 local count="${1:-1}"
125 local filter="${2:-${tcpdump_filter}}"
127 tcpdump_check ()
129 local found=$(tcpdump -n -r $tcpdump_filename "$filter" 2>/dev/null | wc -l)
130 [ $found -ge $count ]
133 echo "Waiting for tcpdump to capture some packets..."
134 if ! wait_until 30 tcpdump_check ; then
135 echo "DEBUG AT $(date '+%F %T'):"
136 local i
137 for i in "onnode -q 0 $CTDB status" "netstat -tanp" "tcpdump -n -e -r $tcpdump_filename" ; do
138 echo "$i"
139 $i || true
140 done
141 return 1
145 tcpdump_show ()
147 local filter="${1:-${tcpdump_filter}}"
149 tcpdump -n -e -vv -XX -r $tcpdump_filename "$filter" 2>/dev/null
152 tcp4tickle_sniff_start ()
154 local src="$1"
155 local dst="$2"
157 local in="src host ${dst%:*} and tcp src port ${dst##*:} and dst host ${src%:*} and tcp dst port ${src##*:}"
158 local out="src host ${src%:*} and tcp src port ${src##*:} and dst host ${dst%:*} and tcp dst port ${dst##*:}"
159 local tickle_ack="${in} and (tcp[tcpflags] & tcp-ack != 0) and (tcp[14:2] == 1234)" # win == 1234
160 local ack_ack="${out} and (tcp[tcpflags] & tcp-ack != 0)"
161 tcptickle_reset="${in} and tcp[tcpflags] & tcp-rst != 0"
162 local filter="(${tickle_ack}) or (${ack_ack}) or (${tcptickle_reset})"
164 tcpdump_start "$filter"
167 # tcp[] does not work for IPv6 (in some versions of tcpdump)
168 tcp6tickle_sniff_start ()
170 local src="$1"
171 local dst="$2"
173 local in="src host ${dst%:*} and tcp src port ${dst##*:} and dst host ${src%:*} and tcp dst port ${src##*:}"
174 local out="src host ${src%:*} and tcp src port ${src##*:} and dst host ${dst%:*} and tcp dst port ${dst##*:}"
175 local tickle_ack="${in} and (ip6[53] & tcp-ack != 0) and (ip6[54:2] == 1234)" # win == 1234
176 local ack_ack="${out} and (ip6[53] & tcp-ack != 0)"
177 tcptickle_reset="${in} and ip6[53] & tcp-rst != 0"
178 local filter="(${tickle_ack}) or (${ack_ack}) or (${tcptickle_reset})"
180 tcpdump_start "$filter"
183 tcptickle_sniff_start ()
185 local src="$1"
186 local dst="$2"
188 case "$dst" in
189 *:*) tcp6tickle_sniff_start "$src" "$dst" ;;
190 *) tcp4tickle_sniff_start "$src" "$dst" ;;
191 esac
194 tcptickle_sniff_wait_show ()
196 tcpdump_wait 1 "$tcptickle_reset"
198 echo "GOOD: here are some TCP tickle packets:"
199 tcpdump_show
202 gratarp4_sniff_start ()
204 tcpdump_start "arp host ${test_ip}"
207 gratarp6_sniff_start ()
209 local neighbor_advertisement="icmp6 and ip6[40] == 136"
210 local hex=$(ipv6_to_hex "$test_ip")
211 local match_target="ip6[48:4] == 0x${hex:0:8} and ip6[52:4] == 0x${hex:8:8} and ip6[56:4] == 0x${hex:16:8} and ip6[60:4] == 0x${hex:24:8}"
213 tcpdump_start "${neighbor_advertisement} and ${match_target}"
216 gratarp_sniff_start ()
218 case "$test_ip" in
219 *:*) gratarp6_sniff_start ;;
220 *) gratarp4_sniff_start ;;
221 esac
224 gratarp_sniff_wait_show ()
226 tcpdump_wait 2
228 echo "GOOD: this should be the some gratuitous ARPs:"
229 tcpdump_show
233 ctdb_test_check_real_cluster ()
235 [ -z "$TEST_LOCAL_DAEMONS" ] || \
236 die "ERROR: This test must be run against a real/virtual cluster, not local daemons."
238 local h=$(hostname)
240 local i
241 for i in $(onnode -q all hostname) ; do
242 [ "$h" != "$i" ] || \
243 die "ERROR: This test must not be run from a cluster node."
244 done
247 ping_wrapper ()
249 case "$*" in
250 *:*) ping6 "$@" ;;
251 *) ping "$@" ;;
252 esac