ipaddress 0.7.5 → 0.8.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/CHANGELOG.rdoc +13 -0
- data/README.rdoc +106 -80
- data/VERSION +1 -1
- data/ipaddress.gemspec +55 -0
- data/lib/ipaddress.rb +16 -2
- data/lib/ipaddress/ipv4.rb +76 -68
- data/lib/ipaddress/ipv6.rb +132 -22
- data/lib/ipaddress/prefix.rb +14 -1
- data/test/ipaddress/ipv4_test.rb +65 -43
- data/test/ipaddress/ipv6_test.rb +68 -2
- metadata +26 -48
- data/lib/ipaddress/extensions/extensions.rb +0 -22
- data/test/ipaddress/extensions/extensions_test.rb +0 -18
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== ipaddress 0.8.0
|
2
|
+
|
3
|
+
CHANGED:: Removed extension methods and extension directory to facilitate integration with the stdlib
|
4
|
+
CHANGED:: Reworked IPv4#<=>, now intuitively sorts objects based on the prefix
|
5
|
+
CHANGED:: IPv4#supernet now returns "0.0.0.0/0" if supernetting with a prefix less than 1
|
6
|
+
CHANGED:: IPv4#subnet now accept a new prefix instead of number of subnets (as per RFC3531)
|
7
|
+
NEW:: IPv6#network
|
8
|
+
NEW:: Prefix128#host_prefix
|
9
|
+
NEW:: IPv6#broadcast_u128
|
10
|
+
NEW:: IPv6#each
|
11
|
+
NEW:: IPv6#<=>
|
12
|
+
NEW:: IPv4#split
|
13
|
+
|
1
14
|
== ipaddress 0.7.5
|
2
15
|
|
3
16
|
CHANGED:: IPAddress::IPv4#each_host to improve speed
|
data/README.rdoc
CHANGED
@@ -14,44 +14,22 @@ examples of typical usage.
|
|
14
14
|
|
15
15
|
== Requirements
|
16
16
|
|
17
|
-
* Ruby >= 1.8.
|
17
|
+
* Ruby >= 1.8.7 (not tested with previous versions)
|
18
|
+
* Ruby 1.9.2 or later is strongly recommended
|
18
19
|
|
19
|
-
IPAddress
|
20
|
+
IPAddress 0.8.0 has been tested on:
|
20
21
|
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
27
|
-
* Ironruby >= 1.0
|
22
|
+
* ruby-1.8.7-p334 [ i386 ]
|
23
|
+
* ree-1.8.7-2011.03 [ i386 ]
|
24
|
+
* rbx-head [ ]
|
25
|
+
* jruby-1.6.1 [ linux-i386-java ]
|
26
|
+
* ruby-1.9.1-p431 [ i386 ]
|
27
|
+
* ruby-1.9.2-p180 [ i386 ]
|
28
28
|
|
29
|
-
|
29
|
+
If you want to collaborate feel
|
30
30
|
free to send a small report to my email address, or
|
31
31
|
{join the discussion}[http://groups.google.com/group/ruby-ipaddress].
|
32
32
|
|
33
|
-
== Why not using IPAddr?
|
34
|
-
|
35
|
-
IPAddr is the IP addresses library that comes with Ruby standard
|
36
|
-
lib. We found this library, although very well written, not very
|
37
|
-
suitable for all our needs, and not very flexible.
|
38
|
-
|
39
|
-
Some quick examples of things you can't do with IPAddr:
|
40
|
-
|
41
|
-
* store both the address and the prefix information
|
42
|
-
* quickly find the broadcast address of a network
|
43
|
-
* iterate over hosts
|
44
|
-
* perform subnetting or network aggregation
|
45
|
-
|
46
|
-
Many methods and procedures are so old that they have been
|
47
|
-
declared deprecated by the IETF, and some others have bugs in their
|
48
|
-
implementation.
|
49
|
-
|
50
|
-
Moreover, IPAddress is more robust and is already around 50% faster than IPAddr,
|
51
|
-
in addition to provide an organic API with logical separation and OO structure.
|
52
|
-
|
53
|
-
We hope that IPAddress will address all these issues and meet all your
|
54
|
-
needs in network programming.
|
55
33
|
|
56
34
|
== Installation
|
57
35
|
|
@@ -81,7 +59,7 @@ documentation with Rake:
|
|
81
59
|
ipaddress$ rake rdoc
|
82
60
|
|
83
61
|
The latest documentation can be found online at
|
84
|
-
{this address}[http://rubydoc.info/gems/ipaddress/0.
|
62
|
+
{this address}[http://rubydoc.info/gems/ipaddress/0.8.0/frames]
|
85
63
|
|
86
64
|
== IPv4
|
87
65
|
|
@@ -127,9 +105,12 @@ networks. Therefore, the default prefix will be /32, or
|
|
127
105
|
255.255.255.255. For example:
|
128
106
|
|
129
107
|
# let's declare an host address
|
130
|
-
host = IPAddress::IPv4.new "10.1.1.1
|
108
|
+
host = IPAddress::IPv4.new "10.1.1.1"
|
109
|
+
|
110
|
+
puts host.to_string
|
111
|
+
#=> "10.1.1.1/32"
|
131
112
|
|
132
|
-
The new created object
|
113
|
+
The new created object has prefix /32, which is the same
|
133
114
|
as we created the following:
|
134
115
|
|
135
116
|
host = IPAddress::IPv4.new "10.1.1.1/32"
|
@@ -222,7 +203,7 @@ address:
|
|
222
203
|
net.to_string
|
223
204
|
#=> "172.16.10.0/24"
|
224
205
|
|
225
|
-
|
206
|
+
Method IPv4#network creates a new IPv4 object from the network
|
226
207
|
number, calculated after the original object. We want to outline here
|
227
208
|
that the network address is a perfect legitimate IPv4 address, which
|
228
209
|
just happen to have all zeroes in the host portion.
|
@@ -402,63 +383,83 @@ For example, if you have network "172.16.10.0/24", we can subnet it
|
|
402
383
|
into 4 smaller subnets. The new prefix will be /26, because 4 is 2^2
|
403
384
|
and therefore we add 2 bits to the network prefix (24+2=26).
|
404
385
|
|
405
|
-
Subnetting is easy with IPAddress.
|
386
|
+
Subnetting is easy with IPAddress. You actually have two options:
|
406
387
|
|
407
|
-
|
388
|
+
* IPv4#subnet: specify a new prefix
|
389
|
+
* IPv4#split: tell IPAddress how many subnets you want to create.
|
408
390
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
391
|
+
Let's examine IPv4#subnet first. Say you have network "172.16.10.0/24"
|
392
|
+
and you want to subnet it into /26 networks. With IPAddress it's very
|
393
|
+
easy:
|
394
|
+
|
395
|
+
network = IPAddress "172.16.10.0/24"
|
396
|
+
|
397
|
+
subnets = network.subnet(26)
|
414
398
|
|
415
399
|
subnets.map{|i| i.to_string}
|
416
|
-
#=> ["172.16.10.0/26",
|
400
|
+
#=> ["172.16.10.0/26",
|
401
|
+
"172.16.10.64/26",
|
402
|
+
"172.16.10.128/26",
|
417
403
|
"172.16.10.192/26"]
|
418
404
|
|
419
|
-
|
420
|
-
|
421
|
-
calculate a subnet: if the IPv4 object is a host IPv4, the method will
|
422
|
-
calculate the network number for that network and then subnet it. For
|
423
|
-
example:
|
405
|
+
As you can see, an Array has been created, containing 4 new IPv4 objects
|
406
|
+
representing the new subnets.
|
424
407
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
408
|
+
Another way to create subnets is to tell IPAddress how many subnets you'd
|
409
|
+
like to have, and letting the library calculate the new prefix for you.
|
410
|
+
|
411
|
+
Let's see how it works, using IPv4#split method. Say you want 4 new subnets:
|
412
|
+
|
413
|
+
network = IPAddress("172.16.10.0/24")
|
414
|
+
|
415
|
+
subnets = network.split(4)
|
430
416
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
417
|
+
subnets.map{|i| i.to_string}
|
418
|
+
#=> ["172.16.10.0/26",
|
419
|
+
"172.16.10.64/26",
|
420
|
+
"172.16.10.128/26",
|
421
|
+
"172.16.10.192/26"]
|
435
422
|
|
436
|
-
|
423
|
+
Hey, that's the same result as before! This actually makes sense, as the
|
424
|
+
two operations are complementary. When you use IPv4#subnet with the new
|
425
|
+
prefix, IPAddress will always create a number of subnets that is a power
|
426
|
+
of two. This is equivalent to use IPv4#split with a power of 2.
|
437
427
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
428
|
+
Where IPv4#split really shines is with the so called "uneven subnetting".
|
429
|
+
You are not limited to split a network into a power-of-two numbers of
|
430
|
+
subnets: IPAddress lets you create any number of subnets, and it will
|
431
|
+
try to organize the new created network in the best possible way, making
|
432
|
+
an efficent allocation of the space.
|
442
433
|
|
443
|
-
|
434
|
+
An example here is worth a thousand words. Let's use the same network
|
435
|
+
as the previous examples:
|
444
436
|
|
445
437
|
network = IPAddress("172.16.10.0/24")
|
446
438
|
|
447
|
-
|
439
|
+
How do we split this network into 3 subnets? Very easy:
|
440
|
+
|
441
|
+
subnets = network.split(3)
|
442
|
+
|
443
|
+
subnets.map{|i| i.to_string}
|
448
444
|
#=> ["172.16.10.0/26",
|
449
445
|
"172.16.10.64/26",
|
450
446
|
"172.16.10.128/25"]
|
451
447
|
|
452
|
-
|
448
|
+
As you can see, IPAddress tried to perform a good allocation by filling up
|
449
|
+
all the address space from the original network. There is no point in splitting
|
450
|
+
a network into 3 subnets like "172.16.10.0/26", "172.16.10.64/26" and
|
451
|
+
"172.16.10.128/26", as you would end up having "172.16.10.192/26" wasted (plus,
|
452
|
+
I suppose I wouldn't need a Ruby library to perform un-efficient IP
|
453
|
+
allocation, as I do that myself very well ;) ).
|
453
454
|
|
454
|
-
|
455
|
+
We can go even further and split into 11 subnets:
|
455
456
|
|
456
|
-
network.
|
457
|
+
network.split(11)
|
457
458
|
#=> ["172.16.10.0/28", "172.16.10.16/28", "172.16.10.32/28",
|
458
459
|
"172.16.10.48/28", "172.16.10.64/28", "172.16.10.80/28",
|
459
460
|
"172.16.10.96/28", "172.16.10.112/28", "172.16.10.128/27",
|
460
461
|
"172.16.10.160/27", "172.16.10.192/26"]
|
461
|
-
|
462
|
+
|
462
463
|
As you can see, most of the networks are /28, with a few /27 and one
|
463
464
|
/26 to fill up the remaining space.
|
464
465
|
|
@@ -572,7 +573,7 @@ eight groups of four hexadecimal digits, each group representing 16
|
|
572
573
|
bits or two octet. For example, the following is a valid IPv6
|
573
574
|
address:
|
574
575
|
|
575
|
-
|
576
|
+
2001:0db8:0000:0000:0008:0800:200c:417a
|
576
577
|
|
577
578
|
Letters in an IPv6 address are usually written downcase, as per
|
578
579
|
RFC. You can create a new IPv6 object using uppercase letters, but
|
@@ -592,7 +593,7 @@ simplifications and compressions that you can use to shorten them.
|
|
592
593
|
Using compression, the IPv6 address written above can be shorten into
|
593
594
|
the following, equivalent, address
|
594
595
|
|
595
|
-
|
596
|
+
2001:db8::8:800:200c:417a
|
596
597
|
|
597
598
|
This short version is often used in human representation.
|
598
599
|
|
@@ -601,7 +602,7 @@ This short version is often used in human representation.
|
|
601
602
|
As we used to do with IPv4 addresses, an IPv6 address can be written
|
602
603
|
using the prefix notation to specify the subnet mask:
|
603
604
|
|
604
|
-
|
605
|
+
2001:db8::8:800:200c:417a/64
|
605
606
|
|
606
607
|
The /64 part means that the first 64 bits of the address are
|
607
608
|
representing the network portion, and the last 64 bits are the host
|
@@ -612,11 +613,11 @@ portion.
|
|
612
613
|
All the IPv6 representations we've just seen are perfectly fine when
|
613
614
|
you want to create a new IPv6 address:
|
614
615
|
|
615
|
-
ip6 = IPAddress "
|
616
|
+
ip6 = IPAddress "2001:0db8:0000:0000:0008:0800:200C:417A"
|
616
617
|
|
617
|
-
ip6 = IPAddress "
|
618
|
+
ip6 = IPAddress "2001:db8:0:0:8:800:200C:417A"
|
618
619
|
|
619
|
-
ip6 = IPAddress "
|
620
|
+
ip6 = IPAddress "2001:db8:8:800:200C:417A"
|
620
621
|
|
621
622
|
All three are giving out the same IPv6 object. The default subnet mask
|
622
623
|
for an IPv6 is 128, as IPv6 addresses don't have classes like IPv4
|
@@ -744,13 +745,13 @@ like in the following example:
|
|
744
745
|
A new IPv6 address can also be created from an unsigned 128 bits
|
745
746
|
integer:
|
746
747
|
|
747
|
-
u128 =
|
748
|
+
u128 = 42540766411282592856906245548098208122
|
748
749
|
|
749
750
|
ip6 = IPAddress::IPv6::parse_u128 u128
|
750
751
|
ip6.prefix = 64
|
751
752
|
|
752
753
|
ip6.to_string
|
753
|
-
#=>
|
754
|
+
#=>"2001:db8::8:800:200c:417a/64"
|
754
755
|
|
755
756
|
Finally, a new IPv6 address can be created from an hex string:
|
756
757
|
|
@@ -909,6 +910,30 @@ group will be automatically added at the beginning
|
|
909
910
|
|
910
911
|
making it a mapped IPv6 compatible address.
|
911
912
|
|
913
|
+
== Why not using IPAddr?
|
914
|
+
|
915
|
+
IPAddr is the IP addresses library that comes with Ruby standard
|
916
|
+
lib. We found this library, although very well written, not very
|
917
|
+
suitable for all our needs, and not very flexible.
|
918
|
+
|
919
|
+
Some quick examples of things you can't do with IPAddr:
|
920
|
+
|
921
|
+
* store both the address and the prefix information
|
922
|
+
* quickly find the broadcast address of a network
|
923
|
+
* iterate over hosts
|
924
|
+
* perform subnetting or network aggregation
|
925
|
+
|
926
|
+
Many methods and procedures are so old that they have been
|
927
|
+
declared deprecated by the IETF, and some others have bugs in their
|
928
|
+
implementation.
|
929
|
+
|
930
|
+
Moreover, IPAddress is more robust and is already around 50% faster than IPAddr,
|
931
|
+
in addition to provide an organic API with logical separation and OO structure.
|
932
|
+
|
933
|
+
We hope that IPAddress will address all these issues and meet all your
|
934
|
+
needs in network programming.
|
935
|
+
|
936
|
+
|
912
937
|
== Community
|
913
938
|
|
914
939
|
Want to join the community?
|
@@ -924,12 +949,13 @@ Feel free to join us and tell us what you think!
|
|
924
949
|
Thanks to Luca Russo (vargolo) and Simone Carletti
|
925
950
|
(weppos) for all the support and technical review. Thanks to Marco Beri,
|
926
951
|
Bryan T. Richardson, Nicolas Fevrier, jdpace, Daniele Alessandri, jrdioko,
|
927
|
-
Ghislain Charrier, Pawel Krzesniak, Mark Sullivan,
|
928
|
-
Steve Rawlinson for their support,
|
952
|
+
Ghislain Charrier, Pawel Krzesniak, Mark Sullivan, Leif Gensert,
|
953
|
+
Erik Ahlström, Peter Vandenberk and Steve Rawlinson for their support,
|
954
|
+
feedback and bug reports.
|
929
955
|
|
930
956
|
== Copyright
|
931
957
|
|
932
958
|
Copyright (c) 2009-2011 Marco Ceresa. See LICENSE for details.
|
933
959
|
|
934
960
|
|
935
|
-
|
961
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.0
|
data/ipaddress.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ipaddress}
|
8
|
+
s.version = "0.8.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Marco Ceresa"]
|
12
|
+
s.date = %q{2011-05-17}
|
13
|
+
s.description = %q{ IPAddress is a Ruby library designed to make manipulation
|
14
|
+
of IPv4 and IPv6 addresses both powerful and simple. It mantains
|
15
|
+
a layer of compatibility with Ruby's own IPAddr, while
|
16
|
+
addressing many of its issues.
|
17
|
+
}
|
18
|
+
s.email = %q{ceresa@gmail.com}
|
19
|
+
s.extra_rdoc_files = [
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc"
|
22
|
+
]
|
23
|
+
s.files = [
|
24
|
+
".document",
|
25
|
+
"CHANGELOG.rdoc",
|
26
|
+
"LICENSE",
|
27
|
+
"README.rdoc",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"ipaddress.gemspec",
|
31
|
+
"lib/ipaddress.rb",
|
32
|
+
"lib/ipaddress/ipv4.rb",
|
33
|
+
"lib/ipaddress/ipv6.rb",
|
34
|
+
"lib/ipaddress/prefix.rb",
|
35
|
+
"test/ipaddress/ipv4_test.rb",
|
36
|
+
"test/ipaddress/ipv6_test.rb",
|
37
|
+
"test/ipaddress/prefix_test.rb",
|
38
|
+
"test/ipaddress_test.rb",
|
39
|
+
"test/test_helper.rb"
|
40
|
+
]
|
41
|
+
s.homepage = %q{http://github.com/bluemonk/ipaddress}
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = %q{1.6.2}
|
44
|
+
s.summary = %q{IPv4/IPv6 addresses manipulation library}
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
s.specification_version = 3
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
+
else
|
51
|
+
end
|
52
|
+
else
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/lib/ipaddress.rb
CHANGED
@@ -14,8 +14,6 @@
|
|
14
14
|
|
15
15
|
require 'ipaddress/ipv4'
|
16
16
|
require 'ipaddress/ipv6'
|
17
|
-
require 'ipaddress/extensions/extensions'
|
18
|
-
|
19
17
|
|
20
18
|
module IPAddress
|
21
19
|
|
@@ -145,6 +143,9 @@ module IPAddress
|
|
145
143
|
false
|
146
144
|
end
|
147
145
|
|
146
|
+
#
|
147
|
+
# Deprecate method
|
148
|
+
#
|
148
149
|
def self.deprecate(message = nil) # :nodoc:
|
149
150
|
message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
|
150
151
|
warn("DEPRECATION WARNING: #{message}")
|
@@ -185,4 +186,17 @@ def IPAddress(str)
|
|
185
186
|
IPAddress::parse str
|
186
187
|
end
|
187
188
|
|
189
|
+
#
|
190
|
+
# Compatibility with Ruby 1.8
|
191
|
+
#
|
192
|
+
if RUBY_VERSION =~ /1\.8/
|
193
|
+
class Hash # :nodoc:
|
194
|
+
alias :key :index
|
195
|
+
end
|
196
|
+
module Math # :nodoc:
|
197
|
+
def Math.log2(n)
|
198
|
+
log(n) / log(2)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
188
202
|
|
data/lib/ipaddress/ipv4.rb
CHANGED
@@ -426,14 +426,22 @@ module IPAddress;
|
|
426
426
|
end
|
427
427
|
|
428
428
|
#
|
429
|
-
# Spaceship operator to compare
|
429
|
+
# Spaceship operator to compare IPv4 objects
|
430
430
|
#
|
431
|
-
#
|
432
|
-
#
|
433
|
-
#
|
431
|
+
# Comparing IPv4 addresses is useful to ordinate
|
432
|
+
# them into lists that match our intuitive
|
433
|
+
# perception of ordered IP addresses.
|
434
|
+
#
|
435
|
+
# The first comparison criteria is the u32 value.
|
436
|
+
# For example, 10.100.100.1 will be considered
|
437
|
+
# to be less than 172.16.0.1, because, in a ordered list,
|
438
|
+
# we expect 10.100.100.1 to come before 172.16.0.1.
|
434
439
|
#
|
435
|
-
#
|
436
|
-
#
|
440
|
+
# The second criteria, in case two IPv4 objects
|
441
|
+
# have identical addresses, is the prefix. An higher
|
442
|
+
# prefix will be considered greater than a lower
|
443
|
+
# prefix. This is because we expect to see
|
444
|
+
# 10.100.100.0/24 come before 10.100.100.0/25.
|
437
445
|
#
|
438
446
|
# Example:
|
439
447
|
#
|
@@ -443,22 +451,15 @@ module IPAddress;
|
|
443
451
|
#
|
444
452
|
# ip1 < ip2
|
445
453
|
# #=> true
|
446
|
-
# ip1
|
454
|
+
# ip1 > ip3
|
447
455
|
# #=> false
|
448
456
|
#
|
457
|
+
# [ip1,ip2,ip3].sort.map{|i| i.to_string}
|
458
|
+
# #=> ["10.100.100.1/8","10.100.100.1/16","172.16.0.1/16"]
|
459
|
+
#
|
449
460
|
def <=>(oth)
|
450
|
-
if to_u32
|
451
|
-
|
452
|
-
elsif to_u32 < oth.to_u32
|
453
|
-
return -1
|
454
|
-
else
|
455
|
-
if prefix < oth.prefix
|
456
|
-
return 1
|
457
|
-
elsif prefix > oth.prefix
|
458
|
-
return -1
|
459
|
-
end
|
460
|
-
end
|
461
|
-
return 0
|
461
|
+
return prefix <=> oth.prefix if to_u32 == oth.to_u32
|
462
|
+
to_u32 <=> oth.to_u32
|
462
463
|
end
|
463
464
|
|
464
465
|
#
|
@@ -552,30 +553,6 @@ module IPAddress;
|
|
552
553
|
others.all? {|oth| include?(oth)}
|
553
554
|
end
|
554
555
|
|
555
|
-
#
|
556
|
-
# True if the object is an IPv4 address
|
557
|
-
#
|
558
|
-
# ip = IPAddress("192.168.10.100/24")
|
559
|
-
#
|
560
|
-
# ip.ipv4?
|
561
|
-
# #-> true
|
562
|
-
#
|
563
|
-
# def ipv4?
|
564
|
-
# true
|
565
|
-
# end
|
566
|
-
|
567
|
-
#
|
568
|
-
# True if the object is an IPv6 address
|
569
|
-
#
|
570
|
-
# ip = IPAddress("192.168.10.100/24")
|
571
|
-
#
|
572
|
-
# ip.ipv6?
|
573
|
-
# #-> false
|
574
|
-
#
|
575
|
-
# def ipv6?
|
576
|
-
# false
|
577
|
-
# end
|
578
|
-
|
579
556
|
#
|
580
557
|
# Checks if an IPv4 address objects belongs
|
581
558
|
# to a private network RFC1918
|
@@ -607,10 +584,10 @@ module IPAddress;
|
|
607
584
|
alias_method :arpa, :reverse
|
608
585
|
|
609
586
|
#
|
610
|
-
#
|
587
|
+
# Splits a network into different subnets
|
611
588
|
#
|
612
589
|
# If the IP Address is a network, it can be divided into
|
613
|
-
# multiple networks. If +self+ is not a network,
|
590
|
+
# multiple networks. If +self+ is not a network, this
|
614
591
|
# method will calculate the network from the IP and then
|
615
592
|
# subnet it.
|
616
593
|
#
|
@@ -636,15 +613,19 @@ module IPAddress;
|
|
636
613
|
# "172.16.10.64/26",
|
637
614
|
# "172.16.10.128/25"]
|
638
615
|
#
|
639
|
-
# Returns an array of
|
616
|
+
# Returns an array of IPv4 objects
|
640
617
|
#
|
641
|
-
def
|
618
|
+
def split(subnets=2)
|
642
619
|
unless (1..(2**@prefix.host_prefix)).include? subnets
|
643
620
|
raise ArgumentError, "Value #{subnets} out of range"
|
644
621
|
end
|
645
|
-
|
622
|
+
networks = subnet(newprefix(subnets))
|
623
|
+
until networks.size == subnets
|
624
|
+
networks = sum_first_found(networks)
|
625
|
+
end
|
626
|
+
return networks
|
646
627
|
end
|
647
|
-
alias_method :/, :
|
628
|
+
alias_method :/, :split
|
648
629
|
|
649
630
|
#
|
650
631
|
# Returns a new IPv4 object from the supernetting
|
@@ -667,11 +648,44 @@ module IPAddress;
|
|
667
648
|
#
|
668
649
|
# ip.supernet(22).to_string
|
669
650
|
# #=> "172.16.8.0/22"
|
670
|
-
#
|
651
|
+
#
|
652
|
+
# If +new_prefix+ is less than 1, returns 0.0.0.0/0
|
653
|
+
#
|
671
654
|
def supernet(new_prefix)
|
672
|
-
raise ArgumentError, "Can't supernet a /1 network" if new_prefix < 1
|
673
655
|
raise ArgumentError, "New prefix must be smaller than existing prefix" if new_prefix >= @prefix.to_i
|
674
|
-
self.class.new(
|
656
|
+
return self.class.new("0.0.0.0/0") if new_prefix < 1
|
657
|
+
return self.class.new(@address+"/#{new_prefix}").network
|
658
|
+
end
|
659
|
+
|
660
|
+
#
|
661
|
+
# This method implements the subnetting function
|
662
|
+
# similar to the one described in RFC3531.
|
663
|
+
#
|
664
|
+
# By specifying a new prefix, the method calculates
|
665
|
+
# the network number for the given IPv4 object
|
666
|
+
# and calculates the subnets associated to the new
|
667
|
+
# prefix.
|
668
|
+
#
|
669
|
+
# For example, given the following network:
|
670
|
+
#
|
671
|
+
# ip = IPAddress "172.16.10.0/24"
|
672
|
+
#
|
673
|
+
# we can calculate the subnets with a /26 prefix
|
674
|
+
#
|
675
|
+
# ip.subnets(26).map{&:to_string)
|
676
|
+
# #=> ["172.16.10.0/26", "172.16.10.64/26",
|
677
|
+
# "172.16.10.128/26", "172.16.10.192/26"]
|
678
|
+
#
|
679
|
+
# The resulting number of subnets will of course always be
|
680
|
+
# a power of two.
|
681
|
+
#
|
682
|
+
def subnet(subprefix)
|
683
|
+
unless ((@prefix.to_i)..32).include? subprefix
|
684
|
+
raise ArgumentError, "New prefix must be between #@prefix and 32"
|
685
|
+
end
|
686
|
+
Array.new(2**(subprefix-@prefix.to_i)) do |i|
|
687
|
+
self.class.parse_u32(network_u32+(i*(2**(32-subprefix))), subprefix)
|
688
|
+
end
|
675
689
|
end
|
676
690
|
|
677
691
|
#
|
@@ -928,9 +942,6 @@ module IPAddress;
|
|
928
942
|
# * Class B, from 128.0.0.0 to 191.255.255.255
|
929
943
|
# * Class C, D and E, from 192.0.0.0 to 255.255.255.254
|
930
944
|
#
|
931
|
-
# Note that classes C, D and E will all have a default
|
932
|
-
# prefix of /24 or 255.255.255.0
|
933
|
-
#
|
934
945
|
# Example:
|
935
946
|
#
|
936
947
|
# ip = IPAddress::IPv4.parse_classful "10.0.0.1"
|
@@ -940,6 +951,9 @@ module IPAddress;
|
|
940
951
|
# ip.a?
|
941
952
|
# #=> true
|
942
953
|
#
|
954
|
+
# Note that classes C, D and E will all have a default
|
955
|
+
# prefix of /24 or 255.255.255.0
|
956
|
+
#
|
943
957
|
def self.parse_classful(ip)
|
944
958
|
if IPAddress.valid_ipv4?(ip)
|
945
959
|
address = ip.strip
|
@@ -954,25 +968,19 @@ module IPAddress;
|
|
954
968
|
# private methods
|
955
969
|
#
|
956
970
|
private
|
957
|
-
|
958
|
-
def
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
mul = i * (2**(32-new_prefix))
|
964
|
-
networks << IPAddress::IPv4.parse_u32(network_u32+mul, new_prefix)
|
965
|
-
end
|
966
|
-
until networks.size == subnets
|
967
|
-
networks = sum_first_found(networks)
|
971
|
+
|
972
|
+
def newprefix(num)
|
973
|
+
num.upto(32) do |i|
|
974
|
+
if (a = Math::log2(i).to_i) == Math::log2(i)
|
975
|
+
return @prefix + a
|
976
|
+
end
|
968
977
|
end
|
969
|
-
return networks
|
970
978
|
end
|
971
979
|
|
972
980
|
def sum_first_found(arr)
|
973
981
|
dup = arr.dup.reverse
|
974
982
|
dup.each_with_index do |obj,i|
|
975
|
-
a = [
|
983
|
+
a = [self.class.summarize(obj,dup[i+1])].flatten
|
976
984
|
if a.size == 1
|
977
985
|
dup[i..i+1] = a
|
978
986
|
return dup.reverse
|