#!/bin/bash prog="ss" usage () { cat >&2 <<EOF Usage: $prog { -t|--tcp | -x|--unix } [options] [ FILTER ] A fake ss stub that prints items depending on the variables FAKE_NETSTAT_TCP_ESTABLISHED, FAKE_TCP_LISTEN, FAKE_NETSTAT_UNIX_LISTEN, depending on command-line options. Note that -n is ignored. EOF exit 1 } not_supported () { echo "Options not supported in stub: $*" >&2 usage } ############################################################ # parse_filter () { # 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 not_supported "|| in parentheses" fi shift ;; sport) p="${3#:}" ; sports="${sports}${p}|" shift 3 ;; src) ip="${2#\[}" ; ip="${ip%\]}" ; srcs="${srcs}${ip}|" shift 2 ;; *) usage ;; esac done } # 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 () { if $header ; then echo "Recv-Q Send-Q Local Address:Port Peer Address:Port" fi parse_filter $* 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 if [ -z "$FAKE_NETSTAT_TCP_ESTABLISHED_FILE" ] ; then return fi while read src dst ; do if filter_socket "$srcs" "$sports" "$src" ; then echo 0 0 "$src" "$dst" fi done <"$FAKE_NETSTAT_TCP_ESTABLISHED_FILE" } ############################################################ unix_listen () { if $header ; then cat <<EOF Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port" EOF fi parse_filter $* _n=12345 for _s in $FAKE_NETSTAT_UNIX_LISTEN ; do # ss matches Unix domain sockets as either src or # sport. if filter_socket "$srcs" "$sports" "${_s}:" || \ filter_socket "$srcs" "$sports" ":${_s}" ; then printf "u_str LISTEN 0 128 %s %d * 0\n" "$_s" "$_n" _n=$((_n + 1)) fi done } ############################################################ # Defaults. tcp=false unix=false all=false listen=false header=true orig="$*" temp=$(getopt -n "$prog" -o "txnalHh" -l tcp -l unix -l help -- "$@") [ $? -eq 0 ] || usage eval set -- "$temp" while true ; do case "$1" in --tcp|-t) tcp=true ; shift ;; --unix|-x) unix=true ; shift ;; -l) listen=true ; shift ;; -a) all=true ; shift ;; -H) header=false ; shift ;; -n) shift ;; --) shift ; break ;; -h|--help|*) usage ;; esac done $tcp || $unix || not_supported "$*" if $tcp ; then if [ "$1" != "state" -o "$2" != "established" ] || $listen ; then usage fi shift 2 # Yes, lose the quoting so we can do a hacky parsing job ss_tcp_established $* exit fi if $unix ; then if ! $listen ; then not_supported "$orig" fi # Yes, lose the quoting so we can do a hacky parsing job unix_listen $* exit fi