ipaddress 0.5.0 → 0.6.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 +73 -0
- data/README.rdoc +120 -86
- data/Rakefile +7 -15
- data/VERSION +1 -1
- data/lib/ipaddress.rb +131 -15
- data/lib/ipaddress/extensions/extensions.rb +8 -2
- data/lib/ipaddress/ipv4.rb +132 -49
- data/lib/ipaddress/ipv6.rb +64 -18
- data/lib/ipaddress/prefix.rb +38 -1
- data/test/ipaddress/ipv4_test.rb +92 -38
- data/test/ipaddress/ipv6_test.rb +34 -10
- data/test/ipaddress/prefix_test.rb +15 -0
- data/test/ipaddress_test.rb +17 -0
- data/test/test_helper.rb +0 -5
- metadata +11 -25
- data/lib/ipaddress/ipbase.rb +0 -83
- data/test/ipaddress/ipbase_test.rb +0 -28
    
        data/CHANGELOG.rdoc
    ADDED
    
    | @@ -0,0 +1,73 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            == ipaddress 0.6.0
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            === API changes
         | 
| 5 | 
            +
            * IPv4#to_s now returns the address portion only, 
         | 
| 6 | 
            +
              to retain compatibility with IPAddr. Example:
         | 
| 7 | 
            +
              
         | 
| 8 | 
            +
                IPAddress("172.16.10.1/24").to_s
         | 
| 9 | 
            +
                  #=> "172.16.10.1"     # ipaddress 0.6.0
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                IPAddress("172.16.10.1/24").to_s
         | 
| 12 | 
            +
                  #=> "172.16.10.1/24"  # ipaddress 0.5.0
         | 
| 13 | 
            +
               
         | 
| 14 | 
            +
            * IPv6#to_s now returns the address portion only,
         | 
| 15 | 
            +
              to retain compatibility with IPAddr. Example:
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                IPAddress "2001:db8::8:800:200c:417a/64".to_s	
         | 
| 18 | 
            +
                  #=> "2001:db8::8:800:200c:417a"    # ipaddress 0.6.0
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                IPAddress "2001:db8::8:800:200c:417a/64".to_s	
         | 
| 21 | 
            +
                  #=> "2001:db8::8:800:200c:417a/64" # ipaddress 0.6.0
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            * IPv6::Unspecified#to_s, IPv6::Loopback and 
         | 
| 24 | 
            +
              IPv6::Mapped#to_s now return the address portion only,
         | 
| 25 | 
            +
              to retain compatibility with IPAddr. 
         | 
| 26 | 
            +
            * IPv4::summarize now returns an array even if the 
         | 
| 27 | 
            +
              result is a single subnet, to keep consistency 
         | 
| 28 | 
            +
              and avoid confusion
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            === New methods
         | 
| 31 | 
            +
            * IPv4#to_string and IPv6#to_string: print the address 
         | 
| 32 | 
            +
              with the prefix portion, like the #to_s method in 
         | 
| 33 | 
            +
              ipaddress 0.5.0
         | 
| 34 | 
            +
            * IPAddress::parse, for those who don't like the wrapper 
         | 
| 35 | 
            +
              method IPAddress()
         | 
| 36 | 
            +
            * IPv6#to_string_uncompressed, returns a string with the
         | 
| 37 | 
            +
              uncompressed IPv6 and the prefix
         | 
| 38 | 
            +
            * IPv6::Mapped#to_string, returns the IPv6 Mapped address 
         | 
| 39 | 
            +
              with IPv4 notation and the prefix
         | 
| 40 | 
            +
            * IPv6#reverse, returns the ip6.arpa DNS reverse lookup 
         | 
| 41 | 
            +
              string
         | 
| 42 | 
            +
            * IPv4#arpa and IPv6#arpa, alias of the respective #reverse
         | 
| 43 | 
            +
              methods
         | 
| 44 | 
            +
            * Prefix#+, Prefix#-
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            === Library structure
         | 
| 47 | 
            +
            * Moved all the IPAddress module methods from 
         | 
| 48 | 
            +
              lib/ipaddress/ipbase.rb to lib/ipaddress.rb
         | 
| 49 | 
            +
            * Removed IPBase superclass
         | 
| 50 | 
            +
            * IPv4 and IPv6 classes no longer inherit from IPBase
         | 
| 51 | 
            +
            * Removed lib/ipaddress/ipbase.rb
         | 
| 52 | 
            +
            * Removed test/ipaddress/ipbase_test.rb
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            === Minor fixes
         | 
| 55 | 
            +
            * Replaced Ruby 1.9 deprecated Hash#index with Hash#key 
         | 
| 56 | 
            +
            * Removed require ruby-prof from tests which was causing 
         | 
| 57 | 
            +
              users to install ruby-prof or manually remove the line
         | 
| 58 | 
            +
            * Removed "must" method from tests, replaced by normal 
         | 
| 59 | 
            +
              Test::Unit methods
         | 
| 60 | 
            +
            * Removed duplicate Jeweler entry in Rakefile
         | 
| 61 | 
            +
            * Made Integer#closest_power_of_2 more general by adding
         | 
| 62 | 
            +
              an optional limit parameter
         | 
| 63 | 
            +
            * Fixed summarization algorithm (thanks to nicolas fevrier)
         | 
| 64 | 
            +
            * Fixed bug in prefix_from_ip (thanks to jdpace)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            === Documentation
         | 
| 67 | 
            +
            * Normalized README rdoc headers
         | 
| 68 | 
            +
            * Added documentation for IPAddress::Prefix
         | 
| 69 | 
            +
            * Added documentation for IPAddress::IPv4 and 
         | 
| 70 | 
            +
              IPAddress::IPv6
         | 
| 71 | 
            +
            * Fixed formatting
         | 
| 72 | 
            +
            * Fixed lots of typos
         | 
| 73 | 
            +
             | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            = IPAddress
         | 
| 2 2 |  | 
| 3 3 | 
             
            IPAddress is a Ruby library designed to make the use of IPv4 and IPv6
         | 
| 4 | 
            -
            addresses  | 
| 4 | 
            +
            addresses simple, powerful and enjoyable. It provides a complete set of
         | 
| 5 5 | 
             
            methods to handle IP addresses for any need, from simple scripting to
         | 
| 6 6 | 
             
            full network design.
         | 
| 7 7 |  | 
| @@ -12,7 +12,25 @@ let you start being productive immediately. | |
| 12 12 | 
             
            This document provides a brief introduction to the library and
         | 
| 13 13 | 
             
            examples of typical usage. 
         | 
| 14 14 |  | 
| 15 | 
            -
             | 
| 15 | 
            +
            == Requirements
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * Ruby >= 1.8.6 (not tested with previous versions)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            IPAddress works perfectly on:
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            * Ruby 1.8.6 (2007-03-13 patchlevel 0) 
         | 
| 22 | 
            +
            * Ruby 1.8.7 
         | 
| 23 | 
            +
            * Ruby 1.9.1 
         | 
| 24 | 
            +
            * Ruby 1.9.2dev (2010-06-08 revision 28230)
         | 
| 25 | 
            +
            * Ruby 1.9.2dev (2010-07-15 revision 28653)
         | 
| 26 | 
            +
            * Rubinius 1.0.1 (1.8.7 release 2010-06-03 JI)
         | 
| 27 | 
            +
            * Ironruby >= 1.0
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            It hasn't yet been tested on any other platform, so if you want to collaborate feel 
         | 
| 30 | 
            +
            free to send a small report to my email address, or 
         | 
| 31 | 
            +
            {join the discussion}[http://groups.google.com/group/ruby-ipaddress]. 
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            == Why not using IPAddr?
         | 
| 16 34 |  | 
| 17 35 | 
             
            IPAddr is the IP addresses library that comes with Ruby standard
         | 
| 18 36 | 
             
            lib. We found this library, although very well written, not very
         | 
| @@ -25,10 +43,13 @@ Some quick examples of things you can't do with IPAddr: | |
| 25 43 | 
             
            * iterate over hosts 
         | 
| 26 44 | 
             
            * perform subnetting or network aggregation
         | 
| 27 45 |  | 
| 46 | 
            +
            Moreover, many methods and procedures are so old that they have been 
         | 
| 47 | 
            +
            declared deprecated by the IETF.
         | 
| 48 | 
            +
             | 
| 28 49 | 
             
            We hope that IPAddress will address all these issues and meet all your
         | 
| 29 50 | 
             
            needs in network programming.
         | 
| 30 51 |  | 
| 31 | 
            -
             | 
| 52 | 
            +
            == Installation
         | 
| 32 53 |  | 
| 33 54 | 
             
            Install the library using rubygems
         | 
| 34 55 |  | 
| @@ -41,36 +62,35 @@ You can then use it in your programs: | |
| 41 62 |  | 
| 42 63 | 
             
            Another way would be to clone the git repository
         | 
| 43 64 |  | 
| 44 | 
            -
              $ git clone git://github.com/bluemonk/ | 
| 65 | 
            +
              $ git clone git://github.com/bluemonk/ipaddress.git
         | 
| 45 66 |  | 
| 46 67 | 
             
            And then install the library
         | 
| 47 68 |  | 
| 48 69 | 
             
              $ cd ipaddress
         | 
| 49 70 | 
             
              ipaddress$ rake install
         | 
| 50 71 |  | 
| 51 | 
            -
             | 
| 72 | 
            +
            == Documentation
         | 
| 52 73 |  | 
| 53 74 | 
             
            The code is fully documented with RDoc. You can generate the
         | 
| 54 75 | 
             
            documentation with Rake:
         | 
| 55 76 |  | 
| 56 77 | 
             
              ipaddress$ rake rdoc
         | 
| 57 78 |  | 
| 58 | 
            -
            The latest documentation can be found online at  | 
| 59 | 
            -
             | 
| 60 | 
            -
            http://marcoceresa.com/ipaddress
         | 
| 79 | 
            +
            The latest documentation can be found online at 
         | 
| 80 | 
            +
            {this address}[http://marcoceresa.com/ipaddress]
         | 
| 61 81 |  | 
| 62 | 
            -
             | 
| 82 | 
            +
            == Usage
         | 
| 63 83 |  | 
| 64 84 | 
             
            In this section I will illustrate how to use the IPAddress library
         | 
| 65 85 | 
             
            through some examples of common tasks.
         | 
| 66 86 |  | 
| 67 | 
            -
             | 
| 87 | 
            +
            === IPv4
         | 
| 68 88 |  | 
| 69 89 | 
             
            Class IPAddress::IPv4 is used to handle IPv4 type addresses. IPAddress
         | 
| 70 90 | 
             
            is similar to other IP Addresses libraries, like Ruby's own
         | 
| 71 91 | 
             
            IPAddr. However it works slightly different, as we will see.
         | 
| 72 92 |  | 
| 73 | 
            -
             | 
| 93 | 
            +
            ==== Create a new IPv4 address
         | 
| 74 94 |  | 
| 75 95 | 
             
            The usual way to express an IP Address is using its dotted decimal
         | 
| 76 96 | 
             
            form, such as 172.16.10.1, and a prefix, such as 24, separated by a
         | 
| @@ -94,7 +114,7 @@ You can specify an IPv4 address in any of two ways: | |
| 94 114 | 
             
            In this example, prefix /24 and netmask 255.255.255.0 are the same and
         | 
| 95 115 | 
             
            you have the flexibility to use either one of them.
         | 
| 96 116 |  | 
| 97 | 
            -
             | 
| 117 | 
            +
            ==== Classful networks
         | 
| 98 118 |  | 
| 99 119 | 
             
            If you don't specify a prefix (or a subnet mask), then the library
         | 
| 100 120 | 
             
            will create an object base on the CLASSFUL network from the given
         | 
| @@ -124,10 +144,10 @@ You can easily check which CLASSFUL network the IP belongs: | |
| 124 144 | 
             
            These methods are only checking the address portion of an IP, and are
         | 
| 125 145 | 
             
            indipendent from its prefix.
         | 
| 126 146 |  | 
| 127 | 
            -
            For more information on CLASSFUL networks visit the  | 
| 128 | 
            -
            Wikipedia page | 
| 147 | 
            +
            For more information on CLASSFUL networks visit the 
         | 
| 148 | 
            +
            {Wikipedia page}[http://en.wikipedia.org/wiki/Classful_network]
         | 
| 129 149 |  | 
| 130 | 
            -
             | 
| 150 | 
            +
            ==== Handling the IPv4 address
         | 
| 131 151 |  | 
| 132 152 | 
             
            Once created, you can obtain the attributes for an IPv4 object:
         | 
| 133 153 |  | 
| @@ -157,28 +177,30 @@ range: | |
| 157 177 | 
             
                #=> 16
         | 
| 158 178 |  | 
| 159 179 | 
             
            If you need to print out the IPv4 address in a canonical form, you can
         | 
| 160 | 
            -
            use IPv4# | 
| 180 | 
            +
            use IPv4#to_string
         | 
| 161 181 |  | 
| 162 | 
            -
              ip. | 
| 182 | 
            +
              ip.to_string
         | 
| 163 183 | 
             
                #=> "172.16.10.l/24"
         | 
| 164 184 |  | 
| 165 | 
            -
             | 
| 185 | 
            +
            ==== Changing netmask
         | 
| 166 186 |  | 
| 167 187 | 
             
            You can set a new prefix (netmask) after creating an IPv4 
         | 
| 168 188 | 
             
            object. For example:
         | 
| 169 189 |  | 
| 170 190 | 
             
              ip.prefix = 25
         | 
| 171 | 
            -
             | 
| 191 | 
            +
             | 
| 192 | 
            +
              ip.to_string
         | 
| 172 193 | 
             
                #=> "172.16.10.l/25"
         | 
| 173 194 |  | 
| 174 195 | 
             
            If you need to use a netmask in IPv4 format, you can achive so by
         | 
| 175 196 | 
             
            using the IPv4#netmask= method
         | 
| 176 197 |  | 
| 177 198 | 
             
              ip.netmask = "255.255.255.252"
         | 
| 178 | 
            -
             | 
| 199 | 
            +
             | 
| 200 | 
            +
              ip.to_string
         | 
| 179 201 | 
             
                #=> "172.16.10.1/30"
         | 
| 180 202 |  | 
| 181 | 
            -
             | 
| 203 | 
            +
            ==== Working with networks, broadcasts and addresses
         | 
| 182 204 |  | 
| 183 205 | 
             
            Some very important topics in dealing with IP addresses are the
         | 
| 184 206 | 
             
            concepts of +network+ and +broadcast+, as well as the addresses
         | 
| @@ -199,15 +221,18 @@ This is very important because, for instance, IP "172.16.10.1/16" is | |
| 199 221 | 
             
            very different to the previous one, belonging to the very different
         | 
| 200 222 | 
             
            network "172.16.0.0/16".
         | 
| 201 223 |  | 
| 224 | 
            +
            ===== Networks
         | 
| 225 | 
            +
             | 
| 202 226 | 
             
            With IPAddress it's very easy to calculate the network for an IP
         | 
| 203 227 | 
             
            address:
         | 
| 204 228 |  | 
| 205 229 | 
             
              ip = IPAddress "172.16.10.1/24"
         | 
| 230 | 
            +
             | 
| 206 231 | 
             
              net = ip.network
         | 
| 207 232 | 
             
                #=> #<IPAddress::IPv4:0xb7a5ab24 @octets=[172, 16, 10, 0], 
         | 
| 208 233 | 
             
                                                 @prefix=24,
         | 
| 209 234 | 
             
                                                 @address="172.16.10.0">
         | 
| 210 | 
            -
              net. | 
| 235 | 
            +
              net.to_string
         | 
| 211 236 | 
             
                #=> "172.16.10.0/24"
         | 
| 212 237 |  | 
| 213 238 | 
             
            The IPv4#network method creates a new IPv4 object from the network
         | 
| @@ -226,6 +251,8 @@ network or not: | |
| 226 251 | 
             
              ip2.network?
         | 
| 227 252 | 
             
                #=> true
         | 
| 228 253 |  | 
| 254 | 
            +
            ===== Broadcast
         | 
| 255 | 
            +
             | 
| 229 256 | 
             
            The broadcast address is the contrary than the network number: where
         | 
| 230 257 | 
             
            the network number has all zeroes in the host portion, the broadcast
         | 
| 231 258 | 
             
            address has all one's. For example, ip "172.16.10.1/24" has broadcast
         | 
| @@ -237,13 +264,16 @@ counterpart: it creates a new IPv4 object to handle the broadcast | |
| 237 264 | 
             
            address:
         | 
| 238 265 |  | 
| 239 266 | 
             
              ip = IPAddress "172.16.10.1/24"
         | 
| 267 | 
            +
             | 
| 240 268 | 
             
              bcast = ip.broadcast
         | 
| 241 269 | 
             
                #=> #<IPAddress::IPv4:0xb7a406fc @octets=[172, 16, 10, 255],
         | 
| 242 270 | 
             
                                                 @prefix=24, 
         | 
| 243 271 | 
             
                                                 @address="172.16.10.255">
         | 
| 244 | 
            -
              bcast. | 
| 272 | 
            +
              bcast.to_string
         | 
| 245 273 | 
             
                #=> "172.16.10.255/24"
         | 
| 246 274 |  | 
| 275 | 
            +
            ===== Addresses, ranges and iterators
         | 
| 276 | 
            +
             | 
| 247 277 | 
             
            So we see that the netmask essentially specifies a range for IP
         | 
| 248 278 | 
             
            addresses that are included in a network: all the addresses between
         | 
| 249 279 | 
             
            the network number and the broadcast. IPAddress has many methods to
         | 
| @@ -274,13 +304,13 @@ respectively the first and the last host address in the range | |
| 274 304 |  | 
| 275 305 | 
             
              ip = IPAddress "172.16.10.100/24"
         | 
| 276 306 |  | 
| 277 | 
            -
              ip.first. | 
| 307 | 
            +
              ip.first.to_string
         | 
| 278 308 | 
             
                #=> "172.16.10.1/24"
         | 
| 279 309 |  | 
| 280 | 
            -
              ip.last. | 
| 310 | 
            +
              ip.last.to_string
         | 
| 281 311 | 
             
                #=> "172.16.10.254/24"
         | 
| 282 312 |  | 
| 283 | 
            -
             | 
| 313 | 
            +
            ==== IP special formats    
         | 
| 284 314 |  | 
| 285 315 | 
             
            The IPAddress library provides a complete set of methods to access an
         | 
| 286 316 | 
             
            IPv4 address in special formats, such as binary, 32 bits unsigned int,
         | 
| @@ -289,6 +319,7 @@ data and hexadecimal. | |
| 289 319 | 
             
            Let's take the following IPv4 as an example:
         | 
| 290 320 |  | 
| 291 321 | 
             
              ip = IPAddress "172.16.10.1/24"
         | 
| 322 | 
            +
             | 
| 292 323 | 
             
              ip.address
         | 
| 293 324 | 
             
                #=> "172.16.10.1"
         | 
| 294 325 |  | 
| @@ -322,12 +353,12 @@ suitable to use in IPv4-IPv6 mapped addresses: | |
| 322 353 | 
             
                #=> "ac10:0a01"
         | 
| 323 354 |  | 
| 324 355 |  | 
| 325 | 
            -
             | 
| 356 | 
            +
            === Network design with IPAddress
         | 
| 326 357 |  | 
| 327 358 | 
             
            IPAddress includes a lot of useful methods to manipulate IPv4 and IPv6
         | 
| 328 359 | 
             
            networks and do some basic network design. 
         | 
| 329 360 |  | 
| 330 | 
            -
             | 
| 361 | 
            +
            ==== Subnetting
         | 
| 331 362 |  | 
| 332 363 | 
             
            The process of subnetting is the division of a network into smaller
         | 
| 333 364 | 
             
            (in terms of hosts capacity) networks, called subnets, so that they
         | 
| @@ -347,7 +378,7 @@ Subnetting is easy with IPAddress. Let's work out the last example: | |
| 347 378 | 
             
                     #<IPAddress::IPv4:0xb7b0e5ac @octets=[172,16,10,128] [...]  
         | 
| 348 379 | 
             
                     #<IPAddress::IPv4:0xb7b0e0c0 @octets=[172,16,10,192] [...]]
         | 
| 349 380 |  | 
| 350 | 
            -
              subnets.map{|i| i. | 
| 381 | 
            +
              subnets.map{|i| i.to_string}
         | 
| 351 382 | 
             
                #=> ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26", 
         | 
| 352 383 | 
             
                     "172.16.10.192/26"]
         | 
| 353 384 |  | 
| @@ -359,7 +390,7 @@ example: | |
| 359 390 |  | 
| 360 391 | 
             
              ip = IPAddress("172.16.10.58/24")
         | 
| 361 392 |  | 
| 362 | 
            -
              ip.subnet(4).map{|i| i. | 
| 393 | 
            +
              ip.subnet(4).map{|i| i.to_string}
         | 
| 363 394 | 
             
                #=> ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26",
         | 
| 364 395 | 
             
                     "172.16.10.192/26"]
         | 
| 365 396 |  | 
| @@ -368,7 +399,7 @@ which is a power of two: in this way, you can be sure that the network | |
| 368 399 | 
             
            will be divived evenly, and all the subnets will have the same number
         | 
| 369 400 | 
             
            of hosts. 
         | 
| 370 401 |  | 
| 371 | 
            -
             | 
| 402 | 
            +
            ==== Uneven subnetting
         | 
| 372 403 |  | 
| 373 404 | 
             
            IPAddress also handles un-even subnetting: if you specify any number
         | 
| 374 405 | 
             
            (up to the prefix limit), the network will be divided so that the
         | 
| @@ -378,7 +409,8 @@ fill out the space. | |
| 378 409 | 
             
            As an example, let's divide network 172.16.10.0/24 into 3 different subnets:
         | 
| 379 410 |  | 
| 380 411 | 
             
              network = IPAddress("172.16.10.0/24")
         | 
| 381 | 
            -
             | 
| 412 | 
            +
             | 
| 413 | 
            +
              network.subnet(3).map{|i| i.to_string}
         | 
| 382 414 | 
             
                #=> ["172.16.10.0/26",
         | 
| 383 415 | 
             
                     "172.16.10.64/26",
         | 
| 384 416 | 
             
                     "172.16.10.128/25"]
         | 
| @@ -386,7 +418,8 @@ As an example, let's divide network 172.16.10.0/24 into 3 different subnets: | |
| 386 418 | 
             
            We can go even further and divide into 11 subnets:
         | 
| 387 419 |  | 
| 388 420 | 
             
              network = IPAddress("172.16.10.0/24")
         | 
| 389 | 
            -
             | 
| 421 | 
            +
             | 
| 422 | 
            +
              network.subnet(11).map{|i| i.to_string}
         | 
| 390 423 | 
             
                #=> ["172.16.10.0/28", "172.16.10.16/28", "172.16.10.32/28",
         | 
| 391 424 | 
             
                     "172.16.10.48/28", "172.16.10.64/28", "172.16.10.80/28",
         | 
| 392 425 | 
             
                     "172.16.10.96/28", "172.16.10.112/28", "172.16.10.128/27",
         | 
| @@ -395,7 +428,7 @@ We can go even further and divide into 11 subnets: | |
| 395 428 | 
             
            As you can see, most of the networks are /28, with a few /27 and one
         | 
| 396 429 | 
             
            /26 to fill up the remaning space.
         | 
| 397 430 |  | 
| 398 | 
            -
             | 
| 431 | 
            +
            ==== Summarization
         | 
| 399 432 |  | 
| 400 433 | 
             
            Summarization (or aggregation) is the process when two or more
         | 
| 401 434 | 
             
            networks are taken together to check if a supernet, including
         | 
| @@ -406,10 +439,11 @@ occur if there are no holes in the aggregated network, or, in | |
| 406 439 | 
             
            other words, if the given networks fill completely the address space
         | 
| 407 440 | 
             
            of the supernet. So the two rules are:
         | 
| 408 441 |  | 
| 409 | 
            -
             | 
| 410 | 
            -
             | 
| 411 | 
            -
             | 
| 412 | 
            -
             | 
| 442 | 
            +
            1) The aggregate network must contain +all+ the IP addresses of the
         | 
| 443 | 
            +
            original networks;   
         | 
| 444 | 
            +
             | 
| 445 | 
            +
            2) The aggregate network must contain +only+ the IP addresses of the
         | 
| 446 | 
            +
            original networks; 
         | 
| 413 447 |  | 
| 414 448 | 
             
            A few examples will help clarify the above. Let's consider for
         | 
| 415 449 | 
             
            instance the following two networks:
         | 
| @@ -420,7 +454,7 @@ instance the following two networks: | |
| 420 454 | 
             
            These two networks can be expressed using only one IP address
         | 
| 421 455 | 
             
            network if we change the prefix. Let Ruby do the work:
         | 
| 422 456 |  | 
| 423 | 
            -
              IPAddress::IPv4::summarize(ip1,ip2). | 
| 457 | 
            +
              IPAddress::IPv4::summarize(ip1,ip2).to_string
         | 
| 424 458 | 
             
                #=> "172.16.10.0/23"
         | 
| 425 459 |  | 
| 426 460 | 
             
            We note how the network "172.16.10.0/23" includes all the
         | 
| @@ -447,8 +481,8 @@ aggregated in a single /22: | |
| 447 481 | 
             
              ip3 = IPAddress("10.0.2.1/24")
         | 
| 448 482 | 
             
              ip4 = IPAddress("10.0.3.1/24")
         | 
| 449 483 |  | 
| 450 | 
            -
              IPAddress::IPv4::summarize(ip1,ip2,ip3,ip4). | 
| 451 | 
            -
                #=> "10.0.0.0/22" | 
| 484 | 
            +
              IPAddress::IPv4::summarize(ip1,ip2,ip3,ip4).map{|i| i.to_string}
         | 
| 485 | 
            +
                #=> ["10.0.0.0/22"]
         | 
| 452 486 |  | 
| 453 487 | 
             
            But the following networks can't be summarized in a single
         | 
| 454 488 | 
             
            network:
         | 
| @@ -457,13 +491,14 @@ network: | |
| 457 491 | 
             
              ip2 = IPAddress("10.0.2.1/24")
         | 
| 458 492 | 
             
              ip3 = IPAddress("10.0.3.1/24")
         | 
| 459 493 | 
             
              ip4 = IPAddress("10.0.4.1/24")
         | 
| 460 | 
            -
             | 
| 494 | 
            +
             | 
| 495 | 
            +
              IPAddress::IPv4::summarize(ip1,ip2,ip3,ip4).map{|i| i.to_string}
         | 
| 461 496 | 
             
                #=> ["10.0.1.0/24","10.0.2.0/23","10.0.4.0/24"]
         | 
| 462 497 |  | 
| 463 498 | 
             
            In this case, the two summarizables networks have been aggregated into
         | 
| 464 499 | 
             
            a single /23, while the other two networks have been left untouched.
         | 
| 465 500 |  | 
| 466 | 
            -
             | 
| 501 | 
            +
            ==== Supernetting
         | 
| 467 502 |  | 
| 468 503 | 
             
            Supernetting is a different operation than aggregation, as it only
         | 
| 469 504 | 
             
            works on a single network and returns a new single IPv4 object,
         | 
| @@ -477,26 +512,25 @@ example, given the network | |
| 477 512 |  | 
| 478 513 | 
             
            you can supernet it with a new /23 prefix
         | 
| 479 514 |  | 
| 480 | 
            -
              ip.supernet(23). | 
| 515 | 
            +
              ip.supernet(23).to_string
         | 
| 481 516 | 
             
                #=> "172.16.10.0/23"
         | 
| 482 517 |  | 
| 483 518 | 
             
            However if you supernet it with a /22 prefix, the network address will
         | 
| 484 519 | 
             
            change: 
         | 
| 485 520 |  | 
| 486 | 
            -
              ip.supernet(22). | 
| 521 | 
            +
              ip.supernet(22).to_string
         | 
| 487 522 | 
             
                #=> "172.16.8.0/22"
         | 
| 488 523 |  | 
| 489 524 | 
             
            This is because "172.16.10.0/22" is not a network anymore, but an host
         | 
| 490 525 | 
             
            address.
         | 
| 491 526 |  | 
| 492 | 
            -
             | 
| 493 | 
            -
            =IPv6
         | 
| 527 | 
            +
            == IPv6
         | 
| 494 528 |  | 
| 495 529 | 
             
            IPAddress is not only fantastic for IPv4 addresses, it's also great to
         | 
| 496 530 | 
             
            handle IPv6 addresses family! Let's discover together how to use it in
         | 
| 497 531 | 
             
            our projects.
         | 
| 498 532 |  | 
| 499 | 
            -
             | 
| 533 | 
            +
            === IPv6 addresses
         | 
| 500 534 |  | 
| 501 535 | 
             
            IPv6 addresses are 128 bits long, in contrast with IPv4 addresses
         | 
| 502 536 | 
             
            which are only 32 bits long. An IPv6 address is generally written as
         | 
| @@ -510,7 +544,7 @@ Letters in an IPv6 address are usually written downcase, as per | |
| 510 544 | 
             
            RFC. You can create a new IPv6 object using uppercase letters, but
         | 
| 511 545 | 
             
            they will be converted.
         | 
| 512 546 |  | 
| 513 | 
            -
             | 
| 547 | 
            +
            ==== Compression
         | 
| 514 548 |  | 
| 515 549 | 
             
            Since IPv6 addresses are very long to write, there are some
         | 
| 516 550 | 
             
            semplifications and compressions that you can use to shorten them. 
         | 
| @@ -528,7 +562,7 @@ the following, equivalent, address | |
| 528 562 |  | 
| 529 563 | 
             
            This short version is often used in human representation.
         | 
| 530 564 |  | 
| 531 | 
            -
             | 
| 565 | 
            +
            ==== Network Mask
         | 
| 532 566 |  | 
| 533 567 | 
             
            As we used to do with IPv4 addresses, an IPv6 address can be written
         | 
| 534 568 | 
             
            using the prefix notation to specify the subnet mask:
         | 
| @@ -539,7 +573,7 @@ The /64 part means that the first 64 bits of the address are | |
| 539 573 | 
             
            representing the network portion, and the last 64 bits are the host
         | 
| 540 574 | 
             
            portion. 
         | 
| 541 575 |  | 
| 542 | 
            -
             | 
| 576 | 
            +
            === Using IPAddress with IPv6 addresses
         | 
| 543 577 |  | 
| 544 578 | 
             
            All the IPv6 representations we've just seen are perfectly fine when
         | 
| 545 579 | 
             
            you want to create a new IPv6 address:
         | 
| @@ -576,7 +610,7 @@ IPv6#compressed method: | |
| 576 610 | 
             
              ip6.compressed
         | 
| 577 611 | 
             
                #=> "2001:db8::8:800:200c:417a"
         | 
| 578 612 |  | 
| 579 | 
            -
             | 
| 613 | 
            +
            === Handling the IPv6 address
         | 
| 580 614 |  | 
| 581 615 | 
             
            Accessing the groups that form an IPv6 address is very easy with the
         | 
| 582 616 | 
             
            IPv6#groups method:
         | 
| @@ -616,21 +650,21 @@ or to hexadecimal representation | |
| 616 650 | 
             
              ip6.to_hex
         | 
| 617 651 | 
             
                #=> "20010db80000000000080800200c417a"
         | 
| 618 652 |  | 
| 619 | 
            -
            To print out an IPv6 address in human readable form, use the IPv6#to_s
         | 
| 620 | 
            -
            and IPv6# | 
| 653 | 
            +
            To print out an IPv6 address in human readable form, use the IPv6#to_s, IPv6#to_string
         | 
| 654 | 
            +
            and IPv6#to_string_uncompressed methods
         | 
| 621 655 |  | 
| 622 656 | 
             
              ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
         | 
| 623 657 |  | 
| 624 | 
            -
              ip6. | 
| 658 | 
            +
              ip6.to_string
         | 
| 625 659 | 
             
                #=> "2001:db8::8:800:200c:417a/96"
         | 
| 626 660 |  | 
| 627 | 
            -
              ip6. | 
| 661 | 
            +
              ip6.to_string_uncompressed
         | 
| 628 662 | 
             
                #=> "2001:0db8:0000:0000:0008:0800:200c:417a/96"
         | 
| 629 663 |  | 
| 630 | 
            -
            As you can see, IPv6. | 
| 631 | 
            -
            IPv6. | 
| 664 | 
            +
            As you can see, IPv6.to_string prints out the compressed form, while
         | 
| 665 | 
            +
            IPv6.to_string_uncompressed uses the expanded version.
         | 
| 632 666 |  | 
| 633 | 
            -
             | 
| 667 | 
            +
            ==== Compressing and uncompressing
         | 
| 634 668 |  | 
| 635 669 | 
             
            If you have a string representing an IPv6 address, you can easily
         | 
| 636 670 | 
             
            compress it and uncompress it using the two class methods IPv6::expand
         | 
| @@ -657,7 +691,7 @@ These methods can be used when you don't want to create a new object | |
| 657 691 | 
             
            just for expanding or compressing an address (although a new object is
         | 
| 658 692 | 
             
            actually created internally).
         | 
| 659 693 |  | 
| 660 | 
            -
             | 
| 694 | 
            +
            === New IPv6 address from other formats
         | 
| 661 695 |  | 
| 662 696 | 
             
            You can create a new IPv6 address from different formats than just a
         | 
| 663 697 | 
             
            string representing the colon-hex groups.
         | 
| @@ -670,7 +704,7 @@ like in the following example: | |
| 670 704 | 
             
              ip6 = IPAddress::IPv6::parse_data data 
         | 
| 671 705 | 
             
              ip6.prefix = 64
         | 
| 672 706 |  | 
| 673 | 
            -
              ip6. | 
| 707 | 
            +
              ip6.to_string
         | 
| 674 708 | 
             
                #=> "2001:db8::8:800:200c:417a/64"
         | 
| 675 709 |  | 
| 676 710 | 
             
            A new IPv6 address can also be created from an unsigned 128 bits
         | 
| @@ -681,7 +715,7 @@ integer: | |
| 681 715 | 
             
              ip6 = IPAddress::IPv6::parse_u128 u128
         | 
| 682 716 | 
             
              ip6.prefix = 64
         | 
| 683 717 |  | 
| 684 | 
            -
              ip6. | 
| 718 | 
            +
              ip6.to_string
         | 
| 685 719 | 
             
                #=> "1080::8:800:200c:417a/64"
         | 
| 686 720 |  | 
| 687 721 | 
             
            Finally, a new IPv6 address can be created from an hex string:
         | 
| @@ -691,16 +725,16 @@ Finally, a new IPv6 address can be created from an hex string: | |
| 691 725 | 
             
              ip6 = IPAddress::IPv6::parse_hex hex
         | 
| 692 726 | 
             
              ip6.prefix = 64
         | 
| 693 727 |  | 
| 694 | 
            -
              ip6. | 
| 728 | 
            +
              ip6.to_string
         | 
| 695 729 | 
             
                #=> "2001:db8::8:800:200c:417a/64"
         | 
| 696 730 |  | 
| 697 | 
            -
             | 
| 731 | 
            +
            === Special IPv6 addresses
         | 
| 698 732 |  | 
| 699 733 | 
             
            Some IPv6 have a special meaning and are expressed in a special form,
         | 
| 700 734 | 
             
            quite different than an usual IPv6 address. IPAddress has builtin
         | 
| 701 735 | 
             
            support for unspecified, loopback and mapped IPv6 addresses.
         | 
| 702 736 |  | 
| 703 | 
            -
             | 
| 737 | 
            +
            ==== Unspecified address
         | 
| 704 738 |  | 
| 705 739 | 
             
            The address with all zero bits is called the +unspecified+ address
         | 
| 706 740 | 
             
            (corresponding to 0.0.0.0 in IPv4). It should be something like this:
         | 
| @@ -721,8 +755,8 @@ subclass: | |
| 721 755 |  | 
| 722 756 | 
             
              ip = IPAddress::IPv6::Unspecified.new
         | 
| 723 757 |  | 
| 724 | 
            -
              ip. | 
| 725 | 
            -
                #=>  | 
| 758 | 
            +
              ip.to_string
         | 
| 759 | 
            +
                #=> "::/128"
         | 
| 726 760 |  | 
| 727 761 | 
             
            You can easily check if an IPv6 object is an unspecified address by
         | 
| 728 762 | 
             
            using the IPv6#unspecified? method
         | 
| @@ -743,7 +777,7 @@ only in software before the application has learned its host's source | |
| 743 777 | 
             
            address appropriate for a pending connection. Routers must not forward
         | 
| 744 778 | 
             
            packets with the unspecified address.
         | 
| 745 779 |  | 
| 746 | 
            -
             | 
| 780 | 
            +
            ==== Loopback address
         | 
| 747 781 |  | 
| 748 782 | 
             
            The loopback  address is a unicast localhost address. If an
         | 
| 749 783 | 
             
            application in a host sends packets to this address, the IPv6 stack
         | 
| @@ -762,14 +796,14 @@ IPAddress calling their own class: | |
| 762 796 |  | 
| 763 797 | 
             
              ip = IPAddress::IPv6::Loopback.new
         | 
| 764 798 |  | 
| 765 | 
            -
              ip. | 
| 799 | 
            +
              ip.to_string
         | 
| 766 800 | 
             
                #=> "::1/128"
         | 
| 767 801 |  | 
| 768 802 | 
             
            or by using the wrapper:
         | 
| 769 803 |  | 
| 770 804 | 
             
              ip = IPAddress "::1"
         | 
| 771 805 |  | 
| 772 | 
            -
              ip. | 
| 806 | 
            +
              ip.to_string
         | 
| 773 807 | 
             
                #=> "::1/128"
         | 
| 774 808 |  | 
| 775 809 | 
             
            Checking if an address is loopback is easy with the IPv6#loopback?
         | 
| @@ -780,7 +814,7 @@ method: | |
| 780 814 |  | 
| 781 815 | 
             
            The IPv6 loopback address corresponds to 127.0.0.1 in IPv4.
         | 
| 782 816 |  | 
| 783 | 
            -
             | 
| 817 | 
            +
            ==== Mapped address
         | 
| 784 818 |  | 
| 785 819 | 
             
            It is usually identified as a IPv4 mapped IPv6 address, a particular
         | 
| 786 820 | 
             
            IPv6 address which aids the transition from IPv4 to IPv6. The
         | 
| @@ -809,8 +843,8 @@ Let's check it's really a mapped address: | |
| 809 843 | 
             
              ip6.mapped?
         | 
| 810 844 | 
             
                #=> true
         | 
| 811 845 |  | 
| 812 | 
            -
              ip6. | 
| 813 | 
            -
                #=> ":: | 
| 846 | 
            +
              ip6.to_string
         | 
| 847 | 
            +
                #=> "::ffff:172.16.10.1/128"
         | 
| 814 848 |  | 
| 815 849 | 
             
            Now with the +ipv4+ attribute, we can easily access the IPv4 portion
         | 
| 816 850 | 
             
            of the mapped IPv6 address:
         | 
| @@ -836,29 +870,29 @@ following format: | |
| 836 870 | 
             
            That is, two colons and the IPv4 address. However, as by RFC, the ffff 
         | 
| 837 871 | 
             
            group will be automatically added at the beginning
         | 
| 838 872 |  | 
| 839 | 
            -
              ip6. | 
| 873 | 
            +
              ip6.to_string
         | 
| 840 874 | 
             
                => "::ffff:172.16.10.1/128"
         | 
| 841 875 |  | 
| 842 876 | 
             
            making it a mapped IPv6 compatible address.
         | 
| 843 877 |  | 
| 844 | 
            -
             | 
| 878 | 
            +
            == Community
         | 
| 845 879 |  | 
| 846 | 
            -
             | 
| 880 | 
            +
            Want to join the community? 
         | 
| 847 881 |  | 
| 848 | 
            -
            *  | 
| 849 | 
            -
            * network design methods for IPv6
         | 
| 850 | 
            -
            * parameter to IPv4#subnet to select where to fill the space
         | 
| 851 | 
            -
              (beginning or ending)
         | 
| 852 | 
            -
            * method to check if a network is private
         | 
| 882 | 
            +
            * {IPAddress google group}[http://groups.google.com/group/ruby-ipaddress]
         | 
| 853 883 |  | 
| 854 | 
            -
             | 
| 884 | 
            +
            We've created a group to discuss about 
         | 
| 885 | 
            +
            IPAddress future development, features and provide some kind of support.
         | 
| 886 | 
            +
            Feel free to join us and tell us what you think!
         | 
| 855 887 |  | 
| 856 | 
            -
             | 
| 888 | 
            +
            == Thanks to
         | 
| 857 889 |  | 
| 858 | 
            -
            Thanks to Luca Russo (vargolo)  | 
| 859 | 
            -
            review.
         | 
| 890 | 
            +
            Thanks to Luca Russo (vargolo) and Simone Carletti (weppos) for all 
         | 
| 891 | 
            +
            the support and technical review. Thanks to Marco Beri, Bryan T. Richardson,
         | 
| 892 | 
            +
            Nicolas Fevrier, jdpace, Daniele Alessandri and Steve Rawlinson for 
         | 
| 893 | 
            +
            their support, feedback and bug reports.
         | 
| 860 894 |  | 
| 861 | 
            -
             | 
| 895 | 
            +
            == Copyright
         | 
| 862 896 |  | 
| 863 897 | 
             
            Copyright (c) 2009-2010 Marco Ceresa. See LICENSE for details.
         | 
| 864 898 |  |