/* Name: ps.rexx Description: fast arexx tcp port scan Requires: rxsocket.library, rmh.library Usage: ps [toport/N] [TIMEOUT/K/N] [VERBOSE=VER/S] scan ports fromport,...,toport if toport is not given then scan only fromport timeout is the timeout in secs for each group 0 means no timeout - default 120 secs if verbose output info on scanning output *only* open ports no output means no open port */ if ~show("L","rexxsupport.library") then if ~addLib("rexxsupport.library",0,-30) then call err("can't find rexxsupport.library") if ~show("L","rxsocket.library") then if ~addLib("rxsocket.library",0,-30) then call err("can't find rxsocket.library") if ~show("L","rmh.library") then if ~addLib("rmh.library",0,-30) then call err("can't find rmh.library") call pragma("P",5) signal on break_c sin.amirc=left(address(),6)=="AMIRC." sin.ws=0 if ~ReadArgs("HOST/A,FROMPORT=FP/A/N,TOPORT=TP/N,TIMEOUT/K/N,VERBOSE=VER/S,PUBSCREEN/K") then do msg=fault(IoErr(),"ps") call err(msg) end host=parm.0.value f=parm.1.value if parm.2.flag then l=parm.2.value else l=parm.1.value if parm.3.flag then if parm.3.value<0 then call err("ps: bad timeout (must be TIMEOUT>=0)") else sin.tout=parm.3.value else sin.tout=120 sin.ver=parm.4.flag if f<1 | f>65536 | l<1 | l>65535 | f>l then call err("ps: bad ports (must be 0") /*****/ if parm.5.flag then do res=OpenSurface("rexx:ps.wizard","SUR") if res~=0 then call err(GetRxWizString(res)) win.PubScreen=parm.5.value win.title="ps <"host">" f l win.Gads=5 win.ID=1 res=OpenWindow("SUR","WIN") if res~=0 then call err(GetRxWizString(res)) sin.ws=WindowSignal("SUR","WIN") end /*****/ ts=128 sin.sig=2**AllocSignal() set.SigEventMask=sin.sig set.DTableSize=ts call SetSocketBase("SET") sin.AddrFamily="INET" sin.AddrAddr= addr /*****/ call info("Scanning <"host">" f",...,"l "by" ts"...") call time("R") n=l-f+1 i=f do for n%ts call info("A"x"scanning" i",...,"i+ts-1) call scan(i,i+ts-1) i=i+ts end if i<=l then do if sin.ver then call info("A"x"--scanning" i",...,"l"--") call scan(i,l) end e=time("E") if sin.ver then call err("A"x"Done. Scanned" n "port(s) in" e "second(s).") else call err("A"x"Done.") scan: procedure expose sin. parse arg f,l do i=f to l j=i-f if CheckSignal(sin.ws) then call break_c ss=socket("INET","STREAM") if ss<0 then call err("no socket") call IOCtlSocket(ss,"FIONBIO",1) call SetSockOpt(ss,"SOCKET","EVENTMASK","CONNECT ERROR READ WRITE") sin.addrport=i call connect(ss,"SIN") socks.ss=i socks.sel.ss=j sel.read.j=ss sel.ex.j=ss end stop=l-f+1 do while stop~=0 res = WaitSelect("SEL",sin.tout,,or(sin.sig,sin.ws)) if and(sel.signals,sin.ws)~=0 then call break_c if res==0 & and(sel.signals,sin.sig)==0 then do do i=f to l j=i-f ss=sel.read.j if ss>=0 then call CloseSocket(ss) end call info(" timeout") return end ss=GetSocketEvents("EVENTS") do while ss>=0 stop=stop-1 j=socks.sel.ss sel.read.j=-1 sel.ex.j=-1 if events.connect then if sin.ver then if GetServByPort("SERV",socks.ss,"tcp") then call info(serv.ServName "("socks.ss") open") else call info("port" socks.ss "open") else call info(socks.ss) call CloseSocket(ss) ss=GetSocketEvents("EVENTS") end end return info: procedure expose sin. parse arg msg if sin.amirc then do if left(msg,1)=="A"x then parse var msg "A"x msg "ECHO P=" || "1B"x || "b«ps» C=6" msg end else say msg return err: procedure expose sin. parse arg msg call info(msg) if sin.ws~=0 then do call CloseWindow("SUR","WIN") call SnapShot("SUR") call CloseSurface("SUR") end exit break_c: call err("ps: user break")