diff --git a/include/haproxy/quic_frame-t.h b/include/haproxy/quic_frame-t.h index 855a37ecf1..6a3226e3ee 100644 --- a/include/haproxy/quic_frame-t.h +++ b/include/haproxy/quic_frame-t.h @@ -88,9 +88,14 @@ enum quic_frame_type { #define QUIC_FT_PKT_TYPE____1_BITMASK QUIC_FT_PKT_TYPE_1_BITMASK -#define QUIC_STREAM_FRAME_FIN_BIT 0x01 -#define QUIC_STREAM_FRAME_LEN_BIT 0x02 -#define QUIC_STREAM_FRAME_OFF_BIT 0x04 +#define QUIC_STREAM_FRAME_TYPE_FIN_BIT 0x01 +#define QUIC_STREAM_FRAME_TYPE_LEN_BIT 0x02 +#define QUIC_STREAM_FRAME_TYPE_OFF_BIT 0x04 + +/* Servers have the stream initiator bit set. */ +#define QUIC_STREAM_FRAME_ID_INITIATOR_BIT 0x01 +/* Unidirectional streams have the direction bit set. */ +#define QUIC_STREAM_FRAME_ID_DIR_BIT 0x02 #define QUIC_PATH_CHALLENGE_LEN 8 diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index bb05c54472..6cf9fae3b8 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -201,6 +201,7 @@ enum quic_pkt_type { #define QUIC_EV_CONN_ADDDATA (1ULL << 25) #define QUIC_EV_CONN_FFLIGHT (1ULL << 26) #define QUIC_EV_CONN_SSLALERT (1ULL << 27) +#define QUIC_EV_CONN_PSTRM (1ULL << 28) #define QUIC_EV_CONN_RTTUPDT (1ULL << 29) #define QUIC_EV_CONN_CC (1ULL << 30) #define QUIC_EV_CONN_SPPKTS (1ULL << 31) diff --git a/src/quic_frame.c b/src/quic_frame.c index d80eb5ac4e..59478569ae 100644 --- a/src/quic_frame.c +++ b/src/quic_frame.c @@ -377,8 +377,8 @@ static int quic_build_stream_frame(unsigned char **buf, const unsigned char *end struct quic_stream *stream = &frm->stream; if (!quic_enc_int(buf, end, stream->id) || - ((frm->type & QUIC_STREAM_FRAME_OFF_BIT) && !quic_enc_int(buf, end, stream->offset)) || - ((frm->type & QUIC_STREAM_FRAME_LEN_BIT) && + ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(buf, end, stream->offset)) || + ((frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) && (!quic_enc_int(buf, end, stream->len) || end - *buf < stream->len))) return 0; @@ -400,14 +400,14 @@ static int quic_parse_stream_frame(struct quic_frame *frm, struct quic_conn *qc, return 0; /* Offset parsing */ - if (!(frm->type & QUIC_STREAM_FRAME_OFF_BIT)) { + if (!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT)) { stream->offset = 0; } else if (!quic_dec_int(&stream->offset, buf, end)) return 0; /* Length parsing */ - if (!(frm->type & QUIC_STREAM_FRAME_LEN_BIT)) { + if (!(frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT)) { stream->len = end - *buf; } else if (!quic_dec_int(&stream->len, buf, end) || end - *buf < stream->len) diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 97160ab8e3..c20d877c39 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -571,6 +571,18 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace if (sz3) chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz3); } + + if (mask & QUIC_EV_CONN_PSTRM) { + const struct quic_frame *frm = a2; + const struct quic_stream *s = &frm->stream; + + chunk_appendf(&trace_buf, " uni=%d fin=%d id=%llu off=%llu len=%llu", + !!(s->id & QUIC_STREAM_FRAME_ID_DIR_BIT), + !!(frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT), + (unsigned long long)s->id, + (unsigned long long)s->offset, + (unsigned long long)s->len); + } } if (mask & QUIC_EV_CONN_LPKT) { const struct quic_rx_packet *pkt = a2; @@ -1642,6 +1654,17 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct quic_conn_ctx *c case QUIC_FT_STREAM_D: case QUIC_FT_STREAM_E: case QUIC_FT_STREAM_F: + { + struct quic_stream *stream = &frm.stream; + + TRACE_PROTO("STREAM frame", QUIC_EV_CONN_PSTRM, ctx->conn, &frm); + if (objt_listener(ctx->conn->target)) { + if (stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT) + goto err; + } else if (!(stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT)) + goto err; + break; + } case QUIC_FT_NEW_CONNECTION_ID: break; case QUIC_FT_CONNECTION_CLOSE: