views:

468

answers:

3

Hey I'm a total n00b at Regular Expressions. I'm wondering if this is the best way to match a string that starts with a private IP address (Perl-style Regex):

(^127\.0\.0\.1)|(^192\.168)|(^10\.)|(^172\.1[6-9])|(^172\.2[0-9])|(^172\.3[0-1])

Thanks much!

A: 

Looks right. Personally, I'd change the first one to:

^127.0

With this: (^127.0.0.1) you looking for anything that starts with 127.0.0.1 and will miss out on 127.0.0.2*, 127.0.2., 127.0. etc.

HTH,

KM

KM
+3  A: 

I'm assuming you want to match these ranges:

127.  0.0.1
 10.  0.0.0 –  10.255.255.255
172. 16.0.0 – 172. 31.255.255
192.168.0.0 – 192.168.255.255

You are missing some dots that would cause it to accept for example 172.169.0.0 even though this should not be accepted. I've fixed it below. Remove the new lines, it's just for readability.

(^127\.0\.0\.1)|
(^10\.)|
(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|
(^192\.168\.)

Also note that this assumes that the IP addresses have already been validated - it accepts things like 10.foobar.

Mark Byers
A: 

This is in case you decide to go with my comment, suggesting you don't use regexps. Untested (but probably works, or at least close), in Perl:

@private = (
    {network => inet_aton('127.0.0.0'),   mask => inet_aton('255.0.0.0')   },
    {network => inet_aton('192.168.0.0'), mask => inet_aton('255.255.0.0') },
    # ...
);

$ip = inet_aton($ip_text);
if (grep $ip & $_->{mask} == $_->{network}, @private) {
    # ip address is private
} else {
    # ip address is not private
}

Note now how @private is just data, which you can easily change. Or download on the fly from the Cymru Bogon Reference.

edit: It occurs to me that asking for a Perl regexp doesn't mean you know Perl, so the key line is there is the 'grep', which just loops over each private address range. You take your IP, bitwise and it with the netmask, and compare to the network address. If equal, its part of that private network.

derobert