From: Nobuyoshi Nakada Date: 2010-08-19T06:45:23+09:00 Subject: [ruby-core:31767] Re: [Backport #3711] IPAddr must not make DNS lookups via IPSocket.getaddress Hi, At Wed, 18 Aug 2010 22:07:42 +0900, Philipp Kempgen wrote in [ruby-core:31756]: > # 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.const_defined? "AF_INET6" +have_inet4 = Socket.const_defined? "AF_INET" +have_inet6 = Socket.const_defined? "AF_INET6" + +unless have_inet6 class Socket < BasicSocket AF_INET6 = Object.new end +end +if have_inet4 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.to_i < 256} + return $~.captures.all? {|i| i.to_i < 256} || nil end return false end + end +end +if have_inet6 + 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 = valid_v4?($')) != 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