I thought I would post it anyway.
Code: Select all
; Simple ping for linux (in pure basic.)
; Alban Read. 2005.
; beware that the time in milliseconds does not seem accurate
#AF_INET=2
#SOCK_RAW=3
#EPERM =1
#ICMP_ECHO=8
#SOL_SOCKET=1
#F_VERBOSE=$100
#IP_HEADER_LEN=20
; fd_set management
#FD_SET_SIZE= 128 ; bytes
#NFD_BITS = 32
Procedure.l FD_ISSET( n.l, fd_set.l )
wordPtr= (fd_set+(4*(n/#NFD_BITS)))
ProcedureReturn (PeekL(wordPtr) & (1 << ((n) % #NFD_BITS)))
EndProcedure
;
Procedure FD_SET( n.l, fd_set.l )
wordPtr= (fd_set+(4*(n/#NFD_BITS)))
PokeL( wordPtr, PeekL( wordPtr) | (1 << ((n) % #NFD_BITS)))
EndProcedure
;
Procedure FD_CLR( n.l, fd_set.l )
wordPtr= (fd_set+(4*(n/#NFD_BITS)))
PokeL( wordPtr, PeekL( wordPtr) & (~(1 << ((n) % #NFD_BITS))))
EndProcedure
;
Procedure FD_ZERO( fd_set.l)
For i=0 To 28 Step 4
PokeL(fd_set,0)
Next i
EndProcedure
Global sequence.w
Global replyIP.l
Procedure.w inverted_checksum( buffer.l, count.l)
i.l=0
sum.l=0
For i=0 To count Step 2
sum = sum + (PeekW( buffer+i) & $ffff)
Next i
; should add odd size check.
While sum > $ffff
sum = (sum >> 16) + ( sum & $ffff)
Wend
sum = ( (~sum) & $ffff)
ProcedureReturn sum
EndProcedure
Procedure.l sendPing( s.l, arg1$, string.s)
; resolve ip address or name.
; this can take a long while to timeout.
;
ip.l=inet_addr_(arg1$)
If ip.l=-1
hp.l = gethostbyname_( arg1$)
If hp.l>0
fullname.s = PeekS(PeekL(hp))
ip.l=(PeekL(PeekL(PeekL(hp+16))))
Else
; PrintN("host name unknown")
pingResult.l=0
ProcedureReturn pingResult
EndIf
EndIf
; --------------------------------------------------------------
; set up destination address
; struct sockaddr_in {
; sa_family_t sin_family; /* address family: AF_INET */
; u_int16_t sin_port; /* port in network byte order*/
; struct in_addr sin_addr; /* internet address */
; dont forget the unused.b[8] as THEY DO MATTER.
; };
lendata.l = Len( string)
whereTo.l=AllocateMemory(16)
PokeW(whereTo.l+0000,#AF_INET)
PokeW(whereTo.l+0002, 0) ; port not used.
PokeL(whereTo.l+0004,ip.l)
PokeL(whereTo.l+0008, 0) ; the unused 8 bytes - are essential!
PokeL(whereTo.l+0012, 0)
address.s=PeekS(inet_ntoa_(PeekL(whereTo.l+0004)))
; PrintN("Familly ="+Str(PeekW(whereTo.l+0000)))
; PrintN("Port ="+Str(PeekW(whereTo.l+0002)))
; PrintN("Address ="+address.s)
; build a packet to send.
; struct icmphdr {
; __u8 type;
; __u8 code;
; __u16 checksum;
; union {
; struct {
; __u16 id;
; __u16 sequence;
; } echo;
; __u32 gateway;
; struct {
; __u16 __unused;
; __u16 mtu;
; } frag;
; } un;
; };
cc.l = lendata.l+8+8
socklen.l=16
ident.w = getpid_()
packetMemory.l=AllocateMemory(64*1024)
ptr.l=packetMemory
; 8 bytes of ICMP header.
PokeB(ptr, #ICMP_ECHO) ; type
ptr=ptr+1
PokeB(ptr, 0) ; code
ptr=ptr+1: chkptr.l=ptr
PokeW(ptr, 0) ; checksum holder.
ptr=ptr+2
PokeW(ptr, ident ) ; ident - will be changed in the reply though.
ptr=ptr+2
PokeW(ptr, sequence) ; sequence number.
ptr=ptr+2
timePtr=ptr
;PokeL(ptr, ElapsedMilliseconds() ) ;time stampA should be done just before we send..
ptr=ptr+4
PokeL(ptr, ident) ; this should be unchanged as part of the reply
ptr=ptr+4
PokeS(ptr, string)
ptr=ptr+lendata
pktsize.l=ptr-packetMemory
; PrintN( "packet size="+Str(pktsize))
; PrintN( "type="+ Str( PeekB(packetMemory.l+0000)))
; PrintN( "code="+ Str( PeekB(packetMemory.l+0001)))
; PrintN( "chksum="+ Str( PeekW(packetMemory.l+0002)))
; PrintN( "ident="+ Str( PeekW(packetMemory.l+0004)))
; PrintN( "sequence="+ Str( PeekW(packetMemory.l+0006)))
; PrintN( "data=<"+PeekS(packetMemory+0016)+">")
PokeL(timePtr, ElapsedMilliseconds() ) ;time stampA
; checksum needs to be done last of all
PokeW(chkptr, inverted_checksum(packetMemory, pktsize) )
result.l = sendto_( s, packetMemory, pktsize, 0, whereTo, socklen )
; perror_("")
; PrintN( Str(result.l ))
sequence.w=sequence.w+1
; our packet should hopefully come back now!
; free the buffers
FreeMemory(packetMemory)
FreeMemory(whereTo)
pingResult=-1
ProcedureReturn pingResult
EndProcedure
Procedure.l GetReply(s)
whereFrom.l=AllocateMemory(16)
PokeW(whereFrom.l+0000, #AF_INET) ; protocol
PokeW(whereFrom.l+0002, 0)
PokeL(whereFrom.l+0004, 0) ; IP address here is ignored.
PokeL(whereFrom.l+0008, 0) ; the unused 8 bytes - are essential!
PokeL(whereFrom.l+0012, 0)
whereLen=16
packetMemory.l = AllocateMemory(64*1024)
fd_set = AllocateMemory(#FD_SET_SIZE)
; set the timeout to wait for a reply
timeout.l=AllocateMemory(8)
PokeL( timeout.l+0,3) ;seconds
PokeL( timeout.l+8,0) ;milliseconds
FD_ZERO( fd_set)
FD_SET( s, fd_set)
memset_(packetMemory,0,64*1024)
sel.l = select_(s +1, fd_set, 0, 0, timeout )
If sel.l > 0
size.l = recvfrom_(s, packetMemory, 64*1024, 0, whereFrom, @whereLen )
recvTime.l= ElapsedMilliseconds()
address.s=PeekS(inet_ntoa_(PeekL(whereFrom+0004)))
packetMemory=packetMemory+#IP_HEADER_LEN ; skip the ip header.
sentTime.l = PeekL( packetMemory+8)
localId.w = PeekL( packetMemory+12)
; - information can be retrieved from the packet.
; If localId.w = getpid_()
; PrintN("Our packet")
; Else
; PrintN("Not Our packet")
; EndIf
; PrintN("Reply from Address ="+address)
; PrintN( "type="+ Hex( PeekB(packetMemory.l+0000)))
; PrintN( "code="+ Hex( PeekB(packetMemory.l+0001)))
; PrintN( "chksum="+ Hex( PeekW(packetMemory.l+0002)))
; PrintN( "remote ident="+ Hex( PeekW(packetMemory.l+0004)))
; PrintN( "sequence="+ Hex( PeekW(packetMemory.l+0006)))
; PrintN( "sent time (ms)="+Str(sentTime.l))
; PrintN( "data=<"+PeekS(packetMemory+0016)+">")
; PrintN( "Time ellapsed ="+Str( recvTime-sentTime))
; PrintN( "local id="+Str( PeekL( packetMemory+12)))
;
If localId.w = getpid_()
pingResult= 1
EndIf
Else
; PrintN("Reply timed out")
pingResult=0
EndIf
; tidy up memory etc
FreeMemory(packetMemory-#IP_HEADER_LEN)
FreeMemory(timeout)
FreeMemory(whereFrom)
ProcedureReturn pingResult
EndProcedure
Procedure.l openRawSocketAsRoot()
; run as root for as little time as possible
; Now the number 1 and the letters icmp
; are brought to you by..
proto.l = getprotobyname_("ICMP")
If proto = 0
PrintN("ICMP protocol unknown")
End
Else
proto$ = PeekS(PeekL(proto))
proto=proto+8
protocolICMP.l=PeekL(proto)
EndIf
; is there even any point at all in getprotobyname?
; RAW sockets must run as root -
; so you must set root permission on the executable to do this or sudo it.
s.l = socket_ (#AF_INET, #SOCK_RAW, protocolICMP )
If s.l<0
perror_("")
End
EndIf
; drop root now that the raw socket is open.
setuid_( getuid_())
ProcedureReturn s
EndProcedure
; console example of simple LINUX ping
s.l = openRawSocketAsRoot()
result.l = OpenConsole()
If result = 0
End
EndIf
arg1$=ProgramParameter()
If arg1$ = ""
PrintN("Ping nodename or ipaddress")
End
EndIf
If sendPing(s, arg1$,"This is a message ")
If GetReply(s)
PrintN( "Ping succeeded")
Else
PrintN("No Reply: Ping failed")
EndIf
Else
PrintN("Unable to ping")
EndIf
End