Поиск файла для соответствующего IP-адреса в Linux - PullRequest
2 голосов
/ 19 февраля 2012

У меня есть файл с выделенными диапазонами IP-адресов. Это выглядит примерно так:

...
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
...

У меня вопрос: возможно ли и как получить конкретную строку из этого файла, используя IP-адрес в качестве параметра поиска в Linux, используя такие инструменты, как grep, awk или некоторые другие инструменты.

например. если искомый IP равен 8.8.8.8, результат должен быть:

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

РЕДАКТИРОВАТЬ // Полный список ipv4 можно найти здесь http://skechboy.com/ips/ipv4_table

Ответы [ 3 ]

4 голосов
/ 19 февраля 2012

если 4-й и 5-й столбцы имеют сетевой префикс и маску подсети , то для ввода ввода для 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,

Пример

$ 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
.

выход

x|x|ipv4|192.168.5.192|64|x|x
x|x|ipv4|192.168.5.0|256|x|x
4 голосов
/ 19 февраля 2012

Вот реализация awk метода @ugoren:

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
1 голос
/ 19 февраля 2012

awk можно использовать следующим образом:
1. Запустите с параметром -F'|', чтобы разделить вертикальной чертой.Теперь $4 - это первый адрес, $5 - это размер сети.
2. Используйте split($4,addr,'.'), чтобы получить массив a с четырьмя частями адреса
3. Выполните некоторые вычисления, чтобы получить числовойадрес: range_start=a[0]*16777216+a[1]*65536+a[2]*256+a[3].
4. Выполните те же вычисления с адресом, который вы ищете.
5. Теперь просто проверьте, находится ли адрес в диапазоне от range_start до range_start+$5* 1015.*

...