diff options
author | Hugo Landau <hlandau@openssl.org> | 2022-11-22 13:25:41 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-01-19 13:17:39 +0000 |
commit | 93e9b6cc4e2b47a5fb32f093c38b7963e9c270aa (patch) | |
tree | 771df6c58ebd79ad8554ce7f46870061b69cc1ad | |
parent | 53b5d6c30f3b8eaf7a582da2265c0d1cfe14d54f (diff) | |
download | openssl-new-93e9b6cc4e2b47a5fb32f093c38b7963e9c270aa.tar.gz |
QUIC DEMUX: (Server support) Add support for default handler
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19734)
-rw-r--r-- | include/internal/quic_demux.h | 33 | ||||
-rw-r--r-- | ssl/quic/quic_demux.c | 51 |
2 files changed, 72 insertions, 12 deletions
diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index dba669645b..1e5a85f9d7 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -169,8 +169,9 @@ typedef struct quic_demux_st QUIC_DEMUX; * to mutate this buffer; once the demuxer calls this callback, it will never * read the buffer again. * - * The callee must arrange for ossl_quic_demux_release_urxe to be called on the URXE - * at some point in the future (this need not be before the callback returns). + * The callee must arrange for ossl_quic_demux_release_urxe or + * ossl_quic_demux_reinject_urxe to be called on the URXE at some point in the + * future (this need not be before the callback returns). * * At the time the callback is made, the URXE will not be in any queue, * therefore the callee can use the prev and next fields as it wishes. @@ -256,6 +257,20 @@ void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, void *cb_arg); /* + * Set the default packet handler. This is used for incoming packets which don't + * match a registered DCID. This is only needed for servers. If a default packet + * handler is not set, a packet which doesn't match a registered DCID is + * silently dropped. A default packet handler may be unset by passing NULL. + * + * The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or + * ossl_quic_demux_release_urxe is called on the passed packet at some point in + * the future, which may or may not be before the handler returns. + */ +void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, + ossl_quic_demux_cb_fn *cb, + void *cb_arg); + +/* * Releases a URXE back to the demuxer. No reference must be made to the URXE or * its buffer after calling this function. The URXE must not be in any queue; * that is, its prev and next pointers must be NULL. @@ -264,6 +279,20 @@ void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux, QUIC_URXE *e); /* + * Reinjects a URXE which was issued to a registered DCID callback or the + * default packet handler callback back into the pending queue. This is useful + * when a packet has been handled by the default packet handler callback such + * that a DCID has now been registered and can be dispatched normally by DCID. + * Once this has been called, the caller must not touch the URXE anymore and + * must not also call ossl_quic_demux_release_urxe(). + * + * The URXE is reinjected at the head of the queue, so it will be reprocessed + * immediately. + */ +void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux, + QUIC_URXE *e); + +/* * Process any unprocessed RX'd datagrams, by calling registered callbacks by * connection ID, reading more datagrams from the BIO if necessary. * diff --git a/ssl/quic/quic_demux.c b/ssl/quic/quic_demux.c index 6d30c1c2b9..b2afe73062 100644 --- a/ssl/quic/quic_demux.c +++ b/ssl/quic/quic_demux.c @@ -25,10 +25,10 @@ typedef struct quic_demux_conn_st QUIC_DEMUX_CONN; struct quic_demux_conn_st { - QUIC_DEMUX_CONN *next; /* used when unregistering only */ - QUIC_CONN_ID dst_conn_id; - ossl_quic_demux_cb_fn *cb; - void *cb_arg; + QUIC_DEMUX_CONN *next; /* used when unregistering only */ + QUIC_CONN_ID dst_conn_id; + ossl_quic_demux_cb_fn *cb; + void *cb_arg; }; DEFINE_LHASH_OF_EX(QUIC_DEMUX_CONN); @@ -76,6 +76,10 @@ struct quic_demux_st { /* Hashtable mapping connection IDs to QUIC_DEMUX_CONN structures. */ LHASH_OF(QUIC_DEMUX_CONN) *conns_by_id; + /* The default packet handler, if any. */ + ossl_quic_demux_cb_fn *default_cb; + void *default_cb_arg; + /* * List of URXEs which are not currently in use (i.e., not filled with * unconsumed data). These are moved to the pending list as they are filled. @@ -285,6 +289,14 @@ void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, } } +void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, + ossl_quic_demux_cb_fn *cb, + void *cb_arg) +{ + demux->default_cb = cb; + demux->default_cb_arg = cb_arg; +} + static QUIC_URXE *demux_alloc_urxe(size_t alloc_len) { QUIC_URXE *e; @@ -406,6 +418,7 @@ static int demux_recv(QUIC_DEMUX *demux) msg[i].data = ossl_quic_urxe_data(urxe); msg[i].data_len = urxe->alloc_len; msg[i].peer = &urxe->peer; + BIO_ADDR_clear(&urxe->peer); if (demux->use_local_addr) msg[i].local = &urxe->local; else @@ -484,12 +497,21 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) conn = demux_identify_conn(demux, e); if (conn == NULL) { /* - * We could not identify a connection. We will never be able to process - * this datagram, so get rid of it. + * We could not identify a connection. If we have a default packet + * handler, pass it to the handler. Otherwise, we will never be able to + * process this datagram, so get rid of it. */ - ossl_list_urxe_remove(&demux->urx_pending, e); - ossl_list_urxe_insert_tail(&demux->urx_free, e); - e->demux_state = URXE_DEMUX_STATE_FREE; + if (demux->default_cb != NULL) { + /* Pass to default handler. */ + ossl_list_urxe_remove(&demux->urx_pending, e); + e->demux_state = URXE_DEMUX_STATE_ISSUED; + demux->default_cb(e, demux->default_cb_arg); + } else { + /* Discard. */ + ossl_list_urxe_remove(&demux->urx_pending, e); + ossl_list_urxe_insert_tail(&demux->urx_free, e); + e->demux_state = URXE_DEMUX_STATE_FREE; + } return 1; /* keep processing pending URXEs */ } @@ -572,7 +594,7 @@ int ossl_quic_demux_inject(QUIC_DEMUX *demux, if (peer != NULL) urxe->peer = *peer; else - BIO_ADDR_clear(&urxe->local); + BIO_ADDR_clear(&urxe->peer); if (local != NULL) urxe->local = *local; @@ -596,3 +618,12 @@ void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux, ossl_list_urxe_insert_tail(&demux->urx_free, e); e->demux_state = URXE_DEMUX_STATE_FREE; } + +void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux, + QUIC_URXE *e) +{ + assert(ossl_list_urxe_prev(e) == NULL && ossl_list_urxe_next(e) == NULL); + assert(e->demux_state == URXE_DEMUX_STATE_ISSUED); + ossl_list_urxe_insert_head(&demux->urx_pending, e); + e->demux_state = URXE_DEMUX_STATE_PENDING; +} |