diff --git a/src/pattern.c b/src/pattern.c index f851331f5..9787eccd0 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 4d504b09d..933351ac8 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 6b2101a24..bd46de29c 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;