From e80b474e3000120bdb8b1cf5392b45a2073df244 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 26 Jul 2024 14:33:10 +0800 Subject: [PATCH] Support IPv6 range --- lib/uri/generic.rb | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index a5c9598..683149f 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -1572,17 +1572,45 @@ def self.use_proxy?(hostname, addr, port, no_proxy) # :nodoc: private + def self.expand_ipv6(ip) + if ip.include?('::') + parts = ip.split('::') + left = parts[0].split(':') + right = parts[1] ? parts[1].split(':') : [] + middle = ['0'] * (8 - left.size - right.size) + (left + middle + right).join(':') + else + ip + end + end + def self.ip_to_i(ip) - ip.split('.').map(&:to_i).pack('C*').unpack1('N') + if ip.include?(':') + expanded_ip = expand_ipv6(ip) + segments = expanded_ip.split(':').map { |seg| seg.rjust(4, '0') } + hex_ip = segments.join + hex_ip.to_i(16) + else + ip.split('.').map(&:to_i).pack('C*').unpack1('N') + end end - + def self.in_ip_range?(ip, range) return false unless range.include?('/') - + base, bits = range.split('/') bits = bits.to_i - mask = (0xFFFFFFFF << (32 - bits)) & 0xFFFFFFFF - (ip_to_i(ip) & mask) == (ip_to_i(base) & mask) + + if base.include?(':') + # IPv6 + expanded_base = expand_ipv6(base) + mask = (1 << 128) - (1 << (128 - bits)) + (ip_to_i(ip) & mask) == (ip_to_i(expanded_base) & mask) + else + # IPv4 + mask = (0xFFFFFFFF << (32 - bits)) & 0xFFFFFFFF + (ip_to_i(ip) & mask) == (ip_to_i(base) & mask) + end end end end