package com.seculayer.seql.util; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; public class IPUtil { public static long ip2long(String ip){ String[] arr = ip.split("\\."); if(arr.length != 4){return 0;} long[] larr = new long[4]; for(int i = 0; i < arr.length; i++){ try{ larr[i] = Long.parseLong(arr[i]); } catch(Exception e){return 0;} } return (larr[3]) | (larr[2] << 8) | (larr[1] << 16) | (larr[0] << 24); } public static String long2ip(long ip) { String res = ""; for(int i = 0; i < 4; i++){ long tmp = ip & 255; res = tmp + res; if(i != 3){res = "." + res;} ip = ip >> 8; } return res; } public static String ip2longString(String ip, int maxLen, String s) { String result = String.valueOf(ip2long(ip)); for (int i = 0; i < (maxLen-result.length()); i++){ result = s + result; } return result; } public static String extractDomain(String domain) { if(domain==null || domain.length()==0) return domain; //0. Cut Parameter String cutDomain = domain.replaceAll("(\\?.+)|([hHtTpPsS]{4,5}://)", ""); //1. IP is return if(cutDomain.replaceAll("[0-9.]", "").length()==0) return cutDomain; String[] arr = cutDomain.split("\\."); //2. if domain is .com/.net if(cutDomain.endsWith(".com")||cutDomain.endsWith(".net")) { return arr[arr.length-2] + "." + arr[arr.length-1]; } //3. if .(dot) is one if(arr.length==2) { return cutDomain; } //4. if .(dot) is two if(arr.length==3) { return arr[arr.length-2] + "." + arr[arr.length-1]; } //5. if .(dot) is three more if(arr.length>=4) { return arr[arr.length-3] + "." + arr[arr.length-2] + "." + arr[arr.length-1]; } return cutDomain; } private static final int N_SHORTS = 8; private static final Pattern IPV4_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); private static final Pattern IPV6_PATTERN = Pattern.compile("^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$"); /** * ip를 BigInteger로 형변환 * ip를 byte화한 후 BigInteger로 변환 * @param addr * @return ip를 BigInteger로 형변환 * @throws UnknownHostException */ public static BigInteger ipToBigInteger(String addr) { InetAddress ia = null; byte[] bytes = {}; try { ia = InetAddress.getByName(addr); bytes = ia.getAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } return new BigInteger(1, bytes); } /** * BigInteger를 ip로 형변환 * @param bInt * @return BigInteger를 ip로 형변환 * @throws UnknownHostException */ public static String BigIntegerToIp(BigInteger bInt) { byte[] bytes = bInt.toByteArray(); int bytesLeg = bytes.length; int ipLeg = (bInt.compareTo(new BigInteger("4294967295")) != 1) ? 4 : 16; byte[] setBytes = new byte[ipLeg]; for(int i=0; i<ipLeg; i++) { setBytes[i] = 0; } if((bytesLeg == 5 && ipLeg == 4) || (bytesLeg == 17 && ipLeg == 16)) { System.arraycopy(bytes, 1, setBytes, 0, bytesLeg-1); } else { System.arraycopy(bytes, 0, setBytes, ipLeg-bytesLeg, bytesLeg); } InetAddress ia = null; try { ia = InetAddress.getByAddress(setBytes); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ia.toString().replaceFirst("/", ""); } public static String BigIntegerToStandardIp(BigInteger bInt) { return ipToStandardIp(BigIntegerToIp(bInt)); } public static boolean checkIPformat(String str) { if (str == null) return false; if(IPV4_PATTERN.matcher(str).matches()){ return true; } else { if(IPV6_PATTERN.matcher(str).matches()){ return true; } else { return false; } } } public static boolean isIPv4(String ip) { if (ip == null) return false; if(IPV4_PATTERN.matcher(ip).matches()){ return true; } return false; } public static boolean isIPv6(String ip) { if (ip == null) return false; if(IPV6_PATTERN.matcher(ip).matches()){ return true; } return false; } /** * 사설 아이피 여부 검증 * @param ip * @return true : is private ip, false : is Not private ip. */ //**** ipv6용 수정해야함. public static boolean isPrivateIP(String ip) { BigInteger ipl = IPUtil.ipToBigInteger(ip); //ipv4용 if(ipl.compareTo(IPUtil.ipToBigInteger("167772160")) != -1 && ipl.compareTo(IPUtil.ipToBigInteger("184549375")) != 1) return true; if(ipl.compareTo(IPUtil.ipToBigInteger("2886729728")) != -1 && ipl.compareTo(IPUtil.ipToBigInteger("2887778303")) != 1) return true; if(ipl.compareTo(IPUtil.ipToBigInteger("3232235520")) != -1 && ipl.compareTo(IPUtil.ipToBigInteger("3232301055")) != 1) return true; //ipv6용 //empty. return false; } /** * binary를 BigInteger로 형변환 * @param bInt, ip형식을 구분해주는 String형 ipType * @return binary를 BigInteger로 형변환 * @throws UnknownHostException */ public static List<Map<String,Object>> BinaryToBigInteger(List<Map<String,Object>> list, String [] columnList) { List<Map<String,Object>> cgList = new ArrayList<Map<String,Object>>(); for(Map<String,Object> data : list){ for(int i = 0; i < columnList.length; i++){ if(data.get(columnList[i]).getClass().getName().equals("java.math.BigInteger")) continue; data.put(columnList[i], new BigInteger(1, (byte[])data.get(columnList[i]))); } cgList.add(data); } return cgList; } /** * binary를 BigInteger로 형변환 * @param bInt, ip형식을 구분해주는 String형 ipType * @return binary를 BigInteger로 형변환 * @throws UnknownHostException */ public static BigInteger BinaryToBigInteger(Map<String,Object> map, String column) { BigInteger data = null; if(map.get(column).getClass().getName().equals("java.math.BigInteger")) return (BigInteger) map.get("column"); data = new BigInteger(1, (byte[])map.get(column)); return data; } /** * Create an IPv6 address from its String representation. For example "1234:5678:abcd:0000:9876:3210:ffff:ffff" or "2001::ff" or even * "::". IPv4-Mapped IPv6 addresses such as "::ffff:123.456.123.456" are also supported. * * @param string string representation * @return IPUtil */ public static String ipToStandardIp(String ip) { if (ip == null) return ""; if(!ip.contains(":")) return ip; else if(!checkIPformat(ip)) return ip; final String withoutIPv4MappedNotation = rewriteIPv4MappedNotation(ip); final String longNotation = expandShortNotation(withoutIPv4MappedNotation); final long[] longs = tryParseStringArrayIntoLongArray(ip, longNotation); validateLongs(longs); return StringUtil.get(mergeLongArrayIntoIPv6Address(longs)); } private static long[] tryParseStringArrayIntoLongArray(String string, String longNotation) { try { return parseStringArrayIntoLongArray(longNotation.split(":")); } catch (NumberFormatException e) { throw new IllegalArgumentException("can not parse [" + string + "]"); } } private static String mergeLongArrayIntoIPv6Address(long[] longs) { long high = 0L; long low = 0L; for (int i = 0; i < longs.length; i++) { if (inHighRange(i)) high |= (longs[i] << ((4 - i - 1) * 16)); else low |= (longs[i] << ((4 - i - 1) * 16)); } /** * Returns a string representation of the IPv6 address. It will use shorthand notation and special notation for IPv4-mapped IPv6 * addresses whenever possible. * */ if (isIPv4Mapped(high, low)) return toIPv4MappedAddressString(high, low); else return toShortHandNotationString(high, low); } private static boolean inHighRange(int shortNumber) { return shortNumber >= 0 && shortNumber < 4; } private static void validateLongs(long[] longs) { if (longs.length != 8) throw new IllegalArgumentException("an IPv6 address should contain 8 shorts [" + Arrays.toString(longs) + "]"); for (long l : longs) { if (l < 0) throw new IllegalArgumentException("each element should be positive [" + Arrays.toString(longs) + "]"); if (l > 0xFFFF) throw new IllegalArgumentException("each element should be less than 0xFFFF [" + Arrays.toString(longs) + "]"); } } private static long[] parseStringArrayIntoLongArray(String[] strings) { final long[] longs = new long[strings.length]; for (int i = 0; i < strings.length; i++) { longs[i] = Long.parseLong(strings[i], 16); } return longs; } private static final Pattern DOT_DELIM = Pattern.compile("\\."); /** * Replaces a w.x.y.z substring at the end of the given string with corresponding hexadecimal notation. This is useful in case the * string was using IPv4-Mapped address notation. */ private static String rewriteIPv4MappedNotation(String string) { if (!string.contains(".")) { return string; } else { int lastColon = string.lastIndexOf(":"); String firstPart = string.substring(0, lastColon + 1); String mappedIPv4Part = string.substring(lastColon + 1); if (mappedIPv4Part.contains(".")) { String[] dotSplits = DOT_DELIM.split(mappedIPv4Part); if (dotSplits.length != 4) throw new IllegalArgumentException(String.format("can not parse [%s]", string)); StringBuilder rewrittenString = new StringBuilder(); rewrittenString.append(firstPart); int byteZero = Integer.parseInt(dotSplits[0]); int byteOne = Integer.parseInt(dotSplits[1]); int byteTwo = Integer.parseInt(dotSplits[2]); int byteThree = Integer.parseInt(dotSplits[3]); rewrittenString.append(String.format("%02x", byteZero)); rewrittenString.append(String.format("%02x", byteOne)); rewrittenString.append(":"); rewrittenString.append(String.format("%02x", byteTwo)); rewrittenString.append(String.format("%02x", byteThree)); return rewrittenString.toString(); }else{ throw new IllegalArgumentException(String.format("can not parse [%s]", string)); } } } private static String expandShortNotation(String string) { if (!string.contains("::")) { return string; } else if (string.equals("::")) { return generateZeroes(8); } else { final int numberOfColons = countOccurrences(string, ':'); if (string.startsWith("::")) return string.replace("::", generateZeroes((7 + 2) - numberOfColons)); else if (string.endsWith("::")) return string.replace("::", ":" + generateZeroes((7 + 2) - numberOfColons)); else return string.replace("::", ":" + generateZeroes((7 + 2 - 1) - numberOfColons)); } } private static int countOccurrences(String haystack, char needle) { int count = 0; for (int i = 0; i < haystack.length(); i++) { if (haystack.charAt(i) == needle) { count++; } } return count; } private static String generateZeroes(int number) { final StringBuilder builder = new StringBuilder(); for (int i = 0; i < number; i++) { builder.append("0:"); } return builder.toString(); } /** * Returns true if the address is an IPv4-mapped IPv6 address. In these addresses, the first 80 bits are zero, the next 16 bits are one, * and the remaining 32 bits are the IPv4 address. * * @return true if the address is an IPv4-mapped IPv6 addresses. */ private static boolean isIPv4Mapped(long highBits, long lowBits) { return highBits == 0 // 64 zero bits && (lowBits & 0xFFFF000000000000L) == 0 // 16 more zero bits && (lowBits & 0x0000FFFF00000000L) == 0x0000FFFF00000000L; // 16 one bits and the remainder is the IPv4 address } private static String toIPv4MappedAddressString(long highBits, long lowBits) { int byteZero = (int) ((lowBits & 0x00000000FF000000L) >> 24); int byteOne = (int) ((lowBits & 0x0000000000FF0000L) >> 16); int byteTwo = (int) ((lowBits & 0x000000000000FF00L) >> 8); int byteThree = (int) ((lowBits & 0x00000000000000FFL)); final StringBuilder result = new StringBuilder("::ffff:"); result.append(byteZero).append(".").append(byteOne).append(".").append(byteTwo).append(".").append(byteThree); return result.toString(); } private static String toShortHandNotationString(long high, long low) { final String[] strings = toArrayOfShortStrings(high, low); final StringBuilder result = new StringBuilder(); int[] shortHandNotationPositionAndLength = startAndLengthOfLongestRunOfZeroes(high, low); int shortHandNotationPosition = shortHandNotationPositionAndLength[0]; int shortHandNotationLength = shortHandNotationPositionAndLength[1]; boolean useShortHandNotation = shortHandNotationLength > 1; // RFC5952 recommends not to use shorthand notation for a single zero for (int i = 0; i < strings.length; i++) { if (useShortHandNotation && i == shortHandNotationPosition) { if (i == 0) result.append("::"); else result.append(":"); } else if (!(i > shortHandNotationPosition && i < shortHandNotationPosition + shortHandNotationLength)) { result.append(strings[i]); if (i < N_SHORTS - 1) result.append(":"); } } return result.toString().toLowerCase(); } private static String[] toArrayOfShortStrings(long high, long low) { final short[] shorts = toShortArray(high, low); final String[] strings = new String[shorts.length]; for (int i = 0; i < shorts.length; i++) { strings[i] = String.format("%x", shorts[i]); } return strings; } private static int[] startAndLengthOfLongestRunOfZeroes(long high, long low) { int longestConsecutiveZeroes = 0; int longestConsecutiveZeroesPos = -1; short[] shorts = toShortArray(high, low); for (int pos = 0; pos < shorts.length; pos++) { int consecutiveZeroesAtCurrentPos = countConsecutiveZeroes(shorts, pos); if (consecutiveZeroesAtCurrentPos > longestConsecutiveZeroes) { longestConsecutiveZeroes = consecutiveZeroesAtCurrentPos; longestConsecutiveZeroesPos = pos; } } return new int[]{longestConsecutiveZeroesPos, longestConsecutiveZeroes}; } private static int countConsecutiveZeroes(short[] shorts, int offset) { int count = 0; for (int i = offset; i < shorts.length && shorts[i] == 0; i++) { count++; } return count; } private static short[] toShortArray(long high, long low) { final short[] shorts = new short[N_SHORTS]; for (int i = 0; i < N_SHORTS; i++) { if (inHighRange(i)) shorts[i] = (short) (((high << i * 16) >>> 16 * (N_SHORTS - 1)) & 0xFFFF); else shorts[i] = (short) (((low << i * 16) >>> 16 * (N_SHORTS - 1)) & 0xFFFF); } return shorts; } public static void main(String[] args) { //System.out.println(">>> Long=["+IPUtil.ip2long("152.99.78.4")+"], IP=["+IPUtil.long2ip(Long.parseLong("2556644869"))+"]"); // String ip = ipToStandardIp("fe80::ec4:7aff:fe32:878"); String ip = ipToStandardIp("2041:0000:130F:0000:0000:07C0:853A:140B"); System.out.println(">>> ip=>" + ip); // BigInteger bint = ipToBigInteger(ip); // System.out.println(">>> bint=>" + bint); BigInteger bint = new BigInteger("42872795166820420802676092457212056587"); String ips = BigIntegerToStandardIp(bint); System.out.println(">>> ips=>" + ips); byte[] byteVal = bint.toByteArray(); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); map.put("sip", byteVal); list.add(map); List<Map<String,Object>> list2 = BinaryToBigInteger(list, new String[]{"sip"}); for(Map<String,Object> m:list2) { System.out.println("===================>" + IPUtil.BigIntegerToStandardIp((BigInteger)m.get("sip"))); } } }