1Net::IP::Match::Regexp(U3s)er Contributed Perl DocumentatNieotn::IP::Match::Regexp(3)
2
3
4

NAME

6       Net::IP::Match::Regexp - Efficiently match IP addresses against ranges
7

LICENSE

9       Copyright 2005-2006 Clotho Advanced Media, Inc., <cpan@clotho.com>
10
11       Copyright 2007-2008 Chris Dolan, <cdolan@cpan.org>
12
13       This library is free software; you can redistribute it and/or modify it
14       under the same terms as Perl itself.
15

SYNOPSIS

17           use Net::IP::Match::Regexp qw( create_iprange_regexp match_ip );
18
19           my $regexp = create_iprange_regexp(
20              qw( 10.0.0.0/8 87.134.66.128 87.134.87.0/24 145.97.0.0/16 )
21           );
22           if (match_ip('209.249.163.62', $regexp)) {
23              ...
24           }
25

DESCRIPTION

27       This module allows you to check an IP address against one or more IP
28       ranges.  It employs Perl's highly optimized regular expression engine
29       to do the hard work, so it is very fast.  It is optimized for speed by
30       doing the match against a regexp which implicitly checks the broadest
31       IP ranges first.  An advantage is that the regexp can be computed and
32       stored in advance (in source code, in a database table, etc) and
33       reused, saving much time if the IP ranges don't change too often.  The
34       match can optionally report a value (e.g. a network name) instead of
35       just a boolean, which makes module useful for mapping IP ranges to
36       names or codes or anything else.
37

LIMITATIONS

39       This module does not yet support IPv6 addresses, although that feature
40       should not be hard to implement as long as the regexps start with a 4
41       vs. 6 flag.  Patches welcome.  :-)
42
43       This module only accepts IP ranges in "a.b.c.d/x" (aka CIDR) notation.
44       To work around that limitation, I recommend Net::CIDR::Lite to
45       conveniently convert collections of IP address ranges into CIDR format.
46
47       This module makes no effort to validate the IP addresses or ranges
48       passed as arguments.  If you pass address ranges like "1000.0.0.0/300",
49       you will probably get weird regexps out.
50

FUNCTIONS

52       create_iprange_regexp($iprange | $hashref | $arrayref, ...)
53           This function digests IP ranges into a regular expression that can
54           subsequently be used to efficiently test single IP addresses.  It
55           returns a regular expression string that can be passed to
56           match_ip().
57
58           The simple way to use this is to pass a list of IP ranges as
59           "aaa.bbb.ccc.ddd/n".  When used this way, the return value of the
60           match_ip() function will be simply 1 or "undef".
61
62           The more complex way is to pass a hash reference of IP range =>
63           return value pairs.  When used this way, the return value of the
64           match_ip() function will be the specified return value or "undef"
65           for no match.
66
67           For example:
68
69               my $re1 = create_iprange_regexp('209.249.163.0/25', '127.0.0.1/32');
70               print match_ip('209.249.163.62', $re1); # prints '1'
71
72               my $re2 = create_iprange_regexp({'209.249.163.0/25' => 'clotho.com',
73                                                '127.0.0.1/32' => 'localhost'});
74               print match_ip('209.249.163.62', $re2); # prints 'clotho.com'
75
76           Be aware that the value string will be wrapped in single quotes in
77           the regexp.  Therefore, you must double-escape any single quotes in
78           that value.  For example:
79
80               create_iprange_regexp({'208.201.239.36/31' => 'O\\'Reilly publishing'});
81
82           Note that the scalar and hash styles can be mixed (a rarely used
83           feature).  These two examples are equivalent:
84
85               create_iprange_regexp('127.0.0.1/32',
86                                     {'209.249.163.0/25' => 'clotho.com'},
87                                     '10.0.0.0/8',
88                                     {'192.168.0.0/16' => 'LAN'});
89
90               create_iprange_regexp({'127.0.0.1/32' => 1,
91                                      '209.249.163.0/25' => 'clotho.com',
92                                      '10.0.0.0/8' => 1,
93                                      '192.168.0.0/16' => 'LAN'});
94
95           If any of the IP ranges are overlapping, the broadest one is used.
96           If they are equivalent, then the first one passed is used.  If you
97           have some data that might be ambiguous, you pass an arrayref
98           instead of a hashref, but it's better to clean up your data
99           instead!  For example:
100
101               my $re = create_iprange_regexp(['1.1.1.0/31' => 'zero', '1.1.1.1/31' => 'one']);
102               print match_ip('1.1.1.1', $re));   # prints 'zero', since both match
103
104           WARNING: This function does no checking for validity of IP ranges.
105           It happily accepts "1000.0.0.0/-38" and makes a garbage regexp.
106           Hopefully a future version will validate the ranges, perhaps via
107           Net::CIDR or Net::IP.
108
109       create_iprange_regexp_depthfirst($iprange | $hashref | $arrayref, ...)
110           Returns a regexp in matches the most specific IP range instead of
111           the broadest range.  Example:
112
113               my $re = create_iprange_regexp_depthfirst({'192.168.0.0/16' => 'LAN',
114                                                          '192.168.0.1' => 'router'});
115               match_ip('192.168.0.1', $re);
116
117           returns 'router' instead of 'LAN'.
118
119       match_ip($ipaddr, $regexp)
120           Given a single IP address as a string of the form "aaa.bbb.ccc.ddd"
121           and a regular expression string (typically the output of
122           create_iprange_regexp()), this function returns a specified value
123           (typically 1) if the IP is in one of the ranges, or "undef" if no
124           ranges match.
125
126           See create_ipranges_regexp() for more details about the return
127           value of this function.
128
129           WARNING: This function does no checking for validity of the IP
130           address.
131

SEE ALSO

133       There are several other CPAN modules that perform a similar function.
134       This one is comparable to or faster than the other ones that I've found
135       and tried.  Here is a synopsis of those others:
136
137   Net::IP::Match
138       Optimized for speed by taking a "source filter" approach.  That is, it
139       modifies your source code at run time, kind of like a C preprocessor.
140       A huge limitation is that the IP ranges must be hard-coded into your
141       program.
142
143   Net::IP::Match::XS
144       (Also released as Net::IP::CMatch)
145
146       Optimized for speed by doing the match in C instead of in Perl.  This
147       module loses efficiency, however, because the IP ranges must be re-
148       parsed every invocation.
149
150   Net::IP::Resolver
151       Uses Net::IP::Match::XS to implement a range-to-name map.
152

PERFORMANCE

154       I ran a series of test on a Mac G5 with Perl 5.8.6 to compare this
155       module to Net::IP::Match::XS.  The tests are intended to be a realistic
156       net filter case: 100,000 random IP addresses tested against a number of
157       semi-random IP ranges.  Times are in seconds.
158
159           Networks: 1, IPs: 100000
160           Test name              | Setup time | Run time | Total time
161           -----------------------+------------+----------+------------
162           Net::IP::Match::XS     |    0.000   |  0.415   |    0.415
163           Net::IP::Match::Regexp |    0.001   |  1.141   |    1.141
164
165           Networks: 10, IPs: 100000
166           Test name              | Setup time | Run time | Total time
167           -----------------------+------------+----------+------------
168           Net::IP::Match::XS     |    0.000   |  0.613   |    0.613
169           Net::IP::Match::Regexp |    0.003   |  1.312   |    1.316
170
171           Networks: 100, IPs: 100000
172           Test name              | Setup time | Run time | Total time
173           -----------------------+------------+----------+------------
174           Net::IP::Match::XS     |    0.000   |  2.621   |    2.622
175           Net::IP::Match::Regexp |    0.024   |  1.381   |    1.405
176
177           Networks: 1000, IPs: 100000
178           Test name              | Setup time | Run time | Total time
179           -----------------------+------------+----------+------------
180           Net::IP::Match::XS     |    0.003   | 20.910   |   20.912
181           Net::IP::Match::Regexp |    0.203   |  1.514   |    1.717
182
183       This test indicates that ::Regexp is faster than ::XS when you have
184       more than about 50 IP ranges to test.  The relative run time does not
185       vary significantly with the number of singe IP to match, but with a
186       small number of IP addresses to match, the setup time begins to
187       dominate, so ::Regexp loses in that scenario.
188
189       To reproduce the above benchmarks, run the following command in the
190       distribution directory:
191
192          perl benchmark/speedtest.pl -s -n 1,10,100,1000 -i 100000
193

IMPLEMENTATION

195       The speed of this module comes from the short-circuit nature of regular
196       expressions.  The setup function turns all of the IP ranges into binary
197       strings, and mixes them into a regexp with "|" choices between ones and
198       zeros.  This regexp can then be passed to the match function.  When an
199       unambiguous match is found, the regexp sets a variable (via the regexp
200       $LAST_REGEXP_CODE_RESULT, aka $^R, feature) and terminates.  That
201       variable becomes the return value for the match, typically a true
202       value.
203
204       Here's an example of the regexp for a single range, that of the
205       Clotho.com subnet:
206
207           print create_iprange_regexp('209.249.163.0/25')'
208           # ^41101000111111001101000110(?{'1'})
209
210       If we add another range, say a NAT LAN, we get:
211
212           print create_iprange_regexp('209.249.163.0/25', '192.168.0.0/16')'
213           # ^4110(?>0000010101000(?{'1'})|1000111111001101000110(?{'1'}))
214
215       Note that for a 192.168.x.x address, the regexp checks at most the
216       first 16 bits (1100000010101000) whereas for a 209.249.163.x address,
217       it goes out to 25 bits (1101000111111001101000110).  The cool part is
218       that for an IP address that starts in the lower half (say 127.0.0.1)
219       only needs to check the first bit (0) to see that the regexp won't
220       match.
221
222       If mapped return values are specified for the ranges, they get embedded
223       into the regexp like so:
224
225           print create_iprange_regexp({'209.249.163.0/25' => 'clotho.com',
226                                        '192.168.0.0/16' => 'localhost'})'
227           # ^4110(?>0000010101000(?{'localhost'})|1000111111001101000110(?{'clotho.com'}))
228
229       This could be implemented in C to be even faster.  In C, it would
230       probably be better to use a binary tree instead of a regexp.  However,
231       a goal of this module is to create a serializable representation of the
232       range data, and the regexp is perfect for that.  So, I'll probably
233       never do a C version.
234

COMPATIBILITY

236       Because this module relies on the "(?{ code })" feature of regexps, it
237       won't work on old Perl versions.  I've successfully tested this module
238       on Perl 5.6.0, 5.8.1 and 5.8.6.  In theory, the code regexp feature
239       should work in 5.005, but I've used "our" and the like, so it won't
240       work there.  I don't have a 5.005 to test anyway...
241
242       Update from Oct 2008: I no longer keep a 5.6.0 around, so I rely on
243       cpantesters.org to tell me when this breaks for older Perls.
244

CODING

246       This module has 100% code coverage in its regression tests, as reported
247       by Devel::Cover via "perl Build testcover".
248
249       This module passes Perl Best Practices guidelines, as enforced by
250       Perl::Critic v1.093.
251

AUTHOR

253       Chris Dolan
254
255       I originally developed this module at Clotho Advanced Media Inc.  Now I
256       maintain it in my spare time.
257

ACKNOWLEDGMENTS

259       TeachingBooks.net inspired and subsidized development of the original
260       version of this module.
261
262       Chris Snyder contributed a valuable and well-written bug report about
263       handling missing mask values.
264
265       Michael Aronsen of cohaesio.com suggested the depth-first matching
266       feature.
267
268
269
270perl v5.36.0                      2023-01-20         Net::IP::Match::Regexp(3)
Impressum