README.rdoc in ipaddress-0.8.0 vs README.rdoc in ipaddress-0.8.2

- old
+ new

@@ -1,5 +1,9 @@ +== <b>IPAddress 1.0 is currently under development and will be released soon! Stay tuned!</b> + +--- + = IPAddress IPAddress is a Ruby library designed to make the use of IPv4 and IPv6 addresses simple, powerful and enjoyable. It provides a complete set of methods to handle IP addresses for any need, from simple scripting to @@ -15,18 +19,20 @@ == Requirements * Ruby >= 1.8.7 (not tested with previous versions) * Ruby 1.9.2 or later is strongly recommended -IPAddress 0.8.0 has been tested on: +IPAddress 0.8.2 has been tested on: * ruby-1.8.7-p334 [ i386 ] * ree-1.8.7-2011.03 [ i386 ] * rbx-head [ ] * jruby-1.6.1 [ linux-i386-java ] * ruby-1.9.1-p431 [ i386 ] * ruby-1.9.2-p180 [ i386 ] +* ruby-2.0.0-p353 [ x86_64-darwin14.0.0 ] +* ruby-2.1.3-p242 [ x86_64-darwin14.0.0 ] If you want to collaborate feel free to send a small report to my email address, or {join the discussion}[http://groups.google.com/group/ruby-ipaddress]. @@ -61,18 +67,18 @@ The latest documentation can be found online at {this address}[http://rubydoc.info/gems/ipaddress/0.8.0/frames] == IPv4 -Class IPAddress::IPv4 is used to handle IPv4 type addresses. IPAddress +Class `IPAddress::IPv4` is used to handle IPv4 type addresses. IPAddress is similar to other IP Addresses libraries, like Ruby's own IPAddr. However it works slightly different, as we will see. === Create a new IPv4 address The usual way to express an IP Address is using its dotted decimal -form, such as 172.16.10.1, and a prefix, such as 24, separated by a +form, such as `172.16.10.1`, and a prefix, such as `24`, separated by a slash. 172.16.10.1/24 To create a new IPv4 object, you can use IPv4 own class @@ -81,42 +87,49 @@ or, in a easier way, using the IPAddress parse method ip = IPAddress.parse "172.16.10.1/24" -which accepts and parses any kind of IP (IPv4, IPV6 and +which accepts and parses any kind of IP (uint32, IPv4, IPV6 and IPv4 IPv6 Mapped addresses). If you like syntactic sugar, you can use the wrapper method -IPAddress(), which is built around IPAddress::parse: +`IPAddress()`, which is built around `IPAddress::parse`: ip = IPAddress "172.16.10.1/24" You can specify an IPv4 address in any of two ways: IPAddress "172.16.10.1/24" IPAddress "172.16.10.1/255.255.255.0" -In this example, prefix /24 and netmask 255.255.255.0 are the same and +In this example, prefix `/24` and netmask `255.255.255.0` are the same and you have the flexibility to use either one of them. If you don't explicitly specify the prefix (or the subnet mask), IPAddress thinks you're dealing with host addresses and not with -networks. Therefore, the default prefix will be /32, or -255.255.255.255. For example: +networks. Therefore, the default prefix will be `/32`, or +`255.255.255.255`. For example: # let's declare an host address host = IPAddress::IPv4.new "10.1.1.1" puts host.to_string #=> "10.1.1.1/32" -The new created object has prefix /32, which is the same +The new created object has prefix `/32`, which is the same as we created the following: host = IPAddress::IPv4.new "10.1.1.1/32" - + +You can also pass a `uint32` to obtain an `IPAddress::IPv4` object: + + # Create host object + ip = IPAddress 167837953 + puts ip.to_string + #=> "10.1.1.1/32" + === Handling the IPv4 address Once created, you can obtain the attributes for an IPv4 object: ip = IPAddress("172.16.10.1/24") @@ -125,29 +138,29 @@ #=> "172.16.10.1" ip.prefix #=> 24 In case you need to retrieve the netmask in IPv4 format, you can use -the IPv4#netmask method: +the `IPv4#netmask` method: ip.netmask #=> "255.255.255.0" -A special attribute, IPv4#octets, is available to get the four +A special attribute, `IPv4#octets`, is available to get the four decimal octets from the IP address: ip.octets #=> [172,16,10,1] -Shortcut method IPv4#[], provides access to a given octet whithin the +Shortcut method `IPv4#[]`, provides access to a given octet whithin the range: ip[1] #=> 16 If you need to print out the IPv4 address in a canonical form, you can -use IPv4#to_string +use `IPv4#to_string`: ip.to_string #=> "172.16.10.l/24" === Changing netmask @@ -159,11 +172,11 @@ ip.to_string #=> "172.16.10.l/25" If you need to use a netmask in IPv4 format, you can achive so by -using the IPv4#netmask= method +using the `IPv4#netmask=` method: ip.netmask = "255.255.255.252" ip.to_string #=> "172.16.10.1/30" @@ -172,24 +185,24 @@ Some very important topics in dealing with IP addresses are the concepts of +network+ and +broadcast+, as well as the addresses included in a range. -When you specify an IPv4 address such as "172.16.10.1/24", you are +When you specify an IPv4 address such as `172.16.10.1/24`, you are actually handling two different information: * The IP address itself, "172.16.10.1" * The subnet mask which indicates the network The network number is the IP which has all zeroes in the host portion. In our example, because the prefix is 24, we identify our network number to have the last 8 (32-24) bits all zeroes. Thus, IP -address "172.16.10.1/24" belongs to network "172.16.10.0/24". +address `172.16.10.1/24` belongs to network `172.16.10.0/24`. -This is very important because, for instance, IP "172.16.10.1/16" is +This is very important because, for instance, IP `172.16.10.1/16` is very different to the previous one, belonging to the very different -network "172.16.0.0/16". +network `172.16.0.0/16`. ==== Networks With IPAddress it's very easy to calculate the network for an IP address: @@ -206,11 +219,11 @@ Method IPv4#network creates a new IPv4 object from the network number, calculated after the original object. We want to outline here that the network address is a perfect legitimate IPv4 address, which just happen to have all zeroes in the host portion. -You can use method IPv4#network? to check whether an IP address is a +You can use method `IPv4#network?` to check whether an IP address is a network or not: ip1 = IPAddress "172.16.10.1/24" ip2 = IPAddress "172.16.10.4/30" @@ -221,15 +234,15 @@ ==== Broadcast The broadcast address is the contrary than the network number: where the network number has all zeroes in the host portion, the broadcast -address has all one's. For example, ip "172.16.10.1/24" has broadcast -"172.16.10.255/24", where ip "172.16.10.1/16" has broadcast -"172.16.255.255/16". +address has all one's. For example, ip `172.16.10.1/24` has broadcast +`172.16.10.255/24`, where ip `172.16.10.1/16` has broadcast +`172.16.255.255/16`. -Method IPv4#broadcast has the same behavior as is #network +Method `IPv4#broadcast` has the same behavior as is `#network` counterpart: it creates a new IPv4 object to handle the broadcast address: ip = IPAddress "172.16.10.1/24" @@ -243,11 +256,11 @@ ==== Addresses, ranges and iterators So we see that the netmask essentially specifies a range for IP addresses that are included in a network: all the addresses between the network number and the broadcast. IPAddress has many methods to -iterate between those addresses. Let's start with IPv4#each, which +iterate between those addresses. Let's start with `IPv4#each`, which iterates over all addresses in a range ip = IPAddress "172.16.10.1/24" ip.each do |addr| @@ -256,30 +269,52 @@ It is important to note that it doesn't matter if the original IP is a host IP or a network number (or a broadcast address): the #each method only considers the range that the original IP specifies. -If you only want to iterate over hosts IP, use the IPv4#each_host +If you only want to iterate over hosts IP, use the `IPv4#each_host` method: ip = IPAddress "172.16.10.1/24" ip.each_host do |host| puts host end -Methods IPv4#first and IPv4#last return a new object containing +Methods `IPv4#first` and `IPv4#last` return a new object containing respectively the first and the last host address in the range ip = IPAddress "172.16.10.100/24" ip.first.to_string #=> "172.16.10.1/24" ip.last.to_string #=> "172.16.10.254/24" +Checking if an address is loopback is easy with the `IPv4#loopback?` +method: + + ip = IPAddress "127.0.0.1" + + ip.loopback? + #=> true + +Checking if an address is in the multicast range can be done using the `IPv4#multicast?` +method: + + ip = IPAddress "224.0.0.1/32" + + ip.multicast? + #=> true + +The ability to generate a range also exists by using the `IPv4#to()` method. This allows you to create a subnet agnostic range based off a fixed amount. + + ip = IPAddress "172.16.10.100/24" + ip.to('172.16.10.110') + #=> ["172.16.10.100", ..., "172.16.10.110"] + === IP special formats The IPAddress library provides a complete set of methods to access an IPv4 address in special formats, such as binary, 32 bits unsigned int, data and hexadecimal. @@ -293,42 +328,47 @@ The first thing to highlight here is that all these conversion methods only take into consideration the address portion of an IPv4 object and not the prefix (netmask). -So, to express the address in binary format, use the IPv4#bits method: +So, to express the address in binary format, use the `IPv4#bits` method: ip.bits #=> "10101100000100000000101000000001" To calculate the 32 bits unsigned int format of the ip address, use -the IPv4#to_u32 method +the `IPv4#to_u32` method ip.to_u32 #=> 2886732289 -This method is the equivalent of the Unix call pton(), expressing an +This method is the equivalent of the Unix call `pton()`, expressing an IP address in the so called +network byte order+ notation. However, if you want to transmit your IP over a network socket, you might need to -transform it in data format using the IPv4#data method: +transform it in data format using the `IPv4#data` method: ip.data #=> "\254\020\n\001" -Finally, you can transform an IPv4 address into a format which is +Also, you can transform an IPv4 address into a format which is suitable to use in IPv4-IPv6 mapped addresses: ip.to_ipv6 #=> "ac10:0a01" +Finally, much like `IPv4#to_ipv6` you can use to `IPv4#to_h` method to return a non-semicolon delineated string (useful with pcap/byte level usage): + + ip.to_h + #=> "ac100a01" + === Classful networks IPAddress allows you to create and manipulate objects using the old and deprecated (but apparently still popular) classful networks concept. Classful networks and addresses don't have a prefix: their subnet mask -is univocally identified by their address, and therefore diveded in classes. +is univocally identified by their address, and therefore divided in classes. As per RFC 791, these classes are: * Class A, from 0.0.0.0 to 127.255.255.255 * Class B, from 128.0.0.0 to 191.255.255.255 * Class C, from 192.0.0.0 to 255.255.255.255 @@ -386,11 +426,11 @@ Subnetting is easy with IPAddress. You actually have two options: * IPv4#subnet: specify a new prefix * IPv4#split: tell IPAddress how many subnets you want to create. -Let's examine IPv4#subnet first. Say you have network "172.16.10.0/24" +Let's examine `IPv4#subnet` first. Say you have network "172.16.10.0/24" and you want to subnet it into /26 networks. With IPAddress it's very easy: network = IPAddress "172.16.10.0/24" @@ -406,11 +446,11 @@ representing the new subnets. Another way to create subnets is to tell IPAddress how many subnets you'd like to have, and letting the library calculate the new prefix for you. -Let's see how it works, using IPv4#split method. Say you want 4 new subnets: +Let's see how it works, using `IPv4#split` method. Say you want 4 new subnets: network = IPAddress("172.16.10.0/24") subnets = network.split(4) @@ -419,19 +459,19 @@ "172.16.10.64/26", "172.16.10.128/26", "172.16.10.192/26"] Hey, that's the same result as before! This actually makes sense, as the -two operations are complementary. When you use IPv4#subnet with the new +two operations are complementary. When you use `IPv4#subnet` with the new prefix, IPAddress will always create a number of subnets that is a power of two. This is equivalent to use IPv4#split with a power of 2. -Where IPv4#split really shines is with the so called "uneven subnetting". +Where `IPv4#split` really shines is with the so called "uneven subnetting". You are not limited to split a network into a power-of-two numbers of subnets: IPAddress lets you create any number of subnets, and it will try to organize the new created network in the best possible way, making -an efficent allocation of the space. +an efficient allocation of the space. An example here is worth a thousand words. Let's use the same network as the previous examples: network = IPAddress("172.16.10.0/24") @@ -445,12 +485,12 @@ "172.16.10.64/26", "172.16.10.128/25"] As you can see, IPAddress tried to perform a good allocation by filling up all the address space from the original network. There is no point in splitting -a network into 3 subnets like "172.16.10.0/26", "172.16.10.64/26" and -"172.16.10.128/26", as you would end up having "172.16.10.192/26" wasted (plus, +a network into 3 subnets like `172.16.10.0/26`, `172.16.10.64/26` and +`172.16.10.128/26`, as you would end up having `172.16.10.192/26` wasted (plus, I suppose I wouldn't need a Ruby library to perform un-efficient IP allocation, as I do that myself very well ;) ). We can go even further and split into 11 subnets: @@ -458,12 +498,12 @@ #=> ["172.16.10.0/28", "172.16.10.16/28", "172.16.10.32/28", "172.16.10.48/28", "172.16.10.64/28", "172.16.10.80/28", "172.16.10.96/28", "172.16.10.112/28", "172.16.10.128/27", "172.16.10.160/27", "172.16.10.192/26"] -As you can see, most of the networks are /28, with a few /27 and one -/26 to fill up the remaining space. +As you can see, most of the networks are `/28`, with a few `/27` and one +`/26` to fill up the remaining space. ==== Summarization Summarization (or aggregation) is the process when two or more networks are taken together to check if a supernet, including @@ -487,14 +527,14 @@ ip2 = IPAddress("172.16.11.0/24") These two networks can be expressed using only one IP address network if we change the prefix. Let Ruby do the work: - IPAddress::IPv4::summarize(ip1,ip2).to_string + IPAddress::IPv4::summarize(ip1,ip2).map(&:to_string) #=> "172.16.10.0/23" -We note how the network "172.16.10.0/23" includes all the +We note how the network `172.16.10.0/23` includes all the addresses specified in the above networks, and (more important) includes ONLY those addresses. If we summarized +ip1+ and +ip2+ with the following network: @@ -507,11 +547,11 @@ is not an aggregate network for +ip1+ and +ip2+. If it's not possible to compute a single aggregated network for all the original networks, the method returns an array with all the aggregate networks found. For example, the following four networks can be -aggregated in a single /22: +aggregated in a single `/22`: ip1 = IPAddress("10.0.0.1/24") ip2 = IPAddress("10.0.1.1/24") ip3 = IPAddress("10.0.2.1/24") ip4 = IPAddress("10.0.3.1/24") @@ -529,11 +569,11 @@ IPAddress::IPv4::summarize(ip1,ip2,ip3,ip4).map{|i| i.to_string} #=> ["10.0.1.0/24","10.0.2.0/23","10.0.4.0/24"] In this case, the two summarizables networks have been aggregated into -a single /23, while the other two networks have been left untouched. +a single `/23`, while the other two networks have been left untouched. ==== Supernetting Supernetting is a different operation than aggregation, as it only works on a single network and returns a new single IPv4 object, @@ -548,17 +588,17 @@ you can supernet it with a new /23 prefix ip.supernet(23).to_string #=> "172.16.10.0/23" -However if you supernet it with a /22 prefix, the network address will +However if you supernet it with a `/22` prefix, the network address will change: ip.supernet(22).to_string #=> "172.16.8.0/22" -This is because "172.16.10.0/22" is not a network anymore, but an host +This is because `172.16.10.0/22` is not a network anymore, but an host address. == IPv6 IPAddress is not only fantastic for IPv4 addresses, it's also great to @@ -636,29 +676,29 @@ ip6.prefix #=> 64 A compressed version of the IPv6 address can be obtained with the -IPv6#compressed method: +`IPv6#compressed` method: ip6 = IPAddress "2001:0db8:0000:0000:0008:200c:417a:00ab/64" ip6.compressed #=> "2001:db8::8:800:200c:417a" === Handling the IPv6 address Accessing the groups that form an IPv6 address is very easy with the -IPv6#groups method: +`IPv6#groups` method: ip6 = IPAddress "2001:db8::8:800:200c:417a/64" ip6.groups #=> [8193, 3512, 0, 0, 8, 2048, 8204, 16762] As with IPv4 addresses, each individual group can be accessed using -the IPv6#[] shortcut method: +the `IPv6#[]` shortcut method: ip6[0] #=> 8193 ip6[1] #=> 3512 @@ -666,40 +706,40 @@ #=> 0 ip6[3] #=> 0 Note that each 16 bits group is expressed in its decimal form. You can -also obtain the groups into hexadecimal format using the IPv6#hexs +also obtain the groups into hexadecimal format using the `IPv6#hexs` method: ip6.hexs #=> => ["2001", "0db8", "0000", "0000", "0008", "0800", "200c", "417a"] A few other methods are available to transform an IPv6 address into -decimal representation, with IPv6.to_i +decimal representation, with `IPv6.to_i` ip6.to_i #=> 42540766411282592856906245548098208122 or to hexadecimal representation ip6.to_hex #=> "20010db80000000000080800200c417a" -To print out an IPv6 address in human readable form, use the IPv6#to_s, IPv6#to_string -and IPv6#to_string_uncompressed methods +To print out an IPv6 address in human readable form, use the `IPv6#to_s`, `IPv6#to_string` +and `IPv6#to_string_uncompressed` methods ip6 = IPAddress "2001:db8::8:800:200c:417a/64" ip6.to_string #=> "2001:db8::8:800:200c:417a/96" ip6.to_string_uncompressed #=> "2001:0db8:0000:0000:0008:0800:200c:417a/96" -As you can see, IPv6.to_string prints out the compressed form, while -IPv6.to_string_uncompressed uses the expanded version. +As you can see, `IPv6.to_string` prints out the compressed form, while +`IPv6.to_string_uncompressed` uses the expanded version. ==== Compressing and uncompressing If you have a string representing an IPv6 address, you can easily compress it and uncompress it using the two class methods IPv6::expand @@ -729,11 +769,11 @@ === New IPv6 address from other formats You can create a new IPv6 address from different formats than just a string representing the colon-hex groups. -For instance, if you have a data stream, you can use IPv6::parse_data, +For instance, if you have a data stream, you can use `IPv6::parse_data`, like in the following example: data = " \001\r\270\000\000\000\000\000\b\b\000 \fAz" ip6 = IPAddress::IPv6::parse_data data @@ -770,11 +810,11 @@ support for unspecified, loopback and mapped IPv6 addresses. ==== Unspecified address The address with all zero bits is called the +unspecified+ address -(corresponding to 0.0.0.0 in IPv4). It should be something like this: +(corresponding to `0.0.0.0` in IPv4). It should be something like this: 0000:0000:0000:0000:0000:0000:0000:0000 but, with the use of compression, it is usually written as just two colons: @@ -812,11 +852,11 @@ address appropriate for a pending connection. Routers must not forward packets with the unspecified address. ==== Loopback address -The loopback address is a unicast localhost address. If an +The loopback address is a unicast localhost address. If an application in a host sends packets to this address, the IPv6 stack will loop these packets back on the same virtual interface. Loopback addresses are expressed in the following form: @@ -839,27 +879,27 @@ ip = IPAddress "::1" ip.to_string #=> "::1/128" -Checking if an address is loopback is easy with the IPv6#loopback? +Checking if an address is loopback is easy with the `IPv6#loopback?` method: ip.loopback? #=> true -The IPv6 loopback address corresponds to 127.0.0.1 in IPv4. +The IPv6 loopback address corresponds to `127.0.0.1` in IPv4. ==== Mapped address It is usually identified as a IPv4 mapped IPv6 address, a particular IPv6 address which aids the transition from IPv4 to IPv6. The structure of the address is ::ffff:w.y.x.z -where w.x.y.z is a normal IPv4 address. For example, the following is +where `w.x.y.z` is a normal IPv4 address. For example, the following is a mapped IPv6 address: ::ffff:192.168.100.1 IPAddress is very powerful in handling mapped IPv6 addresses, as the @@ -879,11 +919,11 @@ #=> true ip6.to_string #=> "::ffff:172.16.10.1/128" -Now with the +ipv4+ attribute, we can easily access the IPv4 portion +Now with the `#ipv4` attribute, we can easily access the IPv4 portion of the mapped IPv6 address: ip6.ipv4.address #=> "172.16.10.1" @@ -900,11 +940,11 @@ A mapped IPv6 can also be created just by specify the address in the following format: ip6 = IPAddress "::172.16.10.1" -That is, two colons and the IPv4 address. However, as by RFC, the ffff +That is, two colons and the IPv4 address. However, as by RFC, the `ffff` group will be automatically added at the beginning ip6.to_string => "::ffff:172.16.10.1/128" @@ -953,9 +993,6 @@ Erik Ahlström, Peter Vandenberk and Steve Rawlinson for their support, feedback and bug reports. == Copyright -Copyright (c) 2009-2011 Marco Ceresa. See LICENSE for details. - - - +Copyright (c) 2009-2015 Marco Ceresa and Mike Mackintosh. See LICENSE for details.