2
2
* ACL management functions.
4
* Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
4
* Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
6
6
* This program is free software; you can redistribute it and/or
7
7
* modify it under the terms of the GNU General Public License
251
251
return ACL_PAT_FAIL;
254
/* Background: Fast way to find a zero byte in a word
255
* http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
256
* hasZeroByte = (v - 0x01010101UL) & ~v & 0x80808080UL;
258
* To look for 4 different byte values, xor the word with those bytes and
259
* then check for zero bytes:
261
* v = (((unsigned char)c * 0x1010101U) ^ delimiter)
262
* where <delimiter> is the 4 byte values to look for (as an uint)
263
* and <c> is the character that is being tested
265
static inline unsigned int is_delimiter(unsigned char c, unsigned int mask)
267
mask ^= (c * 0x01010101); /* propagate the char to all 4 bytes */
268
return (mask - 0x01010101) & ~mask & 0x80808080U;
271
static inline unsigned int make_4delim(unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4)
273
return d1 << 24 | d2 << 16 | d3 << 8 | d4;
254
276
/* This one is used by other real functions. It checks that the pattern is
255
277
* included inside the tested string, but enclosed between the specified
256
* delimitor, or a '/' or a '?' or at the beginning or end of the string.
257
* The delimitor is stripped at the beginning or end of the pattern.
278
* delimiters or at the beginning or end of the string. The delimiters are
279
* provided as an unsigned int made by make_4delim() and match up to 4 different
280
* delimiters. Delimiters are stripped at the beginning and end of the pattern.
259
static int match_word(struct acl_test *test, struct acl_pattern *pattern, char delim)
282
static int match_word(struct acl_test *test, struct acl_pattern *pattern, unsigned int delimiters)
261
284
int may_match, icase;
266
289
pl = pattern->len;
267
290
ps = pattern->ptr.str;
268
while (pl > 0 && (*ps == delim || *ps == '/' || *ps == '?')) {
292
while (pl > 0 && is_delimiter(*ps, delimiters)) {
274
(ps[pl - 1] == delim || ps[pl - 1] == '/' || ps[pl - 1] == '?'))
297
while (pl > 0 && is_delimiter(ps[pl - 1], delimiters))
277
300
if (pl > test->len)
281
304
icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
282
305
end = test->ptr + test->len - pl;
283
306
for (c = test->ptr; c <= end; c++) {
284
if (*c == '/' || *c == delim || *c == '?') {
307
if (is_delimiter(*c, delimiters)) {
293
316
if ((tolower(*c) == tolower(*ps)) &&
294
317
(strncasecmp(ps, c, pl) == 0) &&
295
(c == end || c[pl] == '/' || c[pl] == delim || c[pl] == '?'))
318
(c == end || is_delimiter(c[pl], delimiters)))
296
319
return ACL_PAT_PASS;
298
321
if ((*c == *ps) &&
299
322
(strncmp(ps, c, pl) == 0) &&
300
(c == end || c[pl] == '/' || c[pl] == delim || c[pl] == '?'))
323
(c == end || is_delimiter(c[pl], delimiters)))
301
324
return ACL_PAT_PASS;
308
331
/* Checks that the pattern is included inside the tested string, but enclosed
309
* between slashes or at the beginning or end of the string. Slashes at the
310
* beginning or end of the pattern are ignored.
332
* between the delimiters '?' or '/' or at the beginning or end of the string.
333
* Delimiters at the beginning or end of the pattern are ignored.
312
335
int acl_match_dir(struct acl_test *test, struct acl_pattern *pattern)
314
return match_word(test, pattern, '/');
337
return match_word(test, pattern, make_4delim('/', '?', '?', '?'));
317
340
/* Checks that the pattern is included inside the tested string, but enclosed
318
* between dots or at the beginning or end of the string. Dots at the beginning
319
* or end of the pattern are ignored.
341
* between the delmiters '/', '?', '.' or ":" or at the beginning or end of
342
* the string. Delimiters at the beginning or end of the pattern are ignored.
321
344
int acl_match_dom(struct acl_test *test, struct acl_pattern *pattern)
323
return match_word(test, pattern, '.');
346
return match_word(test, pattern, make_4delim('/', '?', '.', ':'));
326
349
/* Checks that the integer in <test> is included between min and max */
332
355
return ACL_PAT_FAIL;
358
/* Checks that the length of the pattern in <test> is included between min and max */
359
int acl_match_len(struct acl_test *test, struct acl_pattern *pattern)
361
if ((!pattern->val.range.min_set || pattern->val.range.min <= test->len) &&
362
(!pattern->val.range.max_set || test->len <= pattern->val.range.max))
335
367
int acl_match_ip(struct acl_test *test, struct acl_pattern *pattern)
337
369
struct in_addr *s;
779
while (fgets(trash, sizeof(trash), file) != NULL) {
811
while (fgets(trash, trashlen, file) != NULL) {
783
814
/* ignore lines beginning with a dash */