/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.handler.ipfilter;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
*/
public class CIDR4 extends CIDR {
/** The integer for the base address */
private int addressInt;
/** The integer for the end address */
private final int addressEndInt;
protected CIDR4(Inet4Address newaddr, int mask) {
cidrMask = mask;
addressInt = ipv4AddressToInt(newaddr);
int newmask = ipv4PrefixLengthToMask(mask);
addressInt &= newmask;
try {
baseAddress = intToIPv4Address(addressInt);
} catch (UnknownHostException e) {
// this should never happen
}
addressEndInt = addressInt + ipv4PrefixLengthToLength(cidrMask) - 1;
}
@Override
public InetAddress getEndAddress() {
try {
return intToIPv4Address(addressEndInt);
} catch (UnknownHostException e) {
// this should never happen
return null;
}
}
public int compareTo(CIDR arg) {
if (arg instanceof CIDR6) {
byte[] address = getIpV4FromIpV6((Inet6Address) arg.baseAddress);
int net = ipv4AddressToInt(address);
if (net == addressInt && arg.cidrMask == cidrMask) {
return 0;
}
if (net < addressInt) {
return 1;
}
if (net > addressInt) {
return -1;
}
if (arg.cidrMask < cidrMask) {
return -1;
}
return 1;
}
CIDR4 o = (CIDR4) arg;
if (o.addressInt == addressInt && o.cidrMask == cidrMask) {
return 0;
}
if (o.addressInt < addressInt) {
return 1;
}
if (o.addressInt > addressInt) {
return -1;
}
if (o.cidrMask < cidrMask) {
// greater Mask means less IpAddresses so -1
return -1;
}
return 1;
}
@Override
public boolean contains(InetAddress inetAddress) {
int search = ipv4AddressToInt(inetAddress);
return search >= addressInt && search <= addressEndInt;
}
/**
* Given an IPv4 baseAddress length, return the block length. I.e., a
* baseAddress length of 24 will return 256.
*/
private static int ipv4PrefixLengthToLength(int prefixLength) {
return 1 << 32 - prefixLength;
}
/**
* Given a baseAddress length, return a netmask. I.e, a baseAddress length
* of 24 will return 0xFFFFFF00.
*/
private static int ipv4PrefixLengthToMask(int prefixLength) {
return ~((1 << 32 - prefixLength) - 1);
}
/**
* Convert an integer into an (IPv4) InetAddress.
*
* @return the created InetAddress
*/
private static InetAddress intToIPv4Address(int addr) throws UnknownHostException {
byte[] a = new byte[4];
a[0] = (byte) (addr >> 24 & 0xFF);
a[1] = (byte) (addr >> 16 & 0xFF);
a[2] = (byte) (addr >> 8 & 0xFF);
a[3] = (byte) (addr & 0xFF);
return InetAddress.getByAddress(a);
}
/**
* Given an IPv4 address, convert it into an integer.
*
* @return the integer representation of the InetAddress
* @throws IllegalArgumentException if the address is really an
* IPv6 address.
*/
private static int ipv4AddressToInt(InetAddress addr) {
byte[] address;
if (addr instanceof Inet6Address) {
address = getIpV4FromIpV6((Inet6Address) addr);
} else {
address = addr.getAddress();
}
return ipv4AddressToInt(address);
}
/**
* Given an IPv4 address as array of bytes, convert it into an integer.
*
* @return the integer representation of the InetAddress
* @throws IllegalArgumentException if the address is really an
* IPv6 address.
*/
private static int ipv4AddressToInt(byte[] address) {
int net = 0;
for (byte addres : address) {
net <<= 8;
net |= addres & 0xFF;
}
return net;
}
}