All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.net.CIDR Maven / Gradle / Ivy

package panda.net;

import java.io.Serializable;
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 panda.lang.Exceptions;
import panda.lang.Objects;
import panda.lang.Strings;

public class CIDR implements Cloneable, Serializable {
	private static final long serialVersionUID = 1L;

	public static final String MATCH_ALL_V4 = "0.0.0.0/0";
	public static final String MATCH_ALL_V4_ALT = "allv4";
	public static final String MATCH_ALL_V6 = "[::]/0";
	public static final String MATCH_ALL_V6_ALT = "allv6";
	public static final String MATCH_ALL = "all";
	public static final String MATCH_NONE = "none";

	private static final int MASK_ZERO = 0;
	private static final int MASK_MAX = 128;
	private static final int MASK_IPV6 = 128;
	private static final int MASK_IPV4 = 32;
	
	private InetAddress addr;
	private int mask;

	public CIDR() {
		setMatchNone();
	}

	public CIDR(String cidr) {
		setCIDR(cidr);
	}

	public CIDR(CIDR cidr) {
		addr = cidr.addr;
		mask = cidr.mask;
	}

	public static boolean isCIDR(String cidr) {
		try {
			new CIDR(cidr);
			return true;
		}
		catch (Exception e) {
			return false;
		}
	}

	public static List split(String cidrs) {
		String[] ss = Strings.split(cidrs);
		List cs = new ArrayList(ss.length);
		
		for (String s : ss) {
			cs.add(new CIDR(s));
		}
		return cs;
	}


	public boolean isV6() {
		return addr instanceof Inet6Address;
	}

	public boolean isV4() {
		return addr instanceof Inet4Address;
	}

	public boolean isMatchNone() {
		return addr == null && mask == MASK_MAX;
	}

	public boolean isMatchAll() {
		return addr == null && mask == MASK_ZERO;
	}

	public void setMatchNone() {
		addr = null;
		mask = MASK_MAX;
	}

	public void setMatchAll() {
		mask = MASK_ZERO;
		addr = null;
	}

	private InetAddress maskAddress(InetAddress ia, int mask) {
		byte[] bs = ia.getAddress();

		int i = mask / 8;
		if (i < bs.length) {
			byte cmask = (byte)(0xFF << (8 - (mask % 8)));
			bs[i] &= cmask;
			
			for (++i ; i < bs.length; i++) {
				bs[i] = 0;
			}
		
			try {
				return InetAddress.getByAddress(bs);
			}
			catch (UnknownHostException e) {
				throw Exceptions.wrapThrow(e);
			}
		}

		return ia;
	}


	public boolean include(String cidr) {
		return include(new CIDR(cidr));
	}

	// does this CIDR subnet include the supplied address/subnet
	public boolean include(CIDR cidr) {
		return include(cidr.addr);
	}
	
	public boolean include(InetAddress ia) {
		if (isMatchAll()) {
			return true;
		}
		if (isMatchNone()) {
			return false;
		}
		

		InetAddress ma = maskAddress(ia, mask);

		return addr.equals(ma);
	}

	/**
	 * set CIDR
	 * @param cidr a CIDR string
	 * @throws IllegalArgumentException if aCIDR is not a correct CIDR format string
	 */
	public void setCIDR(String cidr) {
		if (MATCH_ALL.equalsIgnoreCase(cidr)) {
			setMatchAll();
			return;
		}
		if (MATCH_NONE.equalsIgnoreCase(cidr)) {
			setMatchNone();
			return;
		}
		if (MATCH_ALL_V4_ALT.equalsIgnoreCase(cidr)) {
			setCIDR(MATCH_ALL_V4);
			return;
		}
		if (MATCH_ALL_V6_ALT.equalsIgnoreCase(cidr)) {
			setCIDR(MATCH_ALL_V6);
			return;
		}

		String addr = cidr;
		int mask = -1;
		int sep = cidr.indexOf('/');
		if (sep >= 0) {
			addr = cidr.substring(0, sep);
			try {
				mask = Integer.parseInt(cidr.substring(sep + 1));
			}
			catch (NumberFormatException e) {
				throw new IllegalArgumentException("Illegal CIDR: " + cidr, e);
			}
		}

		byte[] bs = IPs.toNetAddress(addr);
		if (bs == null) {
			throw new IllegalArgumentException("Illegal CIDR: " + cidr);
		}

		InetAddress ia;
		try {
			ia = InetAddress.getByAddress(bs);
		}
		catch (UnknownHostException e) {
			throw new IllegalArgumentException("Illegal CIDR: " + cidr, e);
		}

		if (IPs.isIPv6(ia)) {
			mask = MASK_IPV6;
			if (sep >= 0) {
				try {
					mask = Integer.parseInt(cidr.substring(sep + 1));
				}
				catch (NumberFormatException e) {
					throw new IllegalArgumentException("Illegal CIDR: " + cidr, e);
				}
			}

			if (mask < 0 || mask > MASK_IPV6) {
				throw new IllegalArgumentException("Illegal CIDR: " + cidr);
			}

			this.mask = mask;
			this.addr = maskAddress(ia, mask);
			return;
		}

		if (IPs.isIPv4(ia)) {
			mask = MASK_IPV4;
			if (sep >= 0) {
				try {
					mask = Integer.parseInt(cidr.substring(sep + 1));
				}
				catch (NumberFormatException e) {
					throw new IllegalArgumentException("Illegal CIDR: " + cidr, e);
				}
			}

			if (mask < 0 || mask > MASK_IPV4) {
				throw new IllegalArgumentException("Illegal CIDR: " + cidr);
			}

			this.mask = mask;
			this.addr = maskAddress(ia, mask);
			return;
		}
	}

	public String toString() {
		if (isMatchAll()) {
			return MATCH_ALL;
		}
		if (isMatchNone()) {
			return MATCH_NONE;
		}
		return addr.getHostAddress() + "/" + mask;
	}

	public String toAddress() {
		return addr == null ? null : addr.getHostAddress();
	}

	/** 
	 */
	@Override
	public CIDR clone() {
		return new CIDR(this);
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return Objects.hash(addr, mask);
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;

		CIDR rhs = (CIDR)obj;
		return Objects.equalsBuilder()
				.append(mask, rhs.mask)
				.append(addr, rhs.addr)
				.isEquals();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy