ip 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|