blackwinter-ipaddress 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,961 @@
1
+ = IPAddress
2
+
3
+ IPAddress is a Ruby library designed to make the use of IPv4 and IPv6
4
+ addresses simple, powerful and enjoyable. It provides a complete set of
5
+ methods to handle IP addresses for any need, from simple scripting to
6
+ full network design.
7
+
8
+ IPAddress is written with a full OO interface, and its code is easy to
9
+ read, maintain and extend. The documentation is full of examples, to
10
+ let you start being productive immediately.
11
+
12
+ This document provides a brief introduction to the library and
13
+ examples of typical usage.
14
+
15
+ == Requirements
16
+
17
+ * Ruby >= 1.8.7 (not tested with previous versions)
18
+ * Ruby 1.9.2 or later is strongly recommended
19
+
20
+ IPAddress 0.8.0 has been tested on:
21
+
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
+
29
+ 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
+
34
+ == Installation
35
+
36
+ Install the library using rubygems
37
+
38
+ $ gem install ipaddress
39
+
40
+ You can then use it in your programs:
41
+
42
+ require 'rubygems' # optional
43
+ require 'ipaddress'
44
+
45
+ Another way would be to clone the git repository
46
+
47
+ $ git clone git://github.com/bluemonk/ipaddress.git
48
+
49
+ And then install the library
50
+
51
+ $ cd ipaddress
52
+ ipaddress$ rake install
53
+
54
+ == Documentation
55
+
56
+ The code is fully documented with RDoc. You can generate the
57
+ documentation with Rake:
58
+
59
+ ipaddress$ rake rdoc
60
+
61
+ The latest documentation can be found online at
62
+ {this address}[http://rubydoc.info/gems/ipaddress/0.8.0/frames]
63
+
64
+ == IPv4
65
+
66
+ Class IPAddress::IPv4 is used to handle IPv4 type addresses. IPAddress
67
+ is similar to other IP Addresses libraries, like Ruby's own
68
+ IPAddr. However it works slightly different, as we will see.
69
+
70
+ === Create a new IPv4 address
71
+
72
+ The usual way to express an IP Address is using its dotted decimal
73
+ form, such as 172.16.10.1, and a prefix, such as 24, separated by a
74
+ slash.
75
+
76
+ 172.16.10.1/24
77
+
78
+ To create a new IPv4 object, you can use IPv4 own class
79
+
80
+ ip = IPAddress::IPv4.new "172.16.10.1/24"
81
+
82
+ or, in a easier way, using the IPAddress parse method
83
+
84
+ ip = IPAddress.parse "172.16.10.1/24"
85
+
86
+ which accepts and parses any kind of IP (IPv4, IPV6 and
87
+ IPv4 IPv6 Mapped addresses).
88
+
89
+ If you like syntactic sugar, you can use the wrapper method
90
+ IPAddress(), which is built around IPAddress::parse:
91
+
92
+ ip = IPAddress "172.16.10.1/24"
93
+
94
+ You can specify an IPv4 address in any of two ways:
95
+
96
+ IPAddress "172.16.10.1/24"
97
+ IPAddress "172.16.10.1/255.255.255.0"
98
+
99
+ In this example, prefix /24 and netmask 255.255.255.0 are the same and
100
+ you have the flexibility to use either one of them.
101
+
102
+ If you don't explicitly specify the prefix (or the subnet mask),
103
+ IPAddress thinks you're dealing with host addresses and not with
104
+ networks. Therefore, the default prefix will be /32, or
105
+ 255.255.255.255. For example:
106
+
107
+ # let's declare an host address
108
+ host = IPAddress::IPv4.new "10.1.1.1"
109
+
110
+ puts host.to_string
111
+ #=> "10.1.1.1/32"
112
+
113
+ The new created object has prefix /32, which is the same
114
+ as we created the following:
115
+
116
+ host = IPAddress::IPv4.new "10.1.1.1/32"
117
+
118
+ === Handling the IPv4 address
119
+
120
+ Once created, you can obtain the attributes for an IPv4 object:
121
+
122
+ ip = IPAddress("172.16.10.1/24")
123
+
124
+ ip.address
125
+ #=> "172.16.10.1"
126
+ ip.prefix
127
+ #=> 24
128
+
129
+ In case you need to retrieve the netmask in IPv4 format, you can use
130
+ the IPv4#netmask method:
131
+
132
+ ip.netmask
133
+ #=> "255.255.255.0"
134
+
135
+ A special attribute, IPv4#octets, is available to get the four
136
+ decimal octets from the IP address:
137
+
138
+ ip.octets
139
+ #=> [172,16,10,1]
140
+
141
+ Shortcut method IPv4#[], provides access to a given octet whithin the
142
+ range:
143
+
144
+ ip[1]
145
+ #=> 16
146
+
147
+ If you need to print out the IPv4 address in a canonical form, you can
148
+ use IPv4#to_string
149
+
150
+ ip.to_string
151
+ #=> "172.16.10.l/24"
152
+
153
+ === Changing netmask
154
+
155
+ You can set a new prefix (netmask) after creating an IPv4
156
+ object. For example:
157
+
158
+ ip.prefix = 25
159
+
160
+ ip.to_string
161
+ #=> "172.16.10.l/25"
162
+
163
+ If you need to use a netmask in IPv4 format, you can achive so by
164
+ using the IPv4#netmask= method
165
+
166
+ ip.netmask = "255.255.255.252"
167
+
168
+ ip.to_string
169
+ #=> "172.16.10.1/30"
170
+
171
+ === Working with networks, broadcasts and addresses
172
+
173
+ Some very important topics in dealing with IP addresses are the
174
+ concepts of +network+ and +broadcast+, as well as the addresses
175
+ included in a range.
176
+
177
+ When you specify an IPv4 address such as "172.16.10.1/24", you are
178
+ actually handling two different information:
179
+
180
+ * The IP address itself, "172.16.10.1"
181
+ * The subnet mask which indicates the network
182
+
183
+ The network number is the IP which has all zeroes in the host
184
+ portion. In our example, because the prefix is 24, we identify our
185
+ network number to have the last 8 (32-24) bits all zeroes. Thus, IP
186
+ address "172.16.10.1/24" belongs to network "172.16.10.0/24".
187
+
188
+ This is very important because, for instance, IP "172.16.10.1/16" is
189
+ very different to the previous one, belonging to the very different
190
+ network "172.16.0.0/16".
191
+
192
+ ==== Networks
193
+
194
+ With IPAddress it's very easy to calculate the network for an IP
195
+ address:
196
+
197
+ ip = IPAddress "172.16.10.1/24"
198
+
199
+ net = ip.network
200
+ #=> #<IPAddress::IPv4:0xb7a5ab24 @octets=[172, 16, 10, 0],
201
+ @prefix=24,
202
+ @address="172.16.10.0">
203
+ net.to_string
204
+ #=> "172.16.10.0/24"
205
+
206
+ Method IPv4#network creates a new IPv4 object from the network
207
+ number, calculated after the original object. We want to outline here
208
+ that the network address is a perfect legitimate IPv4 address, which
209
+ just happen to have all zeroes in the host portion.
210
+
211
+ You can use method IPv4#network? to check whether an IP address is a
212
+ network or not:
213
+
214
+ ip1 = IPAddress "172.16.10.1/24"
215
+ ip2 = IPAddress "172.16.10.4/30"
216
+
217
+ ip1.network?
218
+ #=> false
219
+ ip2.network?
220
+ #=> true
221
+
222
+ ==== Broadcast
223
+
224
+ The broadcast address is the contrary than the network number: where
225
+ the network number has all zeroes in the host portion, the broadcast
226
+ address has all one's. For example, ip "172.16.10.1/24" has broadcast
227
+ "172.16.10.255/24", where ip "172.16.10.1/16" has broadcast
228
+ "172.16.255.255/16".
229
+
230
+ Method IPv4#broadcast has the same behavior as is #network
231
+ counterpart: it creates a new IPv4 object to handle the broadcast
232
+ address:
233
+
234
+ ip = IPAddress "172.16.10.1/24"
235
+
236
+ bcast = ip.broadcast
237
+ #=> #<IPAddress::IPv4:0xb7a406fc @octets=[172, 16, 10, 255],
238
+ @prefix=24,
239
+ @address="172.16.10.255">
240
+ bcast.to_string
241
+ #=> "172.16.10.255/24"
242
+
243
+ ==== Addresses, ranges and iterators
244
+
245
+ So we see that the netmask essentially specifies a range for IP
246
+ addresses that are included in a network: all the addresses between
247
+ the network number and the broadcast. IPAddress has many methods to
248
+ iterate between those addresses. Let's start with IPv4#each, which
249
+ iterates over all addresses in a range
250
+
251
+ ip = IPAddress "172.16.10.1/24"
252
+
253
+ ip.each do |addr|
254
+ puts addr
255
+ end
256
+
257
+ It is important to note that it doesn't matter if the original IP is a
258
+ host IP or a network number (or a broadcast address): the #each method
259
+ only considers the range that the original IP specifies.
260
+
261
+ If you only want to iterate over hosts IP, use the IPv4#each_host
262
+ method:
263
+
264
+ ip = IPAddress "172.16.10.1/24"
265
+
266
+ ip.each_host do |host|
267
+ puts host
268
+ end
269
+
270
+ Methods IPv4#first and IPv4#last return a new object containing
271
+ respectively the first and the last host address in the range
272
+
273
+ ip = IPAddress "172.16.10.100/24"
274
+
275
+ ip.first.to_string
276
+ #=> "172.16.10.1/24"
277
+
278
+ ip.last.to_string
279
+ #=> "172.16.10.254/24"
280
+
281
+ === IP special formats
282
+
283
+ The IPAddress library provides a complete set of methods to access an
284
+ IPv4 address in special formats, such as binary, 32 bits unsigned int,
285
+ data and hexadecimal.
286
+
287
+ Let's take the following IPv4 as an example:
288
+
289
+ ip = IPAddress "172.16.10.1/24"
290
+
291
+ ip.address
292
+ #=> "172.16.10.1"
293
+
294
+ The first thing to highlight here is that all these conversion methods
295
+ only take into consideration the address portion of an IPv4 object and
296
+ not the prefix (netmask).
297
+
298
+ So, to express the address in binary format, use the IPv4#bits method:
299
+
300
+ ip.bits
301
+ #=> "10101100000100000000101000000001"
302
+
303
+ To calculate the 32 bits unsigned int format of the ip address, use
304
+ the IPv4#to_u32 method
305
+
306
+ ip.to_u32
307
+ #=> 2886732289
308
+
309
+ This method is the equivalent of the Unix call pton(), expressing an
310
+ IP address in the so called +network byte order+ notation. However, if
311
+ you want to transmit your IP over a network socket, you might need to
312
+ transform it in data format using the IPv4#data method:
313
+
314
+ ip.data
315
+ #=> "\254\020\n\001"
316
+
317
+ Finally, you can transform an IPv4 address into a format which is
318
+ suitable to use in IPv4-IPv6 mapped addresses:
319
+
320
+ ip.to_ipv6
321
+ #=> "ac10:0a01"
322
+
323
+ === Classful networks
324
+
325
+ IPAddress allows you to create and manipulate objects using the old
326
+ and deprecated (but apparently still popular) classful networks concept.
327
+
328
+ Classful networks and addresses don't have a prefix: their subnet mask
329
+ is univocally identified by their address, and therefore diveded in classes.
330
+ As per RFC 791, these classes are:
331
+
332
+ * Class A, from 0.0.0.0 to 127.255.255.255
333
+ * Class B, from 128.0.0.0 to 191.255.255.255
334
+ * Class C, from 192.0.0.0 to 255.255.255.255
335
+
336
+ Since classful networks here are only considered to calculate the default
337
+ prefix number, classes D and E are not considered.
338
+
339
+ To create a classful IP and prefix from an IP address, use the
340
+ IPv4::parse_classful method:
341
+
342
+ # classful ip
343
+ ip = IPAddress::IPv4::parse_classful "10.1.1.1"
344
+
345
+ ip.prefix
346
+ #=> 8
347
+
348
+ The method automatically created a new IPv4 object and assigned it
349
+ the correct prefix.
350
+
351
+ You can easily check which CLASSFUL network an IPv4 object belongs:
352
+
353
+ ip = IPAddress("10.0.0.1/24")
354
+ ip.a?
355
+ #=> true
356
+
357
+ ip = IPAddress("172.16.10.1/24")
358
+ ip.b?
359
+ #=> true
360
+
361
+ ip = IPAddress("192.168.1.1/30")
362
+ ip.c?
363
+ #=> true
364
+
365
+ Remember that these methods are only checking the address portion of an IP, and are
366
+ independent from its prefix, as classful networks have no concept of prefix.
367
+
368
+ For more information on CLASSFUL networks visit the
369
+ {Wikipedia page}[http://en.wikipedia.org/wiki/Classful_network]
370
+
371
+ === Network design with IPAddress
372
+
373
+ IPAddress includes a lot of useful methods to manipulate IPv4 and IPv6
374
+ networks and do some basic network design.
375
+
376
+ ==== Subnetting
377
+
378
+ The process of subnetting is the division of a network into smaller
379
+ (in terms of hosts capacity) networks, called subnets, so that they
380
+ all share a common root, which is the starting network.
381
+
382
+ For example, if you have network "172.16.10.0/24", we can subnet it
383
+ into 4 smaller subnets. The new prefix will be /26, because 4 is 2^2
384
+ and therefore we add 2 bits to the network prefix (24+2=26).
385
+
386
+ Subnetting is easy with IPAddress. You actually have two options:
387
+
388
+ * IPv4#subnet: specify a new prefix
389
+ * IPv4#split: tell IPAddress how many subnets you want to create.
390
+
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)
398
+
399
+ subnets.map{|i| i.to_string}
400
+ #=> ["172.16.10.0/26",
401
+ "172.16.10.64/26",
402
+ "172.16.10.128/26",
403
+ "172.16.10.192/26"]
404
+
405
+ As you can see, an Array has been created, containing 4 new IPv4 objects
406
+ representing the new subnets.
407
+
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)
416
+
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"]
422
+
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.
427
+
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.
433
+
434
+ An example here is worth a thousand words. Let's use the same network
435
+ as the previous examples:
436
+
437
+ network = IPAddress("172.16.10.0/24")
438
+
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}
444
+ #=> ["172.16.10.0/26",
445
+ "172.16.10.64/26",
446
+ "172.16.10.128/25"]
447
+
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 ;) ).
454
+
455
+ We can go even further and split into 11 subnets:
456
+
457
+ network.split(11)
458
+ #=> ["172.16.10.0/28", "172.16.10.16/28", "172.16.10.32/28",
459
+ "172.16.10.48/28", "172.16.10.64/28", "172.16.10.80/28",
460
+ "172.16.10.96/28", "172.16.10.112/28", "172.16.10.128/27",
461
+ "172.16.10.160/27", "172.16.10.192/26"]
462
+
463
+ As you can see, most of the networks are /28, with a few /27 and one
464
+ /26 to fill up the remaining space.
465
+
466
+ ==== Summarization
467
+
468
+ Summarization (or aggregation) is the process when two or more
469
+ networks are taken together to check if a supernet, including
470
+ all and only these networks, exists. If it exists then this supernet
471
+ is called the summarized (or aggregated) network.
472
+ It is very important to understand that summarization can only
473
+ occur if there are no holes in the aggregated network, or, in
474
+ other words, if the given networks fill completely the address space
475
+ of the supernet. So the two rules are:
476
+
477
+ 1) The aggregate network must contain +all+ the IP addresses of the
478
+ original networks;
479
+
480
+ 2) The aggregate network must contain +only+ the IP addresses of the
481
+ original networks;
482
+
483
+ A few examples will help clarify the above. Let's consider for
484
+ instance the following two networks:
485
+
486
+ ip1 = IPAddress("172.16.10.0/24")
487
+ ip2 = IPAddress("172.16.11.0/24")
488
+
489
+ These two networks can be expressed using only one IP address
490
+ network if we change the prefix. Let Ruby do the work:
491
+
492
+ IPAddress::IPv4::summarize(ip1,ip2).to_string
493
+ #=> "172.16.10.0/23"
494
+
495
+ We note how the network "172.16.10.0/23" includes all the
496
+ addresses specified in the above networks, and (more important) includes
497
+ ONLY those addresses.
498
+
499
+ If we summarized +ip1+ and +ip2+ with the following network:
500
+
501
+ "172.16.0.0/16"
502
+
503
+ we would have satisfied rule #1 above, but not rule #2. So
504
+
505
+ "172.16.0.0/16"
506
+
507
+ is not an aggregate network for +ip1+ and +ip2+.
508
+
509
+ If it's not possible to compute a single aggregated network for
510
+ all the original networks, the method returns an array with all the
511
+ aggregate networks found. For example, the following four networks can be
512
+ aggregated in a single /22:
513
+
514
+ ip1 = IPAddress("10.0.0.1/24")
515
+ ip2 = IPAddress("10.0.1.1/24")
516
+ ip3 = IPAddress("10.0.2.1/24")
517
+ ip4 = IPAddress("10.0.3.1/24")
518
+
519
+ IPAddress::IPv4::summarize(ip1,ip2,ip3,ip4).map{|i| i.to_string}
520
+ #=> ["10.0.0.0/22"]
521
+
522
+ But the following networks can't be summarized in a single
523
+ network:
524
+
525
+ ip1 = IPAddress("10.0.1.1/24")
526
+ ip2 = IPAddress("10.0.2.1/24")
527
+ ip3 = IPAddress("10.0.3.1/24")
528
+ ip4 = IPAddress("10.0.4.1/24")
529
+
530
+ IPAddress::IPv4::summarize(ip1,ip2,ip3,ip4).map{|i| i.to_string}
531
+ #=> ["10.0.1.0/24","10.0.2.0/23","10.0.4.0/24"]
532
+
533
+ In this case, the two summarizables networks have been aggregated into
534
+ a single /23, while the other two networks have been left untouched.
535
+
536
+ ==== Supernetting
537
+
538
+ Supernetting is a different operation than aggregation, as it only
539
+ works on a single network and returns a new single IPv4 object,
540
+ representing the supernet.
541
+
542
+ Supernetting is similar to subnetting, except that you getting as a
543
+ result a network with a smaller prefix (bigger host space). For
544
+ example, given the network
545
+
546
+ ip = IPAddress("172.16.10.0/24")
547
+
548
+ you can supernet it with a new /23 prefix
549
+
550
+ ip.supernet(23).to_string
551
+ #=> "172.16.10.0/23"
552
+
553
+ However if you supernet it with a /22 prefix, the network address will
554
+ change:
555
+
556
+ ip.supernet(22).to_string
557
+ #=> "172.16.8.0/22"
558
+
559
+ This is because "172.16.10.0/22" is not a network anymore, but an host
560
+ address.
561
+
562
+ == IPv6
563
+
564
+ IPAddress is not only fantastic for IPv4 addresses, it's also great to
565
+ handle IPv6 addresses family! Let's discover together how to use it in
566
+ our projects.
567
+
568
+ === IPv6 addresses
569
+
570
+ IPv6 addresses are 128 bits long, in contrast with IPv4 addresses
571
+ which are only 32 bits long. An IPv6 address is generally written as
572
+ eight groups of four hexadecimal digits, each group representing 16
573
+ bits or two octet. For example, the following is a valid IPv6
574
+ address:
575
+
576
+ 2001:0db8:0000:0000:0008:0800:200c:417a
577
+
578
+ Letters in an IPv6 address are usually written downcase, as per
579
+ RFC. You can create a new IPv6 object using uppercase letters, but
580
+ they will be converted.
581
+
582
+ ==== Compression
583
+
584
+ Since IPv6 addresses are very long to write, there are some
585
+ simplifications and compressions that you can use to shorten them.
586
+
587
+ * Leading zeroes: all the leading zeroes within a group can be
588
+ omitted: "0008" would become "8"
589
+
590
+ * A string of consecutive zeroes can be replaced by the string
591
+ "::". This can be only applied once.
592
+
593
+ Using compression, the IPv6 address written above can be shorten into
594
+ the following, equivalent, address
595
+
596
+ 2001:db8::8:800:200c:417a
597
+
598
+ This short version is often used in human representation.
599
+
600
+ ==== Network Mask
601
+
602
+ As we used to do with IPv4 addresses, an IPv6 address can be written
603
+ using the prefix notation to specify the subnet mask:
604
+
605
+ 2001:db8::8:800:200c:417a/64
606
+
607
+ The /64 part means that the first 64 bits of the address are
608
+ representing the network portion, and the last 64 bits are the host
609
+ portion.
610
+
611
+ === Using IPAddress with IPv6 addresses
612
+
613
+ All the IPv6 representations we've just seen are perfectly fine when
614
+ you want to create a new IPv6 address:
615
+
616
+ ip6 = IPAddress "2001:0db8:0000:0000:0008:0800:200C:417A"
617
+
618
+ ip6 = IPAddress "2001:db8:0:0:8:800:200C:417A"
619
+
620
+ ip6 = IPAddress "2001:db8:8:800:200C:417A"
621
+
622
+ All three are giving out the same IPv6 object. The default subnet mask
623
+ for an IPv6 is 128, as IPv6 addresses don't have classes like IPv4
624
+ addresses. If you want a different mask, you can go ahead and explicit
625
+ it:
626
+
627
+ ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
628
+
629
+ Access the address portion and the prefix by using the respective
630
+ methods:
631
+
632
+ ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
633
+
634
+ ip6.address
635
+ #=> "2001:0db8:0000:0000:0008:0800:200c:417a"
636
+
637
+ ip6.prefix
638
+ #=> 64
639
+
640
+ A compressed version of the IPv6 address can be obtained with the
641
+ IPv6#compressed method:
642
+
643
+ ip6 = IPAddress "2001:0db8:0000:0000:0008:200c:417a:00ab/64"
644
+
645
+ ip6.compressed
646
+ #=> "2001:db8::8:800:200c:417a"
647
+
648
+ === Handling the IPv6 address
649
+
650
+ Accessing the groups that form an IPv6 address is very easy with the
651
+ IPv6#groups method:
652
+
653
+ ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
654
+
655
+ ip6.groups
656
+ #=> [8193, 3512, 0, 0, 8, 2048, 8204, 16762]
657
+
658
+ As with IPv4 addresses, each individual group can be accessed using
659
+ the IPv6#[] shortcut method:
660
+
661
+ ip6[0]
662
+ #=> 8193
663
+ ip6[1]
664
+ #=> 3512
665
+ ip6[2]
666
+ #=> 0
667
+ ip6[3]
668
+ #=> 0
669
+
670
+ Note that each 16 bits group is expressed in its decimal form. You can
671
+ also obtain the groups into hexadecimal format using the IPv6#hexs
672
+ method:
673
+
674
+ ip6.hexs
675
+ #=> => ["2001", "0db8", "0000", "0000", "0008", "0800", "200c", "417a"]
676
+
677
+ A few other methods are available to transform an IPv6 address into
678
+ decimal representation, with IPv6.to_i
679
+
680
+ ip6.to_i
681
+ #=> 42540766411282592856906245548098208122
682
+
683
+ or to hexadecimal representation
684
+
685
+ ip6.to_hex
686
+ #=> "20010db80000000000080800200c417a"
687
+
688
+ To print out an IPv6 address in human readable form, use the IPv6#to_s, IPv6#to_string
689
+ and IPv6#to_string_uncompressed methods
690
+
691
+ ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
692
+
693
+ ip6.to_string
694
+ #=> "2001:db8::8:800:200c:417a/96"
695
+
696
+ ip6.to_string_uncompressed
697
+ #=> "2001:0db8:0000:0000:0008:0800:200c:417a/96"
698
+
699
+ As you can see, IPv6.to_string prints out the compressed form, while
700
+ IPv6.to_string_uncompressed uses the expanded version.
701
+
702
+ ==== Compressing and uncompressing
703
+
704
+ If you have a string representing an IPv6 address, you can easily
705
+ compress it and uncompress it using the two class methods IPv6::expand
706
+ and IPv6::compress.
707
+
708
+ For example, let's say you have the following uncompressed IPv6
709
+ address:
710
+
711
+ ip6str = "2001:0DB8:0000:CD30:0000:0000:0000:0000"
712
+
713
+ Here is the compressed version:
714
+
715
+ IPAddress::IPv6.compress ip6str
716
+ #=> "2001:db8:0:cd30::"
717
+
718
+ The other way works as well:
719
+
720
+ ip6str = "2001:db8:0:cd30::"
721
+
722
+ IPAddress::IPv6.expand ip6str
723
+ #=> "2001:0DB8:0000:CD30:0000:0000:0000:0000"
724
+
725
+ These methods can be used when you don't want to create a new object
726
+ just for expanding or compressing an address (although a new object is
727
+ actually created internally).
728
+
729
+ === New IPv6 address from other formats
730
+
731
+ You can create a new IPv6 address from different formats than just a
732
+ string representing the colon-hex groups.
733
+
734
+ For instance, if you have a data stream, you can use IPv6::parse_data,
735
+ like in the following example:
736
+
737
+ data = " \001\r\270\000\000\000\000\000\b\b\000 \fAz"
738
+
739
+ ip6 = IPAddress::IPv6::parse_data data
740
+ ip6.prefix = 64
741
+
742
+ ip6.to_string
743
+ #=> "2001:db8::8:800:200c:417a/64"
744
+
745
+ A new IPv6 address can also be created from an unsigned 128 bits
746
+ integer:
747
+
748
+ u128 = 42540766411282592856906245548098208122
749
+
750
+ ip6 = IPAddress::IPv6::parse_u128 u128
751
+ ip6.prefix = 64
752
+
753
+ ip6.to_string
754
+ #=>"2001:db8::8:800:200c:417a/64"
755
+
756
+ Finally, a new IPv6 address can be created from an hex string:
757
+
758
+ hex = "20010db80000000000080800200c417a"
759
+
760
+ ip6 = IPAddress::IPv6::parse_hex hex
761
+ ip6.prefix = 64
762
+
763
+ ip6.to_string
764
+ #=> "2001:db8::8:800:200c:417a/64"
765
+
766
+ === Special IPv6 addresses
767
+
768
+ Some IPv6 have a special meaning and are expressed in a special form,
769
+ quite different than an usual IPv6 address. IPAddress has built-in
770
+ support for unspecified, loopback and mapped IPv6 addresses.
771
+
772
+ ==== Unspecified address
773
+
774
+ The address with all zero bits is called the +unspecified+ address
775
+ (corresponding to 0.0.0.0 in IPv4). It should be something like this:
776
+
777
+ 0000:0000:0000:0000:0000:0000:0000:0000
778
+
779
+ but, with the use of compression, it is usually written as just two
780
+ colons:
781
+
782
+ ::
783
+
784
+ or, specifying the netmask:
785
+
786
+ ::/128
787
+
788
+ With IPAddress, create a new unspecified IPv6 address using its own
789
+ subclass:
790
+
791
+ ip = IPAddress::IPv6::Unspecified.new
792
+
793
+ ip.to_string
794
+ #=> "::/128"
795
+
796
+ You can easily check if an IPv6 object is an unspecified address by
797
+ using the IPv6#unspecified? method
798
+
799
+ ip.unspecified?
800
+ #=> true
801
+
802
+ An unspecified IPv6 address can also be created with the wrapper
803
+ method, like we've seen before
804
+
805
+ ip = IPAddress "::"
806
+
807
+ ip.unspecified?
808
+ #=> true
809
+
810
+ This address must never be assigned to an interface and is to be used
811
+ only in software before the application has learned its host's source
812
+ address appropriate for a pending connection. Routers must not forward
813
+ packets with the unspecified address.
814
+
815
+ ==== Loopback address
816
+
817
+ The loopback address is a unicast localhost address. If an
818
+ application in a host sends packets to this address, the IPv6 stack
819
+ will loop these packets back on the same virtual interface.
820
+
821
+ Loopback addresses are expressed in the following form:
822
+
823
+ ::1
824
+
825
+ or, with their appropriate prefix,
826
+
827
+ ::1/128
828
+
829
+ As for the unspecified addresses, IPv6 loopbacks can be created with
830
+ IPAddress calling their own class:
831
+
832
+ ip = IPAddress::IPv6::Loopback.new
833
+
834
+ ip.to_string
835
+ #=> "::1/128"
836
+
837
+ or by using the wrapper:
838
+
839
+ ip = IPAddress "::1"
840
+
841
+ ip.to_string
842
+ #=> "::1/128"
843
+
844
+ Checking if an address is loopback is easy with the IPv6#loopback?
845
+ method:
846
+
847
+ ip.loopback?
848
+ #=> true
849
+
850
+ The IPv6 loopback address corresponds to 127.0.0.1 in IPv4.
851
+
852
+ ==== Mapped address
853
+
854
+ It is usually identified as a IPv4 mapped IPv6 address, a particular
855
+ IPv6 address which aids the transition from IPv4 to IPv6. The
856
+ structure of the address is
857
+
858
+ ::ffff:w.y.x.z
859
+
860
+ where w.x.y.z is a normal IPv4 address. For example, the following is
861
+ a mapped IPv6 address:
862
+
863
+ ::ffff:192.168.100.1
864
+
865
+ IPAddress is very powerful in handling mapped IPv6 addresses, as the
866
+ IPv4 portion is stored internally as a normal IPv4 object. Let's have
867
+ a look at some examples. To create a new mapped address, just use the
868
+ class builder itself
869
+
870
+ ip6 = IPAddress::IPv6::Mapped.new "::ffff:172.16.10.1/128"
871
+
872
+ or just use the wrapper method
873
+
874
+ ip6 = IPAddress "::ffff:172.16.10.1/128"
875
+
876
+ Let's check it's really a mapped address:
877
+
878
+ ip6.mapped?
879
+ #=> true
880
+
881
+ ip6.to_string
882
+ #=> "::ffff:172.16.10.1/128"
883
+
884
+ Now with the +ipv4+ attribute, we can easily access the IPv4 portion
885
+ of the mapped IPv6 address:
886
+
887
+ ip6.ipv4.address
888
+ #=> "172.16.10.1"
889
+
890
+ Internally, the IPv4 address is stored as two 16 bits
891
+ groups. Therefore all the usual methods for an IPv6 address are
892
+ working perfectly fine:
893
+
894
+ ip6.to_hex
895
+ #=> "00000000000000000000ffffac100a01"
896
+
897
+ ip6.address
898
+ #=> "0000:0000:0000:0000:0000:ffff:ac10:0a01"
899
+
900
+ A mapped IPv6 can also be created just by specify the address in the
901
+ following format:
902
+
903
+ ip6 = IPAddress "::172.16.10.1"
904
+
905
+ That is, two colons and the IPv4 address. However, as by RFC, the ffff
906
+ group will be automatically added at the beginning
907
+
908
+ ip6.to_string
909
+ => "::ffff:172.16.10.1/128"
910
+
911
+ making it a mapped IPv6 compatible address.
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
+
937
+ == Community
938
+
939
+ Want to join the community?
940
+
941
+ * {IPAddress google group}[http://groups.google.com/group/ruby-ipaddress]
942
+
943
+ We've created a group to discuss about
944
+ IPAddress future development, features and provide some kind of support.
945
+ Feel free to join us and tell us what you think!
946
+
947
+ == Thanks to
948
+
949
+ Thanks to Luca Russo (vargolo) and Simone Carletti
950
+ (weppos) for all the support and technical review. Thanks to Marco Beri,
951
+ Bryan T. Richardson, Nicolas Fevrier, jdpace, Daniele Alessandri, jrdioko,
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.
955
+
956
+ == Copyright
957
+
958
+ Copyright (c) 2009-2011 Marco Ceresa. See LICENSE for details.
959
+
960
+
961
+