]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: pattern: use the standard arg parser
authorWilly Tarreau <w@1wt.eu>
Fri, 20 Apr 2012 12:45:49 +0000 (14:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:13 +0000 (20:57 +0200)
We don't need the pattern-specific args parsers anymore, make use of the
common parser instead. We still need to improve this by adding a validation
function to report abnormal argument values or combinations. We don't report
precise parsing errors yet but this was not previously done either.

include/proto/pattern.h
include/types/pattern.h
src/pattern.c
src/proto_http.c
src/proto_tcp.c

index ef2c5480cefc6971afd79c8a2cd3d2adc5102882..e0fb3eb6ebca2d8e99fa66aadffab22b1a0ac3c8 100644 (file)
@@ -33,7 +33,4 @@ struct pattern *pattern_process(struct proxy *px, struct session *l4,
                                 struct pattern *p);
 void pattern_register_fetches(struct pattern_fetch_kw_list *psl);
 void pattern_register_convs(struct pattern_conv_kw_list *psl);
-
-int pattern_arg_ipmask(const char *arg_str, struct arg **arg_p);
-int pattern_arg_str(const char *arg_str, struct arg **arg_p);
 #endif
index 101485660943cacc4763fc8c780b2471a8c7dca3..c3718862d7567a749c30f01681b8125a333c4133 100644 (file)
@@ -64,8 +64,7 @@ struct pattern_conv {
        const char *kw;                           /* configuration keyword  */
        int (*process)(const struct arg *arg_p,
                       union pattern_data *data); /* process function */
-       int (*parse_args)(const char *arg_str,
-                         struct arg **arg_p);    /* argument parser. May be NULL. */
+       unsigned int arg_mask;                    /* arguments (ARG*()) */
        unsigned int in_type;                     /* input needed pattern type */
        unsigned int out_type;                    /* output pattern type */
 };
@@ -85,8 +84,7 @@ struct pattern_fetch {
                       void *l7,
                       int dir, const struct arg *arg_p,
                       union pattern_data *data); /* fetch processing function */
-       int (*parse_args)(const char *arg_str,
-                         struct arg **arg_p);    /* argument parser. Can be NULL. */
+       unsigned int arg_mask;                    /* arguments (ARG*()) */
        unsigned long out_type;                   /* output pattern type */
        int dir;                                  /* usable directions */
 };
index 72c0b34594051dfbcbb29f50f3433dfc9c60f21c..670eff7d52a2b1e307a592b9a5c79444a477173a 100644 (file)
@@ -13,6 +13,7 @@
 #include <string.h>
 #include <arpa/inet.h>
 
+#include <proto/arg.h>
 #include <proto/pattern.h>
 #include <proto/buffers.h>
 #include <common/standard.h>
@@ -315,9 +316,7 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
        expr->fetch = fetch;
 
        if (end != endw) {
-               int i = end - endw - 2;
-
-               if (!fetch->parse_args) {
+               if (!fetch->arg_mask) {
                        p = my_strndup(str[*idx], endw - str[*idx]);
                        if (p) {
                                snprintf(err, err_size, "fetch method '%s' does not support any args.", p);
@@ -325,12 +324,8 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
                        }
                        goto out_error;
                }
-               p = my_strndup(endw + 1, i);
-               if (!p)
-                       goto out_error;
-               i = fetch->parse_args(p, &expr->arg_p);
-               free(p);
-               if (!i) {
+
+               if (make_arg_list(endw + 1, end - endw - 2, fetch->arg_mask, &expr->arg_p, NULL, NULL, NULL) < 0) {
                        p = my_strndup(str[*idx], endw - str[*idx]);
                        if (p) {
                                snprintf(err, err_size, "invalid args in fetch method '%s'.", p);
@@ -339,7 +334,7 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
                        goto out_error;
                }
        }
-       else if (fetch->parse_args) {
+       else if (fetch->arg_mask) {
                p = my_strndup(str[*idx], endw - str[*idx]);
                if (p) {
                        snprintf(err, err_size, "missing args for fetch method '%s'.", p);
@@ -398,9 +393,7 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
                conv_expr->conv = conv;
 
                if (end != endw) {
-                       int i = end - endw - 2;
-
-                       if (!conv->parse_args) {
+                       if (!conv->arg_mask) {
                                p = my_strndup(str[*idx], endw - str[*idx]);
 
                                if (p) {
@@ -410,12 +403,7 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
                                goto out_error;
                        }
 
-                       p = my_strndup(endw + 1, i);
-                       if (!p)
-                               goto out_error;
-                       i = conv->parse_args(p, &conv_expr->arg_p);
-                       free(p);
-                       if (!i) {
+                       if (make_arg_list(endw + 1, end - endw - 2, conv->arg_mask, &conv_expr->arg_p, NULL, NULL, NULL) < 0) {
                                p = my_strndup(str[*idx], endw - str[*idx]);
                                if (p) {
                                        snprintf(err, err_size, "invalid args in conv method '%s'.", p);
@@ -424,7 +412,7 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
                                goto out_error;
                        }
                }
-               else if (conv->parse_args) {
+               else if (conv->arg_mask) {
                        p = my_strndup(str[*idx], endw - str[*idx]);
                        if (p) {
                                snprintf(err, err_size, "missing args for conv method '%s'.", p);
@@ -476,37 +464,6 @@ struct pattern *pattern_process(struct proxy *px, struct session *l4, void *l7,
        return p;
 }
 
-/* Converts an argument string mask to a arg type IP.
- * Returns non-zero in case of success, 0 on error.
- */
-int pattern_arg_ipmask(const char *arg_str, struct arg **arg_p)
-{
-       *arg_p = calloc(2, sizeof(struct arg));
-       (*arg_p)->type = ARGT_IPV4;
-       arg_p[1]->type = ARGT_STOP;
-
-       if (!str2mask(arg_str, &(*arg_p)->data.ipv4))
-               return 0;
-
-       return 1;
-}
-
-
-/* Converts an argument string to a arg type STRING.
- * Returns non-zero in case of success, 0 on error.
- */
-int pattern_arg_str(const char *arg_str, struct arg **arg_p)
-{
-       *arg_p = calloc(2, sizeof(struct arg));
-       (*arg_p)->type = ARGT_STR;
-       (*arg_p)->data.str.str = strdup(arg_str);
-       (*arg_p)->data.str.len = strlen(arg_str);
-       arg_p[1]->type = ARGT_STOP;
-
-       return 1;
-}
-
-
 /*****************************************************************/
 /*    Pattern format convert functions                           */
 /*****************************************************************/
@@ -548,10 +505,10 @@ static int pattern_conv_ipmask(const struct arg *arg_p, union pattern_data *data
 
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct pattern_conv_kw_list pattern_conv_kws = {{ },{
-       { "upper",  pattern_conv_str2upper, NULL,               PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
-       { "lower",  pattern_conv_str2lower, NULL,               PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
-       { "ipmask", pattern_conv_ipmask,    pattern_arg_ipmask, PATTERN_TYPE_IP,     PATTERN_TYPE_IP },
-       { NULL, NULL, NULL, 0, 0 },
+       { "upper",  pattern_conv_str2upper, 0,            PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
+       { "lower",  pattern_conv_str2lower, 0,            PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
+       { "ipmask", pattern_conv_ipmask,    ARG1(1,MSK4), PATTERN_TYPE_IP,     PATTERN_TYPE_IP },
+       { NULL, NULL, 0, 0, 0 },
 }};
 
 __attribute__((constructor))
index da7fa339ba442d75f7b3a125f308386fefa8bb74..7809b7adabe7e0037f4a233c45b9aed1498c2a53 100644 (file)
@@ -8539,11 +8539,11 @@ pattern_fetch_set_cookie(struct proxy *px, struct session *l4, void *l7, int dir
 /************************************************************************/
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
-       { "hdr", pattern_fetch_hdr, pattern_arg_str, PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
-       { "url_param", pattern_fetch_url_param, pattern_arg_str, PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
-       { "cookie", pattern_fetch_cookie, pattern_arg_str, PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
-       { "set-cookie", pattern_fetch_set_cookie, pattern_arg_str, PATTERN_TYPE_STRING, PATTERN_FETCH_RTR },
-       { NULL, NULL, NULL, 0, 0 },
+       { "hdr",        pattern_fetch_hdr,        ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
+       { "url_param",  pattern_fetch_url_param,  ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
+       { "cookie",     pattern_fetch_cookie,     ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
+       { "set-cookie", pattern_fetch_set_cookie, ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_RTR },
+       { NULL, NULL, 0, 0, 0 },
 }};
 
 
index a0e315ddc532473fa869f88edd24a16f5632154e..52d5cafa4c9fd7659339b7aee528d0154503e076 100644 (file)
@@ -38,6 +38,7 @@
 #include <types/server.h>
 
 #include <proto/acl.h>
+#include <proto/arg.h>
 #include <proto/buffers.h>
 #include <proto/frontend.h>
 #include <proto/log.h>
@@ -1388,75 +1389,6 @@ pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-static int
-pattern_arg_fetch_payloadlv(const char *arg, struct arg **arg_p)
-{
-       int member = 0;
-       int len_offset = 0;
-       int len_size = 0;
-       int buf_offset = 0;
-       int relative = 0;
-       int arg_len = strlen(arg);
-       int i;
-
-       for (i = 0; i < arg_len; i++) {
-               if (arg[i] == ',') {
-                       member++;
-               } else if (member == 0) {
-                       if (arg[i] < '0' || arg[i] > '9')
-                               return 0;
-
-                       len_offset = 10 * len_offset + arg[i] - '0';
-               } else if (member == 1) {
-                       if (arg[i] < '0' || arg[i] > '9')
-                               return 0;
-
-                       len_size = 10 * len_size + arg[i] - '0';
-               } else if (member == 2) {
-                       if (!relative && !buf_offset && arg[i] == '+') {
-                               relative = 1;
-                               continue;
-                       } else if (!relative && !buf_offset && arg[i] == '-') {
-                               relative = 2;
-                               continue;
-                       } else if (arg[i] < '0' || arg[i] > '9')
-                               return 0;
-
-                       buf_offset = 10 * buf_offset + arg[i] - '0';
-               }
-       }
-
-       if (member < 1)
-               return 0;
-
-       if (!len_size)
-               return 0;
-
-       if (member == 1) {
-               buf_offset = len_offset + len_size;
-       }
-       else if (relative == 1) {
-               buf_offset = len_offset + len_size + buf_offset;
-       }
-       else if (relative == 2) {
-               if (len_offset + len_size < buf_offset)
-                       return 0;
-
-               buf_offset = len_offset + len_size - buf_offset;
-       }
-
-       *arg_p = calloc(4, sizeof(struct arg));
-       (*arg_p)[0].type = ARGT_UINT;
-       (*arg_p)[0].data.uint = len_offset;
-       (*arg_p)[1].type = ARGT_UINT;
-       (*arg_p)[1].data.uint = len_size;
-       (*arg_p)[2].type = ARGT_UINT;
-       (*arg_p)[2].data.uint = buf_offset;
-       (*arg_p)[3].type = ARGT_STOP;
-
-       return 1;
-}
-
 static int
 pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, int dir,
                         const struct arg *arg_p, union pattern_data *data)
@@ -1490,6 +1422,13 @@ pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!buf_size)
                return 0;
 
+       /* buf offset may be implicit, absolute or relative */
+       buf_offset = len_offset + len_size;
+       if (arg_p[2].type == ARGT_UINT)
+               buf_offset = arg_p[2].data.uint;
+       else if (arg_p[2].type == ARGT_SINT)
+               buf_offset += arg_p[2].data.sint;
+
        if (buf_offset + buf_size > b->i)
                return 0;
 
@@ -1499,44 +1438,6 @@ pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-static int
-pattern_arg_fetch_payload (const char *arg, struct arg **arg_p)
-{
-       int member = 0;
-       int buf_offset = 0;
-       int buf_size = 0;
-       int arg_len = strlen(arg);
-       int i;
-
-       for (i = 0 ; i < arg_len ; i++) {
-               if (arg[i] == ',') {
-                       member++;
-               } else if (member == 0) {
-                       if (arg[i] < '0' || arg[i] > '9')
-                               return 0;
-
-                       buf_offset = 10 * buf_offset + arg[i] - '0';
-               } else if (member == 1) {
-                       if (arg[i] < '0' || arg[i] > '9')
-                               return 0;
-
-                       buf_size = 10 * buf_size + arg[i] - '0';
-               }
-       }
-
-       if (!buf_size)
-               return 0;
-
-       *arg_p = calloc(3, sizeof(struct arg));
-       (*arg_p)[0].type = ARGT_UINT;
-       (*arg_p)[0].data.uint = buf_offset;
-       (*arg_p)[1].type = ARGT_UINT;
-       (*arg_p)[1].data.uint = buf_size;
-       (*arg_p)[2].type = ARGT_STOP;
-
-       return 1;
-}
-
 static int
 pattern_fetch_payload(struct proxy *px, struct session *l4, void *l7, int dir,
                       const struct arg *arg_p, union pattern_data *data)
@@ -1611,15 +1512,15 @@ static struct acl_kw_list acl_kws = {{ },{
 
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
-       { "src",         pattern_fetch_src,       NULL,                         PATTERN_TYPE_IP,        PATTERN_FETCH_REQ },
-       { "src6",        pattern_fetch_src6,      NULL,                         PATTERN_TYPE_IPV6,      PATTERN_FETCH_REQ },
-       { "dst",         pattern_fetch_dst,       NULL,                         PATTERN_TYPE_IP,        PATTERN_FETCH_REQ },
-       { "dst6",        pattern_fetch_dst6,      NULL,                         PATTERN_TYPE_IPV6,      PATTERN_FETCH_REQ },
-       { "dst_port",    pattern_fetch_dport,     NULL,                         PATTERN_TYPE_INTEGER,   PATTERN_FETCH_REQ },
-       { "payload",     pattern_fetch_payload,   pattern_arg_fetch_payload,    PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
-       { "payload_lv",  pattern_fetch_payloadlv, pattern_arg_fetch_payloadlv,  PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
-       { "rdp_cookie",  pattern_fetch_rdp_cookie, pattern_arg_str,             PATTERN_TYPE_CONSTSTRING, PATTERN_FETCH_REQ },
-       { NULL, NULL, NULL, 0, 0 },
+       { "src",         pattern_fetch_src,       0,                      PATTERN_TYPE_IP,        PATTERN_FETCH_REQ },
+       { "src6",        pattern_fetch_src6,      0,                      PATTERN_TYPE_IPV6,      PATTERN_FETCH_REQ },
+       { "dst",         pattern_fetch_dst,       0,                      PATTERN_TYPE_IP,        PATTERN_FETCH_REQ },
+       { "dst6",        pattern_fetch_dst6,      0,                      PATTERN_TYPE_IPV6,      PATTERN_FETCH_REQ },
+       { "dst_port",    pattern_fetch_dport,     0,                      PATTERN_TYPE_INTEGER,   PATTERN_FETCH_REQ },
+       { "payload",     pattern_fetch_payload,   ARG2(2,UINT,UINT),      PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
+       { "payload_lv",  pattern_fetch_payloadlv, ARG3(2,UINT,UINT,SINT), PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
+       { "rdp_cookie",  pattern_fetch_rdp_cookie, ARG1(1,STR),           PATTERN_TYPE_CONSTSTRING, PATTERN_FETCH_REQ },
+       { NULL, NULL, 0, 0, 0 },
 }};
 
 __attribute__((constructor))