1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

ctdb-scripts: Use ss instead of netstat for finding TCP connections

ss with a filter is much faster than post-processing output from
netstat.  CTDB already has a hard dependency on iproute2 for IP
address handling, so depending on ss is no big deal.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
This commit is contained in:
Martin Schwenke 2015-08-27 13:22:49 +10:00 committed by Amitay Isaacs
parent 4a658440e1
commit 04fe9e2074
2 changed files with 101 additions and 10 deletions

View File

@ -531,11 +531,7 @@ get_tcp_connections_for_ip ()
{
_ip="$1"
netstat -tn | awk -v ip=$_ip \
'index($1, "tcp") == 1 && \
(index($4, ip ":") == 1 || index($4, "::ffff:" ip ":") == 1) \
&& $6 == "ESTABLISHED" \
{print $4" "$5}'
ss -tn state established "src [$_ip]" | awk 'NR > 1 {print $3, $4}'
}
########################################################
@ -1183,17 +1179,24 @@ update_tickles ()
# What public IPs do I hold?
_ips=$(ctdb -X ip | awk -F'|' -v pnn=$pnn '$3 == pnn {print $2}')
# IPs as a regexp choice
_ipschoice="($(echo $_ips | sed -e 's/ /|/g' -e 's/\./\\\\./g'))"
# IPs and port as ss filters
_ip_filter=""
for _ip in $_ips ; do
_ip_filter="${_ip_filter}${_ip_filter:+ || }src [${_ip}]"
done
_port_filter="sport == :${_port}"
# Record connections to our public IPs in a temporary file.
# This temporary file is in CTDB's private state directory and
# $$ is used to avoid a very rare race involving CTDB's script
# debugging. No security issue, nothing to see here...
_my_connections="${tickledir}/${_port}.connections.$$"
netstat -tn |
awk -v destpat="^${_ipschoice}:${_port}\$" \
'$1 == "tcp" && $6 == "ESTABLISHED" && $4 ~ destpat {print $5, $4}' |
# Parentheses are needed around the filters for precedence but
# the parentheses can't be empty!
ss -tn state established \
"${_ip_filter:+( ${_ip_filter} )}" \
"${_port_filter:+( ${_port_filter} )}" |
awk 'NR > 1 {print $4, $3}' |
sort >"$_my_connections"
# Record our current tickles in a temporary file

View File

@ -0,0 +1,88 @@
#!/bin/bash
prog="ss"
usage ()
{
cat >&2 <<EOF
Usage: $prog -tn state established [ '(' ip-filter ')' ] [ '(' port-filter ')' ]
A fake ss stub that prints items depending on the variables
FAKE_NETSTAT_TCP_ESTABLISHED and FAKE_NETSTAT_TCP_ESTABLISHED_FILE.
Note that "-tn state established" must be given.
EOF
exit 1
}
if [ "$1" != "-tn" -o "$2" != "state" -o "$3" != "established" ] ; then
usage
fi
shift 3
# Check if socket has matches in both ok_ips and ok_ports
filter_socket ()
{
ok_ips="$1"
ok_ports="$2"
socket="$3"
ip="${socket%:*}"
port="${socket##*:}"
if [ "$ok_ports" != "|" -a "${ok_ports#*|${port}|}" = "$ok_ports" ] ; then
return 1
fi
if [ "$ok_ips" != "|" -a "${ok_ips#*|${ip}|}" = "$ok_ips" ] ; then
return 1
fi
return 0
}
ss_tcp_established ()
{
echo "Recv-Q Send-Q Local Address:Port Peer Address:Port"
# Very limited implementation:
# We only expect to find || inside parentheses
# We don't expect to see && - it is implied by juxtaposition
# Operator for port comparison is ignored and assumed to be ==
# Build lists of source ports and source IP addresses where each
# entry is surrounded by '|' characters. These lists can be
# easily "searched" using the POSIX prefix and suffix removal
# operators.
in_parens=false
sports="|"
srcs="|"
while [ -n "$1" ] ; do
case "$1" in
\() in_parens=true ; shift ;;
\)) in_parens=false ; shift ;;
\|\|) if ! $in_parens ; then usage ; fi ; shift ;;
sport) p="${3#:}" ; sports="${sports}${p}|" ; shift 3 ;;
src) ip="${2#\[}" ; ip="${ip%\]}" ; srcs="${srcs}${ip}|" ; shift 2 ;;
*) usage ;;
esac
done
for i in $FAKE_NETSTAT_TCP_ESTABLISHED ; do
src="${i%|*}"
dst="${i#*|}"
if filter_socket "$srcs" "$sports" "$src" ; then
echo 0 0 "$src" "$dst"
fi
done
while read src dst ; do
if filter_socket "$srcs" "$sports" "$src" ; then
echo 0 0 "$src" "$dst"
fi
done <"$FAKE_NETSTAT_TCP_ESTABLISHED_FILE"
}
# Yes, lose the quoting so we can do a hacky parsing job
ss_tcp_established $*