Skip to content

Conversation

@Tietew
Copy link
Contributor

@Tietew Tietew commented Jun 24, 2019

When converting IPv4 to/from IPv6, IPAddr#set generates incorrect mask value.
This causes IPAddr#include? returns incorrect result.

ip4 = IPAddr.new('::ffff:127.0.0.1').native
p [ip4.to_s, ip4.prefix]
ip6 = IPAddr.new('127.0.0.1').ipv4_mapped
p [ip6.to_s, ip6.prefix]

Expected

["127.0.0.1", 32]
["::ffff:127.0.0.1", 128]

Actual

["127.0.0.1", -96]       # @mask_addr == 0xFFFFFFFFFFFFFFFF
["::ffff:127.0.0.1", 0]  # @mask_addr == 0x000000000000FFFF

@ioquatix ioquatix requested a review from hsbt June 24, 2019 11:50
@ioquatix ioquatix added the bug label Jun 24, 2019
@ioquatix ioquatix self-assigned this Jun 24, 2019
@hsbt hsbt requested review from knu and removed request for hsbt June 25, 2019 00:39
@ioquatix
Copy link
Member

ioquatix commented Jul 9, 2019

@Tietew can you rebase on master.

@Tietew
Copy link
Contributor Author

Tietew commented Jul 10, 2019

@ioquatix done.

@ioquatix
Copy link
Member

Can you please squash typo fix.

@taketo1113
Copy link
Contributor

#native / #ipv4_mapped (fixed)

In ipaddr v1.2.7, these methods have already been fixed and now behave as expected:

IPAddr::VERSION
=> "1.2.7"

ip4 = IPAddr.new('::ffff:127.0.0.1').native
=> #<IPAddr: IPv4:127.0.0.1/255.255.255.255>
p [ip4.to_s, ip4.prefix]
["127.0.0.1", 32]

ip6 = IPAddr.new('127.0.0.1').ipv4_mapped
=> #<IPAddr: IPv6:0000:0000:0000:0000:0000:ffff:7f00:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
p [ip6.to_s, ip6.prefix]
["::ffff:127.0.0.1", 128]

These fixes were introduced in ipaddr v1.2.4 in the following Pull Requests:
https://github.com/ruby/ipaddr/releases/tag/v1.2.4

#ipv4_compat (still broken)

However, #ipv4_compat still returns incorrect values for #prefix:

ip4 = IPAddr.new('192.168.1.1').ipv4_compat
=> #<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:c0a8:0101/0000:0000:0000:0000:0000:0000:ffff:ffff>
p [ip4.to_s, ip4.prefix]
["::192.168.1.1", 0] # expected ["::192.168.1.1", 128]

ip4 = IPAddr.new('192.168.0.0/16').ipv4_compat
=> #<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:c0a8:0000/0000:0000:0000:0000:0000:0000:ffff:0000>
p [ip4.to_s, ip4.prefix]
["::192.168.0.0", 0] # expected ["::192.168.0.0", 112]

NOTE: fix #ipv4_compat

Since the implementation of lib/ipaddr.rb has changed from when this Pull Request was first created, the following patch can be applied to fix #ipv4_compat so that it behaves as expected:

  def ipv4_compat
    warn "IPAddr\##{__callee__} is obsolete", uplevel: 1 if $VERBOSE
    if !ipv4?
      raise InvalidAddressError, "not an IPv4 address: #{@addr}"
    end
-    return self.clone.set(@addr, Socket::AF_INET6)
+    clone = self.clone.set(@addr, Socket::AF_INET6)
+    clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000)
+    clone
  end
ip4 = IPAddr.new('192.168.1.1').ipv4_compat
=> #<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:c0a8:0101/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
p [ip4.to_s, ip4.prefix]
["::192.168.1.1", 128]

ip4 = IPAddr.new('192.168.0.0/16').ipv4_compat
=> #<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:c0a8:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:0000>
p [ip4.to_s, ip4.prefix]
["::192.168.0.0", 112]

@taketo1113
Copy link
Contributor

@ioquatix I create Pull Request (#86) to fix #ipv4_compat returning an invalid prefix.

@ioquatix ioquatix closed this in #86 Sep 26, 2025
@ioquatix
Copy link
Member

Thanks everyone, appreciate your patience and contributions on this issue.

@Tietew Tietew deleted the keep_prefix_46 branch September 29, 2025 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants