Hi, While making some tweaks to the net-ping library, I noticed that I started getting test failures with 1.9.x on Vista for ICMP pings. A simple program should demonstrate: require ''net/ping'' npi = Net::Ping::ICMP.new(''localhost'') p npi.ping? icmp.rb:109:in `send'': An address incompatible with the requested protocol was used. - send(2) (Errno::EAFNOSUPPORT) from icmp.rb:109:in `ping'' from icmp.rb:184:in `<main>'' Where line 109 (using the latest git repo) is: socket.send(msg, 0, saddr) I don''t see this failure using 1.8, or even 1.9 on Unix platforms. Any ideas? https://github.com/djberg96/net-ping Here''s the icmp.rb source: require File.join(File.dirname(__FILE__), ''ping'') if File::ALT_SEPARATOR require ''win32/security'' require ''windows/system_info'' include Windows::SystemInfo end # The Net module serves as a namespace only. module Net # The Net::Ping::ICMP class encapsulates an icmp ping. class Ping::ICMP < Ping ICMP_ECHOREPLY = 0 # Echo reply ICMP_ECHO = 8 # Echo request ICMP_SUBCODE = 0 # You cannot set or change the port value. A value of 0 is always # used internally for ICMP pings. # undef_method :port # Returns the data size, i.e. number of bytes sent on the ping. The # default size is 56. # attr_reader :data_size # Creates and returns a new Ping::ICMP object. This is similar to its # superclass constructor, but must be created with root privileges (on # UNIX systems), and the port value is ignored. # def initialize(host=nil, port=nil, timeout=5) raise ''requires root privileges'' if Process.euid > 0 if File::ALT_SEPARATOR && windows_version >= 6 unless Win32::Security.elevated_security? raise ''requires elevated security'' end end @seq = 0 @bind_port = 0 @bind_host = nil @data_size = 56 @data = '''' 0.upto(@data_size){ |n| @data << (n % 256).chr } @pid = Process.pid & 0xffff super(host, port, timeout) @port = nil # This value is not used in ICMP pings. end # Sets the number of bytes sent in the ping method. # def data_size=(size) @data_size = size @data = '''' 0.upto(size){ |n| @data << (n % 256).chr } end # Associates the local end of the socket connection with the given # +host+ and +port+. The default port is 0. # def bind(host, port = 0) @bind_host = host @bind_port = port end # Pings the +host+ specified in this method or in the constructor. If a # host was not specified either here or in the constructor, an # ArgumentError is raised. # 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) # Send the message 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 # There is no duration if the ping failed @duration = Time.now - start_time if bool return bool end alias ping? ping alias pingecho ping private # Perform a checksum on the message. This is the sum of all the short # words and it folds the high order bits into the low order bits. # def checksum(msg) length = msg.length num_short = length / 2 check = 0 msg.unpack("n#{num_short}").each do |short| check += short end if length % 2 > 0 check += msg[length-1, 1].unpack(''C'').first << 8 end check = (check >> 16) + (check & 0xffff) return (~((check >> 16) + check) & 0xffff) end end end
Hi, 2012/2/26 Daniel Berger <djberg96 at gmail.com>> Hi, > > While making some tweaks to the net-ping library, I noticed that I started > getting test failures with 1.9.x on Vista for ICMP pings. A simple program > should demonstrate: > > require ''net/ping'' > npi = Net::Ping::ICMP.new(''localhost'') > p npi.ping? > > icmp.rb:109:in `send'': An address incompatible with the requested protocol > was used. - send(2) (Errno::EAFNOSUPPORT) > from icmp.rb:109:in `ping'' > from icmp.rb:184:in `<main>'' > > Where line 109 (using the latest git repo) is: > > socket.send(msg, 0, saddr) > > I don''t see this failure using 1.8, or even 1.9 on Unix platforms. Any > ideas? > >On Windows Vista (and Windows 7), the host "localhost" translated into "::1" IPv6 Loopback address instead of "127.0.0.1" IPv4 Loopback address. You can check it with "ping localhost" in command prompt. You must use "127.0.0.1" instead of "localhost" for this test case. Refer to http://stackoverflow.com/questions/2370388/socketexception-address-incompatible-with-requested-protocol Regards, Park Heesob -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/win32utils-devel/attachments/20120226/a0d99725/attachment.html>
> -----Original Message----- > From: win32utils-devel-bounces at rubyforge.org [mailto:win32utils-devel- > bounces at rubyforge.org] On Behalf Of Heesob Park > Sent: Sunday, February 26, 2012 2:33 AM > To: Development and ideas for win32utils projects > Subject: Re: [Win32utils-devel] ICMP pings on 1.9 > > Hi, > > > 2012/2/26 Daniel Berger <djberg96 at gmail.com> > > > Hi, > > While making some tweaks to the net-ping library, I noticed that > I started > getting test failures with 1.9.x on Vista for ICMP pings. A > simple program > should demonstrate: > > require ''net/ping'' > npi = Net::Ping::ICMP.new(''localhost'') > p npi.ping? > > icmp.rb:109:in `send'': An address incompatible with the requested > protocol > was used. - send(2) (Errno::EAFNOSUPPORT) > from icmp.rb:109:in `ping'' > from icmp.rb:184:in `<main>'' > > Where line 109 (using the latest git repo) is: > > socket.send(msg, 0, saddr) > > I don''t see this failure using 1.8, or even 1.9 on Unix > platforms. Any > ideas? > > > > > On Windows Vista (and Windows 7), the host "localhost" translated into > "::1" IPv6 Loopback address instead of "127.0.0.1" IPv4 Loopback > address. > You can check it with "ping localhost" in command prompt. > > You must use "127.0.0.1" instead of "localhost" for this test case. > > Refer to http://stackoverflow.com/questions/2370388/socketexception- > address-incompatible-with-requested-protocolThank you for the information. However, I''m confused why the tests pass on Vista with 1.8.7 then. I would think they would fail regardless of which version of Ruby I am using. My apologies if I have misunderstood. Regards, Dan
Hi, 2012/2/28 Daniel Berger <djberg96 at gmail.com>> > > > -----Original Message----- > > From: win32utils-devel-bounces at rubyforge.org [mailto:win32utils-devel- > > bounces at rubyforge.org] On Behalf Of Heesob Park > > Sent: Sunday, February 26, 2012 2:33 AM > > To: Development and ideas for win32utils projects > > Subject: Re: [Win32utils-devel] ICMP pings on 1.9 > > > > Hi, > > > > > > 2012/2/26 Daniel Berger <djberg96 at gmail.com> > > > > > > Hi, > > > > While making some tweaks to the net-ping library, I noticed that > > I started > > getting test failures with 1.9.x on Vista for ICMP pings. A > > simple program > > should demonstrate: > > > > require ''net/ping'' > > npi = Net::Ping::ICMP.new(''localhost'') > > p npi.ping? > > > > icmp.rb:109:in `send'': An address incompatible with the requested > > protocol > > was used. - send(2) (Errno::EAFNOSUPPORT) > > from icmp.rb:109:in `ping'' > > from icmp.rb:184:in `<main>'' > > > > Where line 109 (using the latest git repo) is: > > > > socket.send(msg, 0, saddr) > > > > I don''t see this failure using 1.8, or even 1.9 on Unix > > platforms. Any > > ideas? > > > > > > > > > > On Windows Vista (and Windows 7), the host "localhost" translated into > > "::1" IPv6 Loopback address instead of "127.0.0.1" IPv4 Loopback > > address. > > You can check it with "ping localhost" in command prompt. > > > > You must use "127.0.0.1" instead of "localhost" for this test case. > > > > Refer to http://stackoverflow.com/questions/2370388/socketexception- > > address-incompatible-with-requested-protocol > > Thank you for the information. However, I''m confused why the tests pass on > Vista with 1.8.7 then. I would think they would fail regardless of which > version of Ruby I am using. > > My apologies if I have misunderstood. > >Ruby 1.8.7 uses it''s own getaddrinfo function defined in getaddrinfo.c But Ruby 1.9.3 uses Windows native getaddrinfo function. Thus Ruby 1.8.7 translate "localhost" into "127.0.0.1" regardless of OS. Regards, Park Heesob -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/win32utils-devel/attachments/20120229/a27155b7/attachment.html>