Project

General

Profile

Download (21.7 KB) Statistics
| Branch: | Tag: | Revision:
1 ce996bd3 Simon Cornelius P. Umacob
<?php
2
3 523855b0 Scott Ullrich
/*
4 b6aed0e1 Scott Ullrich
	pfSense_MODULE:	utils
5 523855b0 Scott Ullrich
*/
6
7 ce996bd3 Simon Cornelius P. Umacob
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
8
9
/**
10
 * This file contains the implementation of the Net_IPv6 class
11
 *
12
 * PHP versions 4 and 5
13
 *
14
 * LICENSE: This source file is subject to the New BSD license, that is
15
 * available through the world-wide-web at 
16
 * http://www.opensource.org/licenses/bsd-license.php
17
 * If you did not receive a copy of the new BSDlicense and are unable
18
 * to obtain it through the world-wide-web, please send a note to
19
 * license@php.net so we can mail you a copy immediately
20
 *
21
 * @category  Net
22
 * @package   Net_IPv6
23
 * @author    Alexander Merz <alexander.merz@web.de>
24
 * @copyright 2003-2005 The PHP Group
25
 * @license   http://www.opensource.org/licenses/bsd-license.php
26
 * @version   CVS: $Id: IPv6.inc,v 1.2 2008/11/26 03:54:43 sumacob Exp $
27
 * @link      http://pear.php.net/package/Net_IPv6
28
 */
29
30
// {{{ constants
31
32
/**
33
 * Error message if netmask bits was not found
34
 * @see isInNetmask
35
 */
36
define("NET_IPV6_NO_NETMASK_MSG", "Netmask length not found");
37
38
/**
39
 * Error code if netmask bits was not found
40
 * @see isInNetmask
41
 */
42
define("NET_IPV6_NO_NETMASK", 10);
43
44
/**
45
 * Address Type: Unassigned (RFC 1884, Section 2.3)
46
 * @see getAddressType()
47
 */
48
define("NET_IPV6_UNASSIGNED", 1);
49
50
/**
51
 * Address Type: Reserved (RFC 1884, Section 2.3)
52
 * @see getAddressType()
53
 */
54
define("NET_IPV6_RESERVED", 11);
55
56
/**
57
 * Address Type: Reserved for NSAP Allocation (RFC 1884, Section 2.3)
58
 * @see getAddressType()
59
 */
60
define("NET_IPV6_RESERVED_NSAP", 12);
61
62
/**
63
 * Address Type: Reserved for IPX Allocation (RFC 1884, Section 2.3)
64
 * @see getAddressType()
65
 */
66
define("NET_IPV6_RESERVED_IPX", 13);
67
68
/**
69
 * Address Type: Reserved for Geographic-Based Unicast Addresses 
70
 * (RFC 1884, Section 2.3)
71
 * @see getAddressType()
72
 */
73
define("NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC", 14);
74
75
/**
76
 * Address Type: Provider-Based Unicast Address (RFC 1884, Section 2.3)
77
 * @see getAddressType()
78
 */
79
define("NET_IPV6_UNICAST_PROVIDER", 22);
80
81
/**
82
 * Address Type: Multicast Addresses (RFC 1884, Section 2.3)
83
 * @see getAddressType()
84
 */
85
define("NET_IPV6_MULTICAST", 31);
86
87
/**
88
 * Address Type: Link Local Use Addresses (RFC 1884, Section 2.3)
89
 * @see getAddressType()
90
 */
91
define("NET_IPV6_LOCAL_LINK", 42);
92
93
/**
94
 * Address Type: Link Local Use Addresses (RFC 1884, Section 2.3)
95
 * @see getAddressType()
96
 */
97
define("NET_IPV6_LOCAL_SITE", 43);
98
99
/**
100
 * Address Type: address can not assigned to a specific type
101
 * @see getAddressType()
102
 */
103
define("NET_IPV6_UNKNOWN_TYPE", 1001);
104
105
// }}}
106
// {{{ Net_IPv6
107
108
/**
109
 * Class to validate and to work with IPv6 addresses.
110
 *
111
 * @category  Net
112
 * @package   Net_IPv6
113
 * @copyright 2003-2005 The PHP Group
114
 * @license   http://www.opensource.org/licenses/bsd-license.php
115
 * @version   $Release$
116
 * @link      http://pear.php.net/package/Net_IPv6
117
 * @author    Alexander Merz <alexander.merz@web.de>
118
 * @author    <elfrink at introweb dot nl>
119
 * @author    Josh Peck <jmp at joshpeck dot org>
120
 */
121
class Net_IPv6 {
122
123
    // {{{ removeNetmaskBits()
124
125
    /**
126
     * Removes a possible existing netmask specification at an IP addresse.
127
     *
128
     * @param  String $ip the (compressed) IP as Hex representation
129
     *
130
     * @return String the IP without netmask length
131
     * @since  1.1.0
132
     * @access public
133
     * @static
134
     */
135
    function removeNetmaskSpec($ip) 
136
    {
137
        $addr = $ip;
138
139
        if (false !== strpos($ip, '/')) {
140
141
            $elements = explode('/', $ip);
142
143
            if (2 == count($elements)) {
144
145
                $addr = $elements[0];
146
147
            }
148
149
        }
150
151
        return $addr;
152
    }
153
154
    /**
155
     * Returns a possible existing netmask specification at an IP addresse.
156
     *
157
     * @param  String $ip the (compressed) IP as Hex representation
158
     *
159
     * @return String the netmask spec
160
     * @since  1.1.0
161
     * @access public
162
     * @static
163
     */
164
    function getNetmaskSpec($ip) 
165
    {
166
        $spec = '';
167
168
        if (false !== strpos($ip, '/')) {
169
170
            $elements = explode('/', $ip);
171
172
            if (2 == count($elements)) {
173
174
                $spec = $elements[1];
175
176
            }
177
178
        }
179
180
        return $spec;
181
    }
182
183
    // }}}
184
    // {{{ getNetmask()
185
186
    /**
187
     * Calculates the network prefix based on the netmask bits.
188
     *
189
     * @param  String $ip the (compressed) IP in Hex format
190
     * @param  int $bits if the number of netmask bits is not part of the IP
191
     *                  you must provide the number of bits
192
     *
193
     * @return String the network prefix
194
     * @since  1.1.0
195
     * @access public
196
     * @static
197
     */
198
    function getNetmask($ip, $bits = null)
199
    {
200
        if (null==$bits) {
201
202
            $elements = explode('/', $ip);
203
204
            if (2 == count($elements)) {
205
206
                $addr = $elements[0];
207
                $bits = $elements[1];
208
209
            } else {
210
211
                include_once 'PEAR.inc';
212
213
                return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG,
214
                                        NET_IPV6_NO_NETMASK);
215
            }
216
217
        } else {
218
219
            $addr = $ip;
220
221
        }
222
223
        $addr       = Net_IPv6::uncompress($addr);
224
        $binNetmask = str_repeat('1', $bits).str_repeat('0', 128 - $bits);
225
226
        return Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($addr) & $binNetmask);
227
    }
228
229
    // }}}
230
    // {{{ isInNetmask()
231
232
    /**
233
     * Checks if an (compressed) IP is in a specific address space.
234
     *
235
     * IF the IP does not contains the number of netmask bits (F8000::FFFF/16)
236
     * then you have to use the $bits parameter.
237
     *
238
     * @param  String $ip the IP to check (eg. F800::FFFF)
239
     * @param  String $netmask the netmask (eg F800::)
240
     * @param  int $bits the number of netmask bits to compare, 
241
     *                   if not given in $ip
242
     *
243
     * @return boolean true if $ip is in the netmask
244
     * @since  1.1.0
245
     * @access public
246
     * @static
247
     */
248
    function isInNetmask($ip, $netmask, $bits=null) 
249
    {
250
        // try to get the bit count
251
252
        if (null == $bits) {
253
254
            $elements = explode('/', $ip);
255
256
            if (2 == count($elements)) {
257
258
                $ip   = $elements[0];
259
                $bits = $elements[1];
260
261
            } else if (null == $bits) {
262
263
                $elements = explode('/', $netmask);
264
265
                if (2 == count($elements)) {
266
267
                     $netmask = $elements[0];
268
                     $bits   = $elements[1];
269
270
                }
271
272
                if (null == $bits) {
273
274
                    include_once 'PEAR.inc';
275
                    return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG,
276
                                            NET_IPV6_NO_NETMASK);
277
278
                }
279
280
            }
281
282
        }
283
284
        $binIp      = Net_IPv6::_ip2Bin(Net_IPv6::removeNetmaskSpec($ip));
285
        $binNetmask = Net_IPv6::_ip2Bin(Net_IPv6::removeNetmaskSpec($netmask));
286
287
        if (null != $bits 
288
            && "" != $bits 
289
            && 0 == strncmp( $binNetmask, $binIp, $bits)) {
290
291
            return true;
292
293
        }
294
295
        return false;
296
    }
297
298
    // }}}
299
    // {{{ getAddressType()
300
301
    /**
302
     * Returns the type of an IPv6 address.
303
     *
304
     * RFC 1883, Section 2.3 describes several types of addresses in
305
     * the IPv6 addresse space.
306
     * Several addresse types are markers for reserved spaces and as 
307
     * consequence a subject to change.
308
     *
309
     * @param  String $ip the IP address in Hex format, 
310
     *                    compressed IPs are allowed
311
     *
312
     * @return int one of the addresse type constants
313
     * @access public
314
     * @since  1.1.0
315
     * @static
316
     *
317
     * @see    NET_IPV6_UNASSIGNED
318
     * @see    NET_IPV6_RESERVED
319
     * @see    NET_IPV6_RESERVED_NSAP
320
     * @see    NET_IPV6_RESERVED_IPX
321
     * @see    NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC
322
     * @see    NET_IPV6_UNICAST_PROVIDER
323
     * @see    NET_IPV6_MULTICAST
324
     * @see    NET_IPV6_LOCAL_LINK
325
     * @see    NET_IPV6_LOCAL_SITE
326
     * @see    NET_IPV6_UNKNOWN_TYPE
327
     */
328
    function getAddressType($ip) 
329
    {
330
        $ip    = Net_IPv6::removeNetmaskSpec($ip);
331
        $binip = Net_IPv6::_ip2Bin($ip);
332
333
        if (0 == strncmp('1111111010', $binip, 10)) {
334
335
            return NET_IPV6_LOCAL_LINK;
336
337
        } else if (0 == strncmp('1111111011', $binip, 10)) {
338
339
            return NET_IPV6_LOCAL_SITE;
340
341
        } else if (0 == strncmp('111111100', $binip, 9)) {
342
343
            return NET_IPV6_UNASSIGNED;
344
345
        } else if (0 == strncmp('11111111', $binip, 8)) {
346
347
            return NET_IPV6_MULTICAST;
348
349
        }  else if (0 == strncmp('00000000', $binip, 8)) {
350
351
            return NET_IPV6_RESERVED;
352
353
        } else if (0 == strncmp('00000001', $binip, 8) 
354
                    || 0 == strncmp('1111110', $binip, 7)) {
355
356
            return NET_IPV6_UNASSIGNED;
357
358
        } else if (0 == strncmp('0000001', $binip, 7)) {
359
360
            return NET_IPV6_RESERVED_NSAP;
361
362
        } else if (0 == strncmp('0000010', $binip, 7)) {
363
364
            return NET_IPV6_RESERVED_IPX;;
365
366
        } else if (0 == strncmp('0000011', $binip, 7) ||
367
                    0 == strncmp('111110', $binip, 6) ||
368
                    0 == strncmp('11110', $binip, 5) ||
369
                    0 == strncmp('00001', $binip, 5) ||
370
                    0 == strncmp('1110', $binip, 4) ||
371
                    0 == strncmp('0001', $binip, 4) ||
372
                    0 == strncmp('001', $binip, 3) ||
373
                    0 == strncmp('011', $binip, 3) ||
374
                    0 == strncmp('101', $binip, 3) ||
375
                    0 == strncmp('110', $binip, 3)) {
376
377
            return NET_IPV6_UNASSIGNED;
378
379
        } else if (0 == strncmp('010', $binip, 3)) {
380
381
            return NET_IPV6_UNICAST_PROVIDER;
382
383
        }  else if (0 == strncmp('100', $binip, 3)) {
384
385
            return NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC;
386
387
        }
388
389
        return NET_IPV6_UNKNOWN_TYPE;
390
    }
391
392
    // }}}
393
    // {{{ Uncompress()
394
395
    /**
396
     * Uncompresses an IPv6 adress
397
     *
398
     * RFC 2373 allows you to compress zeros in an adress to '::'. This
399
     * function expects an valid IPv6 adress and expands the '::' to
400
     * the required zeros.
401
     *
402
     * Example:  FF01::101  ->  FF01:0:0:0:0:0:0:101
403
     *           ::1        ->  0:0:0:0:0:0:0:1
404
     *
405
     * @access public
406
     * @see Compress()
407
     * @static
408
     * @param string $ip    a valid IPv6-adress (hex format)
409
     * @return string   the uncompressed IPv6-adress (hex format)
410
     */
411
    function uncompress($ip) 
412
    {
413
414
        $prefix = Net_IPv6::getPrefixLength($ip);
415
416
        if (false === $prefix) {
417
418
            $prefix = '';
419
420
        } else {
421
422
            $ip     = Net_IPv6::removePrefixLength($ip);
423
            $prefix = '/'.$prefix;
424
425
        }
426
427
        $netmask = Net_IPv6::getNetmaskSpec($ip);
428
        $uip     = Net_IPv6::removeNetmaskSpec($ip);
429
430
        $c1 = -1;
431
        $c2 = -1;
432
433
        if (false !== strpos($uip, '::') ) {
434
435
            list($ip1, $ip2) = explode('::', $uip);
436
437
            if("" == $ip1) {
438
439
                $c1 = -1;
440
441
            } else {
442
443
                $pos = 0;
444
445
                if (0 < ($pos = substr_count($ip1, ':'))) {
446
447
                    $c1 = $pos;
448
449
                } else {
450
451
                    $c1 = 0;
452
453
                }
454
            }
455
            if ("" == $ip2) {
456
457
                $c2 = -1;
458
459
            } else {
460
461
                $pos = 0;
462
463
                if (0 < ($pos = substr_count($ip2, ':'))) {
464
465
                    $c2 = $pos;
466
467
                } else {
468
469
                    $c2 = 0;
470
471
                }
472
473
            }
474
475
            if (strstr($ip2, '.')) {
476
477
                $c2++;
478
479
            }
480
            if (-1 == $c1 && -1 == $c2) { // ::
481
482
                $uip = "0:0:0:0:0:0:0:0";
483
484
            } else if (-1 == $c1) {              // ::xxx
485
486
                $fill = str_repeat('0:', 7-$c2);
487
                $uip  = str_replace('::', $fill, $uip);
488
489
            } else if (-1 == $c2) {              // xxx::
490
491
                $fill = str_repeat(':0', 7-$c1);
492
                $uip  = str_replace('::', $fill, $uip);
493
494
            } else {                          // xxx::xxx
495
496
                $fill = str_repeat(':0:', 6-$c2-$c1);
497
                $uip  = str_replace('::', $fill, $uip);
498
                $uip  = str_replace('::', ':', $uip);
499
500
            }
501
        }
502
        if ('' != $netmask) {
503
504
                $uip = $uip.'/'.$netmask;
505
506
        }
507
508
        return $uip.$prefix;
509
    }
510
511
    // }}}
512
    // {{{ Compress()
513
514
    /**
515
     * Compresses an IPv6 adress
516
     *
517
     * RFC 2373 allows you to compress zeros in an adress to '::'. This
518
     * function expects an valid IPv6 adress and compresses successive zeros
519
     * to '::'
520
     *
521
     * Example:  FF01:0:0:0:0:0:0:101   -> FF01::101
522
     *           0:0:0:0:0:0:0:1        -> ::1
523
     *
524
     * @access public
525
     * @see Uncompress()
526
     * @static
527
     * @param string $ip    a valid IPv6-adress (hex format)
528
     * @return string   the compressed IPv6-adress (hex format)
529
     * @author elfrink at introweb dot nl
530
     */
531
    function compress($ip)  
532
    {
533
        $prefix = Net_IPv6::getPrefixLength($ip);
534
535
        if (false === $prefix) {
536
537
            $prefix = '';
538
539
        } else {
540
541
            $ip     = Net_IPv6::removePrefixLength($ip);
542
            $prefix = '/'.$prefix;
543
544
        }
545
546
        $netmask = Net_IPv6::getNetmaskSpec($ip);
547
        $ip      = Net_IPv6::removeNetmaskSpec($ip);
548
549
        if (!strstr($ip, '::')) {
550
551
            $ipp = explode(':',$ip);
552
553
            for ($i = 0; $i < count($ipp); $i++) {
554
555
                $ipp[$i] = dechex(hexdec($ipp[$i]));
556
557
            }
558
559
            $cip = ':' . join(':',$ipp) . ':';
560
561
            preg_match_all("/(:0)+/", $cip, $zeros);
562
563
            if (count($zeros[0]) > 0) {
564
565
                $match = '';
566
567
                foreach($zeros[0] as $zero) {
568
569
                    if (strlen($zero) > strlen($match)) {
570
571
                        $match = $zero;
572
573
                    }
574
                }
575
576
                $cip = preg_replace('/' . $match . '/', ':', $cip, 1);
577
578
            }
579
580
            $cip = preg_replace('/((^:)|(:$))/', '' ,$cip);
581
            $cip = preg_replace('/((^:)|(:$))/', '::' ,$cip);
582
583
         }
584
         if ('' != $netmask) {
585
586
                $cip = $cip.'/'.$netmask;
587
588
         }
589
590
         return $cip.$prefix;
591
    }
592
593
    // }}}
594
    // {{{ SplitV64()
595
596
    /**
597
     * Splits an IPv6 adress into the IPv6 and a possible IPv4 part
598
     *
599
     * RFC 2373 allows you to note the last two parts of an IPv6 adress as
600
     * an IPv4 compatible adress
601
     *
602
     * Example:  0:0:0:0:0:0:13.1.68.3
603
     *           0:0:0:0:0:FFFF:129.144.52.38
604
     *
605
     * @param  string $ip  a valid IPv6-adress (hex format)
606
     *
607
     * @return array  [0] contains the IPv6 part, 
608
     *                [1] the IPv4 part (hex format)
609
     * @access public
610
     * @static
611
     */
612
    function SplitV64($ip, $uncompress = true) 
613
    {
614
        $ip = Net_IPv6::removeNetmaskSpec($ip);
615
616
        if ($uncompress) {
617
618
            $ip = Net_IPv6::Uncompress($ip);
619
620
        }
621
622
        if (strstr($ip, '.')) {
623
624
            $pos      = strrpos($ip, ':');
625
            $ip{$pos} = '_';
626
            $ipPart   = explode('_', $ip);
627
628
            return $ipPart;
629
630
        } else {
631
632
            return array($ip, "");
633
634
        }
635
    }
636
637
    // }}}
638
    // {{{ checkIPv6()
639
640
    /**
641
     * Checks an IPv6 adress
642
     *
643
     * Checks if the given IP is IPv6-compatible
644
     *
645
     * @access public
646
     * @static
647
     * @param string $ip    a valid IPv6-adress
648
     * @return boolean  true if $ip is an IPv6 adress
649
     */
650
    function checkIPv6($ip) 
651
    {
652
        $ip = Net_IPv6::removePrefixLength($ip);
653
        $ip = Net_IPv6::removeNetmaskSpec($ip);
654
655
        $ipPart = Net_IPv6::SplitV64($ip);
656
        $count  = 0;
657
658
        if (!empty($ipPart[0]))
659
        {
660
            $ipv6 =explode(':', $ipPart[0]);
661
662
            for ($i = 0; $i < count($ipv6); $i++) {
663
664
                $dec = hexdec($ipv6[$i]);
665
                $hex = strtoupper(preg_replace("/^[0]{1,3}(.*[0-9a-fA-F])$/",
666
                                                "\\1", 
667
                                                $ipv6[$i]));
668
669
                if ($ipv6[$i] >= 0 && $dec <= 65535
670
                    && $hex == strtoupper(dechex($dec))) {
671
672
                    $count++;
673
674
                }
675
676
            }
677
678
            if (8 == $count) {
679
680
                return true;
681
682
            } else if (6 == $count and !empty($ipPart[1])) {
683
684
                $ipv4  = explode('.',$ipPart[1]);
685
                $count = 0;
686
687
                for ($i = 0; $i < count($ipv4); $i++) {
688
689
                    if ($ipv4[$i] >= 0 && (integer)$ipv4[$i] <= 255
690
                        && preg_match("/^\d{1,3}$/", $ipv4[$i])) {
691
692
                        $count++;
693
694
                    }
695
696
                }
697
698
                if (4 == $count) {
699
700
                    return true;
701
702
                }
703
704
            } else {
705
706
                return false;
707
708
            }
709
710
        } else {
711
712
            return false;
713
714
        }
715
716
    }
717
718
    // }}}
719
    // {{{ getPrefixLength()
720
721
    /**
722
     * Tests for a prefix length specification in the address
723
     * and returns the prefix length, if exists
724
     *
725
     * @param  String $ip a valid ipv6 address
726
     *
727
     * @return Mixed the prefix as String or false, if no prefix was found
728
     * @access public
729
     * @static
730
     */
731
    function getPrefixLength($ip) 
732
    {
733
        if (preg_match("/^([0-9a-fA-F:]{2,39})\/(\d{1,3})*$/", 
734
                        $ip, $matches)) {
735
736
            return $matches[2];
737
738
        } else {
739
740
            return false;
741
742
        }
743
744
    }
745
746
    // }}}
747
    // {{{ removePrefixLength()
748
749
    /**
750
     * Tests for a prefix length specification in the address
751
     * and removes the prefix length, if exists
752
     *
753
     * @param  String $ip a valid ipv6 address
754
     *
755
     * @return String the address without a prefix length
756
     * @access public
757
     * @static
758
     */
759
    function removePrefixLength($ip) 
760
    {
761
        $pos = strrpos($ip, '/');
762
763
        if (false !== $pos) {
764
765
            return substr($ip, 0, $pos);
766
767
        }
768
769
        return $ip;
770
    }
771
772
    // }}}
773
774
    // {{{ _parseAddress()
775
776
    /**
777
     * Returns the lowest and highest IPv6 address
778
     * for a given IP and netmask specification
779
     * 
780
     * The netmask may be a part of the $ip or 
781
     * the number of netwask bits is provided via $bits
782
     *
783
     * The result is an indexed array. The key 'start'
784
     * contains the lowest possible IP adress. The key
785
     * 'end' the highest address.
786
     *
787
     * @param  String $ip the IPv6 address
788
     * @param  String $bits the optional count of netmask bits
789
     *
790
     * @return Array ['start', 'end'] the lowest and highest IPv6 address
791
     * @access public
792
     * @static
793
     * @author Nicholas Williams
794
     */
795
796
    function parseAddress($ipToParse, $bits = null)
797
    {
798
799
        $ip      = null;
800
        $bitmask = null;
801
802
    	if( null == $bits )
803
    	{
804
805
    		$elements = explode('/', $ipToParse);
806
807
    		if( 2 == count($elements) ) {
808
809
    			$ip      = Net_IPv6::uncompress($elements[0]);
810
    			$bitmask = $elements[1];
811
812
    		} else {
813
814
    			include_once 'PEAR.inc';
815
816
    			return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG,
817
                                        NET_IPV6_NO_NETMASK);
818
    		}
819
    	}
820
    	else
821
    	{
822
823
    		$ip      = Net_IPv6::uncompress($ipToParse);
824
    		$bitmask = $bits;
825
826
    	}
827
828
    	$binNetmask = str_repeat('1', $bitmask).
829
                      str_repeat('0', 128 - $bitmask);
830
    	$maxNetmask = str_repeat('1', 128);
831
    	$netmask    = Net_IPv6::_bin2Ip($binNetmask);
832
833
    	$startAddress = Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($ip) 
834
                        & $binNetmask);
835
    	$endAddress   = Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($ip)
836
                        | ($binNetmask ^ $maxNetmask));
837
838
    	return array('start' => $startAddress, 'end' => $endAddress);
839
    }
840
841
    // }}}
842
843
    // {{{ _ip2Bin()
844
845
    /**
846
     * Converts an IPv6 address from Hex into Binary representation.
847
     *
848
     * @param String $ip the IP to convert (a:b:c:d:e:f:g:h), 
849
     *                   compressed IPs are allowed
850
     *
851
     * @return String the binary representation
852
     * @access private
853
     @ @since 1.1.0
854
     */
855
    function _ip2Bin($ip) 
856
    {
857
        $binstr = '';
858
859
        $ip = Net_IPv6::removeNetmaskSpec($ip);
860
        $ip = Net_IPv6::Uncompress($ip);
861
862
        $parts = explode(':', $ip);
863
864
        foreach($parts as $v) {
865
866
            $str     = base_convert($v, 16, 2);
867
            $binstr .= str_pad($str, 16, '0', STR_PAD_LEFT);
868
869
        }
870
871
        return $binstr;
872
    }
873
874
    // }}}
875
    // {{{ _bin2Ip()
876
877
    /**
878
     * Converts an IPv6 address from Binary into Hex representation.
879
     *
880
     * @param String $ip the IP as binary
881
     *
882
     * @return String the uncompressed Hex representation
883
     * @access private
884
     @ @since 1.1.0
885
     */
886
    function _bin2Ip($bin)
887
    {
888
        $ip = "";
889
890
        if (strlen($bin) < 128) {
891
892
            $bin = str_pad($str, 128, '0', STR_PAD_LEFT);
893
894
        }
895
896
        $parts = str_split($bin, "16");
897
898
        foreach($parts as $v) {
899
900
            $str = base_convert($v, 2, 16);
901
            $ip .= $str.":";
902
903
        }
904
905
        $ip = substr($ip, 0,-1);
906
907
        return $ip;
908
    }
909
910
    // }}}
911
}
912
// }}}
913
914
/*
915
 * Local variables:
916
 * tab-width: 4
917
 * c-basic-offset: 4
918
 * c-hanging-comment-ender-p: nil
919
 * End:
920
 */
921
922 523855b0 Scott Ullrich
?>