home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 033 / atcp40de.zip / NETSTAT < prev    next >
Text File  |  1994-10-03  |  13KB  |  360 lines

  1. /* sys:rexxc/rx
  2.  * Hey Emacs! This file is -*- rexx -*-
  3.  *
  4.  *      $Id: netstat,v 4.1 1994/10/03 20:38:11 jraja Exp $
  5.  *
  6.  *      $VER: netstat 4.1 (3.10.94)
  7.  *
  8.  *      Copyright ⌐ 1994 AmiTCP/IP Group, 
  9.  *                       Network Solutions Development Inc.
  10.  *                       All rights reserved.
  11.  */
  12.  
  13. ARG opt args
  14. if left(opt,1)~='-' then do
  15.   args=opt
  16.   opt=''
  17. end
  18.  
  19. args=strip(args)
  20. numeric=0
  21.  
  22. if pos('N',opt)~=0 then numeric=1
  23.  
  24. resolver = 'APIPE:AmiTCP:bin/resolve'
  25. resolved. = ''
  26. services. = ''
  27. ALL = 0
  28. tab = "    "
  29.  
  30. if args = "ALL" then ALL=1 /* All information wanted */
  31.  
  32. options results /* Results from external command wanted */
  33. address AMITCP /* default command host is AMITCP */
  34.  
  35. RESULT = "" /* Set so that it don't get value RESULT */
  36.  
  37. if args = "" | args = "ALL" then do
  38.   /* States of TCP finite state machine */
  39.   state.0 = "CLOSED"
  40.   state.1 = "LISTEN"
  41.   state.2 = "SYN_SENT"
  42.   state.3 = "SYN_RECV"
  43.   state.4 = "ESTABLISHED"
  44.   state.5 = "CLOSE_FIN"
  45.   state.6 = "CLOSED_FIN"
  46.   state.7 = "FINACK_WAIT"
  47.   state.8 = "CLOSED_FINACK"
  48.   state.9 = "CLOSED"
  49.   state.A = "TIME_WAIT"
  50.  
  51.   'QUERY' 'CONNECTIONS' /* Ask information */
  52.  
  53.   /* Print header */
  54.   say "Proto Recv-Q Send-Q  Local Address           Foreign Address        (status)"
  55.  
  56.   rest = result
  57.   do while (rest ~= "")
  58.     /* Parse result string */
  59.     parse upper value rest with pr rq sq la lp fa fp st rest
  60.  
  61.     /* Print only if connection is non-listening or all connections wanted */
  62.     if all = 1 | (st ~= 0 & st ~= 1) then do
  63.       if pr=t then do
  64.     pro = "tcp" /* Protocol */
  65.     sts = state.st /* Name of state */
  66.       end
  67.       else do
  68.     pro = "udp"
  69.     sts = "" /* udp is stateless */
  70.       end
  71.  
  72.       say left(pro, 5) right(x2d(rq), 6) right(x2d(sq), 6),
  73.     left("  " || GetSocketName(la, lp, pro), 23),
  74.       left("  " || GetSocketName(fa, fp, pro), 23) "" sts
  75.     end
  76.   
  77.   end /* while */
  78. end /* connections */
  79.  
  80. /* If status wanted */
  81. if left(args,6) = "STATUS" then do
  82.   /* Ask ICMP information */
  83.   'Q' ICMP CHksum ICMP COde ICMP Error ICMP Icmpold ICMP Length ICMP Tooshort ICMP Responses ICMP Shortold
  84.  
  85.   /* Parse ICMP information */
  86.   parse value result with icps_checksum icps_badcode icps_error icps_oldicmp icps_badlen icps_reflect icps_oldshort icps_tooshort .
  87.  
  88.   /* Ask and parse IP information */
  89.   'Q' IP CH IP D IP FC IP FD IP FE IP FO IP FS IP FT IP FW IP H IP LE IP LO IP N IP OD IP OF IP REA IP RED IP TOOSH  IP TOOSM IP TOTAL
  90.   parse value result with ips_badsum ips_delivered ips_cantfragment ips_fragdropped ips_fragmented ips_forward ips_fragments ips_fragtimeout ips_cantforward ips_badhlen ips_badlen ips_localout ips_noproto ips_odropped ips_ofragments ips_reassembed ips_redirectsent ips_tooshort ips_toosmall ips_total .
  91.  
  92.   /* Ask and parse TCP information */
  93.   'Q' TCP Accepts TCP CAttem TCP CDrops TCP CLosed TCP COnnect TCP DElack TCP DRops TCP KADrops TCP KAProbe  TCP KATimeo TCP Persist TCP RACKByte TCP RACKPack TCP RACKToom TCP RAFter TCP RBLate TCP RBYte TCP RChksum TCP RDUPAck TCP RDUPByte TCP RDUPPack TCP ROFfset TCP ROOByte TCP ROOPack TCP RPAck TCP RPDUPByte TCP RPDUPData TCP RPLate TCP RPShort TCP RTOtal TCP RTTupdate TCP RWProbe TCP RWUpdate TCP SAcks TCP SByte TCP SCtrl TCP SEgstimed TCP SPack TCP SREByte TCP SREPack TCP STotal TCP SUrgent TCP SWProbe TCP SWUpdate TCP Timeodrop TCP RExmtt
  94.   parse value result with tcps_accepts tcps_connattempt tcps_conndrops tcps_closed tcps_connects tcps_delack tcps_drops tcps_keepdrops tcps_keepprobe tcps_keeptimeo tcps_persisttimeo tcps_rcvackbyte tcps_rcvackpack tcps_rcvacktoomuch tcps_rcvafterclose tcps_rcvbyteafterwin tcps_rcvbyte tcps_rcvbadsum tcps_rcvdupack tcps_rcvdupbyte tcps_rcvduppack tcps_rcvbadoff tcps_rcvoobyte tcps_rcvoopack tcps_rcvpack tcps_rcvpartdupbyte tcps_rcvpartduppack tcps_rcvpackafterwin tcps_rcvshort tcps_rcvtotal tcps_rttupdated tcps_rcvwinprobe tcps_rcvwinupd tcps_sndacks tcps_sndbyte tcps_sndctrl tcps_segstimed tcps_sndpack tcps_sndrexmitbyte tcps_sndrexmitpack tcps_sndtotal tcps_sndurg tcps_sndprobe tcps_sndwinup tcps_timeoutdrop tcps_rexmttimeo .
  95.  
  96.   /* Ask and parse UDP information */
  97.   'Q' UDP Bcnoport UDP Chksum UDP Fullsoc UDP Headshort UDP Itotal UDP Length UDP Mispcb UDP Noport UDP Ototal
  98.   parse value result with udps_noportbcast udps_badsum udps_fullsock udps_hdrops udps_ipackets udps_badlen udps_pcbcachemiss udps_noport udps_opackets .
  99.  
  100.   /* Ask ICMP history */
  101.   'Q' ICMPHIST
  102.   icmphist = result
  103.  
  104.   say "tcp:"
  105.   say tab || tcps_sndtotal "packets sent"
  106.   say tab || tab || tcps_sndpack "data packets ("||tcps_sndbyte "bytes)"
  107.   say tab || tab || tcps_sndrexmitpack "data packets ("||tcps_sndrexmitbyte "bytes) retransmitted"
  108.   say tab || tab || tcps_sndacks "ack-only packets ("|| tcps_delack "delayed)"
  109.   say tab || tab || tcps_sndurg "URG only packets"
  110.   say tab || tab || tcps_sndprobe "window probe packets"
  111.   say tab || tab || tcps_sndwinup "window update packets"
  112.   say tab || tab || tcps_sndctrl "control packets"
  113.   say tab || tcps_rcvtotal "packets received"
  114.   say tab || tab || tcps_rcvackpack "acks (for" tcps_rcvackbyte "bytes)"
  115.   say tab || tab || tcps_rcvdupack  "duplicate acks"
  116.   say tab || tab || tcps_rcvacktoomuch "acks for unsent data"
  117.   say tab || tab || tcps_rcvpack "packets ("|| tcps_rcvbyte "bytes) received in-sequence"
  118.   say tab || tab || tcps_rcvduppack "completely duplicate packets ("|| tcps_rcvdupbyte "bytes)"
  119.   say tab || tab || tcps_rcvpartduppack "packets with some dup. data ("|| tcps_rcvpartdupbyte "bytes duped)"
  120.   say tab || tab || tcps_rcvoopack "out-of-order packets ("||tcps_rcvoobyte "bytes)"
  121.   say tab || tab || tcps_rcvpackafterwin "packets ("||tcps_rcvbyteafterwin "bytes) of data after window"
  122.   say tab || tab || tcps_rcvwinprobe "window probes"
  123.   say tab || tab || tcps_rcvwinupd "window update packets"
  124.   say tab || tab || tcps_rcvafterclose "packets received after close"
  125.   say tab || tab || tcps_rcvbadsum "discarded for bad checksum"
  126.   say tab || tab || tcps_rcvbadoff "discarded for bad header offset fields"
  127.   say tab || tab || tcps_rcvshort "discarded because packet too short"
  128.   say tab || tcps_connattempt "connection requests"
  129.   say tab || tcps_accepts "connection accepts"
  130.   say tab || tcps_connects "connections established (including accepts)"
  131.   say tab || tcps_closed "connections closed (including" tcps_drops "drops)"
  132.   say tab || tcps_conndrops "embryonic connections dropped"
  133.   say tab || tcps_rttupdated "segments updated rtt (of" tcps_segstimed "attempts)"
  134.   say tab || tcps_rexmttimeo "retransmit timeouts"
  135.   say tab || tab || tcps_timeoutdrop "connections dropped by rexmit timeout"
  136.   say tab || tcps_persisttimeo "persist timeouts"
  137.   say tab || tcps_keeptimeo "keepalive timeouts"
  138.   say tab || tab || tcps_keepprobe "keepalive probes sent"
  139.   say tab || tab || tcps_keepdrops "connections dropped by keepalive"
  140.  
  141.   say "udp:"
  142.   say tab || udps_hdrops "incomplete headers"
  143.   say tab || udps_badlen "bad data length fields"
  144.   say tab || udps_badsum "bad checksums"
  145.  
  146.   say "ip:"
  147.   say tab || ips_total "total packets received"
  148.   say tab || ips_badsum "bad header checksums"
  149.   say tab || ips_tooshort "with size smaller than minimum"
  150.   say tab || ips_toosmall "with data size < data length"
  151.   say tab || ips_badhlen "with header length < data size"
  152.   say tab || ips_badlen "with data length < header length"
  153.   say tab || ips_fragments "fragments received"
  154.   say tab || ips_fragdropped "fragments dropped (dup or out of space)"
  155.   say tab || ips_fragtimeout "fragments dropped after timeout"
  156.   say tab || ips_forward "packets forwarded"
  157.   say tab || ips_cantforward "packets not forwardable"
  158.   say tab || ips_redirectsent "redirects sent"
  159.  
  160.   /* ICMP codes */
  161.   icmph. = "UNKNOWN" /* default */
  162.   icmph.0 = "Echo reply"
  163.   icmph.3 = "Destination unreachable"
  164.   icmph.4 = "Packet lost, slow down"
  165.   icmph.5 = "Shorter route"
  166.   icmph.8 = "Echo service"
  167.   icmph.11 = "Time exceeded"
  168.   icmph.12 = "IP header bad"
  169.   icmph.13 = "Timestamp request"
  170.   icmph.14 = "Timestamp reply"
  171.   icmph.15 = "Information request"
  172.   icmph.16 = "Information reply"
  173.   icmph.17 = "Address mask request"
  174.   icmph.18 = "Address mask reply"
  175.   /* First out, then in statistics */
  176.   say "icmp:"
  177.   do a = 0 to 1
  178.     if a = 0 then do
  179.       say tab || icps_error "calls to icmp_error"
  180.       say tab || icps_oldicmp "errors not generated 'cuz old message was icmp"
  181.       say tab || "Output histogram:"
  182.       end
  183.     else do
  184.       say tab || icps_badcode "messages with bad code fields"
  185.       say tab || icps_tooshort "messages < minimum length"
  186.       say tab || icps_checksum "bad checksums"
  187.       say tab || icps_badlen "messages with bad length"
  188.       say tab || "Input histogram:"
  189.     end
  190.     do b = 0 to 18
  191.       count = subword(icmphist, a*19 + b + 1, 1)
  192.       if count ~= 0 then say tab || tab || count "times" icmph.b
  193.     end 
  194.   end
  195.   say tab || icps_reflect "message responses generated"
  196. end /* end STATUS */
  197.  
  198. /*
  199.  * Dump routing table
  200.  */
  201. if left(args, 5) = "ROUTE" then do
  202.   afamily.1  = "Unix";
  203.   afamily.2  = "Internet Protocols";
  204.   afamily.3  = "Arpanet IMP Addresses";
  205.   afamily.4  = "PUP Protocols";
  206.   afamily.5  = "MIT CHAOS";
  207.   afamily.6  = "XEROX NS ";
  208.   afamily.7  = "ISO Protocols";
  209.   afamily.8  = "ECMA";
  210.   afamily.9  = "Datakit Protocols";
  211.   afamily.10 = "CCITT (X.25) Protocols";
  212.   afamily.11 = "IBM SNA";
  213.   afamily.12 = "DECnet";
  214.   afamily.13 = "DEC Direct Data Link Interface";
  215.   afamily.14 = "LAT";
  216.   afamily.15 = "NSC Hyperchannel";
  217.   afamily.16 = "Apple Talk";
  218.   afamily.17 = "Internal Routing Protocol";
  219.   afamily.18 = "Link layer interface";
  220.   afamily.19 = "eXpress Transfer Protocol";
  221.  
  222.   'QUERY ROUTES ALL' /* Ask information */
  223.  
  224.   oldaf = -1;
  225.   rest = result;
  226.   do while rest ~= ""
  227.     parse value rest with af dest gate flags refs used iface rest
  228.     /* Print address (protocol) family */
  229.     af=x2d(af);
  230.     if af ~= oldaf then do
  231.     /* Print header */
  232.       if af ~= 0 then do 
  233.         say "Routing table for" afamily.af
  234.         say "Destination          Gateway              Flags     Refs     Use  Interface"
  235.       end; else do
  236.     say "Netmasks"
  237.       end
  238.       oldaf = af;
  239.     end
  240.  
  241.     /* Print routes */ 
  242.     if (af == 2) then do
  243.  
  244.       /* Convert addresses to decimal dot notation */
  245.       if (numeric | index(flags, 'H') = 0) then do
  246.         if (dest == "00000000") then do
  247.           desta = "default"
  248.         end; else do
  249.           desta = hex2inet(dest)
  250.         end
  251.         gatea = hex2inet(gate)
  252.       end; else do
  253.     desta = resolve(dest) 
  254.         gatea = resolve(gate)
  255.       end
  256.  
  257.       /* Print route */
  258.       say left(desta, 20) left(gatea, 20) left(flags, 8),
  259.     right(x2d(refs), 4) right(x2d(used), 8) "" iface;
  260.     end 
  261.     else do
  262.       say hex2inet(dest)
  263.     end
  264.   end /* while rest */
  265. end /* ROUTE */
  266.  
  267. exit
  268.  
  269. /*
  270.  * Using the AmiTCP 3.0 'resolve' command, this subroutine tries to convert
  271.  * the ip address into a canonical name of the host.
  272.  * (by Pavel Troller <patrol@k332.feld.cvut.cz>)
  273.  *
  274.  * The resolved names are cached into the "resolved.". If resolving fails,
  275.  * the address is inserted to the cache to prevent resolving the same 
  276.  * address again.
  277.  * (jraja)
  278.  *    
  279.  * Nets and default route are handled by main routine. The error
  280.  * messages are now handled.  The argument should be in hex format.
  281.  * (by ppessi)
  282.  */
  283.  
  284. resolve: procedure expose resolved. resolver 
  285.   parse arg resadr . 
  286.   resname = resolved.resadr
  287.   if resname = '' then do
  288.     /* As x2d is signed this is needed for IP addresses > 128.0.0.0 */ 
  289.     ipaddr = x2d(substr(resadr,1,2)) || "." || x2d(substr(resadr,3,6))
  290.  
  291.     success = open(rfile, resolver || ' ' || ipaddr, 'R')
  292.  
  293.     if (success) then do
  294.       parse value readln(rfile) with keyword bla resnamemaybe .
  295.       call close(rfile)
  296.     end
  297.  
  298.     if (success & keyword = 'HOST') then do 
  299.       resname = resnamemaybe 
  300.     end
  301.     else do
  302.       resname = hex2inet(resadr)
  303.     end
  304.     resolved.resadr = resname
  305.   end
  306.   /*
  307.    * Add the resolved name to cache
  308.    */
  309.   return resname
  310.  
  311. /*
  312.  * Get the socket name (host.service)
  313.  */
  314. GetSocketName: procedure expose resolver services. resolved. numeric
  315.   parse arg address, port, protocol
  316.  
  317.   /* Convert addresses to human readable form */
  318.   if (address = 0) then do 
  319.     hostname = "*";
  320.   end; else if (numeric) then do
  321.     hostname = hex2inet(address);
  322.   end; else do
  323.     hostname = resolve(address);
  324.   end
  325.   
  326.   if (port = 0) then do 
  327.     service = "*";
  328.   end; 
  329.   else if (numeric) then do 
  330.    service = x2d(port);
  331.   end; 
  332.   else do 
  333.     service = services.protocol.port
  334.     if service = '' then do
  335.       service = x2d(port);
  336.       success = open(rfile, resolver||' port '||service||' '||protocol, 'R');
  337.       if (success) then do
  338.         parse value readln(rfile) with keyword servicemaybe .;
  339.         call close(rfile);
  340.       end
  341.       if (success & keyword = 'SERVICE') then do 
  342.         service = servicemaybe;
  343.       end
  344.       /*
  345.        * Add the service name to cache
  346.        */
  347.       services.protocol.port = service;
  348.     end
  349.   end
  350.   return hostname||"."||service;
  351.  
  352. /*
  353.  * Convert Inet address (in hex) into dot notation
  354.  */
  355. hex2inet: procedure
  356.   parse arg haddr .
  357.   inetaddr = x2d(substr(haddr,1,2)) || "." || x2d(substr(haddr,3,2)) ||,
  358.       "." || x2d(substr(haddr,5,2)) || "." || x2d(substr(haddr,7,2))
  359.   return inetaddr
  360.