11cb0ef41Sopenharmony_ci/* MIT License 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Copyright (c) 2023 Brad House 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights 81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 111cb0ef41Sopenharmony_ci * 121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next 131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 141cb0ef41Sopenharmony_ci * Software. 151cb0ef41Sopenharmony_ci * 161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 221cb0ef41Sopenharmony_ci * SOFTWARE. 231cb0ef41Sopenharmony_ci * 241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 251cb0ef41Sopenharmony_ci */ 261cb0ef41Sopenharmony_ci#ifndef __ARES__BUF_H 271cb0ef41Sopenharmony_ci#define __ARES__BUF_H 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci/*! \addtogroup ares__buf Safe Data Builder and buffer 301cb0ef41Sopenharmony_ci * 311cb0ef41Sopenharmony_ci * This is a buffer building and parsing framework with a focus on security over 321cb0ef41Sopenharmony_ci * performance. All data to be read from the buffer will perform explicit length 331cb0ef41Sopenharmony_ci * validation and return a success/fail result. There are also various helpers 341cb0ef41Sopenharmony_ci * for writing data to the buffer which dynamically grows. 351cb0ef41Sopenharmony_ci * 361cb0ef41Sopenharmony_ci * All operations that fetch or consume data from the buffer will move forward 371cb0ef41Sopenharmony_ci * the internal pointer, thus marking the data as processed which may no longer 381cb0ef41Sopenharmony_ci * be accessible after certain operations (such as append). 391cb0ef41Sopenharmony_ci * 401cb0ef41Sopenharmony_ci * The helpers for this object are meant to be added as needed. If you can't 411cb0ef41Sopenharmony_ci * find it, write it! 421cb0ef41Sopenharmony_ci * 431cb0ef41Sopenharmony_ci * @{ 441cb0ef41Sopenharmony_ci */ 451cb0ef41Sopenharmony_cistruct ares__buf; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci/*! Opaque data type for generic hash table implementation */ 481cb0ef41Sopenharmony_citypedef struct ares__buf ares__buf_t; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci/*! Create a new buffer object that dynamically allocates buffers for data. 511cb0ef41Sopenharmony_ci * 521cb0ef41Sopenharmony_ci * \return initialized buffer object or NULL if out of memory. 531cb0ef41Sopenharmony_ci */ 541cb0ef41Sopenharmony_ciares__buf_t *ares__buf_create(void); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci/*! Create a new buffer object that uses a user-provided data pointer. The 571cb0ef41Sopenharmony_ci * data provided will not be manipulated, and cannot be appended to. This 581cb0ef41Sopenharmony_ci * is strictly used for parsing. 591cb0ef41Sopenharmony_ci * 601cb0ef41Sopenharmony_ci * \param[in] data Data to provide to buffer, must not be NULL. 611cb0ef41Sopenharmony_ci * \param[in] data_len Size of buffer provided, must be > 0 621cb0ef41Sopenharmony_ci * 631cb0ef41Sopenharmony_ci * \return initialized buffer object or NULL if out of memory or misuse. 641cb0ef41Sopenharmony_ci */ 651cb0ef41Sopenharmony_ciares__buf_t *ares__buf_create_const(const unsigned char *data, size_t data_len); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci/*! Destroy an initialized buffer object. 691cb0ef41Sopenharmony_ci * 701cb0ef41Sopenharmony_ci * \param[in] buf Initialized buf object 711cb0ef41Sopenharmony_ci */ 721cb0ef41Sopenharmony_civoid ares__buf_destroy(ares__buf_t *buf); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci/*! Append multiple bytes to a dynamic buffer object 761cb0ef41Sopenharmony_ci * 771cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 781cb0ef41Sopenharmony_ci * \param[in] data Data to copy to buffer object 791cb0ef41Sopenharmony_ci * \param[in] data_len Length of data to copy to buffer object. 801cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 811cb0ef41Sopenharmony_ci */ 821cb0ef41Sopenharmony_ciares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data, 831cb0ef41Sopenharmony_ci size_t data_len); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci/*! Append a single byte to the dynamic buffer object 861cb0ef41Sopenharmony_ci * 871cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 881cb0ef41Sopenharmony_ci * \param[in] byte Single byte to append to buffer object. 891cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 901cb0ef41Sopenharmony_ci */ 911cb0ef41Sopenharmony_ciares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char byte); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci/*! Append a null-terminated string to the dynamic buffer object 941cb0ef41Sopenharmony_ci * 951cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 961cb0ef41Sopenharmony_ci * \param[in] str String to append to buffer object. 971cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 981cb0ef41Sopenharmony_ci */ 991cb0ef41Sopenharmony_ciares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci/*! Append a 16bit Big Endian number to the buffer. 1021cb0ef41Sopenharmony_ci * 1031cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 1041cb0ef41Sopenharmony_ci * \param[out] u16 16bit integer 1051cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 1061cb0ef41Sopenharmony_ci */ 1071cb0ef41Sopenharmony_ciares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16); 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci/*! Append a 32bit Big Endian number to the buffer. 1101cb0ef41Sopenharmony_ci * 1111cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 1121cb0ef41Sopenharmony_ci * \param[out] u32 32bit integer 1131cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 1141cb0ef41Sopenharmony_ci */ 1151cb0ef41Sopenharmony_ciares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci/*! Append a number in ASCII decimal form. 1181cb0ef41Sopenharmony_ci * 1191cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 1201cb0ef41Sopenharmony_ci * \param[in] num Number to print 1211cb0ef41Sopenharmony_ci * \param[in] len Length to output, use 0 for no padding 1221cb0ef41Sopenharmony_ci * \return ARES_SUCCESS on success 1231cb0ef41Sopenharmony_ci */ 1241cb0ef41Sopenharmony_ciares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, 1251cb0ef41Sopenharmony_ci size_t len); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci/*! Append a number in ASCII hexadecimal form. 1281cb0ef41Sopenharmony_ci * 1291cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 1301cb0ef41Sopenharmony_ci * \param[in] num Number to print 1311cb0ef41Sopenharmony_ci * \param[in] len Length to output, use 0 for no padding 1321cb0ef41Sopenharmony_ci * \return ARES_SUCCESS on success 1331cb0ef41Sopenharmony_ci */ 1341cb0ef41Sopenharmony_ciares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num, 1351cb0ef41Sopenharmony_ci size_t len); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci/*! Sets the current buffer length. This *may* be used if there is a need to 1381cb0ef41Sopenharmony_ci * override a prior position in the buffer, such as if there is a length 1391cb0ef41Sopenharmony_ci * prefix that isn't easily predictable, and you must go back and overwrite 1401cb0ef41Sopenharmony_ci * that position. 1411cb0ef41Sopenharmony_ci * 1421cb0ef41Sopenharmony_ci * Only valid on non-const buffers. Length provided must not exceed current 1431cb0ef41Sopenharmony_ci * allocated buffer size, but otherwise there are very few protections on 1441cb0ef41Sopenharmony_ci * this function. Use cautiously. 1451cb0ef41Sopenharmony_ci * 1461cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 1471cb0ef41Sopenharmony_ci * \param[in] len Length to set 1481cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 1491cb0ef41Sopenharmony_ci */ 1501cb0ef41Sopenharmony_ciares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci/*! Start a dynamic append operation that returns a buffer suitable for 1541cb0ef41Sopenharmony_ci * writing. A desired minimum length is passed in, and the actual allocated 1551cb0ef41Sopenharmony_ci * buffer size is returned which may be greater than the requested size. 1561cb0ef41Sopenharmony_ci * No operation other than ares__buf_append_finish() is allowed on the 1571cb0ef41Sopenharmony_ci * buffer after this request. 1581cb0ef41Sopenharmony_ci * 1591cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 1601cb0ef41Sopenharmony_ci * \param[in,out] len Desired non-zero length passed in, actual buffer size 1611cb0ef41Sopenharmony_ci * returned. 1621cb0ef41Sopenharmony_ci * \return Pointer to writable buffer or NULL on failure (usage, out of mem) 1631cb0ef41Sopenharmony_ci */ 1641cb0ef41Sopenharmony_ciunsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len); 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci/*! Finish a dynamic append operation. Called after 1671cb0ef41Sopenharmony_ci * ares__buf_append_start() once desired data is written. 1681cb0ef41Sopenharmony_ci * 1691cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object. 1701cb0ef41Sopenharmony_ci * \param[in] len Length of data written. May be zero to terminate 1711cb0ef41Sopenharmony_ci * operation. Must not be greater than returned from 1721cb0ef41Sopenharmony_ci * ares__buf_append_start(). 1731cb0ef41Sopenharmony_ci */ 1741cb0ef41Sopenharmony_civoid ares__buf_append_finish(ares__buf_t *buf, size_t len); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci/*! Write the data provided to the buffer in a hexdump format. 1771cb0ef41Sopenharmony_ci * 1781cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object. 1791cb0ef41Sopenharmony_ci * \param[in] data Data to hex dump 1801cb0ef41Sopenharmony_ci * \param[in] data_len Length of data to hexdump 1811cb0ef41Sopenharmony_ci * \return ARES_SUCCESS on success. 1821cb0ef41Sopenharmony_ci */ 1831cb0ef41Sopenharmony_ciares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, 1841cb0ef41Sopenharmony_ci size_t len); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci/*! Clean up ares__buf_t and return allocated pointer to unprocessed data. It 1871cb0ef41Sopenharmony_ci * is the responsibility of the caller to ares_free() the returned buffer. 1881cb0ef41Sopenharmony_ci * The passed in buf parameter is invalidated by this call. 1891cb0ef41Sopenharmony_ci * 1901cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object. Can not be a "const" buffer. 1911cb0ef41Sopenharmony_ci * \param[out] len Length of data returned 1921cb0ef41Sopenharmony_ci * \return pointer to unprocessed data (may be zero length) or NULL on error. 1931cb0ef41Sopenharmony_ci */ 1941cb0ef41Sopenharmony_ciunsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci/*! Clean up ares__buf_t and return allocated pointer to unprocessed data and 1971cb0ef41Sopenharmony_ci * return it as a string (null terminated). It is the responsibility of the 1981cb0ef41Sopenharmony_ci * caller to ares_free() the returned buffer. The passed in buf parameter is 1991cb0ef41Sopenharmony_ci * invalidated by this call. 2001cb0ef41Sopenharmony_ci * 2011cb0ef41Sopenharmony_ci * This function in no way validates the data in this buffer is actually 2021cb0ef41Sopenharmony_ci * a string, that characters are printable, or that there aren't multiple 2031cb0ef41Sopenharmony_ci * NULL terminators. It is assumed that the caller will either validate that 2041cb0ef41Sopenharmony_ci * themselves or has built this buffer with only a valid character set. 2051cb0ef41Sopenharmony_ci * 2061cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object. Can not be a "const" buffer. 2071cb0ef41Sopenharmony_ci * \param[out] len Optional. Length of data returned, or NULL if not needed. 2081cb0ef41Sopenharmony_ci * \return pointer to unprocessed data or NULL on error. 2091cb0ef41Sopenharmony_ci */ 2101cb0ef41Sopenharmony_cichar *ares__buf_finish_str(ares__buf_t *buf, size_t *len); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci/*! Tag a position to save in the buffer in case parsing needs to rollback, 2131cb0ef41Sopenharmony_ci * such as if insufficient data is available, but more data may be added in 2141cb0ef41Sopenharmony_ci * the future. Only a single tag can be set per buffer object. Setting a 2151cb0ef41Sopenharmony_ci * tag will override any pre-existing tag. 2161cb0ef41Sopenharmony_ci * 2171cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2181cb0ef41Sopenharmony_ci */ 2191cb0ef41Sopenharmony_civoid ares__buf_tag(ares__buf_t *buf); 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci/*! Rollback to a tagged position. Will automatically clear the tag. 2221cb0ef41Sopenharmony_ci * 2231cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2241cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 2251cb0ef41Sopenharmony_ci */ 2261cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_rollback(ares__buf_t *buf); 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci/*! Clear the tagged position without rolling back. You should do this any 2291cb0ef41Sopenharmony_ci * time a tag is no longer needed as future append operations can reclaim 2301cb0ef41Sopenharmony_ci * buffer space. 2311cb0ef41Sopenharmony_ci * 2321cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2331cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 2341cb0ef41Sopenharmony_ci */ 2351cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_clear(ares__buf_t *buf); 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci/*! Fetch the buffer and length of data starting from the tagged position up 2381cb0ef41Sopenharmony_ci * to the _current_ position. It will not unset the tagged position. The 2391cb0ef41Sopenharmony_ci * data may be invalidated by any future ares__buf_*() calls. 2401cb0ef41Sopenharmony_ci * 2411cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2421cb0ef41Sopenharmony_ci * \param[out] len Length between tag and current offset in buffer 2431cb0ef41Sopenharmony_ci * \return NULL on failure (such as no tag), otherwise pointer to start of 2441cb0ef41Sopenharmony_ci * buffer 2451cb0ef41Sopenharmony_ci */ 2461cb0ef41Sopenharmony_ciconst unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf, size_t *len); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci/*! Get the length of the current tag offset to the current position. 2491cb0ef41Sopenharmony_ci * 2501cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2511cb0ef41Sopenharmony_ci * \return length 2521cb0ef41Sopenharmony_ci */ 2531cb0ef41Sopenharmony_cisize_t ares__buf_tag_length(const ares__buf_t *buf); 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci/*! Fetch the bytes starting from the tagged position up to the _current_ 2561cb0ef41Sopenharmony_ci * position using the provided buffer. It will not unset the tagged position. 2571cb0ef41Sopenharmony_ci * 2581cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2591cb0ef41Sopenharmony_ci * \param[in,out] bytes Buffer to hold data 2601cb0ef41Sopenharmony_ci * \param[in,out] len On input, buffer size, on output, bytes place in 2611cb0ef41Sopenharmony_ci * buffer. 2621cb0ef41Sopenharmony_ci * \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size 2631cb0ef41Sopenharmony_ci */ 2641cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf, 2651cb0ef41Sopenharmony_ci unsigned char *bytes, size_t *len); 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci/*! Fetch the bytes starting from the tagged position up to the _current_ 2681cb0ef41Sopenharmony_ci * position as a NULL-terminated string using the provided buffer. The data 2691cb0ef41Sopenharmony_ci * is validated to be ASCII-printable data. It will not unset the tagged 2701cb0ef41Sopenharmony_ci * poition. 2711cb0ef41Sopenharmony_ci * 2721cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2731cb0ef41Sopenharmony_ci * \param[in,out] str Buffer to hold data 2741cb0ef41Sopenharmony_ci * \param[in] len On input, buffer size, on output, bytes place in 2751cb0ef41Sopenharmony_ci * buffer. 2761cb0ef41Sopenharmony_ci * \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size, 2771cb0ef41Sopenharmony_ci * ARES_EBADSTR if not printable ASCII 2781cb0ef41Sopenharmony_ci */ 2791cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str, 2801cb0ef41Sopenharmony_ci size_t len); 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci/*! Consume the given number of bytes without reading them. 2831cb0ef41Sopenharmony_ci * 2841cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2851cb0ef41Sopenharmony_ci * \param[in] len Length to consume 2861cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 2871cb0ef41Sopenharmony_ci */ 2881cb0ef41Sopenharmony_ciares_status_t ares__buf_consume(ares__buf_t *buf, size_t len); 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci/*! Fetch a 16bit Big Endian number from the buffer. 2911cb0ef41Sopenharmony_ci * 2921cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 2931cb0ef41Sopenharmony_ci * \param[out] u16 Buffer to hold 16bit integer 2941cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 2951cb0ef41Sopenharmony_ci */ 2961cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16); 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci/*! Fetch a 32bit Big Endian number from the buffer. 2991cb0ef41Sopenharmony_ci * 3001cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3011cb0ef41Sopenharmony_ci * \param[out] u32 Buffer to hold 32bit integer 3021cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 3031cb0ef41Sopenharmony_ci */ 3041cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32); 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes into the provided buffer 3081cb0ef41Sopenharmony_ci * 3091cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3101cb0ef41Sopenharmony_ci * \param[out] bytes Buffer to hold data 3111cb0ef41Sopenharmony_ci * \param[in] len Requested number of bytes (must be > 0) 3121cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 3131cb0ef41Sopenharmony_ci */ 3141cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, unsigned char *bytes, 3151cb0ef41Sopenharmony_ci size_t len); 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes and return a new buffer that must be 3191cb0ef41Sopenharmony_ci * ares_free()'d by the caller. 3201cb0ef41Sopenharmony_ci * 3211cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3221cb0ef41Sopenharmony_ci * \param[in] len Requested number of bytes (must be > 0) 3231cb0ef41Sopenharmony_ci * \param[in] null_term Even though this is considered binary data, the user 3241cb0ef41Sopenharmony_ci * knows it may be a vald string, so add a null 3251cb0ef41Sopenharmony_ci * terminator. 3261cb0ef41Sopenharmony_ci * \param[out] bytes Pointer passed by reference. Will be allocated. 3271cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 3281cb0ef41Sopenharmony_ci */ 3291cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, size_t len, 3301cb0ef41Sopenharmony_ci ares_bool_t null_term, 3311cb0ef41Sopenharmony_ci unsigned char **bytes); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes and place them into the provided 3341cb0ef41Sopenharmony_ci * dest buffer object. 3351cb0ef41Sopenharmony_ci * 3361cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3371cb0ef41Sopenharmony_ci * \param[out] dest Buffer object to append bytes. 3381cb0ef41Sopenharmony_ci * \param[in] len Requested number of bytes (must be > 0) 3391cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 3401cb0ef41Sopenharmony_ci */ 3411cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, 3421cb0ef41Sopenharmony_ci ares__buf_t *dest, size_t len); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes and return a new buffer that must be 3451cb0ef41Sopenharmony_ci * ares_free()'d by the caller. The returned buffer is a null terminated 3461cb0ef41Sopenharmony_ci * string. 3471cb0ef41Sopenharmony_ci * 3481cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3491cb0ef41Sopenharmony_ci * \param[in] len Requested number of bytes (must be > 0) 3501cb0ef41Sopenharmony_ci * \param[out] str Pointer passed by reference. Will be allocated. 3511cb0ef41Sopenharmony_ci * \return ARES_SUCCESS or one of the c-ares error codes 3521cb0ef41Sopenharmony_ci */ 3531cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str); 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci/*! Consume whitespace characters (0x09, 0x0B, 0x0C, 0x0D, 0x20, and optionally 3561cb0ef41Sopenharmony_ci * 0x0A). 3571cb0ef41Sopenharmony_ci * 3581cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3591cb0ef41Sopenharmony_ci * \param[in] include_linefeed ARES_TRUE to include consuming 0x0A, 3601cb0ef41Sopenharmony_ci * ARES_FALSE otherwise. 3611cb0ef41Sopenharmony_ci * \return number of whitespace characters consumed 3621cb0ef41Sopenharmony_ci */ 3631cb0ef41Sopenharmony_cisize_t ares__buf_consume_whitespace(ares__buf_t *buf, 3641cb0ef41Sopenharmony_ci ares_bool_t include_linefeed); 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci/*! Consume any non-whitespace character (anything other than 0x09, 0x0B, 0x0C, 3681cb0ef41Sopenharmony_ci * 0x0D, 0x20, and 0x0A). 3691cb0ef41Sopenharmony_ci * 3701cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3711cb0ef41Sopenharmony_ci * \return number of characters consumed 3721cb0ef41Sopenharmony_ci */ 3731cb0ef41Sopenharmony_cisize_t ares__buf_consume_nonwhitespace(ares__buf_t *buf); 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci/*! Consume until a character in the character set provided is reached 3771cb0ef41Sopenharmony_ci * 3781cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3791cb0ef41Sopenharmony_ci * \param[in] charset character set 3801cb0ef41Sopenharmony_ci * \param[in] len length of character set 3811cb0ef41Sopenharmony_ci * \param[in] require_charset require we find a character from the charset. 3821cb0ef41Sopenharmony_ci * if ARES_FALSE it will simply consume the 3831cb0ef41Sopenharmony_ci * rest of the buffer. If ARES_TRUE will return 3841cb0ef41Sopenharmony_ci * 0 if not found. 3851cb0ef41Sopenharmony_ci * \return number of characters consumed 3861cb0ef41Sopenharmony_ci */ 3871cb0ef41Sopenharmony_cisize_t ares__buf_consume_until_charset(ares__buf_t *buf, 3881cb0ef41Sopenharmony_ci const unsigned char *charset, size_t len, 3891cb0ef41Sopenharmony_ci ares_bool_t require_charset); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci/*! Consume while the characters match the characters in the provided set. 3931cb0ef41Sopenharmony_ci * 3941cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 3951cb0ef41Sopenharmony_ci * \param[in] charset character set 3961cb0ef41Sopenharmony_ci * \param[in] len length of character set 3971cb0ef41Sopenharmony_ci * \return number of characters consumed 3981cb0ef41Sopenharmony_ci */ 3991cb0ef41Sopenharmony_cisize_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset, 4001cb0ef41Sopenharmony_ci size_t len); 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci/*! Consume from the current position until the end of the line, and optionally 4041cb0ef41Sopenharmony_ci * the end of line character (0x0A) itself. 4051cb0ef41Sopenharmony_ci * 4061cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 4071cb0ef41Sopenharmony_ci * \param[in] include_linefeed ARES_TRUE to include consuming 0x0A, 4081cb0ef41Sopenharmony_ci * ARES_FALSE otherwise. 4091cb0ef41Sopenharmony_ci * \return number of characters consumed 4101cb0ef41Sopenharmony_ci */ 4111cb0ef41Sopenharmony_cisize_t ares__buf_consume_line(ares__buf_t *buf, ares_bool_t include_linefeed); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_citypedef enum { 4141cb0ef41Sopenharmony_ci /*! No flags */ 4151cb0ef41Sopenharmony_ci ARES_BUF_SPLIT_NONE = 0, 4161cb0ef41Sopenharmony_ci /*! The delimiter will be the first character in the buffer, except the 4171cb0ef41Sopenharmony_ci * first buffer since the start doesn't have a delimiter 4181cb0ef41Sopenharmony_ci */ 4191cb0ef41Sopenharmony_ci ARES_BUF_SPLIT_DONT_CONSUME_DELIMS = 1 << 0, 4201cb0ef41Sopenharmony_ci /*! Allow blank sections, by default blank sections are not emitted. If using 4211cb0ef41Sopenharmony_ci * ARES_BUF_SPLIT_DONT_CONSUME_DELIMS, the delimiter is not counted as part 4221cb0ef41Sopenharmony_ci * of the section */ 4231cb0ef41Sopenharmony_ci ARES_BUF_SPLIT_ALLOW_BLANK = 1 << 1, 4241cb0ef41Sopenharmony_ci /*! Remove duplicate entries */ 4251cb0ef41Sopenharmony_ci ARES_BUF_SPLIT_NO_DUPLICATES = 1 << 2, 4261cb0ef41Sopenharmony_ci /*! Perform case-insensitive matching when comparing values */ 4271cb0ef41Sopenharmony_ci ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3 4281cb0ef41Sopenharmony_ci} ares__buf_split_t; 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci/*! Split the provided buffer into multiple sub-buffers stored in the variable 4311cb0ef41Sopenharmony_ci * pointed to by the linked list. The sub buffers are const buffers pointing 4321cb0ef41Sopenharmony_ci * into the buf provided. 4331cb0ef41Sopenharmony_ci * 4341cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 4351cb0ef41Sopenharmony_ci * \param[in] delims Possible delimiters 4361cb0ef41Sopenharmony_ci * \param[in] delims_len Length of possible delimiters 4371cb0ef41Sopenharmony_ci * \param[in] flags One more more flags 4381cb0ef41Sopenharmony_ci * \param[out] list Result. Depending on flags, this may be a 4391cb0ef41Sopenharmony_ci * valid list with no elements. Use 4401cb0ef41Sopenharmony_ci * ares__llist_destroy() to free the memory which 4411cb0ef41Sopenharmony_ci * will also free the contained ares__buf_t 4421cb0ef41Sopenharmony_ci * objects. 4431cb0ef41Sopenharmony_ci * \return ARES_SUCCESS on success, or error like ARES_ENOMEM. 4441cb0ef41Sopenharmony_ci */ 4451cb0ef41Sopenharmony_ciares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, 4461cb0ef41Sopenharmony_ci size_t delims_len, ares__buf_split_t flags, 4471cb0ef41Sopenharmony_ci ares__llist_t **list); 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci/*! Check the unprocessed buffer to see if it begins with the sequence of 4511cb0ef41Sopenharmony_ci * characters provided. 4521cb0ef41Sopenharmony_ci * 4531cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 4541cb0ef41Sopenharmony_ci * \param[in] data Bytes of data to compare. 4551cb0ef41Sopenharmony_ci * \param[in] data_len Length of data to compare. 4561cb0ef41Sopenharmony_ci * \return ARES_TRUE on match, ARES_FALSE otherwise. 4571cb0ef41Sopenharmony_ci */ 4581cb0ef41Sopenharmony_ciares_bool_t ares__buf_begins_with(const ares__buf_t *buf, 4591cb0ef41Sopenharmony_ci const unsigned char *data, size_t data_len); 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci/*! Size of unprocessed remaining data length 4631cb0ef41Sopenharmony_ci * 4641cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 4651cb0ef41Sopenharmony_ci * \return length remaining 4661cb0ef41Sopenharmony_ci */ 4671cb0ef41Sopenharmony_cisize_t ares__buf_len(const ares__buf_t *buf); 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci/*! Retrieve a pointer to the currently unprocessed data. Generally this isn't 4701cb0ef41Sopenharmony_ci * recommended to be used in practice. The returned pointer may be invalidated 4711cb0ef41Sopenharmony_ci * by any future ares__buf_*() calls. 4721cb0ef41Sopenharmony_ci * 4731cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 4741cb0ef41Sopenharmony_ci * \param[out] len Length of available data 4751cb0ef41Sopenharmony_ci * \return Pointer to buffer of unprocessed data 4761cb0ef41Sopenharmony_ci */ 4771cb0ef41Sopenharmony_ciconst unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len); 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci/*! Wipe any processed data from the beginning of the buffer. This will 4811cb0ef41Sopenharmony_ci * move any remaining data to the front of the internally allocated buffer. 4821cb0ef41Sopenharmony_ci * 4831cb0ef41Sopenharmony_ci * Can not be used on const buffer objects. 4841cb0ef41Sopenharmony_ci * 4851cb0ef41Sopenharmony_ci * Typically not needed to call, as any new append operation will automatically 4861cb0ef41Sopenharmony_ci * call this function if there is insufficient space to append the data in 4871cb0ef41Sopenharmony_ci * order to try to avoid another memory allocation. 4881cb0ef41Sopenharmony_ci * 4891cb0ef41Sopenharmony_ci * It may be useful to call in order to ensure the current message being 4901cb0ef41Sopenharmony_ci * processed is in the beginning of the buffer if there is an intent to use 4911cb0ef41Sopenharmony_ci * ares__buf_set_position() and ares__buf_get_position() as may be necessary 4921cb0ef41Sopenharmony_ci * when processing DNS compressed names. 4931cb0ef41Sopenharmony_ci * 4941cb0ef41Sopenharmony_ci * If there is an active tag, it will NOT clear the tag, it will use the tag 4951cb0ef41Sopenharmony_ci * as the start of the unprocessed data rather than the current offset. If 4961cb0ef41Sopenharmony_ci * a prior tag is no longer needed, may be wise to call ares__buf_tag_clear(). 4971cb0ef41Sopenharmony_ci * 4981cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 4991cb0ef41Sopenharmony_ci */ 5001cb0ef41Sopenharmony_civoid ares__buf_reclaim(ares__buf_t *buf); 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ci/*! Set the current offset within the internal buffer. 5031cb0ef41Sopenharmony_ci * 5041cb0ef41Sopenharmony_ci * Typically this should not be used, if possible, use the ares__buf_tag*() 5051cb0ef41Sopenharmony_ci * operations instead. 5061cb0ef41Sopenharmony_ci * 5071cb0ef41Sopenharmony_ci * One exception is DNS name compression which may backwards reference to 5081cb0ef41Sopenharmony_ci * an index in the message. It may be necessary in such a case to call 5091cb0ef41Sopenharmony_ci * ares__buf_reclaim() if using a dynamic (non-const) buffer before processing 5101cb0ef41Sopenharmony_ci * such a message. 5111cb0ef41Sopenharmony_ci * 5121cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 5131cb0ef41Sopenharmony_ci * \param[in] idx Index to set position 5141cb0ef41Sopenharmony_ci * \return ARES_SUCCESS if valid index 5151cb0ef41Sopenharmony_ci */ 5161cb0ef41Sopenharmony_ciares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx); 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci/*! Get the current offset within the internal buffer. 5191cb0ef41Sopenharmony_ci * 5201cb0ef41Sopenharmony_ci * Typically this should not be used, if possible, use the ares__buf_tag*() 5211cb0ef41Sopenharmony_ci * operations instead. 5221cb0ef41Sopenharmony_ci * 5231cb0ef41Sopenharmony_ci * This can be used to get the current position, useful for saving if a 5241cb0ef41Sopenharmony_ci * jump via ares__buf_set_position() is performed and need to restore the 5251cb0ef41Sopenharmony_ci * current position for future operations. 5261cb0ef41Sopenharmony_ci * 5271cb0ef41Sopenharmony_ci * \param[in] buf Initialized buffer object 5281cb0ef41Sopenharmony_ci * \return index of current position 5291cb0ef41Sopenharmony_ci */ 5301cb0ef41Sopenharmony_cisize_t ares__buf_get_position(const ares__buf_t *buf); 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ci/*! Parse a character-string as defined in RFC1035, as a null-terminated 5331cb0ef41Sopenharmony_ci * string. 5341cb0ef41Sopenharmony_ci * 5351cb0ef41Sopenharmony_ci * \param[in] buf initialized buffer object 5361cb0ef41Sopenharmony_ci * \param[in] remaining_len maximum length that should be used for parsing 5371cb0ef41Sopenharmony_ci * the string, this is often less than the remaining 5381cb0ef41Sopenharmony_ci * buffer and is based on the RR record length. 5391cb0ef41Sopenharmony_ci * \param[out] str Pointer passed by reference to be filled in with 5401cb0ef41Sopenharmony_ci * allocated string of the parsed that must be 5411cb0ef41Sopenharmony_ci * ares_free()'d by the caller. 5421cb0ef41Sopenharmony_ci * \param[in] allow_multiple ARES_TRUE if it should attempt to parse multiple 5431cb0ef41Sopenharmony_ci * strings back to back, and will concatenate in 5441cb0ef41Sopenharmony_ci * the returned str. 5451cb0ef41Sopenharmony_ci * \return ARES_SUCCESS on success 5461cb0ef41Sopenharmony_ci */ 5471cb0ef41Sopenharmony_ciares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len, 5481cb0ef41Sopenharmony_ci char **name, ares_bool_t allow_multiple); 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci/*! Parse a character-string as defined in RFC1035, as binary, however for 5511cb0ef41Sopenharmony_ci * convenience this does guarantee a NULL terminator (that is not included 5521cb0ef41Sopenharmony_ci * in the returned length). 5531cb0ef41Sopenharmony_ci * 5541cb0ef41Sopenharmony_ci * \param[in] buf initialized buffer object 5551cb0ef41Sopenharmony_ci * \param[in] remaining_len maximum length that should be used for parsing 5561cb0ef41Sopenharmony_ci * the string, this is often less than the remaining 5571cb0ef41Sopenharmony_ci * buffer and is based on the RR record length. 5581cb0ef41Sopenharmony_ci * \param[out] bin Pointer passed by reference to be filled in with 5591cb0ef41Sopenharmony_ci * allocated string of the parsed that must be 5601cb0ef41Sopenharmony_ci * ares_free()'d by the caller. 5611cb0ef41Sopenharmony_ci * \param[out] bin_len Length of returned string. 5621cb0ef41Sopenharmony_ci * \param[in] allow_multiple ARES_TRUE if it should attempt to parse multiple 5631cb0ef41Sopenharmony_ci * strings back to back, and will concatenate in 5641cb0ef41Sopenharmony_ci * the returned str. 5651cb0ef41Sopenharmony_ci * \return ARES_SUCCESS on success 5661cb0ef41Sopenharmony_ci */ 5671cb0ef41Sopenharmony_ciares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, 5681cb0ef41Sopenharmony_ci unsigned char **bin, size_t *bin_len, 5691cb0ef41Sopenharmony_ci ares_bool_t allow_multiple); 5701cb0ef41Sopenharmony_ci/*! @} */ 5711cb0ef41Sopenharmony_ci 5721cb0ef41Sopenharmony_ci#endif /* __ARES__BUF_H */ 573