2010-11-17 21 views
7

Tengo direcciones IP y una máscara como 10.1.1.1/32. Me gustaría comprobar si 10.1.1.1 está dentro de ese rango. ¿Hay alguna biblioteca o utilidad que pueda hacer esto o debo escribir algo yo mismo?Validar una dirección IP (con máscara)

+2

posible duplicado de [¿Alguien sabe un componente de Java para comprobar si la dirección IP es de particular, la red/máscara de red?] (Http://stackoverflow.com/questions/577363/does-anyone-know-a- java-component-to-check-if-ip-address-is-from-particular-netwo) –

Respuesta

24

Primero usted desea convertir sus direcciones IP en planos int s, que será más fácil trabajar con:

String  s = "10.1.1.99"; 
Inet4Address a = (Inet4Address) InetAddress.getByName(s); 
byte[]  b = a.getAddress(); 
int   i = ((b[0] & 0xFF) << 24) | 
       ((b[1] & 0xFF) << 16) | 
       ((b[2] & 0xFF) << 8) | 
       ((b[3] & 0xFF) << 0); 

Una vez que tenga las direcciones IP como de civil int s que puede hacer un poco de aritmética bits para realizar el control:

int subnet = 0x0A010100; // 10.1.1.0/24 
int bits = 24; 
int ip  = 0x0A010199; // 10.1.1.99 

// Create bitmask to clear out irrelevant bits. For 10.1.1.0/24 this is 
// 0xFFFFFF00 -- the first 24 bits are 1's, the last 8 are 0's. 
// 
//  -1  == 0xFFFFFFFF 
//  32 - bits == 8 
//  -1 << 8 == 0xFFFFFF00 
mask = -1 << (32 - bits) 

if ((subnet & mask) == (ip & mask)) { 
    // IP address is in the subnet. 
} 
+1

Supongamos que comienzo con 'String ip =" 10.1.1.1 "; int mask = 24' ¿cómo obtengo '0x0A010100'? –

+1

@ nn4l Gracias, actualicé mi respuesta para incluir su corrección. –

+1

¿Realmente no hay soporte para esto en la biblioteca de la clase base o algún paquete recomendado de manejo de máscara de red de terceros? – binki

1

Gracias a John Kugelman: utilicé sus fragmentos de código para crear esta clase.

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; 
    } 

} 

que tenía que añadir una máscara a la conversión int en su código:

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))); 

Producción:

ffffffc0 
c0c0c0c0 

En mi sistema:

$> 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) 
$> 

Usted puede eliminar los métodos principales y de prueba de la c anterior muchacha. Están adaptados del código de prueba de la unidad y se agregan aquí por simplicidad.

3
public static boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet) 

     String[] parts = addr.split("/"); 
     String ip = parts[0]; 
     int prefix; 

     if (parts.length < 2) { 
      prefix = 0; 
     } else { 
      prefix = Integer.parseInt(parts[1]); 
     } 

     Inet4Address a =null; 
     Inet4Address a1 =null; 
     try { 
      a = (Inet4Address) InetAddress.getByName(ip); 
      a1 = (Inet4Address) InetAddress.getByName(addr1); 
     } catch (UnknownHostException e){} 

     byte[] b = a.getAddress(); 
     int ipInt = ((b[0] & 0xFF) << 24) | 
         ((b[1] & 0xFF) << 16) | 
         ((b[2] & 0xFF) << 8) | 
         ((b[3] & 0xFF) << 0); 

     byte[] b1 = a1.getAddress(); 
     int ipInt1 = ((b1[0] & 0xFF) << 24) | 
         ((b1[1] & 0xFF) << 16) | 
         ((b1[2] & 0xFF) << 8) | 
         ((b1[3] & 0xFF) << 0); 

     int mask = ~((1 << (32 - prefix)) - 1); 

     if ((ipInt & mask) == (ipInt1 & mask)) { 
      return true; 
     } 
     else { 
      return false; 
     } 
} 
3

Aquí es una versión que lleva descripciones de subred de varias formas comunes, incluyendo IPv6.

Según el otro código publicado aquí. En direcciones IPv4 podría funcionar más lento que el enfoque de realizar operaciones binarias en int desnudo.

package de.c3oe.tryanderror; 
import java.math.BigInteger; 
import java.net.InetAddress; 
import java.net.UnknownHostException; 

/** 
* @author c3oe.de, based on snippets from Scott Plante, John Kugelmann 
*/ 
public class Subnet 
{ 
    final private int bytesSubnetCount; 
    final private BigInteger bigMask; 
    final private BigInteger bigSubnetMasked; 

    /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */ 
    public Subnet(final InetAddress subnetAddress, final int bits) 
    { 
     this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16 
     this.bigMask = BigInteger.valueOf(-1).shiftLeft(this.bytesSubnetCount*8 - bits); // mask = -1 << 32 - bits 
     this.bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(this.bigMask); 
    } 

    /** For use via format "192.168.0.0/255.255.255.0" or single address */ 
    public Subnet(final InetAddress subnetAddress, final InetAddress mask) 
    { 
     this.bytesSubnetCount = subnetAddress.getAddress().length; 
     this.bigMask = null == mask ? BigInteger.valueOf(-1) : new BigInteger(mask.getAddress()); // no mask given case is handled here. 
     this.bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(this.bigMask); 
    } 

    /** 
    * Subnet factory method. 
    * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0" 
    *  or single address or "2001:db8:85a3:880:0:0:0:0/57" 
    * @return a new instance 
    * @throws UnknownHostException thrown if unsupported subnet mask. 
    */ 
    public static Subnet createInstance(final String subnetMask) 
      throws UnknownHostException 
    { 
     final String[] stringArr = subnetMask.split("/"); 
     if (2 > stringArr.length) 
      return new Subnet(InetAddress.getByName(stringArr[ 0 ]), (InetAddress)null); 
     else if (stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":")) 
      return new Subnet(InetAddress.getByName(stringArr[ 0 ]), InetAddress.getByName(stringArr[ 1 ])); 
     else 
      return new Subnet(InetAddress.getByName(stringArr[ 0 ]), Integer.parseInt(stringArr[ 1 ])); 
    } 

    public boolean isInNet(final InetAddress address) 
    { 
     final byte[] bytesAddress = address.getAddress(); 
     if (this.bytesSubnetCount != bytesAddress.length) 
      return false; 
     final BigInteger bigAddress = new BigInteger(bytesAddress); 
     return bigAddress.and(this.bigMask).equals(this.bigSubnetMasked); 
    } 

    @Override 
    final public boolean equals(Object obj) 
    { 
     if (! (obj instanceof Subnet)) 
      return false; 
     final Subnet other = (Subnet)obj; 
     return this.bigSubnetMasked.equals(other.bigSubnetMasked) && 
       this.bigMask.equals(other.bigMask) && 
       this.bytesSubnetCount == other.bytesSubnetCount; 
    } 

    @Override 
    final public int hashCode() 
    { 
     return this.bytesSubnetCount; 
    } 

    @Override 
    public String toString() 
    { 
     final StringBuilder buf = new StringBuilder(); 
     bigInteger2IpString(buf, this.bigSubnetMasked, this.bytesSubnetCount); 
     buf.append('/'); 
     bigInteger2IpString(buf, this.bigMask, this.bytesSubnetCount); 
     return buf.toString(); 
    } 

    static private void bigInteger2IpString(final StringBuilder buf, final BigInteger bigInteger, final int displayBytes) 
    { 
     final boolean isIPv4 = 4 == displayBytes; 
     byte[] bytes = bigInteger.toByteArray(); 
     int diffLen = displayBytes - bytes.length; 
     final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00; 

     int integer; 
     for (int i = 0; i < displayBytes; i++) 
     { 
      if (0 < i && ! isIPv4 && i % 2 == 0) 
       buf.append(':'); 
      else if (0 < i && isIPv4) 
       buf.append('.'); 
      integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]); 
      if (! isIPv4 && 0x10 > integer) 
       buf.append('0'); 
      buf.append(isIPv4 ? integer : Integer.toHexString(integer)); 
     } 
    } 
}