- #!/usr/bin/ksh93
- #
- # list_active_local_tcp_ports1.ksh - list port numbers of local TCP connections
- #
- # Written by Roland Mainz <roland.mainz@nrubsig.org>
- #
- #
- # simple netstat -n parser
- #
- function netstat_list_connections
- {
- set -o nounset
- nameref data=$1
- compound out=( typeset stdout stderr ; integer res )
- out.stderr="${ { out.stdout="${ LC_ALL='POSIX' PATH='/usr/bin:/bin' netstat -a -n ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
- if (( out.res != 0 )) || [[ ${out.stderr} != '' ]] ; then
- return 1
- fi
- typeset -a data.connections
- typeset l
- integer dci=0 # data.connections array index
- while read l ; do
- leftover="${l/~(Elrx)
- (?: # non-capturing group
- #
- # regex group for tcp,udp
- #
- (tcp|tcp6|udp|udp6|raw6) # Proto
- [[:space:]]+
- ([[:digit:]]+) # Recv-Q
- [[:space:]]+
- ([[:digit:]]+) # Send-Q
- [[:space:]]+
- ([^[:space:]]+) # Local Address
- [[:space:]]+
- ([^[:space:]]+) # Foreign Address
- (?:
- |
- [[:space:]]+
- ([^[:space:]]*?) # State (Optional)
- )
- |
- #
- # regex for unix
- #
- (unix) # Proto
- [[:space:]]+
- ([[:digit:]]+) # RefCnt
- [[:space:]]+
- (\[.+?\]) # Flags
- [[:space:]]+
- ([^[:space:]]+) # Type
- [[:space:]]+
- ([^[:space:]]*?) # State (optional)
- [[:space:]]+
- ([[:digit:]]+) # I-Node
- (?:
- |
- [[:space:]]+
- ([^[:space:]]+) # Path (optional)
- )
- )
- /X}"
- # If the regex above did not match then .sh.match
- # remains untouched, so we might see data from the
- # previous round.
- # So we check the "leftover" var whether it just
- # contains the dummy value of "X" to indicate a
- # successful regex match
- if [[ "$leftover" == 'X' ]] ; then
- #print -v .sh.match
- if [[ "${.sh.match[1]-}" != '' ]] ; then
- nameref dcn=data.connections[$dci]
- typeset dcn.proto="${.sh.match[1]}"
- typeset dcn.recv_q="${.sh.match[2]}"
- typeset dcn.send_q="${.sh.match[3]}"
- typeset dcn.local_address="${.sh.match[4]}"
- typeset dcn.foreign_address="${.sh.match[5]}"
- typeset dcn.state="${.sh.match[6]}"
- ((dci++))
- elif [[ "${.sh.match[7]-}" != '' ]] ; then
- nameref dcn=data.connections[$dci]
- typeset dcn.proto="${.sh.match[7]}"
- typeset dcn.refcnt="${.sh.match[8]}"
- typeset dcn.flags="${.sh.match[9]}"
- typeset dcn.type="${.sh.match[10]}"
- [[ "${.sh.match[11]}" != '' ]] && typeset dcn.state="${.sh.match[11]}"
- typeset dcn.inode="${.sh.match[12]}"
- [[ "${.sh.match[13]}" != '' ]] && typeset dcn.path="${.sh.match[13]}"
- ((dci++))
- fi
- else
- true
- #printf $"leftover=%q\n" "${leftover}"
- fi
- done <<<"${out.stdout}"
- return 0
- }
- function netstat_list_active_local_tcp_connections
- {
- set -o nounset
- nameref ar=$1
- compound c
- integer port
- integer i
- netstat_list_connections c || return 1
- #print -v c
- [[ -v ar ]] || integer -a ar
- for i in "${!c.connections[@]}" ; do
- nameref n=c.connections[$i]
- # look for only for TCP connections which match
- # 127.0.*.* or IPv6 ::1 for localhost
- # 0.0.0.0 or IPv6 :: for all addresses (e.g. servers)
- if [[ "${n.proto}" == ~(El)tcp && \
- "${n.local_address}" == ~(Elr)((127\.0\..+|::1)|(::|0\.0\.0\.0|)):[[:digit:]]+ ]] ; then
- port="${n.local_address##*:}"
- #printf $"port = %d\n" port
- (( ar[port]=1 ))
- fi
- done
- return 0
- }
- function netstat_find_next_free_local_tcp_port
- {
- set -o nounset
- compound c=( integer -a ar )
- nameref ret_free_port=$1
- integer start_port
- integer end_port
- integer i
- netstat_list_active_local_tcp_connections c.ar || return 1
- #print -v c
- (( start_port=$2 ))
- if (( $# > 2 )) ; then
- (( end_port=$3 ))
- else
- (( end_port=65535 ))
- fi
- for ((i=start_port ; i < end_port ; i++ )) ; do
- if [[ ! -v c.ar[i] ]] ; then
- (( ret_free_port=i ))
- return 0
- fi
- done
- return 1
- }
- function main
- {
- if (( $# > 0 )) ; then
- integer port=-1
- print -u1 -f $"# next free TCP port:\n"
- netstat_find_next_free_local_tcp_port port "$@" || return 1
- print -f $"%d\n" port
- else
- set -o nounset
- compound c=( integer -a ar )
- print -u1 -f $"# list of open local TCP ports:\n"
- netstat_list_active_local_tcp_connections c.ar || return 1
- #print -v c
- (( ${#c.ar[@]} > 0 )) && printf $"%d\n" "${!c.ar[@]}"
- fi
- return 0
- }
- # main entry point
- main "$@"
- exit $?
- # EOF.
list_active_local_tcp_ports1.ksh - list port numbers of local TCP connections
Posted by Anonymous on Mon 27th Feb 2023 13:57
raw | new post
modification of post by Anonymous (view diff)
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.