MINOR: quic: refactor concat DCID with address for Initial packets

For first Initial packets, the socket source dest address is
concatenated to the DCID. This is used to be able to differentiate
possible collision between several clients which used the same ODCID.

Refactor the code to manage DCID and the concatenation with the address.
Before this, the concatenation was done on the quic_cid struct and its
<len> field incremented. In the code it is difficult to differentiate a
normal DCID with a DCID + address concatenated.

A new field <addrlen> has been added in the quic_cid struct. The <len>
field now only contains the size of the QUIC DCID. the <addrlen> is
first initialized to 0. If the address is concatenated, it will be
updated with the size of the concatenated address. This now means we
have to explicitely used either cid.len or cid.len + cid.addrlen to
access the DCID or the DCID + the address. The code should be clearer
thanks to this.

The field <odcid_len> in quic_rx_packet struct is now useless and has
been removed. However, a new parameter must be added to the
qc_new_conn() function to specify the size of the ODCID addrlen.
This commit is contained in:
Amaury Denoyelle 2021-12-14 17:20:59 +01:00
parent d496251cde
commit c92cbfc014
3 changed files with 32 additions and 28 deletions

View File

@ -252,7 +252,8 @@ extern struct pool_head *pool_head_quic_frame;
*/ */
struct quic_cid { struct quic_cid {
unsigned char data[QUIC_CID_MAXLEN + sizeof(in_port_t) + sizeof(struct in6_addr)]; unsigned char data[QUIC_CID_MAXLEN + sizeof(in_port_t) + sizeof(struct in6_addr)];
unsigned char len; unsigned char len; /* size of QUIC CID, excluding possible concatenated address */
unsigned char addrlen; /* size of port + IP if present in data*/
}; };
/* QUIC connection id attached to a QUIC connection. /* QUIC connection id attached to a QUIC connection.
@ -426,7 +427,6 @@ struct quic_rx_packet {
/* Initial desctination connection ID. */ /* Initial desctination connection ID. */
struct quic_cid dcid; struct quic_cid dcid;
struct quic_cid scid; struct quic_cid scid;
size_t odcid_len;
size_t pn_offset; size_t pn_offset;
/* Packet number */ /* Packet number */
int64_t pn; int64_t pn;

View File

@ -74,14 +74,20 @@ static inline void quic_cid_cpy(struct quic_cid *dst, const struct quic_cid *src
dst->len = src->len; dst->len = src->len;
} }
/* Concatenate the port and address of <saddr> to <cid> QUIC connection ID. /* Concatenate the port and address of <saddr> to <cid> QUIC connection ID. The
* <addrlen> field of <cid> will be updated with the size of the concatenated
* address.
*
* Returns the number of bytes concatenated to <cid>. * Returns the number of bytes concatenated to <cid>.
*/ */
static inline size_t quic_cid_saddr_cat(struct quic_cid *cid, struct sockaddr_storage *saddr) static inline size_t quic_cid_saddr_cat(struct quic_cid *cid,
struct sockaddr_storage *saddr)
{ {
void *port, *addr; void *port, *addr;
size_t port_len, addr_len; size_t port_len, addr_len;
cid->addrlen = 0;
if (saddr->ss_family == AF_INET6) { if (saddr->ss_family == AF_INET6) {
port = &((struct sockaddr_in6 *)saddr)->sin6_port; port = &((struct sockaddr_in6 *)saddr)->sin6_port;
addr = &((struct sockaddr_in6 *)saddr)->sin6_addr; addr = &((struct sockaddr_in6 *)saddr)->sin6_addr;
@ -94,10 +100,11 @@ static inline size_t quic_cid_saddr_cat(struct quic_cid *cid, struct sockaddr_st
port_len = sizeof ((struct sockaddr_in *)saddr)->sin_port; port_len = sizeof ((struct sockaddr_in *)saddr)->sin_port;
addr_len = sizeof ((struct sockaddr_in *)saddr)->sin_addr; addr_len = sizeof ((struct sockaddr_in *)saddr)->sin_addr;
} }
memcpy(cid->data + cid->len, port, port_len); memcpy(cid->data + cid->len, port, port_len);
cid->len += port_len; cid->addrlen += port_len;
memcpy(cid->data + cid->len, addr, addr_len); memcpy(cid->data + cid->len + port_len, addr, addr_len);
cid->len += addr_len; cid->addrlen += addr_len;
return port_len + addr_len; return port_len + addr_len;
} }

View File

@ -3319,7 +3319,7 @@ static struct task *process_timer(struct task *task, void *ctx, unsigned int sta
* Returns 1 if succeeded, 0 if not. * Returns 1 if succeeded, 0 if not.
*/ */
static struct quic_conn *qc_new_conn(unsigned int version, int ipv4, static struct quic_conn *qc_new_conn(unsigned int version, int ipv4,
unsigned char *dcid, size_t dcid_len, unsigned char *dcid, size_t dcid_len, size_t dcid_addr_len,
unsigned char *scid, size_t scid_len, int server, void *owner) unsigned char *scid, size_t scid_len, int server, void *owner)
{ {
int i; int i;
@ -3348,10 +3348,10 @@ static struct quic_conn *qc_new_conn(unsigned int version, int ipv4,
l = owner; l = owner;
HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_SERVER_INITIAL); HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_SERVER_INITIAL);
/* Copy the initial DCID. */ /* Copy the initial DCID with the address. */
qc->odcid.len = dcid_len; qc->odcid.len = dcid_len;
if (qc->odcid.len) qc->odcid.addrlen = dcid_addr_len;
memcpy(qc->odcid.data, dcid, dcid_len); memcpy(qc->odcid.data, dcid, dcid_len + dcid_addr_len);
/* copy the packet SCID to reuse it as DCID for sending */ /* copy the packet SCID to reuse it as DCID for sending */
if (scid_len) if (scid_len)
@ -3883,6 +3883,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
unsigned char *beg; unsigned char *beg;
struct quic_conn *qc; struct quic_conn *qc;
struct eb_root *cids; struct eb_root *cids;
unsigned char dcid_lookup_len;
struct ebmb_node *node; struct ebmb_node *node;
struct listener *l; struct listener *l;
struct ssl_sock_ctx *conn_ctx; struct ssl_sock_ctx *conn_ctx;
@ -3913,8 +3914,6 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
/* Header form */ /* Header form */
qc_parse_hd_form(pkt, *(*buf)++, &long_header); qc_parse_hd_form(pkt, *(*buf)++, &long_header);
if (long_header) { if (long_header) {
unsigned char dcid_len;
if (!quic_packet_read_long_header(buf, end, pkt)) { if (!quic_packet_read_long_header(buf, end, pkt)) {
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT); TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
goto err; goto err;
@ -3940,7 +3939,6 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
goto out; goto out;
} }
dcid_len = pkt->dcid.len;
/* For Initial packets, and for servers (QUIC clients connections), /* For Initial packets, and for servers (QUIC clients connections),
* there is no Initial connection IDs storage. * there is no Initial connection IDs storage.
*/ */
@ -3952,6 +3950,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
*/ */
quic_cid_saddr_cat(&pkt->dcid, saddr); quic_cid_saddr_cat(&pkt->dcid, saddr);
cids = &l->rx.odcids; cids = &l->rx.odcids;
dcid_lookup_len = pkt->dcid.len + pkt->dcid.addrlen;
if (pkt->type == QUIC_PACKET_TYPE_INITIAL) { if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
if (!quic_dec_int(&token_len, (const unsigned char **)buf, end) || if (!quic_dec_int(&token_len, (const unsigned char **)buf, end) ||
@ -3977,6 +3976,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
} }
cids = &l->rx.cids; cids = &l->rx.cids;
dcid_lookup_len = pkt->dcid.len;
} }
/* Only packets packets with long headers and not RETRY or VERSION as type /* Only packets packets with long headers and not RETRY or VERSION as type
@ -3996,14 +3996,13 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
HA_RWLOCK_RDLOCK(OTHER_LOCK, &l->rx.cids_lock); HA_RWLOCK_RDLOCK(OTHER_LOCK, &l->rx.cids_lock);
node = ebmb_lookup(cids, pkt->dcid.data, pkt->dcid.len); node = ebmb_lookup(cids, pkt->dcid.data, dcid_lookup_len);
if (!node && pkt->type == QUIC_PACKET_TYPE_INITIAL && if (!node && pkt->type == QUIC_PACKET_TYPE_INITIAL &&
dcid_len == QUIC_HAP_CID_LEN && cids == &l->rx.odcids) { pkt->dcid.len == QUIC_HAP_CID_LEN && cids == &l->rx.odcids) {
/* Switch to the definitive tree ->cids containing the final CIDs. */ /* Switch to the definitive tree ->cids containing the final CIDs. */
node = ebmb_lookup(&l->rx.cids, pkt->dcid.data, dcid_len); node = ebmb_lookup(&l->rx.cids, pkt->dcid.data, pkt->dcid.len);
if (node) { if (node) {
/* If found, signal this with NULL as special value for <cids>. */ /* If found, signal this with NULL as special value for <cids>. */
pkt->dcid.len = dcid_len;
cids = NULL; cids = NULL;
} }
} }
@ -4022,12 +4021,9 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
} }
pkt->saddr = *saddr; pkt->saddr = *saddr;
/* Note that here, odcid_len equals to pkt->dcid.len minus the length
* of <saddr>.
*/
pkt->odcid_len = dcid_len;
ipv4 = saddr->ss_family == AF_INET; ipv4 = saddr->ss_family == AF_INET;
qc = qc_new_conn(pkt->version, ipv4, pkt->dcid.data, pkt->dcid.len, qc = qc_new_conn(pkt->version, ipv4,
pkt->dcid.data, pkt->dcid.len, pkt->dcid.addrlen,
pkt->scid.data, pkt->scid.len, 1, l); pkt->scid.data, pkt->scid.len, 1, l);
if (qc == NULL) if (qc == NULL)
goto err; goto err;
@ -4036,8 +4032,8 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
/* Copy the transport parameters. */ /* Copy the transport parameters. */
qc->rx.params = l->bind_conf->quic_params; qc->rx.params = l->bind_conf->quic_params;
/* Copy original_destination_connection_id transport parameter. */ /* Copy original_destination_connection_id transport parameter. */
memcpy(odcid->data, &pkt->dcid, pkt->odcid_len); memcpy(odcid->data, &pkt->dcid.data, pkt->dcid.len);
odcid->len = pkt->odcid_len; odcid->len = pkt->dcid.len;
/* Copy the initial source connection ID. */ /* Copy the initial source connection ID. */
quic_cid_cpy(&qc->rx.params.initial_source_connection_id, &qc->scid); quic_cid_cpy(&qc->rx.params.initial_source_connection_id, &qc->scid);
qc->enc_params_len = qc->enc_params_len =
@ -4055,14 +4051,15 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
salt_len = sizeof initial_salt_draft_29; salt_len = sizeof initial_salt_draft_29;
} }
if (!qc_new_isecs(qc, salt, salt_len, if (!qc_new_isecs(qc, salt, salt_len,
pkt->dcid.data, pkt->odcid_len, 1)) { pkt->dcid.data, pkt->dcid.len, 1)) {
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc->conn); TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc->conn);
goto err; goto err;
} }
HA_RWLOCK_WRLOCK(QUIC_LOCK, &l->rx.cids_lock); HA_RWLOCK_WRLOCK(QUIC_LOCK, &l->rx.cids_lock);
/* Insert the DCID the QUIC client has chosen (only for listeners) */ /* Insert the DCID the QUIC client has chosen (only for listeners) */
n = ebmb_insert(&l->rx.odcids, &qc->odcid_node, qc->odcid.len); n = ebmb_insert(&l->rx.odcids, &qc->odcid_node,
qc->odcid.len + qc->odcid.addrlen);
HA_ATOMIC_OR(&qc->flags, QUIC_FL_CONN_ODCID_NODE_TO_DELETE); HA_ATOMIC_OR(&qc->flags, QUIC_FL_CONN_ODCID_NODE_TO_DELETE);
HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &l->rx.cids_lock); HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &l->rx.cids_lock);
@ -5050,7 +5047,7 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
ipv4 = conn->dst->ss_family == AF_INET; ipv4 = conn->dst->ss_family == AF_INET;
qc = qc_new_conn(QUIC_PROTOCOL_VERSION_DRAFT_28, ipv4, qc = qc_new_conn(QUIC_PROTOCOL_VERSION_DRAFT_28, ipv4,
dcid, sizeof dcid, NULL, 0, 0, srv); dcid, sizeof dcid, 0, NULL, 0, 0, srv);
if (qc == NULL) if (qc == NULL)
goto err; goto err;