Class: IpRanges::Range

Inherits:
Object
  • Object
show all
Defined in:
lib/ip-ranges/range.rb

Overview

Class to represent a range of IP numbers. Range objects are instantiated from a string which may be a single Exposes methods to compare this range with another range, and to iterate through all IP numbers in the range.

Constant Summary collapse

SINGLE_IP =
/^\d+\.\d+\.\d+\.\d+$/
DOTTED_RANGE =
/^(\d+\.\d+\.\d+\.\d+)\.\.(\d+\.\d+\.\d+\.\d+)$/
CIDR_RANGE =
%r[/]
BATCHSIZE =
250
PAUSE =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params) ⇒ Range

Instatiate a range from a string representation which can be a single Ip number, a dotted range or a CIDR range

Arguments:

  • A Hash with a single key ‘:range’ whose value is a string defining the range.

Examples:

IpRanges::Range.new :range => '1.2.3.4' => a range containing one Ip
IpRanges::Range.new :range => '1.2.3.4 .. 1.2.3.5' => a range containing two Ip numbers (spaces around the '..' are ignored)
IpRanges::Range.new :range => '1.2.3.0/24' => a range containing 256 Ip numbers (1.2.3.0 .. 1.2.3.255)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/ip-ranges/range.rb', line 33

def initialize(params)
  string = params[:range].gsub(' ', '')
  case string
  when SINGLE_IP
    @first = Ip.new :number => string
    @last = Ip.new :number => string
  when DOTTED_RANGE
    @first = Ip.new :number => $1
    @last = Ip.new :number => $2
  when CIDR_RANGE
    begin
      cidr = NetAddr::CIDR.create(string)
      @first = Ip.new :number => cidr.first
      @last = Ip.new :number => cidr.last
    rescue Exception => e
      puts "Error creating CIDR range from: #{string}"
      raise e
    end
  end
end

Instance Attribute Details

#firstObject

Returns the first Ip object in this range.



9
10
11
# File 'lib/ip-ranges/range.rb', line 9

def first
  @first
end

#lastObject

Returns the last Ip object in this range.



12
13
14
# File 'lib/ip-ranges/range.rb', line 12

def last
  @last
end

Instance Method Details

#==(range) ⇒ Object

Arguments

  • A Range object

True if this range is equivalent to the passed-in range.



93
94
95
# File 'lib/ip-ranges/range.rb', line 93

def ==(range)
  first == range.first && last == range.last
end

#contains_ip?(ip) ⇒ Boolean

Arguments

  • A String or an Ip object

True if the range contains the IP

Returns:

  • (Boolean)


114
115
116
117
# File 'lib/ip-ranges/range.rb', line 114

def contains_ip?(ip)
  test = ip.kind_of?(String) ? Ip.new(:number => ip) : ip
  test >= @first && @last >= test
end

#contains_range?(range) ⇒ Boolean

Arguments

  • A Range object

True if this range completely contains the passed-in range.

Returns:

  • (Boolean)


107
108
109
# File 'lib/ip-ranges/range.rb', line 107

def contains_range?(range)
  contains_ip?(range.first) && contains_ip?(range.last)
end

#each_ipObject

Yields each IP in the range, in turn, as an Ip object.



120
121
122
123
124
125
126
127
128
# File 'lib/ip-ranges/range.rb', line 120

def each_ip
  @counter = 0 # for throttling
  ip = first
  while last >= ip
    yield ip.dup
    ip.increment
    throttle
  end
end

#overlaps_range?(range) ⇒ Boolean

Arguments

  • A Range object

True if this range intersects with the passed-in range.

Returns:

  • (Boolean)


100
101
102
# File 'lib/ip-ranges/range.rb', line 100

def overlaps_range?(range)
  contains_ip?(range.first) || contains_ip?(range.last) || range.contains_ip?(first) || range.contains_ip?(last)
end

#push(ip) ⇒ Object

Arguments

  • An Ip object

Extend the range if the pushed IP is the next, contiguous ip in the range. Otherwise return false and do nothing.



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ip-ranges/range.rb', line 67

def push(ip)
  if empty?
    @first = ip
    @last  = ip
    true
  elsif ip.to_s == @last.dup.increment
    @last = ip
    true
  else
    false
  end
end

#to_sObject



54
55
56
57
58
59
60
61
62
# File 'lib/ip-ranges/range.rb', line 54

def to_s
  if empty?
    ''
  elsif first == last
    first.to_s
  else
    [first.to_s, last.to_s].join('..')
  end
end