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.InetAddress;
19  import java.net.UnknownHostException;
20  import java.util.StringTokenizer;
21  import java.util.Vector;
22  
23  import org.jboss.netty.logging.InternalLogger;
24  import org.jboss.netty.logging.InternalLoggerFactory;
25  
26  /**
27   * This class allows to check if an IP-V4-Address is contained in a subnet.<BR>
28   * Supported Formats for the Subnets are: 1.1.1.1/255.255.255.255 or 1.1.1.1/32 (CIDR-Notation)
29   * and (InetAddress,Mask) where Mask is a integer for CIDR-notation or a String for Standard Mask notation.<BR>
30   * <BR><BR>Example1:<BR>
31   * <tt>IpV4Subnet ips = new IpV4Subnet("192.168.1.0/24");</tt><BR>
32   * <tt>System.out.println("Result: "+ ips.contains("192.168.1.123"));</tt><BR>
33   * <tt>System.out.println("Result: "+ ips.contains(inetAddress2));</tt><BR>
34   * <BR>Example1 bis:<BR>
35   * <tt>IpV4Subnet ips = new IpV4Subnet(inetAddress, 24);</tt><BR>
36   * where inetAddress is 192.168.1.0 and inetAddress2 is 192.168.1.123<BR>
37   * <BR><BR>Example2:<BR>
38   * <tt>IpV4Subnet ips = new IpV4Subnet("192.168.1.0/255.255.255.0");</tt><BR>
39   * <tt>System.out.println("Result: "+ ips.contains("192.168.1.123"));</tt><BR>
40   * <tt>System.out.println("Result: "+ ips.contains(inetAddress2));</tt><BR>
41   * <BR>Example2 bis:<BR>
42   * <tt>IpV4Subnet ips = new IpV4Subnet(inetAddress, "255.255.255.0");</tt><BR>
43   * where inetAddress is 192.168.1.0 and inetAddress2 is 192.168.1.123<BR>
44   */
45  public class IpV4Subnet implements IpSet, Comparable<IpV4Subnet> {
46  
47      private static final InternalLogger logger =
48          InternalLoggerFactory.getInstance(IpV4Subnet.class);
49  
50      private static final int SUBNET_MASK = 0x80000000;
51  
52      private static final int BYTE_ADDRESS_MASK = 0xFF;
53  
54      private InetAddress inetAddress;
55  
56      private int subnet;
57  
58      private int mask;
59  
60      private int cidrMask;
61  
62      /** Create IpV4Subnet for ALL (used for ALLOW or DENY ALL) */
63      public IpV4Subnet() {
64          // ALLOW or DENY ALL
65          mask = -1;
66          // other will be ignored
67          inetAddress = null;
68          subnet = 0;
69          cidrMask = 0;
70      }
71  
72      /**
73       * Create IpV4Subnet using the CIDR or normal Notation<BR>
74       * i.e.:
75       * IpV4Subnet subnet = new IpV4Subnet("10.10.10.0/24"); or
76       * IpV4Subnet subnet = new IpV4Subnet("10.10.10.0/255.255.255.0");
77       *
78       * @param netAddress a network address as string.
79       */
80      public IpV4Subnet(String netAddress) throws UnknownHostException {
81          setNetAddress(netAddress);
82      }
83  
84      /** Create IpV4Subnet using the CIDR Notation */
85      public IpV4Subnet(InetAddress inetAddress, int cidrNetMask) {
86          setNetAddress(inetAddress, cidrNetMask);
87      }
88  
89      /** Create IpV4Subnet using the normal Notation */
90      public IpV4Subnet(InetAddress inetAddress, String netMask) {
91          setNetAddress(inetAddress, netMask);
92      }
93  
94      /**
95       * Sets the Network Address in either CIDR or Decimal Notation.<BR>
96       * i.e.: setNetAddress("1.1.1.1/24"); or<BR>
97       * setNetAddress("1.1.1.1/255.255.255.0");<BR>
98       *
99       * @param netAddress a network address as string.
100      */
101     private void setNetAddress(String netAddress) throws UnknownHostException {
102         Vector<Object> vec = new Vector<Object>();
103         StringTokenizer st = new StringTokenizer(netAddress, "/");
104         while (st.hasMoreTokens()) {
105             vec.add(st.nextElement());
106         }
107 
108         if (vec.get(1).toString().length() < 3) {
109             setNetId(vec.get(0).toString());
110             setCidrNetMask(Integer.parseInt(vec.get(1).toString()));
111         } else {
112             setNetId(vec.get(0).toString());
113             setNetMask(vec.get(1).toString());
114         }
115     }
116 
117     /** Sets the Network Address in CIDR Notation. */
118     private void setNetAddress(InetAddress inetAddress, int cidrNetMask) {
119         setNetId(inetAddress);
120         setCidrNetMask(cidrNetMask);
121     }
122 
123     /** Sets the Network Address in Decimal Notation. */
124     private void setNetAddress(InetAddress inetAddress, String netMask) {
125         setNetId(inetAddress);
126         setNetMask(netMask);
127     }
128 
129     /**
130      * Sets the BaseAdress of the Subnet.<BR>
131      * i.e.: setNetId("192.168.1.0");
132      *
133      * @param netId a network ID
134      */
135     private void setNetId(String netId) throws UnknownHostException {
136         InetAddress inetAddress1 = InetAddress.getByName(netId);
137         this.setNetId(inetAddress1);
138     }
139 
140     /**
141      * Compute integer representation of InetAddress
142      *
143      * @return the integer representation
144      */
145     private static int toInt(InetAddress inetAddress1) {
146         byte[] address = inetAddress1.getAddress();
147         int net = 0;
148         for (byte addres : address) {
149             net <<= 8;
150             net |= addres & BYTE_ADDRESS_MASK;
151         }
152         return net;
153     }
154 
155     /** Sets the BaseAdress of the Subnet. */
156     private void setNetId(InetAddress inetAddress) {
157         this.inetAddress = inetAddress;
158         subnet = toInt(inetAddress);
159     }
160 
161     /**
162      * Sets the Subnet's Netmask in Decimal format.<BR>
163      * i.e.: setNetMask("255.255.255.0");
164      *
165      * @param netMask a network mask
166      */
167     private void setNetMask(String netMask) {
168         StringTokenizer nm = new StringTokenizer(netMask, ".");
169         int i = 0;
170         int[] netmask = new int[4];
171         while (nm.hasMoreTokens()) {
172             netmask[i] = Integer.parseInt(nm.nextToken());
173             i++;
174         }
175         int mask1 = 0;
176         for (i = 0; i < 4; i++) {
177             mask1 += Integer.bitCount(netmask[i]);
178         }
179         setCidrNetMask(mask1);
180     }
181 
182     /**
183      * Sets the CIDR Netmask<BR>
184      * i.e.: setCidrNetMask(24);
185      *
186      * @param cidrNetMask a netmask in CIDR notation
187      */
188     private void setCidrNetMask(int cidrNetMask) {
189         cidrMask = cidrNetMask;
190         mask = SUBNET_MASK >> cidrMask - 1;
191     }
192 
193     /**
194      * Compares the given IP-Address against the Subnet and returns true if
195      * the ip is in the subnet-ip-range and false if not.
196      *
197      * @param ipAddr an ipaddress
198      * @return returns true if the given IP address is inside the currently
199      *         set network.
200      */
201     public boolean contains(String ipAddr) throws UnknownHostException {
202         InetAddress inetAddress1 = InetAddress.getByName(ipAddr);
203         return this.contains(inetAddress1);
204     }
205 
206     /**
207      * Compares the given InetAddress against the Subnet and returns true if
208      * the ip is in the subnet-ip-range and false if not.
209      *
210      * @return returns true if the given IP address is inside the currently
211      *         set network.
212      */
213     public boolean contains(InetAddress inetAddress1) {
214         if (mask == -1) {
215             // ANY
216             return true;
217         }
218         return (toInt(inetAddress1) & mask) == subnet;
219     }
220 
221     @Override
222     public String toString() {
223         return inetAddress.getHostAddress() + "/" + cidrMask;
224     }
225 
226     @Override
227     public boolean equals(Object o) {
228         if (!(o instanceof IpV4Subnet)) {
229             return false;
230         }
231         IpV4Subnet ipV4Subnet = (IpV4Subnet) o;
232         return ipV4Subnet.subnet == subnet && ipV4Subnet.cidrMask == cidrMask;
233     }
234 
235     @Override
236     public int hashCode() {
237         return subnet;
238     }
239 
240     /** Compare two IpV4Subnet */
241     public int compareTo(IpV4Subnet o) {
242         if (o.subnet == subnet && o.cidrMask == cidrMask) {
243             return 0;
244         }
245         if (o.subnet < subnet) {
246             return 1;
247         } else if (o.subnet > subnet) {
248             return -1;
249         } else if (o.cidrMask < cidrMask) {
250             // greater Mask means less IpAddresses so -1
251             return -1;
252         }
253         return 1;
254     }
255 }