Class: IP::CIDR

Inherits:
Object
  • Object
show all
Defined in:
lib/ip/cidr.rb

Overview

IP::CIDR - Works with Classless Inter-Domain Routing formats, such as 10.0.0.1/32 or 10.0.0.1/255.255.255.255

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cidr) ⇒ CIDR

Given a string of format X.X.X.X/X, in standard CIDR notation, this will construct a IP::CIDR object.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/ip/cidr.rb', line 26

def initialize(cidr)
  if !cidr.kind_of? String
    raise IP::AddressException.new("CIDR value is not of type String")
  end

  @cidr = cidr
  @ip, @mask = cidr.split(/\//, 2)

  @ip = IP::Address::Util.string_to_ip(@ip)

  if @ip.nil? or @mask.nil?
    raise IP::AddressException.new("CIDR is not valid - invalid format")
  end

  if @mask.length == 0 or /[^0-9.]/.match @mask or
      (@ip.kind_of? IP::Address::IPv6 and @mask.to_i.to_s != @mask)
    raise IP::AddressException.new("CIDR RHS is not valid - #{@mask}")
  end

  if @ip.kind_of? IP::Address::IPv4 and @mask.length > 2
    # get the short netmask for IPv4 - this will throw an exception if the netmask is malformed.
    @mask = IP::Address::Util.short_netmask(IP::Address::IPv4.new(@mask))
  end

  @mask = @mask.to_i
end

Instance Attribute Details

#cidrObject (readonly)

Contains the original CIDR you fed it, returned as a string.



10
11
12
# File 'lib/ip/cidr.rb', line 10

def cidr
  @cidr
end

#ipObject (readonly)

Contains the IP address (LHS) only. Returned as an IP::Address object.



15
16
17
# File 'lib/ip/cidr.rb', line 15

def ip
  @ip
end

#maskObject (readonly)

Contains the integer-based (short) netmask (RHS) only. Returned as an integer.



20
21
22
# File 'lib/ip/cidr.rb', line 20

def mask
  @mask
end

Instance Method Details

#first_ipObject

This returns the first ip address of the cidr as an IP::Address object.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ip/cidr.rb', line 92

def first_ip
  rawip = @ip.pack

  #
  # since our actual mask calculation is done with the full 128 bits,
  # we have to shift calculations that we want in IPv4 to the left to
  # get proper return values.
  #

  if @ip.kind_of? IP::Address::IPv4
    rawip = rawip << 96
  end

  rawnm = (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) << (128 - @mask)
  lower = rawip & rawnm

  if @ip.kind_of? IP::Address::IPv4
    lower = lower & (0xFFFFFFFF000000000000000000000000)
    lower = lower >> 96
  end

  case @ip.class.object_id
  when IP::Address::IPv4.object_id
    return IP::Address::IPv4.new(lower)
  when IP::Address::IPv6.object_id
    return IP::Address::IPv6.new(lower)
  else
    raise IP::AddressException.new("Cannot determine type of IP address")
  end

end

#includes?(address) ⇒ Boolean

Given an IP::Address object, will determine if it is included in the current subnet. This does not generate a range and is comparatively much faster.

This will not generate an exception when IPv4 objects are compared to IPv6, and vice-versa. This is intentional.

Returns:

  • (Boolean)

Raises:

  • (TypeError)


182
183
184
185
186
187
188
189
190
# File 'lib/ip/cidr.rb', line 182

def includes?(address)
  raise TypeError.new("Expected type of IP::Address or derived") unless (address.kind_of? IP::Address)

  raw   = address.pack
  first = first_ip.pack
  last  = last_ip.pack

  return (raw >= first) && (raw <= last)
end

#last_ipObject

This returns the last ip address of the cidr as an IP::Address object.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ip/cidr.rb', line 127

def last_ip
  rawip = @ip.pack

  # see #first_ip for the reason that we shift this way for IPv4.
  if @ip.kind_of? IP::Address::IPv4
    rawip = rawip << 96
  end

  rawnm = (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) << (128 - @mask)
  upper = rawip | ~rawnm

  if @ip.kind_of? IP::Address::IPv4
    upper = upper & (0xFFFFFFFF000000000000000000000000)
    upper = upper >> 96
  end

  case @ip.class.object_id
  when IP::Address::IPv4.object_id
    return IP::Address::IPv4.new(upper)
  when IP::Address::IPv6.object_id
    return IP::Address::IPv6.new(upper)
  else
    raise IP::AddressException.new("Cannot determine type of IP address")
  end
end

#long_netmaskObject

This produces the long netmask (eg. 255.255.255.255) of the CIDR in an IP::Address object.

This will throw an exception for IPv6 addresses.



64
65
66
67
68
69
70
# File 'lib/ip/cidr.rb', line 64

def long_netmask
  if @ip.kind_of? IP::Address::IPv6
    raise IP::AddressException.new("IPv6 does not support a long netmask.")
  end

  return IP::Address::Util.long_netmask_ipv4(@mask)
end

#netmaskObject



53
54
55
56
# File 'lib/ip/cidr.rb', line 53

def netmask
  warn "IP::CIDR#netmask is deprecated. Please use IP::CIDR#long_netmask instead."
  return self.long_netmask
end

#overlaps?(other_cidr) ⇒ Boolean

This will take another IP::CIDR object as an argument and check to see if it overlaps with this cidr object. Returns true/false on overlap.

This also throws a TypeError if passed invalid data.

Returns:

  • (Boolean)

Raises:

  • (TypeError)


159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/ip/cidr.rb', line 159

def overlaps?(other_cidr)
  raise TypeError.new("Expected object of type IP::CIDR") unless(other_cidr.kind_of?(IP::CIDR))

  myfirst = self.first_ip.pack
  mylast = self.last_ip.pack

  otherfirst = other_cidr.first_ip.pack
  otherlast = other_cidr.last_ip.pack

  return ((myfirst >= otherfirst && myfirst <= otherlast) ||
            (mylast <= otherlast && mylast >= otherfirst) ||
            (otherfirst >= myfirst && otherfirst <= mylast)) ? true : false;
end

#rangeObject

This produces a range ala IP::Range, but only for the subnet defined by the CIDR object.



85
86
87
# File 'lib/ip/cidr.rb', line 85

def range
  return IP::Range[self.first_ip, self.last_ip]
end

#short_netmaskObject

This produces the short netmask (eg. 32) of the CIDR in an IP::Address object.



77
78
79
# File 'lib/ip/cidr.rb', line 77

def short_netmask
  return @mask
end