*ncbuf = NCBUF_NULL;
}
+/* Return the address of the connection owner object type. */
+static inline enum obj_type *qc_owner_obj_type(struct quic_conn *qc)
+{
+ return qc_is_listener(qc) ? &qc->li->obj_type :
+ &objt_server(qc->conn->target)->obj_type;
+}
+
+/* Return the address of the QUIC counters attached to the proxy of
+ * the owner of the connection whose object type address is <o> for
+ * listener and servers, or NULL for others object type.
+ */
+static inline void *qc_counters(enum obj_type *o, const struct stats_module *m)
+{
+ struct proxy *p;
+ struct listener *l = objt_listener(o);
+ struct server *s = objt_server(o);
+
+ p = l ? l->bind_conf->frontend :
+ s ? s->proxy : NULL;
+
+ return p ? EXTRA_COUNTERS_GET(p->extra_counters_fe, m) : NULL;
+}
+
void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err);
void quic_set_tls_alert(struct quic_conn *qc, int alert);
/* Parse a QUIC packet starting at <pos>. Data won't be read after <end> even
* if the packet is incomplete. This function will populate fields of <pkt>
* instance, most notably its length. <dgram> is the UDP datagram which
- * contains the parsed packet. <l> is the listener instance on which it was
- * received.
+ * contains the parsed packet. <o> is the address object type address of the
+ * object which receives this received packet.
*
* Returns 0 on success else non-zero. Packet length is guaranteed to be set to
* the real packet value or to cover all data between <pos> and <end> : this is
*/
static int quic_rx_pkt_parse(struct quic_rx_packet *pkt,
unsigned char *pos, const unsigned char *end,
- struct quic_dgram *dgram, struct listener *l)
+ struct quic_dgram *dgram, enum obj_type *o)
{
const unsigned char *beg = pos;
- struct proxy *prx;
struct quic_counters *prx_counters;
+ struct listener *l = objt_listener(o);
TRACE_ENTER(QUIC_EV_CONN_LPKT);
- prx = l->bind_conf->frontend;
- prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
+ prx_counters = qc_counters(o, &quic_stats_module);
if (end <= pos) {
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
goto drop;
}
- /* RFC9000 6. Version Negotiation */
- if (!pkt->version) {
+ /* RFC9000 6. Version Negotiation. A Version Negotiation packet is
+ * sent only by servers.
+ */
+ if (l && !pkt->version) {
/* unsupported version, send Negotiation packet */
if (send_version_negotiation(l->rx.fd, &dgram->saddr, pkt)) {
TRACE_ERROR("VN packet not sent", QUIC_EV_CONN_LPKT);
goto drop;
}
+ if (!l && pkt->token_len) {
+ /* A server must sent Initial packets with a null token length. */
+ TRACE_PROTO("Packet dropped",
+ QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
+ goto drop;
+ }
+
pkt->token = pos;
pkt->token_len = token_len;
pos += pkt->token_len;
pkt->pn_offset = pos - beg;
pkt->len = pkt->pn_offset + len;
+ /* Interrupt parsing after packet length retrieval : this
+ * ensures that only the packet is dropped but not the whole
+ * datagram.
+ */
+
/* RFC 9000. Initial Datagram Size
*
* A server MUST discard an Initial packet that is carried in a UDP datagram
goto drop;
}
- /* Interrupt parsing after packet length retrieval : this
- * ensures that only the packet is dropped but not the whole
- * datagram.
- */
- if (pkt->type == QUIC_PACKET_TYPE_0RTT && !l->bind_conf->ssl_conf.early_data) {
+ /* O-RTT packet are not sent by servers. */
+ if (pkt->type == QUIC_PACKET_TYPE_0RTT && (!l || !l->bind_conf->ssl_conf.early_data)) {
TRACE_PROTO("RX 0-RTT packet not supported", QUIC_EV_CONN_LPKT);
goto drop;
}
* this function.
*
* If datagram has been received on a quic-conn owned FD, <from_qc> must be set
- * to the connection instance. <li> is the attached listener. The caller is
+ * to the connection instance. <o> is the object type address of the object
+ * (listener or server) receiving the datagram. The caller is
* responsible to ensure that the first packet is destined to this connection
* by comparing CIDs.
*
* the datagram may not have been parsed.
*/
int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc,
- struct listener *li)
+ enum obj_type *o)
{
struct quic_rx_packet *pkt;
struct quic_conn *qc = NULL;
pkt->flags |= QUIC_FL_RX_PACKET_DGRAM_FIRST;
quic_rx_packet_refinc(pkt);
- if (quic_rx_pkt_parse(pkt, pos, end, dgram, li))
+ if (quic_rx_pkt_parse(pkt, pos, end, dgram, o))
goto next;
/* Search quic-conn instance for first packet of the datagram.
*/
if (!qc) {
int new_tid = -1;
+ struct listener *li = objt_listener(o);
qc = from_qc ? from_qc : quic_rx_pkt_retrieve_conn(pkt, dgram, li, &new_tid);
/* qc is NULL if receiving a non Initial packet for an