git: 1e7a9cbf5afa - main - net/pear-Net_IPv6: Add patches for handling zones

From: Renato Botelho <garga_at_FreeBSD.org>
Date: Fri, 12 Aug 2022 11:24:34 UTC
The branch main has been updated by garga:

URL: https://cgit.FreeBSD.org/ports/commit/?id=1e7a9cbf5afa5e830a90b4285b5da0202d55f404

commit 1e7a9cbf5afa5e830a90b4285b5da0202d55f404
Author:     Reid Linnemann <rlinnemann@netgate.com>
AuthorDate: 2022-08-12 11:19:58 +0000
Commit:     Renato Botelho <garga@FreeBSD.org>
CommitDate: 2022-08-12 11:23:28 +0000

    net/pear-Net_IPv6: Add patches for handling zones
    
    Summary:
    The upstream Net/IPv6 package from PEAR has significant bugs revolving around
    handling of string presentation v6 addresses which have RFC 4007 zones. Patches
    are added in this commit to address them plus a handful of other errors until an
    updated version of the package becomes available with these changes included.
    
     * Add getZone() and removeZone() class methods
     * Alter SplitV64() to remove any zone before attempting to split an address
       into v6 and v4 parts. The zone has no meaning in this context
     * Alter compress to remove and restore a zone prior to restoring a prefix
     * Alter compress() to rejoin a compressed v6 part with a v4 part with a colon
       if the v6 part does not already end with one
     * Fix undefined variable '$address' in isCompressible()
     * Ensure no zone is present at the end of an address in _ip2Bin(). The zone is
       not a part of the binary address
     * Change string/int arithmetic to int/int arithmetic in _ip2Bin by mapping
       exploded v4 address octets to integer values
     * Fix unit tests to work in modern versions of php and phpunit
       * Align test case class name with source file name
       * Use phpunit namespaces
       * Make return type of AllTests::setUp() the expected 'void'
    
    In addition, eight unit tests are added for basic verification of zone handling.
    
    Sponsored by:           Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D36151
---
 net/pear-Net_IPv6/Makefile                       |   1 +
 net/pear-Net_IPv6/files/patch-Net_IPv6.php       | 181 ++++++++++++++++++++++-
 net/pear-Net_IPv6/files/patch-tests_AllTests.php | 140 ++++++++++++++++++
 3 files changed, 320 insertions(+), 2 deletions(-)

diff --git a/net/pear-Net_IPv6/Makefile b/net/pear-Net_IPv6/Makefile
index 06151f66e90c..8e48731d9b7d 100644
--- a/net/pear-Net_IPv6/Makefile
+++ b/net/pear-Net_IPv6/Makefile
@@ -1,5 +1,6 @@
 PORTNAME=	Net_IPv6
 DISTVERSION=	1.3.0.b4
+PORTREVISION=	1
 CATEGORIES=	net pear
 DISTNAME=	${PORTNAME}-1.3.0b4
 
diff --git a/net/pear-Net_IPv6/files/patch-Net_IPv6.php b/net/pear-Net_IPv6/files/patch-Net_IPv6.php
index 99517ee348f6..4f341704902c 100644
--- a/net/pear-Net_IPv6/files/patch-Net_IPv6.php
+++ b/net/pear-Net_IPv6/files/patch-Net_IPv6.php
@@ -1,6 +1,159 @@
---- Net/IPv6.php.orig	2018-07-09 11:55:41 UTC
+--- Net/IPv6.php.orig	2022-08-11 20:00:46 UTC
 +++ Net/IPv6.php
-@@ -853,10 +853,10 @@ class Net_IPv6
+@@ -224,6 +224,27 @@ class Net_IPv6
+     }
+ 
+     // }}}
++    // {{{ removeZone()
++
++    /**
++     * Removes a zone from a non-global presentation address if it exists
++     *
++     * @param String $ip a valid ipv6 link local address
++     *
++     * @return String the address without a zone
++     * @access public
++     * @static
++     * @author Reid Linnemann <rlinnemann@netgate.com>
++     */
++    public static function removeZone($ip)
++    {
++
++        $ip = explode('%', $ip)[0];
++
++        return $ip;
++
++    }
++    // }}}
+     // {{{ getNetmaskSpec()
+ 
+     /**
+@@ -324,6 +345,33 @@ class Net_IPv6
+     }
+ 
+     // }}}
++    // {{{ getZone()
++
++    /**
++     * Returns zone from a non-global presentation address if it exists
++     *
++     * @param String $ip a valid ipv6 link local address
++     *
++     * @return String a zone or empty string if none exists
++     * @access public
++     * @static
++     * @author Reid Linnemann <rlinnemann@netgate.com>
++     */
++    public static function getZone($ip)
++    {
++
++        $items = explode('%', $ip);
++
++        if (count($items) > 1) {
++
++            return array_pop($items);
++
++        }
++
++        return '';
++
++    }
++    // }}}
+     // {{{ isInNetmask()
+ 
+     /**
+@@ -549,6 +597,8 @@ class Net_IPv6
+ 
+         }
+ 
++        $zone = Net_IPv6::getZone($ip);
++        $ip = Net_IPv6::removeZone($ip);
+         $netmask = Net_IPv6::getNetmaskSpec($ip);
+         $uip     = Net_IPv6::removeNetmaskSpec($ip);
+ 
+@@ -639,6 +689,12 @@ class Net_IPv6
+             $uip = implode(':', $uipT);
+         }
+ 
++        if ('' != $zone) {
++
++            $uip = $uip.'%'.$zone;
++
++        }
++
+         if ('' != $netmask) {
+ 
+                 $uip = $uip.'/'.$netmask;
+@@ -696,6 +752,9 @@ class Net_IPv6
+ 
+         }
+ 
++        $zone = Net_IPv6::getZone($ip);
++        $ip = Net_IPv6::removeZone($ip);
++
+         $prefix = Net_IPv6::getPrefixLength($ip);
+ 
+         if (false === $prefix) {
+@@ -709,7 +768,7 @@ class Net_IPv6
+ 
+         }
+         
+-        $split = Net_IPv6::splitV64($ip);
++        $split = Net_IPv6::SplitV64($ip);
+         $ip = $split[0];
+ 
+         $netmask = Net_IPv6::getNetmaskSpec($ip);
+@@ -750,9 +809,20 @@ class Net_IPv6
+         }
+ 
+         if ('' != $split[1]) { // add ipv4 part is available
+-            $cip = $cip.$split[1];
++            if(str_ends_with($cip, ':')) {
++                $sep = '';
++            } else {
++                $sep = ':';
++            }
++            $cip = $cip.$sep.$split[1];
+         }
+-        
++
++        if ('' != $zone) {
++
++            $cip = $cip.'%'.$zone;
++
++        }
++
+         if ('' != $netmask) {
+ 
+             $cip = $cip.'/'.$netmask;
+@@ -807,7 +877,7 @@ class Net_IPv6
+     public static function isCompressible($ip)
+     {
+ 
+-        return (bool)($ip != Net_IPv6::compress($address));
++        return (bool)($ip != Net_IPv6::compress($ip));
+ 
+     }
+ 
+@@ -820,6 +890,9 @@ class Net_IPv6
+      * RFC 2373 allows you to note the last two parts of an IPv6 address as
+      * an IPv4 compatible address
+      *
++     * Note that any zone will necessarily be stripped from the IPv6 part that
++     * is returned
++     *
+      * Example:  0:0:0:0:0:0:13.1.68.3
+      *           0:0:0:0:0:FFFF:129.144.52.38
+      *
+@@ -837,6 +910,7 @@ class Net_IPv6
+      */
+     public static function SplitV64($ip, $uncompress = true)
+     {
++        $ip = Net_IPv6::removeZone($ip);
+         $ip = Net_IPv6::removeNetmaskSpec($ip);
+ 
+         if ($uncompress) {
+@@ -853,10 +927,10 @@ class Net_IPv6
                  return array("", $ip);
              }
  
@@ -13,3 +166,27 @@
                  $ipPart[0] .= ":";
              }
  
+@@ -885,7 +959,6 @@ class Net_IPv6
+      */
+     public static function checkIPv6($ip)
+     {
+-
+         $elements = Net_IPv6::separate($ip);
+ 
+         $ip = $elements[0];
+@@ -1057,13 +1130,13 @@ class Net_IPv6
+     protected static function _ip2Bin($ip)
+     {
+         $binstr = '';
+-
++        $ip = Net_IPv6::removeZone($ip);
+         $ip = Net_IPv6::removeNetmaskSpec($ip);
+ 
+         // Correctly convert IPv4 mapped addresses (::ffff:x.x.x.x)
+         list(, $ipv4) = Net_IPv6::SplitV64($ip, FALSE);
+         if (strlen($ipv4)) {
+-            $ipv4map = explode('.', $ipv4, 4);
++            $ipv4map = array_map("intval", explode('.', $ipv4, 4));
+             $ipv4replace = dechex($ipv4map[0] * 256 + $ipv4map[1]) . ':' . dechex($ipv4map[2] * 256 + $ipv4map[3]);
+             $ip = str_replace($ipv4, $ipv4replace, $ip);
+         }
diff --git a/net/pear-Net_IPv6/files/patch-tests_AllTests.php b/net/pear-Net_IPv6/files/patch-tests_AllTests.php
new file mode 100644
index 000000000000..cfdf881b41b5
--- /dev/null
+++ b/net/pear-Net_IPv6/files/patch-tests_AllTests.php
@@ -0,0 +1,140 @@
+--- tests/AllTests.php.orig	2022-08-11 19:31:42 UTC
++++ tests/AllTests.php
+@@ -19,6 +19,7 @@ require_once "Net/IPv6.php";
+ // $Id: AllTests.php 340792 2016-10-29 14:56:52Z alexmerz $
+ 
+ require_once "Net/IPv6.php";
++use PHPUnit\Framework\TestCase;
+ 
+ /**
+ * This testcases tests for several bugs and general topics
+@@ -28,7 +29,7 @@ require_once "Net/IPv6.php";
+ * @version $Id: AllTests.php 340792 2016-10-29 14:56:52Z alexmerz $
+ * @access  public
+ */
+-class NetIPv6Test extends PHPUnit_Framework_TestCase {
++class AllTests extends TestCase {
+ 
+     protected $ip;
+ 
+@@ -39,7 +40,7 @@ class NetIPv6Test extends PHPUnit_Framework_TestCase {
+         return $method;
+     }
+ 
+-    public function setUp() {
++    public function setUp(): void {
+         $this->ip = new Net_IPv6();
+     }
+ 
+@@ -742,6 +743,109 @@ class NetIPv6Test extends PHPUnit_Framework_TestCase {
+         $netmask = '::ffff/96';
+         $testip = '0:0:0:0:0:ffff:c000:22f';
+         $this->assertTrue(Net_IPv6::isInNetmask($testip, $netmask));
++    }
++
++    /**
++     * tests if checkIPv6 can handle addresses with zone
++     * @author Reid Linnemann <rlinnemann@netgate.com>
++     */
++    public function testCheckIPv6WithZone() {
++        $testip = 'fe80::de:ad:be:ef%zone.name';
++        $is = $this->ip->checkIPv6($testip);
++
++        $this->assertTrue($is);
++    }
++
++    /**
++     * tests if splitV64 can handle addresses with zone
++     * @author Reid Linnemann <rlinnemann@netgate.com>
++     */
++    public function testSplitV64WithZone() {
++        $testip = 'fe80::de:ad:be:ef%zone.name';
++        $zonelessip = 'fe80::de:ad:be:ef';
++        $items = $this->ip->SplitV64($testip, false);
++
++        $this->assertEquals(2, count($items));
++        $this->assertEmpty($items[1]);
++        $this->assertEquals($zonelessip, $items[0]);
++    }
++
++    /**
++     * tests zoned address compression
++     * @author Reid Linnemann
++     */
++    public function testCompressWithZone() {
++        $uncompressedip = 'fe80:0:0:0:de:ad:be:ef%zone.name';
++        $compressedip = 'fe80::de:ad:be:ef%zone.name';
++
++        $testip = $this->ip->compress($uncompressedip, false);
++
++        $this->assertEquals($compressedip, $testip);
++    }
++
++    /**
++     * tests zoned address compression with IPv4 part
++     * @author Reid Linnemann
++     */
++    public function testCompressWithIPv4AndZone() {
++        $uncompressedip = 'fe80:0:0:0:dead:beef:172.10.1.1%zone.name';
++        $compressedip = 'fe80::dead:beef:172.10.1.1%zone.name';
++
++        $testip = $this->ip->compress($uncompressedip, false);
++
++        $this->assertEquals($compressedip, $testip);
++    }
++
++    /**
++     * tests zoned address with prefix compression with IPv4 part
++     * @author Reid Linnemann
++     */
++    public function testCompressWithIPv4AndZoneAndPrefix() {
++        $uncompressedip = 'fe80:0:0:0:dead:beef:172.10.1.1%zone.name/64';
++        $compressedip = 'fe80::dead:beef:172.10.1.1%zone.name/64';
++
++        $testip = $this->ip->compress($uncompressedip, false);
++
++        $this->assertEquals($compressedip, $testip);
++    }
++
++    /**
++     * tests zoned address uncompression
++     * @author Reid Linnemann
++     */
++    public function testUncompressWithZone() {
++        $uncompressedip = 'fe80:0:0:0:de:ad:be:ef%zone.name';
++        $compressedip = 'fe80::de:ad:be:ef%zone.name';
++
++        $testip = $this->ip->uncompress($compressedip, false);
++
++        $this->assertEquals($uncompressedip, $testip);
++    }
++
++    /**
++     * tests zoned address uncompression with IPv4 part
++     * @author Reid Linnemann
++     */
++    public function testUncompressWithIPv4AndZone() {
++        $uncompressedip = 'fe80:0:0:0:dead:beef:172.10.1.1%zone.name';
++        $compressedip = 'fe80::dead:beef:172.10.1.1%zone.name';
++
++        $testip = $this->ip->uncompress($compressedip, false);
++
++        $this->assertEquals($uncompressedip, $testip);
++    }
++
++    /**
++     * tests zoned address with prefix uncompression with IPv4 part
++     * @author Reid Linnemann
++     */
++    public function testUncompressWithIPv4AndZoneAndPrefix() {
++        $uncompressedip = 'fe80:0:0:0:dead:beef:172.10.1.1%zone.name/64';
++        $compressedip = 'fe80::dead:beef:172.10.1.1%zone.name/64';
++
++        $testip = $this->ip->uncompress($compressedip, false);
++
++        $this->assertEquals($uncompressedip, $testip);
+     }
+ 
+-}
+\ No newline at end of file
++}