IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and IPv6 are supported.
require 'ipaddr' ipaddr1 = IPAddr.new "3ffe:505:2::1" p ipaddr1 #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff> p ipaddr1.to_s #=> "3ffe:505:2::1" ipaddr2 = ipaddr1.mask(48) #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000> p ipaddr2.to_s #=> "3ffe:505:2::" ipaddr3 = IPAddr.new "192.168.2.0/24" p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
32 bit mask for IPv4
Format string for IPv6
128 bit mask for IPv4
Regexp internally used for parsing IPv4 address.
Regexp internally used for parsing IPv6 address.
Regexp internally used for parsing IPv6 address.
Returns the address family of this IP address.
Creates a new ipaddr object either from a human readable IP address representation in string, or from a packed in_addr value followed by an address family.
In the former case, the following are the valid formats that will be recognized: “address”, “address/prefixlen” and “address/mask”, where IPv6 address may be enclosed in square brackets (`[‘ and `]’). If a prefixlen or a mask is specified, it returns a masked IP address. Although the address family is determined automatically from a specified string, you can specify one explicitly by the optional second argument.
Otherwise an IP address is generated from a packed in_addr value and an address family.
The IPAddr class defines many methods and operators, and some of those, such as &, |, include? and ==, accept a string, or a packed in_addr value instead of an IPAddr object.
# File rake/lib/ipaddr.rb, line 452 def initialize(addr = '::', family = Socket::AF_UNSPEC) if !addr.kind_of?(String) case family when Socket::AF_INET, Socket::AF_INET6 set(addr.to_i, family) @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK return when Socket::AF_UNSPEC raise ArgumentError, "address family must be specified" else raise ArgumentError, "unsupported address family: #{family}" end end prefix, prefixlen = addr.split('/') if prefix =~ /^\[(.*)\]$/ prefix = $1 family = Socket::AF_INET6 end # It seems AI_NUMERICHOST doesn't do the job. #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil, # Socket::AI_NUMERICHOST) @addr = @family = nil if family == Socket::AF_UNSPEC || family == Socket::AF_INET @addr = in_addr(prefix) if @addr @family = Socket::AF_INET end end if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6) @addr = in6_addr(prefix) @family = Socket::AF_INET6 end if family != Socket::AF_UNSPEC && @family != family raise ArgumentError, "address family mismatch" end if prefixlen mask!(prefixlen) else @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK end end
Creates a new ipaddr containing the given network byte ordered string form of an IP address.
# File rake/lib/ipaddr.rb, line 90 def IPAddr::new_ntoh(addr) return IPAddr.new(IPAddr::ntop(addr)) end
Convert a network byte ordered string form of an IP address into human readable form.
# File rake/lib/ipaddr.rb, line 96 def IPAddr::ntop(addr) case addr.size when 4 s = addr.unpack('C4').join('.') when 16 s = IN6FORMAT % addr.unpack('n8') else raise ArgumentError, "unsupported address family" end return s end
Returns a new ipaddr built by bitwise AND.
# File rake/lib/ipaddr.rb, line 109 def &(other) return self.clone.set(@addr & coerce_other(other).to_i) end
Returns a new ipaddr built by bitwise left shift.
# File rake/lib/ipaddr.rb, line 124 def <<(num) return self.clone.set(addr_mask(@addr << num)) end
Compares the ipaddr with another.
# File rake/lib/ipaddr.rb, line 320 def <=>(other) other = coerce_other(other) return nil if other.family != @family return @addr <=> other.to_i end
Returns true if two ipaddrs are equal.
# File rake/lib/ipaddr.rb, line 134 def ==(other) other = coerce_other(other) return @family == other.family && @addr == other.to_i end
Returns a new ipaddr built by bitwise right-shift.
# File rake/lib/ipaddr.rb, line 119 def >>(num) return self.clone.set(@addr >> num) end
Checks equality used by Hash.
# File rake/lib/ipaddr.rb, line 330 def eql?(other) return self.class == other.class && self.hash == other.hash && self == other end
Returns a network byte ordered string form of the IP address.
# File rake/lib/ipaddr.rb, line 220 def hton case @family when Socket::AF_INET return [@addr].pack('N') when Socket::AF_INET6 return (0..7).map { |i| (@addr >> (112 - 16 * i)) & 0xffff }.pack('n8') else raise "unsupported address family" end end
Returns true if the given ipaddr is in the range.
e.g.:
require 'ipaddr' net1 = IPAddr.new("192.168.2.0/24") net2 = IPAddr.new("192.168.2.100") net3 = IPAddr.new("192.168.3.0") p net1.include?(net2) #=> true p net1.include?(net3) #=> false
# File rake/lib/ipaddr.rb, line 154 def include?(other) other = coerce_other(other) if ipv4_mapped? if (@mask_addr >> 32) != 0xffffffffffffffffffffffff return false end mask_addr = (@mask_addr & IN4MASK) addr = (@addr & IN4MASK) family = Socket::AF_INET else mask_addr = @mask_addr addr = @addr family = @family end if other.ipv4_mapped? other_addr = (other.to_i & IN4MASK) other_family = Socket::AF_INET else other_addr = other.to_i other_family = other.family end if family != other_family return false end return ((addr & mask_addr) == (other_addr & mask_addr)) end
Returns a string containing a human-readable representation of the ipaddr. (“#<IPAddr: family:address/mask>”)
# File rake/lib/ipaddr.rb, line 357 def inspect case @family when Socket::AF_INET af = "IPv4" when Socket::AF_INET6 af = "IPv6" else raise "unsupported address family" end return sprintf("#<%s: %s:%s/%s>", self.class.name, af, _to_string(@addr), _to_string(@mask_addr)) end
Returns a string for DNS reverse lookup compatible with RFC3172.
# File rake/lib/ipaddr.rb, line 299 def ip6_arpa if !ipv6? raise ArgumentError, "not an IPv6 address" end return _reverse + ".ip6.arpa" end
Returns a string for DNS reverse lookup compatible with RFC1886.
# File rake/lib/ipaddr.rb, line 307 def ip6_int if !ipv6? raise ArgumentError, "not an IPv6 address" end return _reverse + ".ip6.int" end
Returns true if the ipaddr is an IPv4 address.
# File rake/lib/ipaddr.rb, line 234 def ipv4? return @family == Socket::AF_INET end
Returns a new ipaddr built by converting the native IPv4 address into an IPv4-compatible IPv6 address.
# File rake/lib/ipaddr.rb, line 268 def ipv4_compat if !ipv4? raise ArgumentError, "not an IPv4 address" end return self.clone.set(@addr, Socket::AF_INET6) end
Returns true if the ipaddr is an IPv4-compatible IPv6 address.
# File rake/lib/ipaddr.rb, line 249 def ipv4_compat? if !ipv6? || (@addr >> 32) != 0 return false end a = (@addr & IN4MASK) return a != 0 && a != 1 end
Returns a new ipaddr built by converting the native IPv4 address into an IPv4-mapped IPv6 address.
# File rake/lib/ipaddr.rb, line 259 def ipv4_mapped if !ipv4? raise ArgumentError, "not an IPv4 address" end return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6) end
Returns true if the ipaddr is an IPv4-mapped IPv6 address.
# File rake/lib/ipaddr.rb, line 244 def ipv4_mapped? return ipv6? && (@addr >> 32) == 0xffff end
Returns true if the ipaddr is an IPv6 address.
# File rake/lib/ipaddr.rb, line 239 def ipv6? return @family == Socket::AF_INET6 end
Returns a new ipaddr built by masking IP address with the given prefixlen/netmask. (e.g. 8, 64, “255.255.255.0”, etc.)
# File rake/lib/ipaddr.rb, line 141 def mask(prefixlen) return self.clone.mask!(prefixlen) end
Returns a new ipaddr built by converting the IPv6 address into a native IPv4 address. If the IP address is not an IPv4-mapped or IPv4-compatible IPv6 address, returns self.
# File rake/lib/ipaddr.rb, line 278 def native if !ipv4_mapped? && !ipv4_compat? return self end return self.clone.set(@addr & IN4MASK, Socket::AF_INET) end
Returns a string for DNS reverse lookup. It returns a string in RFC3172 form for an IPv6 address.
# File rake/lib/ipaddr.rb, line 287 def reverse case @family when Socket::AF_INET return _reverse + ".in-addr.arpa" when Socket::AF_INET6 return ip6_arpa else raise "unsupported address family" end end
Returns the successor to the ipaddr.
# File rake/lib/ipaddr.rb, line 315 def succ return self.clone.set(@addr + 1, @family) end
Returns the integer representation of the ipaddr.
# File rake/lib/ipaddr.rb, line 184 def to_i return @addr end
Creates a Range object for the network address.
# File rake/lib/ipaddr.rb, line 340 def to_range begin_addr = (@addr & @mask_addr) case @family when Socket::AF_INET end_addr = (@addr | (IN4MASK ^ @mask_addr)) when Socket::AF_INET6 end_addr = (@addr | (IN6MASK ^ @mask_addr)) else raise "unsupported address family" end return clone.set(begin_addr, @family)..clone.set(end_addr, @family) end
Returns a string containing the IP address representation.
# File rake/lib/ipaddr.rb, line 189 def to_s str = to_string return str if ipv4? str.gsub!(/\b0{1,3}([\da-f]+)\b/, '\1') loop do break if str.sub!(/\A0:0:0:0:0:0:0:0\z/, '::') break if str.sub!(/\b0:0:0:0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0:0\b/, ':') break if str.sub!(/\b0:0:0\b/, ':') break if str.sub!(/\b0:0\b/, ':') break end str.sub!(/:{3,}/, '::') if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\z/ =~ str str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256) end str end
Returns a string containing the IP address representation in canonical form.
# File rake/lib/ipaddr.rb, line 215 def to_string return _to_string(@addr) end
Returns a new ipaddr built by bitwise OR.
# File rake/lib/ipaddr.rb, line 114 def |(other) return self.clone.set(@addr | coerce_other(other).to_i) end
Returns a new ipaddr built by bitwise negation.
# File rake/lib/ipaddr.rb, line 129 def ~ return self.clone.set(addr_mask(~@addr)) end
Set current netmask to given mask.
# File rake/lib/ipaddr.rb, line 396 def mask!(mask) if mask.kind_of?(String) if mask =~ /^\d+$/ prefixlen = mask.to_i else m = IPAddr.new(mask) if m.family != @family raise ArgumentError, "address family is not same" end @mask_addr = m.to_i @addr &= @mask_addr return self end else prefixlen = mask end case @family when Socket::AF_INET if prefixlen < 0 || prefixlen > 32 raise ArgumentError, "invalid length" end masklen = 32 - prefixlen @mask_addr = ((IN4MASK >> masklen) << masklen) when Socket::AF_INET6 if prefixlen < 0 || prefixlen > 128 raise ArgumentError, "invalid length" end masklen = 128 - prefixlen @mask_addr = ((IN6MASK >> masklen) << masklen) else raise "unsupported address family" end @addr = ((@addr >> masklen) << masklen) return self end
Set +@addr+, the internal stored ip address, to
given addr
. The parameter addr
is validated using
the first family
member, which is +Socket::AF_INET+ or
+Socket::AF_INET6+.
# File rake/lib/ipaddr.rb, line 375 def set(addr, *family) case family[0] ? family[0] : @family when Socket::AF_INET if addr < 0 || addr > IN4MASK raise ArgumentError, "invalid address" end when Socket::AF_INET6 if addr < 0 || addr > IN6MASK raise ArgumentError, "invalid address" end else raise ArgumentError, "unsupported address family" end @addr = addr if family[0] @family = family[0] end return self end