/* SPDX-License-Identifier: GPL-2.0 */ /** \file sideband.h exported symbols from sideband.c */ /** * The valid sideband designators. * * A sideband packet consists of a header and a body. The header is sent prior * to the data and contains the length of the buffer and the sideband * designator, an integer. This scheme allows receivers to never read more data * than what was specified in the header. * * The sideband designator indicates the type of the data. The authentication * handshake between the server (para_server or para_audiod) and the client * (para_client or para_audioc) requires to exchange several packages. Each * such package is sent as a sideband package with a dedicated designator. * * Other designators are employed for normal command output and for log * messages, where each loglevel corresponds to a sideband designator. * * Note that the values of this enum are part of the ABI, so never change * or remove entries. Appending is OK though. */ #define SB_DESIGNATORS \ /* Special value for receiving only: Accept any band. */ \ DESIGNATOR(ANY), \ /* This packet contains the authentication challenge. */ \ DESIGNATOR(CHALLENGE), \ /* I solved your challenge and here is the proof. */ \ DESIGNATOR(CHALLENGE_RESPONSE), \ /* Congratulations, you are authenticated. */ \ DESIGNATOR(PROCEED), \ /* This is the command I want you to execute. */ \ DESIGNATOR(COMMAND), \ /* Ready to receive a blob (addblob commands only). */ \ DESIGNATOR(AWAITING_DATA), \ /* Normal command output (default). */ \ DESIGNATOR(OUTPUT), \ /* LL_DEBUG. */ \ DESIGNATOR(DEBUG_LOG), \ /* LL_INFO. */ \ DESIGNATOR(INFO_LOG), \ /* LL_NOTICE. */ \ DESIGNATOR(NOTICE_LOG), \ /* LL_WARNING, */ \ DESIGNATOR(WARNING_LOG), \ /* LL_ERROR. */ \ DESIGNATOR(ERROR_LOG), \ /* LL_CRIT. */ \ DESIGNATOR(CRIT_LOG), \ /* LL_EMERG. */ \ DESIGNATOR(EMERG_LOG), \ /* Command terminated successfully. */ \ DESIGNATOR(EXIT__SUCCESS), \ /* Command failed. */ \ DESIGNATOR(EXIT__FAILURE), \ /* The next chunk of the blob (addblob commands only) */ \ DESIGNATOR(BLOB_DATA), \ /* An afs callback failed. */ \ DESIGNATOR(AFS_CB_FAILURE), \ /** Just prefix with \p SBD_. */ #define DESIGNATOR(x) SBD_ ## x /** All valid sideband designators. */ enum sb_designator {SB_DESIGNATORS NUM_SB_DESIGNATORS}; #undef DESIGNATOR /** One stringified sideband designator. */ #define DESIGNATOR(x) #x /** List of stringified sidedband designators. */ #define SB_DESIGNATORS_ARRAY SB_DESIGNATORS /** * The information contained in a sideband buffer. * * This structure is used for both sending and receiving data through a * sideband channel. A pointer to a sideband buffer is passed to the sending * side of a sideband while the receiving end yields a filled out structure * once all data has been received. */ struct sb_buffer { /** Data and length. */ struct iovec iov; /** The band designator. */ uint8_t band; }; static inline bool sideband_log(const char *pfx, struct sb_buffer *sbb) { size_t len = sbb->iov.iov_len; char *base = sbb->iov.iov_base; switch (sbb->band) { case SBD_DEBUG_LOG: case SBD_INFO_LOG: case SBD_NOTICE_LOG: case SBD_WARNING_LOG: case SBD_ERROR_LOG: case SBD_CRIT_LOG: case SBD_EMERG_LOG: if (len > INT_MAX) return false; para_log(sbb->band - SBD_DEBUG_LOG, "%s: %.*s", pfx, (int)len, base); return true; default: return false; } } /** * The opaque sideband context structure. * * A pointer to a structure of this type is returned by the two sb_new_xxx * functions as an opaque handle. Other public functions of the sideband * API take such a handle as the first parameter. */ struct sb_context; /** * The type of a sideband transformation. * * The sideband API allows the filtering of data through an arbitrary * transformation, which is useful for crypto purposes. The transformation may * either transform the data in place, or return a pointer to a new buffer * which contains the transformed source buffer. The internal sideband * functions can tell the two types of transformations apart by checking * whether the destination buffer coincides with the source buffer. * * If the transformation allocates a new buffer, it _must_ allocate one extra * byte for NULL termination. */ typedef void (*sb_transformation)(struct iovec *src, struct iovec *dst, void *trafo_context); /** Initialize a sideband buffer. */ #define SBB_INIT(_band, _buf, _numbytes) \ { \ .band = _band, \ .iov = { \ .iov_base = _buf, \ .iov_len = _numbytes \ } \ }; /* receiving */ struct sb_context *sb_new_recv(size_t max_size, sb_transformation t, void *trafo_context); void sb_get_recv_buffer(struct sb_context *c, struct iovec *iov); int sb_received(struct sb_context *c, size_t nbytes, struct sb_buffer *result); /* sending */ struct sb_context *sb_new_send(struct sb_buffer *sbb, bool dont_free, sb_transformation t, void *trafo_context); int sb_get_send_buffers(struct sb_context *c, struct iovec iov[2]); bool sb_sent(struct sb_context *c, size_t nbytes); void sb_free(struct sb_context *c);