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#include "ares_setup.h" 271cb0ef41Sopenharmony_ci#include "ares.h" 281cb0ef41Sopenharmony_ci#include "ares_private.h" 291cb0ef41Sopenharmony_ci#include "ares__buf.h" 301cb0ef41Sopenharmony_ci#include <limits.h> 311cb0ef41Sopenharmony_ci#ifdef HAVE_STDINT_H 321cb0ef41Sopenharmony_ci# include <stdint.h> 331cb0ef41Sopenharmony_ci#endif 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cistruct ares__buf { 361cb0ef41Sopenharmony_ci const unsigned char *data; /*!< pointer to start of data buffer */ 371cb0ef41Sopenharmony_ci size_t data_len; /*!< total size of data in buffer */ 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci unsigned char *alloc_buf; /*!< Pointer to allocated data buffer, 401cb0ef41Sopenharmony_ci * not used for const buffers */ 411cb0ef41Sopenharmony_ci size_t alloc_buf_len; /*!< Size of allocated data buffer */ 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci size_t offset; /*!< Current working offset in buffer */ 441cb0ef41Sopenharmony_ci size_t tag_offset; /*!< Tagged offset in buffer. Uses 451cb0ef41Sopenharmony_ci * SIZE_MAX if not set. */ 461cb0ef41Sopenharmony_ci}; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ciares_bool_t ares__isprint(int ch) 491cb0ef41Sopenharmony_ci{ 501cb0ef41Sopenharmony_ci if (ch >= 0x20 && ch <= 0x7E) { 511cb0ef41Sopenharmony_ci return ARES_TRUE; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci return ARES_FALSE; 541cb0ef41Sopenharmony_ci} 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci/* Character set allowed by hostnames. This is to include the normal 571cb0ef41Sopenharmony_ci * domain name character set plus: 581cb0ef41Sopenharmony_ci * - underscores which are used in SRV records. 591cb0ef41Sopenharmony_ci * - Forward slashes such as are used for classless in-addr.arpa 601cb0ef41Sopenharmony_ci * delegation (CNAMEs) 611cb0ef41Sopenharmony_ci * - Asterisks may be used for wildcard domains in CNAMEs as seen in the 621cb0ef41Sopenharmony_ci * real world. 631cb0ef41Sopenharmony_ci * While RFC 2181 section 11 does state not to do validation, 641cb0ef41Sopenharmony_ci * that applies to servers, not clients. Vulnerabilities have been 651cb0ef41Sopenharmony_ci * reported when this validation is not performed. Security is more 661cb0ef41Sopenharmony_ci * important than edge-case compatibility (which is probably invalid 671cb0ef41Sopenharmony_ci * anyhow). */ 681cb0ef41Sopenharmony_ciares_bool_t ares__is_hostnamech(int ch) 691cb0ef41Sopenharmony_ci{ 701cb0ef41Sopenharmony_ci /* [A-Za-z0-9-*._/] 711cb0ef41Sopenharmony_ci * Don't use isalnum() as it is locale-specific 721cb0ef41Sopenharmony_ci */ 731cb0ef41Sopenharmony_ci if (ch >= 'A' && ch <= 'Z') { 741cb0ef41Sopenharmony_ci return ARES_TRUE; 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci if (ch >= 'a' && ch <= 'z') { 771cb0ef41Sopenharmony_ci return ARES_TRUE; 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci if (ch >= '0' && ch <= '9') { 801cb0ef41Sopenharmony_ci return ARES_TRUE; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*') { 831cb0ef41Sopenharmony_ci return ARES_TRUE; 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci return ARES_FALSE; 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciares__buf_t *ares__buf_create(void) 901cb0ef41Sopenharmony_ci{ 911cb0ef41Sopenharmony_ci ares__buf_t *buf = ares_malloc_zero(sizeof(*buf)); 921cb0ef41Sopenharmony_ci if (buf == NULL) { 931cb0ef41Sopenharmony_ci return NULL; 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci buf->tag_offset = SIZE_MAX; 971cb0ef41Sopenharmony_ci return buf; 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ciares__buf_t *ares__buf_create_const(const unsigned char *data, size_t data_len) 1011cb0ef41Sopenharmony_ci{ 1021cb0ef41Sopenharmony_ci ares__buf_t *buf; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci if (data == NULL || data_len == 0) { 1051cb0ef41Sopenharmony_ci return NULL; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci buf = ares__buf_create(); 1091cb0ef41Sopenharmony_ci if (buf == NULL) { 1101cb0ef41Sopenharmony_ci return NULL; 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci buf->data = data; 1141cb0ef41Sopenharmony_ci buf->data_len = data_len; 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci return buf; 1171cb0ef41Sopenharmony_ci} 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_civoid ares__buf_destroy(ares__buf_t *buf) 1201cb0ef41Sopenharmony_ci{ 1211cb0ef41Sopenharmony_ci if (buf == NULL) { 1221cb0ef41Sopenharmony_ci return; 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci ares_free(buf->alloc_buf); 1251cb0ef41Sopenharmony_ci ares_free(buf); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_cistatic ares_bool_t ares__buf_is_const(const ares__buf_t *buf) 1291cb0ef41Sopenharmony_ci{ 1301cb0ef41Sopenharmony_ci if (buf == NULL) { 1311cb0ef41Sopenharmony_ci return ARES_FALSE; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci if (buf->data != NULL && buf->alloc_buf == NULL) { 1351cb0ef41Sopenharmony_ci return ARES_TRUE; 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci return ARES_FALSE; 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_civoid ares__buf_reclaim(ares__buf_t *buf) 1421cb0ef41Sopenharmony_ci{ 1431cb0ef41Sopenharmony_ci size_t prefix_size; 1441cb0ef41Sopenharmony_ci size_t data_size; 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci if (buf == NULL) { 1471cb0ef41Sopenharmony_ci return; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci if (ares__buf_is_const(buf)) { 1511cb0ef41Sopenharmony_ci return; 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci /* Silence coverity. All lengths are zero so would bail out later but 1551cb0ef41Sopenharmony_ci * coverity doesn't know this */ 1561cb0ef41Sopenharmony_ci if (buf->alloc_buf == NULL) { 1571cb0ef41Sopenharmony_ci return; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci if (buf->tag_offset != SIZE_MAX && buf->tag_offset < buf->offset) { 1611cb0ef41Sopenharmony_ci prefix_size = buf->tag_offset; 1621cb0ef41Sopenharmony_ci } else { 1631cb0ef41Sopenharmony_ci prefix_size = buf->offset; 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci if (prefix_size == 0) { 1671cb0ef41Sopenharmony_ci return; 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci data_size = buf->data_len - prefix_size; 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci memmove(buf->alloc_buf, buf->alloc_buf + prefix_size, data_size); 1731cb0ef41Sopenharmony_ci buf->data = buf->alloc_buf; 1741cb0ef41Sopenharmony_ci buf->data_len = data_size; 1751cb0ef41Sopenharmony_ci buf->offset -= prefix_size; 1761cb0ef41Sopenharmony_ci if (buf->tag_offset != SIZE_MAX) { 1771cb0ef41Sopenharmony_ci buf->tag_offset -= prefix_size; 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci return; 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_cistatic ares_status_t ares__buf_ensure_space(ares__buf_t *buf, 1841cb0ef41Sopenharmony_ci size_t needed_size) 1851cb0ef41Sopenharmony_ci{ 1861cb0ef41Sopenharmony_ci size_t remaining_size; 1871cb0ef41Sopenharmony_ci size_t alloc_size; 1881cb0ef41Sopenharmony_ci unsigned char *ptr; 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci if (buf == NULL) { 1911cb0ef41Sopenharmony_ci return ARES_EFORMERR; 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci if (ares__buf_is_const(buf)) { 1951cb0ef41Sopenharmony_ci return ARES_EFORMERR; 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci /* When calling ares__buf_finish_str() we end up adding a null terminator, 1991cb0ef41Sopenharmony_ci * so we want to ensure the size is always sufficient for this as we don't 2001cb0ef41Sopenharmony_ci * want an ARES_ENOMEM at that point */ 2011cb0ef41Sopenharmony_ci needed_size++; 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci /* No need to do an expensive move operation, we have enough to just append */ 2041cb0ef41Sopenharmony_ci remaining_size = buf->alloc_buf_len - buf->data_len; 2051cb0ef41Sopenharmony_ci if (remaining_size >= needed_size) { 2061cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2071cb0ef41Sopenharmony_ci } 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci /* See if just moving consumed data frees up enough space */ 2101cb0ef41Sopenharmony_ci ares__buf_reclaim(buf); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci remaining_size = buf->alloc_buf_len - buf->data_len; 2131cb0ef41Sopenharmony_ci if (remaining_size >= needed_size) { 2141cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci alloc_size = buf->alloc_buf_len; 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci /* Not yet started */ 2201cb0ef41Sopenharmony_ci if (alloc_size == 0) { 2211cb0ef41Sopenharmony_ci alloc_size = 16; /* Always shifts 1, so ends up being 32 minimum */ 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci /* Increase allocation by powers of 2 */ 2251cb0ef41Sopenharmony_ci do { 2261cb0ef41Sopenharmony_ci alloc_size <<= 1; 2271cb0ef41Sopenharmony_ci remaining_size = alloc_size - buf->data_len; 2281cb0ef41Sopenharmony_ci } while (remaining_size < needed_size); 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci ptr = ares_realloc(buf->alloc_buf, alloc_size); 2311cb0ef41Sopenharmony_ci if (ptr == NULL) { 2321cb0ef41Sopenharmony_ci return ARES_ENOMEM; 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci buf->alloc_buf = ptr; 2361cb0ef41Sopenharmony_ci buf->alloc_buf_len = alloc_size; 2371cb0ef41Sopenharmony_ci buf->data = ptr; 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2401cb0ef41Sopenharmony_ci} 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ciares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len) 2431cb0ef41Sopenharmony_ci{ 2441cb0ef41Sopenharmony_ci if (buf == NULL || ares__buf_is_const(buf)) { 2451cb0ef41Sopenharmony_ci return ARES_EFORMERR; 2461cb0ef41Sopenharmony_ci } 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci if (len >= buf->alloc_buf_len - buf->offset) { 2491cb0ef41Sopenharmony_ci return ARES_EFORMERR; 2501cb0ef41Sopenharmony_ci } 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci buf->data_len = len; 2531cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2541cb0ef41Sopenharmony_ci} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ciares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data, 2571cb0ef41Sopenharmony_ci size_t data_len) 2581cb0ef41Sopenharmony_ci{ 2591cb0ef41Sopenharmony_ci ares_status_t status; 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci if (data == NULL || data_len == 0) { 2621cb0ef41Sopenharmony_ci return ARES_EFORMERR; 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci status = ares__buf_ensure_space(buf, data_len); 2661cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2671cb0ef41Sopenharmony_ci return status; 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci memcpy(buf->alloc_buf + buf->data_len, data, data_len); 2711cb0ef41Sopenharmony_ci buf->data_len += data_len; 2721cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2731cb0ef41Sopenharmony_ci} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ciares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char byte) 2761cb0ef41Sopenharmony_ci{ 2771cb0ef41Sopenharmony_ci return ares__buf_append(buf, &byte, 1); 2781cb0ef41Sopenharmony_ci} 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ciares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16) 2811cb0ef41Sopenharmony_ci{ 2821cb0ef41Sopenharmony_ci ares_status_t status; 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, (unsigned char)((u16 >> 8) & 0xff)); 2851cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2861cb0ef41Sopenharmony_ci return status; 2871cb0ef41Sopenharmony_ci } 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, (unsigned char)(u16 & 0xff)); 2901cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2911cb0ef41Sopenharmony_ci return status; 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2951cb0ef41Sopenharmony_ci} 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ciares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32) 2981cb0ef41Sopenharmony_ci{ 2991cb0ef41Sopenharmony_ci ares_status_t status; 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, ((unsigned char)(u32 >> 24) & 0xff)); 3021cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3031cb0ef41Sopenharmony_ci return status; 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, ((unsigned char)(u32 >> 16) & 0xff)); 3071cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3081cb0ef41Sopenharmony_ci return status; 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, ((unsigned char)(u32 >> 8) & 0xff)); 3121cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3131cb0ef41Sopenharmony_ci return status; 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, ((unsigned char)u32 & 0xff)); 3171cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3181cb0ef41Sopenharmony_ci return status; 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3221cb0ef41Sopenharmony_ci} 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ciunsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len) 3251cb0ef41Sopenharmony_ci{ 3261cb0ef41Sopenharmony_ci ares_status_t status; 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci if (len == NULL || *len == 0) { 3291cb0ef41Sopenharmony_ci return NULL; 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci status = ares__buf_ensure_space(buf, *len); 3331cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3341cb0ef41Sopenharmony_ci return NULL; 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci /* -1 for possible null terminator for ares__buf_finish_str() */ 3381cb0ef41Sopenharmony_ci *len = buf->alloc_buf_len - buf->data_len - 1; 3391cb0ef41Sopenharmony_ci return buf->alloc_buf + buf->data_len; 3401cb0ef41Sopenharmony_ci} 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_civoid ares__buf_append_finish(ares__buf_t *buf, size_t len) 3431cb0ef41Sopenharmony_ci{ 3441cb0ef41Sopenharmony_ci if (buf == NULL) { 3451cb0ef41Sopenharmony_ci return; 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci buf->data_len += len; 3491cb0ef41Sopenharmony_ci} 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ciunsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len) 3521cb0ef41Sopenharmony_ci{ 3531cb0ef41Sopenharmony_ci unsigned char *ptr = NULL; 3541cb0ef41Sopenharmony_ci if (buf == NULL || len == NULL || ares__buf_is_const(buf)) { 3551cb0ef41Sopenharmony_ci return NULL; 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci ares__buf_reclaim(buf); 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci /* We don't want to return NULL except on failure, may be zero-length */ 3611cb0ef41Sopenharmony_ci if (buf->alloc_buf == NULL && 3621cb0ef41Sopenharmony_ci ares__buf_ensure_space(buf, 1) != ARES_SUCCESS) { 3631cb0ef41Sopenharmony_ci return NULL; 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci ptr = buf->alloc_buf; 3661cb0ef41Sopenharmony_ci *len = buf->data_len; 3671cb0ef41Sopenharmony_ci ares_free(buf); 3681cb0ef41Sopenharmony_ci return ptr; 3691cb0ef41Sopenharmony_ci} 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_cichar *ares__buf_finish_str(ares__buf_t *buf, size_t *len) 3721cb0ef41Sopenharmony_ci{ 3731cb0ef41Sopenharmony_ci char *ptr; 3741cb0ef41Sopenharmony_ci size_t mylen; 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci ptr = (char *)ares__buf_finish_bin(buf, &mylen); 3771cb0ef41Sopenharmony_ci if (ptr == NULL) { 3781cb0ef41Sopenharmony_ci return NULL; 3791cb0ef41Sopenharmony_ci } 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci if (len != NULL) { 3821cb0ef41Sopenharmony_ci *len = mylen; 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci /* NOTE: ensured via ares__buf_ensure_space() that there is always at least 3861cb0ef41Sopenharmony_ci * 1 extra byte available for this specific use-case */ 3871cb0ef41Sopenharmony_ci ptr[mylen] = 0; 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci return ptr; 3901cb0ef41Sopenharmony_ci} 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_civoid ares__buf_tag(ares__buf_t *buf) 3931cb0ef41Sopenharmony_ci{ 3941cb0ef41Sopenharmony_ci if (buf == NULL) { 3951cb0ef41Sopenharmony_ci return; 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci buf->tag_offset = buf->offset; 3991cb0ef41Sopenharmony_ci} 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_rollback(ares__buf_t *buf) 4021cb0ef41Sopenharmony_ci{ 4031cb0ef41Sopenharmony_ci if (buf == NULL || buf->tag_offset == SIZE_MAX) { 4041cb0ef41Sopenharmony_ci return ARES_EFORMERR; 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci buf->offset = buf->tag_offset; 4081cb0ef41Sopenharmony_ci buf->tag_offset = SIZE_MAX; 4091cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_clear(ares__buf_t *buf) 4131cb0ef41Sopenharmony_ci{ 4141cb0ef41Sopenharmony_ci if (buf == NULL || buf->tag_offset == SIZE_MAX) { 4151cb0ef41Sopenharmony_ci return ARES_EFORMERR; 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci buf->tag_offset = SIZE_MAX; 4191cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4201cb0ef41Sopenharmony_ci} 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ciconst unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf, size_t *len) 4231cb0ef41Sopenharmony_ci{ 4241cb0ef41Sopenharmony_ci if (buf == NULL || buf->tag_offset == SIZE_MAX || len == NULL) { 4251cb0ef41Sopenharmony_ci return NULL; 4261cb0ef41Sopenharmony_ci } 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci *len = buf->offset - buf->tag_offset; 4291cb0ef41Sopenharmony_ci return buf->data + buf->tag_offset; 4301cb0ef41Sopenharmony_ci} 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_cisize_t ares__buf_tag_length(const ares__buf_t *buf) 4331cb0ef41Sopenharmony_ci{ 4341cb0ef41Sopenharmony_ci if (buf == NULL || buf->tag_offset == SIZE_MAX) { 4351cb0ef41Sopenharmony_ci return 0; 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci return buf->offset - buf->tag_offset; 4381cb0ef41Sopenharmony_ci} 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf, 4411cb0ef41Sopenharmony_ci unsigned char *bytes, size_t *len) 4421cb0ef41Sopenharmony_ci{ 4431cb0ef41Sopenharmony_ci size_t ptr_len = 0; 4441cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_tag_fetch(buf, &ptr_len); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci if (ptr == NULL || bytes == NULL || len == NULL) { 4471cb0ef41Sopenharmony_ci return ARES_EFORMERR; 4481cb0ef41Sopenharmony_ci } 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci if (*len < ptr_len) { 4511cb0ef41Sopenharmony_ci return ARES_EFORMERR; 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci *len = ptr_len; 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci if (ptr_len > 0) { 4571cb0ef41Sopenharmony_ci memcpy(bytes, ptr, ptr_len); 4581cb0ef41Sopenharmony_ci } 4591cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4601cb0ef41Sopenharmony_ci} 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str, 4631cb0ef41Sopenharmony_ci size_t len) 4641cb0ef41Sopenharmony_ci{ 4651cb0ef41Sopenharmony_ci size_t out_len; 4661cb0ef41Sopenharmony_ci ares_status_t status; 4671cb0ef41Sopenharmony_ci size_t i; 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci if (str == NULL || len == 0) { 4701cb0ef41Sopenharmony_ci return ARES_EFORMERR; 4711cb0ef41Sopenharmony_ci } 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci /* Space for NULL terminator */ 4741cb0ef41Sopenharmony_ci out_len = len - 1; 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci status = ares__buf_tag_fetch_bytes(buf, (unsigned char *)str, &out_len); 4771cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4781cb0ef41Sopenharmony_ci return status; 4791cb0ef41Sopenharmony_ci } 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ci /* NULL terminate */ 4821cb0ef41Sopenharmony_ci str[out_len] = 0; 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci /* Validate string is printable */ 4851cb0ef41Sopenharmony_ci for (i = 0; i < out_len; i++) { 4861cb0ef41Sopenharmony_ci if (!ares__isprint(str[i])) { 4871cb0ef41Sopenharmony_ci return ARES_EBADSTR; 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4921cb0ef41Sopenharmony_ci} 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_cistatic const unsigned char *ares__buf_fetch(const ares__buf_t *buf, size_t *len) 4951cb0ef41Sopenharmony_ci{ 4961cb0ef41Sopenharmony_ci if (len != NULL) { 4971cb0ef41Sopenharmony_ci *len = 0; 4981cb0ef41Sopenharmony_ci } 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci if (buf == NULL || len == NULL || buf->data == NULL) { 5011cb0ef41Sopenharmony_ci return NULL; 5021cb0ef41Sopenharmony_ci } 5031cb0ef41Sopenharmony_ci 5041cb0ef41Sopenharmony_ci *len = buf->data_len - buf->offset; 5051cb0ef41Sopenharmony_ci if (*len == 0) { 5061cb0ef41Sopenharmony_ci return NULL; 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci return buf->data + buf->offset; 5101cb0ef41Sopenharmony_ci} 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ciares_status_t ares__buf_consume(ares__buf_t *buf, size_t len) 5131cb0ef41Sopenharmony_ci{ 5141cb0ef41Sopenharmony_ci size_t remaining_len = ares__buf_len(buf); 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci if (remaining_len < len) { 5171cb0ef41Sopenharmony_ci return ARES_EBADRESP; 5181cb0ef41Sopenharmony_ci } 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ci buf->offset += len; 5211cb0ef41Sopenharmony_ci return ARES_SUCCESS; 5221cb0ef41Sopenharmony_ci} 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16) 5251cb0ef41Sopenharmony_ci{ 5261cb0ef41Sopenharmony_ci size_t remaining_len; 5271cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 5281cb0ef41Sopenharmony_ci unsigned int u32; 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ci if (buf == NULL || u16 == NULL || remaining_len < sizeof(*u16)) { 5311cb0ef41Sopenharmony_ci return ARES_EBADRESP; 5321cb0ef41Sopenharmony_ci } 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci /* Do math in an unsigned int in order to prevent warnings due to automatic 5351cb0ef41Sopenharmony_ci * conversion by the compiler from short to int during shifts */ 5361cb0ef41Sopenharmony_ci u32 = ((unsigned int)(ptr[0]) << 8 | (unsigned int)ptr[1]); 5371cb0ef41Sopenharmony_ci *u16 = (unsigned short)(u32 & 0xFFFF); 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci return ares__buf_consume(buf, sizeof(*u16)); 5401cb0ef41Sopenharmony_ci} 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32) 5431cb0ef41Sopenharmony_ci{ 5441cb0ef41Sopenharmony_ci size_t remaining_len; 5451cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci if (buf == NULL || u32 == NULL || remaining_len < sizeof(*u32)) { 5481cb0ef41Sopenharmony_ci return ARES_EBADRESP; 5491cb0ef41Sopenharmony_ci } 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci *u32 = ((unsigned int)(ptr[0]) << 24 | (unsigned int)(ptr[1]) << 16 | 5521cb0ef41Sopenharmony_ci (unsigned int)(ptr[2]) << 8 | (unsigned int)(ptr[3])); 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ci return ares__buf_consume(buf, sizeof(*u32)); 5551cb0ef41Sopenharmony_ci} 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, unsigned char *bytes, 5581cb0ef41Sopenharmony_ci size_t len) 5591cb0ef41Sopenharmony_ci{ 5601cb0ef41Sopenharmony_ci size_t remaining_len; 5611cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci if (buf == NULL || bytes == NULL || len == 0 || remaining_len < len) { 5641cb0ef41Sopenharmony_ci return ARES_EBADRESP; 5651cb0ef41Sopenharmony_ci } 5661cb0ef41Sopenharmony_ci 5671cb0ef41Sopenharmony_ci memcpy(bytes, ptr, len); 5681cb0ef41Sopenharmony_ci return ares__buf_consume(buf, len); 5691cb0ef41Sopenharmony_ci} 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, size_t len, 5721cb0ef41Sopenharmony_ci ares_bool_t null_term, 5731cb0ef41Sopenharmony_ci unsigned char **bytes) 5741cb0ef41Sopenharmony_ci{ 5751cb0ef41Sopenharmony_ci size_t remaining_len; 5761cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ci if (buf == NULL || bytes == NULL || len == 0 || remaining_len < len) { 5791cb0ef41Sopenharmony_ci return ARES_EBADRESP; 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci *bytes = ares_malloc(null_term ? len + 1 : len); 5831cb0ef41Sopenharmony_ci if (*bytes == NULL) { 5841cb0ef41Sopenharmony_ci return ARES_ENOMEM; 5851cb0ef41Sopenharmony_ci } 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci memcpy(*bytes, ptr, len); 5881cb0ef41Sopenharmony_ci if (null_term) { 5891cb0ef41Sopenharmony_ci (*bytes)[len] = 0; 5901cb0ef41Sopenharmony_ci } 5911cb0ef41Sopenharmony_ci return ares__buf_consume(buf, len); 5921cb0ef41Sopenharmony_ci} 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str) 5951cb0ef41Sopenharmony_ci{ 5961cb0ef41Sopenharmony_ci size_t remaining_len; 5971cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 5981cb0ef41Sopenharmony_ci 5991cb0ef41Sopenharmony_ci if (buf == NULL || str == NULL || len == 0 || remaining_len < len) { 6001cb0ef41Sopenharmony_ci return ARES_EBADRESP; 6011cb0ef41Sopenharmony_ci } 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci *str = ares_malloc(len + 1); 6041cb0ef41Sopenharmony_ci if (*str == NULL) { 6051cb0ef41Sopenharmony_ci return ARES_ENOMEM; 6061cb0ef41Sopenharmony_ci } 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci memcpy(*str, ptr, len); 6091cb0ef41Sopenharmony_ci (*str)[len] = 0; 6101cb0ef41Sopenharmony_ci 6111cb0ef41Sopenharmony_ci return ares__buf_consume(buf, len); 6121cb0ef41Sopenharmony_ci} 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, 6151cb0ef41Sopenharmony_ci ares__buf_t *dest, size_t len) 6161cb0ef41Sopenharmony_ci{ 6171cb0ef41Sopenharmony_ci size_t remaining_len; 6181cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 6191cb0ef41Sopenharmony_ci ares_status_t status; 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_ci if (buf == NULL || dest == NULL || len == 0 || remaining_len < len) { 6221cb0ef41Sopenharmony_ci return ARES_EBADRESP; 6231cb0ef41Sopenharmony_ci } 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci status = ares__buf_append(dest, ptr, len); 6261cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6271cb0ef41Sopenharmony_ci return status; 6281cb0ef41Sopenharmony_ci } 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci return ares__buf_consume(buf, len); 6311cb0ef41Sopenharmony_ci} 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_cisize_t ares__buf_consume_whitespace(ares__buf_t *buf, 6341cb0ef41Sopenharmony_ci ares_bool_t include_linefeed) 6351cb0ef41Sopenharmony_ci{ 6361cb0ef41Sopenharmony_ci size_t remaining_len = 0; 6371cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 6381cb0ef41Sopenharmony_ci size_t i; 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ci if (ptr == NULL) { 6411cb0ef41Sopenharmony_ci return 0; 6421cb0ef41Sopenharmony_ci } 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci for (i = 0; i < remaining_len; i++) { 6451cb0ef41Sopenharmony_ci switch (ptr[i]) { 6461cb0ef41Sopenharmony_ci case '\r': 6471cb0ef41Sopenharmony_ci case '\t': 6481cb0ef41Sopenharmony_ci case ' ': 6491cb0ef41Sopenharmony_ci case '\v': 6501cb0ef41Sopenharmony_ci case '\f': 6511cb0ef41Sopenharmony_ci break; 6521cb0ef41Sopenharmony_ci case '\n': 6531cb0ef41Sopenharmony_ci if (!include_linefeed) { 6541cb0ef41Sopenharmony_ci goto done; 6551cb0ef41Sopenharmony_ci } 6561cb0ef41Sopenharmony_ci break; 6571cb0ef41Sopenharmony_ci default: 6581cb0ef41Sopenharmony_ci goto done; 6591cb0ef41Sopenharmony_ci } 6601cb0ef41Sopenharmony_ci } 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_cidone: 6631cb0ef41Sopenharmony_ci if (i > 0) { 6641cb0ef41Sopenharmony_ci ares__buf_consume(buf, i); 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci return i; 6671cb0ef41Sopenharmony_ci} 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_cisize_t ares__buf_consume_nonwhitespace(ares__buf_t *buf) 6701cb0ef41Sopenharmony_ci{ 6711cb0ef41Sopenharmony_ci size_t remaining_len = 0; 6721cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 6731cb0ef41Sopenharmony_ci size_t i; 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_ci if (ptr == NULL) { 6761cb0ef41Sopenharmony_ci return 0; 6771cb0ef41Sopenharmony_ci } 6781cb0ef41Sopenharmony_ci 6791cb0ef41Sopenharmony_ci for (i = 0; i < remaining_len; i++) { 6801cb0ef41Sopenharmony_ci switch (ptr[i]) { 6811cb0ef41Sopenharmony_ci case '\r': 6821cb0ef41Sopenharmony_ci case '\t': 6831cb0ef41Sopenharmony_ci case ' ': 6841cb0ef41Sopenharmony_ci case '\v': 6851cb0ef41Sopenharmony_ci case '\f': 6861cb0ef41Sopenharmony_ci case '\n': 6871cb0ef41Sopenharmony_ci goto done; 6881cb0ef41Sopenharmony_ci default: 6891cb0ef41Sopenharmony_ci break; 6901cb0ef41Sopenharmony_ci } 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci 6931cb0ef41Sopenharmony_cidone: 6941cb0ef41Sopenharmony_ci if (i > 0) { 6951cb0ef41Sopenharmony_ci ares__buf_consume(buf, i); 6961cb0ef41Sopenharmony_ci } 6971cb0ef41Sopenharmony_ci return i; 6981cb0ef41Sopenharmony_ci} 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_cisize_t ares__buf_consume_line(ares__buf_t *buf, ares_bool_t include_linefeed) 7011cb0ef41Sopenharmony_ci{ 7021cb0ef41Sopenharmony_ci size_t remaining_len = 0; 7031cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 7041cb0ef41Sopenharmony_ci size_t i; 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_ci if (ptr == NULL) { 7071cb0ef41Sopenharmony_ci return 0; 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci for (i = 0; i < remaining_len; i++) { 7111cb0ef41Sopenharmony_ci if (ptr[i] == '\n') { 7121cb0ef41Sopenharmony_ci goto done; 7131cb0ef41Sopenharmony_ci } 7141cb0ef41Sopenharmony_ci } 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_cidone: 7171cb0ef41Sopenharmony_ci if (include_linefeed && i < remaining_len && ptr[i] == '\n') { 7181cb0ef41Sopenharmony_ci i++; 7191cb0ef41Sopenharmony_ci } 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci if (i > 0) { 7221cb0ef41Sopenharmony_ci ares__buf_consume(buf, i); 7231cb0ef41Sopenharmony_ci } 7241cb0ef41Sopenharmony_ci return i; 7251cb0ef41Sopenharmony_ci} 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_cisize_t ares__buf_consume_until_charset(ares__buf_t *buf, 7281cb0ef41Sopenharmony_ci const unsigned char *charset, size_t len, 7291cb0ef41Sopenharmony_ci ares_bool_t require_charset) 7301cb0ef41Sopenharmony_ci{ 7311cb0ef41Sopenharmony_ci size_t remaining_len = 0; 7321cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 7331cb0ef41Sopenharmony_ci size_t i; 7341cb0ef41Sopenharmony_ci ares_bool_t found = ARES_FALSE; 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ci if (ptr == NULL || charset == NULL || len == 0) { 7371cb0ef41Sopenharmony_ci return 0; 7381cb0ef41Sopenharmony_ci } 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_ci for (i = 0; i < remaining_len; i++) { 7411cb0ef41Sopenharmony_ci size_t j; 7421cb0ef41Sopenharmony_ci for (j = 0; j < len; j++) { 7431cb0ef41Sopenharmony_ci if (ptr[i] == charset[j]) { 7441cb0ef41Sopenharmony_ci found = ARES_TRUE; 7451cb0ef41Sopenharmony_ci goto done; 7461cb0ef41Sopenharmony_ci } 7471cb0ef41Sopenharmony_ci } 7481cb0ef41Sopenharmony_ci } 7491cb0ef41Sopenharmony_ci 7501cb0ef41Sopenharmony_cidone: 7511cb0ef41Sopenharmony_ci if (require_charset && !found) { 7521cb0ef41Sopenharmony_ci return 0; 7531cb0ef41Sopenharmony_ci } 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_ci if (i > 0) { 7561cb0ef41Sopenharmony_ci ares__buf_consume(buf, i); 7571cb0ef41Sopenharmony_ci } 7581cb0ef41Sopenharmony_ci return i; 7591cb0ef41Sopenharmony_ci} 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_cisize_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset, 7621cb0ef41Sopenharmony_ci size_t len) 7631cb0ef41Sopenharmony_ci{ 7641cb0ef41Sopenharmony_ci size_t remaining_len = 0; 7651cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 7661cb0ef41Sopenharmony_ci size_t i; 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_ci if (ptr == NULL || charset == NULL || len == 0) { 7691cb0ef41Sopenharmony_ci return 0; 7701cb0ef41Sopenharmony_ci } 7711cb0ef41Sopenharmony_ci 7721cb0ef41Sopenharmony_ci for (i = 0; i < remaining_len; i++) { 7731cb0ef41Sopenharmony_ci size_t j; 7741cb0ef41Sopenharmony_ci for (j = 0; j < len; j++) { 7751cb0ef41Sopenharmony_ci if (ptr[i] == charset[j]) { 7761cb0ef41Sopenharmony_ci break; 7771cb0ef41Sopenharmony_ci } 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci /* Not found */ 7801cb0ef41Sopenharmony_ci if (j == len) { 7811cb0ef41Sopenharmony_ci break; 7821cb0ef41Sopenharmony_ci } 7831cb0ef41Sopenharmony_ci } 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_ci if (i > 0) { 7861cb0ef41Sopenharmony_ci ares__buf_consume(buf, i); 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci return i; 7891cb0ef41Sopenharmony_ci} 7901cb0ef41Sopenharmony_ci 7911cb0ef41Sopenharmony_cistatic void ares__buf_destroy_cb(void *arg) 7921cb0ef41Sopenharmony_ci{ 7931cb0ef41Sopenharmony_ci ares__buf_destroy(arg); 7941cb0ef41Sopenharmony_ci} 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_cistatic ares_bool_t ares__buf_split_isduplicate(ares__llist_t *list, 7971cb0ef41Sopenharmony_ci const unsigned char *val, 7981cb0ef41Sopenharmony_ci size_t len, 7991cb0ef41Sopenharmony_ci ares__buf_split_t flags) 8001cb0ef41Sopenharmony_ci{ 8011cb0ef41Sopenharmony_ci ares__llist_node_t *node; 8021cb0ef41Sopenharmony_ci 8031cb0ef41Sopenharmony_ci for (node = ares__llist_node_first(list); node != NULL; 8041cb0ef41Sopenharmony_ci node = ares__llist_node_next(node)) { 8051cb0ef41Sopenharmony_ci const ares__buf_t *buf = ares__llist_node_val(node); 8061cb0ef41Sopenharmony_ci size_t plen = 0; 8071cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_peek(buf, &plen); 8081cb0ef41Sopenharmony_ci 8091cb0ef41Sopenharmony_ci /* Can't be duplicate if lengths mismatch */ 8101cb0ef41Sopenharmony_ci if (plen != len) { 8111cb0ef41Sopenharmony_ci continue; 8121cb0ef41Sopenharmony_ci } 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci if (flags & ARES_BUF_SPLIT_CASE_INSENSITIVE) { 8151cb0ef41Sopenharmony_ci if (ares__memeq_ci(ptr, val, len)) { 8161cb0ef41Sopenharmony_ci return ARES_TRUE; 8171cb0ef41Sopenharmony_ci } 8181cb0ef41Sopenharmony_ci } else { 8191cb0ef41Sopenharmony_ci if (memcmp(ptr, val, len) == 0) { 8201cb0ef41Sopenharmony_ci return ARES_TRUE; 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci } 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci return ARES_FALSE; 8251cb0ef41Sopenharmony_ci} 8261cb0ef41Sopenharmony_ci 8271cb0ef41Sopenharmony_ciares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, 8281cb0ef41Sopenharmony_ci size_t delims_len, ares__buf_split_t flags, 8291cb0ef41Sopenharmony_ci ares__llist_t **list) 8301cb0ef41Sopenharmony_ci{ 8311cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 8321cb0ef41Sopenharmony_ci ares_bool_t first = ARES_TRUE; 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci if (buf == NULL || delims == NULL || delims_len == 0 || list == NULL) { 8351cb0ef41Sopenharmony_ci return ARES_EFORMERR; 8361cb0ef41Sopenharmony_ci } 8371cb0ef41Sopenharmony_ci 8381cb0ef41Sopenharmony_ci *list = ares__llist_create(ares__buf_destroy_cb); 8391cb0ef41Sopenharmony_ci if (*list == NULL) { 8401cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 8411cb0ef41Sopenharmony_ci goto done; 8421cb0ef41Sopenharmony_ci } 8431cb0ef41Sopenharmony_ci 8441cb0ef41Sopenharmony_ci while (ares__buf_len(buf)) { 8451cb0ef41Sopenharmony_ci size_t len; 8461cb0ef41Sopenharmony_ci 8471cb0ef41Sopenharmony_ci ares__buf_tag(buf); 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_ci len = ares__buf_consume_until_charset(buf, delims, delims_len, ARES_FALSE); 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci /* Don't treat a delimiter as part of the length */ 8521cb0ef41Sopenharmony_ci if (!first && len && flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) { 8531cb0ef41Sopenharmony_ci len--; 8541cb0ef41Sopenharmony_ci } 8551cb0ef41Sopenharmony_ci 8561cb0ef41Sopenharmony_ci if (len != 0 || flags & ARES_BUF_SPLIT_ALLOW_BLANK) { 8571cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_tag_fetch(buf, &len); 8581cb0ef41Sopenharmony_ci ares__buf_t *data; 8591cb0ef41Sopenharmony_ci 8601cb0ef41Sopenharmony_ci if (!(flags & ARES_BUF_SPLIT_NO_DUPLICATES) || 8611cb0ef41Sopenharmony_ci !ares__buf_split_isduplicate(*list, ptr, len, flags)) { 8621cb0ef41Sopenharmony_ci /* Since we don't allow const buffers of 0 length, and user wants 8631cb0ef41Sopenharmony_ci * 0-length buffers, swap what we do here */ 8641cb0ef41Sopenharmony_ci if (len) { 8651cb0ef41Sopenharmony_ci data = ares__buf_create_const(ptr, len); 8661cb0ef41Sopenharmony_ci } else { 8671cb0ef41Sopenharmony_ci data = ares__buf_create(); 8681cb0ef41Sopenharmony_ci } 8691cb0ef41Sopenharmony_ci 8701cb0ef41Sopenharmony_ci if (data == NULL) { 8711cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 8721cb0ef41Sopenharmony_ci goto done; 8731cb0ef41Sopenharmony_ci } 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_ci if (ares__llist_insert_last(*list, data) == NULL) { 8761cb0ef41Sopenharmony_ci ares__buf_destroy(data); 8771cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 8781cb0ef41Sopenharmony_ci goto done; 8791cb0ef41Sopenharmony_ci } 8801cb0ef41Sopenharmony_ci } 8811cb0ef41Sopenharmony_ci } 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ci if (!(flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) && 8841cb0ef41Sopenharmony_ci ares__buf_len(buf) != 0) { 8851cb0ef41Sopenharmony_ci /* Consume delimiter */ 8861cb0ef41Sopenharmony_ci ares__buf_consume(buf, 1); 8871cb0ef41Sopenharmony_ci } 8881cb0ef41Sopenharmony_ci 8891cb0ef41Sopenharmony_ci first = ARES_FALSE; 8901cb0ef41Sopenharmony_ci } 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_cidone: 8931cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8941cb0ef41Sopenharmony_ci ares__llist_destroy(*list); 8951cb0ef41Sopenharmony_ci *list = NULL; 8961cb0ef41Sopenharmony_ci } 8971cb0ef41Sopenharmony_ci 8981cb0ef41Sopenharmony_ci return status; 8991cb0ef41Sopenharmony_ci} 9001cb0ef41Sopenharmony_ci 9011cb0ef41Sopenharmony_ciares_bool_t ares__buf_begins_with(const ares__buf_t *buf, 9021cb0ef41Sopenharmony_ci const unsigned char *data, size_t data_len) 9031cb0ef41Sopenharmony_ci{ 9041cb0ef41Sopenharmony_ci size_t remaining_len = 0; 9051cb0ef41Sopenharmony_ci const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len); 9061cb0ef41Sopenharmony_ci 9071cb0ef41Sopenharmony_ci if (ptr == NULL || data == NULL || data_len == 0) { 9081cb0ef41Sopenharmony_ci return ARES_FALSE; 9091cb0ef41Sopenharmony_ci } 9101cb0ef41Sopenharmony_ci 9111cb0ef41Sopenharmony_ci if (data_len > remaining_len) { 9121cb0ef41Sopenharmony_ci return ARES_FALSE; 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_ci if (memcmp(ptr, data, data_len) != 0) { 9161cb0ef41Sopenharmony_ci return ARES_FALSE; 9171cb0ef41Sopenharmony_ci } 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_ci return ARES_TRUE; 9201cb0ef41Sopenharmony_ci} 9211cb0ef41Sopenharmony_ci 9221cb0ef41Sopenharmony_cisize_t ares__buf_len(const ares__buf_t *buf) 9231cb0ef41Sopenharmony_ci{ 9241cb0ef41Sopenharmony_ci if (buf == NULL) { 9251cb0ef41Sopenharmony_ci return 0; 9261cb0ef41Sopenharmony_ci } 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci return buf->data_len - buf->offset; 9291cb0ef41Sopenharmony_ci} 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ciconst unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len) 9321cb0ef41Sopenharmony_ci{ 9331cb0ef41Sopenharmony_ci return ares__buf_fetch(buf, len); 9341cb0ef41Sopenharmony_ci} 9351cb0ef41Sopenharmony_ci 9361cb0ef41Sopenharmony_cisize_t ares__buf_get_position(const ares__buf_t *buf) 9371cb0ef41Sopenharmony_ci{ 9381cb0ef41Sopenharmony_ci if (buf == NULL) { 9391cb0ef41Sopenharmony_ci return 0; 9401cb0ef41Sopenharmony_ci } 9411cb0ef41Sopenharmony_ci return buf->offset; 9421cb0ef41Sopenharmony_ci} 9431cb0ef41Sopenharmony_ci 9441cb0ef41Sopenharmony_ciares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx) 9451cb0ef41Sopenharmony_ci{ 9461cb0ef41Sopenharmony_ci if (buf == NULL) { 9471cb0ef41Sopenharmony_ci return ARES_EFORMERR; 9481cb0ef41Sopenharmony_ci } 9491cb0ef41Sopenharmony_ci 9501cb0ef41Sopenharmony_ci if (idx > buf->data_len) { 9511cb0ef41Sopenharmony_ci return ARES_EFORMERR; 9521cb0ef41Sopenharmony_ci } 9531cb0ef41Sopenharmony_ci 9541cb0ef41Sopenharmony_ci buf->offset = idx; 9551cb0ef41Sopenharmony_ci return ARES_SUCCESS; 9561cb0ef41Sopenharmony_ci} 9571cb0ef41Sopenharmony_ci 9581cb0ef41Sopenharmony_ciares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, 9591cb0ef41Sopenharmony_ci unsigned char **bin, size_t *bin_len, 9601cb0ef41Sopenharmony_ci ares_bool_t allow_multiple) 9611cb0ef41Sopenharmony_ci{ 9621cb0ef41Sopenharmony_ci unsigned char len; 9631cb0ef41Sopenharmony_ci ares_status_t status; 9641cb0ef41Sopenharmony_ci ares__buf_t *binbuf = NULL; 9651cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 9661cb0ef41Sopenharmony_ci 9671cb0ef41Sopenharmony_ci if (buf == NULL) { 9681cb0ef41Sopenharmony_ci return ARES_EFORMERR; 9691cb0ef41Sopenharmony_ci } 9701cb0ef41Sopenharmony_ci 9711cb0ef41Sopenharmony_ci if (remaining_len == 0) { 9721cb0ef41Sopenharmony_ci return ARES_EBADRESP; 9731cb0ef41Sopenharmony_ci } 9741cb0ef41Sopenharmony_ci 9751cb0ef41Sopenharmony_ci binbuf = ares__buf_create(); 9761cb0ef41Sopenharmony_ci if (binbuf == NULL) { 9771cb0ef41Sopenharmony_ci return ARES_ENOMEM; 9781cb0ef41Sopenharmony_ci } 9791cb0ef41Sopenharmony_ci 9801cb0ef41Sopenharmony_ci while (orig_len - ares__buf_len(buf) < remaining_len) { 9811cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes(buf, &len, 1); 9821cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 9831cb0ef41Sopenharmony_ci break; 9841cb0ef41Sopenharmony_ci } 9851cb0ef41Sopenharmony_ci 9861cb0ef41Sopenharmony_ci if (len) { 9871cb0ef41Sopenharmony_ci /* XXX: Maybe we should scan to make sure it is printable? */ 9881cb0ef41Sopenharmony_ci if (bin != NULL) { 9891cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_into_buf(buf, binbuf, len); 9901cb0ef41Sopenharmony_ci } else { 9911cb0ef41Sopenharmony_ci status = ares__buf_consume(buf, len); 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 9941cb0ef41Sopenharmony_ci break; 9951cb0ef41Sopenharmony_ci } 9961cb0ef41Sopenharmony_ci } 9971cb0ef41Sopenharmony_ci 9981cb0ef41Sopenharmony_ci if (!allow_multiple) { 9991cb0ef41Sopenharmony_ci break; 10001cb0ef41Sopenharmony_ci } 10011cb0ef41Sopenharmony_ci } 10021cb0ef41Sopenharmony_ci 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10051cb0ef41Sopenharmony_ci ares__buf_destroy(binbuf); 10061cb0ef41Sopenharmony_ci } else { 10071cb0ef41Sopenharmony_ci if (bin != NULL) { 10081cb0ef41Sopenharmony_ci size_t mylen = 0; 10091cb0ef41Sopenharmony_ci /* NOTE: we use ares__buf_finish_str() here as we guarantee NULL 10101cb0ef41Sopenharmony_ci * Termination even though we are technically returning binary data. 10111cb0ef41Sopenharmony_ci */ 10121cb0ef41Sopenharmony_ci *bin = (unsigned char *)ares__buf_finish_str(binbuf, &mylen); 10131cb0ef41Sopenharmony_ci *bin_len = mylen; 10141cb0ef41Sopenharmony_ci } 10151cb0ef41Sopenharmony_ci } 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci return status; 10181cb0ef41Sopenharmony_ci} 10191cb0ef41Sopenharmony_ci 10201cb0ef41Sopenharmony_ciares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len, 10211cb0ef41Sopenharmony_ci char **str, ares_bool_t allow_multiple) 10221cb0ef41Sopenharmony_ci{ 10231cb0ef41Sopenharmony_ci size_t len; 10241cb0ef41Sopenharmony_ci return ares__buf_parse_dns_binstr(buf, remaining_len, (unsigned char **)str, 10251cb0ef41Sopenharmony_ci &len, allow_multiple); 10261cb0ef41Sopenharmony_ci} 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_ciares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, size_t len) 10291cb0ef41Sopenharmony_ci{ 10301cb0ef41Sopenharmony_ci size_t i; 10311cb0ef41Sopenharmony_ci size_t mod; 10321cb0ef41Sopenharmony_ci 10331cb0ef41Sopenharmony_ci if (len == 0) { 10341cb0ef41Sopenharmony_ci len = ares__count_digits(num); 10351cb0ef41Sopenharmony_ci } 10361cb0ef41Sopenharmony_ci 10371cb0ef41Sopenharmony_ci mod = ares__pow(10, len); 10381cb0ef41Sopenharmony_ci 10391cb0ef41Sopenharmony_ci for (i = len; i > 0; i--) { 10401cb0ef41Sopenharmony_ci size_t digit = (num % mod); 10411cb0ef41Sopenharmony_ci ares_status_t status; 10421cb0ef41Sopenharmony_ci 10431cb0ef41Sopenharmony_ci mod /= 10; 10441cb0ef41Sopenharmony_ci 10451cb0ef41Sopenharmony_ci /* Silence coverity. Shouldn't be possible since we calculate it above */ 10461cb0ef41Sopenharmony_ci if (mod == 0) { 10471cb0ef41Sopenharmony_ci return ARES_EFORMERR; 10481cb0ef41Sopenharmony_ci } 10491cb0ef41Sopenharmony_ci 10501cb0ef41Sopenharmony_ci digit /= mod; 10511cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, '0' + (unsigned char)(digit & 0xFF)); 10521cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10531cb0ef41Sopenharmony_ci return status; 10541cb0ef41Sopenharmony_ci } 10551cb0ef41Sopenharmony_ci } 10561cb0ef41Sopenharmony_ci return ARES_SUCCESS; 10571cb0ef41Sopenharmony_ci} 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ciares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num, size_t len) 10601cb0ef41Sopenharmony_ci{ 10611cb0ef41Sopenharmony_ci size_t i; 10621cb0ef41Sopenharmony_ci static const unsigned char hexbytes[] = "0123456789ABCDEF"; 10631cb0ef41Sopenharmony_ci 10641cb0ef41Sopenharmony_ci if (len == 0) { 10651cb0ef41Sopenharmony_ci len = ares__count_hexdigits(num); 10661cb0ef41Sopenharmony_ci } 10671cb0ef41Sopenharmony_ci 10681cb0ef41Sopenharmony_ci for (i = len; i > 0; i--) { 10691cb0ef41Sopenharmony_ci ares_status_t status; 10701cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, hexbytes[(num >> ((i - 1) * 4)) & 0xF]); 10711cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10721cb0ef41Sopenharmony_ci return status; 10731cb0ef41Sopenharmony_ci } 10741cb0ef41Sopenharmony_ci } 10751cb0ef41Sopenharmony_ci return ARES_SUCCESS; 10761cb0ef41Sopenharmony_ci} 10771cb0ef41Sopenharmony_ci 10781cb0ef41Sopenharmony_ciares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str) 10791cb0ef41Sopenharmony_ci{ 10801cb0ef41Sopenharmony_ci return ares__buf_append(buf, (const unsigned char *)str, ares_strlen(str)); 10811cb0ef41Sopenharmony_ci} 10821cb0ef41Sopenharmony_ci 10831cb0ef41Sopenharmony_cistatic ares_status_t ares__buf_hexdump_line(ares__buf_t *buf, size_t idx, 10841cb0ef41Sopenharmony_ci const unsigned char *data, 10851cb0ef41Sopenharmony_ci size_t len) 10861cb0ef41Sopenharmony_ci{ 10871cb0ef41Sopenharmony_ci size_t i; 10881cb0ef41Sopenharmony_ci ares_status_t status; 10891cb0ef41Sopenharmony_ci 10901cb0ef41Sopenharmony_ci /* Address */ 10911cb0ef41Sopenharmony_ci status = ares__buf_append_num_hex(buf, idx, 6); 10921cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10931cb0ef41Sopenharmony_ci return status; 10941cb0ef41Sopenharmony_ci } 10951cb0ef41Sopenharmony_ci 10961cb0ef41Sopenharmony_ci /* | */ 10971cb0ef41Sopenharmony_ci status = ares__buf_append_str(buf, " | "); 10981cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10991cb0ef41Sopenharmony_ci return status; 11001cb0ef41Sopenharmony_ci } 11011cb0ef41Sopenharmony_ci 11021cb0ef41Sopenharmony_ci for (i = 0; i < 16; i++) { 11031cb0ef41Sopenharmony_ci if (i >= len) { 11041cb0ef41Sopenharmony_ci status = ares__buf_append_str(buf, " "); 11051cb0ef41Sopenharmony_ci } else { 11061cb0ef41Sopenharmony_ci status = ares__buf_append_num_hex(buf, data[i], 2); 11071cb0ef41Sopenharmony_ci } 11081cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11091cb0ef41Sopenharmony_ci return status; 11101cb0ef41Sopenharmony_ci } 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, ' '); 11131cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11141cb0ef41Sopenharmony_ci return status; 11151cb0ef41Sopenharmony_ci } 11161cb0ef41Sopenharmony_ci } 11171cb0ef41Sopenharmony_ci 11181cb0ef41Sopenharmony_ci /* | */ 11191cb0ef41Sopenharmony_ci status = ares__buf_append_str(buf, " | "); 11201cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11211cb0ef41Sopenharmony_ci return status; 11221cb0ef41Sopenharmony_ci } 11231cb0ef41Sopenharmony_ci 11241cb0ef41Sopenharmony_ci for (i = 0; i < 16; i++) { 11251cb0ef41Sopenharmony_ci if (i >= len) { 11261cb0ef41Sopenharmony_ci break; 11271cb0ef41Sopenharmony_ci } 11281cb0ef41Sopenharmony_ci status = ares__buf_append_byte(buf, ares__isprint(data[i]) ? data[i] : '.'); 11291cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11301cb0ef41Sopenharmony_ci return status; 11311cb0ef41Sopenharmony_ci } 11321cb0ef41Sopenharmony_ci } 11331cb0ef41Sopenharmony_ci 11341cb0ef41Sopenharmony_ci return ares__buf_append_byte(buf, '\n'); 11351cb0ef41Sopenharmony_ci} 11361cb0ef41Sopenharmony_ci 11371cb0ef41Sopenharmony_ciares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, 11381cb0ef41Sopenharmony_ci size_t len) 11391cb0ef41Sopenharmony_ci{ 11401cb0ef41Sopenharmony_ci size_t i; 11411cb0ef41Sopenharmony_ci 11421cb0ef41Sopenharmony_ci /* Each line is 16 bytes */ 11431cb0ef41Sopenharmony_ci for (i = 0; i < len; i += 16) { 11441cb0ef41Sopenharmony_ci ares_status_t status; 11451cb0ef41Sopenharmony_ci status = ares__buf_hexdump_line(buf, i, data + i, len - i); 11461cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11471cb0ef41Sopenharmony_ci return status; 11481cb0ef41Sopenharmony_ci } 11491cb0ef41Sopenharmony_ci } 11501cb0ef41Sopenharmony_ci 11511cb0ef41Sopenharmony_ci return ARES_SUCCESS; 11521cb0ef41Sopenharmony_ci} 1153