/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.geofence.core.model; import org.geoserver.geofence.core.model.util.SubnetV4Utils; import java.io.Serializable; import java.net.Inet4Address; import java.net.InetAddress; import javax.persistence.Embeddable; import javax.xml.bind.annotation.XmlRootElement; /** * * @author ETj (etj at geo-solutions.it) */ @XmlRootElement(name = "IPAddressRange") @Embeddable public class IPAddressRange implements Serializable { /** * The lower 64 bits. * For IPv4, only the lower 32 are used. */ private Long low; /** * The higher 64 bits. * For IPv4, this is null */ private Long high; /** * CIDR based prefix size. * It's equivalent to the number of leading 1 bits in the routing prefix mask. * http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing */ private Integer size; protected IPAddressRange() { } public IPAddressRange(String cidrNotation) { SubnetV4Utils su = new SubnetV4Utils(cidrNotation); low = new Long(su.getInfo().getAddressAsInteger()); size = su.getInfo().getMaskSize(); } public boolean match(String address) { if( ! SubnetV4Utils.isAddress(address)) return false; SubnetV4Utils su = new SubnetV4Utils(low, size); return su.getInfo().isInRange(address); } public boolean match(InetAddress address) { if(address instanceof Inet4Address ) { return match((Inet4Address)address); } else { throw new UnsupportedOperationException("IPv6 non implemented yet"); } } public boolean match(Inet4Address address) { SubnetV4Utils su = new SubnetV4Utils(low, size); return su.getInfo().isInRange(address.getHostAddress()); } public String getAddress() { return high == null? encodeIPv4(): encodeIPv6(); } /** * @return the range in CIDR format: x.y.z.w/sz */ public String getCidrSignature() { if(high == null) { SubnetV4Utils su = new SubnetV4Utils(low, size); return su.getInfo().getCidrSignature(); } else { throw new UnsupportedOperationException("IPv6 non implemented yet"); } } protected String encodeIPv4() { SubnetV4Utils su = new SubnetV4Utils(low, size); return su.getInfo().getAddress(); } protected String encodeIPv6() { throw new UnsupportedOperationException("IPv6 non implemented yet"); } /** * The lower 64 bits. * For IPv4, only the lower 32 are used. */ public Long getLow() { return low; } public void setLow(Long low) { this.low = low; } /** * The higher 64 bits. * For IPv4, this is null */ public Long getHigh() { return high; } public void setHigh(Long high) { this.high = high; } /** * CIDR based prefix size. * It's equivalent to the number of leading 1 bits in the routing prefix mask. * http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing */ public int getSize() { return size; } public void setSize(int size) { this.size = size; } @Override public int hashCode() { int hash = 5; hash = 43 * hash + (this.low != null ? this.low.hashCode() : 0); hash = 43 * hash + (this.high != null ? this.high.hashCode() : 0); hash = 43 * hash + (this.size != null ? this.size.hashCode() : 0); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final IPAddressRange other = (IPAddressRange) obj; if (this.low != other.low && (this.low == null || !this.low.equals(other.low))) { return false; } if (this.high != other.high && (this.high == null || !this.high.equals(other.high))) { return false; } if (this.size != other.size && (this.size == null || !this.size.equals(other.size))) { return false; } return true; } @Override public String toString() { return getCidrSignature(); } }