Feature #3711

IPAddr must not make DNS lookups via IPSocket.getaddress

Added by Philipp Kempgen over 3 years ago. Updated over 1 year ago.

[ruby-core:31756]
Status:Feedback
Priority:Normal
Assignee:Akinori MUSHA
Category:-
Target version:next minor

Description

=begin
class MustNotCallError < NotImplementedError ; end

class IpAddrNoResolvTestCase < Test::Unit::TestCase
def setup()
class << IPSocket
alias originalgetaddress getaddress
def getaddress( host )
# DNS lookups are slow and totally unnecessary for IP addresses
raise MustNotCallError.new( 'IPAddr.new() must not call IPSocket.getaddress()!' )
end
end
end
def test
ipaddrmustnotresolvevalidipv4address
assertnothingraised { IPAddr.new( '1.2.3.4', Socket::AFINET ) }
end
def test
ipaddrmustnotresolveinvalidipv4styleaddress
assert
raise( ArgumentError ) { IPAddr.new( '1.2.3.400', Socket::AFINET ) }
end
def test
ipaddrmustnotresolvevalidipv6address
assertnothingraised { IPAddr.new( '::', Socket::AFINET6 ) }
end
def test
ipaddrmustnotresolveinvalidipv6styleaddress
assert
raise( ArgumentError ) { IPAddr.new( '::1::', Socket::AF_INET6 ) }
end
end
=end

History

#1 Updated by Nobuyoshi Nakada over 3 years ago

=begin
Hi,

At Wed, 18 Aug 2010 22:07:42 +0900,
Philipp Kempgen wrote in :

DNS lookups are slow and totally unnecessary for IP addresses

raise MustNotCallError.new( 'IPAddr.new() must not call IPSocket.getaddress()!' )

IPAddr.new already does not call getaddress for valid IPv4
addresses if IPv6 is not available. Seems it should be enabled
even if IPv6 is available, since there is valid_v6? method
already.

diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb
index 226a996..8d3ee00 100644
--- a/lib/ipaddr.rb
+++ b/lib/ipaddr.rb
@@ -17,45 +17,71 @@
#
require 'socket'

-unless Socket.constdefined? "AFINET6"
+haveinet4 = Socket.constdefined? "AFINET"
+have
inet6 = Socket.constdefined? "AFINET6"
+
+unless haveinet6
class Socket < BasicSocket
AF
INET6 = Object.new
end
+end

+if haveinet4
class << IPSocket
def valid
v4?(addr)
if /\A(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})\Z/ =~ addr
- return $~.captures.all? {|i| i.toi < 256}
+ return $~.captures.all? {|i| i.to
i < 256} || nil
end
return false
end
+ end
+end

+if haveinet6
+ class << IPSocket
def valid
v6?(addr)
+ s = nil
# IPv6 (normal)
return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})\Z/ =~ addr
return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})
::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4}))?\Z/ =~ addr
return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})
)?\Z/ =~ addr
# IPv6 (IPv4 compat)
- return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4}):/ =~ addr && valid_v4?($')
+ return s if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})
:/ =~ addr && (s = validv4?($')) != false
return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4}):)?/ =~ addr && valid
v4?($')
- return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4}):)?/ =~ addr && valid_v4?($')
+ return s if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})
:)?/ =~ addr && (s = valid_v4?($')) != false

    false
  end
  • end +else
  • class << IPSocket
  • def valid_v6?(addr)
  • false
  • end
  • end
    +end

    +if have_inet6

  • class << IPSocket
    def valid?(addr)

  •  valid_v4?(addr) || valid_v6?(addr)
    
  •  (s = valid_v4?(addr)) == false ? valid_v6?(addr) : s
    

    end

  • end
    +else

  • class << IPSocket

  • alias valid? valid_v4?

  • end
    +end

  • alias getaddress_orig getaddress

  • def getaddress(s)

  •  if valid?(s)
    
  •    s
    
  •  elsif /\A[-A-Za-z\d.]+\Z/ =~ s
    
  •    getaddress_orig(s)
    
  •  else
    
  •    raise ArgumentError, "invalid address"
    
  •  end
    

    +class << IPSocket

  • alias getaddress_orig getaddress

  • def getaddress(s)

  • if v = valid?(s)

  •  s
    
  • elsif v == false && /\A[-A-Za-z\d.]+\Z/ =~ s

  •  getaddress_orig(s)
    
  • else

  •  raise ArgumentError, "invalid address"
    

    end
    end
    end

    Nobu Nakada

=end

#2 Updated by Shyouhei Urabe over 3 years ago

  • Status changed from Open to Feedback

=begin

=end

#3 Updated by Hiroshi Nakamura about 2 years ago

  • Description updated (diff)
  • Assignee set to Akinori MUSHA

#4 Updated by Yusuke Endoh over 1 year ago

  • Target version set to next minor

Also available in: Atom PDF