mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

dugan
19.49.2006 efedd2b6485014a4e87fb16be44081e79289e10a
Add code to support issue #151 client connection disconnect.
2 files added
4 files modified
1024 ■■■■■ changed files
opends/resource/schema/02-config.ldif 3 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ProtocolMessages.java 35 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java 76 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/AddressMask.java 597 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java 275 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TypesTestCase.java 38 ●●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif
@@ -1041,7 +1041,8 @@
objectClasses: ( 1.3.6.1.4.1.26027.1.2.13
  NAME 'ds-cfg-connection-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-connection-handler-class $
  ds-cfg-connection-handler-enabled ) X-ORIGIN 'OpenDS Directory Server' )
  ds-cfg-connection-handler-enabled ) MAY ( ds-cfg-allowed-client $
  ds-cfg-denied-client ) X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.14
  NAME 'ds-cfg-ldap-connection-handler' SUP ds-cfg-connection-handler
  STRUCTURAL MUST ds-cfg-listen-port MAY ( ds-cfg-listen-address $
opends/src/server/org/opends/server/messages/ProtocolMessages.java
@@ -4132,7 +4132,28 @@
  public static final int MSGID_ACCTUSABLERES_DECODE_ERROR =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 379;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to decode an invalid AddressMask rule prefix.
   */
  public static final int MSGID_ADDRESSMASK_PREFIX_DECODE_ERROR =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 380;
    /**
   * The message ID for the message that will be used if an error occurs
   * because a address mask prefix was specified with an wild card
   * character "*".
   */
  public static final int MSGID_ADDRESSMASK_WILDCARD_DECODE_ERROR =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 381;
  /**
   * The message ID for the message that will be used if an error occurs
   * because a address mask format was invalid.
   *
   */
  public static final int MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR =
       CATEGORY_MASK_PROTOCOL | SEVERITY_MASK_SEVERE_ERROR | 382;
  /**
   * Associates a set of generic messages with the message IDs defined in this
@@ -5893,8 +5914,18 @@
                    "The account availability response control had an " +
                    "unknown ACCOUNT_USABLE_RESPONSE element type of %s.");
    registerMessage(MSGID_ACCTUSABLERES_DECODE_ERROR,
                    "Cannot decode the provided account availability " +
                    "response control:  %s.");
            "Cannot decode the provided account availability " +
            "response control:  %s.");
    registerMessage(MSGID_ADDRESSMASK_PREFIX_DECODE_ERROR,
            "Cannot decode the provided address mask prefix because an" +
            "invalid value was specified. The permitted values for IPv4" +
            "are 0 to32 and for IPv6 0 to128");
    registerMessage(MSGID_ADDRESSMASK_WILDCARD_DECODE_ERROR,
            "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" +
            "invalid format.");
  }
}
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -1224,12 +1224,44 @@
                  ServerSocketChannel serverChannel =
                       (ServerSocketChannel) key.channel();
                  SocketChannel clientChannel = serverChannel.accept();
                  clientChannel.socket().setKeepAlive(useKeepAlive);
                  clientChannel.socket().setTcpNoDelay(useTCPNoDelay);
                  LDAPClientConnection clientConnection =
                       new LDAPClientConnection(this, clientChannel);
                  InetAddress clientAddr=clientConnection.getRemoteAddress();
                  // Check to see if the client is on the denied list.  If so,
                  // then reject it immediately.
                  if((deniedClients != null) && (deniedClients.length > 0) &&
                          AddressMask.maskListContains(clientAddr.getAddress(),
                                  clientAddr.getHostName(), deniedClients))
                  {
                      clientConnection.disconnect(
                              DisconnectReason.CONNECTION_REJECTED,
                              sendRejectionNotice,
                              MSGID_LDAP_CONNHANDLER_DENIED_CLIENT,
                              clientConnection.getClientHostPort(),
                              clientConnection.getServerHostPort());
                      iterator.remove();
                      continue;
                  }
                  // Check to see if there is an allowed list and if there is
                  // whether the client is on that list.  If not, then reject
                  // the connection.
                  if((allowedClients != null) && (allowedClients.length > 0) &&
                        (!AddressMask.maskListContains(clientAddr.getAddress(),
                                  clientAddr.getHostName(), allowedClients)))
                  {
                      clientConnection.disconnect(
                              DisconnectReason.CONNECTION_REJECTED,
                              sendRejectionNotice,
                              MSGID_LDAP_CONNHANDLER_DISALLOWED_CLIENT,
                              clientConnection.getClientHostPort(),
                              clientConnection.getServerHostPort());
                      iterator.remove();
                      continue;
                  }
                  clientChannel.socket().setKeepAlive(useKeepAlive);
                  clientChannel.socket().setTcpNoDelay(useTCPNoDelay);
                  ConnectionSecurityProvider connectionSecurityProvider =
                       securityProvider.newInstance(clientConnection,
                                                    clientChannel);
@@ -1246,44 +1278,6 @@
                    continue;
                  }
                  // Check to see if the client is on the denied list.  If so,
                  // then reject it immediately.
                  if ((deniedClients != null) &&
                      AddressMask.maskListContains(clientConnection,
                                                   deniedClients))
                  {
                    clientConnection.disconnect(
                         DisconnectReason.CONNECTION_REJECTED,
                         sendRejectionNotice,
                         MSGID_LDAP_CONNHANDLER_DENIED_CLIENT,
                         clientConnection.getClientHostPort(),
                         clientConnection.getServerHostPort());
                    iterator.remove();
                    continue;
                  }
                  // Check to see if there is an allowed list and if there is
                  // whether the client is on that list.  If not, then reject
                  // the connection.
                  if ((allowedClients != null) && (allowedClients.length > 0) &&
                      (! AddressMask.maskListContains(clientConnection,
                                                      allowedClients)))
                  {
                    clientConnection.disconnect(
                         DisconnectReason.CONNECTION_REJECTED,
                         sendRejectionNotice,
                         MSGID_LDAP_CONNHANDLER_DISALLOWED_CLIENT,
                         clientConnection.getClientHostPort(),
                         clientConnection.getServerHostPort());
                    iterator.remove();
                    continue;
                  }
                  // If we've gotten here, then we'll take the connection so
                  // choose a request handler and register the client with it.
                  try
opends/src/server/org/opends/server/types/AddressMask.java
@@ -26,75 +26,560 @@
 */
package org.opends.server.types;
import org.opends.server.api.ClientConnection;
import org.opends.server.config.ConfigException;
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;
/**
 * 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 class AddressMask
public final class AddressMask
{
  // NYI
   /**
   * The fully-qualified name of this class for debugging purposes.
   */
  private static final String CLASS_NAME =
       "org.opends.server.types.AddressMask";
  /**
   * Decodes the provided string as an address mask.
   *
   * @param  maskString  The string to decode as an address mask.
   *
   * @return  AddressMask  The address mask decoded from the provided
   *                       string.
   *
   * @throws  ConfigException  If the provided string cannot be
   *                           decoded as an address mask.
   */
  public static AddressMask decode(String maskString)
         throws ConfigException
  {
    // NYI
    return null;
     * Types of rules we have.
     *
     * IPv4 - ipv4 rule
     * IPv6 - ipv6 rule (begin with '['). Not supported see issue #670
     * HOST - hostname match (foo.sun.com)
     * HOSTPATTERN - host pattern match (begin with '.')
     * ALLWILDCARD - *.*.*.* (first HOST is applied then ipv4)
     *
     */
     enum RuleType
    {
        IPv4, IPv6, HOSTPATTERN, ALLWILDCARD, HOST;
    }
    // Type of rule determined
    private  RuleType ruleType;
    // IPv4 values for number of bytes and max CIDR prefix
    /**
     * IPv4 address size.
     */
    public static int IN4ADDRSZ = 4;
    private  int IPV4MAXPREFIX = 32;
    // IPv6 values for number of bytes and max CIDR prefix
    //private  int IN6ADDRSZ = 16;
    //private  int IPV6MAXPREFIX = 128;
    //Holds binary representations of rule and mask respectively.
    private  byte[] ruleMask, prefixMask;
    //Bit array that holds wildcard info for above binary arrays.
    private  BitSet wildCard = new BitSet();
    //Array that holds each component of a hostname.
    private  String[] hostName;
    //Holds a hostname pattern (ie, rule that begins with '.');'
    private  String hostPattern;
    //Holds string passed into the constructor.
    private  String ruleString;
    /**
     * Address mask constructor.
     * @param rule The rule string to process.
     * @throws ConfigException If the rule string is not valid.
     */
    private AddressMask( String rule)
    throws ConfigException
    {
        determineRuleType(rule);
        switch (ruleType)
        {
        case IPv4:
            processIpv4(rule);
            break;
            /*            case IPv6:
                processIPv6(rule);
                break;
             */
        case HOST:
            processHost(rule);
            break;
        case HOSTPATTERN:
            processHostPattern(rule);
            break;
        case ALLWILDCARD:
            processAllWilds(rule);
        }
        ruleString=rule;
    }
    /**
     * Try to determine what type of rule string this is. See
     * RuleType above for valid types.
     * @param ruleString The rule string to be examined.
     * @throws ConfigException If the rule type cannot be
     *         determined from the rule string.
     */
    private void  determineRuleType(String ruleString)
    throws ConfigException
    {
        //Rule ending with '.' is invalid'
        if(ruleString.endsWith("."))
        {
            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String message = getMessage(msgID);
            throw new ConfigException(msgID, message);
        }
        else if(ruleString.startsWith("."))
        {
            ruleType=RuleType.HOSTPATTERN;
        }
        else if(ruleString.startsWith("["))
        {
            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;
        }
        else
        {
            int wildCount=0;
            String[] s = ruleString.split("\\.", -1);
            //Try to figure out how many wildcards and if the rule is
            // 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("*"))
                {
                    wildCount++;
                    continue;
                }
                //Looks like an ipv4 address
                if(Character.isDigit(s[i].charAt(0)))
                {
                    ruleType=RuleType.IPv4;
                    break;
                }
            }
            //All wildcards (*.*.*.*)
            if(wildCount == s.length)
            {
                ruleType=RuleType.ALLWILDCARD;
            }
        }
    }
    /**
     * The rule string is an IPv4 rule. Build both the prefix
     * mask array and rule mask from the string.
     * @param rule The rule string containing the IPv4 rule.
     * @throws ConfigException If the rule string is not a valid
     *         IPv4 rule.
     */
    private void processIpv4(String rule)
    throws ConfigException {
        String[] s = rule.split("/", -1);
        ruleMask=new byte[IN4ADDRSZ];
        prefixMask=new byte[IN4ADDRSZ];
        prefixMask(processPrefix(s,IPV4MAXPREFIX));
        processIpv4Subnet((s.length == 0) ? rule : s[0]);
    }
    /**
     * The rule string is all wildcards. Set both address wildcard
     * bitmask and hostname wildcard array.
     * @param rule The rule string containing all wildcards.
     */
    private void processAllWilds(String rule)
    {
        String s[]=rule.split("\\.", -1);
        if(s.length == IN4ADDRSZ)
        {
            for(int i=0;i<IN4ADDRSZ;i++)
                wildCard.set(i);
        }
        hostName=rule.split("\\.", -1);
    }
    /**
     * Examine the rule string of a host pattern and set the
     * host pattern from the rule.
     * @param rule The rule string to examine.
     * @throws ConfigException If the rule string is not a valid
     *         host pattern rule.
     */
    private void processHostPattern(String rule)
    throws ConfigException
    {
        //quick check for invalid chars like " "
        String s[]=rule.split("^[0-9a-zA-z-.]+");
        if(s.length > 0)
        {
            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String message = getMessage(msgID);
            throw new ConfigException(msgID,  message);
        }
        hostPattern=rule;
    }
    /**
     * Examine rule string and build a hostname string array
     * of its parts.
     * @param rule The rule string.
     * @throws ConfigException If the rule string is not a valid
     *         host name.
     */
    private void processHost(String rule)
    throws ConfigException
    {
        //Note that '*' is valid in host rule
        String s[]=rule.split("^[0-9a-zA-z-.*]+");
        if(s.length > 0)
        {
            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String message = getMessage(msgID);
            throw new ConfigException(msgID, message);
        }
        hostName=rule.split("\\.", -1);
    }
    /**
     * Build the prefix mask of prefix len bits set in the array.
     * @param prefix The len of the prefix to use.
     */
    private void prefixMask(int prefix)
    {
        int i=0;
        for( i=0;prefix > 8 ; i++)
        {
            prefixMask[i] = (byte) 0xff;
            prefix -= 8;
        }
        prefixMask[i] = (byte) ((0xff) << (8 - prefix));
    }
    /**
     * Examine the subnet part of a rule string and build a
     * byte array representation of it.
     * @param subnet The subnet string part of the rule.
     * @throws ConfigException If the subnet string is not a valid
     *         IPv4 subnet string.
     */
    private void  processIpv4Subnet(String subnet)
    throws ConfigException {
        String[] s = subnet.split("\\.", -1);
        try {
            //Make sure we have four parts
            if(s.length != IN4ADDRSZ) {
                int id=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
                String message = getMessage(id);
                throw new ConfigException(id, message);
            }
            for(int i=0; i < IN4ADDRSZ; i++)
            {
                String quad=s[i].trim();
                if(quad.equals("*"))
                    wildCard.set(i) ; //see wildcard mark bitset
                else
                {
                    long val=Integer.parseInt(quad);
                    //must be between 0-255
                    if((val < 0) ||  (val > 0xff))
                    {
                        int id=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
                        String message = getMessage(id);
                        throw new ConfigException(id, message);
                    }
                    ruleMask[i] = (byte) (val & 0xff);
                }
            }
        } catch (NumberFormatException nfex)
        {
            int id=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String message = getMessage(id);
            throw new ConfigException(id, message);
        }
    }
    /**
     * Examine rule string for correct prefix usage.
     * @param s The string array with rule string add and prefix
     *          strings.
     * @param maxPrefix The max value the prefix can be.
     * @return The prefix integer value.
     * @throws ConfigException If the string array and prefix
     *         are not valid.
     */
    private int  processPrefix(String[] s, int maxPrefix)
    throws ConfigException {
        int prefix=maxPrefix;
        try {
            //can only have one prefix value and a subnet string
            if((s.length  < 1) || (s.length > 2) )
            {
                int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
                String message = getMessage(msgID);
                throw new ConfigException(msgID, message);
            }
            else  if(s.length == 2)
            {
                //can't have wildcard with a prefix
                if(s[0].indexOf('*') > -1)
                {
                    int msgID=MSGID_ADDRESSMASK_WILDCARD_DECODE_ERROR;
                    String message = getMessage(msgID);
                    throw new ConfigException(msgID, message);
                }
                prefix = Integer.parseInt(s[1]);
            }
            //must be between 0-maxprefix
            if((prefix < 0) || (prefix > maxPrefix))
            {
                int msgID=MSGID_ADDRESSMASK_PREFIX_DECODE_ERROR;
                String message = getMessage(msgID);
                throw new ConfigException(msgID, message);
            }
        }
        catch(NumberFormatException nfex)
        {
            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String msg = getMessage(msgID);
            throw new ConfigException(msgID,msg);
        }
        return prefix;
    }
    /**
     * Decodes the provided string as an address mask.
     *
     * @param  maskString  The string to decode as an address mask.
     *
     * @return  AddressMask  The address mask decoded from the
     *                       provided string.
     *
     * @throws  ConfigException  If the provided string cannot be
     *                           decoded as an address mask.
     */
    public static AddressMask decode(String maskString)
    throws ConfigException {
        return new AddressMask(maskString);
    }
    /**
     * Indicates whether provided address or hostname matches one of
     * the address masks in the provided array.
     *
     * @param remoteAddr The remote address byte array.
     * @param remoteName The remote host name string.
     * @param masks      An array of address masks to check.
     * @return <CODE>true</CODE> if the provided address or hostname
     *          does match one of the given address masks, or
     *         <CODE>false</CODE> if it does not.
     */
    public  static boolean maskListContains(byte[] remoteAddr,
            String remoteName,
            AddressMask[] masks)
    {
        for(int i=0; i < masks.length; i++)
        {
            if(masks[i].match(remoteAddr, remoteName))
                return true;
        }
        return false;
    }
    /**
     * Retrieves a string representation of this address mask.
     *
     * @return  A string representation of this address mask.
     */
    public String toString()
    {
        return new String(ruleString);
    }
    /**
     * Main match function that determines which rule-type match
     * function to use.
     * @param remoteAddr The remote client address byte array.
     * @param remoteName The remote client host name.
     * @return <CODE>true</CODE>if one of the match functions found
     *         a match or <CODE>false</CODE>if not.
     */
    private boolean match(byte[] remoteAddr, String remoteName)
    {
        boolean ret=false;
        switch(ruleType) {
        case IPv4:
            //this Address mask is an IPv4 rule
            ret=matchAddress(remoteAddr);
            break;
        case HOST:
            // HOST rule use hostname
            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);
            break;
        case ALLWILDCARD:
            //first try  ipv4 addr match, then hostname
            ret=matchAddress(remoteAddr);
            if(!ret)
                ret=matchHostName(remoteName);
            break;
        }
        return ret;
    }
    /**
     * Try to match remote host name string against the pattern rule.
     * @param remoteHostName The remote client host name.
     * @return <CODE>true</CODE>if the remote host name matches or
     *         <CODE>false</CODE>if not.
     */
    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;
    }
    /**
     * Try to match remote client host name against rule host name.
     * @param remoteHostName The remote host name string.
     * @return <CODE>true</CODE>if the remote client host name matches
     *         <CODE>false</CODE> if it does not.
     */
    private boolean matchHostName(String remoteHostName) {
        String[] s = remoteHostName.split("\\.", -1);
        if(s.length != hostName.length)
            return false;
        if(ruleType == RuleType.ALLWILDCARD)
            return true;
        for(int i=0;i<s.length;i++)
        {
            if(!hostName[i].equals("*")) //skip if wildcard
            {
                if(!s[i].equalsIgnoreCase(hostName[i]))
                    return false;
            }
        }
        return true;
    }
    /**
     * Try to match remote client address using prefix mask and
     * rule mask.
     * @param remoteMask The byte array with remote client address.
     * @return <CODE>true</CODE> if remote client address matches or
     *         <CODE>false</CODE>if not.
     */
    private boolean matchAddress(byte[] remoteMask)
    {
        if(prefixMask== null)
            return false;
        if(remoteMask.length != prefixMask.length)
            return false;
        if(ruleType  == RuleType.ALLWILDCARD)
            return true;
        for(int i=0;i < prefixMask.length; i++)
        {
            if(!wildCard.get(i))
            {
                if((ruleMask[i] & prefixMask[i]) !=
                    (remoteMask[i] & prefixMask[i]))
                    return false;
            }
        }
        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);
      }
  }
  /**
   * Indicates whether the provided address matches one of the address
   * masks in the provided array.
   *
   * @param  clientConnection  The client connection for which to make
   *                           the determination.
   * @param  masks             The set of address masks to check.
   *
   * @return  <CODE>true</CODE> if the provided address does match one
   *          or more of the given address masks, or
   *          <CODE>false</CODE> if it does not.
   */
  public static boolean maskListContains(
                             ClientConnection clientConnection,
                             AddressMask[] masks)
  {
    // NYI
    return false;
  }
  /**
   * Retrieves a string representation of this address mask.
   *
   * @return  A string representation of this address mask.
   */
  public String toString()
  {
    // NYI
    return null;
  }
     */
}
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java
New file
@@ -0,0 +1,275 @@
/*
 * 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 2006 Sun Microsystems, Inc.
 */
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.*;
public class TestAddressMask extends TypesTestCase {
    /* These are all valid rules -- should all pass. */
    @DataProvider(name = "validRules")
    public Object[][] validData() {
        return new Object[][] {
            { "129.34.55.67"},
            { "129.*.78.55"},
            {".central.sun.com"},
            {"foo.central.sun.com"},
            {"foo.*.sun.*"},
            {"128.*.*.*"},
            {"129.45.23.67/22"},
            {"128.33.23.21/32"},
            {"*.*.*.*"},
            {"129.45.67.34/0"},
            {"foo.com"},
            {"foo"}
        };
    }
 @DataProvider(name = "invalidRules")
  public Object[][] invalidData() {
    return new Object[][] {
         { "129.*.900.67" },
         { "129.67" },
         {"   "},
         {"129.56.78.90/2000"},
         {"677.777.AG.BC"},
         {"/34"},
         {"234.12.12.*/31"},
         {"234.12.12.90/"},
         {"129.34.56.78/-100"},
         {"129"},
         {"129.34.-90.67"},
         {"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/"}
    };
  }
 @DataProvider(name = "toStringRule")
 public Object[][] toStringData() {
     return new Object[][] {
         {"129.35.45.66/12"}
     };
 }
@Test(dataProvider = "validRules")
 public void testValidDecode(String mask)
 throws Exception {
     AddressMask.decode(mask);
 }
 @Test(expectedExceptions=ConfigException.class, dataProvider="invalidRules")
 public void testInvalidDecode(String mask)
 throws Exception {
     try {
         AddressMask.decode(mask);
     } catch (ConfigException e) {
         throw e;
     } catch (Exception e) {
         //MPD FIX this
         System.out.println(
                 "Invalid mask  <" + mask + "> threw wrong exception type.");
         throw e;
     }
     throw new RuntimeException(
             "Invalid mask <" + mask + "> did not throw an exception.");
 }
 @DataProvider(name = "matchRules")
 public Object[][] ruleMatchData() {
     return new Object[][] {
             {
                 //Rules
                 new String[] {
                         "129.56.*.22", //1
                         "*.domain.com", //2
                         "foo.example.com", //3
                         "126.67.89.90", //4
                         "90.89.78.67/30", //5
                         ".test.com", //6
                         "128.153.147.32/21",//7
                         "128.153.146.32/26",//8
                         "90.89.78.67/26"}, //9
                //Addresses
                new String[] {
                         "128.153.147.45", //rule 7
                         "128.153.146.60", //rule 8
                         "148.45.45.46",     //host
                         "129.56.78.22",    //rule 1
                         "148.45.45.47",    //host
                         "148.45.45.48",    //host
                         "90.89.78.65"},   //rule 5
              //Hostnames
              new String[]  {
                         "some.host.name", //addr
                         "some.host.name", //addr
                         "foo.example.com", //rule 3
                         "some.host.name", //addr
                         "foo.test.com",       //rule 6
                         "foo.domain.com", //rule 2
                         "some.host.name" //addr
                         }
             }
     };
 }
 @DataProvider(name = "noMatchRules")
 public Object[][] ruleNoMatchData() {
     return new Object[][] {
         {
             // Rule to not match
             new String[] {
                     "129.56.*.22", //1
                     "*.domain.com", //2
                     "foo.example.com", //3
                     "126.67.89.90", //4
                     "90.89.78.67/30", //5
                     ".test.com", //6
                     "128.153.147.32/21",//7
                     "128.153.146.32/26",//8
                     "90.89.78.67/26"}, //9
                     //Addresses
                     new String[] {
                              "128.153.140.45",
                              "128.153.143.255",
                              "148.45.45.46",
                              "126.56.78.22",
                              "148.45.45.47",
                              "148.45.45.48",
                              "90.89.78.128",
                              "148.45.45.49"},
                   //Hostnames
                   new String[]  {
                              "some.host.name",
                              "some.host.name",
                              "foo.examplee.com",
                              "some.host.name",
                              "foo.ttest.com",
                              "foo.domain.comm",
                              "some.host.name",
                              "f.e.c",
                              "foo.domain.cm"}
                  }
         };
     }
 @DataProvider(name = "matchWCRules")
 public Object[][] ruleMatchWCData() {
     return new Object[][] {
             {
                 //Rules
                 new String[] {
                         "*.*.*",
                         "*.*.*.*"},
                //Addresses
                new String[] {
                        "129.34.45.12",
                        "129.34.45.13"},
              //Hostnames
              new String[]  {
                         "some.host.name" ,
                         "some.host.name"}
             }
     };
 }
 @Test(dataProvider = "matchRules")
 public void testMatch(String[] rules, String[] addrs, String[]hostNames) {
     boolean ret=true;
     ret=match(rules,addrs,hostNames);
     assertTrue(ret);
 }
 @Test(dataProvider = "matchWCRules")
 public void testWildCardMatch(String[] rules, String[] addrs, String[]hostNames) {
     boolean ret=true;
     ret=match(rules,addrs,hostNames);
     assertTrue(ret);
 }
 @Test(dataProvider = "noMatchRules")
 public void testNoMatch(String[] rules, String[] addrs, String[] hostNames) {
     boolean ret=false;
     ret=match(rules,addrs,hostNames);
     assertFalse(ret);
 }
 @Test(dataProvider="toStringRule")
 public void testToString(String rule) {
     try {
         AddressMask m = AddressMask.decode(rule);
         assertEquals(rule, m.toString());
     } catch (ConfigException ce) {
         throw new RuntimeException(
                 "Invalid mask <" + rule + "> data should be all 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++) {
         if(!AddressMask.maskListContains(getAddress(addrs[j]),hostNames[j],m)) {
             ret=false;
             break;
         }
     }
     return ret;
 }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TypesTestCase.java
New file
@@ -0,0 +1,38 @@
/*
 * 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 2006 Sun Microsystems, Inc.
 */
package org.opends.server.types ;
import org.opends.server.DirectoryServerTestCase;
import org.testng.annotations.Test;
/**
 * An abstract class that all types  unit test should extend.
 */
@Test(groups = { "precommit, types" })
public abstract class TypesTestCase extends DirectoryServerTestCase
{}