diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb index 7a5cf94830..b7877970e4 100644 --- a/lib/ipaddr.rb +++ b/lib/ipaddr.rb @@ -263,7 +263,8 @@ class IPAddr # Returns true if the ipaddr is a private address. IPv4 addresses # in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 as defined in RFC # 1918 and IPv6 Unique Local Addresses in fc00::/7 as defined in RFC - # 4193 are considered private. + # 4193 are considered private. Private IPv4 addresses in the + # IPv4-mapped IPv6 address range are also considered private. def private? case @family when Socket::AF_INET @@ -271,7 +272,12 @@ class IPAddr @addr & 0xfff00000 == 0xac100000 || # 172.16.0.0/12 @addr & 0xffff0000 == 0xc0a80000 # 192.168.0.0/16 when Socket::AF_INET6 - @addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000 + @addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000 || + (@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && ( + @addr & 0xff000000 == 0x0a000000 || # ::ffff:10.0.0.0/8 + @addr & 0xfff00000 == 0xac100000 || # ::ffff::172.16.0.0/12 + @addr & 0xffff0000 == 0xc0a80000 # ::ffff::192.168.0.0/16 + )) else raise AddressFamilyError, "unsupported address family" end diff --git a/test/test_ipaddr.rb b/test/test_ipaddr.rb index c07ee2a8ee..90a7fc352a 100644 --- a/test/test_ipaddr.rb +++ b/test/test_ipaddr.rb @@ -426,6 +426,26 @@ class TC_Operator < Test::Unit::TestCase assert_equal(true, IPAddr.new('fc84:8bf7:e905::1').private?) assert_equal(true, IPAddr.new('fd84:8bf7:e905::1').private?) assert_equal(false, IPAddr.new('fe84:8bf7:e905::1').private?) + + assert_equal(false, IPAddr.new('::ffff:0.0.0.0').private?) + assert_equal(false, IPAddr.new('::ffff:127.0.0.1').private?) + + assert_equal(false, IPAddr.new('::ffff:8.8.8.8').private?) + assert_equal(true, IPAddr.new('::ffff:10.0.0.0').private?) + assert_equal(true, IPAddr.new('::ffff:10.255.255.255').private?) + assert_equal(false, IPAddr.new('::ffff:11.255.1.1').private?) + + assert_equal(false, IPAddr.new('::ffff:172.15.255.255').private?) + assert_equal(true, IPAddr.new('::ffff:172.16.0.0').private?) + assert_equal(true, IPAddr.new('::ffff:172.31.255.255').private?) + assert_equal(false, IPAddr.new('::ffff:172.32.0.0').private?) + + assert_equal(false, IPAddr.new('::ffff:190.168.0.0').private?) + assert_equal(true, IPAddr.new('::ffff:192.168.0.0').private?) + assert_equal(true, IPAddr.new('::ffff:192.168.255.255').private?) + assert_equal(false, IPAddr.new('::ffff:192.169.0.0').private?) + + assert_equal(false, IPAddr.new('::ffff:169.254.0.1').private?) end def test_link_local?