Class: Ronin::Support::Network::IPRange::CIDR

Inherits:
IPAddr
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ronin/support/network/ip_range/cidr.rb

Overview

Represents CIDR notation IP ranges.

Examples

cidr = Network::IP::CIDR.new('10.0.0.1/24')
cidr.each { |ip puts }
# 10.0.0.0
# 10.0.0.1
# ...
# 10.0.0.254
# 10.0.0.255

Since:

  • 1.0.0

Constant Summary collapse

IPV4_REGEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regular expression that matches IPv4 CIDR ranges.

Since:

  • 1.1.0

%r{\A#{ipv4_addr}(?:/(?:\d|[12]\d|3[0-2]))?\z}
IPV6_REGEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regular expression that matches IPv6 CIDR ranges.

Since:

  • 1.1.0

%r{\A(?:
  (?:[0-9a-fA-F]{1,4}:){6}#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){5}[0-9a-fA-F]{1,4}:#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){5}:[0-9a-fA-F]{1,4}:#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){1,1}(?::[0-9a-fA-F]{1,4}){1,4}:#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,3}:#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,2}:#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,1}:#{ipv4_addr}|
  :(?::[0-9a-fA-F]{1,4}){1,5}:#{ipv4_addr}|
  (?:(?:[0-9a-fA-F]{1,4}:){1,5}|:):#{ipv4_addr}|
  (?:[0-9a-fA-F]{1,4}:){1,1}(?::[0-9a-fA-F]{1,4}){1,6}|
  (?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|
  (?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|
  (?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|
  (?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|
  (?:[0-9a-fA-F]{1,4}:){1,6}(?::[0-9a-fA-F]{1,4}){1,1}|
  [0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){7}|
  :(?::[0-9a-fA-F]{1,4}){1,7}|
  (?:(?:[0-9a-fA-F]{1,4}:){1,7}|:):
)(?:/(?:\d{1,2}|1[0-1]\d+|12[0-8]))?\z}x
REGEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regular expression to match IP-glob ranges.

Since:

  • 1.1.0

/#{IPV4_REGEX}|#{IPV6_REGEX}/
SIZES =

Socket families and IP address sizes

Since:

  • 1.0.0

{
  Socket::AF_INET  => 32,
  Socket::AF_INET6 => 128
}
MASKS =

Socket families and IP address masks

Since:

  • 1.0.0

{
  Socket::AF_INET  => IN4MASK,
  Socket::AF_INET6 => IN6MASK
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#map_hash

Constructor Details

#initialize(string, family = Socket::AF_UNSPEC) ⇒ CIDR

Initializes and parses the CIDR range.

Parameters:

  • string (String)

    The CIDR range string to parse.

  • family (Integer) (defaults to: Socket::AF_UNSPEC)

    The address family for the CIDR range. This is mainly for backwards compatibility with IPAddr#initialize.

Raises:

  • (ArgumentError)

    The CIDR range string was not a valid IPv4 or IPv6 CIDR range.

Since:

  • 1.0.0



107
108
109
110
111
112
113
114
115
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 107

def initialize(string,family=Socket::AF_UNSPEC)
  unless (string =~ IPV4_REGEX || string =~ IPV6_REGEX)
    raise(ArgumentError,"invalid CIDR range: #{string.inspect}")
  end

  super(string,family)

  @string = string
end

Instance Attribute Details

#stringString (readonly)

The CIDR IP range string.

Returns:

Since:

  • 1.0.0



92
93
94
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 92

def string
  @string
end

Class Method Details

.each(string) {|ip| ... } ⇒ Object

Enumerates over each IP address that is included in the addresses netmask. Supports both IPv4 and IPv6 addresses.

Examples:

IPRange::CIDR.each('10.0.0.1/24') { |ip| puts ip }
# 10.0.0.0
# 10.0.0.1
# ...
# 10.0.0.254
# 10.0.0.255

Parameters:

  • string (String)

    The CIDR range string to parse and enumerate over.

Yields:

  • (ip)

    The block which will be passed every IP address covered be the netmask of the IPAddr object.

Yield Parameters:

  • ip (String)

    An IP address.

Since:

  • 1.0.0



211
212
213
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 211

def self.each(string,&block)
  new(string).each(&block)
end

.parse(string) ⇒ CIDR

Alias for new.

Parameters:

  • string (String)

    The CIDR range string to parse.

Returns:

  • (CIDR)

    The parsed CIDR range.

See Also:

Since:

  • 1.0.0



130
131
132
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 130

def self.parse(string)
  new(string)
end

.range(first, last) ⇒ CIDR

Calcualtes the CIDR range between two IP addresses.

Examples:

IPRange::CIDR.range("1.1.1.1","1.1.1.255")
# => #<Ronin::Support::Network::IPRange::CIDR: 1.1.1.1/24>

Parameters:

  • first (String, IPAddr)

    The first IP address in the CIDR range.

  • last (String, IPAddr)

    The last IP Address in the CIDR range.

Returns:

  • (CIDR)

    The CIDR range between the two IP addresses.

Since:

  • 1.0.0



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 162

def self.range(first,last)
  first_ip = case first
             when IPAddr then first
             else             IPAddr.new(first)
             end

  last_ip = case last
            when IPAddr then last
            else             IPAddr.new(last)
            end

  unless (first_ip.family == last_ip.family)
    raise(ArgumentError,"must specify two IPv4 or IPv6 addresses: #{first.inspect} #{last.inspect}")
  end

  num_bits  = SIZES.fetch(first_ip.family)
  diff_bits = first_ip.to_i ^ last_ip.to_i

  if diff_bits > 0
    prefix_length = num_bits - Math.log2(diff_bits).ceil

    return new("#{first_ip}/#{prefix_length}")
  else
    return new(first_ip.to_s)
  end
end

Instance Method Details

#==(other) ⇒ Boolean

Compares the CIDR range to another IP range.

Parameters:

  • other (Object)

    The other IP range.

Returns:

  • (Boolean)

Since:

  • 1.1.0



247
248
249
250
251
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 247

def ==(other)
  other.kind_of?(self.class) &&
    family == other.family &&
    to_i   == other.to_i
end

#===(other) ⇒ Boolean

Determines if the given IP range is a sub-set of the IP CIDR range.

Parameters:

Returns:

  • (Boolean)

Since:

  • 1.1.0



263
264
265
266
267
268
269
270
271
272
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 263

def ===(other)
  case other
  when CIDR
    include?(other.first) && include?(other.last)
  when Enumerable
    other.all? { |ip| include?(ip) }
  else
    false
  end
end

#each {|ip| ... } ⇒ self

Iterates over each IP address that is included in the addresses netmask. Supports both IPv4 and IPv6 addresses.

Examples:

cidr = IPAddr.new('10.1.1.1/24')
cidr.each { |ip| puts ip }
# 10.0.0.0
# 10.0.0.1
# ...
# 10.0.0.254
# 10.0.0.255

Yields:

  • (ip)

    The block which will be passed every IP address covered be the netmask of the IPAddr object.

Yield Parameters:

  • ip (String)

    An IP address.

Returns:

  • (self)

Since:

  • 1.0.0



296
297
298
299
300
301
302
303
304
305
306
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 296

def each
  return enum_for(__method__) unless block_given?

  family_mask = MASKS[@family]

  (0..((~@mask_addr) & family_mask)).each do |i|
    yield _to_string(@addr | i)
  end

  return self
end

#firstString

The first IP address of the CIDR Range.

Returns:

Since:

  • 1.0.0



313
314
315
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 313

def first
  _to_string(@addr)
end

#include?(ip) ⇒ Boolean

Determines if the given IP belongs to the IP CIDR range.

Parameters:

Returns:

  • (Boolean)

    Specifies whether the IP is or is not within the IP CIDR range.

Since:

  • 1.1.0



226
227
228
229
230
231
232
233
234
235
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 226

def include?(ip)
  ip = IPAddr.new(ip) unless ip.kind_of?(IPAddr)

  family_mask = MASKS[@family]
  start_addr  = @addr
  end_addr    = @addr | (~@mask_addr & family_mask)
  ip_addr     = ip.to_i

  return (ip_addr >= start_addr) && (ip_addr <= end_addr)
end

#inspectString

Inspects the CIDR range.

Returns:

Since:

  • 1.0.0



351
352
353
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 351

def inspect
  "#<#{self.class}: #{@string}>"
end

#lastString

The last IP address of the CIDR range.

Returns:

Since:

  • 1.0.0



322
323
324
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 322

def last
  _to_string(@addr | ~@mask_addr)
end

#sizeInteger

Calculates the size of the CIDR range.

Returns:

Since:

  • 1.1.0



333
334
335
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 333

def size
  2**(SIZES.fetch(family) - prefix)
end

#to_sString

Converts the CIDR range back into a String.

Returns:

Since:

  • 1.0.0



342
343
344
# File 'lib/ronin/support/network/ip_range/cidr.rb', line 342

def to_s
  @string
end