/* * Copyright 2009 Red Hat, Inc. * * Red Hat 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; /** * @author frederic bregier */ public class CIDR4 extends CIDR { /** * The integer for the base address */ private int addressInt; /** * The integer for the end address */ private final int addressEndInt; /** * @param newaddr * @param mask */ 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; } else if (net > addressInt) { return -1; } else 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; } else if (o.addressInt > addressInt) { return -1; } else if (o.cidrMask < cidrMask) { // greater Mask means less IpAddresses so -1 return -1; } return 1; } /* (non-Javadoc) * @see org.jboss.netty.handler.ipfilter.CIDR#contains(java.net.InetAddress) */ @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 prefix_length) { return 1 << 32 - prefix_length; } /** Given a baseAddress length, return a netmask. I.e, a baseAddress length * of 24 will return 0xFFFFFF00. */ private static int ipv4PrefixLengthToMask(int prefix_length) { return ~((1 << 32 - prefix_length) - 1); } /** Convert an integer into an (IPv4) InetAddress. * @param addr * @return the created InetAddress * @throws UnknownHostException * @throws UnknownHostException */ 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. * @param addr * @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 = null; 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. * @param address * @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; } }