#!/usr/bin/perl -w use strict; # BrowserUk's conversion subs sub bin2dd{ join '.', unpack 'C4', pack 'N', $_[0] } sub dd2bin{ unpack 'N', pack 'C4', split '\.', $_[0] } my @ips; push @ips, shift while @ARGV && -1 == index $ARGV[0], '/'; die "usage: $0 IPs subnets\n" unless @ips && @ARGV; my %subnets; foreach my $subnet (@ARGV) { my ($net, $plen) = split /\//, $subnet; $net .= '.0' x (3 - $net =~ tr/.//); my $net_bin = dd2bin $net; my $zero_bits = ~(~0 << 32-$plen); if ($net_bin & $zero_bits) { print STDERR "warning: fixing $net/$plen => "; $net_bin &= ~$zero_bits; $net = bin2dd $net_bin; print STDERR "$net/$plen\n"; } $subnets{"$net_bin/$plen"} = "$net/$plen"; } foreach my $ip (@ips) { my $ip_bin = dd2bin $ip; foreach my $plen (8..32) { my $key = (~0 << 32-$plen & $ip_bin) . "/$plen"; if (exists $subnets{$key}) { print "$ip matches $subnets{$key}\n"; # last; } } } __END__ $ ip-in-subnet.pl 192.168.1.7 64.96.128.11 2.219.155.11 \ 8.8.8.8 64.96.128.0/28 64.96.128.0/17 64.96.128.11/32 64/8 \ 192.168.1.0/24 192.168/16 8/8 2.219/16 192.168.1.7 matches 192.168.0.0/16 192.168.1.7 matches 192.168.1.0/24 64.96.128.11 matches 64.0.0.0/8 64.96.128.11 matches 64.96.128.0/17 64.96.128.11 matches 64.96.128.0/28 64.96.128.11 matches 64.96.128.11/32 2.219.155.11 matches 2.219.0.0/16 8.8.8.8 matches 8.0.0.0/8