MEDIUM: pattern: add sample lookup function.
Some functions needs to change the sample associated to pattern. This
new pointer permit to return the a pointer to the sample pointer. The
caller can use or change the value.
diff --git a/src/pattern.c b/src/pattern.c
index 170955f..48cec0d 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -88,6 +88,23 @@
[PAT_MATCH_REG] = pat_del_list_reg,
};
+struct sample_storage **(*pat_find_smp_fcts[PAT_MATCH_NUM])(struct pattern_expr *,
+ struct pattern *) = {
+ [PAT_MATCH_FOUND] = pat_find_smp_list_val,
+ [PAT_MATCH_BOOL] = pat_find_smp_list_val,
+ [PAT_MATCH_INT] = pat_find_smp_list_val,
+ [PAT_MATCH_IP] = pat_find_smp_tree_ip,
+ [PAT_MATCH_BIN] = pat_find_smp_list_ptr,
+ [PAT_MATCH_LEN] = pat_find_smp_list_val,
+ [PAT_MATCH_STR] = pat_find_smp_tree_str,
+ [PAT_MATCH_BEG] = pat_find_smp_list_str,
+ [PAT_MATCH_SUB] = pat_find_smp_list_str,
+ [PAT_MATCH_DIR] = pat_find_smp_list_str,
+ [PAT_MATCH_DOM] = pat_find_smp_list_str,
+ [PAT_MATCH_END] = pat_find_smp_list_str,
+ [PAT_MATCH_REG] = pat_find_smp_list_reg,
+};
+
void (*pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *) = {
[PAT_MATCH_FOUND] = pat_prune_val,
[PAT_MATCH_BOOL] = pat_prune_val,
@@ -1212,6 +1229,189 @@
return 1;
}
+struct sample_storage **pat_find_smp_list_val(struct pattern_expr *expr, struct pattern *pattern)
+{
+ struct pattern_list *pat;
+ struct pattern_list *safe;
+
+ list_for_each_entry_safe(pat, safe, &expr->patterns, list) {
+
+ /* Check equality. */
+ 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;
+
+ /* Return the pointer on the sample pointer. */
+ return &pat->pat.smp;
+ }
+
+ return NULL;
+}
+
+struct sample_storage **pat_find_smp_tree_ip(struct pattern_expr *expr, struct pattern *pattern)
+{
+ struct ebmb_node *node, *next_node;
+ struct pattern_tree *elt;
+ struct pattern_list *pat;
+ struct pattern_list *safe;
+ unsigned int mask;
+
+ /* browse each node of the tree for IPv4 addresses. */
+ if (pattern->type == SMP_T_IPV4) {
+ /* Convert mask. If the mask is contiguous, browse each node
+ * of the tree for IPv4 addresses.
+ */
+ mask = ntohl(pattern->val.ipv4.mask.s_addr);
+ if (mask + (mask & -mask) == 0) {
+ mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
+
+ for (node = ebmb_first(&expr->pattern_tree), next_node = ebmb_next(node);
+ node;
+ node = next_node, next_node = next_node ? ebmb_next(next_node) : NULL) {
+ /* Extract container of the tree node. */
+ elt = container_of(node, struct pattern_tree, node);
+
+ /* Check equality. */
+ if (strcmp(pattern->ptr.str, (char *)elt->node.key) != 0)
+ continue;
+
+ /* Return the pointer on the sample pointer. */
+ return &elt->smp;
+ }
+ }
+ else {
+ /* Browse each node of the list for IPv4 addresses. */
+ list_for_each_entry_safe(pat, safe, &expr->patterns, list) {
+ /* Check equality. */
+ if (memcmp(&pattern->val.ipv4.addr, &pat->pat.val.ipv4.addr,
+ sizeof(pat->pat.val.ipv4.addr)) != 0)
+ continue;
+ if (memcmp(&pattern->val.ipv4.mask, &pat->pat.val.ipv4.mask,
+ sizeof(pat->pat.val.ipv4.addr)) != 0)
+ continue;
+
+ /* Return the pointer on the sample pointer. */
+ return &pat->pat.smp;
+ }
+ }
+ }
+ else if (pattern->type == SMP_T_IPV6) {
+ /* browse each node of the tree for IPv4 addresses. */
+ for (node = ebmb_first(&expr->pattern_tree_2), next_node = ebmb_next(node);
+ node;
+ node = next_node, next_node = next_node ? ebmb_next(next_node) : NULL) {
+ /* Extract container of the tree node. */
+ elt = container_of(node, struct pattern_tree, node);
+
+ /* Check equality. */
+ if (strcmp(pattern->ptr.str, (char *)elt->node.key) != 0)
+ continue;
+
+ /* Return the pointer on the sample pointer. */
+ return &elt->smp;
+ }
+ }
+
+ return NULL;
+}
+
+struct sample_storage **pat_find_smp_list_ptr(struct pattern_expr *expr, struct pattern *pattern)
+{
+ struct pattern_list *pat;
+ struct pattern_list *safe;
+
+ list_for_each_entry_safe(pat, safe, &expr->patterns, list) {
+ /* Check equality. */
+ if (pattern->len != pat->pat.len)
+ continue;
+ if (memcmp(pattern->ptr.ptr, pat->pat.ptr.ptr, pat->pat.len) != 0)
+ continue;
+
+ /* Return the pointer on the sample pointer. */
+ return &pat->pat.smp;
+ }
+
+ return NULL;
+}
+
+struct sample_storage **pat_find_smp_tree_str(struct pattern_expr *expr, struct pattern *pattern)
+{
+ struct ebmb_node *node, *next_node;
+ struct pattern_tree *elt;
+
+ /* browse each node of the tree. */
+ for (node = ebmb_first(&expr->pattern_tree), next_node = ebmb_next(node);
+ node;
+ node = next_node, next_node = next_node ? ebmb_next(next_node) : NULL) {
+ /* Extract container of the tree node. */
+ elt = container_of(node, struct pattern_tree, node);
+
+ /* Check equality. */
+ if (strcmp(pattern->ptr.str, (char *)elt->node.key) != 0)
+ continue;
+
+ /* Return the pointer on the sample pointer. */
+ return &elt->smp;
+ }
+
+ return NULL;
+}
+
+struct sample_storage **pat_find_smp_list_str(struct pattern_expr *expr, struct pattern *pattern)
+{
+ struct pattern_list *pat;
+ struct pattern_list *safe;
+
+ list_for_each_entry_safe(pat, safe, &expr->patterns, list) {
+ /* Check equality. */
+ 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;
+ }
+
+ /* Return the pointer on the sample pointer. */
+ return &pat->pat.smp;
+ }
+
+ return NULL;
+}
+
+struct sample_storage **pat_find_smp_list_reg(struct pattern_expr *expr, struct pattern *pattern)
+{
+ struct pattern_list *pat;
+ struct pattern_list *safe;
+
+ list_for_each_entry_safe(pat, safe, &expr->patterns, list) {
+ /* Check equality. */
+ 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;
+ }
+
+ /* Return the pointer on the sample pointer. */
+ return &pat->pat.smp;
+ }
+
+ return NULL;
+}
+
void pat_del_list_val(struct pattern_expr *expr, struct pattern *pattern)
{
struct pattern_list *pat;
@@ -1526,6 +1726,20 @@
expr->prune(expr);
}
+/* This function lookup for a pattern matching the <key> and return a
+ * pointer to a pointer of the sample stoarge. If the <key> dont match,
+ * the function returns NULL. If the key cannot be parsed, the function
+ * fill <err>.
+ */
+struct sample_storage **pattern_find_smp(const char *key, struct pattern_expr *expr, char **err)
+{
+ struct pattern pattern;
+
+ if (!expr->parse(key, &pattern, err))
+ return NULL;
+ return expr->find_smp(expr, &pattern);
+}
+
/* This function search all the pattern matching the <key> and delete it.
* If the parsing of the input key fails, the function returns 0 and the
* <err> is filled, else return 1;