DISABLE ADBLOCK

ADBlock is blocking some content on the site

ADBlock errore

Search file for matching IP address in Linux

StackOverflow https://stackoverflow.com/questions/9351292

Question

I have file with allocated IP address ranges. It looks something like this:

...
arin|US|ipv4|8.0.0.0|16777216|19921201|allocated
arin|US|ipv4|9.0.0.0|16777216|19881216|assigned
apnic|ID|ipv4|122.200.144.0|2048|20061023|allocated
apnic|TW|ipv4|122.200.152.0|2048|20080424|allocated
apnic|AU|ipv4|122.200.160.0|4096|20061020|allocated
apnic|AU|ipv4|122.200.176.0|4096|20110121|allocated
apnic|JP|ipv4|122.200.192.0|8192|20061023|allocated
...

My question is if it is possible and how to get specific row from this file using an IP address as search parameter in Linux by using tools like grep, awk or some other tools.

e.g. if the searched IP is 8.8.8.8 the result should be:

arin|US|ipv4|8.0.0.0|16777216|19921201|allocated

EDIT// FUll ipv4 list can be found here http://skechboy.com/ips/ipv4_table

Solution

if 4th and 5th columns are network prefix and subnet mask then to grep input for an ip:

#!/usr/bin/env python
import fileinput, socket, struct, sys

# x.x.x.x string -> integer
ip2int = lambda ipstr: struct.unpack('!I', socket.inet_aton(ipstr))[0]    

ip = ip2int(sys.argv.pop(1)) # get ip from command-line
for line in fileinput.input(): # read from stdin or file(s) given at command-line
    try:
        family, network_prefix, subnet_mask = line.split('|')[2:5]
        if (family == 'ipv4' and
            (ip & (2**32 - int(subnet_mask))) == ip2int(network_prefix)):
            print line,
    except Exception:
        print >>sys.stderr, "can't parse", line,

Example

$ python grep-ip.py 192.168.5.193 <<'.'
x|x|ipv4|192.168.5.128|64|x|x
x|x|ipv4|192.168.5.192|64|x|x
x|x|ipv4|192.168.5.0|64|x|x
x|x|ipv4|192.168.5.0|256|x|x
.

Output

x|x|ipv4|192.168.5.192|64|x|x
x|x|ipv4|192.168.5.0|256|x|x

OTHER TIPS

Here is the awk implementation of @ugoren method:

sphynx@fjord% cat ipgrep.awk

BEGIN { FS = "|"; }

{
    ip = ip2num(ADDR);
    network_start = ip2num($4);
    network_length = $5;
    if (ip >= network_start && ip <= network_start + network_length) {
        print;
    }
}

function ip2num(ip)
{
    split(ip, addr, ".");
    return addr[1] * 2^24 + addr[2] * 2^16 + addr[3] * 2^8 + addr[4];
}


sphynx@fjord% awk -v ADDR=8.8.8.8 -f ipgrep.awk data 
arin|US|ipv4|8.0.0.0|16777216|19921201|allocated

awk can be used, this way:
1. Run with the -F'|' parameter, to separate by the vertical bar. Now $4 is the first address, $5 is the network size.
2. Use split($4,addr,'.') To get an array a with the 4 address parts
3. Do some math to get the numeric address: range_start=a[0]*16777216+a[1]*65536+a[2]*256+a[3].
4. Do the same math on the address you're looking for.
5. Now just check if the address is in the range, between range_start and range_start+$5

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow