From 742d377d978115fa1c38e43c3e5dad8830901e9f Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Thu, 28 Jun 2007 12:12:21 +0000
Subject: [PATCH] Fix ACI IP bind rule behavior to be compatible with DSEE. Issue 461.

---
 /dev/null                                                                                                       |  140 ------
 opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/PatternIP.java                          |  458 ++++++++++++++++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java |  386 +++++++++++++++++
 opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java                           |    2 
 opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IP.java                                 |  132 ++++++
 opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java                                        |  174 +++++++
 6 files changed, 1,148 insertions(+), 144 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
index 502d8b1..5910b65 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
@@ -508,7 +508,7 @@
             }
             case IP:
             {
-                rule = IpCriteria.decode(expr, op);
+                rule=IP.decode(expr, op);
                 break;
             }
             case DNS:
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IP.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IP.java
new file mode 100644
index 0000000..555a28e
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IP.java
@@ -0,0 +1,132 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.authorization.dseecompat;
+
+import static org.opends.server.messages.AciMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import java.util.regex.Pattern;
+import java.util.*;
+import java.net.InetAddress;
+
+/**
+ * This class represents a single ACI's IP bind rule expression. It is possble
+ * for that expression to contain several IP addresses to evaluate, so the
+ * class contains a list of classes that can evaluate a remote clients IP
+ * address for each IP address parsed from the bind rule.
+ */
+public class IP implements KeywordBindRule {
+
+    /*
+      Regular expression used to do a quick check on the characters in a
+      bind rule address. These are all of the valid characters that may
+      appear in an bind rule address part.
+    */
+    private  static final String ipRegEx =
+            "((?i)[\\.{1}[a-f]\\d:\\+{1}\\*/{1}\\t\\[{1}\\]{1}]+(?-i))";
+
+    /*
+      List of the pattern classes, one for each address decoded from the
+      bind rule.
+    */
+    private List<PatternIP> patternIPList=null;
+
+    /*
+      The type of the bind rule (!= or =).
+     */
+    private EnumBindRuleType type=null;
+
+    /**
+     * Create a class representing the IP bind rule expressions for this ACI.
+     * @param patternIPList A list of PatternIP objects representing the IP
+     *                      bind rule expressions decoded from ACI.
+     * @param type An enumeration representing the expression type.
+     */
+    private IP(List<PatternIP> patternIPList, EnumBindRuleType type) {
+        this.patternIPList=patternIPList;
+        this.type=type;
+    }
+
+    /**
+     * Decodes the provided IP bind rule expression string and returns an
+     * IP class the can be used to evaluate remote clients IP addresses.
+     *
+     * @param expr The expression string from the ACI IP bind rule.
+     * @param type An enmumeration representing the expression type.
+     * @return  A class that can be used to evaluate remote clients IP
+     *          addresses.
+     * @throws AciException  If there is a parsing error.
+     */
+    public static KeywordBindRule decode(String expr, EnumBindRuleType type)
+            throws AciException  {
+        //Split on the ','.
+        String[] ipStrs=expr.split("\\,", -1);
+        List<PatternIP> patternIPList= new LinkedList<PatternIP>();
+        for (String ipStr : ipStrs) {
+            if (!Pattern.matches(ipRegEx, ipStr)) {
+                int msgID = MSGID_ACI_SYNTAX_INVALID_IP_EXPRESSION;
+                String message = getMessage(msgID, expr);
+                throw new AciException(msgID, message);
+            }
+            PatternIP ipPattern = PatternIP.decode(ipStr);
+            patternIPList.add(ipPattern);
+        }
+        return new IP(patternIPList, type);
+    }
+
+    /**
+     * Perform an evaluation using the provided evaluation context's remote
+     * IP address information.
+     *
+     * @param evalCtx An evaluation context containing the remote clients
+     * IP address information.
+     *
+     * @return An enumeration representing if the address matched.
+     */
+    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
+        InetAddress remoteAddr=evalCtx.getRemoteAddress();
+        return evaluate(remoteAddr);
+    }
+
+    /**
+     * Perform an evaluation using the InetAddress.
+     *
+     * @param addr  The InetAddress to evaluate against PatternIP classes.
+     * @return  An enumeration representing if the address matched one
+     *          of the patterns.
+     */
+    EnumEvalResult evaluate(InetAddress addr) {
+        EnumEvalResult matched=EnumEvalResult.FALSE;
+        Iterator<PatternIP> it=patternIPList.iterator();
+        for(; it.hasNext() && matched != EnumEvalResult.TRUE &&
+                matched != EnumEvalResult.ERR;) {
+            PatternIP patternIP=it.next();
+            matched=patternIP.evaluate(addr);
+        }
+        return matched.getRet(type, false);
+    }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpBitsNetworkCriteria.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpBitsNetworkCriteria.java
deleted file mode 100644
index a0c4348..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpBitsNetworkCriteria.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.authorization.dseecompat;
-
-import static org.opends.server.messages.AciMessages.*;
-import static org.opends.server.messages.MessageHandler.getMessage;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * This class builds a network string to an internal representation.
- */
-public class IpBitsNetworkCriteria {
-
-  byte[] _address;    // address in byte format
-  int _bits;      // number of bits for matching
-  byte[] _bitsArray;    // bits in network order
-  InetAddress _inetAddress;
-
-  /**
-   * Creates a new IpBitsNeworkCriteria instance.
-   *
-   * @param  theInputAddress     IP address associated the rule. For IPV4
-   *                             addresses, the following
-   *                             textual formats are supported
-   *                             a.b.c.d
-   *                             a.b.c
-   *                             a.b
-   *                             a
-   *                             For IPv6 addresses, the following textual
-   *                             format are supported:
-   *                             x:x:x:x:x:x:x:x, where x are the hexadecimal
-   *                             values of the 8
-   *                             16-bits pieces of the address
-   *                             Use of :: to compress the leading
-   *                             and/or trailing zeros e.g.
-   *                             x::x:x:x:x:x:x
-   *
-   * @param  theBits             Number of bits of the network address
-   *                             necessary for matching.
-   *                             Max is 32 for IPv4 addresses and 128
-   *                              for IPv6 addresses \
-   *
-   * @throws UnknownHostException Thrown if the inetaddress cannot be gotten
-   * from the input address string.
-   * @throws AciException Thrown if the bit count is not in the correct
-   * ranges.
-   */
-
-  public IpBitsNetworkCriteria(String theInputAddress, int theBits)
-  throws UnknownHostException, AciException
-  {
-    boolean ipv4 = true;
-    _inetAddress = InetAddress.getByName(theInputAddress);
-
-    if (_inetAddress instanceof Inet6Address)
-    {
-      if (theBits < 0 || theBits > 128) {
-          int msgID = MSGID_ACI_SYNTAX_INVALID_NETWORK_BIT_MATCH;
-          String message = getMessage(msgID, "IPV6",
-                  "Bits must be in [0..128] range.");
-          throw new AciException(msgID, message);
-      }
-      ipv4=false;
-    }
-    else
-    {
-      // Assume IPv4
-      if (theBits < 0 || theBits > 32) {
-          int msgID = MSGID_ACI_SYNTAX_INVALID_NETWORK_BIT_MATCH;
-          String message = getMessage(msgID, "IPV4",
-                  "Bits must be in [0..32] range.");
-          throw new AciException(msgID, message);
-      }
-    }
-
-    _bits = theBits;
-
-    // Convert the bits into a mask in network byte order
-    if (ipv4)
-    {
-      _bitsArray = new byte[4];
-      // in java int is exactly 4 bytes
-      int rawBits;
-      if (theBits==0)
-        rawBits=0;
-      else
-        rawBits=~0;
-      rawBits = rawBits << (32 - theBits);
-      // Use network order for the comparison
-      _bitsArray[0] = (byte) ((rawBits >> 24) & 0xFF );
-      _bitsArray[1] = (byte) ((rawBits >> 16) & 0xFF );
-      _bitsArray[2] = (byte) ((rawBits >> 8) & 0xFF );
-      _bitsArray[3] = (byte) ((rawBits) & 0xFF );
-    }
-    else
-    {
-      _bitsArray = new byte[16];
-      int index=0;
-      if (theBits > 64)
-      {
-        _bitsArray[0] = (byte) 0xFF;
-        _bitsArray[1] = (byte) 0xFF;
-        _bitsArray[2] = (byte) 0xFF;
-        _bitsArray[3] = (byte) 0xFF;
-        _bitsArray[4] = (byte) 0xFF;
-        _bitsArray[5] = (byte) 0xFF;
-        _bitsArray[6] = (byte) 0xFF;
-        _bitsArray[7] = (byte) 0xFF;
-        theBits-=64;
-        index=8;
-      }
-      long rawBits = ~0;
-      rawBits = rawBits << (64 - theBits);
-
-      if (_bits !=0)
-      {
-        _bitsArray[index++] = (byte) ((rawBits >> 56) & 0xFF );
-        _bitsArray[index++] = (byte) ((rawBits >> 48) & 0xFF );
-        _bitsArray[index++] = (byte) ((rawBits >> 40) & 0xFF );
-        _bitsArray[index++] = (byte) ((rawBits >> 32) & 0xFF );
-        _bitsArray[index++] = (byte) ((rawBits >> 24) & 0xFF );
-        _bitsArray[index++] = (byte) ((rawBits >> 16) & 0xFF );
-        _bitsArray[index++] = (byte) ((rawBits >> 8) & 0xFF );
-        _bitsArray[index] = (byte) ((rawBits ) & 0xFF );
-      }
-    }
-
-    _address = _inetAddress.getAddress();
-  }
-
-  /**
-   * Compare an IP address with the network rule.
-   *
-   * @param  theSourceAddress   IP source address of the client contacting
-   *                            the proxy server.
-   * @return  <CODE>true</CODE> if client matches the network rule or
-   *          <CODE>false</CODE> if they may not.
-   */
-
-  public boolean match (InetAddress theSourceAddress)
-  {
-    byte[] addr = theSourceAddress.getAddress();
-
-    if ((addr.length * 8) < _bits) {
-      // Client IP  too small. Won't match.
-      return false;
-    }
-
-    for (int i=0; i<addr.length; i++)
-    {
-      if ((addr[i] & _bitsArray[i]) != (_address[i] & _bitsArray[i])) {
-        return false;
-      }
-    }
-
-    return true;
-
-  }
-
-  /**
-   * String representation of this criteria.
-   *
-   * @return  a String representation of the IpMaskNetworkCriteria
-   */
-
-  public String toString()
-  {
-    return "Address:" + _inetAddress.getHostAddress() +
-        "/" + Integer.toString(_bits);
-  }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java
deleted file mode 100644
index 88c5ea3..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.authorization.dseecompat;
-
-import static org.opends.server.messages.AciMessages.*;
-import static org.opends.server.authorization.dseecompat.Aci.*;
-import static org.opends.server.messages.MessageHandler.getMessage;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.HashSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * This class represents a ip bind rule keyword.
- */
-public class IpCriteria implements KeywordBindRule {
-    private EnumBindRuleType type=null;
-
-    // private token to express that any address is accepted
-    private final static String ANY_ADDRESSES = "ALL";
-    private boolean matchAnyAddress = false;
-
-    private IpBitsNetworkCriteria[] ipBitsCriteria = null;
-    private IpMaskNetworkCriteria[] ipMaskCriteria = null;
-
-    private static final String valueRegex =
-                                   "([^," + ZERO_OR_MORE_WHITESPACE + "]+)";
-
-    private static final String valuesRegex =
-            valueRegex + ZERO_OR_MORE_WHITESPACE + "(," +
-            ZERO_OR_MORE_WHITESPACE + valueRegex + ")*";
-
-    /*
-     * TODO Verifiy IpCriteria constructor adheres to DS 5.2 ip keyword
-     * syntax.
-     *
-     * Based on the contents of the constructor, it doesn't appear that the
-     * IpCriteria class uses the same set of allowed values as DS 5.2 does
-     * with the "ip" keyword (as documented at
-     * http://docs.sun.com/source/817-7613/aci.html#wp20242).  Was that the
-     * intention?  It looks like it doesn't allow asterisks as wild-ccards or
-     * plus signs to specify netmasks (although it appears that it expects a
-     * slash to be  used if you want a netmask).  While I don't mind allowing
-     * alternate formats (e.g., CIDR-style addresses), we can't drop support
-     * for the existing ones if we're trying to maintain compatibility.
-     */
-    /**
-     * Constructor that creates an IpCriteria from an array of values and
-     * an enumeration bind rule type.
-     * @param values An array of address values.
-     * @param type An enumeration of the bind rule type.
-     * @throws UnknownHostException If the host address cannot be resolved to
-     * a hostname.
-     * @throws AciException  If a part of the address is invalid.
-     * @throws IndexOutOfBoundsException  If an index is incremented past an
-     * array bounds when copying or evaluating an address.
-     */
-    public IpCriteria(String[] values, EnumBindRuleType type)
-    throws UnknownHostException, IndexOutOfBoundsException, AciException {
-        IpBitsNetworkCriteria[] ipBitsCriteria_2 = null;
-        IpMaskNetworkCriteria[] ipMaskCriteria_2 = null;
-        try
-        {
-            for (String value : values)
-            {
-                if (value.equalsIgnoreCase(ANY_ADDRESSES))
-                {
-                    matchAnyAddress = true;
-                    continue;
-                }
-                // determine what format it is to instantiate
-                // the right criteria object
-                int slash = value.indexOf("/");
-                if (slash == -1)
-                {
-                    // simple raw IP address
-                    IpBitsNetworkCriteria newInstance;
-                    if (InetAddress.getByName(value)
-                            instanceof Inet6Address)
-                    {
-                        newInstance = new IpBitsNetworkCriteria(value, 128);
-                    } else
-                    {
-                        newInstance = new IpBitsNetworkCriteria(value, 32);
-                    }
-                    if (ipBitsCriteria_2 == null)
-                    {
-                        ipBitsCriteria_2 = new IpBitsNetworkCriteria[1];
-                    } else
-                    {
-                        IpBitsNetworkCriteria[] newIpBitsCriteria =
-                         new IpBitsNetworkCriteria[ipBitsCriteria_2.length + 1];
-                        System.arraycopy(ipBitsCriteria_2, 0,
-                                newIpBitsCriteria, 0, ipBitsCriteria_2.length);
-                        ipBitsCriteria_2 = newIpBitsCriteria;
-                    }
-                    ipBitsCriteria_2[ipBitsCriteria_2.length - 1] = newInstance;
-                } else
-                {
-                    // Extract data following the / and figure out whether it
-                    // is a bit number or a mask
-                    try
-                    {
-                        int bits =
-                                Integer.parseInt(value.substring(slash + 1));
-                        // Well, no exception, so this is a bit
-                        // Let's instantiate the corresponding criterion
-                        if (ipBitsCriteria_2 == null)
-                        {
-                            ipBitsCriteria_2 = new IpBitsNetworkCriteria[1];
-                        } else
-                        {
-                         IpBitsNetworkCriteria[] newIpBitsCriteria =
-                         new IpBitsNetworkCriteria[ipBitsCriteria_2.length + 1];
-                            System.arraycopy(ipBitsCriteria_2, 0,
-                                 newIpBitsCriteria, 0, ipBitsCriteria_2.length);
-                            ipBitsCriteria_2 = newIpBitsCriteria;
-                        }
-                        ipBitsCriteria_2[ipBitsCriteria_2.length - 1] =
-                                new IpBitsNetworkCriteria(value.
-                                        substring(0, slash), bits);
-                    }
-                    catch (IndexOutOfBoundsException e1)
-                    {
-                        throw e1;
-                    }
-                    catch (Exception e2)
-                    {
-                        // Looks like this is a network mask.
-                        if (ipMaskCriteria_2 == null)
-                        {
-                            ipMaskCriteria_2 = new IpMaskNetworkCriteria[1];
-                        } else
-                        {
-                        IpMaskNetworkCriteria[] newIpMaskCriteria =
-                         new IpMaskNetworkCriteria[ipMaskCriteria_2.length + 1];
-                            System.arraycopy(ipMaskCriteria_2, 0,
-                                 newIpMaskCriteria, 0, ipMaskCriteria_2.length);
-                            ipMaskCriteria_2 = newIpMaskCriteria;
-                        }
-                        try
-                        {
-                            ipMaskCriteria_2[ipMaskCriteria_2.length - 1] =
-                              new IpMaskNetworkCriteria(value.
-                              substring(0, slash), value.substring(slash + 1));
-                        }
-                        catch (IndexOutOfBoundsException e3)
-                        {
-                            throw e3;
-                        }
-                    }
-                }
-            }
-        }
-        catch (UnknownHostException ue)
-        {
-            throw ue;
-        }
-        ipBitsCriteria = ipBitsCriteria_2;
-        ipMaskCriteria = ipMaskCriteria_2;
-        this.type=type;
-    }
-
-    /**
-     * Return the ipBitsNetworkCriteria of this  IpCriteria.
-     * @return Returns the ipBitsNetworkCriteria.
-     */
-    public IpBitsNetworkCriteria[] getIpBitsNetworkCriteria() {
-        return ipBitsCriteria;
-    }
-
-    /**
-     * Return the ipMaskNetworkCriteria of this IpCriteria.
-     * @return Returns the ipMaskNetworkCriteria.
-     */
-    public IpMaskNetworkCriteria[] getIpMaskNetworkCriteria() {
-        return ipMaskCriteria;
-    }
-
-    /**
-     * Compare an IP address with the network rule.
-     *
-     * @param  theSourceAddress   IP source address of the client.
-     * @return  <CODE>true</CODE> if client matches the network rule or
-     *          <CODE>false</CODE> if they may not.
-     */
-    public boolean match (InetAddress theSourceAddress)
-    {
-        if (matchAnyAddress){
-            return true;
-        }
-        if (ipMaskCriteria != null)
-        {
-            for (IpMaskNetworkCriteria anIpMaskCriteria : ipMaskCriteria)
-            {
-                if (anIpMaskCriteria.match(theSourceAddress))
-                {
-                    return true;
-                }
-            }
-        }
-
-        if (ipBitsCriteria != null)
-        {
-            for (IpBitsNetworkCriteria anIpBitsCriteria : ipBitsCriteria)
-            {
-                if (anIpBitsCriteria.match(theSourceAddress))
-                {
-                    return true;
-                }
-            }
-        }
-
-        return (ipBitsCriteria == null) && (ipMaskCriteria == null);
-    }
-
-    /**
-     * Decode an expression string representing a ip keyword bind rule
-     * expression.
-     * @param expr A string representing the expression.
-     * @param type An enumeration representing the bind rule type.
-     * @return  An keyword bind rule that can be used to evaluate the
-     * expression.
-     * @throws AciException  If the expression string is invalid.
-     */
-    public static KeywordBindRule decode(String expr, EnumBindRuleType type)
-    throws AciException  {
-        if (!Pattern.matches(valuesRegex, expr)) {
-            int msgID = MSGID_ACI_SYNTAX_INVALID_IP_EXPRESSION;
-            String message = getMessage(msgID, expr);
-            throw new AciException(msgID, message);
-        }
-
-        int valuePos = 1;
-        Pattern valuePattern = Pattern.compile(valueRegex);
-        Matcher valueMatcher = valuePattern.matcher(expr);
-        HashSet<String> values = new HashSet<String>();
-        while (valueMatcher.find()) {
-            String value = valueMatcher.group(valuePos);
-            values.add(value);
-        }
-        IpCriteria ipCriteria;
-        String[] strValues = null;
-        if (!values.isEmpty()) {
-            strValues = values.toArray(new String[values.size()]);
-        }
-        try {
-            ipCriteria = new IpCriteria(strValues, type);
-        } catch (Exception e) {
-            int msgID = MSGID_ACI_SYNTAX_INVALID_IP_CRITERIA_DECODE;
-            String message = getMessage(msgID, e.getMessage());
-            throw new AciException(msgID, message);
-        }
-        return ipCriteria;
-    }
-
-    /**
-     * Evaluate the evaluation context against this ip criteria.
-     * @param evalCtx An evaluation context to use.
-     * @return An enumeration evaluation result.
-     */
-    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
-        EnumEvalResult matched=EnumEvalResult.FALSE;
-        if(match(evalCtx.getRemoteAddress()))
-              matched=EnumEvalResult.TRUE;
-        return matched.getRet(type, false);
-    }
-}
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpMaskNetworkCriteria.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpMaskNetworkCriteria.java
deleted file mode 100644
index 4c4c5d0..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/IpMaskNetworkCriteria.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.authorization.dseecompat;
-
-import static org.opends.server.messages.AciMessages.*;
-import static org.opends.server.messages.MessageHandler.getMessage;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- *   This class creates a network mask criteria from the address and mask
- *   string passed to it.
- */
-class IpMaskNetworkCriteria
-{
-
-  byte[] _address;    // address in byte format
-  byte[] _mask;     // mask in byte format
-  InetAddress _inetAddress;
-  InetAddress _inetMask;
-  boolean _ipv4;      // true if ipv4 address
-
-
-  /**
-   * Creates a new IpMaskNeworkCriteria instance.
-   *
-   * @param  theInputAddress     IP address associated the rule. For IPV4
-   *                             addresses, the following
-   *                             textual formats are supported
-   *                             a.b.c.d
-   *                             a.b.c
-   *                             a.b
-   *                             a
-   *                             For IPv6 addresses, the following textual
-   *                             format are supported:
-   *                             x:x:x:x:x:x:x:x, where x are the hexadecimal
-   *                             values of the 8 16-bits pieces of the address
-   *                             Use of :: to compress the leading  and/or
-   *                             trailing zeros e.g.x::x:x:x:x:x:x
-   *
-   * @param  theInputMask        Bits of the network address necessary
-   *                             for matching.
-   *                             Same format as the IP address above.
-   *
-   * @throws UnknownHostException Thrown if the hostname of the input address
-   * cannot be resolved.
-   * @throws AciException If the address family has a mismatch.
-   */
-
-  public IpMaskNetworkCriteria(String theInputAddress, String theInputMask)
-  throws UnknownHostException, AciException {
-    _inetAddress = InetAddress.getByName(theInputAddress);
-    _inetMask = InetAddress.getByName(theInputMask);
-    _address = _inetAddress.getAddress();
-    _mask = _inetMask.getAddress();
-
-    if (_inetAddress instanceof Inet4Address)
-      _ipv4=true;
-
-    if (_ipv4 && !(_inetMask instanceof Inet4Address) ||
-       (!_ipv4 && !(_inetMask instanceof Inet6Address))) {
-        int msgID = MSGID_ACI_SYNTAX_ADDRESS_FAMILY_MISMATCH;
-        String message = getMessage(msgID, theInputMask, theInputAddress);
-        throw new AciException(msgID, message);
-    }
-  }
-
-  /**
-   * Compare an IP address with the network criteria.
-   *
-   * @param  theSourceAddress   IP source address of the client.
-   * @return  <CODE>true</CODE> if client matches the network rule or
-   *          <CODE>false</CODE> if they may not.
-   */
-
-  public boolean match (InetAddress theSourceAddress)
-  {
-    // First address family must match
-    if (_ipv4)
-    {
-      if (!(theSourceAddress instanceof Inet4Address))
-        return false;
-    }
-    else
-    {
-      if (!(theSourceAddress instanceof Inet6Address))
-        return false;
-    }
-
-    byte[] addr = theSourceAddress.getAddress();
-    for (int i=0; i<addr.length; i++) {
-      if ((addr[i] & _mask[i]) != (_address[i] & _mask[i])) {
-        return false;
-      }
-    }
-    return true;
-
-  }
-
-  /**
-   * String representation of this rule.
-   *
-   * @return  a String representation of the IpMaskNetworkRule.
-   */
-
-  public String toString()
-  {
-    return "Address:" + _inetAddress.getHostAddress() +
-        " Mask:" + _inetMask.getHostAddress();
-  }
-}
-
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/PatternIP.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/PatternIP.java
new file mode 100644
index 0000000..e56cc77
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/PatternIP.java
@@ -0,0 +1,458 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+
+package org.opends.server.authorization.dseecompat;
+
+import static org.opends.server.messages.AciMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.net.Inet6Address;
+
+/**
+ * A class representing a single IP address parsed from a IP bind rule
+ * expression. The class can be used to evaluate a remote clients IP address
+ * using the information parsed from the IP bind rule expression.
+ */
+public class PatternIP {
+
+    /**
+     * Enumeration that represents if the pattern is IPv5 or
+     * IPv4.
+     */
+     enum IPType {
+        IPv4, IPv6
+    }
+
+    /*
+      The IP address type (v6 or v4).
+     */
+    private IPType ipType;
+
+    /*
+      IPv4 sizes of addresses and prefixes.
+     */
+    private static int IN4ADDRSZ = 4;
+    private static int IPV4MAXPREFIX = 32;
+
+    /*
+      IPv6 sizes of addresses and prefixes.
+     */
+    private static int IN6ADDRSZ = 16;
+    private static int IPV6MAXPREFIX = 128;
+
+    /*
+      Byte arrays used to match the remote IP address. The ruleAddrByte array
+      contains the bytes of the address from the ACI IP bind rule. The
+      rulePrefixBytes array contains the bytes of the cidr prefix or netmask
+      representation.
+     */
+    private byte[] ruleAddrBytes, rulePrefixBytes;
+
+    /*
+      Bit set that holds the wild-card information of processed IPv4 addresses.
+     */
+    private BitSet wildCardBitSet;
+
+    /*
+      Hash map of valid netmask strings. Used in parsing netmask values.
+     */
+    private static HashMap<String,String> validNetMasks =
+                                               new HashMap<String, String>();
+
+    /*
+     Initialize valid netmask hash map.
+     */
+    static {
+        initNetMask(
+                "255.255.255.255",
+                "255.255.255.254",
+                "255.255.255.252",
+                "255.255.255.248",
+                "255.255.255.240",
+                "255.255.255.224",
+                "255.255.255.192",
+                "255.255.255.128",
+                "255.255.255.0",
+                "255.255.254.0",
+                "255.255.252.0",
+                "255.255.248.0",
+                "255.255.240.0",
+                "255.255.224.0",
+                "255.255.192.0",
+                "255.255.128.0",
+                "255.255.0.0",
+                "255.254.0.0",
+                "255.252.0.0",
+                "255.248.0.0",
+                "255.240.0.0",
+                "255.224.0.0",
+                "255.192.0.0",
+                "255.128.0.0",
+                "255.0.0.0",
+                "254.0.0.0",
+                "252.0.0.0",
+                "248.0.0.0",
+                "240.0.0.0",
+                "224.0.0.0",
+                "192.0.0.0",
+                "128.0.0.0",
+                "0.0.0.0"
+        );
+    }
+
+    /**
+     * Load the valid netmask hash map with the 33 possible valid netmask
+     * strings.
+     *
+      * @param lines The strings representing the valid netmasks.
+     */
+    private static void initNetMask(String... lines) {
+        for(String line : lines) {
+            validNetMasks.put(line, line);
+        }
+    }
+
+    /**
+     * Create a class that can be used to evaluate an IP address using the
+     * information decoded from the ACI IP bind rule expression.
+     *
+     * @param ipType The type of the ACI IP address (IPv4 or 6).
+     * @param ruleAddrBytes Byte array representing the ACI IP address.
+     * @param rulePrefixBytes Prefix byte array corresponding to the bits set
+     *                        by the cidr prefix or netmask.
+     * @param wildCardBitSet Bit set holding IPv4 wild-card information.
+     */
+    private PatternIP(IPType ipType, byte[] ruleAddrBytes,
+                      byte[] rulePrefixBytes, BitSet wildCardBitSet) {
+       this.ipType=ipType;
+       this.ruleAddrBytes=ruleAddrBytes;
+       this.rulePrefixBytes=rulePrefixBytes;
+       this.wildCardBitSet=wildCardBitSet;
+    }
+
+    /**
+     * Decode the provided address expression string and create a class that
+     * can be used to perform an evaluation of an IP address based on the
+     * decoded expression string information.
+     *
+     * @param expr The address expression string from the ACI IP bind rule.
+     * @return A class that can evaluate a remote clients IP address using the
+     *         expression's information.
+     * @throws AciException If the address expression is invalid.
+     */
+    public static
+    PatternIP decode(String expr)  throws AciException {
+        IPType ipType=IPType.IPv4;
+        byte[] prefixBytes;
+        String addrStr;
+        if(expr.indexOf(':') != -1)
+            ipType = IPType.IPv6;
+        if(expr.indexOf('/') != -1) {
+            String prefixStr=null;
+            String[] s = expr.split("[/]", -1);
+            if(s.length == 2) prefixStr=s[1];
+            int prefix = getPrefixValue(ipType, s.length, expr, prefixStr);
+            prefixBytes=getPrefixBytes(prefix, ipType);
+            addrStr=s[0];
+        } else if(expr.indexOf('+') != -1) {
+            String netMaskStr=null;
+            String[] s = expr.split("[+]", -1);
+            if(s.length == 2)
+                netMaskStr=s[1];
+            prefixBytes=getNetmaskBytes(netMaskStr, s.length, expr);
+            addrStr=s[0];
+        } else {
+            int prefix = getPrefixValue(ipType, 1, expr, null);
+            prefixBytes=getPrefixBytes(prefix, ipType);
+            addrStr=expr;
+        }
+        //Set the bit set size fo IN6ADDRSZ even though only 4 positions are
+        //used.
+        BitSet wildCardBitSet = new BitSet(IN6ADDRSZ);
+        byte[] addrBytes;
+        if(ipType == IPType.IPv4)
+            addrBytes = procIPv4Addr(addrStr, wildCardBitSet, expr);
+        else {
+            addrBytes=procIPv6Addr(addrStr, expr);
+            //The IPv6 address processed above might be a IPv4-compatible
+            //address, in which case only 4 bytes will be returned in the
+            //address byte  array. Ignore any IPv6 prefix.
+            if(addrBytes.length == IN4ADDRSZ) {
+                ipType=IPType.IPv4;
+                prefixBytes=getPrefixBytes(IPV4MAXPREFIX, ipType);
+            }
+        }
+        return new PatternIP(ipType, addrBytes, prefixBytes, wildCardBitSet);
+    }
+
+    /**
+     * Process the IP address prefix part of the expression. Handles if there is
+     * no prefix in the expression.
+     *
+     * @param ipType The type of the expression, either IPv6 or IPv4.
+     * @param numParts The number of parts in the IP address expression.
+     *                 1 if there isn't a prefix, and 2 if there is. Anything
+     *                 else is an error (i.e., 254.244.123.234/7/6).
+     * @param expr The original expression from the bind rule.
+     * @param prefixStr The string representation of the prefix part of the
+     *                  IP address.
+     * @return  An integer value determined from the prefix string.
+     * @throws AciException If the prefix string is invalid.
+     */
+    private static int
+    getPrefixValue(IPType ipType, int numParts, String expr, String prefixStr)
+    throws AciException {
+
+        int prefix = IPV4MAXPREFIX;
+        int maxPrefix= IPV4MAXPREFIX;
+        if(ipType == IPType.IPv6) {
+            prefix= IPV6MAXPREFIX;
+            maxPrefix=IPV6MAXPREFIX;
+        }
+        try {
+            //Can only have one prefix value and one address string.
+            if((numParts  < 1) || (numParts > 2) ) {
+                int msgID = MSGID_ACI_SYNTAX_INVALID_PREFIX_FORMAT;
+                String message = getMessage(msgID, expr);
+                throw new AciException(msgID, message);
+            }
+            if(prefixStr != null)
+                prefix = Integer.parseInt(prefixStr);
+            //Must be between 0 to maxprefix.
+            if((prefix < 0) || (prefix > maxPrefix)) {
+                int msgID=MSGID_ACI_SYNTAX_INVALID_PREFIX_VALUE;
+                String message = getMessage(msgID, expr);
+                throw new AciException(msgID, message);
+            }
+        } catch(NumberFormatException nfex) {
+            int msgID=MSGID_ACI_SYNTAX_PREFIX_NOT_NUMERIC;
+            String msg = getMessage(msgID, expr);
+            throw new AciException(msgID,msg);
+        }
+        return prefix;
+    }
+
+    /**
+     * Determine the prefix bit mask based on the provided prefix value. Handles
+     * both IPv4 and IPv6 prefix values.
+     *
+     * @param prefix  The value of the prefix parsed from the address
+     *                expression.
+     * @param ipType  The type of the prefix, either IPv6 or IPv4.
+     * @return A byte array representing the prefix bit mask used to match
+     *         IP addresses.
+     */
+    private static byte[] getPrefixBytes(int prefix, IPType ipType) {
+        int i;
+        int maxSize=IN4ADDRSZ;
+        if(ipType==IPType.IPv6)
+            maxSize= IN6ADDRSZ;
+        byte[] prefixBytes=new byte[maxSize];
+        for(i=0;prefix > 8 ; i++) {
+            prefixBytes[i] = (byte) 0xff;
+            prefix -= 8;
+        }
+        prefixBytes[i] = (byte) ((0xff) << (8 - prefix));
+        return prefixBytes;
+    }
+
+    /**
+     * Process the specified netmask string. Only pertains to IPv4 address
+     * expressions.
+     *
+     * @param netmaskStr String represntation of the netmask parsed from the
+     *                   address expression.
+     * @param numParts The number of parts in the IP address expression.
+     *                 1 if there isn't a netmask, and 2 if there is. Anything
+     *                 else is an error (i.e., 254.244.123.234++255.255.255.0).
+     * @param expr The original expression from the bind rule.
+     * @return A byte array representing the netmask bit mask used to match
+     *         IP addresses.
+     * @throws AciException If the netmask string is invalid.
+     */
+    private static
+    byte[] getNetmaskBytes(String netmaskStr, int numParts, String expr)
+    throws AciException {
+        byte[] netmaskBytes=new byte[IN4ADDRSZ];
+        //Look up the string in the valid netmask hash table. If it isn't
+        //there it is an error.
+        if(!validNetMasks.containsKey(netmaskStr)) {
+            int id=MSGID_ACI_SYNTAX_INVALID_NETMASK;
+            String message = getMessage(id, expr);
+            throw new AciException(id, message);
+        }
+        //Can only have one netmask value and one address string.
+        if((numParts  < 1) || (numParts > 2) ) {
+            int msgID = MSGID_ACI_SYNTAX_INVALID_NETMASK_FORMAT;
+            String message = getMessage(msgID, expr);
+            throw new AciException(msgID, message);
+        }
+        String[] s = netmaskStr.split("\\.", -1);
+        try {
+            for(int i=0; i < IN4ADDRSZ; i++) {
+                String quad=s[i].trim();
+                long val=Integer.parseInt(quad);
+                netmaskBytes[i] = (byte) (val & 0xff);
+            }
+        } catch (NumberFormatException nfex) {
+            int id=MSGID_ACI_SYNTAX_IPV4_NOT_NUMERIC;
+            String message = getMessage(id, expr);
+            throw new AciException(id, message);
+        }
+        return netmaskBytes;
+    }
+
+    /**
+     * Process the provided IPv4 address string parsed from the IP bind rule
+     * address expression. It returns a byte array corresponding to the
+     * address string.  The specified bit set represents wild-card characters
+     * '*' found in the string.
+     *
+     * @param addrStr  A string representing an IPv4 address.
+     * @param wildCardBitSet A bit set used to save wild-card information.
+     * @param expr The original expression from the IP bind rule.
+     * @return A address byte array that can be used along with the prefix bit
+     *         mask to evaluate an IPv4 address.
+     *
+     * @throws AciException If the address string is not a valid IPv4 address
+     *                      string.
+     */
+    private static byte[]
+    procIPv4Addr(String addrStr, BitSet wildCardBitSet, String expr)
+    throws AciException {
+        byte[] addrBytes=new byte[IN4ADDRSZ];
+        String[] s = addrStr.split("\\.", -1);
+        try {
+            if(s.length != IN4ADDRSZ) {
+                int id=MSGID_ACI_SYNTAX_INVALID_IPV4_FORMAT;
+                String message = getMessage(id, expr);
+                throw new AciException(id, message);
+            }
+            for(int i=0; i < IN4ADDRSZ; i++) {
+                String quad=s[i].trim();
+                if(quad.equals("*"))
+                    wildCardBitSet.set(i) ;
+                else {
+                    long val=Integer.parseInt(quad);
+                    //must be between 0-255
+                    if((val < 0) ||  (val > 0xff)) {
+                        int id=MSGID_ACI_SYNTAX_INVALID_IPV4_VALUE;
+                        String message = getMessage(id, expr);
+                        throw new AciException(id, message);
+                    }
+                    addrBytes[i] = (byte) (val & 0xff);
+                }
+            }
+        } catch (NumberFormatException nfex) {
+            int id=MSGID_ACI_SYNTAX_IPV4_NOT_NUMERIC;
+            String message = getMessage(id, expr);
+            throw new AciException(id, message);
+        }
+        return addrBytes;
+    }
+
+    /**
+     * Process the provided IPv6  address string parsed from the IP bind rule
+     * IP expression. It returns a byte array corresponding to the
+     * address string. Wild-cards are not allowed in IPv6 addresses.
+     *
+     * @param addrStr A string representing an IPv6 address.
+     * @param expr The original expression from the IP bind rule.
+     * @return A address byte array that can be used along with the prefix bit
+     *         mask to evaluate an IPv6 address.
+     * @throws AciException If the address string is not a valid IPv6 address
+     *                      string.
+     */
+    private static byte[]
+    procIPv6Addr(String addrStr, String expr) throws AciException {
+        if(addrStr.indexOf('*') > -1) {
+            int msgID=MSGID_ACI_SYNTAX_IPV6_WILDCARD_INVALID;
+            String message = getMessage(msgID, expr);
+            throw new AciException(msgID, message);
+        }
+        byte[] addrBytes;
+        try {
+            addrBytes=InetAddress.getByName(addrStr).getAddress();
+        } catch (UnknownHostException ex) {
+            int id=MSGID_ACI_SYNTAX_INVALID_IPV6_FORMAT;
+            String message = getMessage(id, expr, ex.getMessage());
+            throw new AciException(id, message);
+        }
+        return addrBytes;
+    }
+
+    /**
+     * Evaluate the provided IP address against the information processed during
+     * the IP bind rule expression decode.
+     *
+     * @param remoteAddr  A IP address to evaluate.
+     * @return An enumeration representing the result of the evaluation.
+     */
+    public EnumEvalResult evaluate(InetAddress remoteAddr) {
+        EnumEvalResult matched=EnumEvalResult.FALSE;
+        IPType ipType=IPType.IPv4;
+        byte[] addressBytes=remoteAddr.getAddress();
+        if(remoteAddr instanceof Inet6Address) {
+            ipType=IPType.IPv6;
+            Inet6Address addr6 = (Inet6Address) remoteAddr;
+            addressBytes= addr6.getAddress();
+            if(addr6.isIPv4CompatibleAddress())
+                ipType=IPType.IPv4;
+        }
+        if(ipType != this.ipType)
+            return EnumEvalResult.FALSE;
+        if(matchAddress(addressBytes))
+            matched=EnumEvalResult.TRUE;
+        return matched;
+    }
+
+    /**
+     * Attempt to match the address byte array  using the  prefix bit mask array
+     * and the address byte array processed in the decode. Wild-cards take
+     * priority over the mask.
+     *
+     * @param addrBytes IP address byte array.
+     * @return True if the remote address matches based on the information
+     *         parsed from the IP bind rule expression.
+     */
+    private boolean matchAddress(byte[] addrBytes) {
+        if(wildCardBitSet.cardinality() == IN4ADDRSZ)
+            return true;
+        for(int i=0;i <rulePrefixBytes.length; i++) {
+            if(!wildCardBitSet.get(i)) {
+                if((ruleAddrBytes[i] & rulePrefixBytes[i]) !=
+                        (addrBytes[i] & rulePrefixBytes[i]))
+                    return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java
index 1b366b6..08a595c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java
@@ -807,6 +807,113 @@
         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 80;
 
     /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field had an invalid
+     * prefix format. This takes one argument, which is the IP field from the
+     * bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_PREFIX_FORMAT =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 81;
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field had an invalid
+     * prefix value. This takes one argument, which is the IP field from the
+     * bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_PREFIX_VALUE =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 82;
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field has an
+     * prefix value that is not numeric. This takes one argument, which is
+     * the IP field from the bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_PREFIX_NOT_NUMERIC =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 83;
+
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field IPv4 address has an
+     * invalid format. This takes one argument, which is
+     * the IP field from the bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_IPV4_FORMAT =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 84;
+
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field IPv4 address has an
+     * invalid value. This takes one argument, which is
+     * the IP field from the bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_IPV4_VALUE =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 85;
+
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field IPv4 address has an
+     * non-numeric value. This takes one argument, which is
+     * the IP field from the bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_IPV4_NOT_NUMERIC =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 86;
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field IPv6 address
+     * contains a wildcard character '*'. This takes one argument, which is
+     * the IP field from the bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_IPV6_WILDCARD_INVALID =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 87;
+
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field IPv6 address
+     * has an invalid format. This takes otwo arguments, which are
+     * the IP field from the bind rule expression and the message from the
+     * IPv6 parsing method.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_IPV6_FORMAT =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 88;
+
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field had an invalid
+     * netmask format. This takes one argument, which is the IP field from the
+     * bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_NETMASK_FORMAT =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 89;
+
+
+    /**
+     * The message ID for the message that will be used if an "aci" attribute
+     * type value parse fails beacause a bind rule IP field had an invalid
+     * netmask value. This takes one argument, which is the IP field from the
+     * bind rule expression.
+     */
+
+     public static final int MSGID_ACI_SYNTAX_INVALID_NETMASK =
+         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 89;
+
+    /**
      * Associates a set of generic messages with the message IDs defined in
      * this class.
      */
@@ -926,8 +1033,9 @@
         registerMessage(MSGID_ACI_SYNTAX_INVALID_IP_EXPRESSION,
                 "The provided Access Control Instruction (ACI) bind rule " +
                 "ip expression value \"%s\" is invalid. A valid ip " +
-                "keyword expression value requires one or more" +
-                "comma-separated elements of an IP address list expression");
+                "keyword expression requires one or more " +
+                "comma-separated elements of a valid IP address list" +
+                " expression");
 
         registerMessage(MSGID_ACI_SYNTAX_INVALID_DNS_EXPRESSION,
                 "The provided Access Control Instruction (ACI) bind rule " +
@@ -935,7 +1043,6 @@
                 "keyword expression value requires a valid fully qualified"+
                 " DNS domain name");
 
-
         registerMessage(MSGID_ACI_SYNTAX_INVALID_DNS_WILDCARD,
                 "The provided Access Control Instruction (ACI) bind rule " +
                 "dns expression value \"%s\" is invalid, because a wild-card" +
@@ -1267,5 +1374,66 @@
                 "userattr expression value failed to parse because the " +
                 "attribute field of the ldap URL \"%s\" either contains more " +
                 "than one description or the field is empty");
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_PREFIX_FORMAT,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "prefix part of the expression \"%s\" has an invalid format");
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_PREFIX_VALUE,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                "IP address expression failed to parse because the " +
+                "prefix value of the expression \"%s\" was an invalid" +
+                " value. All values must greater than or equal to 0 and " +
+                "either less than or equal 32 for IPV4 addresses or less than" +
+                " or equal to 128 for IPV6 addresses");
+
+        registerMessage(MSGID_ACI_SYNTAX_PREFIX_NOT_NUMERIC,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "prefix part of the expression \"%s\" has an non-numeric" +
+                 " value");
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_IPV4_FORMAT,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "the IPv4 address expression \"%s\" format was invalid");
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_IPV4_VALUE,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 " IPv4 address expression \"%s\" contains an invalid value." +
+                 "All values of the address must be between 0 and 255");
+
+        registerMessage(MSGID_ACI_SYNTAX_IPV4_NOT_NUMERIC,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "the IPv4 address expression \"%s\" contains a non-numeric" +
+                 " value");
+
+        registerMessage(MSGID_ACI_SYNTAX_IPV6_WILDCARD_INVALID,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "the IPv6 address expression \"%s\" contains an illegal" +
+                 " wildcard character. Wildcards are not supported when " +
+                 "using IPv6 addresses in a IP bind rule expression");
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_IPV6_FORMAT,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression \"%s\" failed to parse for the " +
+                 "following reason: \"%s\"");
+
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_NETMASK_FORMAT,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "netmask part of the expression \"%s\" has an invalid format");
+
+
+        registerMessage(MSGID_ACI_SYNTAX_INVALID_NETMASK_FORMAT,
+                "The provided Access Control Instruction (ACI) bind rule " +
+                 "IP address expression failed to parse because the " +
+                 "netmask part of the expression \"%s\" has an invalid value");
+
     }
 }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java
new file mode 100644
index 0000000..0f802cd
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java
@@ -0,0 +1,386 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+
+package org.opends.server.authorization.dseecompat;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import java.net.InetAddress;
+
+/**
+ * Test of IP bind rule address decoding and address matching.
+ */
+public class IPTestCase extends AciTestCase {
+
+    //Various patterns and addresses that can be put in IP bind rule
+    //expressions. For example: ip="72.*.78.*,*.*.*.*".
+
+    private String ipExpr="72.56.78.9,127.0.0.1";
+    private String ipExprWc="72.*.78.*,*.*.*.*";
+    private String netmaskWc=
+             "72.56.78.0+255.255.255.240,127.0.0.0+255.255.255.0";
+    private String netmaskWcOverRide=
+                   "72.*.78.*+255.255.255.248,*.0.0.0+192.0.0.0";
+    private String ip6Expr="12AB:0000:0000:CD30:0000:0000:0000:0000";
+    private String ip6ExprC="12ab:0:0:cd30::";
+    private String ip6ExprCidr="12ab:0:0:cd30::/60";
+    private String ip6ExprCidrB="[12ab:0:0:cd30::]/60";
+    private String ip4compat="::ffff:127.0.0.1,::ffff:72.56.78.9";
+    private String cidr=
+             "72.56.78.0/28,127.0.0.0/24";
+    private String cidrWc=
+                   "72.*.78.*/29,*.0.0.0/7";
+    private String
+            mixed="::ffff:72.56.78.9,45.*.33.*,[12ab:0:0:cd30::]/60," +
+                 "56.56.78.0+255.255.255.0";
+
+    //Providers that test the above expressions.
+    //Mix of Ipv6 and Ipv4 addresses.
+    @DataProvider(name = "mixedMatches")
+    public Object[][] mixedData() {
+        return new Object[][] {
+                {"12AB:0000:0000:CD30:0000:0000:0000:0000"},
+                {"12ab:0:0:cd3f:0000:0000:23DC:DC30"},
+                {"45.56.33.9"},
+                {"72.56.78.9"},
+                {"56.56.78.9"}
+
+        };
+    }
+    //Ipv6 addresses in long and various compressed forms.
+    @DataProvider(name = "v6Matches")
+    public Object[][] v6MatchData() {
+        return new Object[][] {
+                {"12AB:0000:0000:CD30:0000:0000:0000:0000"},
+                {"12AB::CD30:0:0:0:0"},
+                {"12ab:0:0:cd30::"}
+        };
+    }
+
+    //Ipv6 addresses used in cidr tests.
+    @DataProvider(name = "v6Matches1")
+    public Object[][] v6MatchData1() {
+        return new Object[][] {
+                {"12ab:0:0:cd3f:0000:0000:23DC:DC30"},
+                {"12ab::cd3f:0:0:23dc:dc30"}
+        };
+    }
+
+    //Ipv4 addresses.
+    @DataProvider(name = "v4Matches")
+    public Object[][] v4MatchData() {
+        return new Object[][] {
+                {"127.0.0.1"},
+                {"72.56.78.9"}
+        };
+    }
+
+    //Valid IPv4 expressions.
+    @DataProvider(name = "validRules")
+    public Object[][] validData() {
+        return new Object[][] {
+            { "129.34.55.67/0"},
+            { "129.*.78.55+255.255.248.0"},
+            {"128.*.*.*"},
+            {"129.45.23.67/22"},
+            {"128.33.23.*/32"},
+            {"*.*.*.*"},
+            {"129.45.67.34/0"},
+            {"129.45.67.34+255.255.255.0"}
+        };
+    }
+
+    //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"}
+        };
+    }
+
+    //Invalid Ipv4 expressions.
+    @DataProvider(name = "invalidRules")
+    public Object[][] inValidData() {
+        return new Object[][] {
+                {"128.33.23.xx"},
+                {"128.33.23.22++"},
+                {"128.33.23.22+"},
+                {"128.33.23.22+56"},
+                {"128.33.23.22+255.255.45"},
+                {"128.33.23.22+255.255.45.45"},//netmask is invalid
+                {"128.33.23.22/-1"},
+                {"128..33.23"},
+                {"128.33.23.66.88"},
+                {"128.33.600.66"},
+                {"128.33.9.66/33"},
+                {"."},
+                {"foo"}
+        };
+    }
+
+    //Invalid IPv6 expressions.
+    @DataProvider(name = "invalid6Rules")
+    public Object[][] inValid5Data() {
+        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"},
+        };
+    }
+
+    /**
+     * This test uses the mixed (ipv4 and 6) expression above to match against
+     * ipv4 and 6 addresses. All addresses should pass.
+     *
+     * @param ipStr The string to convert into InetAddress.
+     * @throws Exception If the evaluation doesn't return true.
+     */
+    @Test(dataProvider="mixedMatches")
+    public void testMixed(String ipStr) throws Exception {
+         IP ip=(IP) IP.decode(mixed, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+         InetAddress addr=InetAddress.getByName(ipStr);
+         EnumEvalResult res=ip.evaluate(addr);
+         if(res != EnumEvalResult.TRUE)
+             throw new RuntimeException ("Addr: " + ipStr +
+                     "expr: " + mixed);
+     }
+
+
+    /**
+     * Test Ipv6 Ipv4 compat expression. All addresses should pass.
+     *
+     * @param ipStr The string to convert into IPv4 InetAddress.
+     * @throws Exception If the evaluation doesn't return true.
+     */
+    @Test(dataProvider = "v4Matches")
+    public void test4compat(String ipStr) throws Exception {
+        IP ip=(IP) IP.decode(ip4compat, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        InetAddress addr=InetAddress.getByName(ipStr);
+        EnumEvalResult res=ip.evaluate(addr);
+        if(res != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                    "expr: " + ip4compat);
+    }
+
+    /**
+     * Test various IPv6 expressions. First IPv6 expression with CIDR prefix,
+     * then RFC 2732 format (brackets around address) expression.
+     *
+     * @param ipStr The string to convert into IPv6 InetAddress.
+     * @throws Exception If the evaluation doesn't return true.
+     */
+    @Test(dataProvider = "v6Matches1")
+    public void test6Cidr(String ipStr) throws Exception {
+        IP ip=(IP) IP.decode(ip6ExprCidr, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        InetAddress addr=InetAddress.getByName(ipStr);
+        EnumEvalResult res=ip.evaluate(addr);
+        if(res != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + ip6ExprCidr);
+        IP ip1=(IP) IP.decode(ip6ExprCidrB, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        EnumEvalResult res1=ip1.evaluate(addr);
+        if(res1 != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + ip6ExprCidrB);
+    }
+
+    /**
+     * Test IPv6 address expressions. First using the long form, then the
+     * compressed form. The addresses to match have long and compressed forms
+     * also. All tests should pass.
+     *
+     * @param ipStr The string to convert into IPv6 InetAddress.
+     * @throws Exception If the evaluation doesn't return true.
+     */
+    @Test(dataProvider = "v6Matches")
+    public void test6Simple(String ipStr) throws Exception {
+        IP ip=(IP) IP.decode(ip6Expr, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        InetAddress addr=InetAddress.getByName(ipStr);
+        EnumEvalResult res=ip.evaluate(addr);
+        if(res != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + ip6Expr);
+        IP ip1=(IP) IP.decode(ip6ExprC, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        EnumEvalResult res1=ip1.evaluate(addr);
+        if(res1 != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + ip6ExprC);
+    }
+
+    /**
+     * Test IPv4 cidr prefix expressions and cidr prefix with wild-card
+     * expressions. All tests should pass.
+     *
+     * @param ipStr The string to convert into IPv4 InetAddress.
+     * @throws Exception If the evaluation doesn't return true.
+     */
+    @Test(dataProvider = "v4Matches")
+    public void test4NCidr(String ipStr) throws Exception {
+        IP ip=(IP) IP.decode(cidr, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        InetAddress addr=InetAddress.getByName(ipStr);
+        EnumEvalResult res=ip.evaluate(addr);
+        if(res != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + cidr);
+
+        IP ip1=(IP) IP.decode(cidrWc, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        EnumEvalResult res1=ip.evaluate(addr);
+        if(res1 != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + cidrWc);
+    }
+
+    /**
+     * Test IPv4 netmask expressions and netmask with wild-card expressions.
+     * All tests should pass.
+     *
+     * @param ipStr The string to convert into IPv4 InetAddress.
+     * @throws Exception If the evaluation doesn't return true.
+     */
+    @Test(dataProvider = "v4Matches")
+    public void test4Netmasks(String ipStr) throws Exception {
+        IP ip=(IP) IP.decode(netmaskWc, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        InetAddress addr=InetAddress.getByName(ipStr);
+        EnumEvalResult res=ip.evaluate(addr);
+        if(res != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + netmaskWc);
+        IP ip1 = (IP) IP.decode(netmaskWcOverRide,
+                EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        EnumEvalResult res1=ip1.evaluate(addr);
+        if(res1 != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + netmaskWc);
+    }
+
+    /**
+     * Test IPv4 expressions and expression with wild-cards.
+     * All Tests should pass.
+     *
+     * @param ipStr The string to convert into IPv4 InetAddress.
+     * @throws Exception  If the evaluation doesn't return true.
+     */
+    @Test(dataProvider = "v4Matches")
+    public void test4SimpleWildCard(String ipStr) throws Exception {
+        IP ip=(IP) IP.decode(ipExpr, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        InetAddress addr=InetAddress.getByName(ipStr);
+        EnumEvalResult res=ip.evaluate(addr);
+        if(res != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr: " + ipExpr);
+        IP ipWc=(IP) IP.decode(ipExprWc, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        EnumEvalResult resWc=ipWc.evaluate(addr);
+        if(resWc != EnumEvalResult.TRUE)
+            throw new RuntimeException ("Addr: " + ipStr +
+                                        "expr:" + ipExprWc);
+    }
+
+    /**
+     * Test  decoding of various valid rules.
+     *
+     * @param mask The expression to decode.
+     * @throws Exception If the valid rule failed decoding.
+     */
+    @Test(dataProvider = "validRules")
+    public void testValidIPDecode(String mask)
+            throws Exception {
+         IP.decode(mask, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+    }
+
+    /**
+     * Test decoding of invalid rules.
+     *
+     * @param mask The expression to decode.
+     * @throws Exception If the valid rule failed decoding.
+     */
+    @Test(expectedExceptions= AciException.class, dataProvider="invalidRules")
+    public void testInvalidDecode(String mask)
+            throws Exception {
+        try {
+            IP.decode(mask, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        } catch (AciException ae) {
+            throw ae;
+        } 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 decoding of valid IPv6 rules.
+     *
+     * @param mask  The expression to decode.
+     * @throws Exception If the valid rule failed decoding.
+     */
+    @Test(dataProvider = "valid6Rules")
+    public void testValidIP6Decode(String mask)
+            throws Exception {
+        IP.decode(mask, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+    }
+
+
+    /**
+     * Test deocding of invalid IPV6 rules.
+     *
+     * @param mask The expression to decode.
+     * @throws Exception If the valid rule failed decoding.
+     */
+    @Test(expectedExceptions= AciException.class, dataProvider="invalid6Rules")
+    public void testInvalid6Decode(String mask)
+            throws Exception {
+        try {
+            IP.decode(mask, EnumBindRuleType.EQUAL_BINDRULE_TYPE);
+        } catch (AciException ae) {
+            throw ae;
+        } 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.");
+    }
+}

--
Gitblit v1.10.0