package mapreduce.nat;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import job.Utilities;
/**
* 关于ip操作的工具类
*
* @author hjb
*
*/
public class IPV6Util {
public static BigInteger ipv6ToBytesToBigInteger(String ipv6) {
byte[] ret = new byte[17];
ret[0] = 0;
int ib = 16;
boolean comFlag = false;// ipv4混合模式标记
if (ipv6.startsWith(":"))// 去掉开头的冒号
ipv6 = ipv6.substring(1);
if (ipv6.endsWith("::")) {
ipv6 = ipv6+"0";
}
String groups[] = ipv6.split(":");
for (int ig = groups.length - 1; ig > -1; ig--) {// 反向扫描
if (groups[ig].contains(".")) {
// 出现ipv4混合模式
byte[] temp = ipv4ToBytes(groups[ig]);
ret[ib--] = temp[4];
ret[ib--] = temp[3];
ret[ib--] = temp[2];
ret[ib--] = temp[1];
comFlag = true;
} else if ("".equals(groups[ig])) {
// 出现零长度压缩,计算缺少的组数
int zlg = 9 - (groups.length + (comFlag ? 1 : 0));
while (zlg-- > 0) {// 将这些组置0
ret[ib--] = 0;
ret[ib--] = 0;
}
} else {
int temp = Integer.parseInt(groups[ig], 16);
ret[ib--] = (byte) temp;
ret[ib--] = (byte) (temp >> 8);
}
}
return new BigInteger(ret);
}
private static byte[] ipv4ToBytes(String ipv4) {
byte[] ret = new byte[5];
ret[0] = 0;
// 先找到IP地址字符串中.的位置
int position1 = ipv4.indexOf(".");
int position2 = ipv4.indexOf(".", position1 + 1);
int position3 = ipv4.indexOf(".", position2 + 1);
// 将每个.之间的字符串转换成整型
ret[1] = (byte) Integer.parseInt(ipv4.substring(0, position1));
ret[2] = (byte) Integer.parseInt(ipv4.substring(position1 + 1,
position2));
ret[3] = (byte) Integer.parseInt(ipv4.substring(position2 + 1,
position3));
ret[4] = (byte) Integer.parseInt(ipv4.substring(position3 + 1));
return ret;
}
public static BigInteger[] convertList(String ip) {
BigInteger[] arr = new BigInteger[2];
String tmpIp = ip.substring(0, ip.indexOf("/"));
if (Utilities.isValidIP(tmpIp)) {
Long[] ipToLong = Utilities.getIpLong(ip);
arr[0] = BigInteger.valueOf(ipToLong[0]);
arr[1] = BigInteger.valueOf(ipToLong[1]);
} else if (Utilities.isValidIPv6(tmpIp)) {
arr = IPV6Util.getIpv6Long(ip);
}
return arr;
}
public static BigInteger convertToBigInteger(String ip) throws Exception {
BigInteger tmpBig = null;
if (Utilities.isValidIP(ip)) {
Long ipToLong1 = Utilities.ipToLong(ip);
tmpBig = BigInteger.valueOf(ipToLong1);
} else if (Utilities.isValidIPv6(ip)) {
tmpBig = ipv6ToBytesToBigInteger(ip);
}
return tmpBig;
}
// 将ipv6地址转换为二进制分段(为了创造ip段写的)
public static String fenduan(String ipv6) throws UnknownHostException {
ipv6 = completIpv6(ipv6);
String[] split = ipv6.split(":");
String tmpString = "";
if (split.length == 8) {
for (int i = 0; i < split.length; i++) {
String str = Long.toBinaryString(Long.valueOf(split[i], 16));
tmpString += str + " ";
}
}
return tmpString;
}
public static String fenduan4(String ipv6) throws UnknownHostException {
String[] split = ipv6.split("\\.");
String tmpString = "";
if (split.length == 4) {
for (int i = 0; i < split.length; i++) {
String str = Long.toBinaryString(Long.valueOf(split[i]));
tmpString += str + " ";
}
}
return tmpString;
}
public static boolean isInRange(String ip, String cidr) {
String[] ips = ip.split("\\.");
int ipAddr = (Integer.parseInt(ips[0]) << 24) | (Integer.parseInt(ips[1]) << 16)
| (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]);
int type = Integer.parseInt(cidr.replaceAll(".*/", ""));
int mask = 0xFFFFFFFF << (32 - type);
String cidrIp = cidr.replaceAll("/.*", "");
String[] cidrIps = cidrIp.split("\\.");
int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24) | (Integer.parseInt(cidrIps[1]) << 16)
| (Integer.parseInt(cidrIps[2]) << 8) | Integer.parseInt(cidrIps[3]);
return (ipAddr & mask) == (cidrIpAddr & mask);
}
public static boolean isBelongIpv6(String ipv6, String ipv6area) throws Exception {
// ipv6 = completIpv6(ipv6);
int suffix = 0;
if (ipv6area.contains("/")) {
suffix = Integer.parseInt(ipv6area.substring(ipv6area.indexOf("/") + 1));
ipv6area = ipv6area.substring(0, ipv6area.indexOf("/"));
}
BigInteger ipv6Big = ipv6ToBytesToBigInteger(ipv6);
BigInteger ipv6areaBig = ipv6ToBytesToBigInteger(ipv6area);
BigDecimal ss = new BigDecimal(2);
BigDecimal pow = ss.pow(128);
BigInteger aa = new BigInteger(pow.toString());
String str = aa.toString(2).replaceAll("0", "1").substring(1);
BigInteger bb = new BigInteger(str, 2);
String str1 = bb.shiftLeft(128 - suffix).toString(2);
String str2 = str1.substring(128 - suffix, str1.length());
BigInteger mask = new BigInteger(str2, 2);
return ipv6Big.and(mask).compareTo(ipv6areaBig.and(mask)) == 0 ? true : false;
}
/**
* 将ipv6每段补齐4位
*
* @return
* @throws UnknownHostException
*/
public static String completIpv6(String ipv6) throws UnknownHostException {
StringBuffer str = new StringBuffer();
if (isValidIPv6(ipv6)) {
String ip = InetAddress.getByName(ipv6).toString().replace("/", "");
String[] info = ip.split(":");
for (int i = 0; i < info.length; i++) {
switch (info[i].length()) {
case 1:
info[i] = "000" + info[i];
break;
case 2:
info[i] = "00" + info[i];
break;
case 3:
info[i] = "0" + info[i];
break;
default:
break;
}
if (i < 7) {
str.append(info[i] + ":");
} else {
str.append(info[i]);
}
}
}
return str.toString();
}
/**
* 将ipv6地址转换为10进制
*
* @throws Exception
*/
public static BigInteger ipv6ToBigInt(String ipv6) throws Exception {
BigInteger numip = BigInteger.ZERO;
String completIpv6 = completIpv6(ipv6);
// String completIpv6 = ipv6;
if (completIpv6.endsWith(":") && completIpv6.contains(".")) {
completIpv6 = completIpv6.replace(":", "");
}
if (isIpV4OrV6(completIpv6) == 4) {
numip = BigInteger.valueOf(Utilities.ipToLong(completIpv6));
} else if (isIpV4OrV6(completIpv6) == 6) {
String[] split = completIpv6.split(":");
for (int i = 0; i < split.length; i++) {
numip = numip
.add(BigInteger.valueOf(Long.parseLong(split[i], 16)).shiftLeft(16 * (split.length - i - 1)));
}
}
return numip;
}
/**
* 将整数形式的ipv6地址转换为字符串形式
*
*/
public static String int2ipv6(BigInteger big) {
String str = "";
BigInteger ff = BigInteger.valueOf(0xffff);
for (int i = 0; i < 8; i++) {
str = big.and(ff).toString(16) + ":" + str;
big = big.shiftRight(16);
}
str = str.substring(0, str.length() - 1);
return str.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
}
/**
* 将ipv6地址压缩为最简模式 IPv6简写规范: 1) 每个IPv6地址段起始的0可以被省略; 2) 如果一段为4个零,可以简写为一个0 3)
* 如果有连续的多个段全为0,则可以使用::表示 注:一个地址段中只能有一个::出现,不可以出现两个及以上
*/
public static String ipv6Shorted(String ipv6) {
if (isValidIPv6(ipv6)) {
ipv6 = ipv6.substring(0, ipv6.length() - 1);
}
return ipv6.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
}
/**
* ipv4或ipv6字符串
*
* @return 4 :ipv4, 6:ipv6, 0:地址不对
* @throws Exception
*/
public static int isIpV4OrV6(String ipAdress) throws Exception {
InetAddress address = InetAddress.getByName(ipAdress);
if (address instanceof Inet4Address)
return 4;
else if (address instanceof Inet6Address)
return 6;
return 0;
}
/**
* IPv4转换为IPv6
*/
public static String ipv4ToIpv6(String ipv6) {
String[] octets = ipv6.split("\\.");
byte[] octetBytes = new byte[4];
for (int i = 0; i < 4; ++i) {
octetBytes[i] = (byte) Integer.parseInt(octets[i]);
}
byte ipv4asIpV6addr[] = new byte[16];
ipv4asIpV6addr[10] = (byte) 0xff;
ipv4asIpV6addr[11] = (byte) 0xff;
ipv4asIpV6addr[12] = octetBytes[0];
ipv4asIpV6addr[13] = octetBytes[1];
ipv4asIpV6addr[14] = octetBytes[2];
ipv4asIpV6addr[15] = octetBytes[3];
return "::" + (ipv4asIpV6addr[12] & 0xff) + "." + (ipv4asIpV6addr[13] & 0xff) + "."
+ (ipv4asIpV6addr[14] & 0xff) + "." + (ipv4asIpV6addr[15] & 0xff);
}
/**
* 判断ipv6是否合法
*
* @param ip
* @return
*/
public static boolean isValidIPv6(String ip) {
if (ip == null || ip.trim().length() == 0) {
return false;
}
String t = "^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$";
Pattern p = Pattern.compile(t);
Matcher macher = p.matcher(ip);
return macher.matches();
}
/**
* 判断IPv6是否属于某个IPv6段
*
* @throws Exception
*/
public static boolean isBelongIpv6List(String ipv6, List<String> ipv6area) throws Exception {
for (String iparea : ipv6area) {
if (isBelongIpv6(ipv6, iparea)) {
return true;
}
}
return false;
}
/**
* 判断ip是否属于某个网段
*
* @param ip
* @return
*/
public static boolean isBelongIpareaData(BigInteger ipv6, List<BigInteger[]> data) {
for (BigInteger[] tmp : data) {
if ((ipv6.compareTo(tmp[0]) == 1 || ipv6.compareTo(tmp[0]) == 0)
&& (ipv6.compareTo(tmp[1]) == -1 || ipv6.compareTo(tmp[1]) == 0)) {
return true;
}
}
return false;
}
public static BigInteger[] getIpv6Long(String iparea) {
try {
iparea = iparea.trim();
BigInteger[] info = new BigInteger[2];
// 判断是否是具体IP
int index = iparea.indexOf("/");
if (index < 0) {
info[0] = ipv6ToBytesToBigInteger(iparea);
info[1] = ipv6ToBytesToBigInteger(iparea);
if (info[0] == null || info[1] == null) {
return null;
}
return info;
}
String ipinfo = iparea.substring(0, index);
Integer count = Integer.valueOf(iparea.substring(index + 1));
BigInteger small = BigInteger.ZERO;
BigInteger big = BigInteger.ZERO;
StringBuffer mask = new StringBuffer();
for (int i = 0; i < 128; i++) {
if (i<count) {
mask.append("1");
}else {
mask.append("0");
}
}
String string = new BigInteger(mask.toString(),2).toString(10);
// for (int i = 0; i < 128 - count; i++) {
// double pow = Math.pow(2d, Double.valueOf(Integer.valueOf(i).toString()));
// BigInteger tmp = BigDecimal.valueOf(pow).toBigInteger();
// small = small.add(tmp);
// }
// big = BigDecimal.valueOf(Math.pow(2d, Double.valueOf("128"))).toBigInteger().subtract(small)
// .subtract(BigInteger.valueOf(1));
info[0] = areaIp.and(big);
info[1] = areaIp.or(small);
BigInteger areaIp = ipv6ToBytesToBigInteger(ipinfo);
info[0] = areaIp.and(new BigInteger(string));
String re = mask.substring(mask.lastIndexOf("1")+1).replace("0", "1");
info[1] = areaIp.or(new BigInteger(new BigInteger(re.toString(),2).toString(10)).subtract(BigInteger.valueOf(1)));
if (info[0] == null || info[1] == null) {
return null;
}
return info;
} catch (Exception e) {
return null;
}
}
/**
* 给定两个初始ip和结束ip,,计算求得CIDR IP段
*
* @param startIp
* @param endIp
* @return
*/
public static List<String> range2cidrlist(String startIp, String endIp) {
long start = ipToLong(startIp);
long end = ipToLong(endIp);
ArrayList<String> pairs = new ArrayList<String>();
while (end >= start) {
byte maxsize = 32;
while (maxsize > 0) {
long mask = CIDR2MASK[maxsize - 1];
long maskedBase = start & mask;
if (maskedBase != start) {
break;
}
maxsize--;
}
double x = Math.log(end - start + 1) / Math.log(2);
byte maxdiff = (byte) (32 - Math.floor(x));
if (maxsize < maxdiff) {
maxsize = maxdiff;
}
String ip = Utilities.longToIP(start);
pairs.add(ip + "/" + maxsize);
start += Math.pow(2, (32 - maxsize));
}
return pairs;
}
public static final int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 0xFFF80000,
0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800, 0xFFFFFC00,
0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
0xFFFFFFFF };
private static long ipToLong(String strIP) {
long[] ip = new long[4];
String[] ipSec = strIP.split("\\.");
for (int k = 0; k < 4; k++) {
ip[k] = Long.valueOf(ipSec[k]);
}
return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
}
}