1 /* 2 * Copyright 2022-2024 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/quic_predef.h" 16 # include "internal/bio_addr.h" 17 # include "internal/time.h" 18 # include "internal/list.h" 19 20 # ifndef OPENSSL_NO_QUIC 21 22 /* 23 * QUIC Demuxer 24 * ============ 25 * 26 * The QUIC connection demuxer is the entity responsible for receiving datagrams 27 * from the network via a datagram BIO. It parses the headers of the first 28 * packet in the datagram to determine that packet's DCID and hands off 29 * processing of the entire datagram to a single callback function which can 30 * decide how to handle and route the datagram, for example by looking up 31 * a QRX instance and injecting the URXE into that QRX. 32 * 33 * A QRX will typically be instantiated per QUIC connection and contains the 34 * cryptographic resources needed to decrypt QUIC packets for that connection. 35 * However, it is up to the callback function to handle routing, for example by 36 * consulting a LCIDM instance. Thus the demuxer has no specific knowledge of 37 * any QRX and is not coupled to it. All CID knowledge is also externalised into 38 * a LCIDM or other CID state tracking object, without the DEMUX being coupled 39 * to any particular DCID resolution mechanism. 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 /* Maximum number of packets we allow to exist in one datagram. */ 87 #define QUIC_MAX_PKT_PER_URXE (sizeof(uint64_t) * 8) 88 89 struct quic_urxe_st { 90 OSSL_LIST_MEMBER(urxe, QUIC_URXE); 91 92 /* 93 * The URXE data starts after this structure so we don't need a pointer. 94 * data_len stores the current length (i.e., the length of the received 95 * datagram) and alloc_len stores the allocation length. The URXE will be 96 * reallocated if we need a larger allocation than is available, though this 97 * should not be common as we will have a good idea of worst-case MTUs up 98 * front. 99 */ 100 size_t data_len, alloc_len; 101 102 /* 103 * Bitfields per packet. processed indicates the packet has been processed 104 * and must not be processed again, hpr_removed indicates header protection 105 * has already been removed. Used by QRX only; not used by the demuxer. 106 */ 107 uint64_t processed, hpr_removed; 108 109 /* 110 * This monotonically increases with each datagram received. It is used for 111 * diagnostic purposes only. 112 */ 113 uint64_t datagram_id; 114 115 /* 116 * Address of peer we received the datagram from, and the local interface 117 * address we received it on. If local address support is not enabled, local 118 * is zeroed. 119 */ 120 BIO_ADDR peer, local; 121 122 /* 123 * Time at which datagram was received (or ossl_time_zero()) if a now 124 * function was not provided). 125 */ 126 OSSL_TIME time; 127 128 /* 129 * Used by the QRX to mark whether a datagram has been deferred. Used by the 130 * QRX only; not used by the demuxer. 131 */ 132 char deferred; 133 134 /* 135 * Used by the DEMUX to track if a URXE has been handed out. Used primarily 136 * for debugging purposes. 137 */ 138 char demux_state; 139 }; 140 141 /* Accessors for URXE buffer. */ 142 static ossl_unused ossl_inline unsigned char * 143 ossl_quic_urxe_data(const QUIC_URXE *e) 144 { 145 return (unsigned char *)&e[1]; 146 } 147 148 static ossl_unused ossl_inline unsigned char * 149 ossl_quic_urxe_data_end(const QUIC_URXE *e) 150 { 151 return ossl_quic_urxe_data(e) + e->data_len; 152 } 153 154 /* List structure tracking a queue of URXEs. */ 155 DEFINE_LIST_OF(urxe, QUIC_URXE); 156 typedef OSSL_LIST(urxe) QUIC_URXE_LIST; 157 158 /* 159 * List management helpers. These are used by the demuxer but can also be used 160 * by users of the demuxer to manage URXEs. 161 */ 162 void ossl_quic_urxe_remove(QUIC_URXE_LIST *l, QUIC_URXE *e); 163 void ossl_quic_urxe_insert_head(QUIC_URXE_LIST *l, QUIC_URXE *e); 164 void ossl_quic_urxe_insert_tail(QUIC_URXE_LIST *l, QUIC_URXE *e); 165 166 /* 167 * Called when a datagram is received for a given connection ID. 168 * 169 * e is a URXE containing the datagram payload. It is permissible for the callee 170 * to mutate this buffer; once the demuxer calls this callback, it will never 171 * read the buffer again. 172 * 173 * If a DCID was identified for the datagram, dcid is non-NULL; otherwise 174 * it is NULL. 175 * 176 * The callee must arrange for ossl_quic_demux_release_urxe or 177 * ossl_quic_demux_reinject_urxe to be called on the URXE at some point in the 178 * future (this need not be before the callback returns). 179 * 180 * At the time the callback is made, the URXE will not be in any queue, 181 * therefore the callee can use the prev and next fields as it wishes. 182 */ 183 typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg, 184 const QUIC_CONN_ID *dcid); 185 186 /* 187 * Creates a new demuxer. The given BIO is used to receive datagrams from the 188 * network using BIO_recvmmsg. short_conn_id_len is the length of destination 189 * connection IDs used in RX'd packets; it must have the same value for all 190 * connections used on a socket. default_urxe_alloc_len is the buffer size to 191 * receive datagrams into; it should be a value large enough to contain any 192 * received datagram according to local MTUs, etc. 193 * 194 * now is an optional function used to determine the time a datagram was 195 * received. now_arg is an opaque argument passed to the function. If now is 196 * NULL, ossl_time_zero() is used as the datagram reception time. 197 */ 198 QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio, 199 size_t short_conn_id_len, 200 OSSL_TIME (*now)(void *arg), 201 void *now_arg); 202 203 /* 204 * Destroy a demuxer. All URXEs must have been released back to the demuxer 205 * before calling this. No-op if demux is NULL. 206 */ 207 void ossl_quic_demux_free(QUIC_DEMUX *demux); 208 209 /* 210 * Changes the BIO which the demuxer reads from. This also sets the MTU if the 211 * BIO supports querying the MTU. 212 */ 213 void ossl_quic_demux_set_bio(QUIC_DEMUX *demux, BIO *net_bio); 214 215 /* 216 * Changes the MTU in bytes we use to receive datagrams. 217 */ 218 int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu); 219 220 /* 221 * Set the default packet handler. This is used for incoming packets which don't 222 * match a registered DCID. This is only needed for servers. If a default packet 223 * handler is not set, a packet which doesn't match a registered DCID is 224 * silently dropped. A default packet handler may be unset by passing NULL. 225 * 226 * The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or 227 * ossl_quic_demux_release_urxe is called on the passed packet at some point in 228 * the future, which may or may not be before the handler returns. 229 */ 230 void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, 231 ossl_quic_demux_cb_fn *cb, 232 void *cb_arg); 233 234 /* 235 * Releases a URXE back to the demuxer. No reference must be made to the URXE or 236 * its buffer after calling this function. The URXE must not be in any queue; 237 * that is, its prev and next pointers must be NULL. 238 */ 239 void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux, 240 QUIC_URXE *e); 241 242 /* 243 * Reinjects a URXE which was issued to a registered DCID callback or the 244 * default packet handler callback back into the pending queue. This is useful 245 * when a packet has been handled by the default packet handler callback such 246 * that a DCID has now been registered and can be dispatched normally by DCID. 247 * Once this has been called, the caller must not touch the URXE anymore and 248 * must not also call ossl_quic_demux_release_urxe(). 249 * 250 * The URXE is reinjected at the head of the queue, so it will be reprocessed 251 * immediately. 252 */ 253 void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux, 254 QUIC_URXE *e); 255 256 /* 257 * Process any unprocessed RX'd datagrams, by calling registered callbacks by 258 * connection ID, reading more datagrams from the BIO if necessary. 259 * 260 * Returns one of the following values: 261 * 262 * QUIC_DEMUX_PUMP_RES_OK 263 * At least one incoming datagram was processed. 264 * 265 * QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL 266 * No more incoming datagrams are currently available. 267 * Call again later. 268 * 269 * QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL 270 * Either the network read BIO has failed in a non-transient fashion, or 271 * the QUIC implementation has encountered an internal state, assertion 272 * or allocation error. The caller should tear down the connection 273 * similarly to in the case of a protocol violation. 274 * 275 */ 276 #define QUIC_DEMUX_PUMP_RES_OK 1 277 #define QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL (-1) 278 #define QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL (-2) 279 280 int ossl_quic_demux_pump(QUIC_DEMUX *demux); 281 282 /* 283 * Artificially inject a packet into the demuxer for testing purposes. The 284 * buffer must not exceed the URXE size being used by the demuxer. 285 * 286 * If peer or local are NULL, their respective fields are zeroed in the injected 287 * URXE. 288 * 289 * Returns 1 on success or 0 on failure. 290 */ 291 int ossl_quic_demux_inject(QUIC_DEMUX *demux, 292 const unsigned char *buf, 293 size_t buf_len, 294 const BIO_ADDR *peer, 295 const BIO_ADDR *local); 296 297 /* 298 * Returns 1 if there are any pending URXEs. 299 */ 300 int ossl_quic_demux_has_pending(const QUIC_DEMUX *demux); 301 302 # endif 303 304 #endif 305