Function to determine if IP is in CIDR network?

jason_lau
Tera Contributor

Is there an existing script class I can use to determine if an IP address is in a given CIDR range?

Basically I want to make a call like: isInCIDR(ip_addr, cidr) and it returns true or false. I'd like to do this without first converting CIDR to range and then using SncIPRangeV4 for example.

Or as a corollary, is there a function I can call where given an IP address, it will return the IP Network (cmdb_ci_ip_network) that IP belongs to, regardless if I have that IP address mapped in CMDB.

1 ACCEPTED SOLUTION

Chuck Tomasi
Tera Patron

Hi Jason,



Thanks for the inquiry. As far as I know, there's nothing OOB. It sounded like a fun thing to build on a weekend so... here's a script include you can use.



var CidrUtil = Class.create();


CidrUtil.prototype = {


  initialize: function() {


  },



  ipIsInCidr : function(ip, cidr) {


            var cidrIp = cidr.split('/')[0];


            var cidrSm = cidr.split('/')[1];



            return (this.IPnumber(ip) & this.IPmask(cidrSm)) == this.IPnumber(cidrIp);


  },



  IPnumber : function (IPaddress) {


            var ip = IPaddress.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);


            if(ip) {


                      return (+ip[1]<<24) + (+ip[2]<<16) + (+ip[3]<<8) + (+ip[4]);


            }


            // else ... ?


            return null;


  },



  IPmask : function(maskSize) {


            return -1<<(32-maskSize);


  },


  type: 'CidrUtil'


};



Here's a small example how it can be used:



var ip = '192.168.1.4';


var cidr = '192.168.1.0/24';



var cu = new CidrUtil();


gs.log(cu.ipIsInCidr(ip, cidr));


View solution in original post

16 REPLIES 16

yes, that's pretty much how I did it earlier. Function I wrote is getIpNetwork(ip) and it returns glide record of matching cmdb_ci_ip_network. I sort the results in ascending order by ip count (custom field) so it will return the most precise subnet defined in IP Networks.



I use that to determine default department assignment for new CI's: if the IP of a new CI is in a network that is 'owned' by a business unit / department, I use that department sourced from cmdb_ci_ip_network for the server ci.



(let me know how you guys are tagging code posts for formatting and I'll include sample).



-j


Click on "use advanced editor" then use the double right chevron/arrow button for syntax highlighting.



Sent from my iPhone


I took @Chuck Tomasi's code and added the "inRange" function, to validate the IP Address is part of a range.

Also took into consideration @jonathanriehle's suggestion over the regex and return 'undefined' to prevent false results.

var ipUtil = Class.create();
ipUtil.prototype = {
    initialize: function() {},

	// convert IP Address to numeric value
    IPnumber: function(IPaddress) {
        var ip = IPaddress.match(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);
        return (ip) ? (+ip[1] << 24) + (+ip[2] << 16) + (+ip[3] << 8) + (+ip[4]) : undefined;
    },

	// get un-mask bit from network mask
    IPmask: function(maskSize) {
        return -1 << (32 - maskSize);
    },

	// validate IP Address is member of a network based on id and mask
    inNetwork: function(IPaddress, NetworkIDandMask) {
        var NetworkID = NetworkIDandMask.split('/')[0];
        var NetworkMask = NetworkIDandMask.split('/')[1];
        return (this.IPnumber(IPaddress) & this.IPmask(NetworkMask)) == this.IPnumber(NetworkID);
    },

    // validate IP Address is between given Start-End IP Addresses
    inRange: function(startingIP, endingIP, IP) {
        return (this.IPnumber(startingIP) <= this.IPnumber(IP) && this.IPnumber(endingIP) >= this.IPnumber(IP)) ? true : false;
    },

    type: 'ipUtil'
};

//example code _ start
/*
var ip = '192.168.1.256'; // change .256 to a proper octet
var networkid = '192.168.1.0/24';
var network_start = "192.168.1.1";
var network_end = "192.168.1.256"; // change .256 to a proper octet
var cu = new ipUtil();
gs.print("inNetwork: " + cu.inNetwork(ip, networkid));
gs.print("inRange: " + cu.inRange(network_start,network_end,ip));
*/
// example code _ end

This code is not working for some situations in my code e.g. ip can be 145.54.0.236/30

Good afternoon @Girish Deshpan1 , @Girish Deshpan1 ,

Thank you very much for validating the solution!

I've reviewed the code and made the corresponding adjustments to make it work.

Also added extra functions.

var ipUtil = Class.create();
ipUtil.prototype = {
    initialize: function () {},

    // convert Integer to IP Address
    int2ip: function (ipInt) {
        return ((ipInt >>> 24) + '.' + (ipInt >> 16 & 255) + '.' + (ipInt >> 8 & 255) + '.' + (ipInt & 255));
    },

    // convert IP Address to Integer
    ip2int: function (ip) {
        return ip.split('.').reduce(function (ipInt, octet) {
            return (ipInt << 😎 + parseInt(octet, 10)
        }, 0) >>> 0;
    },

    // convert Binary to IP Address
    bin2ip: function (ipBinary) {
        return this.bin2num(ipBinary.slice(0, 8).join('')) + '.' +
            this.bin2num(ipBinary.slice(8, 16).join('')) + '.' +
            this.bin2num(ipBinary.slice(16, 24).join('')) + '.' +
            this.bin2num(ipBinary.slice(24, 32).join(''));
    },

    // convert Integer octet to binary
    oct2bin: function (oct) {
        oct = parseInt(oct);
        return "00000000".substr(oct.toString(2).length) + oct.toString(2);
    },

    // convert binary to Integer
    bin2num: function (bin) {
        return parseInt(bin, 2)
    },

    // convert IP Address to numeric value
    IPnumber: function (IPaddress) {
        var ip = IPaddress.match(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);
        //return (ip) ? (+ip[1] << 24) + (+ip[2] << 16) + (+ip[3] << 😎 + (+ip[4]) : undefined;
        return (ip) ? IPaddress.split('.').reduce(function (ipInt, octet) {
            return (ipInt << 😎 + parseInt(octet, 10)
        }, 0) >>> 0 : undefined;
    },

    // get un-mask bit from network mask
    IPmask: function (mask) {
        return -1 << (32 - mask);
    },

    // get network information
    getNetworkInfo: function (network) {
        var NetworkID = network.split('/')[0];
        var NetworkMask = network.split('/')[1];

        // check format
        if (!this.IPnumber(NetworkID) & !this.IPmask(NetworkMask)) {
            gs.print('network and mask format is incorrect');
            return {};
        }

        // iniciate variables
        var id, mask, start, end, broadcast;

        // set ip octets
        var tempIP = (
            this.oct2bin(NetworkID.split('.')[0]) +
            this.oct2bin(NetworkID.split('.')[1]) +
            this.oct2bin(NetworkID.split('.')[2]) +
            this.oct2bin(NetworkID.split('.')[3])
        ).split('').toString();
        // set mask as Integer
        mask = parseInt(NetworkMask);

        // set id as binary array
        id = tempIP.split(',');
        // set start
        start = tempIP.split(',');
        // set end
        end = tempIP.split(',');
        // set broadcast
        broadcast = tempIP.split(',');

        // set initial values
        for (var i = mask; i < id.length; i++) {
            id[i] = "0";
            start[i] = "0";
            broadcast[i] = "1";
            end[i] = "1";
        }
        // set start
        start[31] = "1";
        // set end
        end[31] = "0";

        // build response object
        var NetworkInfo = {
            'id': this.bin2ip(id),
            'mask': mask,
            'start': this.bin2ip(start),
            'end': this.bin2ip(end),
            'broadcast': this.bin2ip(broadcast)
        };

        return NetworkInfo;

    },

    // validate IP Address is between given Start-End IP Addresses
    inRange: function (startIP, endIP, IP) {
        return (this.IPnumber(startIP) <= this.IPnumber(IP) && this.IPnumber(endIP) >= this.IPnumber(IP)) ? true : false;
    },

    // validate IP Address is member of a network: id, broadcast or range
    inNetwork: function (IPaddress, Network) {
        return (IPaddress == Network.id || IPaddress == Network.broadcast || this.inRange(Network.start, Network.end, IPaddress)) ? true : false;
    },

    type: 'ipUtil'
};

//example code _ start
var ip = '145.54.0.240';
var network = '145.54.0.230/28';

var cu = new ipUtil();
var networkInfo = cu.getNetworkInfo(network);

gs.print('network id = ' + networkInfo.id);
gs.print('network mask = ' + networkInfo.mask);
gs.print('network start = ' + networkInfo.start);
gs.print('network end = ' + networkInfo.end);
gs.print('network broadcast = ' + networkInfo.broadcast);

gs.print("inNetwork: " + cu.inNetwork(ip, networkInfo));
gs.print("inRange: " + cu.inRange(networkInfo.start, networkInfo.end, ip));