diff --git a/src/main/java/com/alibaba/druid/support/http/util/IPAddress.java b/src/main/java/com/alibaba/druid/support/http/util/IPAddress.java
new file mode 100644
index 0000000000..5bc0189259
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/support/http/util/IPAddress.java
@@ -0,0 +1,296 @@
+package com.alibaba.druid.support.http.util;
+
+import java.util.NoSuchElementException;
+
+/**
+ * This class represents an IP address represented by an 32 bits integer value. Dotted-decimal notation divides the
+ * 32-bit Internet address into four 8-bit (byte) fields and specifies the value of each field independently as a
+ * decimal number with the fields separated by dots :
+ *
+ *
+ * 10010001 . 00001010 . 00100010 . 00000011
+ * 145
+ * 10 34
+ * 3
+ *
+ *
+ * -> 145.10.34.3
+ *
+ *
+ * IP address are classified into three classes :
+ *
+ * class A:
+ *
+ *
+ * bit# 0 1
+ *
+ * 7 8
+ *
+ * 31
+ *
+ * +--+-------------------+------------------------------+
+ *
+ * |0 |
+ * |
+ *
+ *
+ * |
+ *
+ * +--+-------------------+------------------------------+
+ *
+ * <-- network number --> <------- host number -------->
+ *
+ *
+ * class B:
+ *
+ *
+ * bit# 0 2
+ *
+ * 15 16
+ *
+ * 31
+ *
+ * +--+-------------------------+------------------------+
+ *
+ * |10|
+ * |
+ *
+ *
+ * |
+ *
+ * +--+-------------------------+------------------------+
+ *
+ * <----- network number -----> <---- host number ----->
+ *
+ *
+ * class C:
+ *
+ *
+ * bit# 0 3
+ *
+ *
+ * 23 24
+ *
+ * 31
+ *
+ * +---+-----------------------------+-------------------+
+ *
+ * |110|
+ *
+ * |
+ * |
+ *
+ * +---+-----------------------------+-------------------+
+ *
+ * <------- network number --------> <-- host number -->
+ *
+ *
+ *
+ * @author Marcel Dullaart
+ * @version 1.0
+ */
+public class IPAddress implements Cloneable {
+
+ /** IP address */
+ protected int ipAddress = 0;
+
+ // -------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @param ip String representation of the IP address. The format of the ip's string representation must follow the
+ * decimal-dotted notation xxx.xxx.xxx.xxx.
+ * @exception InvalidIPAddressException Throws this exception when the specified string doesn't represent a valid IP
+ * address.
+ */
+ public IPAddress(String ipAddressStr) {
+ ipAddress = parseIPAddress(ipAddressStr);
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @param ip Binary representation of the IP address.
+ */
+ public IPAddress(int address){
+ ipAddress = address;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Return the integer representation of the IP address.
+ *
+ * @return The IP address.
+ */
+ public final int getIPAddress() {
+ return ipAddress;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Return the string representation of the IP Address following the common decimal-dotted notation xxx.xxx.xxx.xxx.
+ *
+ * @return Return the string representation of the IP address.
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ int temp;
+
+ temp = ipAddress & 0x000000FF;
+ result.append(temp);
+ result.append(".");
+
+ temp = (ipAddress >> 8) & 0x000000FF;
+ result.append(temp);
+ result.append(".");
+
+ temp = (ipAddress >> 16) & 0x000000FF;
+ result.append(temp);
+ result.append(".");
+
+ temp = (ipAddress >> 24) & 0x000000FF;
+ result.append(temp);
+
+ return result.toString();
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Check if the IP address is belongs to a Class A IP address.
+ *
+ * @return Return true if the encapsulated IP address belongs to a class A IP address, otherwise
+ * returne false.
+ */
+ public final boolean isClassA() {
+ return (ipAddress & 0x00000001) == 0;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Check if the IP address is belongs to a Class B IP address.
+ *
+ * @return Return true if the encapsulated IP address belongs to a class B IP address, otherwise
+ * returne false.
+ */
+ public final boolean isClassB() {
+ return (ipAddress & 0x00000003) == 1;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Check if the IP address is belongs to a Class C IP address.
+ *
+ * @return Return true if the encapsulated IP address belongs to a class C IP address, otherwise
+ * returne false.
+ */
+ public final boolean isClassC() {
+ return (ipAddress & 0x00000007) == 3;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Convert a decimal-dotted notation representation of an IP address into an 32 bits interger value.
+ *
+ * @param ipAddressStr Decimal-dotted notation (xxx.xxx.xxx.xxx) of the IP address.
+ * @return Return the 32 bits integer representation of the IP address.
+ * @exception InvalidIPAddressException Throws this exception if the specified IP address is not compliant to the
+ * decimal-dotted notation xxx.xxx.xxx.xxx.
+ */
+ protected int parseIPAddress(String ipAddressStr) {
+ int result = 0;
+
+ if (ipAddressStr == null) {
+ throw new IllegalArgumentException();
+ }
+
+ try {
+ String tmp = ipAddressStr;
+
+ // get the 3 first numbers
+ int offset = 0;
+ for (int i = 0; i < 3; i++) {
+
+ // get the position of the first dot
+ int index = tmp.indexOf(".");
+
+ // if there is not a dot then the ip string representation is
+ // not compliant to the decimal-dotted notation.
+ if (index != -1) {
+
+ // get the number before the dot and convert it into
+ // an integer.
+ String numberStr = tmp.substring(0, index);
+ int number = Integer.parseInt(numberStr);
+ if ((number < 0) || (number > 255)) {
+ throw new IllegalArgumentException("Invalid IP Address [" + ipAddressStr + "]");
+ }
+
+ result += number << offset;
+ offset += 8;
+ tmp = tmp.substring(index + 1);
+ } else {
+ throw new IllegalArgumentException("Invalid IP Address [" + ipAddressStr + "]");
+ }
+ }
+
+ // the remaining part of the string should be the last number.
+ if (tmp.length() > 0) {
+ int number = Integer.parseInt(tmp);
+ if ((number < 0) || (number > 255)) {
+ throw new IllegalArgumentException("Invalid IP Address [" + ipAddressStr + "]");
+ }
+
+ result += number << offset;
+ ipAddress = result;
+ } else {
+ throw new IllegalArgumentException("Invalid IP Address [" + ipAddressStr + "]");
+ }
+ } catch (NoSuchElementException ex) {
+ throw new IllegalArgumentException("Invalid IP Address [" + ipAddressStr + "]");
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException("Invalid IP Address [" + ipAddressStr + "]");
+ }
+
+ return result;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Compare the specified IP address to the encapsulated one.
+ *
+ * @param another The IP address to be compared.
+ * @return Return true if the encapsulated IP address is the same as the specified one, otherwise
+ * return false.
+ */
+ public boolean equals(Object another) {
+ if (another instanceof IPAddress) {
+ return ipAddress == ((IPAddress) another).ipAddress;
+ }
+ return false;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Clone the encapsulated IP address.
+ *
+ * @return Return a new object representing the encapsulated IP address.
+ */
+ public Object clone() {
+ return new IPAddress(ipAddress);
+ }
+
+ public static void main(String[] args) {
+
+ System.out.println(Integer.toBinaryString(255));
+
+ // try {//"192.168.1.1"
+ // IPAddress ip = new IPAddress(Integer.toBinaryString(3));
+ // System.out.println(ip.getIPAddress());
+ // System.out.println(ip.toString());
+ // System.out.println(ip.parseIPAddress("192.168.4.4"));
+ // } catch (InvalidIPAddressException e) {
+ // e.printStackTrace();
+ // }
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/support/http/util/IPRange.java b/src/main/java/com/alibaba/druid/support/http/util/IPRange.java
new file mode 100644
index 0000000000..1f04cd638f
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/support/http/util/IPRange.java
@@ -0,0 +1,305 @@
+package com.alibaba.druid.support.http.util;
+
+/**
+ * This class represents an IP Range, which are represented by an IP address and and a subnet mask. The standards
+ * describing modern routing protocols often refer to the extended-network-prefix-length rather than the subnet mask.
+ * The prefix length is equal to the number of contiguous one-bits in the traditional subnet mask. This means that
+ * specifying the network address 130.5.5.25 with a subnet mask of 255.255.255.0 can also be expressed as 130.5.5.25/24.
+ * The / notation is more compact and easier to understand than writing out the mask in its traditional
+ * dotted-decimal format.
+ *
+ *
+ * 130.5.5.25
+ * 10000010 . 00000101 . 00000101 . 00011001
+ * 255.255.255.0
+ * 11111111 . 11111111 . 11111111 . 00000000
+ *
+ * <--extended-network-prefix -->
+ * or
+ * 130.5.5.25/24
+ * 10000010 . 00000101 . 00000101 . 00011001
+ *
+ * This class supports both standards : the extended network prefix and the subnet mask.
+ *
+ * @author Marcel Dullaart
+ * @version 1.0
+ * @see IPAddress
+ */
+public class IPRange {
+
+ /** IP address */
+ private IPAddress ipAddress = null;
+
+ /** IP subnet mask */
+ private IPAddress ipSubnetMask = null;
+
+ /** extended network prefix */
+ private int extendedNetworkPrefix = 0;
+
+ // -------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @param ip String representation of the IP address. The two following formats are supported :
+ * xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx/xx <- extended network prefix
+ * @exception InvalidIPRangeException Throws this exception when the specified string doesn't represent a valid IP
+ * address.
+ */
+ public IPRange(String range){
+ parseRange(range);
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @param ipAddress Reference to the IP address number
+ * @param subnetMask Reference to the subnet mask
+ * @exception InvalidIPRangeException Throws this exception when the combination of the IP address and the subnet
+ * mask does not define a valid IP range.
+ * @exception InvalidIPAddressException Throws this exception if the specified IP address or subnet mask do ne
+ * define a valid IP number.
+ */
+ public IPRange(IPAddress ipAddress, IPAddress subnetMask){
+ if ((ipAddress == null) || (subnetMask == null)) {
+ throw new IllegalArgumentException();
+ }
+
+ this.ipAddress = ipAddress;
+ this.ipSubnetMask = subnetMask;
+
+ extendedNetworkPrefix = computeNetworkPrefixFromMask(subnetMask);
+ if (extendedNetworkPrefix == -1) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @param ipAddress The reference on the IP address.
+ * @param extendedNetworkPrefix The extended network prefix (0-32).
+ */
+ public IPRange(IPAddress ipAddress, int extendedNetworkPrefix){
+ if (ipAddress == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if ((extendedNetworkPrefix < 0) || (extendedNetworkPrefix > 32)) {
+ throw new IllegalArgumentException();
+ }
+
+ this.ipAddress = ipAddress;
+ this.extendedNetworkPrefix = extendedNetworkPrefix;
+ this.ipSubnetMask = computeMaskFromNetworkPrefix(extendedNetworkPrefix);
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Return the encapsulated IP address.
+ *
+ * @return The IP address.
+ */
+ public final IPAddress getIPAddress() {
+ return ipAddress;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Return the encapsulated subnet mask
+ *
+ * @return The IP range's subnet mask.
+ */
+ public final IPAddress getIPSubnetMask() {
+ return ipSubnetMask;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Return the extended extended network prefix.
+ *
+ * @return Return the extended network prefix.
+ */
+ public final int getExtendedNetworkPrefix() {
+ return extendedNetworkPrefix;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Convert the IP Range into a string representation.
+ *
+ * @return Return the string representation of the IP Address following the common format xxx.xxx.xxx.xxx/xx (IP
+ * address/extended network prefixs).
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer(ipAddress.toString());
+ result.append("/");
+ result.append(extendedNetworkPrefix);
+
+ return result.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + extendedNetworkPrefix;
+ result = prime * result + ((ipAddress == null) ? 0 : ipAddress.hashCode());
+ result = prime * result + ((ipSubnetMask == null) ? 0 : ipSubnetMask.hashCode());
+ return result;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Compare the specified IP range to the encapsulated one.
+ *
+ * @param another The IP range to be compared.
+ * @return Return true if the encapsulated IP range is the same as the specified one, otherwise return
+ * false.
+ */
+ public boolean equals(Object another) {
+ if (another instanceof IPRange) {
+ IPRange range = (IPRange) another;
+
+ return (ipAddress.equals(range.getIPAddress()) && (extendedNetworkPrefix == range.extendedNetworkPrefix));
+ }
+ return false;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Parse the IP range string representation.
+ *
+ * @param range String representation of the IP range.
+ * @exception InvalidIPRangeException Throws this exception if the specified range is not a valid IP network range.
+ */
+ protected void parseRange(String range) {
+ if (range == null) {
+ throw new IllegalArgumentException("Invalid IP range");
+ }
+
+ int index = range.indexOf("/");
+ String subnetStr = null;
+ if (index == -1) {
+ ipAddress = new IPAddress(range);
+ } else {
+ ipAddress = new IPAddress(range.substring(0, index));
+ subnetStr = range.substring(index + 1);
+ }
+
+ // try to convert the remaining part of the range into a decimal
+ // value.
+ try {
+ if (subnetStr != null) {
+ extendedNetworkPrefix = Integer.parseInt(subnetStr);
+ if ((extendedNetworkPrefix < 0) || (extendedNetworkPrefix > 32)) {
+ throw new IllegalArgumentException("Invalid IP range [" + range + "]");
+ }
+ ipSubnetMask = computeMaskFromNetworkPrefix(extendedNetworkPrefix);
+ }
+ } catch (NumberFormatException ex) {
+
+ // the remaining part is not a valid decimal value.
+ // Check if it's a decimal-dotted notation.
+ ipSubnetMask = new IPAddress(subnetStr);
+
+ // create the corresponding subnet decimal
+ extendedNetworkPrefix = computeNetworkPrefixFromMask(ipSubnetMask);
+ if (extendedNetworkPrefix == -1) {
+ throw new IllegalArgumentException("Invalid IP range [" + range + "]");
+ }
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Compute the extended network prefix from the IP subnet mask.
+ *
+ * @param mask Reference to the subnet mask IP number.
+ * @return Return the extended network prefix. Return -1 if the specified mask cannot be converted into a extended
+ * prefix network.
+ */
+ private int computeNetworkPrefixFromMask(IPAddress mask) {
+
+ int result = 0;
+ int tmp = mask.getIPAddress();
+
+ while ((tmp & 0x00000001) == 0x00000001) {
+ result++;
+ tmp = tmp >>> 1;
+ }
+
+ if (tmp != 0) {
+ return -1;
+ }
+
+ return result;
+ }
+
+ public static String toDecimalString(String inBinaryIpAddress) {
+ String decimalip = new String();
+ String[] binary = new String[4];
+
+ for (int i = 0, c = 0; i < 32; i = i + 8, c++) {
+ binary[c] = inBinaryIpAddress.substring(i, i + 8);
+ int octet = Integer.parseInt(binary[c], 2);
+ decimalip = decimalip + Integer.toString(octet);
+ if (c < 3) {
+ decimalip = decimalip + ".";
+ }
+ }
+ return decimalip;
+ }
+
+ // -------------------------------------------------------------------------
+ /**
+ * Convert a extended network prefix integer into an IP number.
+ *
+ * @param prefix The network prefix number.
+ * @return Return the IP number corresponding to the extended network prefix.
+ */
+ private IPAddress computeMaskFromNetworkPrefix(int prefix) {
+
+ /*
+ * int subnet = 0; for (int i=0; itrue if the specified IP address is in the encapsulated IP range, otherwise return
+ * false.
+ */
+ public boolean isIPAddressInRange(IPAddress address) {
+ if (ipSubnetMask == null) {
+ return this.ipAddress.equals(address);
+ }
+
+ int result1 = address.getIPAddress() & ipSubnetMask.getIPAddress();
+ int result2 = ipAddress.getIPAddress() & ipSubnetMask.getIPAddress();
+
+ return result1 == result2;
+ }
+
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/support/http/util/IPRangeTest.java b/src/test/java/com/alibaba/druid/bvt/support/http/util/IPRangeTest.java
new file mode 100644
index 0000000000..983f12ca7a
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/support/http/util/IPRangeTest.java
@@ -0,0 +1,69 @@
+package com.alibaba.druid.bvt.support.http.util;
+
+import junit.framework.TestCase;
+
+import com.alibaba.druid.support.http.util.IPAddress;
+import com.alibaba.druid.support.http.util.IPRange;
+
+public class IPRangeTest extends TestCase {
+
+ public void test_ipRange_0() throws Exception {
+ IPRange rang = new IPRange("128.242.127.0/24");
+
+ assertEquals("128.242.127.0", rang.getIPAddress().toString());
+ assertEquals("255.255.255.0", rang.getIPSubnetMask().toString());
+
+ assertTrue(rang.isIPAddressInRange(new IPAddress("128.242.127.2")));
+
+ assertFalse(rang.isIPAddressInRange(new IPAddress("128.242.126.2")));
+
+ }
+
+ public void test_ipRange_1() throws Exception {
+ IPRange rang = new IPRange("128.242.127.0/30");
+
+ assertEquals("128.242.127.0", rang.getIPAddress().toString());
+ assertEquals("255.255.255.252", rang.getIPSubnetMask().toString());
+
+ assertTrue(rang.isIPAddressInRange(new IPAddress("128.242.127.0")));
+ assertTrue(rang.isIPAddressInRange(new IPAddress("128.242.127.1")));
+ assertTrue(rang.isIPAddressInRange(new IPAddress("128.242.127.2")));
+ assertTrue(rang.isIPAddressInRange(new IPAddress("128.242.127.3")));
+
+ assertFalse(rang.isIPAddressInRange(new IPAddress("128.242.127.4")));
+
+ }
+
+ public void test_ipRange_2() throws Exception {
+ IPRange rang = new IPRange("10.16.200.0/24");
+
+ assertTrue(rang.isIPAddressInRange(new IPAddress("10.16.200.0")));
+ assertTrue(rang.isIPAddressInRange(new IPAddress("10.16.200.255")));
+
+ }
+
+ public void test_ipRange_3() throws Exception {
+ IPRange rang = new IPRange("0.0.0.0/0");
+ assertTrue(rang.isIPAddressInRange(new IPAddress("2.16.200.0")));
+
+ }
+
+ public void test_ipRange_4() throws Exception {
+ IPRange rang = new IPRange("1.1.1.1/0");
+
+ assertTrue(rang.isIPAddressInRange(new IPAddress("2.16.200.0")));
+ }
+
+ public void test_ipRange_5() throws Exception {
+ IPRange rang = new IPRange("1.1.1.1");
+
+ assertTrue(rang.isIPAddressInRange(new IPAddress("1.1.1.1")));
+ }
+
+ public void test_ipRange_6() throws Exception {
+ IPRange rang = new IPRange("128.242.127.3");
+
+ assertTrue(rang.isIPAddressInRange(new IPAddress("128.242.127.3")));
+ assertFalse(rang.isIPAddressInRange(new IPAddress("128.242.127.4")));
+ }
+}