def ping(host = @host)
super(host)
bool = false
socket = Socket.new(
Socket::PF_INET,
Socket::SOCK_RAW,
Socket::IPPROTO_ICMP
)
if @bind_host
saddr = Socket.pack_sockaddr_in(@bind_port, @bind_host)
socket.bind(saddr)
end
@seq = (@seq + 1) % 65536
pstring = 'C2 n3 A' << @data_size.to_s
timeout = @timeout
checksum = 0
msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
checksum = checksum(msg)
msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
begin
saddr = Socket.pack_sockaddr_in(0, host)
rescue Exception
socket.close unless socket.closed?
return bool
end
start_time = Time.now
socket.send(msg, 0, saddr)
begin
Timeout.timeout(@timeout){
while true
io_array = select([socket], nil, nil, timeout)
if io_array.nil? || io_array[0].empty?
return false
end
pid = nil
seq = nil
data, sender = socket.recvfrom(1500)
port, host = Socket.unpack_sockaddr_in(sender)
type, subcode = data[20, 2].unpack('C2')
case type
when ICMP_ECHOREPLY
if data.length >= 28
pid, seq = data[24, 4].unpack('n3')
end
else
if data.length > 56
pid, seq = data[52, 4].unpack('n3')
end
end
if pid == @pid && seq == @seq && type == ICMP_ECHOREPLY
bool = true
break
end
end
}
rescue Exception => err
@exception = err
ensure
socket.close if socket
end
@duration = Time.now - start_time if bool
return bool
end