Splunk Search

How can I calculate CIDR Range?

atebysandwich
Path Finder

I have two fields: Network_Address and Netmask. The Network_Address field has the network address of the network as field values and the Netmask field has the network mask as it's value. Here is an example:

Network_Address Netmask

10.1.1.0                       255.255.255.0

How can I write a search so Splunk tells me the CIDR subnet rage for the two fields? I need the output to be put in a new field named CIDR. 

Labels (5)
0 Karma
1 Solution

atebysandwich
Path Finder

This is what worked between @yuanliu and @ITWhisperer suggestions:

| eval bitmask = split(Netmask, ".")
| eval bitmask = 32 - sum(mvmap(bitmask, log(256 - bitmask,2)))
| eval CIDR = Network_Address . "/" . bitmask 

 

View solution in original post

0 Karma

tfujita_splunk
Splunk Employee
Splunk Employee

FYI,

I added the following external command lookup to the App below.

Usage:

| makeresults
| eval Network_Address="10.1.1.0", Netmask="255.255.255.0"

| eval ip=Network_Address."/".Netmask
| lookup local=t ipcalclookup Address as ip OUTPUT Network Prefix
| eval CIDR=Network."/".Prefix

Numeral system macros for Splunk
https://splunkbase.splunk.com/app/6595 

0 Karma

atebysandwich
Path Finder

This is what worked between @yuanliu and @ITWhisperer suggestions:

| eval bitmask = split(Netmask, ".")
| eval bitmask = 32 - sum(mvmap(bitmask, log(256 - bitmask,2)))
| eval CIDR = Network_Address . "/" . bitmask 

 

0 Karma

tscroggins
Influencer

@atebysandwich 

It's a tidy solution. Just keep in mind that it assumes Netmask is a valid network mask and Network_Address is a valid network address relative to Netmask. If either assumption is false, the resulting CIDR value is invalid.

0 Karma

tscroggins
Influencer

To simplify netmask validation, I would introduce a lookup, e.g. netmask_lookup:

netmask,sigbits
0.0.0.0,0
128.0.0.0,1
192.0.0.0,2
224.0.0.0,3
240.0.0.0,4
248.0.0.0,5
252.0.0.0,6
254.0.0.0,7
255.0.0.0,8
255.128.0.0,9
255.192.0.0,10
255.224.0.0,11
255.240.0.0,12
255.248.0.0,13
255.252.0.0,14
255.254.0.0,15
255.255.0.0,16
255.255.128.0,17
255.255.192.0,18
255.255.224.0,19
255.255.240.0,20
255.255.248.0,21
255.255.252.0,22
255.255.254.0,23
255.255.255.0,24
255.255.255.128,25
255.255.255.192,26
255.255.255.224,27
255.255.255.240,28
255.255.255.248,29
255.255.255.252,30
255.255.255.254,31
255.255.255.255,32
| lookup netmask_lookup netmask as Netmask output sigbits

If sigbits (significant bits) is null, the netmask is invalid, and the network cannot be expressed in CIDR notation.

To mask the address using a valid netmask, let's introduce a macro to perform a bitwise AND between two 8-bit values [1]:

 

[bitand_8(2)]
args = x, y
definition = sum(1 * (floor($x$ / 1) % 2) * (floor($y$ / 1) % 2), 2 * (floor($x$ / 2) % 2) * (floor($y$ / 2) % 2), 4 * (floor($x$ / 4) % 2) * (floor($y$ / 4) % 2), 8 * (floor($x$ / 8 ) % 2) * (floor($y$ / 8 ) % 2), 16 * (floor($x$ / 16) % 2) * (floor($y$ / 16) % 2), 32 * (floor($x$ / 32) % 2) * (floor($y$ / 32) % 2), 64 * (floor($x$ / 64) % 2) * (floor($y$ / 64) % 2), 128 * (floor($x$ / 128) % 2) * (floor($y$ / 128) % 2))
iseval = 0

 

Combining all of the above:

| makeresults
| eval Network_Address="10.1.1.0", Netmask="255.255.255.0"
| lookup netmask_lookup netmask as Netmask output sigbits
| eval addr_octets=split(Network_Address, "."), netmask_octets=split(Netmask, ".")
| eval x=tonumber(mvindex(addr_octets, 0, 0)), y=tonumber(mvindex(netmask_octets, 0, 0)), addr0=`bitand_8(x, y)`
| eval x=tonumber(mvindex(addr_octets, 1, 1)), y=tonumber(mvindex(netmask_octets, 1, 1)), addr1=`bitand_8(x, y)`
| eval x=tonumber(mvindex(addr_octets, 2, 2)), y=tonumber(mvindex(netmask_octets, 2, 2)), addr2=`bitand_8(x, y)`
| eval x=tonumber(mvindex(addr_octets, 3, 3)), y=tonumber(mvindex(netmask_octets, 3, 3)), addr3=`bitand_8(x, y)`
| eval CIDR=addr0.".".addr1.".".addr2.".".addr3."/".sigbits

=> 10.1.1.0/24

We can validate with several cases:

| eval Network_Address="10.1.1.0", Netmask="255.255.254.0"

=> 10.1.0.0/23

| eval Network_Address="10.1.1.32", Netmask="0.0.0.0"

=> 0.0.0.0/0 (the default route)

| eval Network_Address="10.1.1.32", Netmask="255.255.255.255"

=> 10.1.1.32/32 (the host route)

| eval Network_Address="10.1.1.32", Netmask="255.0.255.0"

=> null (invalid netmask)

A simpler solution overall--and one compatible with both IPv4 and IPv6--would offload the work to either a custom command or an external lookup, but the above steps should work for any unprivileged Splunk user.

EDIT: I'm apparently stuck in a pre-9.0 world. You can replace the eval and bitand logic with a single ipmask() eval function [2]. That said, it isn't difficult to perform bitwise operations in core Splunk up to a certain size. For IPv6, you're still better off implementing a custom command or external lookup.

1. https://en.wikipedia.org/wiki/Bitwise_operation#Mathematical_equivalents
2. https://docs.splunk.com/Documentation/Splunk/9.0.4/SearchReference/ConversionFunctions#ipmask.28.26l...

0 Karma

yuanliu
SplunkTrust
SplunkTrust

Not so much a search, but mere calculation using the definition.

 

| eval bitmask = split(Netmask, ".")
| eval bitmask = sum(mvmap(bitmask, log(bitmask + 1, 2)))
| eval CIDR = Network_Address . "/" . bitmask

 

Your sample data will return

CIDRNetmaskNetwork_Addressbitmask
10.1.1.0/24255.255.255.010.1.1.024
Tags (2)

atebysandwich
Path Finder

This seemed work for the most part. The only I issue I see is some of the values in the new CIDR field have .99435343685886 at the end.

Example:

Network address            Netmask                          CIDR
10.21.72.1                       255.255.254.0                  10.21.72.0/23.99435343685886

Is there a way to trim the "." and the numbers to the right off it off?

0 Karma

ITWhisperer
SplunkTrust
SplunkTrust

@yuanliu  is close but it fails for mask which aren't 255 - try flipping it to subtract the number of missing bits from 32

| eval bitmask = 32 - sum(mvmap(bitmask, log(256 - bitmask,2)))

atebysandwich
Path Finder

Haha I didn't see this before I replied back to @yuanliu  post. Your idea did the trick. Thank you both for the help!

0 Karma
Get Updates on the Splunk Community!

Index This | I am a number, but when you add ‘G’ to me, I go away. What number am I?

March 2024 Edition Hayyy Splunk Education Enthusiasts and the Eternally Curious!  We’re back with another ...

What’s New in Splunk App for PCI Compliance 5.3.1?

The Splunk App for PCI Compliance allows customers to extend the power of their existing Splunk solution with ...

Extending Observability Content to Splunk Cloud

Register to join us !   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to ...