1Net::IP::Match::Regexp(U3s)er Contributed Perl DocumentatNieotn::IP::Match::Regexp(3)
2
3
4
6 Net::IP::Match::Regexp - Efficiently match IP addresses against ranges
7
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
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
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
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
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
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
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
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
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
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
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
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)