tcpdump mailing list archives

Re: Sniffing ranges of ips


From: Jefferson Ogata <Jefferson.Ogata () noaa gov>
Date: Sat, 20 Nov 2004 16:29:29 -0500

MMatos wrote:
Note: I'm resending this message because i've sent it 20 hours ago and it wasn't arrived to the list (at least i wasn't received it yet).

I saw it yesterday.

Alexander Dupuy wrote:
Jefferson Ogata wrote:
Or you can do something more utilitarian, such as:

tcpdump [options] '( ip[12:4] >= 0xc0a8020f ) and ( ip[12:4] <= 0xc0a80228 )'

This doesn't support non-power-of-two ranges; for example addresses between 192.168.1.10 and 192.168.1.19. For something like that, with IPv4 you can use a hack like "(ip[12:4] >= 0x01020304) and (ip[12:4] <= 0x01020506)" to express that the source IP address should be within the range of 1.2.3.4 to 1.2.5.6 (inclusive). No simple expression exists for non-power-of-two IPv6 address ranges, but you could probably cobble up something only fairly heinous by computing enclosing power-of-two ranges using an adaptation of Jefferson Ogata's genrange.pl and aggregate.pl scripts and doing something similar with comparisons on low-order four-byte pieces of the address.

Yes solving that problem of unsopported non-power-of-two-ranges wouldn't
be much difficult

The aggregate.pl script I sent earlier did in fact have bugs (I apparently hadn't actually tested it in days of yore), so attached find a more correct implementation.

How can I know that a given bpf filter is correct for a given range by
analysing its opcodes? Maybe a link to to a doc lying somewhere?

Usually we trust it. But the code generator is a snarly rat's nest, and the optimizer is terrifying to behold. So it helps to know the virtual machine semantics. You can find them here, among other places:

http://www.tcpdump.org/papers/bpf-usenix93.pdf
http://www.freebsd.org/cgi/man.cgi?query=bpf&apropos=0&sektion=0&manpath=FreeBSD+5.3-RELEASE+and+Ports&format=html

--
Jefferson Ogata <Jefferson.Ogata () noaa gov>
NOAA Computer Incident Response Team (N-CIRT) <ncirt () noaa gov>
#!/usr/bin/perl -wT

my %in;
my %out;

my $me = $0;
$me =~ s/.*\///;

my $cidrOut = 0;

while (defined ($_ = shift))
{
    if (s/^\-//)
    {
        $cidrOut += s/c//g;

        next unless (length);
    }

    print STDERR <<EOT;
usage: $me [-c]
EOT
    exit (1);
}

while (defined ($_ = <STDIN>))
{
    chomp;
    my $line = $_;
    s/#.*$//;
    s/\s+//;
    next unless (length);
    die (qq{$.:$line}) unless (/^([\d\.]+)(?:\/(\d+))?$/);
    my ($ip, $bits) = ($1, $2);
    $bits = 32 unless (defined ($bits));
    $mask = &mask ($bits);
    $ip = &a2n ($ip) & $mask;

    # Eliminate subnets.
    foreach my $check (sort { $in{$b} <=> $in{$a}; } (keys (%in)))
    {
        my $checkMask = &mask ($in{$check});

        if (($check & $mask) == $ip)
        {
            delete ($in{$check});
        }
        elsif (($ip & $checkMask) == $check)
        {
            $ip = undef;
            last;
        }
    }
    next unless (defined ($ip));

    $in{$ip} = $bits;
}

# Aggregate what's left.
while (scalar (keys (%in)))
{
    foreach (sort { $in{$b} <=> $in{$a}; } (keys (%in)))
    {
        next unless (exists ($in{$_}));
        my $bits = $in{$_};
        my $other = $_ ^ (1 << (32 - $bits));
        if (exists ($in{$other}))
        {
            delete ($in{$_});
            delete ($in{$other});
            my $super = $_ & &mask ($bits - 1);
            $in{$super} = $bits - 1;
        }
        else
        {
            $out{$_} = $bits;
            delete ($in{$_});
        }
    }
}

foreach (sort { $a <=> $b; } (keys (%out)))
{
    my $addr = &n2a ($_);
    my $mask = $cidrOut ? $out{$_} : &n2a (&mask ($out{$_}));
    print qq($addr/$mask\n);
}


sub a2n
{
    return unpack ('N', pack ('C4', split (/\./, $_[0])));
}

sub n2a
{
    return join ('.', unpack ('C4', pack ('N', $_[0])));
}

sub mask
{
    my $bits = shift;
    return 0xffffffff if ($bits > 32);
    return 0 if ($bits < 1);
    return ~((1 << (32 - $bits)) - 1);
}


-
This is the tcpdump-workers list.
Visit https://lists.sandelman.ca/ to unsubscribe.

Current thread: