QUIC: Enable building with QUIC support disabled
[openssl.git] / include / internal / quic_demux.h
1 /*
2  * Copyright 2022 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 /* Accessors for URXE buffer. */
132 static ossl_unused ossl_inline unsigned char *
133 ossl_quic_urxe_data(const QUIC_URXE *e)
134 {
135     return (unsigned char *)&e[1];
136 }
137
138 static ossl_unused ossl_inline unsigned char *
139 ossl_quic_urxe_data_end(const QUIC_URXE *e)
140 {
141     return ossl_quic_urxe_data(e) + e->data_len;
142 }
143
144 /* List structure tracking a queue of URXEs. */
145 DEFINE_LIST_OF(urxe, QUIC_URXE);
146 typedef OSSL_LIST(urxe) QUIC_URXE_LIST;
147
148 /*
149  * List management helpers. These are used by the demuxer but can also be used
150  * by users of the demuxer to manage URXEs.
151  */
152 void ossl_quic_urxe_remove(QUIC_URXE_LIST *l, QUIC_URXE *e);
153 void ossl_quic_urxe_insert_head(QUIC_URXE_LIST *l, QUIC_URXE *e);
154 void ossl_quic_urxe_insert_tail(QUIC_URXE_LIST *l, QUIC_URXE *e);
155
156 /* Opaque type representing a demuxer. */
157 typedef struct quic_demux_st QUIC_DEMUX;
158
159 /*
160  * Called when a datagram is received for a given connection ID.
161  *
162  * e is a URXE containing the datagram payload. It is permissible for the callee
163  * to mutate this buffer; once the demuxer calls this callback, it will never
164  * read the buffer again.
165  *
166  * The callee must arrange for ossl_quic_demux_release_urxe to be called on the URXE
167  * at some point in the future (this need not be before the callback returns).
168  *
169  * At the time the callback is made, the URXE will not be in any queue,
170  * therefore the callee can use the prev and next fields as it wishes.
171  */
172 typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg);
173
174 /*
175  * Creates a new demuxer. The given BIO is used to receive datagrams from the
176  * network using BIO_recvmmsg. short_conn_id_len is the length of destination
177  * connection IDs used in RX'd packets; it must have the same value for all
178  * connections used on a socket. default_urxe_alloc_len is the buffer size to
179  * receive datagrams into; it should be a value large enough to contain any
180  * received datagram according to local MTUs, etc.
181  *
182  * now is an optional function used to determine the time a datagram was
183  * received. now_arg is an opaque argument passed to the function. If now is
184  * NULL, ossl_time_zero() is used as the datagram reception time.
185  */
186 QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio,
187                                 size_t short_conn_id_len,
188                                 size_t default_urxe_alloc_len,
189                                 OSSL_TIME (*now)(void *arg),
190                                 void *now_arg);
191
192 /*
193  * Destroy a demuxer. All URXEs must have been released back to the demuxer
194  * before calling this. No-op if demux is NULL.
195  */
196 void ossl_quic_demux_free(QUIC_DEMUX *demux);
197
198 /*
199  * Changes the BIO which the demuxer reads from.
200  */
201 void ossl_quic_demux_set_bio(QUIC_DEMUX *demux, BIO *net_bio);
202
203 /*
204  * Register a datagram handler callback for a connection ID.
205  *
206  * ossl_quic_demux_pump will call the specified function if it receives a datagram
207  * the first packet of which has the specified destination connection ID.
208  *
209  * It is assumed all packets in a datagram have the same destination connection
210  * ID (as QUIC mandates this), but it is the user's responsibility to check for
211  * this and reject subsequent packets in a datagram that violate this rule.
212  *
213  * dst_conn_id is a destination connection ID; it is copied and need not remain
214  * valid after this function returns.
215  *
216  * cb_arg is passed to cb when it is called. For information on the callback,
217  * see its typedef above.
218  *
219  * Only one handler can be set for a given connection ID. If a handler is
220  * already set for the given connection ID, returns 0.
221  *
222  * Returns 1 on success or 0 on failure.
223  */
224 int ossl_quic_demux_register(QUIC_DEMUX *demux,
225                              const QUIC_CONN_ID *dst_conn_id,
226                              ossl_quic_demux_cb_fn *cb,
227                              void *cb_arg);
228
229 /*
230  * Unregisters any datagram handler callback set for the given connection ID.
231  * Fails if no handler is registered for the given connection ID.
232  *
233  * Returns 1 on success or 0 on failure.
234  */
235 int ossl_quic_demux_unregister(QUIC_DEMUX *demux,
236                                const QUIC_CONN_ID *dst_conn_id);
237
238 /*
239  * Unregisters any datagram handler callback from all connection IDs it is used
240  * for. cb and cb_arg must both match the values passed to
241  * ossl_quic_demux_register.
242  */
243 void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux,
244                                       ossl_quic_demux_cb_fn *cb,
245                                       void *cb_arg);
246
247 /*
248  * Releases a URXE back to the demuxer. No reference must be made to the URXE or
249  * its buffer after calling this function. The URXE must not be in any queue;
250  * that is, its prev and next pointers must be NULL.
251  */
252 void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux,
253                                   QUIC_URXE *e);
254
255 /*
256  * Process any unprocessed RX'd datagrams, by calling registered callbacks by
257  * connection ID, reading more datagrams from the BIO if necessary.
258  *
259  * Returns 1 on success or 0 on failure.
260  */
261 int ossl_quic_demux_pump(QUIC_DEMUX *demux);
262
263 /*
264  * Artificially inject a packet into the demuxer for testing purposes. The
265  * buffer must not exceed the URXE size being used by the demuxer.
266  *
267  * If peer or local are NULL, their respective fields are zeroed in the injected
268  * URXE.
269  *
270  * Returns 1 on success or 0 on failure.
271  */
272 int ossl_quic_demux_inject(QUIC_DEMUX *demux,
273                            const unsigned char *buf,
274                            size_t buf_len,
275                            const BIO_ADDR *peer,
276                            const BIO_ADDR *local);
277
278 # endif
279
280 #endif