MAJOR: pattern/map: Extends the map edition system in the patterns
This patch add the following socket command line options:
show acl [<id>]
clear acl <id>
get acl <id> <pattern>
del acl <id> <pattern>
add acl <id> <pattern>
The system used for maps is backported in the pattern functions.
diff --git a/src/map.c b/src/map.c
index b266614..064c52e 100644
--- a/src/map.c
+++ b/src/map.c
@@ -17,26 +17,13 @@
#include <types/global.h>
#include <types/map.h>
+#include <types/pattern.h>
#include <proto/arg.h>
#include <proto/map.h>
#include <proto/pattern.h>
#include <proto/sample.h>
-struct list maps = LIST_HEAD_INIT(maps); /* list of struct map_reference */
-
-/* This function return existing map reference or return NULL. */
-struct map_reference *map_get_reference(const char *reference)
-{
- struct map_reference *ref;
-
- /* process the lookup */
- list_for_each_entry(ref, &maps, list)
- if (strcmp(ref->reference, reference) == 0)
- return ref;
- return NULL;
-}
-
/* Parse an IPv4 address and store it into the sample.
* The output type is IPV4.
*/
@@ -105,63 +92,10 @@
return 1;
}
-/* This function creates and initializes a new map_reference entry. This
- * function only fails in case of a memory allocation issue, in which case
- * it returns NULL. <reference> here is a unique identifier for the map's
- * contents, typically the name of the file used to build the map.
- */
-static struct map_reference *map_create_reference(const char *reference)
-{
- struct map_reference *ref;
-
- /* create new entry */
- ref = calloc(1, sizeof(*ref));
- if (!ref)
- return NULL;
-
- ref->reference = strdup(reference);
- if (!ref->reference)
- return NULL;
-
- LIST_INIT(&ref->entries);
- LIST_INIT(&ref->maps);
- LIST_ADDQ(&maps, &ref->list);
-
- return ref;
-}
-
-/* This function just create new entry */
-static struct map_entry *map_create_entry(int line, char *key, char *value)
-{
- struct map_entry *ent;
-
- ent = calloc(1, sizeof(*ent));
- if (!ent)
- return NULL;
-
- ent->line = line;
-
- ent->key = strdup(key);
- if (!ent->key) {
- free(ent);
- return NULL;
- }
-
- ent->value = strdup(value);
- if (!ent->value) {
- free(ent->key);
- free(ent);
- return NULL;
- }
-
- return ent;
-}
-
/* This crete and initialize map descriptor.
* Return NULL if out of memory error
*/
-static struct map_descriptor *map_create_descriptor(struct map_reference *ref,
- struct sample_conv *conv)
+static struct map_descriptor *map_create_descriptor(struct sample_conv *conv)
{
struct map_descriptor *desc;
@@ -170,27 +104,10 @@
return NULL;
desc->conv = conv;
- desc->ref = ref;
-
- LIST_ADDQ(&ref->maps, &desc->list);
return desc;
}
-/* This function just add entry into the list of pattern.
- * It can return false only in memory problem case
- */
-static int map_add_entry(struct map_reference *map, int line, char *key, char *value)
-{
- struct map_entry *ent;
-
- ent = map_create_entry(line, key, value);
- if (!ent)
- return 0;
- LIST_ADDQ(&map->entries, &ent->list);
- return 1;
-}
-
/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
* be returned there on errors and the caller will have to free it.
*
@@ -214,7 +131,7 @@
* Return non-zero in case of succes, otherwise 0.
*/
static int map_read_entries_from_file(const char *filename,
- struct map_reference *ref,
+ struct pat_ref *ref,
char **err)
{
FILE *file;
@@ -278,7 +195,7 @@
*value_end = '\0';
/* insert values */
- if (!map_add_entry(ref, line, key_beg, value_beg)) {
+ if (!pat_ref_append(ref, key_beg, value_beg, line)) {
memprintf(err, "out of memory");
goto out_close;
}
@@ -292,41 +209,6 @@
return ret;
}
-/* This function read the string entries of <ent>, parse it with
- * the <desc> methods, and strore the result into <desc> dummy ACL.
- * return 1 in succes case, else return 0 and <err> is filled.
- *
- * The acm parser use <pattern> for creating new pattern (list
- * of values case) or using the same pattern (tree index case).
- *
- * <patflags> must be PAT_F_*.
- */
-static int map_parse_and_index(struct map_descriptor *desc,
- struct map_entry *ent,
- int patflags,
- char **err)
-{
- struct sample_storage *smp;
-
- /* use new smp for storing value */
- smp = calloc(1, sizeof(*smp));
- if (!smp)
- return 0;
-
- /* first read and convert value */
- if (!desc->pat->parse_smp(ent->value, smp)) {
- memprintf(err, "parse value failed at line %d of file <%s>",
- ent->line, desc->ref->reference);
- return 0;
- }
-
- /* register key */
- if (!pattern_register(desc->pat, ent->key, smp, patflags, err))
- return 0;
-
- return 1;
-}
-
/* This function load the map file according with data type declared into
* the "struct sample_conv".
*
@@ -335,100 +217,68 @@
*/
static int sample_load_map(struct arg *arg, struct sample_conv *conv, char **err)
{
- struct map_reference *ref;
+ struct pat_ref *ref;
struct map_descriptor *desc;
- struct map_entry *ent;
- struct pattern_expr *pat = NULL;
+ struct pattern_expr *expr;
/* look for existing map reference. The reference is the
* file encountered in the first argument. arg[0] with string
* type is guaranteed by the parser.
+ *
+ * If the reference dosn't exists, create it and load file.
*/
- ref = map_get_reference(arg[0].data.str.str);
-
- /* The reference doesn't exist */
+ ref = pat_ref_lookup(arg[0].data.str.str);
if (!ref) {
-
- /* create new reference entry */
- ref = map_create_reference(arg[0].data.str.str);
+ ref = pat_ref_new(arg[0].data.str.str, PAT_REF_MAP);
if (!ref) {
memprintf(err, "out of memory");
return 0;
}
-
- /* load the file */
if (!map_read_entries_from_file(arg[0].data.str.str, ref, err))
return 0;
}
- /* look for identical existing map. Two maps are identical if
- * their in_type and out_type are the same. If is not found, pat
- * is NULL.
- */
- else {
- list_for_each_entry(desc, &ref->maps, list)
- if (desc->conv->in_type == conv->in_type &&
- desc->conv->out_type == conv->out_type &&
- desc->conv->private == conv->private)
- break;
- if (&desc->list != &ref->maps)
- pat = desc->pat;
- }
-
/* create new map descriptor */
- desc = map_create_descriptor(ref, conv);
+ desc = map_create_descriptor(conv);
if (!desc) {
memprintf(err, "out of memory");
return 0;
}
+ /* Initialize pattern */
+ pattern_init_head(&desc->pat);
+
- /* check the output parse method */
+ /* This is original pattern, must free */
+ desc->do_free = 1;
+
+ /* Set the match method. */
+ desc->pat.match = pat_match_fcts[conv->private];
+ desc->pat.parse = pat_parse_fcts[conv->private];
+ desc->pat.index = pat_index_fcts[conv->private];
+ desc->pat.delete = pat_delete_fcts[conv->private];
+ desc->pat.prune = pat_prune_fcts[conv->private];
+ desc->pat.find_smp = pat_find_smp_fcts[conv->private];
+
+ /* Set the output parse method. */
switch (desc->conv->out_type) {
- case SMP_T_STR: desc->pat->parse_smp = map_parse_str; break;
- case SMP_T_UINT: desc->pat->parse_smp = map_parse_int; break;
- case SMP_T_IPV4: desc->pat->parse_smp = map_parse_ip; break;
- case SMP_T_IPV6: desc->pat->parse_smp = map_parse_ip6; break;
+ case SMP_T_STR: desc->pat.parse_smp = map_parse_str; break;
+ case SMP_T_UINT: desc->pat.parse_smp = map_parse_int; break;
+ case SMP_T_IPV4: desc->pat.parse_smp = map_parse_ip; break;
+ case SMP_T_IPV6: desc->pat.parse_smp = map_parse_ip6; break;
default:
memprintf(err, "map: internal haproxy error: no default parse case for the input type <%d>.",
conv->out_type);
return 0;
}
- /* If identical pattern is not found, initialize his own pattern */
- if (!pat) {
-
- desc->pat = calloc(1, sizeof(*desc->pat));
- if (!desc->pat) {
- memprintf(err, "out of memory");
- return 0;
- }
-
- pattern_init_expr(desc->pat);
-
- /* This is original pattern, must free */
- desc->do_free = 1;
-
- /* set the match method */
- desc->pat->match = pat_match_fcts[conv->private];
- desc->pat->parse = pat_parse_fcts[conv->private];
- desc->pat->index = pat_index_fcts[conv->private];
- desc->pat->delete = pat_delete_fcts[conv->private];
- desc->pat->prune = pat_prune_fcts[conv->private];
- desc->pat->find_smp = pat_find_smp_fcts[conv->private];
-
- /* parse each line of the file */
- list_for_each_entry(ent, &ref->entries, list)
- if (!map_parse_and_index(desc, ent, 0, err))
- return 0;
- }
+ /* Create new pattern expression for this reference. */
+ expr = pattern_new_expr(&desc->pat, ref, err);
+ if (!expr)
+ return 0;
- /* identical pattern found. Use reference to this pattern, and mark
- * the map_descriptor pattern as non freeable
- */
- else {
- desc->pat = pat;
- desc->do_free = 0;
- }
+ /* Load the reference content in the pattern expression. */
+ if (!pat_ref_load(ref, expr, 0, 1, err))
+ return 0;
/* The second argument is the default value */
if (arg[1].type == ARGT_STR) {
@@ -442,7 +292,7 @@
memprintf(err, "out of memory");
return 0;
}
- if (!desc->pat->parse_smp(desc->default_value, desc->def)) {
+ if (!desc->pat.parse_smp(desc->default_value, desc->def)) {
memprintf(err, "Cannot parse default value");
return 0;
}
@@ -466,7 +316,7 @@
desc = arg_p[0].data.map;
/* Execute the match function. */
- pat = pattern_exec_match(desc->pat, smp, 1);
+ pat = pattern_exec_match(&desc->pat, smp, 1);
/* Match case. */
if (pat) {