ip 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/check-included.rb +27 -0
- data/examples/check-overlap.rb +26 -0
- data/examples/generate-a-records.rb +26 -0
- data/lib/ip.rb +9 -339
- data/lib/ip/address.rb +393 -0
- data/lib/ip/cidr.rb +192 -0
- data/lib/ip/range.rb +54 -0
- data/lib/ip/util.rb +144 -0
- data/test/ip.rb +394 -84
- metadata +10 -2
data/lib/ip/range.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# IP::Range - Calculates a range of IP addresses, and returns an
|
3
|
+
# Array of IP::Address objects.
|
4
|
+
#
|
5
|
+
# Usage::
|
6
|
+
#
|
7
|
+
# IP::Range['10.0.0.1', '10.0.0.2'] => IP::Address objects between
|
8
|
+
# 10.0.0.1 and 10.0.0.2 (inclusive)
|
9
|
+
#
|
10
|
+
# IP::Range can also take two IP::Address objects.
|
11
|
+
#
|
12
|
+
# Will throw a IP::AddressException if for some reason addresses
|
13
|
+
# cannot be parsed.
|
14
|
+
#
|
15
|
+
|
16
|
+
class IP::Range
|
17
|
+
|
18
|
+
#
|
19
|
+
# See the documentation for IP::Range for more information on this
|
20
|
+
# method.
|
21
|
+
#
|
22
|
+
|
23
|
+
def self.[](addr1, addr2)
|
24
|
+
raw1, raw2 = [nil, nil]
|
25
|
+
tmpip = nil
|
26
|
+
|
27
|
+
if addr1.kind_of? String
|
28
|
+
addr1 = IP::Address::Util.string_to_ip(addr1)
|
29
|
+
elsif ! addr1.kind_of? IP::Address
|
30
|
+
raise IP::AddressException.new("IP Address is not type String or IP::Address")
|
31
|
+
end
|
32
|
+
|
33
|
+
if addr2.kind_of? String
|
34
|
+
addr2 = IP::Address::Util.string_to_ip(addr2)
|
35
|
+
elsif ! addr2.kind_of? IP::Address
|
36
|
+
raise IP::AddressException.new("IP Address is not type String or IP::Address")
|
37
|
+
end
|
38
|
+
|
39
|
+
if addr2.class.name != addr1.class.name
|
40
|
+
raise IP::AddressException.new("First and Second IP in range are not of the same type")
|
41
|
+
end
|
42
|
+
|
43
|
+
raw1 = addr1.pack
|
44
|
+
raw2 = addr2.pack
|
45
|
+
|
46
|
+
range = []
|
47
|
+
|
48
|
+
# use the class we were given to force certain results, instead
|
49
|
+
# of relying on the fairly inaccurate unpack facility.
|
50
|
+
range = (raw1..raw2).collect { |x| addr1.class.new(x) }
|
51
|
+
|
52
|
+
return range
|
53
|
+
end
|
54
|
+
end
|
data/lib/ip/util.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
#
|
2
|
+
# General utility functions used by other IP classes.
|
3
|
+
#
|
4
|
+
|
5
|
+
module IP::Address::Util
|
6
|
+
#
|
7
|
+
# Pack an object into a long integer used for calculation. Returns a
|
8
|
+
# 'FixNum' type. Can take both IP::Address::IPv4 and
|
9
|
+
# IP::Address::IPv6 objects.
|
10
|
+
#
|
11
|
+
|
12
|
+
def pack(ip)
|
13
|
+
return ip.pack
|
14
|
+
end
|
15
|
+
|
16
|
+
module_function :pack
|
17
|
+
|
18
|
+
#
|
19
|
+
# This routine takes an array of integers which are intended to be
|
20
|
+
# an IP address, and joins them into a single integer used for easy
|
21
|
+
# calculation.
|
22
|
+
#
|
23
|
+
# IPv4 and IPv6 objects are packed into the same size, a 128-bit
|
24
|
+
# integer. This is done for easier processing within the library.
|
25
|
+
#
|
26
|
+
|
27
|
+
def raw_pack(array)
|
28
|
+
ret = 0
|
29
|
+
myip = array.reverse
|
30
|
+
8.times { |x| ret = ret | myip[x] << 16*x }
|
31
|
+
return ret
|
32
|
+
end
|
33
|
+
|
34
|
+
module_function :raw_pack
|
35
|
+
|
36
|
+
#
|
37
|
+
# Take an 'Integer' type and return an IP::Address object.
|
38
|
+
#
|
39
|
+
# This routine will 'guess' at what version of IP addressing you
|
40
|
+
# want, returning the oldest type possible (IPv4 addresses will
|
41
|
+
# return IP::Address::IPv4 objects).
|
42
|
+
#
|
43
|
+
# In almost all cases, you'll want to use the type-specific
|
44
|
+
# routines, which merely involve passing an Integer to the
|
45
|
+
# constructor for each class.
|
46
|
+
#
|
47
|
+
def unpack(ip)
|
48
|
+
ret = raw_unpack(ip)
|
49
|
+
|
50
|
+
# any IPv6 address should meet this criteria.
|
51
|
+
if ret[2..8].any? { |x| x > 0 }
|
52
|
+
return IP::Address::IPv6.new(ip)
|
53
|
+
end
|
54
|
+
|
55
|
+
return IP::Address::IPv4.new(ip)
|
56
|
+
end
|
57
|
+
|
58
|
+
module_function :unpack
|
59
|
+
|
60
|
+
#
|
61
|
+
# Take a 'FixNum' and return it's in-place octet
|
62
|
+
# representation. This is mostly a helper method for the unpack
|
63
|
+
# routines.
|
64
|
+
#
|
65
|
+
|
66
|
+
def raw_unpack(ip)
|
67
|
+
ret = []
|
68
|
+
8.times { |x| ret.push((ip >> 16*x) & 0xFFFF) }
|
69
|
+
return ret
|
70
|
+
end
|
71
|
+
|
72
|
+
module_function :raw_unpack
|
73
|
+
|
74
|
+
#
|
75
|
+
# Returns a short subnet mask - works for all IP::Address objects.
|
76
|
+
#
|
77
|
+
# ex:
|
78
|
+
# short_netmask(IP::Address::IPv4.new("255.255.255.255")) => 32
|
79
|
+
# short_netmask(IP::Address::IPv6.new("2001:0DB8:0000:CD30:0000:0000:0000:0000")) => 60
|
80
|
+
#
|
81
|
+
|
82
|
+
def short_netmask(ip)
|
83
|
+
#
|
84
|
+
# This method handles 128-bit integers better for both types of
|
85
|
+
# addresses, even though it is a bit slower.
|
86
|
+
#
|
87
|
+
# TODO: there really is probably a better way to do this.
|
88
|
+
#
|
89
|
+
|
90
|
+
s = ip.pack.to_s(2)
|
91
|
+
|
92
|
+
pad = 0
|
93
|
+
|
94
|
+
case ip.class.object_id
|
95
|
+
when IP::Address::IPv6.object_id
|
96
|
+
pad = 128
|
97
|
+
when IP::Address::IPv4.object_id
|
98
|
+
pad = 32
|
99
|
+
end
|
100
|
+
|
101
|
+
s = ("0" * (pad - s.length)) + s
|
102
|
+
|
103
|
+
return s.rindex("1") + 1
|
104
|
+
end
|
105
|
+
|
106
|
+
module_function :short_netmask
|
107
|
+
|
108
|
+
def long_netmask(short)
|
109
|
+
warn "This function is deprecated, please use IP::Address::Util.long_netmask_ipv4 instead."
|
110
|
+
return long_netmask_ipv4(short)
|
111
|
+
end
|
112
|
+
|
113
|
+
module_function :long_netmask
|
114
|
+
|
115
|
+
#
|
116
|
+
# Given a CIDR-notation "short" netmask, returns a IP::Address object containing
|
117
|
+
# the equivalent "long" netmask.
|
118
|
+
#
|
119
|
+
# ex:
|
120
|
+
# long_netmask(32) => IP::Address object of "255.255.255.255"
|
121
|
+
# long_netmask(28) => IP::Address object of "255.255.255.240"
|
122
|
+
#
|
123
|
+
|
124
|
+
def long_netmask_ipv4(short)
|
125
|
+
raw = (0xFFFFFFFF << (32 - short)) & 0xFFFFFFFF
|
126
|
+
return IP::Address::Util.unpack(raw)
|
127
|
+
end
|
128
|
+
|
129
|
+
module_function :long_netmask_ipv4
|
130
|
+
|
131
|
+
#
|
132
|
+
# This takes a string which supposedly contains an IP address, and
|
133
|
+
# tries to figure out if it is a IPv6 or IPv4 address. Returns a
|
134
|
+
# constructed object of the proper type.
|
135
|
+
#
|
136
|
+
|
137
|
+
def string_to_ip(s)
|
138
|
+
return IP::Address::IPv6.new(s) if s.match(/:/)
|
139
|
+
return IP::Address::IPv4.new(s)
|
140
|
+
end
|
141
|
+
|
142
|
+
module_function :string_to_ip
|
143
|
+
|
144
|
+
end
|
data/test/ip.rb
CHANGED
@@ -7,8 +7,9 @@ class CIDRTest < Test::Unit::TestCase
|
|
7
7
|
return "IP::CIDR tests"
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def test_init_generic
|
11
11
|
a = nil
|
12
|
+
|
12
13
|
begin
|
13
14
|
IP::CIDR.new(Hash.new)
|
14
15
|
a = false
|
@@ -16,52 +17,112 @@ class CIDRTest < Test::Unit::TestCase
|
|
16
17
|
a = true
|
17
18
|
end
|
18
19
|
|
19
|
-
assert(a, "
|
20
|
+
assert(a, "only accepts string")
|
21
|
+
|
22
|
+
begin
|
23
|
+
IP::CIDR.new("foomatic_wootmaster/32")
|
24
|
+
a = false
|
25
|
+
rescue IP::AddressException => e
|
26
|
+
a = true
|
27
|
+
end
|
20
28
|
|
29
|
+
assert(a, "ensures we have a IP address")
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_init_ipv6
|
33
|
+
a = nil
|
34
|
+
|
21
35
|
begin
|
22
|
-
IP::CIDR.new("
|
36
|
+
IP::CIDR.new("F00F:DEAD:BEEF::")
|
23
37
|
a = false
|
24
38
|
rescue IP::AddressException => e
|
25
39
|
a = true
|
26
40
|
end
|
41
|
+
|
42
|
+
assert(a, "no subnet")
|
43
|
+
|
44
|
+
begin
|
45
|
+
IP::CIDR.new("F00F:DEAD:BEEF::/")
|
46
|
+
a = false
|
47
|
+
rescue IP::AddressException => e
|
48
|
+
a = true
|
49
|
+
end
|
50
|
+
|
51
|
+
assert(a, "subnet marker, no integer")
|
27
52
|
|
28
|
-
|
53
|
+
begin
|
54
|
+
IP::CIDR.new("F00F:DEAD:BEEF::/asdf/32")
|
55
|
+
a = false
|
56
|
+
rescue IP::AddressException => e
|
57
|
+
a = true
|
58
|
+
end
|
59
|
+
|
60
|
+
assert(a, "'two' subnets")
|
61
|
+
|
62
|
+
begin
|
63
|
+
IP::CIDR.new("F00F:DEAD:BEEF::/foomatic_wootmaster")
|
64
|
+
a = false
|
65
|
+
rescue IP::AddressException => e
|
66
|
+
a = true
|
67
|
+
end
|
68
|
+
|
69
|
+
assert(a, "junk subnet")
|
70
|
+
|
71
|
+
begin
|
72
|
+
IP::CIDR.new("F00F:DEAD:BEEF::/255.255.255.255")
|
73
|
+
a = false
|
74
|
+
rescue IP::AddressException => e
|
75
|
+
a = true
|
76
|
+
end
|
77
|
+
|
78
|
+
assert(a, "ipv4 long subnet on ipv6")
|
79
|
+
|
80
|
+
cidr = IP::CIDR.new("F00F:DEAD:BEEF::0001/128")
|
81
|
+
|
82
|
+
# this sort of indirectly tests the ipv6 address manipulation.
|
83
|
+
assert(cidr.ip.short_address == "F00F:DEAD:BEEF::1", "ipv6 object constructed clean")
|
84
|
+
assert(cidr.mask == 128, "mask is set properly")
|
85
|
+
assert(cidr.cidr == "F00F:DEAD:BEEF::0001/128", "original CIDR preserved")
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_init_ipv4
|
89
|
+
a = nil
|
29
90
|
|
30
91
|
begin
|
31
|
-
IP::CIDR.new("10.0.0.1
|
92
|
+
IP::CIDR.new("10.0.0.1")
|
32
93
|
a = false
|
33
94
|
rescue IP::AddressException => e
|
34
95
|
a = true
|
35
96
|
end
|
36
97
|
|
37
|
-
assert(a, "data
|
98
|
+
assert(a, "ipv4 data validation test #1")
|
38
99
|
|
39
100
|
begin
|
40
|
-
IP::CIDR.new("10.0.0.1/
|
101
|
+
IP::CIDR.new("10.0.0.1/")
|
41
102
|
a = false
|
42
103
|
rescue IP::AddressException => e
|
43
104
|
a = true
|
44
105
|
end
|
45
|
-
|
46
|
-
assert(a, "data
|
106
|
+
|
107
|
+
assert(a, "ipv4 data validation test #2")
|
47
108
|
|
48
109
|
begin
|
49
|
-
IP::CIDR.new("10.0.0.1/
|
110
|
+
IP::CIDR.new("10.0.0.1/asdf/32")
|
50
111
|
a = false
|
51
112
|
rescue IP::AddressException => e
|
52
113
|
a = true
|
53
114
|
end
|
54
115
|
|
55
|
-
assert(a, "data
|
56
|
-
|
116
|
+
assert(a, "ipv4 data validation test #3")
|
117
|
+
|
57
118
|
begin
|
58
|
-
IP::CIDR.new("foomatic_wootmaster
|
119
|
+
IP::CIDR.new("10.0.0.1/foomatic_wootmaster")
|
59
120
|
a = false
|
60
121
|
rescue IP::AddressException => e
|
61
122
|
a = true
|
62
123
|
end
|
63
|
-
|
64
|
-
assert(a, "data
|
124
|
+
|
125
|
+
assert(a, "ipv4 data validation test #4")
|
65
126
|
|
66
127
|
begin
|
67
128
|
IP::CIDR.new("10.0.0.1/255")
|
@@ -70,54 +131,94 @@ class CIDRTest < Test::Unit::TestCase
|
|
70
131
|
a = true
|
71
132
|
end
|
72
133
|
|
73
|
-
assert(a, "data
|
134
|
+
assert(a, "ipv4 data validation test #5")
|
74
135
|
|
75
136
|
cidr = IP::CIDR.new("10.0.0.1/32")
|
76
137
|
|
77
|
-
assert(cidr.ip.ip_address == "10.0.0.1", "data integrity test #1")
|
78
|
-
assert(cidr.mask == 32, "data integrity test #2")
|
79
|
-
assert(cidr.cidr == "10.0.0.1/32", "data integrity test #3")
|
138
|
+
assert(cidr.ip.ip_address == "10.0.0.1", "ipv4 data integrity test #1")
|
139
|
+
assert(cidr.mask == 32, "ipv4 data integrity test #2")
|
140
|
+
assert(cidr.cidr == "10.0.0.1/32", "ipv4 data integrity test #3")
|
80
141
|
|
81
142
|
cidr = IP::CIDR.new("10.0.0.1/255.255.255.255")
|
82
143
|
|
83
|
-
assert(cidr.ip.ip_address == "10.0.0.1", "data integrity test #4")
|
84
|
-
assert(cidr.mask == 32, "data integrity test #5")
|
85
|
-
assert(cidr.cidr == "10.0.0.1/255.255.255.255", "data integrity test #6")
|
144
|
+
assert(cidr.ip.ip_address == "10.0.0.1", "ipv4 data integrity test #4")
|
145
|
+
assert(cidr.mask == 32, "ipv4 data integrity test #5")
|
146
|
+
assert(cidr.cidr == "10.0.0.1/255.255.255.255", "ipv4 data integrity test #6")
|
86
147
|
end
|
87
148
|
|
88
149
|
def test_netmasks
|
89
|
-
|
90
|
-
assert(cidr.short_netmask == 32, "netmask test #1")
|
91
|
-
assert(cidr.long_netmask.ip_address == "255.255.255.255", "netmask test #2")
|
150
|
+
a = nil
|
92
151
|
|
93
|
-
cidr = IP::CIDR.new("10.0.0.1/
|
94
|
-
assert(cidr.short_netmask ==
|
95
|
-
assert(cidr.long_netmask.ip_address == "255.255.255.
|
152
|
+
cidr = IP::CIDR.new("10.0.0.1/32")
|
153
|
+
assert(cidr.short_netmask == 32, "ipv4 netmask test #1")
|
154
|
+
assert(cidr.long_netmask.ip_address == "255.255.255.255", "ipv4 netmask test #2")
|
155
|
+
|
156
|
+
cidr = IP::CIDR.new("10.0.0.1/255.255.255.248")
|
157
|
+
assert(cidr.short_netmask == 29, "ipv4 netmask test #3")
|
158
|
+
assert(cidr.long_netmask.ip_address == "255.255.255.248", "ipv4 netmask test #4")
|
159
|
+
|
160
|
+
cidr = IP::CIDR.new("F00F:DEAD::/16")
|
161
|
+
assert(cidr.short_netmask == 16, "ipv6 has proper short netmask")
|
162
|
+
|
163
|
+
begin
|
164
|
+
cidr.long_netmask
|
165
|
+
a = false
|
166
|
+
rescue IP::AddressException => e
|
167
|
+
a = true
|
168
|
+
end
|
169
|
+
|
170
|
+
assert(a, "ipv6 cannot use a long netmask")
|
96
171
|
end
|
97
172
|
|
98
173
|
def test_first_last
|
99
174
|
cidr = IP::CIDR.new("10.0.0.2/24")
|
100
|
-
assert(cidr.first_ip.ip_address == "10.0.0.0", "first/last test #1")
|
101
|
-
assert(cidr.last_ip.ip_address == "10.0.0.255", "first/last test #2")
|
175
|
+
assert(cidr.first_ip.ip_address == "10.0.0.0", "ipv4 first/last test #1")
|
176
|
+
assert(cidr.last_ip.ip_address == "10.0.0.255", "ipv4 first/last test #2")
|
102
177
|
end
|
103
178
|
|
104
179
|
def test_range
|
105
180
|
cidr = IP::CIDR.new("10.0.0.2/24")
|
106
|
-
assert(cidr.range.find_all { |x| x.ip_address == "10.0.0.1" }.length == 1, "range test #1")
|
107
|
-
assert(cidr.range.find_all { |x| x.ip_address == "10.0.1.0" }.length == 0, "range test #2")
|
181
|
+
assert(cidr.range.find_all { |x| x.ip_address == "10.0.0.1" }.length == 1, "ipv4 range test #1")
|
182
|
+
assert(cidr.range.find_all { |x| x.ip_address == "10.0.1.0" }.length == 0, "ipv4 range test #2")
|
183
|
+
|
184
|
+
cidr = IP::CIDR.new("::0001/120")
|
185
|
+
assert(cidr.range.find_all { |x| x.ip_address == "0:0:0:0:0:0:0:00FF" }.length == 1, "ipv6 range test (included)")
|
186
|
+
assert(cidr.range.find_all { |x| x.ip_address ==" 0:0:0:0:0:0:0:0F00" }.length == 0, "ipv6 range test (not included)")
|
108
187
|
end
|
109
188
|
|
110
189
|
def test_overlaps
|
111
190
|
cidr = IP::CIDR.new("10.0.0.2/24")
|
112
191
|
cidr2 = IP::CIDR.new("10.0.0.1/29")
|
113
192
|
|
114
|
-
assert(cidr.overlaps?(cidr2), "overlaps test #1")
|
193
|
+
assert(cidr.overlaps?(cidr2), "ipv4 overlaps test #1")
|
115
194
|
|
116
195
|
cidr2 = IP::CIDR.new("10.0.0.1/16")
|
117
196
|
|
118
|
-
assert(cidr2.overlaps?(cidr), "overlaps test #2")
|
119
|
-
assert(cidr.overlaps?(cidr2), "overlaps test #3")
|
197
|
+
assert(cidr2.overlaps?(cidr), "ipv4 overlaps test #2")
|
198
|
+
assert(cidr.overlaps?(cidr2), "ipv4 overlaps test #3")
|
199
|
+
|
200
|
+
cidr = IP::CIDR.new("F00F:DEAD::/16")
|
201
|
+
cidr2 = IP::CIDR.new("F00F:BEEF::/16")
|
202
|
+
|
203
|
+
assert(cidr.overlaps?(cidr2), "ipv6 #overlaps? reports correctly #1")
|
204
|
+
assert(cidr2.overlaps?(cidr), "ipv6 #overlaps? reports correctly #2")
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_includes
|
208
|
+
cidr = IP::CIDR.new("10.0.0.2/24")
|
209
|
+
ip = IP::Address::IPv4.new("10.0.0.1")
|
210
|
+
|
211
|
+
assert(cidr.includes?(ip), "ipv4 #includes? reports correctly (included)")
|
212
|
+
ip = IP::Address::IPv4.new("10.0.1.0")
|
213
|
+
assert(!cidr.includes?(ip), "ipv4 #includes? reports correctly (not included)")
|
214
|
+
|
215
|
+
cidr = IP::CIDR.new("FF00::/16")
|
216
|
+
ip = IP::Address::IPv6.new("FF00::DEAD")
|
217
|
+
assert(cidr.includes?(ip), "ipv6 #includes? reports correctly (included)")
|
218
|
+
ip = IP::Address::IPv6.new("F000::DEAD")
|
219
|
+
assert(!cidr.includes?(ip), "ipv6 #includes? reports correctly (not included)")
|
120
220
|
end
|
221
|
+
|
121
222
|
end
|
122
223
|
|
123
224
|
class RangeTest < Test::Unit::TestCase
|
@@ -125,7 +226,75 @@ class RangeTest < Test::Unit::TestCase
|
|
125
226
|
return "IP::Range tests"
|
126
227
|
end
|
127
228
|
|
128
|
-
def
|
229
|
+
def test_range_generic
|
230
|
+
a = nil
|
231
|
+
begin
|
232
|
+
IP::Range[Hash.new, ""]
|
233
|
+
a = false
|
234
|
+
rescue Exception => e
|
235
|
+
a = true
|
236
|
+
end
|
237
|
+
|
238
|
+
assert(a, "generic data types test #1")
|
239
|
+
|
240
|
+
begin
|
241
|
+
IP::Range["", Hash.new]
|
242
|
+
a = false
|
243
|
+
rescue Exception => e
|
244
|
+
a = true
|
245
|
+
end
|
246
|
+
|
247
|
+
assert(a, "generic data types test #2")
|
248
|
+
|
249
|
+
begin
|
250
|
+
IP::Range[IP::Address::IPv6.new("F00F::"), IP::Address::IPv4.new("10.0.0.1")]
|
251
|
+
a = false
|
252
|
+
rescue Exception => e
|
253
|
+
a = true
|
254
|
+
end
|
255
|
+
|
256
|
+
assert(a, "generic data types test #3")
|
257
|
+
|
258
|
+
begin
|
259
|
+
IP::Range[IP::Address::IPv4.new("10.0.0.1"), IP::Address::IPv6.new("F00F::")]
|
260
|
+
a = false
|
261
|
+
rescue Exception => e
|
262
|
+
a = true
|
263
|
+
end
|
264
|
+
|
265
|
+
assert(a, "generic data types test #4")
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_range_ipv6
|
269
|
+
a = nil
|
270
|
+
|
271
|
+
begin
|
272
|
+
IP::Range["::0001", "::00F0"]
|
273
|
+
a = true
|
274
|
+
rescue Exception => e
|
275
|
+
a = false
|
276
|
+
end
|
277
|
+
|
278
|
+
assert(a, "ipv6 data types test #1")
|
279
|
+
|
280
|
+
begin
|
281
|
+
IP::Range[IP::Address::IPv6.new("::0001"), IP::Address::IPv6.new("::00F0")]
|
282
|
+
a = true
|
283
|
+
rescue Exception => e
|
284
|
+
a = false
|
285
|
+
end
|
286
|
+
|
287
|
+
assert(a, "ipv6 data types test #2")
|
288
|
+
|
289
|
+
range = IP::Range["::0001", "::0010"]
|
290
|
+
|
291
|
+
assert(range.find_all { |x| x.short_address == "::1" }.length == 1, "ipv6 range check #1")
|
292
|
+
assert(range.find_all { |x| x.short_address == "::0010" }.length == 1, "ipv6 range check #2")
|
293
|
+
assert(range.find_all { |x| x.short_address == "::000A" }.length == 1, "ipv6 range check #3")
|
294
|
+
assert(range.find_all { |x| x.short_address == "::0011" }.length == 0, "ipv6 range check #4")
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_range_ipv4
|
129
298
|
a = nil
|
130
299
|
begin
|
131
300
|
IP::Range["10.0.0.1", "10.0.0.2"]
|
@@ -134,37 +303,205 @@ class RangeTest < Test::Unit::TestCase
|
|
134
303
|
a = false
|
135
304
|
end
|
136
305
|
|
137
|
-
assert(a, "data types test #1")
|
306
|
+
assert(a, "ipv4 data types test #1")
|
138
307
|
|
139
308
|
begin
|
140
|
-
IP::Range[IP::Address.new("10.0.0.1"), IP::Address.new("10.0.0.2")]
|
309
|
+
IP::Range[IP::Address::IPv4.new("10.0.0.1"), IP::Address::IPv4.new("10.0.0.2")]
|
141
310
|
a = true
|
142
311
|
rescue Exception => e
|
143
312
|
a = false
|
144
313
|
end
|
145
314
|
|
146
|
-
assert(a, "data types test #2")
|
315
|
+
assert(a, "ipv4 data types test #2")
|
147
316
|
|
148
317
|
range = IP::Range["10.0.0.1", "10.0.0.10"]
|
149
318
|
|
150
|
-
assert(range.find_all { |x| x.ip_address == "10.0.0.1" }.length == 1, "range check #1")
|
151
|
-
assert(range.find_all { |x| x.ip_address == "10.0.0.10" }.length == 1, "range check #2")
|
152
|
-
assert(range.find_all { |x| x.ip_address == "10.0.0.7" }.length == 1, "range check #3")
|
153
|
-
assert(range.find_all { |x| x.ip_address == "10.0.0.11" }.length == 0, "range check #4")
|
319
|
+
assert(range.find_all { |x| x.ip_address == "10.0.0.1" }.length == 1, "ipv4 range check #1")
|
320
|
+
assert(range.find_all { |x| x.ip_address == "10.0.0.10" }.length == 1, "ipv4 range check #2")
|
321
|
+
assert(range.find_all { |x| x.ip_address == "10.0.0.7" }.length == 1, "ipv4 range check #3")
|
322
|
+
assert(range.find_all { |x| x.ip_address == "10.0.0.11" }.length == 0, "ipv4 range check #4")
|
323
|
+
end
|
154
324
|
|
325
|
+
end
|
326
|
+
|
327
|
+
class IPv6AddressTest < Test::Unit::TestCase
|
328
|
+
def name
|
329
|
+
return "IP::Address::IPv6 tests"
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_init
|
333
|
+
a = nil
|
334
|
+
|
335
|
+
# test the good data first...
|
336
|
+
|
337
|
+
begin
|
338
|
+
IP::Address::IPv6.new("0000:0000:0000:0000:0000:0000:0000:0001")
|
339
|
+
a = true
|
340
|
+
rescue IP::AddressException => e
|
341
|
+
a = false
|
342
|
+
end
|
343
|
+
|
344
|
+
assert(a, "full address")
|
345
|
+
|
346
|
+
begin
|
347
|
+
IP::Address::IPv6.new("::0001")
|
348
|
+
a = true
|
349
|
+
rescue IP::AddressException => e
|
350
|
+
a = false
|
351
|
+
end
|
352
|
+
|
353
|
+
assert(a, "wildcard address, wildcard left")
|
354
|
+
|
355
|
+
begin
|
356
|
+
IP::Address::IPv6.new("FF00::")
|
357
|
+
a = true
|
358
|
+
rescue IP::AddressException => e
|
359
|
+
a = false
|
360
|
+
end
|
361
|
+
|
362
|
+
assert(a, "wildcard address, wildcard right")
|
363
|
+
|
364
|
+
begin
|
365
|
+
IP::Address::IPv6.new("FF00::0001")
|
366
|
+
a = true
|
367
|
+
rescue IP::AddressException => e
|
368
|
+
a = false
|
369
|
+
end
|
370
|
+
|
371
|
+
assert(a, "wildcard address, wildcard center")
|
372
|
+
|
373
|
+
begin
|
374
|
+
IP::Address::IPv6.new("FF00:BEEF::0001")
|
375
|
+
a = true
|
376
|
+
rescue IP::AddressException => e
|
377
|
+
a = false
|
378
|
+
end
|
379
|
+
|
380
|
+
assert(a, "wildcard address, wildcard center with two leading")
|
381
|
+
|
382
|
+
begin
|
383
|
+
IP::Address::IPv6.new("FF00::BEEF:0001")
|
384
|
+
a = true
|
385
|
+
rescue IP::AddressException => e
|
386
|
+
a = false
|
387
|
+
end
|
388
|
+
|
389
|
+
assert(a, "wildcard address, wildcard center with two trailing")
|
390
|
+
|
391
|
+
begin
|
392
|
+
IP::Address::IPv6.new("::1.2.3.4")
|
393
|
+
a = true
|
394
|
+
rescue IP::AddressException => e
|
395
|
+
puts e
|
396
|
+
a = false
|
397
|
+
end
|
398
|
+
|
399
|
+
assert(a, "IPv4 address in IPv6, wildcard left")
|
400
|
+
|
401
|
+
begin
|
402
|
+
IP::Address::IPv6.new("FFFF::1.2.3.4")
|
403
|
+
a = true
|
404
|
+
rescue IP::AddressException => e
|
405
|
+
a = false
|
406
|
+
end
|
407
|
+
|
408
|
+
assert(a, "IPv4 in IPv6, data on wildcard @ left")
|
409
|
+
|
410
|
+
begin
|
411
|
+
IP::Address::IPv6.new("FFFF:0000:0000:0000:0000:0000:1.2.3.4")
|
412
|
+
a = true
|
413
|
+
rescue IP::AddressException => e
|
414
|
+
a = false
|
415
|
+
end
|
416
|
+
|
417
|
+
assert(a, "IPv4 in IPv6, no wildcard")
|
418
|
+
|
419
|
+
# now, the tests that should fail
|
420
|
+
|
421
|
+
begin
|
422
|
+
IP::Address::IPv6.new("FF00:BEEF:")
|
423
|
+
a = false
|
424
|
+
rescue IP::AddressException => e
|
425
|
+
a = true
|
426
|
+
end
|
427
|
+
|
428
|
+
assert(a, "not enough octets")
|
429
|
+
|
430
|
+
begin
|
431
|
+
IP::Address::IPv6.new("FF00::BEEF::")
|
432
|
+
a = false
|
433
|
+
rescue IP::AddressException => e
|
434
|
+
a = true
|
435
|
+
end
|
436
|
+
|
437
|
+
assert(a, "double wildcard no trailer")
|
438
|
+
|
439
|
+
begin
|
440
|
+
IP::Address::IPv6.new("FF00::BEEF::DEAD")
|
441
|
+
a = false
|
442
|
+
rescue IP::AddressException => e
|
443
|
+
a = true
|
444
|
+
end
|
445
|
+
|
446
|
+
assert(a, "double wildcard w/ trailer")
|
447
|
+
|
448
|
+
begin
|
449
|
+
IP::Address::IPv6.new("HF00::0001")
|
450
|
+
a = false
|
451
|
+
rescue IP::AddressException => e
|
452
|
+
a = true
|
453
|
+
end
|
454
|
+
|
455
|
+
assert(a, "invalid hexidecimal")
|
456
|
+
|
457
|
+
begin
|
458
|
+
IP::Address::IPv6.new("1.2.3.4::0001")
|
459
|
+
a = false
|
460
|
+
rescue IP::AddressException => e
|
461
|
+
a = true
|
462
|
+
end
|
463
|
+
|
464
|
+
assert(a, "invalid IPv4 in IPv6")
|
465
|
+
|
466
|
+
end
|
467
|
+
|
468
|
+
def test_accessors
|
469
|
+
ip = IP::Address::IPv6.new("F00F::DEAD:BEEF")
|
470
|
+
|
471
|
+
assert(ip[0] == 61455 && ip.octet(0) == 61455, "#octet is integer representation, #[] is #octet")
|
472
|
+
assert(ip.octet_as_hex(0) == "F00F", "octet converts to hex properly")
|
473
|
+
assert(ip.ip_address == "F00F::DEAD:BEEF", '#ip_address preserves original address')
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_address
|
477
|
+
ip = IP::Address::IPv6.new("F00F::DEAD:BEEF")
|
478
|
+
assert(ip.short_address == "F00F::DEAD:BEEF", 'wildcard left - #short_address returns a compressed version')
|
479
|
+
assert(ip.long_address == "F00F:0:0:0:0:0:DEAD:BEEF", 'wildcard left - #long_address returns the right thing')
|
480
|
+
|
481
|
+
ip = IP::Address::IPv6.new("F00F:DEAD::BEEF")
|
482
|
+
assert(ip.short_address == "F00F:DEAD::BEEF", 'wildcard right - #short_address returns a compressed version')
|
483
|
+
assert(ip.long_address == "F00F:DEAD:0:0:0:0:0:BEEF", 'wildcard right - #long_address returns the right thing')
|
484
|
+
|
485
|
+
ip = IP::Address::IPv6.new("F00F:DEAD:0:0:0:0:0:BEEF")
|
486
|
+
assert(ip.short_address == "F00F:DEAD::BEEF", 'no wildcard - #short_address returns a compressed version')
|
487
|
+
assert(ip.long_address == "F00F:DEAD:0:0:0:0:0:BEEF", 'no wildcard - #long_address returns the right thing')
|
488
|
+
|
489
|
+
ip = IP::Address::IPv6.new("F00F::DEAD:BEEF:0:0")
|
490
|
+
assert(ip.short_address == "F00F:0:0:0:DEAD:BEEF::", '#short_address returns a compressed version with wildcard @ right')
|
155
491
|
end
|
156
492
|
|
157
493
|
end
|
158
494
|
|
159
|
-
|
495
|
+
|
496
|
+
class IPv4AddressTest < Test::Unit::TestCase
|
160
497
|
def name
|
161
|
-
return "IP::Address tests"
|
498
|
+
return "IP::Address::IPv4 tests"
|
162
499
|
end
|
163
500
|
|
164
501
|
def test_init
|
165
502
|
ip = nil
|
166
503
|
begin
|
167
|
-
ip = IP::Address.new(Hash.new)
|
504
|
+
ip = IP::Address::IPv4.new(Hash.new)
|
168
505
|
rescue IP::AddressException => e
|
169
506
|
assert(true, "init test #1")
|
170
507
|
end
|
@@ -174,7 +511,7 @@ class AddressTest < Test::Unit::TestCase
|
|
174
511
|
ip = nil
|
175
512
|
|
176
513
|
begin
|
177
|
-
ip = IP::Address.new("asdf")
|
514
|
+
ip = IP::Address::IPv4.new("asdf")
|
178
515
|
rescue IP::AddressException => e
|
179
516
|
assert(true, "init test #2")
|
180
517
|
end
|
@@ -183,7 +520,7 @@ class AddressTest < Test::Unit::TestCase
|
|
183
520
|
ip = nil
|
184
521
|
|
185
522
|
begin
|
186
|
-
ip = IP::Address.new("0.0.0")
|
523
|
+
ip = IP::Address::IPv4.new("0.0.0")
|
187
524
|
rescue IP::AddressException => e
|
188
525
|
assert(true, "init test #3")
|
189
526
|
end
|
@@ -192,7 +529,7 @@ class AddressTest < Test::Unit::TestCase
|
|
192
529
|
ip = nil
|
193
530
|
|
194
531
|
begin
|
195
|
-
ip = IP::Address.new("256.255.255.255")
|
532
|
+
ip = IP::Address::IPv4.new("256.255.255.255")
|
196
533
|
rescue IP::AddressException => e
|
197
534
|
assert(true, "init test #4")
|
198
535
|
end
|
@@ -201,7 +538,7 @@ class AddressTest < Test::Unit::TestCase
|
|
201
538
|
|
202
539
|
ip = nil
|
203
540
|
begin
|
204
|
-
ip = IP::Address.new("255.255.255.255aaaa")
|
541
|
+
ip = IP::Address::IPv4.new("255.255.255.255aaaa")
|
205
542
|
rescue IP::AddressException => e
|
206
543
|
assert(true, "init test #5")
|
207
544
|
end
|
@@ -210,7 +547,7 @@ class AddressTest < Test::Unit::TestCase
|
|
210
547
|
|
211
548
|
ip = nil
|
212
549
|
begin
|
213
|
-
ip = IP::Address.new("255.255.255.")
|
550
|
+
ip = IP::Address::IPv4.new("255.255.255.")
|
214
551
|
rescue IP::AddressException => e
|
215
552
|
assert(true, "init test #6")
|
216
553
|
end
|
@@ -220,7 +557,7 @@ class AddressTest < Test::Unit::TestCase
|
|
220
557
|
end
|
221
558
|
|
222
559
|
def test_accessor
|
223
|
-
ip = IP::Address.new("10.1.2.3")
|
560
|
+
ip = IP::Address::IPv4.new("10.1.2.3")
|
224
561
|
assert(ip.ip_address == "10.1.2.3", "accessor test #1")
|
225
562
|
assert(ip.octets[0] == 10, "accessor test #2")
|
226
563
|
assert(ip.octets[3] == 3, "accessor test #3")
|
@@ -248,46 +585,19 @@ class UtilTest < Test::Unit::TestCase
|
|
248
585
|
|
249
586
|
def test_pack_unpack
|
250
587
|
address = "10.0.0.1"
|
251
|
-
assert(IP::Address::Util.unpack(IP::Address::Util.pack(IP::Address.new(address))).ip_address == address, "pack/unpack test")
|
588
|
+
assert(IP::Address::Util.unpack(IP::Address::Util.pack(IP::Address::IPv4.new(address))).ip_address == address, "pack/unpack test")
|
252
589
|
end
|
253
590
|
|
254
591
|
def test_short_netmask
|
255
|
-
ip = IP::Address.new("255.255.255.255")
|
592
|
+
ip = IP::Address::IPv4.new("255.255.255.255")
|
256
593
|
assert(IP::Address::Util.short_netmask(ip) == 32, "Short Netmask Test #1")
|
257
|
-
ip = IP::Address.new("255.255.255.
|
594
|
+
ip = IP::Address::IPv4.new("255.255.255.248")
|
258
595
|
assert(IP::Address::Util.short_netmask(ip) == 29, "Short Netmask Test #2")
|
259
|
-
|
260
|
-
nm = nil
|
261
|
-
|
262
|
-
begin
|
263
|
-
nm = IP::Address::Util.short_netmask(IP::Address.new("255.255.0.255"))
|
264
|
-
rescue IP::BoundaryException => e
|
265
|
-
assert(true, "Short Netmask BoundaryException Check #1")
|
266
|
-
end
|
267
|
-
|
268
|
-
assert(false, "Short Netmask BoundaryException Check #1") if nm
|
269
|
-
|
270
|
-
nm = nil
|
271
|
-
|
272
|
-
begin
|
273
|
-
nm = IP::Address::Util.short_netmask(IP::Address.new("255.255.240.255"))
|
274
|
-
rescue IP::BoundaryException => e
|
275
|
-
assert(true, "Short Netmask BoundaryException check #2")
|
276
|
-
end
|
277
|
-
|
278
|
-
assert(false, "Short Netmask BoundaryException check #2") if nm
|
279
596
|
end
|
280
597
|
|
281
598
|
def test_long_netmask
|
282
|
-
assert(IP::Address::Util.
|
283
|
-
assert(IP::Address::Util.
|
284
|
-
end
|
285
|
-
|
286
|
-
def test_binary_vector
|
287
|
-
assert(IP::Address::Util.binary_vector(255).length == 8, "Binary Vector Test #1")
|
288
|
-
assert(IP::Address::Util.binary_vector(240).find_all { |x| x == 1 }.length == 4, "Binary Vector Test #2")
|
289
|
-
assert(IP::Address::Util.binary_vector(241).find_all { |x| x == 1 }.length == 5, "Binary Vector Test #3")
|
290
|
-
assert(IP::Address::Util.binary_vector(240)[0] == 1, "Binary Vector Test #4")
|
599
|
+
assert(IP::Address::Util.long_netmask_ipv4(32).ip_address == "255.255.255.255", "Long Netmask Test #1")
|
600
|
+
assert(IP::Address::Util.long_netmask_ipv4(29).ip_address == "255.255.255.248", "Long Netmask Test #2")
|
291
601
|
end
|
292
602
|
|
293
603
|
end
|