Skip to content

DataTables filter by ip address

DataTables filter by ip address

I had to make a custom filter for ip address which accepted cidr notation (e.g /24). While there was the function to sort by ip at the time when i was doing it, a filter by ip address that accepted cidr or subnet masks function didn’t seem to have been implemented. I couldn’t find any publicly available solution online either, so i took some time to implement it. The solution is in php but can be easily ported to javascript/html if you wish

To get it to work on your own code, you will have to modify the 2 variables

var ipColNum = 0; // column number of your ip address

var tableId = “#results”; // table id that you want to attach datatables to

<!--jquery-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!--datatables-->
<link rel='stylesheet' type='text/css' href='//cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css'/>
<script type='text/javascript' src='//cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js'></script>


<table id="results">
  <thead>
    <tr>
      <th>Ip Address</th>
      <th>Name</th>
      <th>Country</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>192.168.0.1</td>
      <td>abc</td>
      <td>abc country</td>
    </tr>
    <tr>
      <td>122.20.21.133</td>
      <td>xyz</td>
      <td>xyz country</td>
    </tr>
    <tr>
      <td>192.168.0.10</td>
      <td>john</td>
      <td>john country</td>
    </tr>
    <tr>
      <td>192.168.1.1</td>
      <td>sally</td>
      <td>sally country</td>
    </tr>
  </tbody>
</table>


<script>
    var table = null;
    var ipColNum = 0; // set the column number for the ip address
    var tableId = "#results";
    
    function getIpRangeFromAddressAndNetmask(str) {
      var part = str.split("/"); // part[0] = base address, part[1] = netmask
      var ipaddress = part[0].split('.');
      var netmaskblocks = ["0","0","0","0"];
      if(!/\d+\.\d+\.\d+\.\d+/.test(part[1])) {
        // part[1] has to be between 0 and 32
        netmaskblocks = ("1".repeat(parseInt(part[1], 10)) + "0".repeat(32-parseInt(part[1], 10))).match(/.{1,8}/g);
        netmaskblocks = netmaskblocks.map(function(el) { return parseInt(el, 2); });
      } else {
        // xxx.xxx.xxx.xxx
        netmaskblocks = part[1].split('.').map(function(el) { return parseInt(el, 10) });
      }
      var invertedNetmaskblocks = netmaskblocks.map(function(el) { return el ^ 255; });
      var baseAddress = ipaddress.map(function(block, idx) { return block & netmaskblocks[idx]; });
      var broadcastaddress = ipaddress.map(function(block, idx) { return block | invertedNetmaskblocks[idx]; });
      return [baseAddress.join('.'), broadcastaddress.join('.')];
    }

  function ip2long(IP) {
    var i = 0;
    IP = IP.match( /^([1-9]\d*|0[0-7]*|0x[\da-f]+)(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?$/i );
    if (!IP) { return false; }
    IP[0] = 0;
    for (i = 1; i < 5; i += 1) {
      IP[0] += !!((IP[i] || '').length);
      IP[i] = parseInt(IP[i]) || 0;
    }
    IP.push(256, 256, 256, 256);
    IP[4 + IP[0]] *= Math.pow(256, 4 - IP[0]);
    if (IP[1] >= IP[5] || IP[2] >= IP[6] || IP[3] >= IP[7] || IP[4] >= IP[8]) { return false; }
    return IP[1] * (IP[0] === 1 || 16777216) + IP[2] * (IP[0] <= 2 || 65536) + IP[3] * (IP[0] <= 3 || 256) + IP[4] * 1;
  }

//https://www.jqueryscript.net/demo/DataTables-Jquery-Table-Plugin/examples/plug-ins/range_filtering.html
var ipFilter = function(searchValue) {
    $.fn.dataTable.ext.search.push(
        function( settings, data, dataIndex ) {
            console.log("srchValue" + searchValue);
            var ipRange = searchValue;
            var colIpAddr = data[0]; // use data for the age column
     				var range = getIpRangeFromAddressAndNetmask(ipRange);
            var min = ip2long(range[0]);
            var max = ip2long(range[1]);

            //console.log(ipRange);
            //console.log("min : " + min + " max : " + max);
            //console.log("chk : " + colIpAddr);

            var longIpAddr = ip2long(colIpAddr);
            
            if( longIpAddr >= min && longIpAddr <= max ) {
                return true;
            }
            return false;
        }
    );

    table.draw();
    $.fn.dataTable.ext.search.pop();
};

 

$(document).ready( function () {
    table = $(tableId).DataTable({
        responsive: true
    });

    if( !table ) {
        console.log("Failed to initialize DataTable()");
    } else {
   
        // Change filter algorithm when cidr notation detected
        $('.dataTables_filter input').unbind().keyup(function() 
        {
            var value = $(this).val();
            if (value.length==0) {
                table.search('').draw();
                return;
            }

            // Must have the format xxx.xxx.xxx.xxx/0-32 
            // Does not match any string without a '/<number>' at the back.
            if( /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))$/.test(value) ) {
                // We need to reset the table first, otherwise our filter won't work 
                // probably because it detects e.g 192.168.0.1/32 -> 192.168.0.1, 192.168.0.1/ , 192.168.0.1/3, 192.168.0.1/32. The earlier 2 has to results.
       
                table.search('').draw();
                ipFilter(value);
            } else {
                table.search(value).draw();
            }
        });
        
    }
} );


</script>

 

See it in action over at the JsFiddle : here or below .You can test it out by putting a search value of “192.168.0.0/23” or any others of your choice

Enjoyed the content ? Share it with your friends !
Published inProgramming

Be First to Comment

Leave a Reply

Your email address will not be published.