From: Willy Tarreau Date: Mon, 23 Apr 2012 20:38:26 +0000 (+0200) Subject: MEDIUM: pattern: retrieve the sample type in the sample, not in the keyword description X-Git-Tag: v1.5-dev9~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b8c8f1f61170a9e8fef9eaad03ac8f66b0a035ab;p=thirdparty%2Fhaproxy.git MEDIUM: pattern: retrieve the sample type in the sample, not in the keyword description We need the pattern fetchers and converters to correctly set the output type so that they can be used by ACL fetchers. By using the sample type instead of the keyword type, we also open the possibility to create some multi-type pattern fetch methods later (eg: "src" being v4/v6). Right now the type in the keyword is used to validate the configuration. --- diff --git a/src/pattern.c b/src/pattern.c index f851331f52..9787eccd06 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -118,6 +118,8 @@ static struct chunk *get_trash_chunk(void) /******************************************************************/ /* Pattern casts functions */ +/* Note: these functions do *NOT* set the output type on the */ +/* sample, the caller is responsible for doing this on return. */ /******************************************************************/ static int c_ip2int(struct sample *smp) @@ -466,6 +468,10 @@ out_error: * pattern is not found or when format conversion failed. * If

is not null, function returns results in structure pointed by

. * If

is null, functions returns a pointer on a static pattern structure. + * + * Note: the fetch functions are required to properly set the return type. The + * conversion functions must do so too. However the cast functions do not need + * to since they're made to cast mutiple types according to what is required. */ struct sample *pattern_process(struct proxy *px, struct session *l4, void *l7, int dir, struct pattern_expr *expr, struct sample *p) @@ -479,23 +485,21 @@ struct sample *pattern_process(struct proxy *px, struct session *l4, void *l7, i if (!expr->fetch->process(px, l4, l7, dir, expr->arg_p, p)) return NULL; - p->type = expr->fetch->out_type; - list_for_each_entry(conv_expr, &expr->conv_exprs, list) { if (!pattern_casts[p->type][conv_expr->conv->in_type](p)) return NULL; + /* force the output type after a cast */ p->type = conv_expr->conv->in_type; if (!conv_expr->conv->process(conv_expr->arg_p, p)) return NULL; - - p->type = conv_expr->conv->out_type; } return p; } /*****************************************************************/ /* Pattern format convert functions */ +/* These functions set the data type on return. */ /*****************************************************************/ static int pattern_conv_str2lower(const struct arg *arg_p, struct sample *smp) @@ -509,6 +513,7 @@ static int pattern_conv_str2lower(const struct arg *arg_p, struct sample *smp) if ((smp->data.str.str[i] >= 'A') && (smp->data.str.str[i] <= 'Z')) smp->data.str.str[i] += 'a' - 'A'; } + smp->type = SMP_T_STR; return 1; } @@ -523,6 +528,7 @@ static int pattern_conv_str2upper(const struct arg *arg_p, struct sample *smp) if ((smp->data.str.str[i] >= 'a') && (smp->data.str.str[i] <= 'z')) smp->data.str.str[i] += 'A' - 'a'; } + smp->type = SMP_T_STR; return 1; } @@ -530,6 +536,7 @@ static int pattern_conv_str2upper(const struct arg *arg_p, struct sample *smp) static int pattern_conv_ipmask(const struct arg *arg_p, struct sample *smp) { smp->data.ipv4.s_addr &= arg_p->data.ipv4.s_addr; + smp->type = SMP_T_IPV4; return 1; } diff --git a/src/proto_http.c b/src/proto_http.c index 4d504b09da..933351ac85 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -8352,6 +8352,7 @@ pattern_fetch_hdr(struct proxy *px, struct session *l4, void *l7, int dir, { struct http_txn *txn = l7; + smp->type = SMP_T_CSTR; return http_get_hdr(&txn->req, arg_p->data.str.str, arg_p->data.str.len, &txn->hdr_idx, -1, NULL, &smp->data.str.str, &smp->data.str.len); } @@ -8455,6 +8456,7 @@ pattern_fetch_url_param(struct proxy *px, struct session *l4, void *l7, int dir, &url_param_value, &url_param_value_l)) return 0; + smp->type = SMP_T_CSTR; smp->data.str.str = url_param_value; smp->data.str.len = url_param_value_l; return 1; @@ -8508,6 +8510,7 @@ pattern_fetch_cookie(struct proxy *px, struct session *l4, void *l7, int dir, arg_p->data.str.str, arg_p->data.str.len, 1, &cookie_value, &cookie_value_l); if (found) { + smp->type = SMP_T_CSTR; smp->data.str.str = cookie_value; smp->data.str.len = cookie_value_l; } @@ -8530,6 +8533,7 @@ pattern_fetch_set_cookie(struct proxy *px, struct session *l4, void *l7, int dir arg_p->data.str.str, arg_p->data.str.len, 1, &cookie_value, &cookie_value_l); if (found) { + smp->type = SMP_T_CSTR; smp->data.str.str = cookie_value; smp->data.str.len = cookie_value_l; } diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 6b2101a248..bd46de29c0 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -1281,6 +1281,7 @@ pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir, if (l4->si[0].addr.from.ss_family != AF_INET ) return 0; + smp->type = SMP_T_IPV4; smp->data.ipv4.s_addr = ((struct sockaddr_in *)&l4->si[0].addr.from)->sin_addr.s_addr; return 1; } @@ -1293,6 +1294,7 @@ pattern_fetch_src6(struct proxy *px, struct session *l4, void *l7, int dir, if (l4->si[0].addr.from.ss_family != AF_INET6) return 0; + smp->type = SMP_T_IPV6; memcpy(smp->data.ipv6.s6_addr, ((struct sockaddr_in6 *)&l4->si[0].addr.from)->sin6_addr.s6_addr, sizeof(smp->data.ipv6.s6_addr)); return 1; } @@ -1346,6 +1348,7 @@ pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir, if (l4->si[0].addr.to.ss_family != AF_INET) return 0; + smp->type = SMP_T_IPV4; smp->data.ipv4.s_addr = ((struct sockaddr_in *)&l4->si[0].addr.to)->sin_addr.s_addr; return 1; } @@ -1360,6 +1363,7 @@ pattern_fetch_dst6(struct proxy *px, struct session *l4, void *l7, int dir, if (l4->si[0].addr.to.ss_family != AF_INET6) return 0; + smp->type = SMP_T_IPV6; memcpy(smp->data.ipv6.s6_addr, ((struct sockaddr_in6 *)&l4->si[0].addr.to)->sin6_addr.s6_addr, sizeof(smp->data.ipv6.s6_addr)); return 1; } @@ -1383,6 +1387,7 @@ static int pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, const struct arg *arg, struct sample *smp) { + smp->type = SMP_T_UINT; stream_sock_get_to_addr(&l4->si[0]); if (!(smp->data.uint = get_host_port(&l4->si[0].addr.to))) @@ -1435,6 +1440,7 @@ pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, int dir, return 0; /* init chunk as read only */ + smp->type = SMP_T_CBIN; chunk_initlen(&smp->data.str, b->p + buf_offset, 0, buf_size); return 1; @@ -1460,6 +1466,7 @@ pattern_fetch_payload(struct proxy *px, struct session *l4, void *l7, int dir, return 0; /* init chunk as read only */ + smp->type = SMP_T_CBIN; chunk_initlen(&smp->data.str, b->p + buf_offset, 0, buf_size); return 1; @@ -1486,6 +1493,7 @@ pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir expr.args = args; + /* type set by acl_fetch_rdp_cookie */ ret = acl_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, &expr, smp); if (ret == 0 || (smp->flags & SMP_F_MAY_CHANGE) || smp->data.str.len == 0) return 0;