Skip to content
Browse files

Replace sun.net.util.IPAddressUtil usage with own implementation

  • Loading branch information...
1 parent e2b2407 commit 213c1e3d234135a5d33e333079f662af2f8f823b @normanmaurer normanmaurer committed Nov 18, 2012
View
10 codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequest.java
@@ -17,7 +17,7 @@
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
-import sun.net.util.IPAddressUtil;
+import io.netty.util.IPUtil;
import java.net.IDN;
@@ -46,7 +46,7 @@ public SocksCmdRequest(CmdType cmdType, AddressType addressType, String host, in
}
switch (addressType) {
case IPv4:
- if (!IPAddressUtil.isIPv4LiteralAddress(host)) {
+ if (!IPUtil.isValidIPV4Address(host)) {
throw new IllegalArgumentException(host + " is not a valid IPv4 address");
}
break;
@@ -56,7 +56,7 @@ public SocksCmdRequest(CmdType cmdType, AddressType addressType, String host, in
}
break;
case IPv6:
- if (!IPAddressUtil.isIPv6LiteralAddress(host)) {
+ if (!IPUtil.isValidIP6Address(host)) {
throw new IllegalArgumentException(host + " is not a valid IPv6 address");
}
break;
@@ -116,7 +116,7 @@ public void encodeAsByteBuf(ByteBuf byteBuf) {
byteBuf.writeByte(addressType.getByteValue());
switch (addressType) {
case IPv4: {
- byteBuf.writeBytes(IPAddressUtil.textToNumericFormatV4(host));
+ byteBuf.writeBytes(IPUtil.createByteArrayFromIPAddressString(host));
byteBuf.writeShort(port);
break;
}
@@ -129,7 +129,7 @@ public void encodeAsByteBuf(ByteBuf byteBuf) {
}
case IPv6: {
- byteBuf.writeBytes(IPAddressUtil.textToNumericFormatV6(host));
+ byteBuf.writeBytes(IPUtil.createByteArrayFromIPAddressString(host));
byteBuf.writeShort(port);
break;
}
View
453 common/src/main/java/io/netty/util/IPUtil.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2012 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.util;
+
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+/**
+ * Utility functions for IPV6 operations.
+ *
+ * see Inet6Util from the Apache Harmony project
+ *
+ * see org.apache.harmony.util.Inet6Util
+ */
+public final class IPUtil {
+
+ private IPUtil() {
+ // make this class a an utility class non-instantiable
+ }
+
+ /**
+ * Creates an byte[] based on an ipAddressString. No error handling is
+ * performed here.
+ */
+ public static byte[] createByteArrayFromIPAddressString(
+ String ipAddressString) {
+
+ if (isValidIPV4Address(ipAddressString)) {
+ StringTokenizer tokenizer = new StringTokenizer(ipAddressString,
+ ".");
+ String token;
+ int tempInt;
+ byte[] byteAddress = new byte[4];
+ for (int i = 0; i < 4; i++) {
+ token = tokenizer.nextToken();
+ tempInt = Integer.parseInt(token);
+ byteAddress[i] = (byte) tempInt;
+ }
+
+ return byteAddress;
+ }
+
+ if (ipAddressString.charAt(0) == '[') {
+ ipAddressString = ipAddressString.substring(1, ipAddressString
+ .length() - 1);
+ }
+
+ StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ":.",
+ true);
+ ArrayList<String> hexStrings = new ArrayList<String>();
+ ArrayList<String> decStrings = new ArrayList<String>();
+ String token = "";
+ String prevToken = "";
+ int doubleColonIndex = -1; // If a double colon exists, we need to
+ // insert 0s.
+
+ // Go through the tokens, including the seperators ':' and '.'
+ // When we hit a : or . the previous token will be added to either
+ // the hex list or decimal list. In the case where we hit a ::
+ // we will save the index of the hexStrings so we can add zeros
+ // in to fill out the string
+ while (tokenizer.hasMoreTokens()) {
+ prevToken = token;
+ token = tokenizer.nextToken();
+
+ if (":".equals(token)) {
+ if (":".equals(prevToken)) {
+ doubleColonIndex = hexStrings.size();
+ } else if (!prevToken.isEmpty()) {
+ hexStrings.add(prevToken);
+ }
+ } else if (".".equals(token)) {
+ decStrings.add(prevToken);
+ }
+ }
+
+ if (":".equals(prevToken)) {
+ if (":".equals(token)) {
+ doubleColonIndex = hexStrings.size();
+ } else {
+ hexStrings.add(token);
+ }
+ } else if (".".equals(prevToken)) {
+ decStrings.add(token);
+ }
+
+ // figure out how many hexStrings we should have
+ // also check if it is a IPv4 address
+ int hexStringsLength = 8;
+
+ // If we have an IPv4 address tagged on at the end, subtract
+ // 4 bytes, or 2 hex words from the total
+ if (!decStrings.isEmpty()) {
+ hexStringsLength -= 2;
+ }
+
+ // if we hit a double Colon add the appropriate hex strings
+ if (doubleColonIndex != -1) {
+ int numberToInsert = hexStringsLength - hexStrings.size();
+ for (int i = 0; i < numberToInsert; i++) {
+ hexStrings.add(doubleColonIndex, "0");
+ }
+ }
+
+ byte[] ipByteArray = new byte[16];
+
+ // Finally convert these strings to bytes...
+ for (int i = 0; i < hexStrings.size(); i++) {
+ convertToBytes(hexStrings.get(i), ipByteArray, i * 2);
+ }
+
+ // Now if there are any decimal values, we know where they go...
+ for (int i = 0; i < decStrings.size(); i++) {
+ ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings
+ .get(i)) & 255);
+ }
+
+ // now check to see if this guy is actually and IPv4 address
+ // an ipV4 address is ::FFFF:d.d.d.d
+ boolean ipV4 = true;
+ for (int i = 0; i < 10; i++) {
+ if (ipByteArray[i] != 0) {
+ ipV4 = false;
+ break;
+ }
+ }
+
+ if (ipByteArray[10] != -1 || ipByteArray[11] != -1) {
+ ipV4 = false;
+ }
+
+ if (ipV4) {
+ byte[] ipv4ByteArray = new byte[4];
+ System.arraycopy(ipByteArray, 12, ipv4ByteArray, 0, 4);
+ return ipv4ByteArray;
+ }
+
+ return ipByteArray;
+
+ }
+
+ /** Converts a 4 character hex word into a 2 byte word equivalent */
+ private static void convertToBytes(String hexWord, byte[] ipByteArray,
+ int byteIndex) {
+
+ int hexWordLength = hexWord.length();
+ int hexWordIndex = 0;
+ ipByteArray[byteIndex] = 0;
+ ipByteArray[byteIndex + 1] = 0;
+ int charValue;
+
+ // high order 4 bits of first byte
+ if (hexWordLength > 3) {
+ charValue = getIntValue(hexWord.charAt(hexWordIndex++));
+ ipByteArray[byteIndex] |= charValue << 4;
+ }
+
+ // low order 4 bits of the first byte
+ if (hexWordLength > 2) {
+ charValue = getIntValue(hexWord.charAt(hexWordIndex++));
+ ipByteArray[byteIndex] |= charValue;
+ }
+
+ // high order 4 bits of second byte
+ if (hexWordLength > 1) {
+ charValue = getIntValue(hexWord.charAt(hexWordIndex++));
+ ipByteArray[byteIndex + 1] |= charValue << 4;
+ }
+
+ // low order 4 bits of the first byte
+ charValue = getIntValue(hexWord.charAt(hexWordIndex));
+ ipByteArray[byteIndex + 1] |= charValue & 15;
+ }
+
+ static int getIntValue(char c) {
+
+ switch (c) {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ }
+
+ c = Character.toLowerCase(c);
+ switch (c) {
+ case 'a':
+ return 10;
+ case 'b':
+ return 11;
+ case 'c':
+ return 12;
+ case 'd':
+ return 13;
+ case 'e':
+ return 14;
+ case 'f':
+ return 15;
+ }
+ return 0;
+ }
+
+ public static boolean isValidIP6Address(String ipAddress) {
+ int length = ipAddress.length();
+ boolean doubleColon = false;
+ int numberOfColons = 0;
+ int numberOfPeriods = 0;
+ int numberOfPercent = 0;
+ StringBuilder word = new StringBuilder();
+ char c = 0;
+ char prevChar;
+ int offset = 0; // offset for [] ip addresses
+
+ if (length < 2) {
+ return false;
+ }
+
+ for (int i = 0; i < length; i++) {
+ prevChar = c;
+ c = ipAddress.charAt(i);
+ switch (c) {
+
+ // case for an open bracket [x:x:x:...x]
+ case '[':
+ if (i != 0) {
+ return false; // must be first character
+ }
+ if (ipAddress.charAt(length - 1) != ']') {
+ return false; // must have a close ]
+ }
+ offset = 1;
+ if (length < 4) {
+ return false;
+ }
+ break;
+
+ // case for a closed bracket at end of IP [x:x:x:...x]
+ case ']':
+ if (i != length - 1) {
+ return false; // must be last charcter
+ }
+ if (ipAddress.charAt(0) != '[') {
+ return false; // must have a open [
+ }
+ break;
+
+ // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d
+ case '.':
+ numberOfPeriods++;
+ if (numberOfPeriods > 3) {
+ return false;
+ }
+ if (!isValidIP4Word(word.toString())) {
+ return false;
+ }
+ if (numberOfColons != 6 && !doubleColon) {
+ return false;
+ }
+ // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an
+ // IPv4 ending, otherwise 7 :'s is bad
+ if (numberOfColons == 7 && ipAddress.charAt(offset) != ':'
+ && ipAddress.charAt(1 + offset) != ':') {
+ return false;
+ }
+ word.delete(0, word.length());
+ break;
+
+ case ':':
+ // FIX "IP6 mechanism syntax #ip6-bad1"
+ // An IPV6 address cannot start with a single ":".
+ // Either it can starti with "::" or with a number.
+ if (i == offset && (ipAddress.length() <= i || ipAddress.charAt(i + 1) != ':')) {
+ return false;
+ }
+ // END FIX "IP6 mechanism syntax #ip6-bad1"
+ numberOfColons++;
+ if (numberOfColons > 7) {
+ return false;
+ }
+ if (numberOfPeriods > 0) {
+ return false;
+ }
+ if (prevChar == ':') {
+ if (doubleColon) {
+ return false;
+ }
+ doubleColon = true;
+ }
+ word.delete(0, word.length());
+ break;
+ case '%':
+ if (numberOfColons == 0) {
+ return false;
+ }
+ numberOfPercent++;
+
+ // validate that the stuff after the % is valid
+ if (i + 1 >= length) {
+ // in this case the percent is there but no number is
+ // available
+ return false;
+ }
+ try {
+ Integer.parseInt(ipAddress.substring(i + 1));
+ } catch (NumberFormatException e) {
+ // right now we just support an integer after the % so if
+ // this is not
+ // what is there then return
+ return false;
+ }
+ break;
+
+ default:
+ if (numberOfPercent == 0) {
+ if (word != null && word.length() > 3) {
+ return false;
+ }
+ if (!isValidHexChar(c)) {
+ return false;
+ }
+ }
+ word.append(c);
+ }
+ }
+
+ // Check if we have an IPv4 ending
+ if (numberOfPeriods > 0) {
+ if (numberOfPeriods != 3 || !isValidIP4Word(word.toString())) {
+ return false;
+ }
+ } else {
+ // If we're at then end and we haven't had 7 colons then there is a
+ // problem unless we encountered a doubleColon
+ if (numberOfColons != 7 && !doubleColon) {
+ return false;
+ }
+
+ // If we have an empty word at the end, it means we ended in either
+ // a : or a .
+ // If we did not end in :: then this is invalid
+ if (numberOfPercent == 0) {
+ if (word.length() == 0 && ipAddress.charAt(length - 1 - offset) == ':'
+ && ipAddress.charAt(length - 2 - offset) != ':') {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean isValidIP4Word(String word) {
+ char c;
+ if (word.length() < 1 || word.length() > 3) {
+ return false;
+ }
+ for (int i = 0; i < word.length(); i++) {
+ c = word.charAt(i);
+ if (!(c >= '0' && c <= '9')) {
+ return false;
+ }
+ }
+ if (Integer.parseInt(word) > 255) {
+ return false;
+ }
+ return true;
+ }
+
+ static boolean isValidHexChar(char c) {
+ return c >= '0' && c <= '9' || c >= 'A' && c <= 'F'
+ || c >= 'a' && c <= 'f';
+ }
+
+ /**
+ * Takes a string and parses it to see if it is a valid IPV4 address.
+ *
+ * @return true, if the string represents an IPV4 address in dotted
+ * notation, false otherwise
+ */
+ public static boolean isValidIPV4Address(String value) {
+
+ int periods = 0;
+ int i;
+ int length = value.length();
+
+ if (length > 15) {
+ return false;
+ }
+ char c;
+ StringBuilder word = new StringBuilder();
+ for (i = 0; i < length; i++) {
+ c = value.charAt(i);
+ if (c == '.') {
+ periods++;
+ if (periods > 3) {
+ return false;
+ }
+ if (word.length() == 0) {
+ return false;
+ }
+ if (Integer.parseInt(word.toString()) > 255) {
+ return false;
+ }
+ word.delete(0, word.length());
+ } else if (!Character.isDigit(c)) {
+ return false;
+ } else {
+ if (word.length() > 2) {
+ return false;
+ }
+ word.append(c);
+ }
+ }
+
+ if (word.length() == 0 || Integer.parseInt(word.toString()) > 255) {
+ return false;
+ }
+ if (periods != 3) {
+ return false;
+ }
+ return true;
+ }
+
+}
View
1 pom.xml
@@ -280,7 +280,6 @@
<ignores>
<ignore>sun.misc.Unsafe</ignore>
<ignore>sun.misc.Cleaner</ignore>
- <ignore>sun.net.util.IPAddressUtil</ignore>
<ignore>java.util.zip.Deflater</ignore>

0 comments on commit 213c1e3

Please sign in to comment.
Something went wrong with that request. Please try again.