2010-11-17 16 views
7

J'ai des adresses IP et un masque tel que 10.1.1.1/32. Je voudrais vérifier si 10.1.1.1 est à l'intérieur de cette gamme. Y a-t-il une bibliothèque ou un service public qui ferait cela ou dois-je écrire quelque chose moi-même?Valider une adresse IP (avec masque)

+2

double possible de [Quelqu'un sait-il un composant java pour vérifier si l'adresse IP est de réseau particulier/netmask?] (Http://stackoverflow.com/questions/577363/does-anyone-know-a- java-component-to-check-if-ip-adresse-is-from-particulier-netwo) –

Répondre

24

D'abord, vous aurez envie de convertir vos adresses IP en int plat s, ce qui sera plus facile de travailler avec:

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

Une fois que vous avez vos adresses IP comme simples int s vous pouvez faire de l'arithmétique binaire pour effectuer la vérification:

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

Supposons que je commence par 'String ip =" 10.1.1.1 "; int mask = 24' comment puis-je obtenir '0x0A010100'? –

+1

@ nn4l Merci, mis à jour ma réponse pour inclure votre correction. –

+1

Donc, il n'y a vraiment pas de support pour cela dans la bibliothèque de classes de base ou dans un paquet de gestion de masque de réseau tiers recommandé? – binki

1

Merci à John Kugelman - J'ai utilisé ses extraits de code pour créer cette classe.

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

} 

Je ne dois ajouter un masque à la conversion int dans son 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))); 

Produit:

ffffffc0 
c0c0c0c0 

Sur mon système:

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

Vous peut supprimer les méthodes principales et de test de la c ci-dessus fille. Ils sont adaptés à partir du code de test unitaire et ajoutés ici pour plus de simplicité.

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

Voici une version qui prend des descriptions de sous-réseau de plusieurs manières communes, y compris IPv6.

Basé sur le code affiché ici. Sur adresses IPv4 il peut fonctionner plus lentement que l'approche d'effectuer des opérations binaires sur int nues.

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