--sm4nu43k4a2Rpi4c Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Dec 01, 2006 at 04:47:05AM +0900, Daniel Berger wrote: > Well, you could start by porting the ping_icmp() function from Ping.pm > to Ruby. I started working on it but I got stuck and I need to work on > other things. Below is what I've got so far: I've made some progress; see attached. Let me know what you think. -- Jos Backus jos at catnook.com --sm4nu43k4a2Rpi4c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="ping_icmp.rb" #!/usr/bin/env ruby require 'rubygems' require 'net/ping' module Net class Ping::ICMP < Ping ICMP_ECHOREPLY ICMP_ECHO ICMP_STRUCT C2 n3 A' ICMP_SUBCODE ICMP_FLAGS ICMP_PORT def initialize(*args) super(args) raise 'requires root privileges' if Process.euid > 0 # unsure @seq @data_size @data ' @pid rocess.pid & 0xffff end def checksum(msg) length sg.length num_short ength / 2 check msg.unpack("n#{num_short}").each do |short| check + hort end if length % 2 > 0 check + sg[length-1, 1].unpack('C') << 8 end check check >> 16) + (check & 0xffff) return (~((check >> 16) + check) & 0xffff) end def ping(ip, timeout) ret il socket ocket.new( Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_ICMP ) @seq @seq + 1) % 65536 pstring C2 n3 A' << @data_size.to_s checksum msg ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring) checksum hecksum(msg) msg ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring) begin saddr ocket.pack_sockaddr_in(ICMP_PORT, ip) rescue exc return nil end @from_ip from_type from_subcode il socket.send(msg, ICMP_FLAGS, saddr) # Send the message done alse finish_time ime.now + timeout while !done and timeout > 0 nfound elect([socket], nil, nil, timeout) timeout inish_time - Time.now if nfound.nil? # timed out ret il done rue elsif !nfound[0].empty? recv_msg ' from_pid 1 from_seq 1 recv_msg, from_saddr ocket.recvfrom(1500, ICMP_FLAGS) from_port, from_ip ocket.unpack_sockaddr_in(from_saddr) from_type, from_subcode ecv_msg[20, 2].unpack('C2') case from_type when ICMP_ECHOREPLY if recv_msg.length > 8 from_pid, from_seq ecv_msg[24, 4].unpack('n3') end else if recv_msg.length > 6 from_pid, from_seq ecv_msg[52, 4].unpack('n3') end end @from_ip rom_ip @from_type rom_type @from_subcode rom_subcode if from_pid @pid and from_seq @seq if from_type ICMP_ECHOREPLY ret end done rue end else # Shouldn't happen done rue end end return ret end end end p et::Ping::ICMP.new p p.ping(ARGV.shift, 5) --sm4nu43k4a2Rpi4c--