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
Be First to Comment