001/* 002 * Copyright 2015-2018 the original author or authors 003 * 004 * This software is licensed under the Apache License, Version 2.0, 005 * the GNU Lesser General Public License version 2 or later ("LGPL") 006 * and the WTFPL. 007 * You may choose either license to govern your use of this software only 008 * upon the condition that you accept all of the terms of either 009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL. 010 */ 011package org.minidns.util; 012 013import java.net.Inet4Address; 014import java.net.Inet6Address; 015import java.net.InetAddress; 016import java.net.UnknownHostException; 017import java.util.regex.Pattern; 018 019import org.minidns.dnsname.DnsName; 020 021public class InetAddressUtil { 022 023 public static Inet4Address ipv4From(CharSequence cs) { 024 InetAddress inetAddress; 025 try { 026 inetAddress = InetAddress.getByName(cs.toString()); 027 } catch (UnknownHostException e) { 028 throw new IllegalArgumentException(e); 029 } 030 if (inetAddress instanceof Inet4Address) { 031 return (Inet4Address) inetAddress; 032 } 033 throw new IllegalArgumentException(); 034 } 035 036 public static Inet6Address ipv6From(CharSequence cs) { 037 InetAddress inetAddress; 038 try { 039 inetAddress = InetAddress.getByName(cs.toString()); 040 } catch (UnknownHostException e) { 041 throw new IllegalArgumentException(e); 042 } 043 if (inetAddress instanceof Inet6Address) { 044 return (Inet6Address) inetAddress; 045 } 046 throw new IllegalArgumentException(); 047 } 048 049 // IPV4_REGEX from http://stackoverflow.com/a/46168/194894 by Kevin Wong (http://stackoverflow.com/users/4792/kevin-wong) licensed under 050 // CC BY-SA 3.0. 051 private final static Pattern IPV4_PATTERN = Pattern.compile("\\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z"); 052 053 public static boolean isIpV4Address(CharSequence address) { 054 if (address == null) { 055 return false; 056 } 057 return IPV4_PATTERN.matcher(address).matches(); 058 } 059 060 // IPv6 Regular Expression from http://stackoverflow.com/a/17871737/194894 by David M. Syzdek 061 // (http://stackoverflow.com/users/903194/david-m-syzdek) licensed under CC BY-SA 3.0. 062 private final static Pattern IPV6_PATTERN = Pattern.compile( 063 "(([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]))"); 064 065 public static boolean isIpV6Address(CharSequence address) { 066 if (address == null) { 067 return false; 068 } 069 return IPV6_PATTERN.matcher(address).matches(); 070 } 071 072 public static boolean isIpAddress(CharSequence address) { 073 return isIpV6Address(address) || isIpV4Address(address); 074 } 075 076 public static DnsName reverseIpAddressOf(Inet6Address inet6Address) { 077 final String ipAddress = inet6Address.getHostAddress(); 078 final String[] ipAddressParts = ipAddress.split(":"); 079 080 String[] parts = new String[32]; 081 int currentPartNum = 0; 082 for (int i = ipAddressParts.length - 1; i >= 0; i--) { 083 final String currentPart = ipAddressParts[i]; 084 final int missingPlaces = 4 - currentPart.length(); 085 for (int j = 0; j < missingPlaces; j++) { 086 parts[currentPartNum++] = "0"; 087 } 088 for (int j = 0; j < currentPart.length(); j++) { 089 parts[currentPartNum++] = Character.toString(currentPart.charAt(j)); 090 } 091 } 092 093 return DnsName.from(parts); 094 } 095 096 public static DnsName reverseIpAddressOf(Inet4Address inet4Address) { 097 final String[] ipAddressParts = inet4Address.getHostAddress().split("\\."); 098 assert(ipAddressParts.length == 4); 099 100 return DnsName.from(ipAddressParts); 101 } 102}