pastebin - collaborative debugging tool
rovema.kpaste.net RSS


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)

  1. #!/usr/bin/ksh93
  2.  
  3. #
  4. # list_active_local_tcp_ports1.ksh - list port numbers of local TCP connections
  5. #
  6. # Written by Roland Mainz <roland.mainz@nrubsig.org>
  7. #
  8.  
  9. #    
  10. # simple netstat -n parser
  11. #    
  12. function netstat_list_connections
  13. {
  14.         set -o nounset
  15.         nameref data=$1
  16.        
  17.         compound out=( typeset stdout stderr ; integer res )
  18.        
  19.         out.stderr="${ { out.stdout="${ LC_ALL='POSIX' PATH='/usr/bin:/bin' netstat -a -n ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
  20.         if (( out.res != 0 )) || [[ ${out.stderr} != '' ]] ; then
  21.                 return 1
  22.         fi
  23.  
  24.         typeset -a data.connections
  25.         typeset l
  26.         integer dci=0 # data.connections array index
  27.  
  28.         while read l ; do
  29.                 leftover="${l/~(Elrx)
  30.                 (?: # non-capturing group
  31.                         #
  32.                         # regex group for tcp,udp
  33.                         #
  34.                         (tcp|tcp6|udp|udp6|raw6)        # Proto
  35.                         [[:space:]]+
  36.                         ([[:digit:]]+)                  # Recv-Q
  37.                         [[:space:]]+
  38.                         ([[:digit:]]+)                  # Send-Q
  39.                         [[:space:]]+
  40.                         ([^[:space:]]+)                 # Local Address
  41.                         [[:space:]]+
  42.                         ([^[:space:]]+)                 # Foreign Address
  43.                         (?:
  44.                                 |
  45.                                 [[:space:]]+
  46.                                 ([^[:space:]]*?)        # State (Optional)
  47.                         )
  48.                 |
  49.                         #
  50.                         # regex for unix
  51.                         #
  52.                         (unix)                          # Proto
  53.                         [[:space:]]+
  54.                         ([[:digit:]]+)                  # RefCnt
  55.                         [[:space:]]+
  56.                         (\[.+?\])                       # Flags
  57.                         [[:space:]]+
  58.                         ([^[:space:]]+)                 # Type
  59.                         [[:space:]]+
  60.                         ([^[:space:]]*?)                # State (optional)
  61.                         [[:space:]]+
  62.                         ([[:digit:]]+)                  # I-Node
  63.                         (?:
  64.                                 |
  65.                                 [[:space:]]+
  66.                                 ([^[:space:]]+)         # Path (optional)
  67.                         )
  68.                 )
  69.                         /X}"
  70.        
  71.                 # If the regex above did not match then .sh.match
  72.                 # remains untouched, so we might see data from the
  73.                 # previous round.
  74.                 # So we check the "leftover" var whether it just
  75.                 # contains the dummy value of "X" to indicate a
  76.                 # successful regex match
  77.                 if [[ "$leftover" == 'X' ]] ; then
  78.                         #print -v .sh.match
  79.                        
  80.                         if [[ "${.sh.match[1]-}" != '' ]] ; then
  81.                                 nameref dcn=data.connections[$dci]
  82.  
  83.                                 typeset dcn.proto="${.sh.match[1]}"
  84.                                 typeset dcn.recv_q="${.sh.match[2]}"
  85.                                 typeset dcn.send_q="${.sh.match[3]}"
  86.                                 typeset dcn.local_address="${.sh.match[4]}"
  87.                                 typeset dcn.foreign_address="${.sh.match[5]}"
  88.                                 typeset dcn.state="${.sh.match[6]}"
  89.                                 ((dci++))
  90.                         elif [[ "${.sh.match[7]-}" != '' ]] ; then
  91.                                 nameref dcn=data.connections[$dci]
  92.  
  93.                                 typeset dcn.proto="${.sh.match[7]}"
  94.                                 typeset dcn.refcnt="${.sh.match[8]}"
  95.                                 typeset dcn.flags="${.sh.match[9]}"
  96.                                 typeset dcn.type="${.sh.match[10]}"
  97.                                 [[ "${.sh.match[11]}" != '' ]] && typeset dcn.state="${.sh.match[11]}"
  98.                                 typeset dcn.inode="${.sh.match[12]}"
  99.                                 [[ "${.sh.match[13]}" != '' ]] && typeset dcn.path="${.sh.match[13]}"
  100.                                 ((dci++))
  101.                         fi
  102.                 else
  103.                         true
  104.                         #printf $"leftover=%q\n" "${leftover}"
  105.                 fi
  106.         done <<<"${out.stdout}"
  107.        
  108.         return 0
  109. }        
  110.  
  111. function netstat_list_active_local_tcp_connections
  112. {
  113.         set -o nounset
  114.         nameref ar=$1
  115.         compound c
  116.         integer port
  117.         integer i
  118.  
  119.         netstat_list_connections c || return 1
  120.         #print -v c
  121.        
  122.         [[ -v ar ]] || integer -a ar
  123.  
  124.         for i in "${!c.connections[@]}" ; do
  125.                 nameref n=c.connections[$i]
  126.                
  127.                 # look for only for TCP connections which match
  128.                 # 127.0.*.* or IPv6 ::1 for localhost
  129.                 # 0.0.0.0 or IPv6 :: for all addresses (e.g. servers)
  130.                 if [[ "${n.proto}" == ~(El)tcp && \
  131.                         "${n.local_address}" == ~(Elr)((127\.0\..+|::1)|(::|0\.0\.0\.0|)):[[:digit:]]+ ]] ; then
  132.  
  133.                         port="${n.local_address##*:}"
  134.                         #printf $"port = %d\n" port
  135.  
  136.                         (( ar[port]=1 ))
  137.                 fi
  138.         done
  139.  
  140.         return 0
  141. }
  142.  
  143. function netstat_find_next_free_local_tcp_port
  144. {
  145.         set -o nounset
  146.         compound c=( integer -a ar )
  147.         nameref ret_free_port=$1
  148.         integer start_port
  149.         integer end_port
  150.         integer i
  151.  
  152.         netstat_list_active_local_tcp_connections c.ar || return 1
  153.  
  154.         #print -v c
  155.  
  156.         (( start_port=$2 ))
  157.         if (( $# > 2 )) ; then
  158.                 (( end_port=$3 ))
  159.         else
  160.                 (( end_port=65535 ))
  161.         fi
  162.  
  163.         for ((i=start_port ; i < end_port ; i++ )) ; do
  164.                 if [[ ! -v c.ar[i] ]] ; then
  165.                         (( ret_free_port=i ))
  166.                         return 0
  167.                 fi
  168.         done
  169.        
  170.         return 1
  171. }
  172.  
  173.  
  174. function main
  175. {
  176.         if (( $# > 0 )) ; then
  177.                 integer port=-1
  178.  
  179.                 print -u1 -f $"# next free TCP port:\n"
  180.                 netstat_find_next_free_local_tcp_port port "$@" || return 1
  181.                 print -f $"%d\n" port
  182.         else
  183.                 set -o nounset
  184.                 compound c=( integer -a ar )
  185.  
  186.                 print -u1 -f $"# list of open local TCP ports:\n"
  187.  
  188.                 netstat_list_active_local_tcp_connections c.ar || return 1
  189.                 #print -v c
  190.  
  191.                 (( ${#c.ar[@]} > 0 )) && printf $"%d\n" "${!c.ar[@]}"
  192.         fi
  193.  
  194.         return 0
  195. }
  196.  
  197. # main entry point
  198. main "$@"
  199. exit $?
  200. # EOF.

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at