Java Library for IP/Subnet Calculator

Created By Saddam Abu Ghaida and Nicolai Tufar

Hello everybody.

I created a IP Subnetting library in java long time ago, and the reason why i created it because there where no available Java library to do this kind of calculations, so i created my own with the help of my Friend Nicolai.

i want to share it with you so you don’t need to waste your time doing it 🙂

feel free to use it the way you want.

/*
Copyright (c) 2010, Saddam Abu Ghaida, Nicolai TufarAll rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Saddam Abu Ghaida or Nicolai Tufar nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Saddam Abu Ghaida or Nicolai Tufar BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.IPCalculator.client;

import java.util.ArrayList;
import java.util.List;

public class IPv4 {
    int baseIPnumeric;
    int netmaskNumeric;

    /**
* Specify IP address and netmask like: new
* IPv4("10.1.0.25","255.255.255.16")
*
*@param symbolicIP
*@param netmask
*/
    public IPv4(String symbolicIP, String netmask) throws NumberFormatException {

        /* IP */
        String[] st = symbolicIP.split("\.");

        if (st.length != 4)
            throw new NumberFormatException("Invalid IP address: " + symbolicIP);

        int i = 24;
        baseIPnumeric = 0;

        for (int n = 0; n < st.length; n++) {

            int value = Integer.parseInt(st[n]);

            if (value != (value & 0xff)) {

                throw new NumberFormatException("Invalid IP address: "+ symbolicIP);
            }

            baseIPnumeric += value << i;
            i -= 8;
        }

        /* Netmask */
        st = netmask.split("\.");

        if (st.length != 4)
            throw new NumberFormatException("Invalid netmask address: "

                    + netmask);

        i = 24;
        netmaskNumeric = 0;

        if (Integer.parseInt(st[0]) < 255) {

            throw new NumberFormatException(
                    "The first byte of netmask can not be less than 255");
        }
        for (int n = 0; n < st.length; n++) {

            int value = Integer.parseInt(st[n]);

            if (value != (value & 0xff)) {

                throw new NumberFormatException("Invalid netmask address: "  + netmask);
            }

            netmaskNumeric += value << i;
            i -= 8;

        }
/*
* see if there are zeroes inside netmask, like: 1111111101111 This is
* illegal, throw exception if encountered. Netmask should always have
* only ones, then only zeroes, like: 11111111110000
*/
        boolean encounteredOne = false;
        int ourMaskBitPattern = 1;

        for (i = 0; i < 32; i++) {

            if ((netmaskNumeric & ourMaskBitPattern) != 0) {

                encounteredOne = true; // the bit is 1
            } else { // the bit is 0
                if (encounteredOne == true)

                    throw new NumberFormatException("Invalid netmask: " + netmask + " (bit " + (i + 1) + ")");
            }

            ourMaskBitPattern = ourMaskBitPattern << 1;
        }
    }

/**
* Specify IP in CIDR format like: new IPv4("10.1.0.25/16");
*
*@param IPinCIDRFormat
*/
    public IPv4(String IPinCIDRFormat) throws NumberFormatException {

        String[] st = IPinCIDRFormat.split("\/");
        if (st.length != 2)

            throw new NumberFormatException("Invalid CIDR format '"
                    + IPinCIDRFormat + "', should be: xx.xx.xx.xx/xx");

        String symbolicIP = st[0];
        String symbolicCIDR = st[1];

        Integer numericCIDR = new Integer(symbolicCIDR);
        if (numericCIDR > 32)

            throw new NumberFormatException("CIDR can not be greater than 32");

        /* IP */
        st = symbolicIP.split("\.");

        if (st.length != 4)
            throw new NumberFormatException("Invalid IP address: " + symbolicIP);

        int i = 24;
        baseIPnumeric = 0;

        for (int n = 0; n < st.length; n++) {

            int value = Integer.parseInt(st[n]);

            if (value != (value & 0xff)) {

                throw new NumberFormatException("Invalid IP address: " + symbolicIP);
            }

            baseIPnumeric += value << i;
            i -= 8;

        }

        /* netmask from CIDR */
        if (numericCIDR < 8)
            throw new NumberFormatException("Netmask CIDR can not be less than 8");
        netmaskNumeric = 0xffffffff;
        netmaskNumeric = netmaskNumeric << (32 - numericCIDR);

    }

    /**
* Get the IP in symbolic form, i.e. xxx.xxx.xxx.xxx
*
*@return
*/
    public String getIP() {
        return convertNumericIpToSymbolic(baseIPnumeric);

    }

    private String convertNumericIpToSymbolic(Integer ip) {
        StringBuffer sb = new StringBuffer(15);

        for (int shift = 24; shift > 0; shift -= 8) {

            // process 3 bytes, from high order byte down.
            sb.append(Integer.toString((ip >>> shift) & 0xff));

            sb.append('.');
        }
        sb.append(Integer.toString(ip & 0xff));

        return sb.toString();
    }

/**
* Get the net mask in symbolic form, i.e. xxx.xxx.xxx.xxx
*
*@return
*/

    public String getNetmask() {
        StringBuffer sb = new StringBuffer(15);

        for (int shift = 24; shift > 0; shift -= 8) {

            // process 3 bytes, from high order byte down.
            sb.append(Integer.toString((netmaskNumeric >>> shift) & 0xff));

            sb.append('.');
        }
        sb.append(Integer.toString(netmaskNumeric & 0xff));

        return sb.toString();
    }

/**
* Get the IP and netmask in CIDR form, i.e. xxx.xxx.xxx.xxx/xx
*
*@return
*/

    public String getCIDR() {
        int i;
        for (i = 0; i < 32; i++) {

            if ((netmaskNumeric << i) == 0)
                break;

        }
        return convertNumericIpToSymbolic(baseIPnumeric & netmaskNumeric) + "/" + i;
    }

/**
* Get an arry of all the IP addresses available for the IP and netmask/CIDR
* given at initialization
*
*@return
*/
    public List<String> getAvailableIPs(Integer numberofIPs) {

        ArrayList<String> result = new ArrayList<String>();
        int numberOfBits;

        for (numberOfBits = 0; numberOfBits < 32; numberOfBits++) {

            if ((netmaskNumeric << numberOfBits) == 0)
                break;

        }
        Integer numberOfIPs = 0;
        for (int n = 0; n < (32 - numberOfBits); n++) {

            numberOfIPs = numberOfIPs << 1;
            numberOfIPs = numberOfIPs | 0x01;

        }

        Integer baseIP = baseIPnumeric & netmaskNumeric;

        for (int i = 1; i < (numberOfIPs) && i < numberofIPs; i++) {

            Integer ourIP = baseIP + i;

            String ip = convertNumericIpToSymbolic(ourIP);

            result.add(ip);
        }
        return result;
    }

/**
* Range of hosts
*
*@return
*/
    public String getHostAddressRange() {

        int numberOfBits;
        for (numberOfBits = 0; numberOfBits < 32; numberOfBits++) {

            if ((netmaskNumeric << numberOfBits) == 0)
                break;
        }
        Integer numberOfIPs = 0;
        for (int n = 0; n < (32 - numberOfBits); n++) {

            numberOfIPs = numberOfIPs << 1;
            numberOfIPs = numberOfIPs | 0x01;

        }

        Integer baseIP = baseIPnumeric & netmaskNumeric;
        String firstIP = convertNumericIpToSymbolic(baseIP + 1);
        String lastIP = convertNumericIpToSymbolic(baseIP + numberOfIPs - 1);
        return firstIP + " - " + lastIP;
    }

/**
* Returns number of hosts available in given range
*
*@return number of hosts
*/
    public Long getNumberOfHosts() {
        int numberOfBits;

        for (numberOfBits = 0; numberOfBits < 32; numberOfBits++) {

            if ((netmaskNumeric << numberOfBits) == 0)
                break;

        }

        Double x = Math.pow(2, (32 - numberOfBits));

        if (x == -1)
            x = 1D;

        return x.longValue();
    }

/**
* The XOR of the netmask
*
*@return wildcard mask in text form, i.e. 0.0.15.255
*/

    public String getWildcardMask() {
        Integer wildcardMask = netmaskNumeric ^ 0xffffffff;

        StringBuffer sb = new StringBuffer(15);
        for (int shift = 24; shift > 0; shift -= 8) {

            // process 3 bytes, from high order byte down.
            sb.append(Integer.toString((wildcardMask >>> shift) & 0xff));

            sb.append('.');
        }
        sb.append(Integer.toString(wildcardMask & 0xff));

        return sb.toString();

    }

    public String getBroadcastAddress() {

        if (netmaskNumeric == 0xffffffff)
            return "0.0.0.0";

        int numberOfBits;
        for (numberOfBits = 0; numberOfBits < 32; numberOfBits++) {

            if ((netmaskNumeric << numberOfBits) == 0)
                break;

        }
        Integer numberOfIPs = 0;
        for (int n = 0; n < (32 - numberOfBits); n++) {

            numberOfIPs = numberOfIPs << 1;
            numberOfIPs = numberOfIPs | 0x01;
        }

        Integer baseIP = baseIPnumeric & netmaskNumeric;
        Integer ourIP = baseIP + numberOfIPs;

        String ip = convertNumericIpToSymbolic(ourIP);

        return ip;
    }

    private String getBinary(Integer number) {
        String result = "";

        Integer ourMaskBitPattern = 1;
        for (int i = 1; i <= 32; i++) {

            if ((number & ourMaskBitPattern) != 0) {

                result = "1" + result; // the bit is 1
            } else { // the bit is 0

                result = "0" + result;
            }
            if ((i % 8) == 0 && i != 0 && i != 32)

                result = "." + result;
            ourMaskBitPattern = ourMaskBitPattern << 1;

        }
        return result;
    }

    public String getNetmaskInBinary() {

        return getBinary(netmaskNumeric);
    }

/**
* Checks if the given IP address contains in subnet
*
*@param IPaddress
*@return
*/
    public boolean contains(String IPaddress) {

        Integer checkingIP = 0;
        String[] st = IPaddress.split("\.");

        if (st.length != 4)
            throw new NumberFormatException("Invalid IP address: " + IPaddress);

        int i = 24;
        for (int n = 0; n < st.length; n++) {

            int value = Integer.parseInt(st[n]);

            if (value != (value & 0xff)) {

                throw new NumberFormatException("Invalid IP address: "
                        + IPaddress);
            }

            checkingIP += value << i;
            i -= 8;
        }

        if ((baseIPnumeric & netmaskNumeric) == (checkingIP & netmaskNumeric))

            return true;
        else
            return false;
    }

    public boolean contains(IPv4 child) {

        Integer subnetID = child.baseIPnumeric;

        Integer subnetMask = child.netmaskNumeric;

        if ((subnetID & this.netmaskNumeric) == (this.baseIPnumeric & this.netmaskNumeric)) {

            if ((this.netmaskNumeric < subnetMask) == true
                    && this.baseIPnumeric <= subnetID) {

                return true;
            }

        }
        return false;

    }

    public boolean validateIPAddress() {
        String IPAddress = getIP();

        if (IPAddress.startsWith("0")) {
            return false;

        }

        if (IPAddress.isEmpty()) {

            return false;
        }

        if (IPAddress
                .matches("\A(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z")) {

            return true;
        }
        return false;
    }

/**
*@param args
*/
    public static void main(String[] args) {

        // ipv4.setIP("10.20.30.5", "255.255.255.200");
        // System.out.println(ipv4.getIP());
        // System.out.println(ipv4.getNetmask());
        // System.out.println(ipv4.getCIDR());

/*
* IPv4 ipv4 = new IPv4("10.1.17.0/20");
* System.out.println(ipv4.getIP());
* System.out.println(ipv4.getNetmask());
* System.out.println(ipv4.getCIDR());
*
* System.out.println("============= Available IPs ===============");
* List<String> availableIPs = ipv4.getAvailableIPs(); int counter=0;
* for (String ip : availableIPs) { System.out.print(ip);
* System.out.print(" "); counter++; if((counter%10)==0)
* System.out.print("n"); }
*/

        IPv4 ipv4 = new IPv4("12.12.12.0/16");

        IPv4 ipv4Child = new IPv4("12.12.12.0/17");
        // IPv4 ipv4 = new IPv4("192.168.20.0/16");
        // System.out.println(ipv4.getIP());
        // System.out.println(ipv4.getNetmask());

        // System.out.println(ipv4.getCIDR());
        // System.out.println("======= MATCHES =======");
        // System.out.println(ipv4.getBinary(ipv4.baseIPnumeric));
        // System.out.println(ipv4.getBinary(ipv4.netmaskNumeric));

        System.out.println(ipv4.contains(ipv4Child));

        System.out.println(ipv4.getBinary(ipv4.baseIPnumeric));
        System.out.println(ipv4.getBinary(ipv4.netmaskNumeric));

        System.out.println(ipv4Child.getBinary(ipv4Child.baseIPnumeric));

        System.out.println(ipv4Child.getBinary(ipv4Child.netmaskNumeric));

        System.out.println("==============output================");
        System.out.println(ipv4.contains(ipv4Child));

        // ipv4.contains("192.168.50.11");
        // System.out.println("======= DOES NOT MATCH =======");
        // ipv4.contains("10.2.3.4");
        // System.out.println(ipv4.validateIPAddress());
        // System.out.println(ipv4.getBinary(ipv4.baseIPnumeric));
        // System.out.println(ipv4.getBinary(ipv4.netmaskNumeric));
    }
}
Posted in Network, Programming and tagged , , , , , , , , , , . Bookmark the permalink. RSS feed for this post. Leave a trackback.

25 Responses to Java Library for IP/Subnet Calculator

  1. Jonna Beeker says:

    Just want to say your article is as astounding. The clearness to your publish is just cool and that i could suppose you’re a professional in this subject. Well along with your permission allow me to snatch your RSS feed to keep up to date with impending post. Thanks one million and please continue the rewarding work.

  2. Thank the author very much for this good post. Great job!

  3. Jayaprakash says:

    Thanks for providing the IP Subnetting library. It is very useful and a great post. Please keep writing.

  4. Lina says:

    why when i run the coding in cmd, the below error msg appear…

    IPv4.java:21: error: illegal escape character
    String[] st = symbolicIP.split(“\.”);
    ^
    IPv4.java:43: error: illegal escape character
    st = netmask.split(“\.”);
    ^
    IPv4.java:101: error: illegal escape character
    String[] st = IPinCIDRFormat.split(“\/”);

  5. Lina says:

    This the error that i get :

    Exception in thread “main” java.lang.NoClassDefFoundError: IPv4 (wrong name: com
    /IPCalculator/client/IPv4)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14
    1)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    Could not find the main class: IPv4. Program will exit.

    • Saddam Abu Ghaida says:

      you need to remove the following line, and replace it with your package structure if you have
      package com.IPCalculator.client;

      tell me if it worked for you

      • Lina says:

        when i comment the package, i get this error

        C:\MyOop>java IPv4
        Exception in thread “main” java.lang.NumberFormatException: Invalid CIDR format
        12.12.12.0/16, should be: xx.xx.xx.xx/xx
        at IPv4.(IPv4.java:102)
        at IPv4.main(IPv4.java:472)

        • Saddam Abu Ghaida says:

          you are calling the function in a wrong way because /16 means 255.255.0.0 which means the network ID is 12.12.0.0
          if you are interested in this im going to add you to my Yahoo messenger in order to be able to help you.
          regards

  6. Andrei says:

    Immediately compiled with GWT. Now I can perform advanced input client-side validation for IPs/netmask inputs in my project. Thanks so much!

  7. Sumeet says:

    Hello Sir

    Good Evening

    Sir I got an exception

    Exception in thread “main” java.lang.NumberFormatException:Invalid IP address: 64.12.12.

    as i wrote 64.12.12.

  8. Sumeet says:

    Hello Sir

    Continuesly i got this exception

    Exception in thread “main” java.lang.NumberFormatException: Invalid CIDR format ‘12.12.12.0/27’, should be: xx.xx.xx.xx/xx
    at com.IPCalculator.client.IPv4.(IPv4.java:104)
    at com.IPCalculator.client.IPv4.main(IPv4.java:471)
    Please help sir

    • Saddam Abu Ghaida says:

      you shouldn’t get this exception, i believe you need to escape / so you will write it like this 12.12.12.0\/27

  9. Sumeet says:

    Exception in thread “main” java.lang.Error: Unresolved compilation problem:
    Invalid escape sequence (valid ones are \b \t \n \f \r \” \’ \\ )

    • Andrei says:

      Try this regex in method validateIPAddress():
      “^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$”

  10. Saddam Abu Ghaida says:

    Hello,

    can you attach exception stack trace .

    Regards

  11. mamidiprashanth says:

    Actually iam running this cod ein netbeans and in windows 8 and iam getting many errors com.IPCalculator is not a valid one and and secong error at IPv4 at starting of String[] st = IPinCIDRFormat.split(“\/”);the code public class nad even (“\.”) even this is showing error error iilegal character.matches(“\A(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z”)) { error illegal character can u please help me out

  12. sankar balaji marikani says:

    Thanks for providing great post . I am have small hiccup using your
    library. Say for example take a example IP
    String ipInCIDR = “10.10.10.10/20”
    IPv4 parent = new IPv4 (ipInCIDR );
    IPv4 child= new IPv4 (ipInCIDR );
    System.out.println (parent.contains (child));

    The above code snippet should return true, instead it is returning false or is my understanding is wrong ? … Could you please enlighten me on the algorithm used for the method boolean contains (IPv4 child)

    • Saddam Abu Ghaida says:

      Hello Sankar,

      Contains refers to validate the possibility of an ip address could be a member in the same subnet,
      so the second IP Addess should be passed without subnet. I hope that it helps

      Regards

  13. din says:

    hello, can i run this code in eclipse juno ? and run ?

  14. din says:

    .matches(“^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$”)) {

    i have error at this. why ?

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

Swedish Greys - a WordPress theme from Nordic Themepark.