diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h index 9589c3048..0cd9baba5 100644 --- a/include/haproxy/stream-t.h +++ b/include/haproxy/stream-t.h @@ -292,7 +292,7 @@ struct stream { struct { void *ptr; /* Pointer on the entity (def: NULL) */ - int type; /* entity type (0: undef, 1: rule) */ + int type; /* entity type (0: undef, 1: rule, 2: filter) */ } last_entity; /* last evaluated entity that interrupted processing */ unsigned int stream_epoch; /* copy of stream_epoch when the stream was created */ diff --git a/src/filters.c b/src/filters.c index e650a0899..45bfa12a6 100644 --- a/src/filters.c +++ b/src/filters.c @@ -72,7 +72,11 @@ static int handle_analyzer_result(struct stream *s, struct channel *chn, unsigne #define BREAK_EXECUTION(strm, chn, label) \ do { \ - strm_flt(strm)->current[CHN_IDX(chn)] = filter; \ + if (ret < 0) { \ + (strm)->last_entity.type = 2; \ + (strm)->last_entity.ptr = filter; \ + } \ + strm_flt(strm)->current[CHN_IDX(chn)] = filter; \ goto label; \ } while (0) @@ -556,8 +560,11 @@ flt_set_stream_backend(struct stream *s, struct proxy *be) list_for_each_entry(filter, &strm_flt(s)->filters, list) { if (FLT_OPS(filter)->stream_set_backend) { filter->calls++; - if (FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0) + if (FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; return -1; + } } } if (be->be_req_ana & AN_REQ_FLT_START_BE) { @@ -693,8 +700,11 @@ flt_http_payload(struct stream *s, struct http_msg *msg, unsigned int len) DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); filter->calls++; ret = FLT_OPS(filter)->http_payload(s, filter, msg, out + offset, data - offset); - if (ret < 0) + if (ret < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; goto end; + } data = ret + *flt_off - *strm_off; *flt_off += ret; } @@ -832,8 +842,11 @@ flt_post_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s); filter->calls++; ret = FLT_OPS(filter)->channel_post_analyze(s, filter, chn, an_bit); - if (ret < 0) + if (ret < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; break; + } filter->post_analyzers &= ~an_bit; } } @@ -986,8 +999,11 @@ flt_tcp_payload(struct stream *s, struct channel *chn, unsigned int len) DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s); filter->calls++; ret = FLT_OPS(filter)->tcp_payload(s, filter, chn, out + offset, data - offset); - if (ret < 0) + if (ret < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; goto end; + } data = ret + *flt_off - *strm_off; *flt_off += ret; } diff --git a/src/stream.c b/src/stream.c index 618f350f7..e015b97bf 100644 --- a/src/stream.c +++ b/src/stream.c @@ -4137,6 +4137,21 @@ static int smp_fetch_last_entity(const struct arg *args, struct sample *smp, con trash->data = snprintf(trash->area, trash->size, "%s:%d", rule->conf.file, rule->conf.line); smp->data.u.str = *trash; } + else if (smp->strm->last_entity.type == 2) { + struct filter *filter = smp->strm->last_entity.ptr; + + if (FLT_ID(filter)) { + smp->flags |= SMP_F_CONST; + smp->data.u.str.area = (char *)FLT_ID(filter); + smp->data.u.str.data = strlen(FLT_ID(filter)); + } + else { + struct buffer *trash = get_trash_chunk(); + + trash->data = snprintf(trash->area, trash->size, "%p", filter->config); + smp->data.u.str = *trash; + } + } else return 0;