From 4834c06ae25b70b8b6fc7e84987dafd0e71d6c4e Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Thu, 05 Jul 2007 11:35:50 +0000
Subject: [PATCH] Fix for unresolved issue 670 that can be fixed  using some code from from a previous fix for issue 471. Issue 670.

---
 opends/src/server/org/opends/server/types/AddressMask.java                             |  166 +++++++++++----------------
 opends/src/server/org/opends/server/messages/ProtocolMessages.java                     |    2 
 opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java |  188 ++++++++++++++++++++++--------
 3 files changed, 206 insertions(+), 150 deletions(-)

diff --git a/opends/src/server/org/opends/server/messages/ProtocolMessages.java b/opends/src/server/org/opends/server/messages/ProtocolMessages.java
index f96dac6..aa9a360 100644
--- a/opends/src/server/org/opends/server/messages/ProtocolMessages.java
+++ b/opends/src/server/org/opends/server/messages/ProtocolMessages.java
@@ -6531,7 +6531,7 @@
             "Cannot decode the provided address mask because an prefix mask"+
             "was specified with an wild card \"*\" match character");
     registerMessage(MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR,
-            "Cannot decode the provided address mask because the it has an" +
+            "Cannot decode the provided address mask because the it has an " +
             "invalid format");
 
 
diff --git a/opends/src/server/org/opends/server/types/AddressMask.java b/opends/src/server/org/opends/server/types/AddressMask.java
index 3775380..d33a46b 100644
--- a/opends/src/server/org/opends/server/types/AddressMask.java
+++ b/opends/src/server/org/opends/server/types/AddressMask.java
@@ -30,19 +30,14 @@
 import static org.opends.server.messages.ProtocolMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
 import java.util.BitSet;
-
-//This import statements causes problems in checkstyles so
-//it has been turned off until issue #??? is fixed.
-//import sun.net.util.IPAddressUtil;
-//import java.net.Inet6Address;
-
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 
 /**
  * This class defines an address mask, which can be used to perform
  * efficient comparisons against IP addresses to determine whether a
  * particular IP address is in a given range.
- * Currently IPV6 is not supported. Issue #670 will track IPV6
- * support.
  */
 
 public final class AddressMask
@@ -52,7 +47,7 @@
      * Types of rules we have.
      *
      * IPv4 - ipv4 rule
-     * IPv6 - ipv6 rule (begin with '['). Not supported see issue #670
+     * IPv6 - ipv6 rule (begin with '[' or contains an ':').
      * HOST - hostname match (foo.sun.com)
      * HOSTPATTERN - host pattern match (begin with '.')
      * ALLWILDCARD - *.*.*.* (first HOST is applied then ipv4)
@@ -61,7 +56,7 @@
 
      enum RuleType
     {
-        IPv4, IPv6, HOSTPATTERN, ALLWILDCARD, HOST;
+        IPv4, IPv6, HOSTPATTERN, ALLWILDCARD, HOST
     }
 
     // Type of rule determined
@@ -75,8 +70,8 @@
     private  int IPV4MAXPREFIX = 32;
 
     // IPv6 values for number of bytes and max CIDR prefix
-    //private  int IN6ADDRSZ = 16;
-    //private  int IPV6MAXPREFIX = 128;
+    private  int IN6ADDRSZ = 16;
+    private  int IPV6MAXPREFIX = 128;
 
     //Holds binary representations of rule and mask respectively.
     private  byte[] ruleMask, prefixMask;
@@ -104,14 +99,14 @@
         determineRuleType(rule);
         switch (ruleType)
         {
+        case IPv6:
+            processIPv6(rule);
+             break;
+
         case IPv4:
             processIpv4(rule);
             break;
 
-            /*            case IPv6:
-                processIPv6(rule);
-                break;
-             */
         case HOST:
             processHost(rule);
             break;
@@ -148,13 +143,10 @@
         {
             ruleType=RuleType.HOSTPATTERN;
         }
-        else if(ruleString.startsWith("["))
+        else if(ruleString.startsWith("[") ||
+                (ruleString.indexOf(':') != -1))
         {
-            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
-            String message = getMessage(msgID);
-            throw new ConfigException(msgID, message);
-            //IPV6 is not supported see issue #670
-            //ruleType=RuleType.IPv6;
+           ruleType=RuleType.IPv6;
         }
         else
         {
@@ -164,17 +156,14 @@
             // hostname (can't begin with digit) or ipv4 address.
             //Default to IPv4 ruletype.
             ruleType=RuleType.HOST;
-            for(int i=0;i<s.length;i++)
-            {
-                if(s[i].equals("*"))
-                {
+            for (String value : s) {
+                if (value.equals("*")) {
                     wildCount++;
                     continue;
                 }
                 //Looks like an ipv4 address
-                if(Character.isDigit(s[i].charAt(0)))
-                {
-                    ruleType=RuleType.IPv4;
+                if (Character.isDigit(value.charAt(0))) {
+                    ruleType = RuleType.IPv4;
                     break;
                 }
             }
@@ -196,10 +185,10 @@
     private void processIpv4(String rule)
     throws ConfigException {
         String[] s = rule.split("/", -1);
-        ruleMask=new byte[IN4ADDRSZ];
-        prefixMask=new byte[IN4ADDRSZ];
+        this.ruleMask=new byte[IN4ADDRSZ];
+        this.prefixMask=new byte[IN4ADDRSZ];
         prefixMask(processPrefix(s,IPV4MAXPREFIX));
-        processIpv4Subnet((s.length == 0) ? rule : s[0]);
+        processIPv4Subnet((s.length == 0) ? rule : s[0]);
     }
 
     /**
@@ -266,13 +255,13 @@
      */
     private void prefixMask(int prefix)
     {
-        int i=0;
+        int i;
         for( i=0;prefix > 8 ; i++)
         {
-            prefixMask[i] = (byte) 0xff;
+            this.prefixMask[i] = (byte) 0xff;
             prefix -= 8;
         }
-        prefixMask[i] = (byte) ((0xff) << (8 - prefix));
+        this.prefixMask[i] = (byte) ((0xff) << (8 - prefix));
     }
 
     /**
@@ -282,7 +271,7 @@
      * @throws ConfigException If the subnet string is not a valid
      *         IPv4 subnet string.
      */
-    private void  processIpv4Subnet(String subnet)
+    private void  processIPv4Subnet(String subnet)
     throws ConfigException {
         String[] s = subnet.split("\\.", -1);
         try {
@@ -397,12 +386,11 @@
      *         <CODE>false</CODE> if it does not.
      */
     public  static boolean maskListContains(byte[] remoteAddr,
-            String remoteName,
-            AddressMask[] masks)
+                                            String remoteName,
+                                            AddressMask[] masks)
     {
-        for(int i=0; i < masks.length; i++)
-        {
-            if(masks[i].match(remoteAddr, remoteName))
+        for (AddressMask mask : masks) {
+            if(mask.match(remoteAddr, remoteName))
                 return true;
         }
         return false;
@@ -431,6 +419,7 @@
         boolean ret=false;
 
         switch(ruleType) {
+        case IPv6:
         case IPv4:
             //this Address mask is an IPv4 rule
             ret=matchAddress(remoteAddr);
@@ -441,15 +430,6 @@
             ret=matchHostName(remoteName);
             break;
 
-            /*
-          case IPv6:
-              //IPv6 rule only valid of addr is an Inet6Address
-              if(addr instanceof Inet6Address) {
-                  Inet6Address addr6 = (Inet6Address) addr;
-                  ret=match(addr6.getAddress());
-              }
-              break;
-             */
         case HOSTPATTERN:
             //HOSTPATTERN rule
             ret=matchPattern(remoteName);
@@ -473,12 +453,8 @@
      */
     private boolean matchPattern(String remoteHostName) {
         int len=remoteHostName.length() - hostPattern.length();
-        if(len > 0)
-        {
-            return remoteHostName.regionMatches(true,len,
-                    hostPattern,0,hostPattern.length());
-        }
-        return false;
+        return len > 0 && remoteHostName.regionMatches(true, len,
+                hostPattern, 0, hostPattern.length());
     }
 
     /**
@@ -532,48 +508,44 @@
         return true;
     }
 
-    /* Turned off until IPV6 issue #670 is fixed.
-
-  private void processIPv6(String rule)
-  throws ConfigException {
-      String[] s = rule.split("/", -1);
-      //ipv6 rule must end with ']''
-      if(!s[0].endsWith("]"))
-      {
-          int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
-          String message = getMessage(msgID);
-          throw new ConfigException(msgID,message);
-      }
-      String subnet  = s[0].substring(1, s[0].length() -1);
-      byte[] tmpMask=IPAddressUtil.textToNumericFormatV6(subnet);
-      //don't have a vaild ipv6 address bail
-      if (tmpMask == null)
-      {
-          int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
-          String message = getMessage(msgID);
-          throw new ConfigException(msgID, message);remoteMask
-      }
-      //we were returned an ipv4-mapped address ::ffff:<ipv4 addr>
-      //make sure we don't have a prefix
-      if((tmpMask.length == IN4ADDRSZ)  &&
-              (s.length == 2)) {
-          int msgID = MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
-          String message = getMessage(msgID);
-          throw new ConfigException(msgID,  message);
-       //build a ipv4 structure using a 32-bit prefix
-      } else if (tmpMask.length == IN4ADDRSZ) {
-          setRuleType(Rtype.IPv4);
-          setRuleMask(tmpMask);
-          setPrefixMask(new byte[IN4ADDRSZ]);
-          prefixMask(32);
-      } else { //plain Ipv6 address
-          setRuleMask(tmpMask);
-          setPrefixMask(new byte[IN6ADDRSZ]);
-          prefixMask(processPrefix(s,IPV6MAXPREFIX));
-          setRuleType(Rtype.IPv6);
-      }
-  }
+    /**
+     * The rule string is an IPv6 rule. Build both the prefix
+     * mask array and rule mask from the string.
+     *
+     * @param rule The rule string containing the IPv6 rule.
+     * @throws ConfigException If the rule string is not a valid
+     *         IPv6 rule.
      */
+     private void processIPv6(String rule) throws ConfigException {
+        String[] s = rule.split("/", -1);
+        InetAddress addr;
+        try {
+            addr = InetAddress.getByName(s[0]);
+        } catch (UnknownHostException ex) {
+            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
+            String message = getMessage(msgID);
+            throw new ConfigException(msgID, message);
+        }
+        if(addr instanceof Inet6Address) {
+            this.ruleType=RuleType.IPv6;
+            Inet6Address addr6 = (Inet6Address) addr;
+            this.ruleMask=addr6.getAddress();
+            this.prefixMask=new byte[IN6ADDRSZ];
+            prefixMask(processPrefix(s,IPV6MAXPREFIX));
+        } else {
+           //The address might be an IPv4-compat address.
+           //Throw an error if the rule has a prefix.
+            if(s.length == 2) {
+                int msgID = MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
+                String message = getMessage(msgID);
+                throw new ConfigException(msgID,  message);
+            }
+            this.ruleMask=addr.getAddress();
+            this.ruleType=RuleType.IPv4;
+            this.prefixMask=new byte[IN4ADDRSZ];
+            prefixMask(processPrefix(s,IPV4MAXPREFIX));
+        }
+    }
 }
 
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java
index 40ae20f..4648147 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java
@@ -26,12 +26,14 @@
  */
 package org.opends.server.types;
 
-import org.opends.server.types.AddressMask;
 import org.opends.server.config.ConfigException;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import static org.testng.Assert.*;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
 public class TestAddressMask extends TypesTestCase {
 
 	/* These are all valid rules -- should all pass. */
@@ -70,7 +72,6 @@
          {"129.**.56.67"},
          {"foo bar.com"},
          {"12foo.example.com"},
-         {"[2001:fecd:ba23:cd1f:dcb1:1010:9234:4088]/124"},
          {"123.45."},
          {".central.sun day.com"},
          {"129.34.45.45/4/3/"}
@@ -106,8 +107,8 @@
              "Invalid mask <" + mask + "> did not throw an exception.");
  }
 
- @DataProvider(name = "matchRules")
- public Object[][] ruleMatchData() {
+  @DataProvider(name = "matchRules")
+  public Object[][] ruleMatchData() {
      return new Object[][] {
              {
                  //Rules
@@ -121,7 +122,7 @@
                          "128.153.147.32/21",//7
                          "128.153.146.32/26",//8
                          "90.89.78.67/26"}, //9
-                //Addresses         
+                //Addresses
                 new String[] {
                          "128.153.147.45", //rule 7
                          "128.153.146.60", //rule 8
@@ -130,7 +131,7 @@
                          "148.45.45.47",    //host
                          "148.45.45.48",    //host
                          "90.89.78.65"},   //rule 5
-              //Hostnames           
+              //Hostnames
               new String[]  {
                          "some.host.name", //addr
                          "some.host.name", //addr
@@ -159,9 +160,9 @@
                      "128.153.147.32/21",//7
                      "128.153.146.32/26",//8
                      "90.89.78.67/26"}, //9
-                     //Addresses         
+                     //Addresses
                      new String[] {
-                              "128.153.140.45", 
+                              "128.153.140.45",
                               "128.153.143.255",
                               "148.45.45.46",
                               "126.56.78.22",
@@ -169,7 +170,7 @@
                               "148.45.45.48",
                               "90.89.78.128",
                               "148.45.45.49"},
-                   //Hostnames           
+                   //Hostnames
                    new String[]  {
                               "some.host.name",
                               "some.host.name",
@@ -191,12 +192,12 @@
                  //Rules
                  new String[] {
                          "*.*.*",
-                         "*.*.*.*"}, 
-                //Addresses         
+                         "*.*.*.*"},
+                //Addresses
                 new String[] {
                         "129.34.45.12",
-                        "129.34.45.13"},  
-              //Hostnames           
+                        "129.34.45.13"},
+              //Hostnames
               new String[]  {
                          "some.host.name" ,
                          "some.host.name"}
@@ -206,7 +207,7 @@
 
  @Test(dataProvider = "matchRules")
  public void testMatch(String[] rules, String[] addrs, String[]hostNames) {
-     boolean ret=true;
+     boolean ret;
      ret=match(rules,addrs,hostNames);
      assertTrue(ret);
  }
@@ -214,7 +215,7 @@
  @Test(dataProvider = "matchWCRules")
  public void testWildCardMatch(String[] rules, String[] addrs,
          String[]hostNames) {
-     boolean ret=true;
+     boolean ret;
      ret=match(rules,addrs,hostNames);
      assertTrue(ret);
  }
@@ -222,7 +223,7 @@
  @Test(dataProvider = "noMatchRules")
  public void testNoMatch(String[] rules, String[] addrs,
          String[] hostNames) {
-     boolean ret=false;
+     boolean ret;
      ret=match(rules,addrs,hostNames);
      assertFalse(ret);
  }
@@ -234,47 +235,130 @@
          assertEquals(rule, m.toString());
      } catch (ConfigException ce) {
          throw new RuntimeException(
-                 "Invalid mask <" + rule + 
+                 "Invalid mask <" + rule +
                  "> all data should be valid for this test");
      }
  }
 
- private byte[] getAddress(String remote) {
-     byte[] addr=new byte[AddressMask.IN4ADDRSZ];
-     String[] s = remote.split("\\.", -1);
-     try {
-         for(int i=0;i<AddressMask.IN4ADDRSZ;i++) {
-             long val = Integer.parseInt(s[i]);
-             addr[i] = (byte) (val & 0xff);
-         }
-     }  catch (NumberFormatException nfex) {
-         return addr;
-     }
-     return addr;
+  private boolean match(String[] rules, String[] addrs,  String[]hostNames) {
+    boolean ret=true;
+    int i=0;
+
+    AddressMask[] m = new AddressMask[rules.length];
+    try {
+      for (i = 0; i < rules.length; i++) {
+        m[i] = AddressMask.decode(rules[i]);
+      }
+    } catch (ConfigException ce) {
+      throw new RuntimeException(
+              "Invalid mask <" + rules[i] +
+                      "> all data must be valid for this test");
+    }
+    for(int j = 0; j < addrs.length; j++) {
+      try  {
+        InetAddress addr = InetAddress.getByName(addrs[j]);
+        if(!AddressMask.maskListContains(addr.getAddress(), hostNames[j], m)) {
+          ret=false;
+          break;
+        }
+      } catch (UnknownHostException ex) {
+        ret=false;
+      }
+    }
+    return ret;
+  }
+
+  /*
+    IPV6 data and tests.
+  */
+
+  //Invalid IPv6 expressions.
+  @DataProvider(name = "invalid6Rules")
+  public Object[][] inValid6Data() {
+        return new Object[][] {
+                {"2001:feca:ba23:cd1f:dcb1:1010:9234:4088///124"},
+                {"2001:feca:ba23:cd1f:dcb1:1010:9234:4088?124"},
+                {"2001:fecz:ba23:cd1f:dcb1:1010:9234:4088/124"},
+                {"2001:fecd:ba23:cd1ff:dcb1:1010:9234:4088/46"},
+                {"0:0:0:0:0:ffff:101..45.75.219"},
+                {"0:0:0:0:0:0:101.45.75.700"},
+                {"1080::8:800:200C:417A/500"},
+                {"1080::8:800:*:417A/66"},
+                 {"2001:fecd:ba23:cd1ff:dcb1:1010:202.45.66.20"},
+        };
+  }
+
+  //Valid IPv6 expressions.
+  @DataProvider(name = "valid6Rules")
+  public Object[][] valid6Data() {
+      return new Object[][] {
+              {"2001:fecd:ba23:cd1f:dcb1:1010:9234:4088/124"},
+              {"2001:fecd:ba23:cd1f:dcb1:1010:9234:4088"},
+              {"[2001:fecd:ba23:cd1f:dcb1:1010:9234:4088]/45"},
+              {"::/128"},
+              {"::1/128"},
+              {"::"},
+              {"0:0:0:0:0:ffff:101.45.75.219"},
+              {"1080::8:800:200C:417A"},
+              {"0:0:0:0:0:0:101.45.75.219"},
+              {"::101.45.75.219"}
+      };
+  }
+
+
+  @DataProvider(name = "match6Rules")
+  public Object[][] ruleMatch6Data() {
+     return new Object[][] {
+             {
+                 //IPV6 Rules
+                 new String[] {
+                         "[12ab:0:0:cd30::]/60",
+                         "::ffff:72.56.78.9",
+                         "::",
+                         "42ab:0:0:dd30::"},
+                //IPv6 Addresses
+                new String[] {
+                         "12ab:0:0:cd3f:0000:0000:23DC:DC30",
+                         "72.56.78.9",
+                         "::",
+                         "42ab:0000:0000:dd30:0000:0000:0000:0000"},
+              //ignored Hostnames
+              new String[]  {
+                         "ignored.host.name",
+                         "ignored.host.name",
+                         "ignored.host.name",
+                         "ignored.host.name"
+                         }
+             }
+     };
  }
 
- private boolean match(String[] rules, String[] addrs,
-         String[]hostNames) {
-     boolean ret=true;
-     int i=0;
+ @Test(dataProvider = "valid6Rules")
+  public void testValid6Decode(String mask)
+          throws Exception {
+    AddressMask.decode(mask);
+  }
 
-     AddressMask[] m = new AddressMask[rules.length];
-     try {
-         for (i = 0; i < rules.length; i++) {
-             m[i] = AddressMask.decode(rules[i]);
-         }
-     } catch (ConfigException ce) {
-         throw new RuntimeException(
-                 "Invalid mask <" + rules[i] + 
-                 "> all data must be valid for this test");
-     }
-     for(int j =0; j < addrs.length; j++) {
-         if(!AddressMask.maskListContains(getAddress(addrs[j]),
-                 hostNames[j],m)) {
-             ret=false;
-             break;
-         }
-     }
-     return ret;
- }
+  @Test(expectedExceptions=ConfigException.class, dataProvider="invalid6Rules")
+  public void testInvalid6Decode(String mask)
+          throws Exception {
+    try {
+      AddressMask.decode(mask);
+    } catch (ConfigException e) {
+      throw e;
+    } catch (Exception e) {
+      System.out.println(
+              "Invalid mask  <" + mask + "> threw wrong exception type.");
+      throw e;
+    }
+    throw new RuntimeException(
+            "Invalid mask <" + mask + "> did not throw an exception.");
+  }
+
+  @Test(dataProvider = "match6Rules")
+  public void testMatch6(String[] rules, String[] addrs, String[]hostNames) {
+      boolean ret;
+      ret=match(rules,addrs,hostNames);
+      assertTrue(ret);
+  }
 }

--
Gitblit v1.10.0