MEDIUM: pattern: use the standard arg parser
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.
This commit is contained in:
parent
f995410355
commit
9fcb984b17
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 },
|
||||
}};
|
||||
|
||||
|
||||
|
|
133
src/proto_tcp.c
133
src/proto_tcp.c
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue