Validate an IP Address (with Mask)

后端 未结 6 1532
一整个雨季
一整个雨季 2021-02-01 09:52

I have ip addresses and a mask such as 10.1.1.1/32. I would like to check if 10.1.1.1 is inside that range. Is there a library or utility that would do

6条回答
  •  谎友^
    谎友^ (楼主)
    2021-02-01 10:19

    Thanks to John Kugelman--I used his code snippets to create this class.

    package bs;
    
    import java.net.Inet4Address;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /**
     * Represents an IP range based on an address/mask.
     * @author Scott Plante, using code snippets by John Kugelman.
     */
    public class IPMask
    {
      public static void main(String args[]) 
          throws UnknownHostException
      {
        IPMask ipmask;
    
        ipmask = IPMask.getIPMask("192.168.20.32/24");
        System.out.println("Checking "+ipmask+"...");
    
        test(ipmask, "192.168.20.31 ", true);
        test(ipmask, "192.168.20.32 ", true);
        test(ipmask, "192.168.20.33 ", true);
        test(ipmask, "192.168.20.34 ", true);
        test(ipmask, "192.168.20.35 ", true);
        test(ipmask, "192.168.20.36 ", true);
        test(ipmask, "192.168.20.254", true);
        test(ipmask, "192.168.20.157", true);
        test(ipmask, "192.168.21.1  ", false);
        test(ipmask, "192.168.19.255", false);
        test(ipmask, "192.168.24.1  ", false);
    
        ipmask = IPMask.getIPMask("192.168.20.32/31");
        System.out.println("Checking "+ipmask+"...");
    
        test(ipmask, "192.168.20.31 ", false);
        test(ipmask, "192.168.20.32 ", true);
        test(ipmask, "192.168.20.33 ", true);
        test(ipmask, "192.168.20.34 ", false);
        test(ipmask, "192.168.20.35 ", false);
        test(ipmask, "192.168.20.36 ", false);
        test(ipmask, "192.168.20.254", false);
        test(ipmask, "192.168.20.157", false);
        test(ipmask, "192.168.21.1  ", false);
        test(ipmask, "192.168.19.255", false);
        test(ipmask, "192.168.24.1  ", false);
    
        ipmask = IPMask.getIPMask("192.168.20.32/23");
        System.out.println("Checking "+ipmask+"...");
    
        test(ipmask, "192.168.20.31 ", true);
        test(ipmask, "192.168.20.32 ", true);
        test(ipmask, "192.168.20.33 ", true);
        test(ipmask, "192.168.20.254", true);
        test(ipmask, "192.168.21.254", true);
        test(ipmask, "192.168.19.255", false);
        test(ipmask, "192.168.24.1  ", false);
    
      }
    
      public static void test(IPMask ipmask, String addr, boolean expect) 
          throws UnknownHostException
      {
        boolean got = ipmask.matches(addr);
        System.out.println(addr + "\t(" + expect + ") ?\t"+got
            + "\t" + (got==expect?"":"!!!!!!!!"));
      }
    
      private Inet4Address i4addr;
      private byte maskCtr;
    
      private int addrInt;
      private int maskInt;
    
      public IPMask(Inet4Address i4addr, byte mask)
      {
        this.i4addr = i4addr;
        this.maskCtr = mask;
    
        this.addrInt = addrToInt(i4addr);
        this.maskInt = ~((1 << (32 - maskCtr)) - 1);
      }
    
      /** IPMask factory method. 
       * 
       * @param addrSlashMask IP/Mask String in format "nnn.nnn.nnn.nnn/mask". If 
       *    the "/mask" is omitted, "/32" (just the single address) is assumed.
       * @return a new IPMask
       * @throws UnknownHostException if address part cannot be parsed by 
       *    InetAddress
       */
      public static IPMask getIPMask(String addrSlashMask) 
          throws UnknownHostException
      {
        int pos = addrSlashMask.indexOf('/');
        String addr;
        byte maskCtr;
        if (pos==-1)
        {
          addr = addrSlashMask;
          maskCtr = 32;
        }
        else
        { 
          addr = addrSlashMask.substring(0, pos);
          maskCtr = Byte.parseByte(addrSlashMask.substring(pos + 1));
        }
        return new IPMask((Inet4Address) InetAddress.getByName(addr), maskCtr);
      }
    
     /** Test given IPv4 address against this IPMask object.
       * 
       * @param testAddr address to check.
       * @return true if address is in the IP Mask range, false if not.
       */  
      public boolean matches(Inet4Address testAddr)
      {
        int testAddrInt = addrToInt(testAddr);   
        return ((addrInt & maskInt) == (testAddrInt & maskInt));
      }
    
    /** Convenience method that converts String host to IPv4 address.
       * 
       * @param addr IP address to match in nnn.nnn.nnn.nnn format or hostname.
       * @return true if address is in the IP Mask range, false if not.
       * @throws UnknownHostException if the string cannot be decoded.
       */
      public boolean matches(String addr) 
          throws UnknownHostException
      {
        return matches((Inet4Address)InetAddress.getByName(addr));
      }
    
    /** Converts IPv4 address to integer representation.
       */
      private static int addrToInt(Inet4Address i4addr)
      {
        byte[] ba = i4addr.getAddress();  
        return (ba[0]       << 24) 
            | ((ba[1]&0xFF) << 16) 
            | ((ba[2]&0xFF) << 8) 
            |  (ba[3]&0xFF);
      }
    
      @Override
      public String toString()
      {
        return "IPMask(" + i4addr.getHostAddress() + "/" + maskCtr + ")";
      }
    
      @Override
      public boolean equals(Object obj)
      {
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        final IPMask that = (IPMask) obj;    
        return (this.addrInt == that.addrInt && this.maskInt == that.maskInt);
      }
    
      @Override
      public int hashCode()
      {
        return this.maskInt + this.addrInt;
      }
    
    }
    

    I did have to add a mask to the int conversion in his code:

    Inet4Address a = (Inet4Address) InetAddress.getByName("192.192.192.192");
    byte[]       b = a.getAddress();
    int          i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0);
    System.out.println(Integer.toHexString(i));
    System.out.println(Integer.toHexString(addrToInt(a)));
    

    Produced:

    ffffffc0
    c0c0c0c0
    

    On my system:

    $> uname -a
    Linux guin 2.6.37.6-0.5-desktop #1 SMP PREEMPT 2011-04-25 21:48:33 +0200 x86_64 x86_64 x86_64 GNU/Linux
    $> java -version
    java version "1.6.0_25"
    Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
    Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode)
    $> 
    

    You can remove the main and test methods from the above class. They're adapted from the unit test code and added here for simplicity.

提交回复
热议问题