]>
Commit | Line | Data |
---|---|---|
ec279ac2 | 1 | /* |
da1c088f | 2 | * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. |
ec279ac2 HL |
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" | |
948c656c | 16 | # include "internal/time.h" |
3fb172ef | 17 | # include "internal/list.h" |
ec279ac2 | 18 | |
6292519c HL |
19 | # ifndef OPENSSL_NO_QUIC |
20 | ||
ec279ac2 HL |
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 | |
19571483 HL |
28 | * the packet to the correct QUIC Record Layer (QRL)'s RX side (known as the |
29 | * QRX). | |
ec279ac2 | 30 | * |
19571483 | 31 | * A QRX is instantiated per QUIC connection and contains the cryptographic |
ec279ac2 | 32 | * resources needed to decrypt QUIC packets for that connection. Received |
19571483 HL |
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. | |
ec279ac2 | 36 | * |
19571483 | 37 | * A connection may have multiple connection IDs associated with it; a QRX |
ec279ac2 HL |
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 | |
19571483 | 57 | * to route a received datagram, and it is the responsibility of the QRX to |
ec279ac2 HL |
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 | |
19571483 | 62 | * of the QRX. |
ec279ac2 HL |
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 | |
19571483 | 70 | * components, like the QRX, which would otherwise have to allocate extra |
ec279ac2 HL |
71 | * memory corresponding to each URXE. |
72 | * | |
19571483 | 73 | * - Other components, like the QRX, can keep the URXE in queues of its own |
ec279ac2 HL |
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 { | |
3fb172ef | 92 | OSSL_LIST_MEMBER(urxe, QUIC_URXE); |
ec279ac2 HL |
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 | |
19571483 | 107 | * has already been removed. Used by QRX only; not used by the demuxer. |
ec279ac2 HL |
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; | |
948c656c HL |
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; | |
0ff98137 HL |
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; | |
d7668ff2 HL |
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; | |
ec279ac2 HL |
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. */ | |
3fb172ef P |
151 | DEFINE_LIST_OF(urxe, QUIC_URXE); |
152 | typedef OSSL_LIST(urxe) QUIC_URXE_LIST; | |
ec279ac2 HL |
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 | * | |
93e9b6cc HL |
172 | * The callee must arrange for ossl_quic_demux_release_urxe or |
173 | * ossl_quic_demux_reinject_urxe to be called on the URXE at some point in the | |
174 | * future (this need not be before the callback returns). | |
ec279ac2 HL |
175 | * |
176 | * At the time the callback is made, the URXE will not be in any queue, | |
177 | * therefore the callee can use the prev and next fields as it wishes. | |
178 | */ | |
179 | typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg); | |
180 | ||
cdd91631 P |
181 | /* |
182 | * Called when a datagram is received. | |
183 | * Returns 1 if the datagram ends with a stateless reset token and | |
184 | * 0 if not. | |
185 | */ | |
186 | typedef int (ossl_quic_stateless_reset_cb_fn)(const unsigned char *data, | |
187 | size_t data_len, void *arg); | |
188 | ||
ec279ac2 HL |
189 | /* |
190 | * Creates a new demuxer. The given BIO is used to receive datagrams from the | |
191 | * network using BIO_recvmmsg. short_conn_id_len is the length of destination | |
192 | * connection IDs used in RX'd packets; it must have the same value for all | |
193 | * connections used on a socket. default_urxe_alloc_len is the buffer size to | |
194 | * receive datagrams into; it should be a value large enough to contain any | |
195 | * received datagram according to local MTUs, etc. | |
948c656c HL |
196 | * |
197 | * now is an optional function used to determine the time a datagram was | |
198 | * received. now_arg is an opaque argument passed to the function. If now is | |
199 | * NULL, ossl_time_zero() is used as the datagram reception time. | |
ec279ac2 HL |
200 | */ |
201 | QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio, | |
202 | size_t short_conn_id_len, | |
948c656c HL |
203 | OSSL_TIME (*now)(void *arg), |
204 | void *now_arg); | |
ec279ac2 HL |
205 | |
206 | /* | |
207 | * Destroy a demuxer. All URXEs must have been released back to the demuxer | |
208 | * before calling this. No-op if demux is NULL. | |
209 | */ | |
210 | void ossl_quic_demux_free(QUIC_DEMUX *demux); | |
211 | ||
964f0deb | 212 | /* |
d7668ff2 HL |
213 | * Changes the BIO which the demuxer reads from. This also sets the MTU if the |
214 | * BIO supports querying the MTU. | |
964f0deb HL |
215 | */ |
216 | void ossl_quic_demux_set_bio(QUIC_DEMUX *demux, BIO *net_bio); | |
217 | ||
d7668ff2 HL |
218 | /* |
219 | * Changes the MTU in bytes we use to receive datagrams. | |
220 | */ | |
221 | int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu); | |
222 | ||
ec279ac2 HL |
223 | /* |
224 | * Register a datagram handler callback for a connection ID. | |
225 | * | |
226 | * ossl_quic_demux_pump will call the specified function if it receives a datagram | |
227 | * the first packet of which has the specified destination connection ID. | |
228 | * | |
229 | * It is assumed all packets in a datagram have the same destination connection | |
230 | * ID (as QUIC mandates this), but it is the user's responsibility to check for | |
231 | * this and reject subsequent packets in a datagram that violate this rule. | |
232 | * | |
233 | * dst_conn_id is a destination connection ID; it is copied and need not remain | |
234 | * valid after this function returns. | |
235 | * | |
236 | * cb_arg is passed to cb when it is called. For information on the callback, | |
237 | * see its typedef above. | |
238 | * | |
239 | * Only one handler can be set for a given connection ID. If a handler is | |
240 | * already set for the given connection ID, returns 0. | |
241 | * | |
242 | * Returns 1 on success or 0 on failure. | |
243 | */ | |
244 | int ossl_quic_demux_register(QUIC_DEMUX *demux, | |
245 | const QUIC_CONN_ID *dst_conn_id, | |
246 | ossl_quic_demux_cb_fn *cb, | |
247 | void *cb_arg); | |
248 | ||
249 | /* | |
250 | * Unregisters any datagram handler callback set for the given connection ID. | |
251 | * Fails if no handler is registered for the given connection ID. | |
252 | * | |
253 | * Returns 1 on success or 0 on failure. | |
254 | */ | |
255 | int ossl_quic_demux_unregister(QUIC_DEMUX *demux, | |
256 | const QUIC_CONN_ID *dst_conn_id); | |
257 | ||
258 | /* | |
259 | * Unregisters any datagram handler callback from all connection IDs it is used | |
260 | * for. cb and cb_arg must both match the values passed to | |
261 | * ossl_quic_demux_register. | |
262 | */ | |
263 | void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, | |
264 | ossl_quic_demux_cb_fn *cb, | |
265 | void *cb_arg); | |
266 | ||
93e9b6cc HL |
267 | /* |
268 | * Set the default packet handler. This is used for incoming packets which don't | |
269 | * match a registered DCID. This is only needed for servers. If a default packet | |
270 | * handler is not set, a packet which doesn't match a registered DCID is | |
271 | * silently dropped. A default packet handler may be unset by passing NULL. | |
272 | * | |
273 | * The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or | |
274 | * ossl_quic_demux_release_urxe is called on the passed packet at some point in | |
275 | * the future, which may or may not be before the handler returns. | |
276 | */ | |
277 | void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, | |
278 | ossl_quic_demux_cb_fn *cb, | |
279 | void *cb_arg); | |
280 | ||
cdd91631 P |
281 | /* |
282 | * Sets a callback for stateless reset processing. | |
283 | * | |
284 | * If set, this callback is called for datagrams for which we cannot identify | |
285 | * a CID. This function should return 1 if there is a stateless reset token | |
286 | * present and 0 if not. If there is a token present, the connection should | |
287 | * also be reset. | |
288 | */ | |
289 | void ossl_quic_demux_set_stateless_reset_handler( | |
290 | QUIC_DEMUX *demux, | |
291 | ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg); | |
292 | ||
ec279ac2 HL |
293 | /* |
294 | * Releases a URXE back to the demuxer. No reference must be made to the URXE or | |
295 | * its buffer after calling this function. The URXE must not be in any queue; | |
296 | * that is, its prev and next pointers must be NULL. | |
297 | */ | |
298 | void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux, | |
299 | QUIC_URXE *e); | |
300 | ||
93e9b6cc HL |
301 | /* |
302 | * Reinjects a URXE which was issued to a registered DCID callback or the | |
303 | * default packet handler callback back into the pending queue. This is useful | |
304 | * when a packet has been handled by the default packet handler callback such | |
305 | * that a DCID has now been registered and can be dispatched normally by DCID. | |
306 | * Once this has been called, the caller must not touch the URXE anymore and | |
307 | * must not also call ossl_quic_demux_release_urxe(). | |
308 | * | |
309 | * The URXE is reinjected at the head of the queue, so it will be reprocessed | |
310 | * immediately. | |
311 | */ | |
312 | void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux, | |
313 | QUIC_URXE *e); | |
314 | ||
ec279ac2 HL |
315 | /* |
316 | * Process any unprocessed RX'd datagrams, by calling registered callbacks by | |
317 | * connection ID, reading more datagrams from the BIO if necessary. | |
318 | * | |
66eab5e0 HL |
319 | * Returns one of the following values: |
320 | * | |
321 | * QUIC_DEMUX_PUMP_RES_OK | |
322 | * At least one incoming datagram was processed. | |
323 | * | |
324 | * QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL | |
325 | * No more incoming datagrams are currently available. | |
326 | * Call again later. | |
327 | * | |
328 | * QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL | |
329 | * Either the network read BIO has failed in a non-transient fashion, or | |
330 | * the QUIC implementation has encountered an internal state, assertion | |
331 | * or allocation error. The caller should tear down the connection | |
332 | * similarly to in the case of a protocol violation. | |
333 | * | |
ec279ac2 | 334 | */ |
66eab5e0 HL |
335 | #define QUIC_DEMUX_PUMP_RES_OK 1 |
336 | #define QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL (-1) | |
337 | #define QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL (-2) | |
cdd91631 | 338 | #define QUIC_DEMUX_PUMP_RES_STATELESS_RESET (-3) |
66eab5e0 | 339 | |
ec279ac2 HL |
340 | int ossl_quic_demux_pump(QUIC_DEMUX *demux); |
341 | ||
342 | /* | |
343 | * Artificially inject a packet into the demuxer for testing purposes. The | |
344 | * buffer must not exceed the URXE size being used by the demuxer. | |
345 | * | |
346 | * If peer or local are NULL, their respective fields are zeroed in the injected | |
347 | * URXE. | |
348 | * | |
349 | * Returns 1 on success or 0 on failure. | |
350 | */ | |
351 | int ossl_quic_demux_inject(QUIC_DEMUX *demux, | |
352 | const unsigned char *buf, | |
353 | size_t buf_len, | |
354 | const BIO_ADDR *peer, | |
355 | const BIO_ADDR *local); | |
356 | ||
9280d26a HL |
357 | /* |
358 | * Returns 1 if there are any pending URXEs. | |
359 | */ | |
360 | int ossl_quic_demux_has_pending(const QUIC_DEMUX *demux); | |
361 | ||
6292519c HL |
362 | # endif |
363 | ||
ec279ac2 | 364 | #endif |