expr->delete(expr, &pattern);
return 1;
}
-
-/* This function browse the pattern expr <expr> to lookup the key <key>. On
- * error it returns 0. On success, it returns 1 and fills either <pat_elt>
- * or <idx_elt> with the respectively matched pointers, and the other one with
- * NULL. Pointers are not set if they're passed as NULL.
- */
-int pattern_lookup(const char *key, struct pattern_expr *expr,
- struct pattern_list **pat_elt, struct pattern_tree **idx_elt, char **err)
-{
- struct pattern pattern;
- struct pattern_list *pat;
- struct ebmb_node *node;
- struct pattern_tree *elt;
- unsigned int mask = 0;
-
- /* no real pattern */
- if (!expr->match || expr->match == pat_match_nothing)
- return 0;
-
- /* build lookup pattern */
- if (!expr->parse(key, &pattern, NULL))
- return 0;
-
- pat = NULL;
- elt = NULL;
-
- /* Try to look up the tree first. IPv6 is not indexed */
- if (!eb_is_empty(&expr->pattern_tree) && pattern.type != SMP_T_IPV6) {
- /* Check the pattern type */
- if (pattern.type != SMP_T_STR &&
- pattern.type != SMP_T_IPV4) {
- memprintf(err, "Unexpected pattern type.");
- return 0;
- }
-
- /* Convert mask. If the mask is not contiguous, ignore the lookup
- * in the tree, and browse the list.
- */
- if (expr->match == pat_match_ip) {
- mask = ntohl(pattern.val.ipv4.mask.s_addr);
- if (mask + (mask & -mask) != 0)
- goto browse_list;
- mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
- }
-
- /* browse each node of the tree, and check string */
- if (expr->match == pat_match_str) {
- for (node = ebmb_first(&expr->pattern_tree);
- node;
- node = ebmb_next(node)) {
- elt = container_of(node, struct pattern_tree, node);
- if (strcmp(pattern.ptr.str, (char *)elt->node.key) == 0)
- goto found;
- }
- }
- else if (expr->match == pat_match_ip) {
- for (node = ebmb_first(&expr->pattern_tree);
- node;
- node = ebmb_next(node)) {
- elt = container_of(node, struct pattern_tree, node);
- if (elt->node.node.pfx == mask &&
- memcmp(&pattern.val.ipv4.addr.s_addr, elt->node.key, 4) == 0)
- goto found;
- }
- }
- }
-
-browse_list:
- elt = NULL;
- if (expr->parse == pat_parse_int ||
- expr->parse == pat_parse_len) {
- list_for_each_entry(pat, &expr->patterns, list) {
- if (pat->pat.flags & PAT_F_TREE)
- continue;
- if (pattern.val.range.min_set != pat->pat.val.range.min_set)
- continue;
- if (pattern.val.range.max_set != pat->pat.val.range.max_set)
- continue;
- if (pattern.val.range.min_set &&
- pattern.val.range.min != pat->pat.val.range.min)
- continue;
- if (pattern.val.range.max_set &&
- pattern.val.range.max != pat->pat.val.range.max)
- continue;
- goto found;
- }
- }
- else if (expr->parse == pat_parse_ip) {
- list_for_each_entry(pat, &expr->patterns, list) {
- if (pat->pat.flags & PAT_F_TREE)
- continue;
- if (pattern.type != pat->pat.type)
- continue;
- if (pattern.type == SMP_T_IPV4 &&
- memcmp(&pattern.val.ipv4.addr, &pat->pat.val.ipv4.addr, sizeof(pat->pat.val.ipv4.addr)) != 0)
- continue;
- if (pattern.type == SMP_T_IPV4 &&
- memcmp(&pattern.val.ipv4.mask, &pat->pat.val.ipv4.mask, sizeof(pat->pat.val.ipv4.addr)) != 0)
- continue;
- if (pattern.type == SMP_T_IPV6 &&
- memcmp(&pattern.val.ipv6.addr, &pat->pat.val.ipv6.addr, sizeof(pat->pat.val.ipv6.addr)) != 0)
- continue;
- if (pattern.type == SMP_T_IPV6 &&
- pattern.val.ipv6.mask != pat->pat.val.ipv6.mask)
- continue;
- goto found;
- }
- }
- else if (expr->parse == pat_parse_str) {
- list_for_each_entry(pat, &expr->patterns, list) {
- if (pat->pat.flags & PAT_F_TREE)
- continue;
- if (pattern.len != pat->pat.len)
- continue;
- if (pat->pat.flags & PAT_F_IGNORE_CASE) {
- if (strncasecmp(pattern.ptr.str, pat->pat.ptr.str, pat->pat.len) != 0)
- continue;
- }
- else {
- if (strncmp(pattern.ptr.str, pat->pat.ptr.str, pat->pat.len) != 0)
- continue;
- }
- goto found;
- }
- }
- else if (expr->parse == pat_parse_bin) {
- list_for_each_entry(pat, &expr->patterns, list) {
- if (pat->pat.flags & PAT_F_TREE)
- continue;
- if (pattern.len != pat->pat.len)
- continue;
- if (memcmp(pattern.ptr.ptr, pat->pat.ptr.ptr, pat->pat.len) != 0)
- continue;
- goto found;
- }
- }
- else if (expr->parse == pat_parse_reg) {
- list_for_each_entry(pat, &expr->patterns, list) {
- if (pat->pat.flags & PAT_F_TREE)
- continue;
- if (pat->pat.flags & PAT_F_IGNORE_CASE) {
- if (strcasecmp(pattern.ptr.reg->regstr, pat->pat.ptr.reg->regstr) != 0)
- continue;
- }
- else {
- if (strcmp(pattern.ptr.reg->regstr, pat->pat.ptr.reg->regstr) != 0)
- continue;
- }
- goto found;
- }
- }
-
- /* if we get there, we didn't find the pattern */
- return 0;
-found:
- if (idx_elt)
- *idx_elt = elt;
-
- if (pat_elt)
- *pat_elt = pat;
-
- return 1;
-}