View Javadoc

    1   /*
    2    * Copyright 2009 University Corporation for Advanced Internet Development, Inc.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * 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,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16
    17  package edu.internet2.middleware.shibboleth.idp.util;
    18
    19  import java.net.InetAddress;
    20  import java.net.UnknownHostException;
    21  import java.util.BitSet;
    22
    23  import org.opensaml.xml.util.DatatypeHelper;
    24
    25  /** Represents a range of IP addresses. */
    26  public class IPRange {
    27
    28      /** Number of bits within */
    29      private int addressLength;
    30
    31      /** The IP network address for the range. */
    32      private BitSet network;
    33
    34      /** The netmask for the range. */
    35      private BitSet mask;
    36
    37      /**
    38       * Constructor
    39       *
    40       * @param networkAddress the network address for the range
    41       * @param maskSize the number of bits in the netmask
    42       */
    43      public IPRange(InetAddress networkAddress, int maskSize) {
    44          this(networkAddress.getAddress(), maskSize);
    45      }
    46
    47      /**
    48       * Constructor
    49       *
    50       * @param networkAddress the network address for the range
    51       * @param maskSize the number of bits in the netmask
    52       */
    53      public IPRange(byte[] networkAddress, int maskSize) {
    54          addressLength = networkAddress.length * 8;
    55          if (addressLength != 32 && addressLength != 128) {
    56              throw new IllegalArgumentException("Network address was neither an IPv4 or IPv6 address");
    57          }
    58
    59          network = toBitSet(networkAddress);
    60          mask = new BitSet(addressLength);
    61          mask.set(addressLength - maskSize, addressLength, true);
    62      }
    63
    64      /**
    65       * Parses a CIDR block definition in to an IP range.
    66       *
    67       * @param cidrBlock the CIDR block definition
    68       *
    69       * @return the resultant IP range
    70       */
    71      public static IPRange parseCIDRBlock(String cidrBlock){
    72          String block = DatatypeHelper.safeTrimOrNullString(cidrBlock);
    73          if(block == null){
    74              throw new IllegalArgumentException("CIDR block definition may not be null");
    75          }
    76
    77          String[] blockParts = block.split("/");
    78          try{
    79              InetAddress networkAddress = InetAddress.getByName(blockParts[0]);
    80              int maskSize = Integer.parseInt(blockParts[1]);
    81              return new IPRange(networkAddress, maskSize);
    82          }catch(UnknownHostException e){
    83              throw new IllegalArgumentException("Invalid IP address");
    84          }catch(NumberFormatException e){
    85              throw new IllegalArgumentException("Invalid netmask size");
    86          }
    87      }
    88
    89      /**
    90       * Determines whether the given address is contained in the IP range.
    91       *
    92       * @param address the address to check
    93       *
    94       * @return true if the address is in the range, false it not
    95       */
    96      public boolean contains(InetAddress address) {
    97          return contains(address.getAddress());
    98      }
    99
    100     /**
    101      * Determines whether the given address is contained in the IP range.
    102      *
    103      * @param address the address to check
    104      *
    105      * @return true if the address is in the range, false it not
    106      */
    107     public boolean contains(byte[] address) {
    108         if (address.length * 8 != addressLength) {
    109             return false;
    110         }
    111
    112         BitSet addrNetwork = toBitSet(address);
    113         addrNetwork.and(mask);
    114
    115         return addrNetwork.equals(network);
    116     }
    117
    118     /**
    119      * Converts a byte array to a BitSet.
    120      *
    121      * The supplied byte array is assumed to have the most significant bit in element 0.
    122      *
    123      * @param bytes the byte array with most significant bit in element 0.
    124      *
    125      * @return the BitSet
    126      */
    127     protected BitSet toBitSet(byte[] bytes) {
    128         BitSet bits = new BitSet(bytes.length * 8);
    129
    130         for (int i = 0; i < bytes.length * 8; i++) {
    131             if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) {
    132                 bits.set(i);
    133             }
    134         }
    135
    136         return bits;
    137     }
    138 }