Home | History | Annotate | Line # | Download | only in internal
      1      1.1  christos /*
      2  1.1.1.2  christos  * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
      3  1.1.1.2  christos  *
      4  1.1.1.2  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  1.1.1.2  christos  * this file except in compliance with the License.  You can obtain a copy
      6  1.1.1.2  christos  * in the file LICENSE in the source distribution or at
      7  1.1.1.2  christos  * https://www.openssl.org/source/license.html
      8  1.1.1.2  christos  */
      9      1.1  christos 
     10      1.1  christos #ifndef OSSL_INTERNAL_QUIC_RCIDM_H
     11  1.1.1.2  christos #define OSSL_INTERNAL_QUIC_RCIDM_H
     12  1.1.1.2  christos #pragma once
     13      1.1  christos 
     14  1.1.1.2  christos #include "internal/e_os.h"
     15  1.1.1.2  christos #include "internal/time.h"
     16  1.1.1.2  christos #include "internal/quic_types.h"
     17  1.1.1.2  christos #include "internal/quic_wire.h"
     18      1.1  christos 
     19  1.1.1.2  christos #ifndef OPENSSL_NO_QUIC
     20      1.1  christos 
     21      1.1  christos /*
     22      1.1  christos  * QUIC Remote Connection ID Manager
     23      1.1  christos  * =================================
     24      1.1  christos  *
     25      1.1  christos  * This manages connection IDs for the TX side. The RCIDM tracks remote CIDs
     26      1.1  christos  * (RCIDs) which a peer has issued to us and which we can use as the DCID of
     27      1.1  christos  * packets we transmit. It is entirely separate from the LCIDM, which handles
     28      1.1  christos  * routing received packets by their DCIDs.
     29      1.1  christos  *
     30      1.1  christos  * RCIDs fall into four categories:
     31      1.1  christos  *
     32      1.1  christos  *   1. A client's Initial ODCID                        (0..1)
     33      1.1  christos  *   2. A peer's Initial SCID                           (1)
     34      1.1  christos  *   3. A server's Retry SCID                           (0..1)
     35      1.1  christos  *   4. A CID issued via a NEW_CONNECTION_ID frame      (n)
     36      1.1  christos  *
     37      1.1  christos  * Unlike a LCIDM, which is per port, a RCIDM is per connection, as there is no
     38      1.1  christos  * need for routing of outgoing packets.
     39      1.1  christos  */
     40      1.1  christos typedef struct quic_rcidm_st QUIC_RCIDM;
     41      1.1  christos 
     42      1.1  christos /*
     43      1.1  christos  * Creates a new RCIDM. Returns NULL on failure.
     44      1.1  christos  *
     45      1.1  christos  * For a client, initial_odcid is the client's Initial ODCID.
     46      1.1  christos  * For a server, initial_odcid is NULL.
     47      1.1  christos  */
     48      1.1  christos QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);
     49      1.1  christos 
     50      1.1  christos /* Frees a RCIDM. */
     51      1.1  christos void ossl_quic_rcidm_free(QUIC_RCIDM *rcidm);
     52      1.1  christos 
     53      1.1  christos /*
     54      1.1  christos  * CID Events
     55      1.1  christos  * ==========
     56      1.1  christos  */
     57      1.1  christos 
     58      1.1  christos /*
     59      1.1  christos  * To be called by a client when a server responds to the first Initial packet
     60      1.1  christos  * sent with its own Initial packet with its own SCID; or to be called by a
     61      1.1  christos  * server when we first get an Initial packet from a client with the client's
     62      1.1  christos  * supplied SCID. The added RCID implicitly has a sequence number of 0.
     63      1.1  christos  *
     64      1.1  christos  * We immediately switch to using this SCID as our preferred RCID. This SCID
     65      1.1  christos  * must be enrolled using this function. May only be called once.
     66      1.1  christos  */
     67      1.1  christos int ossl_quic_rcidm_add_from_initial(QUIC_RCIDM *rcidm,
     68  1.1.1.2  christos     const QUIC_CONN_ID *rcid);
     69      1.1  christos 
     70      1.1  christos /*
     71      1.1  christos  * To be called by a client when a server responds to the first Initial packet
     72      1.1  christos  * sent with a Retry packet with its own SCID (the "Retry ODCID"). We
     73      1.1  christos  * immediately switch to using this SCID as our preferred RCID when conducting
     74      1.1  christos  * the retry. This SCID must be enrolled using this function. May only be called
     75      1.1  christos  * once. The added RCID has no sequence number associated with it as it is
     76      1.1  christos  * essentially a new ODCID (hereafter a Retry ODCID).
     77      1.1  christos  *
     78      1.1  christos  * Not for server use.
     79      1.1  christos  */
     80      1.1  christos int ossl_quic_rcidm_add_from_server_retry(QUIC_RCIDM *rcidm,
     81  1.1.1.2  christos     const QUIC_CONN_ID *retry_odcid);
     82      1.1  christos 
     83      1.1  christos /*
     84      1.1  christos  * Processes an incoming NEW_CONN_ID frame, recording the new CID as a potential
     85      1.1  christos  * RCID. The RCIDM retirement mechanism is ratcheted according to the
     86      1.1  christos  * ncid->retire_prior_to field. The stateless_reset field is ignored; the caller
     87      1.1  christos  * is responsible for handling it separately.
     88      1.1  christos  */
     89      1.1  christos int ossl_quic_rcidm_add_from_ncid(QUIC_RCIDM *rcidm,
     90  1.1.1.2  christos     const OSSL_QUIC_FRAME_NEW_CONN_ID *ncid);
     91      1.1  christos 
     92      1.1  christos /*
     93      1.1  christos  * Other Events
     94      1.1  christos  * ============
     95      1.1  christos  */
     96      1.1  christos 
     97      1.1  christos /*
     98      1.1  christos  * Notifies the RCIDM that the handshake for a connection is complete.
     99      1.1  christos  * Should only be called once; further calls are ignored.
    100      1.1  christos  *
    101      1.1  christos  * This may influence the RCIDM's RCID change policy.
    102      1.1  christos  */
    103      1.1  christos void ossl_quic_rcidm_on_handshake_complete(QUIC_RCIDM *rcidm);
    104      1.1  christos 
    105      1.1  christos /*
    106      1.1  christos  * Notifies the RCIDM that one or more packets have been sent.
    107      1.1  christos  *
    108      1.1  christos  * This may influence the RCIDM's RCID change policy.
    109      1.1  christos  */
    110      1.1  christos void ossl_quic_rcidm_on_packet_sent(QUIC_RCIDM *rcidm, uint64_t num_packets);
    111      1.1  christos 
    112      1.1  christos /*
    113      1.1  christos  * Manually request switching to a new RCID as soon as possible.
    114      1.1  christos  */
    115      1.1  christos void ossl_quic_rcidm_request_roll(QUIC_RCIDM *rcidm);
    116      1.1  christos 
    117      1.1  christos /*
    118      1.1  christos  * Queries
    119      1.1  christos  * =======
    120      1.1  christos  */
    121      1.1  christos 
    122      1.1  christos /*
    123      1.1  christos  * The RCIDM decides when it will never use a given RCID again. When it does
    124      1.1  christos  * this, it outputs the sequence number of that RCID using this function, which
    125      1.1  christos  * pops from a logical queue of retired RCIDs. The caller is responsible
    126      1.1  christos  * for polling this function and generating Retire CID frames from the result.
    127      1.1  christos  *
    128      1.1  christos  * If nothing needs doing and the queue is empty, this function returns 0. If
    129      1.1  christos  * there is an RCID which needs retiring, the sequence number of that RCID is
    130      1.1  christos  * written to *seq_num (if seq_num is non-NULL) and this function returns 1. The
    131      1.1  christos  * queue entry is popped (and the caller is thus assumed to have taken
    132      1.1  christos  * responsibility for transmitting the necessary Retire CID frame).
    133      1.1  christos  *
    134      1.1  christos  * Note that the caller should not transmit a Retire CID frame immediately as
    135      1.1  christos  * packets using the RCID may still be in flight. The caller must determine an
    136      1.1  christos  * appropriate delay using knowledge of network conditions (RTT, etc.) which is
    137      1.1  christos  * outside the scope of the RCIDM. The caller is responsible for implementing
    138      1.1  christos  * this delay based on the last time a packet was transmitted using the RCID
    139      1.1  christos  * being retired.
    140      1.1  christos  */
    141      1.1  christos int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
    142      1.1  christos 
    143      1.1  christos /*
    144      1.1  christos  * Like ossl_quic_rcidm_pop_retire_seq_num, but does not pop the item from the
    145      1.1  christos  * queue. If this call succeeds, the next call to
    146      1.1  christos  * ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
    147      1.1  christos  * number.
    148      1.1  christos  */
    149      1.1  christos int ossl_quic_rcidm_peek_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
    150      1.1  christos 
    151      1.1  christos /*
    152      1.1  christos  * Writes the DCID preferred for a newly transmitted packet at this time to
    153      1.1  christos  * *tx_dcid. This function should be called to determine what DCID to use when
    154      1.1  christos  * transmitting a packet to the peer. The RCIDM may implement arbitrary policy
    155      1.1  christos  * to decide when to change the preferred RCID.
    156      1.1  christos  *
    157      1.1  christos  * Returns 1 on success and 0 on failure.
    158      1.1  christos  */
    159      1.1  christos int ossl_quic_rcidm_get_preferred_tx_dcid(QUIC_RCIDM *rcidm,
    160  1.1.1.2  christos     QUIC_CONN_ID *tx_dcid);
    161      1.1  christos 
    162      1.1  christos /*
    163      1.1  christos  * Returns 1 if the value output by ossl_quic_rcidm_get_preferred_tx_dcid() has
    164      1.1  christos  * changed since the last call to this function with clear set. If clear is set,
    165      1.1  christos  * clears the changed flag. Returns the old value of the changed flag.
    166      1.1  christos  */
    167      1.1  christos int ossl_quic_rcidm_get_preferred_tx_dcid_changed(QUIC_RCIDM *rcidm,
    168  1.1.1.2  christos     int clear);
    169      1.1  christos 
    170      1.1  christos /*
    171      1.1  christos  * Returns the number of active numbered RCIDs we have. Note that this includes
    172      1.1  christos  * RCIDs on the retir*ing* queue accessed via
    173      1.1  christos  * ossl_quic_rcidm_pop_retire_seq_num() as these are still active until actually
    174      1.1  christos  * retired.
    175      1.1  christos  */
    176      1.1  christos size_t ossl_quic_rcidm_get_num_active(const QUIC_RCIDM *rcidm);
    177      1.1  christos 
    178      1.1  christos /*
    179      1.1  christos  * Returns the number of retir*ing* numbered RCIDs we have.
    180      1.1  christos  */
    181      1.1  christos size_t ossl_quic_rcidm_get_num_retiring(const QUIC_RCIDM *rcidm);
    182      1.1  christos 
    183  1.1.1.2  christos #endif
    184      1.1  christos 
    185      1.1  christos #endif
    186