Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

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