Skip to content

Commit 006db8f

Browse files
author
Frantisek Tobias
committed
quic: refactor error handling
So far no application error codes (defined in rfc 9250 4.3) were specified when closing connections
1 parent 02129a9 commit 006db8f

File tree

8 files changed

+264
-279
lines changed

8 files changed

+264
-279
lines changed

daemon/quic_common.c

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/* Copyright (C) CZ.NIC, z.s.p.o. <[email protected]>
22
* SPDX-License-Identifier: GPL-3.0-or-later
33
*/
4+
#include <ngtcp2/ngtcp2.h>
5+
#include "contrib/openbsd/siphash.h"
46
#include "quic_common.h"
57
#include "libdnssec/random.h"
68
#include "session2.h"
7-
#include <ngtcp2/ngtcp2.h>
9+
#include "quic_conn.h"
810

911
uint64_t quic_timestamp(void)
1012
{
@@ -35,18 +37,83 @@ void init_random_cid(ngtcp2_cid *cid, size_t len)
3537
/* DNSSEC_EOK */0 ? len : 0;
3638
}
3739

38-
ssize_t send_version_negotiation(struct wire_buf *dest, ngtcp2_version_cid dec_cids,
39-
ngtcp2_cid dcid, ngtcp2_cid scid)
40+
uint64_t cid2hash(const ngtcp2_cid *cid, kr_quic_table_t *table)
41+
{
42+
SIPHASH_CTX ctx;
43+
SipHash24_Init(&ctx, (const SIPHASH_KEY *)(table->hash_secret));
44+
SipHash24_Update(&ctx, cid->data, MIN(cid->datalen, 8));
45+
uint64_t ret = SipHash24_End(&ctx);
46+
47+
return ret;
48+
}
49+
50+
kr_quic_cid_t **kr_quic_table_lookup2(const ngtcp2_cid *cid, kr_quic_table_t *table)
4051
{
41-
uint8_t rnd = 0;
42-
dnssec_random_buffer(&rnd, sizeof(rnd));
43-
uint32_t supported_quic[1] = { NGTCP2_PROTO_VER_V1 };
44-
int ret = ngtcp2_pkt_write_version_negotiation(
52+
uint64_t hash = cid2hash(cid, table);
53+
54+
kr_quic_cid_t **res = table->conns + (hash % table->size);
55+
while (*res != NULL && !ngtcp2_cid_eq(cid, (const ngtcp2_cid *)(*res)->cid_placeholder)) {
56+
res = &(*res)->next;
57+
}
58+
59+
return res;
60+
}
61+
62+
struct pl_quic_conn_sess_data *kr_quic_table_lookup(const ngtcp2_cid *cid, kr_quic_table_t *table)
63+
{
64+
kr_quic_cid_t **pcid = kr_quic_table_lookup2(cid, table);
65+
return *pcid == NULL ? NULL : (*pcid)->conn_sess;
66+
}
67+
68+
bool init_unique_cid(ngtcp2_cid *cid, size_t len, kr_quic_table_t *table)
69+
{
70+
do {
71+
if (init_random_cid(cid, len), cid->datalen == 0)
72+
return false;
73+
74+
} while (kr_quic_table_lookup(cid, table) != NULL);
75+
76+
return true;
77+
}
78+
79+
int write_retry_packet(struct wire_buf *dest, kr_quic_table_t *table,
80+
ngtcp2_version_cid *dec_cids,
81+
const struct sockaddr *src_addr,
82+
uint8_t *secret, size_t secret_len)
83+
{
84+
ngtcp2_cid dcid;
85+
ngtcp2_cid scid;
86+
ngtcp2_cid new_dcid;
87+
88+
ngtcp2_cid_init(&dcid, dec_cids->dcid, dec_cids->dcidlen);
89+
ngtcp2_cid_init(&scid, dec_cids->scid, dec_cids->scidlen);
90+
91+
init_random_cid(&new_dcid, 0);
92+
if (!init_unique_cid(&new_dcid, 0, table)) {
93+
kr_log_debug(DOQ, "Failed to initialize unique cid for Retry packet\n");
94+
return -1;
95+
}
96+
97+
uint8_t retry_token[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN2];
98+
uint64_t now = quic_timestamp();
99+
100+
int ret = ngtcp2_crypto_generate_retry_token2(
101+
retry_token, (const uint8_t *)secret,
102+
secret_len, dec_cids->version,
103+
src_addr, kr_sockaddr_len(src_addr),
104+
&new_dcid, &dcid, now);
105+
106+
if (ret < 0) {
107+
kr_log_debug(DOQ, "Failed to generate retry token\n");
108+
return ret;
109+
}
110+
111+
ret = ngtcp2_crypto_write_retry(
45112
wire_buf_free_space(dest),
46113
wire_buf_free_space_length(dest),
47-
rnd, dec_cids.scid, dec_cids.scidlen,
48-
dec_cids.dcid, dec_cids.dcidlen, supported_quic,
49-
sizeof(supported_quic) / sizeof(*supported_quic)
114+
dec_cids->version, &scid,
115+
&new_dcid, &dcid,
116+
retry_token, ret
50117
);
51118

52119
return ret;

daemon/quic_common.h

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
#include <gnutls/gnutls.h>
1313
#include <gnutls/crypto.h>
1414

15-
#include "quic_conn.h"
15+
#include "session2.h"
1616

17-
/** RFC 9250 4.3. DoQ Error Codes */
17+
/** RFC 9250 4.3 DoQ Error Codes for use as application protocol error codes */
1818
typedef enum {
1919
/*! No error. This is used when the connection or stream needs to be
2020
closed, but there is no error to signal. */
@@ -40,12 +40,12 @@ typedef enum {
4040

4141
// Macros from knot quic impl
4242
#define SERVER_DEFAULT_SCIDLEN 18
43-
#define QUIC_REGULAR_TOKEN_TIMEOUT (24LLU * 3600LLU * 1000000000LLU)
43+
#define QUIC_REGULAR_TOKEN_TIMEOUT (24LLU * 3600LLU * 1000000000LLU)
4444
#define QUIC_SEND_VERSION_NEGOTIATION NGTCP2_ERR_VERSION_NEGOTIATION
4545
#define QUIC_SEND_RETRY NGTCP2_ERR_RETRY
4646
#define QUIC_SEND_STATELESS_RESET (-NGTCP2_STATELESS_RESET_TOKENLEN)
4747
#define QUIC_SEND_CONN_CLOSE (-2000)
48-
#define QUIC_SEND_EXCESSIVE_LOAD (-KR_QUIC_ERR_EXCESSIVE_LOAD)
48+
4949
#define BUCKETS_PER_CONNS 8
5050

5151
/* Application is responsible for extending the stream limit.
@@ -66,22 +66,60 @@ typedef enum {
6666
#define container_of(ptr, type, member) \
6767
((type *)((char *)(ptr) - offsetof(type, member)))
6868

69+
typedef enum {
70+
KNOT_QUIC_TABLE_CLIENT_ONLY = (1 << 0),
71+
} kr_quic_table_flag_t;
72+
73+
typedef struct kr_quic_cid {
74+
uint8_t cid_placeholder[32];
75+
struct pl_quic_conn_sess_data *conn_sess;
76+
struct kr_quic_cid *next;
77+
} kr_quic_cid_t;
78+
79+
typedef struct kr_quic_table {
80+
kr_quic_table_flag_t flags;
81+
/* general "settings" for connections */
82+
size_t size;
83+
size_t usage;
84+
size_t pointers;
85+
size_t max_conns;
86+
size_t udp_payload_limit;
87+
void (*log_cb)(const char *);
88+
const char *qlog_dir;
89+
uint64_t hash_secret[4];
90+
struct tls_credentials *creds;
91+
struct gnutls_priority_st *priority;
92+
struct heap *expiry_heap;
93+
struct kr_quic_cid *conns[];
94+
} kr_quic_table_t;
95+
6996
/* quic subsession init parameters */
7097
struct kr_quic_conn_param {
98+
bool retry_sent;
99+
kr_quic_table_t *table;
71100
ngtcp2_cid dcid;
72101
ngtcp2_cid scid;
73102
ngtcp2_cid odcid;
74103
ngtcp2_version_cid *dec_cids;
75104
struct comm_info *comm_storage;
76105
};
106+
77107
struct kr_quic_stream_param {
78108
int64_t stream_id;
79109
ngtcp2_conn *conn;
80110
struct comm_info comm_storage;
81111
};
82112

83-
uint64_t quic_timestamp(void);
84113
bool kr_quic_conn_timeout(struct pl_quic_conn_sess_data *conn, uint64_t *now);
114+
uint64_t cid2hash(const ngtcp2_cid *cid, kr_quic_table_t *table);
115+
bool init_unique_cid(ngtcp2_cid *cid, size_t len, kr_quic_table_t *table);
85116
void init_random_cid(ngtcp2_cid *cid, size_t len);
86-
ssize_t send_version_negotiation(struct wire_buf *dest, ngtcp2_version_cid dec_cids,
87-
ngtcp2_cid dcid, ngtcp2_cid scid);
117+
uint64_t quic_timestamp(void);
118+
kr_quic_cid_t **kr_quic_table_lookup2(const ngtcp2_cid *cid,
119+
kr_quic_table_t *table);
120+
struct pl_quic_conn_sess_data *kr_quic_table_lookup(const ngtcp2_cid *cid,
121+
kr_quic_table_t *table);
122+
int write_retry_packet(struct wire_buf *dest, kr_quic_table_t *table,
123+
ngtcp2_version_cid *dec_cids,
124+
const struct sockaddr *src_addr,
125+
uint8_t *secret, size_t secret_len);

0 commit comments

Comments
 (0)