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>