View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.handler.ipfilter;
17  
18  import java.net.Inet4Address;
19  import java.net.Inet6Address;
20  import java.net.InetAddress;
21  import java.net.UnknownHostException;
22  
23  /**
24   */
25  public class CIDR4 extends CIDR {
26      /** The integer for the base address */
27      private int addressInt;
28  
29      /** The integer for the end address */
30      private final int addressEndInt;
31  
32      protected CIDR4(Inet4Address newaddr, int mask) {
33          cidrMask = mask;
34          addressInt = ipv4AddressToInt(newaddr);
35          int newmask = ipv4PrefixLengthToMask(mask);
36          addressInt &= newmask;
37          try {
38              baseAddress = intToIPv4Address(addressInt);
39          } catch (UnknownHostException e) {
40              // this should never happen
41          }
42          addressEndInt = addressInt + ipv4PrefixLengthToLength(cidrMask) - 1;
43      }
44  
45      @Override
46      public InetAddress getEndAddress() {
47          try {
48              return intToIPv4Address(addressEndInt);
49          } catch (UnknownHostException e) {
50              // this should never happen
51              return null;
52          }
53      }
54  
55      public int compareTo(CIDR arg) {
56          if (arg instanceof CIDR6) {
57              byte[] address = getIpV4FromIpV6((Inet6Address) arg.baseAddress);
58              int net = ipv4AddressToInt(address);
59              if (net == addressInt && arg.cidrMask == cidrMask) {
60                  return 0;
61              }
62              if (net < addressInt) {
63                  return 1;
64              }
65              if (net > addressInt) {
66                  return -1;
67              }
68              if (arg.cidrMask < cidrMask) {
69                  return -1;
70              }
71              return 1;
72          }
73          CIDR4 o = (CIDR4) arg;
74          if (o.addressInt == addressInt && o.cidrMask == cidrMask) {
75              return 0;
76          }
77          if (o.addressInt < addressInt) {
78              return 1;
79          }
80          if (o.addressInt > addressInt) {
81              return -1;
82          }
83          if (o.cidrMask < cidrMask) {
84              // greater Mask means less IpAddresses so -1
85              return -1;
86          }
87          return 1;
88      }
89  
90      @Override
91      public boolean contains(InetAddress inetAddress) {
92          if (inetAddress == null) {
93              throw new NullPointerException("inetAddress");
94          }
95  
96          if (cidrMask == 0) {
97              return true;
98          }
99  
100         int search = ipv4AddressToInt(inetAddress);
101         return search >= addressInt && search <= addressEndInt;
102     }
103 
104     /**
105      * Given an IPv4 baseAddress length, return the block length.  I.e., a
106      * baseAddress length of 24 will return 256.
107      */
108     private static int ipv4PrefixLengthToLength(int prefixLength) {
109         return 1 << 32 - prefixLength;
110     }
111 
112     /**
113      * Given a baseAddress length, return a netmask.  I.e, a baseAddress length
114      * of 24 will return 0xFFFFFF00.
115      */
116     private static int ipv4PrefixLengthToMask(int prefixLength) {
117         return ~((1 << 32 - prefixLength) - 1);
118     }
119 
120     /**
121      * Convert an integer into an (IPv4) InetAddress.
122      *
123      * @return the created InetAddress
124      */
125     private static InetAddress intToIPv4Address(int addr) throws UnknownHostException {
126         byte[] a = new byte[4];
127         a[0] = (byte) (addr >> 24 & 0xFF);
128         a[1] = (byte) (addr >> 16 & 0xFF);
129         a[2] = (byte) (addr >> 8 & 0xFF);
130         a[3] = (byte) (addr & 0xFF);
131         return InetAddress.getByAddress(a);
132     }
133 
134     /**
135      * Given an IPv4 address, convert it into an integer.
136      *
137      * @return the integer representation of the InetAddress
138      * @throws IllegalArgumentException if the address is really an
139      *                                  IPv6 address.
140      */
141     private static int ipv4AddressToInt(InetAddress addr) {
142         byte[] address;
143         if (addr instanceof Inet6Address) {
144             address = getIpV4FromIpV6((Inet6Address) addr);
145         } else {
146             address = addr.getAddress();
147         }
148         return ipv4AddressToInt(address);
149     }
150 
151     /**
152      * Given an IPv4 address as array of bytes, convert it into an integer.
153      *
154      * @return the integer representation of the InetAddress
155      * @throws IllegalArgumentException if the address is really an
156      *                                  IPv6 address.
157      */
158     private static int ipv4AddressToInt(byte[] address) {
159         int net = 0;
160         for (byte addres : address) {
161             net <<= 8;
162             net |= addres & 0xFF;
163         }
164         return net;
165     }
166 }