Click here to Skip to main content
14,775,705 members
Articles » Languages » Java » General
Tip/Trick
Posted 6 Dec 2014

Tagged as

Stats

36.6K views
7 bookmarked

IP/Subnet Calculator Lib

Rate me:
Please Sign up or sign in to vote.
4.91/5 (3 votes)
6 Dec 2014BSD
IP/Subnet Calculator Lib

Introduction

I created an IP/subnetting library using Java a long time ago, and the reason why I created it is because there were no available Java libraries to do this kind of calculations or at least the way i wanted it, so I created my own with the help of my friend, Nicolai Tufar.

Background

IP subnetting is quite a burdensome task especially when it comes to large scales IP Providers, and on a smaller scale, it is pretty confusing such as you work with Subnet mask all the time when it comes to network or network programming, and I wanted to do an application to manage this quite troublesome issue, and me and my friend cam up with this library.

Using the Code

The code included below is a library you just add the class to your project and start using it instantly.

This code will give you the following features:

  • Convert form CIDR to VLSM and the other way around
  • Number of Hosts per subnet and the IP Ranges
  • Matches of Two IP Address is related to the same subnet
  • Gives a binary representation for the IP address
  • Gives the wildcard subnet mask of the given network ID or subnet
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;
    }
}

And here is an example of how to use the library and what you can get out of it.

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


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(ipv4.contains(ipv4Child));

History

  • Version 1.0 - > 2014-12-06

License

This article, along with any associated source code and files, is licensed under The BSD License

Share

About the Author

saddam abu ghaida
Team Leader CCC
Greece Greece
Nothing Much i love reading and developing new things and thats about it

Comments and Discussions

 
QuestiongetHostAddressRange Pin
Member 1408372110-Dec-18 0:04
MemberMember 1408372110-Dec-18 0:04 
QuestionReally comes as an Great Help to me .. Pin
Member 102303006-Feb-17 19:31
MemberMember 102303006-Feb-17 19:31 
Suggestionadd a method to validate the correct IP Pin
jasonZhouChao21-Dec-14 17:28
MemberjasonZhouChao21-Dec-14 17:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.