]> git.ipfire.org Git - thirdparty/openssl.git/blob - include/internal/quic_demux.h
QUIC DEMUX: Allow parsed DCID to be learnt in default packet handler
[thirdparty/openssl.git] / include / internal / quic_demux.h
1 /*
2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #ifndef OSSL_QUIC_DEMUX_H
11 # define OSSL_QUIC_DEMUX_H
12
13 # include <openssl/ssl.h>
14 # include "internal/quic_types.h"
15 # include "internal/bio_addr.h"
16 # include "internal/time.h"
17 # include "internal/list.h"
18
19 # ifndef OPENSSL_NO_QUIC
20
21 /*
22 * QUIC Demuxer
23 * ============
24 *
25 * The QUIC connection demuxer is the entity responsible for receiving datagrams
26 * from the network via a datagram BIO. It parses packet headers to determine
27 * each packet's destination connection ID (DCID) and hands off processing of
28 * the packet to the correct QUIC Record Layer (QRL)'s RX side (known as the
29 * QRX).
30 *
31 * A QRX is instantiated per QUIC connection and contains the cryptographic
32 * resources needed to decrypt QUIC packets for that connection. Received
33 * datagrams are passed from the demuxer to the QRX via a callback registered
34 * for a specific DCID by the QRX; thus the demuxer has no specific knowledge of
35 * the QRX and is not coupled to it.
36 *
37 * A connection may have multiple connection IDs associated with it; a QRX
38 * handles this simply by registering multiple connection IDs with the demuxer
39 * via multiple register calls.
40 *
41 * URX Queue
42 * ---------
43 *
44 * Since the demuxer must handle the initial reception of datagrams from the OS,
45 * RX queue management for new, unprocessed datagrams is also handled by the
46 * demuxer.
47 *
48 * The demuxer maintains a queue of Unprocessed RX Entries (URXEs), which store
49 * unprocessed (i.e., encrypted, unvalidated) data received from the network.
50 * The URXE queue is designed to allow multiple datagrams to be received in a
51 * single call to BIO_recvmmsg, where supported.
52 *
53 * One URXE is used per received datagram. Each datagram may contain multiple
54 * packets, however, this is not the demuxer's concern. QUIC prohibits different
55 * packets in the same datagram from containing different DCIDs; the demuxer
56 * only considers the DCID of the first packet in a datagram when deciding how
57 * to route a received datagram, and it is the responsibility of the QRX to
58 * enforce this rule. Packets other than the first packet in a datagram are not
59 * examined by the demuxer, and the demuxer does not perform validation of
60 * packet headers other than to the minimum extent necessary to extract the
61 * DCID; further parsing and validation of packet headers is the responsibility
62 * of the QRX.
63 *
64 * Rather than defining an opaque interface, the URXE structure internals
65 * are exposed. Since the demuxer is only exposed to other parts of the QUIC
66 * implementation internals, this poses no problem, and has a number of
67 * advantages:
68 *
69 * - Fields in the URXE can be allocated to support requirements in other
70 * components, like the QRX, which would otherwise have to allocate extra
71 * memory corresponding to each URXE.
72 *
73 * - Other components, like the QRX, can keep the URXE in queues of its own
74 * when it is not being managed by the demuxer.
75 *
76 * URX Queue Structure
77 * -------------------
78 *
79 * The URXE queue is maintained as a simple doubly-linked list. URXE entries are
80 * moved between different lists in their lifecycle (for example, from a free
81 * list to a pending list and vice versa). The buffer into which datagrams are
82 * received immediately follows this URXE header structure and is part of the
83 * same allocation.
84 */
85
86 typedef struct quic_urxe_st QUIC_URXE;
87
88 /* Maximum number of packets we allow to exist in one datagram. */
89 #define QUIC_MAX_PKT_PER_URXE (sizeof(uint64_t) * 8)
90
91 struct quic_urxe_st {
92 OSSL_LIST_MEMBER(urxe, QUIC_URXE);
93
94 /*
95 * The URXE data starts after this structure so we don't need a pointer.
96 * data_len stores the current length (i.e., the length of the received
97 * datagram) and alloc_len stores the allocation length. The URXE will be
98 * reallocated if we need a larger allocation than is available, though this
99 * should not be common as we will have a good idea of worst-case MTUs up
100 * front.
101 */
102 size_t data_len, alloc_len;
103
104 /*
105 * Bitfields per packet. processed indicates the packet has been processed
106 * and must not be processed again, hpr_removed indicates header protection
107 * has already been removed. Used by QRX only; not used by the demuxer.
108 */
109 uint64_t processed, hpr_removed;
110
111 /*
112 * Address of peer we received the datagram from, and the local interface
113 * address we received it on. If local address support is not enabled, local
114 * is zeroed.
115 */
116 BIO_ADDR peer, local;
117
118 /*
119 * Time at which datagram was received (or ossl_time_zero()) if a now
120 * function was not provided).
121 */
122 OSSL_TIME time;
123
124 /*
125 * Used by the QRX to mark whether a datagram has been deferred. Used by the
126 * QRX only; not used by the demuxer.
127 */
128 char deferred;
129
130 /*
131 * Used by the DEMUX to track if a URXE has been handed out. Used primarily
132 * for debugging purposes.
133 */
134 char demux_state;
135 };
136
137 /* Accessors for URXE buffer. */
138 static ossl_unused ossl_inline unsigned char *
139 ossl_quic_urxe_data(const QUIC_URXE *e)
140 {
141 return (unsigned char *)&e[1];
142 }
143
144 static ossl_unused ossl_inline unsigned char *
145 ossl_quic_urxe_data_end(const QUIC_URXE *e)
146 {
147 return ossl_quic_urxe_data(e) + e->data_len;
148 }
149
150 /* List structure tracking a queue of URXEs. */
151 DEFINE_LIST_OF(urxe, QUIC_URXE);
152 typedef OSSL_LIST(urxe) QUIC_URXE_LIST;
153
154 /*
155 * List management helpers. These are used by the demuxer but can also be used
156 * by users of the demuxer to manage URXEs.
157 */
158 void ossl_quic_urxe_remove(QUIC_URXE_LIST *l, QUIC_URXE *e);
159 void ossl_quic_urxe_insert_head(QUIC_URXE_LIST *l, QUIC_URXE *e);
160 void ossl_quic_urxe_insert_tail(QUIC_URXE_LIST *l, QUIC_URXE *e);
161
162 /* Opaque type representing a demuxer. */
163 typedef struct quic_demux_st QUIC_DEMUX;
164
165 /*
166 * Called when a datagram is received for a given connection ID.
167 *
168 * e is a URXE containing the datagram payload. It is permissible for the callee
169 * to mutate this buffer; once the demuxer calls this callback, it will never
170 * read the buffer again.
171 *
172 * If a DCID was identified for the datagram, dcid is non-NULL; otherwise
173 * it is NULL.
174 *
175 * The callee must arrange for ossl_quic_demux_release_urxe or
176 * ossl_quic_demux_reinject_urxe to be called on the URXE at some point in the
177 * future (this need not be before the callback returns).
178 *
179 * At the time the callback is made, the URXE will not be in any queue,
180 * therefore the callee can use the prev and next fields as it wishes.
181 */
182 typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg,
183 const QUIC_CONN_ID *dcid);
184
185 /*
186 * Called when a datagram is received.
187 * Returns 1 if the datagram ends with a stateless reset token and
188 * 0 if not.
189 */
190 typedef int (ossl_quic_stateless_reset_cb_fn)(const unsigned char *data,
191 size_t data_len, void *arg);
192
193 /*
194 * Creates a new demuxer. The given BIO is used to receive datagrams from the
195 * network using BIO_recvmmsg. short_conn_id_len is the length of destination
196 * connection IDs used in RX'd packets; it must have the same value for all
197 * connections used on a socket. default_urxe_alloc_len is the buffer size to
198 * receive datagrams into; it should be a value large enough to contain any
199 * received datagram according to local MTUs, etc.
200 *
201 * now is an optional function used to determine the time a datagram was
202 * received. now_arg is an opaque argument passed to the function. If now is
203 * NULL, ossl_time_zero() is used as the datagram reception time.
204 */
205 QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio,
206 size_t short_conn_id_len,
207 OSSL_TIME (*now)(void *arg),
208 void *now_arg);
209
210 /*
211 * Destroy a demuxer. All URXEs must have been released back to the demuxer
212 * before calling this. No-op if demux is NULL.
213 */
214 void ossl_quic_demux_free(QUIC_DEMUX *demux);
215
216 /*
217 * Changes the BIO which the demuxer reads from. This also sets the MTU if the
218 * BIO supports querying the MTU.
219 */
220 void ossl_quic_demux_set_bio(QUIC_DEMUX *demux, BIO *net_bio);
221
222 /*
223 * Changes the MTU in bytes we use to receive datagrams.
224 */
225 int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu);
226
227 /*
228 * Register a datagram handler callback for a connection ID.
229 *
230 * ossl_quic_demux_pump will call the specified function if it receives a datagram
231 * the first packet of which has the specified destination connection ID.
232 *
233 * It is assumed all packets in a datagram have the same destination connection
234 * ID (as QUIC mandates this), but it is the user's responsibility to check for
235 * this and reject subsequent packets in a datagram that violate this rule.
236 *
237 * dst_conn_id is a destination connection ID; it is copied and need not remain
238 * valid after this function returns.
239 *
240 * cb_arg is passed to cb when it is called. For information on the callback,
241 * see its typedef above.
242 *
243 * Only one handler can be set for a given connection ID. If a handler is
244 * already set for the given connection ID, returns 0.
245 *
246 * Returns 1 on success or 0 on failure.
247 */
248 int ossl_quic_demux_register(QUIC_DEMUX *demux,
249 const QUIC_CONN_ID *dst_conn_id,
250 ossl_quic_demux_cb_fn *cb,
251 void *cb_arg);
252
253 /*
254 * Unregisters any datagram handler callback set for the given connection ID.
255 * Fails if no handler is registered for the given connection ID.
256 *
257 * Returns 1 on success or 0 on failure.
258 */
259 int ossl_quic_demux_unregister(QUIC_DEMUX *demux,
260 const QUIC_CONN_ID *dst_conn_id);
261
262 /*
263 * Unregisters any datagram handler callback from all connection IDs it is used
264 * for. cb and cb_arg must both match the values passed to
265 * ossl_quic_demux_register.
266 */
267 void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux,
268 ossl_quic_demux_cb_fn *cb,
269 void *cb_arg);
270
271 /*
272 * Set the default packet handler. This is used for incoming packets which don't
273 * match a registered DCID. This is only needed for servers. If a default packet
274 * handler is not set, a packet which doesn't match a registered DCID is
275 * silently dropped. A default packet handler may be unset by passing NULL.
276 *
277 * The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or
278 * ossl_quic_demux_release_urxe is called on the passed packet at some point in
279 * the future, which may or may not be before the handler returns.
280 */
281 void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux,
282 ossl_quic_demux_cb_fn *cb,
283 void *cb_arg);
284
285 /*
286 * Sets a callback for stateless reset processing.
287 *
288 * If set, this callback is called for datagrams for which we cannot identify
289 * a CID. This function should return 1 if there is a stateless reset token
290 * present and 0 if not. If there is a token present, the connection should
291 * also be reset.
292 */
293 void ossl_quic_demux_set_stateless_reset_handler(
294 QUIC_DEMUX *demux,
295 ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg);
296
297 /*
298 * Releases a URXE back to the demuxer. No reference must be made to the URXE or
299 * its buffer after calling this function. The URXE must not be in any queue;
300 * that is, its prev and next pointers must be NULL.
301 */
302 void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux,
303 QUIC_URXE *e);
304
305 /*
306 * Reinjects a URXE which was issued to a registered DCID callback or the
307 * default packet handler callback back into the pending queue. This is useful
308 * when a packet has been handled by the default packet handler callback such
309 * that a DCID has now been registered and can be dispatched normally by DCID.
310 * Once this has been called, the caller must not touch the URXE anymore and
311 * must not also call ossl_quic_demux_release_urxe().
312 *
313 * The URXE is reinjected at the head of the queue, so it will be reprocessed
314 * immediately.
315 */
316 void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux,
317 QUIC_URXE *e);
318
319 /*
320 * Process any unprocessed RX'd datagrams, by calling registered callbacks by
321 * connection ID, reading more datagrams from the BIO if necessary.
322 *
323 * Returns one of the following values:
324 *
325 * QUIC_DEMUX_PUMP_RES_OK
326 * At least one incoming datagram was processed.
327 *
328 * QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL
329 * No more incoming datagrams are currently available.
330 * Call again later.
331 *
332 * QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL
333 * Either the network read BIO has failed in a non-transient fashion, or
334 * the QUIC implementation has encountered an internal state, assertion
335 * or allocation error. The caller should tear down the connection
336 * similarly to in the case of a protocol violation.
337 *
338 */
339 #define QUIC_DEMUX_PUMP_RES_OK 1
340 #define QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL (-1)
341 #define QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL (-2)
342 #define QUIC_DEMUX_PUMP_RES_STATELESS_RESET (-3)
343
344 int ossl_quic_demux_pump(QUIC_DEMUX *demux);
345
346 /*
347 * Artificially inject a packet into the demuxer for testing purposes. The
348 * buffer must not exceed the URXE size being used by the demuxer.
349 *
350 * If peer or local are NULL, their respective fields are zeroed in the injected
351 * URXE.
352 *
353 * Returns 1 on success or 0 on failure.
354 */
355 int ossl_quic_demux_inject(QUIC_DEMUX *demux,
356 const unsigned char *buf,
357 size_t buf_len,
358 const BIO_ADDR *peer,
359 const BIO_ADDR *local);
360
361 /*
362 * Returns 1 if there are any pending URXEs.
363 */
364 int ossl_quic_demux_has_pending(const QUIC_DEMUX *demux);
365
366 # endif
367
368 #endif