From 7f19f162db429f277ea8a2bf7ed31a810ea2f730 Mon Sep 17 00:00:00 2001 From: Brad House Date: Thu, 22 Aug 2024 19:09:33 -0400 Subject: [PATCH] Expose library/utility functions to tools (#860) The tools like `adig` and `ahost` can take advantage of some of the library functions within c-ares. We can't really split these library functions into a helper library without possibly breaking users. Technically if we could guarantee they rely on pkg-config or cmake helpers we could make it work ... we can revisit that in the future, maybe if we make a c-ares 2.0 where people might expect more breakage (but I still wouldn't want to break API/ABI). So what this does is it just exports some symbols in headers that aren't distributed so end users aren't meant to use the symbols, but any utilities or tests built by c-ares can. It does clutter up some of the namespace, but all these symbols are guaranteed to be prefixed with `ares_` so there shouldn't ever be symbol clashes due to this for end users and its not so many symbols that it should affect any load times. There will be **zero** API/ABI guarantees for these symbols. They can change from release to release, this is ok since they are not public. I'm not entirely thrilled with doing this solution, but I want to avoid thing like hand-written parsers, such as is used in #856. Authored-By: Brad House (@bradh352) --- .reuse/dep5 | 2 +- Makefile.Watcom | 3 +- Makefile.dj | 2 +- Makefile.m32 | 2 +- Makefile.msvc | 11 +- src/lib/CMakeLists.txt | 2 + src/lib/Makefile.am | 3 +- src/lib/Makefile.inc | 19 +- src/lib/ares__hosts_file.c | 4 +- src/lib/ares__parse_into_addrinfo.c | 4 +- src/lib/ares_getaddrinfo.c | 4 +- src/lib/ares_library_init.c | 40 ++- src/lib/ares_platform.c | 2 +- src/lib/ares_private.h | 34 +-- src/lib/ares_process.c | 4 +- src/lib/ares_search.c | 4 +- src/lib/ares_sysconfig_files.c | 38 +-- src/lib/ares_sysconfig_mac.c | 2 +- src/lib/dsa/ares__htable_strvp.c | 9 +- src/lib/event/ares_event_configchg.c | 4 +- src/lib/include/README.md | 8 + src/lib/{dsa => include}/ares__array.h | 53 ++-- src/lib/{str => include}/ares__buf.h | 177 +++++------ src/lib/{dsa => include}/ares__htable_asvp.h | 28 +- src/lib/{dsa => include}/ares__htable_strvp.h | 24 +- src/lib/{dsa => include}/ares__htable_szvp.h | 22 +- src/lib/{dsa => include}/ares__htable_vpvp.h | 26 +- src/lib/{dsa => include}/ares__llist.h | 63 ++-- .../ares_strcasecmp.h => include/ares_mem.h} | 20 +- src/lib/include/ares_str.h | 185 ++++++++++++ src/lib/legacy/ares_parse_ptr_reply.c | 2 +- src/lib/record/ares_dns_mapping.c | 4 +- src/lib/record/ares_dns_multistring.c | 71 +++++ src/lib/record/ares_dns_multistring.h | 23 ++ src/lib/record/ares_dns_name.c | 2 +- src/lib/record/ares_dns_parse.c | 3 +- src/lib/str/ares__buf.c | 70 ----- src/lib/str/ares_str.c | 165 +++++++++++ src/lib/str/ares_str.h | 89 ------ src/lib/str/ares_strcasecmp.c | 79 ----- src/lib/util/ares__iface_ips.c | 4 +- src/tools/CMakeLists.txt | 2 + src/tools/Makefile.am | 1 + src/tools/Makefile.inc | 6 +- src/tools/adig.c | 18 +- src/tools/ahost.c | 21 +- test/CMakeLists.txt | 1 + test/Makefile.am | 13 +- test/Makefile.m32 | 2 +- test/Makefile.msvc | 2 +- test/ares-test-internal.cc | 279 +++++++++--------- 51 files changed, 920 insertions(+), 736 deletions(-) create mode 100644 src/lib/include/README.md rename src/lib/{dsa => include}/ares__array.h (79%) rename src/lib/{str => include}/ares__buf.h (77%) rename src/lib/{dsa => include}/ares__htable_asvp.h (82%) rename src/lib/{dsa => include}/ares__htable_strvp.h (82%) rename src/lib/{dsa => include}/ares__htable_szvp.h (83%) rename src/lib/{dsa => include}/ares__htable_vpvp.h (82%) rename src/lib/{dsa => include}/ares__llist.h (71%) rename src/lib/{str/ares_strcasecmp.h => include/ares_mem.h} (75%) create mode 100644 src/lib/include/ares_str.h delete mode 100644 src/lib/str/ares_str.h delete mode 100644 src/lib/str/ares_strcasecmp.c diff --git a/.reuse/dep5 b/.reuse/dep5 index 38cbdc15..57631e9a 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -9,7 +9,7 @@ Copyright: The c-ares project and its contributors. License: MIT # Docs -Files: AUTHORS CHANGES CHANGES.0 CONTRIBUTING.md GIT-INFO NEWS README.cares README.md README.msvc RELEASE-NOTES RELEASE-PROCEDURE.md SECURITY.md DEVELOPER-NOTES.md TODO INSTALL.md test/README.md test/gmock-1.11.0/README.md src/lib/thirdparty/apple/README.md +Files: AUTHORS CONTRIBUTING.md GIT-INFO README.md README.msvc RELEASE-PROCEDURE.md RELEASE-NOTES.md SECURITY.md DEVELOPER-NOTES.md INSTALL.md test/README.md src/lib/include/README.md src/lib/thirdparty/apple/README.md Copyright: The c-ares project and its contributors. License: MIT diff --git a/Makefile.Watcom b/Makefile.Watcom index 96ffedb1..2fbb1852 100644 --- a/Makefile.Watcom +++ b/Makefile.Watcom @@ -43,7 +43,8 @@ CP = copy CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm -aa & -wcd=201 -bt=nt -d+ -dCARES_BUILDING_LIBRARY & - -dNTDDI_VERSION=0x06020000 -I. -I.\include -I.\src\lib $(SYS_INCL) + -dNTDDI_VERSION=0x06020000 -I. -I.\include -I.\src\lib -I.\src\lib\include & + $(SYS_INCL) LFLAGS = option quiet, map, caseexact, eliminate diff --git a/Makefile.dj b/Makefile.dj index 69b3ca31..8dca20cb 100644 --- a/Makefile.dj +++ b/Makefile.dj @@ -23,7 +23,7 @@ VPATH = src/lib src/tools WATT32_ROOT = $(realpath $(WATT_ROOT)) WATT32_LIB = $(WATT32_ROOT)/lib/libwatt.a -CFLAGS = -g -O2 -I./include -I./src/lib \ +CFLAGS = -g -O2 -I./include -I./src/lib -I./src/lib/include \ -I$(WATT32_ROOT)/inc \ -Wall \ -Wextra \ diff --git a/Makefile.m32 b/Makefile.m32 index 36ae674c..7bd85165 100644 --- a/Makefile.m32 +++ b/Makefile.m32 @@ -19,7 +19,7 @@ RANLIB = $(CROSSPREFIX)ranlib #RM = rm -f CP = cp -afv -CFLAGS = $(CARES_CFLAG_EXTRAS) -O2 -Wall -I./include -I./src/lib -D_WIN32_WINNT=0x0602 +CFLAGS = $(CARES_CFLAG_EXTRAS) -O2 -Wall -I./include -I./src/lib -I./src/lib/include -D_WIN32_WINNT=0x0602 CFLAGS += -DCARES_STATICLIB LDFLAGS = $(CARES_LDFLAG_EXTRAS) -s LIBS = -lws2_32 -liphlpapi diff --git a/Makefile.msvc b/Makefile.msvc index 619c2d39..8395d1a7 100644 --- a/Makefile.msvc +++ b/Makefile.msvc @@ -192,7 +192,7 @@ EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2 CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /RTCsu -CC_CFLAGS = $(CFLAGS) /D_REENTRANT /I.\src\lib /I.\include /W3 /EHsc /FD +CC_CFLAGS = $(CFLAGS) /D_REENTRANT /I.\src\lib /I.\include /I.\src\lib\include /W3 /EHsc /FD RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG" RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG" @@ -344,15 +344,6 @@ PROG3_OBJS = $(PROG3_OBJS) $(PROG3_OBJDIR)\ahost.obj {$(SRCDIR)\src\tools}.c{$(PROG3_OBJDIR)}.obj: $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(PROG3_OBJDIR)\ /c $< -# Hack Alert! we reference ../lib/str files in the Makefile.inc for tools as they -# share some files with the library itself. We need to hack around that here. - -{$(SRCDIR)\src\lib\str}.c{$(PROG2_OBJDIR)\..\lib\str}.obj: - $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG2_OBJDIR)\str\$(@F) /Fd$(PROG2_OBJDIR)\str\ /c $< - -{$(SRCDIR)\src\lib\str}.c{$(PROG3_OBJDIR)\..\lib\str}.obj: - $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG3_OBJDIR)\str\$(@F) /Fd$(PROG3_OBJDIR)\str\ /c $< - # ------------------------------------------------------------- # # ------------------------------------------------------------- # # Default target when no CFG library type has been specified, # diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index ef0acf37..9956fd62 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -53,6 +53,7 @@ IF (CARES_SHARED) "$" "$" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/include" ) TARGET_COMPILE_DEFINITIONS (${PROJECT_NAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY) @@ -110,6 +111,7 @@ IF (CARES_STATIC) "$" "$" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/include" ) TARGET_COMPILE_DEFINITIONS (${LIBNAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 44e04bd3..db4f2640 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -11,7 +11,8 @@ ACLOCAL_AMFLAGS = -I m4 --install AM_CPPFLAGS += -I$(top_builddir)/include \ -I$(top_builddir)/src/lib \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib/include lib_LTLIBRARIES = libcares.la diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 8fa434c3..169c59ee 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -81,7 +81,6 @@ CSOURCES = ares__addrinfo2hostent.c \ record/ares_dns_record.c \ record/ares_dns_write.c \ str/ares__buf.c \ - str/ares_strcasecmp.c \ str/ares_str.c \ str/ares_strsplit.c \ util/ares__iface_ips.c \ @@ -98,23 +97,21 @@ HHEADERS = ares_android.h \ ares_platform.h \ ares_private.h \ ares_setup.h \ - dsa/ares__array.h \ dsa/ares__htable.h \ - dsa/ares__htable_asvp.h \ - dsa/ares__htable_strvp.h \ - dsa/ares__htable_szvp.h \ - dsa/ares__htable_vpvp.h \ - dsa/ares__llist.h \ dsa/ares__slist.h \ event/ares_event.h \ event/ares_event_win32.h \ + include/ares__array.h \ + include/ares__buf.h \ + include/ares__htable_asvp.h \ + include/ares__htable_strvp.h \ + include/ares__htable_szvp.h \ + include/ares__htable_vpvp.h \ + include/ares__llist.h \ + include/ares_str.h \ record/ares_dns_multistring.h \ record/ares_dns_private.h \ - str/ares__buf.h \ - str/ares_strcasecmp.h \ - str/ares_str.h \ str/ares_strsplit.h \ util/ares__iface_ips.h \ util/ares__threads.h \ thirdparty/apple/dnsinfo.h - diff --git a/src/lib/ares__hosts_file.c b/src/lib/ares__hosts_file.c index ae9c071d..429d96d2 100644 --- a/src/lib/ares__hosts_file.c +++ b/src/lib/ares__hosts_file.c @@ -366,7 +366,7 @@ static ares_bool_t ares__hosts_entry_isdup(ares_hosts_entry_t *entry, for (node = ares__llist_node_first(entry->ips); node != NULL; node = ares__llist_node_next(node)) { const char *myhost = ares__llist_node_val(node); - if (strcasecmp(myhost, host) == 0) { + if (ares_strcaseeq(myhost, host)) { return ARES_TRUE; } } @@ -620,7 +620,7 @@ static ares_bool_t ares__hosts_expired(const char *filename, } /* If filenames are different, its expired */ - if (strcasecmp(hf->filename, filename) != 0) { + if (!ares_strcaseeq(hf->filename, filename)) { return ARES_TRUE; } diff --git a/src/lib/ares__parse_into_addrinfo.c b/src/lib/ares__parse_into_addrinfo.c index 65c94c04..85ef5c49 100644 --- a/src/lib/ares__parse_into_addrinfo.c +++ b/src/lib/ares__parse_into_addrinfo.c @@ -90,7 +90,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec, * * rname = ares_dns_rr_get_name(rr); * if ((rtype == ARES_REC_TYPE_A || rtype == ARES_REC_TYPE_AAAA) && - * strcasecmp(rname, hostname) != 0) { + * !ares_strcaseeq(rname, hostname)) { * continue; * } */ @@ -147,7 +147,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec, } /* save the hostname as ai->name */ - if (ai->name == NULL || strcasecmp(ai->name, hostname) != 0) { + if (ai->name == NULL || !ares_strcaseeq(ai->name, hostname)) { ares_free(ai->name); ai->name = ares_strdup(hostname); if (ai->name == NULL) { diff --git a/src/lib/ares_getaddrinfo.c b/src/lib/ares_getaddrinfo.c index f67acdec..ff2d054c 100644 --- a/src/lib/ares_getaddrinfo.c +++ b/src/lib/ares_getaddrinfo.c @@ -371,7 +371,7 @@ ares_bool_t ares__is_localhost(const char *name) return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ } - if (strcmp(name, "localhost") == 0) { + if (ares_strcaseeq(name, "localhost")) { return ARES_TRUE; } @@ -380,7 +380,7 @@ ares_bool_t ares__is_localhost(const char *name) return ARES_FALSE; } - if (strcmp(name + (len - 10 /* strlen(".localhost") */), ".localhost") == 0) { + if (ares_strcaseeq(name + (len - 10 /* strlen(".localhost") */), ".localhost")) { return ARES_TRUE; } diff --git a/src/lib/ares_library_init.c b/src/lib/ares_library_init.c index 6c2f7c0f..2b91692b 100644 --- a/src/lib/ares_library_init.c +++ b/src/lib/ares_library_init.c @@ -52,8 +52,6 @@ static void *default_malloc(size_t size) return malloc(size); } -#if defined(_WIN32) -/* We need indirections to handle Windows DLL rules. */ static void *default_realloc(void *p, size_t size) { return realloc(p, size); @@ -63,13 +61,25 @@ static void default_free(void *p) { free(p); } -#else -# define default_realloc realloc -# define default_free free -#endif -void *(*ares_malloc)(size_t size) = default_malloc; -void *(*ares_realloc)(void *ptr, size_t size) = default_realloc; -void (*ares_free)(void *ptr) = default_free; + +static void *(*__ares_malloc)(size_t size) = default_malloc; +static void *(*__ares_realloc)(void *ptr, size_t size) = default_realloc; +static void (*__ares_free)(void *ptr) = default_free; + +void *ares_malloc(size_t size) +{ + return __ares_malloc(size); +} + +void *ares_realloc(void *ptr, size_t size) +{ + return __ares_realloc(ptr, size); +} + +void ares_free(void *ptr) +{ + __ares_free(ptr); +} void *ares_malloc_zero(size_t size) { @@ -115,13 +125,13 @@ int ares_library_init_mem(int flags, void *(*amalloc)(size_t size), void *(*arealloc)(void *ptr, size_t size)) { if (amalloc) { - ares_malloc = amalloc; + __ares_malloc = amalloc; } if (arealloc) { - ares_realloc = arealloc; + __ares_realloc = arealloc; } if (afree) { - ares_free = afree; + __ares_free = afree; } return ares_library_init(flags); } @@ -143,9 +153,9 @@ void ares_library_cleanup(void) #endif ares_init_flags = ARES_LIB_INIT_NONE; - ares_malloc = malloc; - ares_realloc = realloc; - ares_free = free; + __ares_malloc = default_malloc; + __ares_realloc = default_realloc; + __ares_free = default_free; } int ares_library_initialized(void) diff --git a/src/lib/ares_platform.c b/src/lib/ares_platform.c index 8f0a1dbf..f4c43f13 100644 --- a/src/lib/ares_platform.c +++ b/src/lib/ares_platform.c @@ -11032,7 +11032,7 @@ struct servent *getservbyport(int port, const char *proto) if (!error) { for (i = 0; i < (sizeof(IANAports) / sizeof(IANAports[0])) - 1; i++) { if (u_port == IANAports[i].s_port) { - if (!protocol || !strcasecmp(protocol, IANAports[i].s_proto)) { + if (!protocol || ares_strcaseeq(protocol, IANAports[i].s_proto)) { return (struct servent *)&IANAports[i]; } } diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index ecb161d7..bd84a558 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -100,20 +100,21 @@ W32_FUNC const char *_w32_GetHostsFile(void); #endif +#include "ares_mem.h" #include "ares_ipv6.h" struct ares_rand_state; typedef struct ares_rand_state ares_rand_state; -#include "dsa/ares__array.h" -#include "dsa/ares__llist.h" +#include "ares__array.h" +#include "ares__llist.h" #include "dsa/ares__slist.h" -#include "dsa/ares__htable_strvp.h" -#include "dsa/ares__htable_szvp.h" -#include "dsa/ares__htable_asvp.h" -#include "dsa/ares__htable_vpvp.h" +#include "ares__htable_strvp.h" +#include "ares__htable_szvp.h" +#include "ares__htable_asvp.h" +#include "ares__htable_vpvp.h" #include "record/ares_dns_multistring.h" -#include "str/ares__buf.h" +#include "ares__buf.h" #include "record/ares_dns_private.h" #include "util/ares__iface_ips.h" #include "util/ares__threads.h" @@ -123,19 +124,9 @@ typedef struct ares_rand_state ares_rand_state; # define getenv(ptr) ares_getenv(ptr) #endif -#include "str/ares_str.h" +#include "ares_str.h" #include "str/ares_strsplit.h" -#ifndef HAVE_STRCASECMP -# include "str/ares_strcasecmp.h" -# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2) -#endif - -#ifndef HAVE_STRNCASECMP -# include "str/ares_strcasecmp.h" -# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n) -#endif - /********* EDNS defines section ******/ #define EDNSPACKETSZ \ 1232 /* Reasonable UDP payload size, as agreed by operators \ @@ -469,13 +460,6 @@ struct ares_channeldata { /* Does the domain end in ".onion" or ".onion."? Case-insensitive. */ ares_bool_t ares__is_onion_domain(const char *name); -/* Memory management functions */ -extern void *(*ares_malloc)(size_t size); -extern void *(*ares_realloc)(void *ptr, size_t size); -extern void (*ares_free)(void *ptr); -void *ares_malloc_zero(size_t size); -void *ares_realloc_zero(void *ptr, size_t orig_size, size_t new_size); - /* return true if now is exactly check time or later */ ares_bool_t ares__timedout(const ares_timeval_t *now, const ares_timeval_t *check); diff --git a/src/lib/ares_process.c b/src/lib/ares_process.c index 1fb48bfa..a243e1b8 100644 --- a/src/lib/ares_process.c +++ b/src/lib/ares_process.c @@ -1190,12 +1190,12 @@ static ares_bool_t same_questions(const ares_query_t *query, * server to preserve the case of the name in the response packet. * https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00 */ - if (strcmp(qname, aname) != 0) { + if (!ares_streq(qname, aname)) { goto done; } } else { /* without DNS0x20 use case-insensitive matching */ - if (strcasecmp(qname, aname) != 0) { + if (!ares_strcaseeq(qname, aname)) { goto done; } } diff --git a/src/lib/ares_search.c b/src/lib/ares_search.c index ae98df39..7609550e 100644 --- a/src/lib/ares_search.c +++ b/src/lib/ares_search.c @@ -474,7 +474,7 @@ ares_status_t ares__cat_domain(const char *name, const char *domain, char **s) } memcpy(*s, name, nlen); (*s)[nlen] = '.'; - if (strcmp(domain, ".") == 0) { + if (ares_streq(domain, ".")) { /* Avoid appending the root domain to the separator, which would set *s to an ill-formed value (ending in two consecutive dots). */ dlen = 0; @@ -555,7 +555,7 @@ ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel, } /* Match hostname */ - if (strcasecmp(hostname, name) != 0) { + if (!ares_strcaseeq(hostname, name)) { continue; } diff --git a/src/lib/ares_sysconfig_files.c b/src/lib/ares_sysconfig_files.c index 7b8bdbe4..d3783fbc 100644 --- a/src/lib/ares_sysconfig_files.c +++ b/src/lib/ares_sysconfig_files.c @@ -346,12 +346,12 @@ static ares_status_t config_lookup(ares_sysconfig_t *sysconfig, continue; } - if (strcasecmp(value, "dns") == 0 || strcasecmp(value, "bind") == 0 || - strcasecmp(value, "resolv") == 0 || strcasecmp(value, "resolve") == 0) { + if (ares_strcaseeq(value, "dns") || ares_strcaseeq(value, "bind") || + ares_strcaseeq(value, "resolv") || ares_strcaseeq(value, "resolve")) { ch = 'b'; - } else if (strcasecmp(value, "files") == 0 || - strcasecmp(value, "file") == 0 || - strcasecmp(value, "local") == 0) { + } else if (ares_strcaseeq(value, "files") || + ares_strcaseeq(value, "file") || + ares_strcaseeq(value, "local")) { ch = 'f'; } else { continue; @@ -409,21 +409,21 @@ static ares_status_t process_option(ares_sysconfig_t *sysconfig, valint = (unsigned int)strtoul(val, NULL, 10); } - if (strcmp(key, "ndots") == 0) { + if (ares_streq(key, "ndots")) { sysconfig->ndots = valint; - } else if (strcmp(key, "retrans") == 0 || strcmp(key, "timeout") == 0) { + } else if (ares_streq(key, "retrans") || ares_streq(key, "timeout")) { if (valint == 0) { return ARES_EFORMERR; } sysconfig->timeout_ms = valint * 1000; - } else if (strcmp(key, "retry") == 0 || strcmp(key, "attempts") == 0) { + } else if (ares_streq(key, "retry") || ares_streq(key, "attempts")) { if (valint == 0) { return ARES_EFORMERR; } sysconfig->tries = valint; - } else if (strcmp(key, "rotate") == 0) { + } else if (ares_streq(key, "rotate")) { sysconfig->rotate = ARES_TRUE; - } else if (strcmp(key, "use-vc") == 0 || strcmp(key, "usevc") == 0) { + } else if (ares_streq(key, "use-vc") || ares_streq(key, "usevc")) { sysconfig->usevc = ARES_TRUE; } @@ -590,21 +590,21 @@ static ares_status_t parse_resolvconf_line(ares_sysconfig_t *sysconfig, /* At this point we have a string option and a string value, both trimmed * of leading and trailing whitespace. Lets try to evaluate them */ - if (strcmp(option, "domain") == 0) { + if (ares_streq(option, "domain")) { /* Domain is legacy, don't overwrite an existing config set by search */ if (sysconfig->domains == NULL) { status = config_search(sysconfig, value, 1); } - } else if (strcmp(option, "lookup") == 0 || - strcmp(option, "hostresorder") == 0) { + } else if (ares_streq(option, "lookup") || + ares_streq(option, "hostresorder")) { ares__buf_tag_rollback(line); status = config_lookup(sysconfig, line, " \t"); - } else if (strcmp(option, "search") == 0) { + } else if (ares_streq(option, "search")) { status = config_search(sysconfig, value, 0); - } else if (strcmp(option, "nameserver") == 0) { + } else if (ares_streq(option, "nameserver")) { status = ares__sconfig_append_fromstr(&sysconfig->sconfig, value, ARES_TRUE); - } else if (strcmp(option, "sortlist") == 0) { + } else if (ares_streq(option, "sortlist")) { /* Ignore all failures except ENOMEM. If the sysadmin set a bad * sortlist, just ignore the sortlist, don't cause an inoperable * channel */ @@ -613,7 +613,7 @@ static ares_status_t parse_resolvconf_line(ares_sysconfig_t *sysconfig, if (status != ARES_ENOMEM) { status = ARES_SUCCESS; } - } else if (strcmp(option, "options") == 0) { + } else if (ares_streq(option, "options")) { status = ares__sysconfig_set_options(sysconfig, value); } @@ -651,7 +651,7 @@ static ares_status_t parse_nsswitch_line(ares_sysconfig_t *sysconfig, } /* Only support "hosts:" */ - if (strcmp(option, "hosts") != 0) { + if (!ares_streq(option, "hosts")) { goto done; } @@ -698,7 +698,7 @@ static ares_status_t parse_svcconf_line(ares_sysconfig_t *sysconfig, } /* Only support "hosts=" */ - if (strcmp(option, "hosts") != 0) { + if (!ares_streq(option, "hosts")) { goto done; } diff --git a/src/lib/ares_sysconfig_mac.c b/src/lib/ares_sysconfig_mac.c index 38ac451c..19341597 100644 --- a/src/lib/ares_sysconfig_mac.c +++ b/src/lib/ares_sysconfig_mac.c @@ -154,7 +154,7 @@ static ares_bool_t search_is_duplicate(const ares_sysconfig_t *sysconfig, { size_t i; for (i = 0; i < sysconfig->ndomains; i++) { - if (strcasecmp(sysconfig->domains[i], name) == 0) { + if (ares_strcaseeq(sysconfig->domains[i], name)) { return ARES_TRUE; } } diff --git a/src/lib/dsa/ares__htable_strvp.c b/src/lib/dsa/ares__htable_strvp.c index d73a1928..2e449c10 100644 --- a/src/lib/dsa/ares__htable_strvp.c +++ b/src/lib/dsa/ares__htable_strvp.c @@ -74,14 +74,7 @@ static void bucket_free(void *bucket) static ares_bool_t key_eq(const void *key1, const void *key2) { - const char *k1 = key1; - const char *k2 = key2; - - if (strcasecmp(k1, k2) == 0) { - return ARES_TRUE; - } - - return ARES_FALSE; + return ares_strcaseeq(key1, key2); } ares__htable_strvp_t * diff --git a/src/lib/event/ares_event_configchg.c b/src/lib/event/ares_event_configchg.c index 10f0e21d..4bdb3b87 100644 --- a/src/lib/event/ares_event_configchg.c +++ b/src/lib/event/ares_event_configchg.c @@ -116,8 +116,8 @@ static void ares_event_configchg_cb(ares_event_thread_t *e, ares_socket_t fd, continue; } - if (strcasecmp(event->name, "resolv.conf") == 0 || - strcasecmp(event->name, "nsswitch.conf") == 0) { + if (ares_strcaseeq(event->name, "resolv.conf") || + ares_strcaseeq(event->name, "nsswitch.conf")) { triggered = ARES_TRUE; } } diff --git a/src/lib/include/README.md b/src/lib/include/README.md new file mode 100644 index 00000000..f08021ba --- /dev/null +++ b/src/lib/include/README.md @@ -0,0 +1,8 @@ +# Semi-public headers +The headers listed here all export symbols into the ares namespace as public +symbols, but these headers are NOT included in the distribution. They are +meant to be used by other tools such as `adig` and `ahost`. + +These are most likely going to be general purpose library functions such +as data structures and algorithms. + diff --git a/src/lib/dsa/ares__array.h b/src/lib/include/ares__array.h similarity index 79% rename from src/lib/dsa/ares__array.h rename to src/lib/include/ares__array.h index 6fa1c0e1..7b0fca4f 100644 --- a/src/lib/dsa/ares__array.h +++ b/src/lib/include/ares__array.h @@ -26,6 +26,8 @@ #ifndef __ARES__ARRAY_H #define __ARES__ARRAY_H +#include "ares.h" + /*! \addtogroup ares__array Array Data Structure * * This is an array with helpers. It is meant to have as little overhead @@ -72,8 +74,8 @@ typedef int (*ares__array_cmp_t)(const void *data1, const void *data2); * * \return array object or NULL on out of memory */ -ares__array_t *ares__array_create(size_t member_size, - ares__array_destructor_t destruct); +CARES_EXTERN ares__array_t * + ares__array_create(size_t member_size, ares__array_destructor_t destruct); /*! Request the array be at least the requested size. Useful if the desired @@ -83,7 +85,8 @@ ares__array_t *ares__array_create(size_t member_size, * \param[in] size Minimum number of members * \return ARES_SUCCESS on success, ARES_EFORMERR on misuse, * ARES_ENOMEM on out of memory */ -ares_status_t ares__array_set_size(ares__array_t *arr, size_t size); +CARES_EXTERN ares_status_t ares__array_set_size(ares__array_t *arr, + size_t size); /*! Sort the array using the given comparison function. This is not * persistent, any future elements inserted will not maintain this sort. @@ -92,14 +95,15 @@ ares_status_t ares__array_set_size(ares__array_t *arr, size_t size); * \param[in] cb Sort callback * \return ARES_SUCCESS on success */ -ares_status_t ares__array_sort(ares__array_t *arr, ares__array_cmp_t cmp); +CARES_EXTERN ares_status_t ares__array_sort(ares__array_t *arr, + ares__array_cmp_t cmp); /*! Destroy an array object. If a destructor is set, will be called on each * member of the array. * * \param[in] arr Initialized array object. */ -void ares__array_destroy(ares__array_t *arr); +CARES_EXTERN void ares__array_destroy(ares__array_t *arr); /*! Retrieve the array in the native format. This will also destroy the * container. It is the responsibility of the caller to free the returned @@ -109,14 +113,14 @@ void ares__array_destroy(ares__array_t *arr); * \param[out] num_members the number of members in the returned array * \return pointer to native array on success, NULL on failure. */ -void *ares__array_finish(ares__array_t *arr, size_t *num_members); +CARES_EXTERN void *ares__array_finish(ares__array_t *arr, size_t *num_members); /*! Retrieve the number of members in the array * * \param[in] arr Initialized array object. * \return numbrer of members */ -size_t ares__array_len(const ares__array_t *arr); +CARES_EXTERN size_t ares__array_len(const ares__array_t *arr); /*! Insert a new array member at the given index * @@ -127,8 +131,9 @@ size_t ares__array_len(const ares__array_t *arr); * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index, * ARES_ENOMEM on out of memory. */ -ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr, - size_t idx); +CARES_EXTERN ares_status_t ares__array_insert_at(void **elem_ptr, + ares__array_t *arr, + size_t idx); /*! Insert a new array member at the end of the array * @@ -136,7 +141,8 @@ ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr, * \param[in] arr Initialized array object. * \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory. */ -ares_status_t ares__array_insert_last(void **elem_ptr, ares__array_t *arr); +CARES_EXTERN ares_status_t ares__array_insert_last(void **elem_ptr, + ares__array_t *arr); /*! Insert a new array member at the beginning of the array * @@ -144,39 +150,41 @@ ares_status_t ares__array_insert_last(void **elem_ptr, ares__array_t *arr); * \param[in] arr Initialized array object. * \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory. */ -ares_status_t ares__array_insert_first(void **elem_ptr, ares__array_t *arr); +CARES_EXTERN ares_status_t ares__array_insert_first(void **elem_ptr, + ares__array_t *arr); /*! Fetch a pointer to the given element in the array * \param[in] array Initialized array object * \param[in] idx Index to fetch * \return pointer on success, NULL on failure */ -void *ares__array_at(ares__array_t *arr, size_t idx); +CARES_EXTERN void *ares__array_at(ares__array_t *arr, size_t idx); /*! Fetch a pointer to the first element in the array * \param[in] array Initialized array object * \return pointer on success, NULL on failure */ -void *ares__array_first(ares__array_t *arr); +CARES_EXTERN void *ares__array_first(ares__array_t *arr); /*! Fetch a pointer to the last element in the array * \param[in] array Initialized array object * \return pointer on success, NULL on failure */ -void *ares__array_last(ares__array_t *arr); +CARES_EXTERN void *ares__array_last(ares__array_t *arr); /*! Fetch a constant pointer to the given element in the array * \param[in] array Initialized array object * \param[in] idx Index to fetch * \return pointer on success, NULL on failure */ -const void *ares__array_at_const(const ares__array_t *arr, size_t idx); +CARES_EXTERN const void *ares__array_at_const(const ares__array_t *arr, + size_t idx); /*! Fetch a constant pointer to the first element in the array * \param[in] array Initialized array object * \return pointer on success, NULL on failure */ -const void *ares__array_first_const(const ares__array_t *arr); +CARES_EXTERN const void *ares__array_first_const(const ares__array_t *arr); /*! Fetch a constant pointer to the last element in the array * \param[in] array Initialized array object * \return pointer on success, NULL on failure */ -const void *ares__array_last_const(const ares__array_t *arr); +CARES_EXTERN const void *ares__array_last_const(const ares__array_t *arr); /*! Claim the data from the specified array index, copying it to the buffer * provided by the caller. The index specified in the array will then be @@ -192,8 +200,8 @@ const void *ares__array_last_const(const ares__array_t *arr); * \param[in] idx Index to claim * \return ARES_SUCCESS on success, ARES_EFORMERR on usage failure. */ -ares_status_t ares__array_claim_at(void *dest, size_t dest_size, - ares__array_t *arr, size_t idx); +CARES_EXTERN ares_status_t ares__array_claim_at(void *dest, size_t dest_size, + ares__array_t *arr, size_t idx); /*! Remove the member at the specified array index. The destructor will be * called. @@ -202,21 +210,22 @@ ares_status_t ares__array_claim_at(void *dest, size_t dest_size, * \param[in] idx Index to remove * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use */ -ares_status_t ares__array_remove_at(ares__array_t *arr, size_t idx); +CARES_EXTERN ares_status_t ares__array_remove_at(ares__array_t *arr, + size_t idx); /*! Remove the first member of the array. * * \param[in] arr Initialized array object * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use */ -ares_status_t ares__array_remove_first(ares__array_t *arr); +CARES_EXTERN ares_status_t ares__array_remove_first(ares__array_t *arr); /*! Remove the last member of the array. * * \param[in] arr Initialized array object * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use */ -ares_status_t ares__array_remove_last(ares__array_t *arr); +CARES_EXTERN ares_status_t ares__array_remove_last(ares__array_t *arr); /*! @} */ diff --git a/src/lib/str/ares__buf.h b/src/lib/include/ares__buf.h similarity index 77% rename from src/lib/str/ares__buf.h rename to src/lib/include/ares__buf.h index cb887aa2..855853fa 100644 --- a/src/lib/str/ares__buf.h +++ b/src/lib/include/ares__buf.h @@ -26,6 +26,8 @@ #ifndef __ARES__BUF_H #define __ARES__BUF_H +#include "ares.h" + /*! \addtogroup ares__buf Safe Data Builder and buffer * * This is a buffer building and parsing framework with a focus on security over @@ -45,13 +47,13 @@ struct ares__buf; /*! Opaque data type for generic hash table implementation */ -typedef struct ares__buf ares__buf_t; +typedef struct ares__buf ares__buf_t; /*! Create a new buffer object that dynamically allocates buffers for data. * * \return initialized buffer object or NULL if out of memory. */ -ares__buf_t *ares__buf_create(void); +CARES_EXTERN ares__buf_t *ares__buf_create(void); /*! Create a new buffer object that uses a user-provided data pointer. The * data provided will not be manipulated, and cannot be appended to. This @@ -62,14 +64,15 @@ ares__buf_t *ares__buf_create(void); * * \return initialized buffer object or NULL if out of memory or misuse. */ -ares__buf_t *ares__buf_create_const(const unsigned char *data, size_t data_len); +CARES_EXTERN ares__buf_t *ares__buf_create_const(const unsigned char *data, + size_t data_len); /*! Destroy an initialized buffer object. * * \param[in] buf Initialized buf object */ -void ares__buf_destroy(ares__buf_t *buf); +CARES_EXTERN void ares__buf_destroy(ares__buf_t *buf); /*! Append multiple bytes to a dynamic buffer object @@ -79,8 +82,9 @@ void ares__buf_destroy(ares__buf_t *buf); * \param[in] data_len Length of data to copy to buffer object. * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data, - size_t data_len); +CARES_EXTERN ares_status_t ares__buf_append(ares__buf_t *buf, + const unsigned char *data, + size_t data_len); /*! Append a single byte to the dynamic buffer object * @@ -88,7 +92,8 @@ ares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data, * \param[in] b Single byte to append to buffer object. * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char b); +CARES_EXTERN ares_status_t ares__buf_append_byte(ares__buf_t *buf, + unsigned char b); /*! Append a null-terminated string to the dynamic buffer object * @@ -96,7 +101,8 @@ ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char b); * \param[in] str String to append to buffer object. * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str); +CARES_EXTERN ares_status_t ares__buf_append_str(ares__buf_t *buf, + const char *str); /*! Append a 16bit Big Endian number to the buffer. * @@ -104,7 +110,8 @@ ares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str); * \param[out] u16 16bit integer * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16); +CARES_EXTERN ares_status_t ares__buf_append_be16(ares__buf_t *buf, + unsigned short u16); /*! Append a 32bit Big Endian number to the buffer. * @@ -112,7 +119,8 @@ ares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16); * \param[out] u32 32bit integer * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32); +CARES_EXTERN ares_status_t ares__buf_append_be32(ares__buf_t *buf, + unsigned int u32); /*! Append a number in ASCII decimal form. * @@ -121,8 +129,8 @@ ares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32); * \param[in] len Length to output, use 0 for no padding * \return ARES_SUCCESS on success */ -ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, - size_t len); +CARES_EXTERN ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, + size_t num, size_t len); /*! Append a number in ASCII hexadecimal form. * @@ -131,8 +139,8 @@ ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, * \param[in] len Length to output, use 0 for no padding * \return ARES_SUCCESS on success */ -ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num, - size_t len); +CARES_EXTERN ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, + size_t num, size_t len); /*! Sets the current buffer length. This *may* be used if there is a need to * override a prior position in the buffer, such as if there is a length @@ -147,7 +155,7 @@ ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num, * \param[in] len Length to set * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len); +CARES_EXTERN ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len); /*! Start a dynamic append operation that returns a buffer suitable for @@ -161,7 +169,8 @@ ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len); * returned. * \return Pointer to writable buffer or NULL on failure (usage, out of mem) */ -unsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len); +CARES_EXTERN unsigned char *ares__buf_append_start(ares__buf_t *buf, + size_t *len); /*! Finish a dynamic append operation. Called after * ares__buf_append_start() once desired data is written. @@ -171,7 +180,7 @@ unsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len); * operation. Must not be greater than returned from * ares__buf_append_start(). */ -void ares__buf_append_finish(ares__buf_t *buf, size_t len); +CARES_EXTERN void ares__buf_append_finish(ares__buf_t *buf, size_t len); /*! Write the data provided to the buffer in a hexdump format. * @@ -180,8 +189,9 @@ void ares__buf_append_finish(ares__buf_t *buf, size_t len); * \param[in] len Length of data to hexdump * \return ARES_SUCCESS on success. */ -ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, - size_t len); +CARES_EXTERN ares_status_t ares__buf_hexdump(ares__buf_t *buf, + const unsigned char *data, + size_t len); /*! Clean up ares__buf_t and return allocated pointer to unprocessed data. It * is the responsibility of the caller to ares_free() the returned buffer. @@ -191,7 +201,7 @@ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, * \param[out] len Length of data returned * \return pointer to unprocessed data (may be zero length) or NULL on error. */ -unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len); +CARES_EXTERN unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len); /*! Clean up ares__buf_t and return allocated pointer to unprocessed data and * return it as a string (null terminated). It is the responsibility of the @@ -207,7 +217,7 @@ unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len); * \param[out] len Optional. Length of data returned, or NULL if not needed. * \return pointer to unprocessed data or NULL on error. */ -char *ares__buf_finish_str(ares__buf_t *buf, size_t *len); +CARES_EXTERN char *ares__buf_finish_str(ares__buf_t *buf, size_t *len); /*! Tag a position to save in the buffer in case parsing needs to rollback, * such as if insufficient data is available, but more data may be added in @@ -216,14 +226,14 @@ char *ares__buf_finish_str(ares__buf_t *buf, size_t *len); * * \param[in] buf Initialized buffer object */ -void ares__buf_tag(ares__buf_t *buf); +CARES_EXTERN void ares__buf_tag(ares__buf_t *buf); /*! Rollback to a tagged position. Will automatically clear the tag. * * \param[in] buf Initialized buffer object * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_tag_rollback(ares__buf_t *buf); +CARES_EXTERN ares_status_t ares__buf_tag_rollback(ares__buf_t *buf); /*! Clear the tagged position without rolling back. You should do this any * time a tag is no longer needed as future append operations can reclaim @@ -232,7 +242,7 @@ ares_status_t ares__buf_tag_rollback(ares__buf_t *buf); * \param[in] buf Initialized buffer object * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_tag_clear(ares__buf_t *buf); +CARES_EXTERN ares_status_t ares__buf_tag_clear(ares__buf_t *buf); /*! Fetch the buffer and length of data starting from the tagged position up * to the _current_ position. It will not unset the tagged position. The @@ -243,14 +253,15 @@ ares_status_t ares__buf_tag_clear(ares__buf_t *buf); * \return NULL on failure (such as no tag), otherwise pointer to start of * buffer */ -const unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf, size_t *len); +CARES_EXTERN const unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf, + size_t *len); /*! Get the length of the current tag offset to the current position. * * \param[in] buf Initialized buffer object * \return length */ -size_t ares__buf_tag_length(const ares__buf_t *buf); +CARES_EXTERN size_t ares__buf_tag_length(const ares__buf_t *buf); /*! Fetch the bytes starting from the tagged position up to the _current_ * position using the provided buffer. It will not unset the tagged position. @@ -261,8 +272,9 @@ size_t ares__buf_tag_length(const ares__buf_t *buf); * buffer. * \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size */ -ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf, - unsigned char *bytes, size_t *len); +CARES_EXTERN ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf, + unsigned char *bytes, + size_t *len); /*! Fetch the bytes starting from the tagged position up to the _current_ * position as a NULL-terminated string using the provided buffer. The data @@ -276,8 +288,8 @@ ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf, * \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size, * ARES_EBADSTR if not printable ASCII */ -ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str, - size_t len); +CARES_EXTERN ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, + char *str, size_t len); /*! Consume the given number of bytes without reading them. * @@ -285,7 +297,7 @@ ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str, * \param[in] len Length to consume * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_consume(ares__buf_t *buf, size_t len); +CARES_EXTERN ares_status_t ares__buf_consume(ares__buf_t *buf, size_t len); /*! Fetch a 16bit Big Endian number from the buffer. * @@ -293,7 +305,8 @@ ares_status_t ares__buf_consume(ares__buf_t *buf, size_t len); * \param[out] u16 Buffer to hold 16bit integer * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16); +CARES_EXTERN ares_status_t ares__buf_fetch_be16(ares__buf_t *buf, + unsigned short *u16); /*! Fetch a 32bit Big Endian number from the buffer. * @@ -301,7 +314,8 @@ ares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16); * \param[out] u32 Buffer to hold 32bit integer * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32); +CARES_EXTERN ares_status_t ares__buf_fetch_be32(ares__buf_t *buf, + unsigned int *u32); /*! Fetch the requested number of bytes into the provided buffer @@ -311,8 +325,9 @@ ares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32); * \param[in] len Requested number of bytes (must be > 0) * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, unsigned char *bytes, - size_t len); +CARES_EXTERN ares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, + unsigned char *bytes, + size_t len); /*! Fetch the requested number of bytes and return a new buffer that must be @@ -326,9 +341,10 @@ ares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, unsigned char *bytes, * \param[out] bytes Pointer passed by reference. Will be allocated. * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, size_t len, - ares_bool_t null_term, - unsigned char **bytes); +CARES_EXTERN ares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, + size_t len, + ares_bool_t null_term, + unsigned char **bytes); /*! Fetch the requested number of bytes and place them into the provided * dest buffer object. @@ -338,8 +354,9 @@ ares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, size_t len, * \param[in] len Requested number of bytes (must be > 0) * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, - ares__buf_t *dest, size_t len); +CARES_EXTERN ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, + ares__buf_t *dest, + size_t len); /*! Fetch the requested number of bytes and return a new buffer that must be * ares_free()'d by the caller. The returned buffer is a null terminated @@ -350,7 +367,8 @@ ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, * \param[out] str Pointer passed by reference. Will be allocated. * \return ARES_SUCCESS or one of the c-ares error codes */ -ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str); +CARES_EXTERN ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, + char **str); /*! Consume whitespace characters (0x09, 0x0B, 0x0C, 0x0D, 0x20, and optionally * 0x0A). @@ -360,8 +378,8 @@ ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str); * ARES_FALSE otherwise. * \return number of whitespace characters consumed */ -size_t ares__buf_consume_whitespace(ares__buf_t *buf, - ares_bool_t include_linefeed); +CARES_EXTERN size_t ares__buf_consume_whitespace(ares__buf_t *buf, + ares_bool_t include_linefeed); /*! Consume any non-whitespace character (anything other than 0x09, 0x0B, 0x0C, @@ -370,7 +388,7 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf, * \param[in] buf Initialized buffer object * \return number of characters consumed */ -size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf); +CARES_EXTERN size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf); /*! Consume until a character in the character set provided is reached. Does @@ -385,9 +403,9 @@ size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf); * 0 if not found. * \return number of characters consumed */ -size_t ares__buf_consume_until_charset(ares__buf_t *buf, - const unsigned char *charset, size_t len, - ares_bool_t require_charset); +CARES_EXTERN size_t ares__buf_consume_until_charset( + ares__buf_t *buf, const unsigned char *charset, size_t len, + ares_bool_t require_charset); /*! Consume while the characters match the characters in the provided set. @@ -397,8 +415,9 @@ size_t ares__buf_consume_until_charset(ares__buf_t *buf, * \param[in] len length of character set * \return number of characters consumed */ -size_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset, - size_t len); +CARES_EXTERN size_t ares__buf_consume_charset(ares__buf_t *buf, + const unsigned char *charset, + size_t len); /*! Consume from the current position until the end of the line, and optionally @@ -409,7 +428,8 @@ size_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset, * ARES_FALSE otherwise. * \return number of characters consumed */ -size_t ares__buf_consume_line(ares__buf_t *buf, ares_bool_t include_linefeed); +CARES_EXTERN size_t ares__buf_consume_line(ares__buf_t *buf, + ares_bool_t include_linefeed); typedef enum { /*! No flags */ @@ -457,9 +477,9 @@ typedef enum { * objects. * \return ARES_SUCCESS on success, or error like ARES_ENOMEM. */ -ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, - size_t delims_len, ares__buf_split_t flags, - size_t max_sections, ares__llist_t **list); +CARES_EXTERN ares_status_t ares__buf_split( + ares__buf_t *buf, const unsigned char *delims, size_t delims_len, + ares__buf_split_t flags, size_t max_sections, ares__llist_t **list); /*! Check the unprocessed buffer to see if it begins with the sequence of @@ -470,8 +490,9 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, * \param[in] data_len Length of data to compare. * \return ARES_TRUE on match, ARES_FALSE otherwise. */ -ares_bool_t ares__buf_begins_with(const ares__buf_t *buf, - const unsigned char *data, size_t data_len); +CARES_EXTERN ares_bool_t ares__buf_begins_with(const ares__buf_t *buf, + const unsigned char *data, + size_t data_len); /*! Size of unprocessed remaining data length @@ -479,7 +500,7 @@ ares_bool_t ares__buf_begins_with(const ares__buf_t *buf, * \param[in] buf Initialized buffer object * \return length remaining */ -size_t ares__buf_len(const ares__buf_t *buf); +CARES_EXTERN size_t ares__buf_len(const ares__buf_t *buf); /*! Retrieve a pointer to the currently unprocessed data. Generally this isn't * recommended to be used in practice. The returned pointer may be invalidated @@ -489,7 +510,8 @@ size_t ares__buf_len(const ares__buf_t *buf); * \param[out] len Length of available data * \return Pointer to buffer of unprocessed data */ -const unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len); +CARES_EXTERN const unsigned char *ares__buf_peek(const ares__buf_t *buf, + size_t *len); /*! Wipe any processed data from the beginning of the buffer. This will @@ -512,7 +534,7 @@ const unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len); * * \param[in] buf Initialized buffer object */ -void ares__buf_reclaim(ares__buf_t *buf); +CARES_EXTERN void ares__buf_reclaim(ares__buf_t *buf); /*! Set the current offset within the internal buffer. * @@ -528,7 +550,7 @@ void ares__buf_reclaim(ares__buf_t *buf); * \param[in] idx Index to set position * \return ARES_SUCCESS if valid index */ -ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx); +CARES_EXTERN ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx); /*! Get the current offset within the internal buffer. * @@ -542,7 +564,7 @@ ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx); * \param[in] buf Initialized buffer object * \return index of current position */ -size_t ares__buf_get_position(const ares__buf_t *buf); +CARES_EXTERN size_t ares__buf_get_position(const ares__buf_t *buf); /*! Parse a character-string as defined in RFC1035, as a null-terminated * string. @@ -556,29 +578,9 @@ size_t ares__buf_get_position(const ares__buf_t *buf); * ares_free()'d by the caller. * \return ARES_SUCCESS on success */ -ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len, - char **name); - -/*! Parse an array of character strings as defined in RFC1035, as binary, - * however, for convenience this does guarantee a NULL terminator (that is - * not included in the length for each value). - * - * \param[in] buf initialized buffer object - * \param[in] remaining_len maximum length that should be used for - * parsing the string, this is often less than - * the remaining buffer and is based on the RR - * record length. - * \param[out] strs Pointer passed by reference to be filled in - * with - * the array of values. - * \param[out] validate_printable Validate the strings contain only printable - * data. - * \return ARES_SUCCESS on success - */ -ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf, - size_t remaining_len, - ares__dns_multistring_t **strs, - ares_bool_t validate_printable); +CARES_EXTERN ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, + size_t remaining_len, + char **name); /*! Parse a character-string as defined in RFC1035, as binary, however for * convenience this does guarantee a NULL terminator (that is not included @@ -594,8 +596,10 @@ ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf, * \param[out] bin_len Length of returned string. * \return ARES_SUCCESS on success */ -ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, - unsigned char **bin, size_t *bin_len); +CARES_EXTERN ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, + size_t remaining_len, + unsigned char **bin, + size_t *bin_len); /*! Load data from specified file path into provided buffer. The entire file * is loaded into memory. @@ -606,7 +610,8 @@ ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, * \return ARES_ENOTFOUND if file not found, ARES_EFILE if issues reading * file, ARES_ENOMEM if out of memory, ARES_SUCCESS on success. */ -ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf); +CARES_EXTERN ares_status_t ares__buf_load_file(const char *filename, + ares__buf_t *buf); /*! @} */ diff --git a/src/lib/dsa/ares__htable_asvp.h b/src/lib/include/ares__htable_asvp.h similarity index 82% rename from src/lib/dsa/ares__htable_asvp.h rename to src/lib/include/ares__htable_asvp.h index 49a766d0..5ef892ed 100644 --- a/src/lib/dsa/ares__htable_asvp.h +++ b/src/lib/include/ares__htable_asvp.h @@ -57,7 +57,7 @@ typedef void (*ares__htable_asvp_val_free_t)(void *val); * * \param[in] htable Initialized hashtable */ -void ares__htable_asvp_destroy(ares__htable_asvp_t *htable); +CARES_EXTERN void ares__htable_asvp_destroy(ares__htable_asvp_t *htable); /*! Create size_t key, void pointer value hash table * @@ -65,7 +65,7 @@ void ares__htable_asvp_destroy(ares__htable_asvp_t *htable); * NULL it is expected the caller will clean up any user * supplied values. */ -ares__htable_asvp_t * +CARES_EXTERN ares__htable_asvp_t * ares__htable_asvp_create(ares__htable_asvp_val_free_t val_free); /*! Retrieve an array of keys from the hashtable. @@ -74,8 +74,8 @@ ares__htable_asvp_t * * \param[out] num Count of returned keys * \return Array of keys in the hashtable. Must be free'd with ares_free(). */ -ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable, - size_t *num); +CARES_EXTERN ares_socket_t * + ares__htable_asvp_keys(const ares__htable_asvp_t *htable, size_t *num); /*! Insert key/value into hash table @@ -85,8 +85,8 @@ ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable, * \param[in] val value to store (takes ownership). May be NULL. * \return ARES_TRUE on success, ARES_FALSE on out of memory or misuse */ -ares_bool_t ares__htable_asvp_insert(ares__htable_asvp_t *htable, - ares_socket_t key, void *val); +CARES_EXTERN ares_bool_t ares__htable_asvp_insert(ares__htable_asvp_t *htable, + ares_socket_t key, void *val); /*! Retrieve value from hashtable based on key * @@ -95,8 +95,8 @@ ares_bool_t ares__htable_asvp_insert(ares__htable_asvp_t *htable, * \param[out] val Optional. Pointer to store value. * \return ARES_TRUE on success, ARES_FALSE on failure */ -ares_bool_t ares__htable_asvp_get(const ares__htable_asvp_t *htable, - ares_socket_t key, void **val); +CARES_EXTERN ares_bool_t ares__htable_asvp_get( + const ares__htable_asvp_t *htable, ares_socket_t key, void **val); /*! Retrieve value from hashtable directly as return value. Caveat to this * function over ares__htable_asvp_get() is that if a NULL value is stored @@ -106,8 +106,9 @@ ares_bool_t ares__htable_asvp_get(const ares__htable_asvp_t *htable, * \param[in] key key to use to search * \return value associated with key in hashtable or NULL */ -void *ares__htable_asvp_get_direct(const ares__htable_asvp_t *htable, - ares_socket_t key); +CARES_EXTERN void * + ares__htable_asvp_get_direct(const ares__htable_asvp_t *htable, + ares_socket_t key); /*! Remove a value from the hashtable by key * @@ -115,15 +116,16 @@ void *ares__htable_asvp_get_direct(const ares__htable_asvp_t *htable, * \param[in] key key to use to search * \return ARES_TRUE if found, ARES_FALSE if not found */ -ares_bool_t ares__htable_asvp_remove(ares__htable_asvp_t *htable, - ares_socket_t key); +CARES_EXTERN ares_bool_t ares__htable_asvp_remove(ares__htable_asvp_t *htable, + ares_socket_t key); /*! Retrieve the number of keys stored in the hash table * * \param[in] htable Initialized hash table * \return count */ -size_t ares__htable_asvp_num_keys(const ares__htable_asvp_t *htable); +CARES_EXTERN size_t + ares__htable_asvp_num_keys(const ares__htable_asvp_t *htable); /*! @} */ diff --git a/src/lib/dsa/ares__htable_strvp.h b/src/lib/include/ares__htable_strvp.h similarity index 82% rename from src/lib/dsa/ares__htable_strvp.h rename to src/lib/include/ares__htable_strvp.h index 878c7186..c95f8d69 100644 --- a/src/lib/dsa/ares__htable_strvp.h +++ b/src/lib/include/ares__htable_strvp.h @@ -55,7 +55,7 @@ typedef void (*ares__htable_strvp_val_free_t)(void *val); * * \param[in] htable Initialized hashtable */ -void ares__htable_strvp_destroy(ares__htable_strvp_t *htable); +CARES_EXTERN void ares__htable_strvp_destroy(ares__htable_strvp_t *htable); /*! Create string, void pointer value hash table * @@ -63,7 +63,7 @@ void ares__htable_strvp_destroy(ares__htable_strvp_t *htable); * NULL it is expected the caller will clean up any user * supplied values. */ -ares__htable_strvp_t * +CARES_EXTERN ares__htable_strvp_t * ares__htable_strvp_create(ares__htable_strvp_val_free_t val_free); /*! Insert key/value into hash table @@ -73,8 +73,8 @@ ares__htable_strvp_t * * \param[in] val value to store (takes ownership). May be NULL. * \return ARES_TRUE on success, ARES_FALSE on failure or out of memory */ -ares_bool_t ares__htable_strvp_insert(ares__htable_strvp_t *htable, - const char *key, void *val); +CARES_EXTERN ares_bool_t ares__htable_strvp_insert(ares__htable_strvp_t *htable, + const char *key, void *val); /*! Retrieve value from hashtable based on key * @@ -83,8 +83,8 @@ ares_bool_t ares__htable_strvp_insert(ares__htable_strvp_t *htable, * \param[out] val Optional. Pointer to store value. * \return ARES_TRUE on success, ARES_FALSE on failure */ -ares_bool_t ares__htable_strvp_get(const ares__htable_strvp_t *htable, - const char *key, void **val); +CARES_EXTERN ares_bool_t ares__htable_strvp_get( + const ares__htable_strvp_t *htable, const char *key, void **val); /*! Retrieve value from hashtable directly as return value. Caveat to this * function over ares__htable_strvp_get() is that if a NULL value is stored @@ -94,8 +94,9 @@ ares_bool_t ares__htable_strvp_get(const ares__htable_strvp_t *htable, * \param[in] key key to use to search * \return value associated with key in hashtable or NULL */ -void *ares__htable_strvp_get_direct(const ares__htable_strvp_t *htable, - const char *key); +CARES_EXTERN void * + ares__htable_strvp_get_direct(const ares__htable_strvp_t *htable, + const char *key); /*! Remove a value from the hashtable by key * @@ -103,15 +104,16 @@ void *ares__htable_strvp_get_direct(const ares__htable_strvp_t *htable, * \param[in] key key to use to search * \return ARES_TRUE if found, ARES_FALSE if not */ -ares_bool_t ares__htable_strvp_remove(ares__htable_strvp_t *htable, - const char *key); +CARES_EXTERN ares_bool_t ares__htable_strvp_remove(ares__htable_strvp_t *htable, + const char *key); /*! Retrieve the number of keys stored in the hash table * * \param[in] htable Initialized hash table * \return count */ -size_t ares__htable_strvp_num_keys(const ares__htable_strvp_t *htable); +CARES_EXTERN size_t + ares__htable_strvp_num_keys(const ares__htable_strvp_t *htable); /*! @} */ diff --git a/src/lib/dsa/ares__htable_szvp.h b/src/lib/include/ares__htable_szvp.h similarity index 83% rename from src/lib/dsa/ares__htable_szvp.h rename to src/lib/include/ares__htable_szvp.h index 62b1776b..0fa8167a 100644 --- a/src/lib/dsa/ares__htable_szvp.h +++ b/src/lib/include/ares__htable_szvp.h @@ -55,7 +55,7 @@ typedef void (*ares__htable_szvp_val_free_t)(void *val); * * \param[in] htable Initialized hashtable */ -void ares__htable_szvp_destroy(ares__htable_szvp_t *htable); +CARES_EXTERN void ares__htable_szvp_destroy(ares__htable_szvp_t *htable); /*! Create size_t key, void pointer value hash table * @@ -63,7 +63,7 @@ void ares__htable_szvp_destroy(ares__htable_szvp_t *htable); * NULL it is expected the caller will clean up any user * supplied values. */ -ares__htable_szvp_t * +CARES_EXTERN ares__htable_szvp_t * ares__htable_szvp_create(ares__htable_szvp_val_free_t val_free); /*! Insert key/value into hash table @@ -73,8 +73,8 @@ ares__htable_szvp_t * * \param[in] val value to store (takes ownership). May be NULL. * \return ARES_TRUE on success, ARES_FALSE on failure or out of memory */ -ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, size_t key, - void *val); +CARES_EXTERN ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, + size_t key, void *val); /*! Retrieve value from hashtable based on key * @@ -83,8 +83,8 @@ ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, size_t key, * \param[out] val Optional. Pointer to store value. * \return ARES_TRUE on success, ARES_FALSE on failure */ -ares_bool_t ares__htable_szvp_get(const ares__htable_szvp_t *htable, size_t key, - void **val); +CARES_EXTERN ares_bool_t ares__htable_szvp_get( + const ares__htable_szvp_t *htable, size_t key, void **val); /*! Retrieve value from hashtable directly as return value. Caveat to this * function over ares__htable_szvp_get() is that if a NULL value is stored @@ -94,8 +94,8 @@ ares_bool_t ares__htable_szvp_get(const ares__htable_szvp_t *htable, size_t key, * \param[in] key key to use to search * \return value associated with key in hashtable or NULL */ -void *ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable, - size_t key); +CARES_EXTERN void * + ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable, size_t key); /*! Remove a value from the hashtable by key * @@ -103,14 +103,16 @@ void *ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable, * \param[in] key key to use to search * \return ARES_TRUE if found, ARES_FALSE if not */ -ares_bool_t ares__htable_szvp_remove(ares__htable_szvp_t *htable, size_t key); +CARES_EXTERN ares_bool_t ares__htable_szvp_remove(ares__htable_szvp_t *htable, + size_t key); /*! Retrieve the number of keys stored in the hash table * * \param[in] htable Initialized hash table * \return count */ -size_t ares__htable_szvp_num_keys(const ares__htable_szvp_t *htable); +CARES_EXTERN size_t + ares__htable_szvp_num_keys(const ares__htable_szvp_t *htable); /*! @} */ diff --git a/src/lib/dsa/ares__htable_vpvp.h b/src/lib/include/ares__htable_vpvp.h similarity index 82% rename from src/lib/dsa/ares__htable_vpvp.h rename to src/lib/include/ares__htable_vpvp.h index 1e0c750d..7aac0edf 100644 --- a/src/lib/dsa/ares__htable_vpvp.h +++ b/src/lib/include/ares__htable_vpvp.h @@ -61,7 +61,7 @@ typedef void (*ares__htable_vpvp_val_free_t)(void *val); * * \param[in] htable Initialized hashtable */ -void ares__htable_vpvp_destroy(ares__htable_vpvp_t *htable); +CARES_EXTERN void ares__htable_vpvp_destroy(ares__htable_vpvp_t *htable); /*! Create size_t key, void pointer value hash table * @@ -72,9 +72,9 @@ void ares__htable_vpvp_destroy(ares__htable_vpvp_t *htable); * NULL it is expected the caller will clean up any user * supplied values. */ -ares__htable_vpvp_t * +CARES_EXTERN ares__htable_vpvp_t * ares__htable_vpvp_create(ares__htable_vpvp_key_free_t key_free, - ares__htable_vpvp_val_free_t val_free); + ares__htable_vpvp_val_free_t val_free); /*! Insert key/value into hash table * @@ -83,8 +83,8 @@ ares__htable_vpvp_t * * \param[in] val value to store (takes ownership). May be NULL. * \return ARES_TRUE on success, ARES_FALSE on failure or out of memory */ -ares_bool_t ares__htable_vpvp_insert(ares__htable_vpvp_t *htable, void *key, - void *val); +CARES_EXTERN ares_bool_t ares__htable_vpvp_insert(ares__htable_vpvp_t *htable, + void *key, void *val); /*! Retrieve value from hashtable based on key * @@ -93,8 +93,8 @@ ares_bool_t ares__htable_vpvp_insert(ares__htable_vpvp_t *htable, void *key, * \param[out] val Optional. Pointer to store value. * \return ARES_TRUE on success, ARES_FALSE on failure */ -ares_bool_t ares__htable_vpvp_get(const ares__htable_vpvp_t *htable, - const void *key, void **val); +CARES_EXTERN ares_bool_t ares__htable_vpvp_get( + const ares__htable_vpvp_t *htable, const void *key, void **val); /*! Retrieve value from hashtable directly as return value. Caveat to this * function over ares__htable_vpvp_get() is that if a NULL value is stored @@ -104,8 +104,9 @@ ares_bool_t ares__htable_vpvp_get(const ares__htable_vpvp_t *htable, * \param[in] key key to use to search * \return value associated with key in hashtable or NULL */ -void *ares__htable_vpvp_get_direct(const ares__htable_vpvp_t *htable, - const void *key); +CARES_EXTERN void * + ares__htable_vpvp_get_direct(const ares__htable_vpvp_t *htable, + const void *key); /*! Remove a value from the hashtable by key * @@ -113,15 +114,16 @@ void *ares__htable_vpvp_get_direct(const ares__htable_vpvp_t *htable, * \param[in] key key to use to search * \return ARES_TRUE if found, ARES_FALSE if not */ -ares_bool_t ares__htable_vpvp_remove(ares__htable_vpvp_t *htable, - const void *key); +CARES_EXTERN ares_bool_t ares__htable_vpvp_remove(ares__htable_vpvp_t *htable, + const void *key); /*! Retrieve the number of keys stored in the hash table * * \param[in] htable Initialized hash table * \return count */ -size_t ares__htable_vpvp_num_keys(const ares__htable_vpvp_t *htable); +CARES_EXTERN size_t + ares__htable_vpvp_num_keys(const ares__htable_vpvp_t *htable); /*! @} */ diff --git a/src/lib/dsa/ares__llist.h b/src/lib/include/ares__llist.h similarity index 71% rename from src/lib/dsa/ares__llist.h rename to src/lib/include/ares__llist.h index 213f5413..6769fb3a 100644 --- a/src/lib/dsa/ares__llist.h +++ b/src/lib/include/ares__llist.h @@ -59,7 +59,8 @@ typedef void (*ares__llist_destructor_t)(void *data); * \param[in] destruct Optional. Destructor to call on all removed nodes * \return linked list object or NULL on out of memory */ -ares__llist_t *ares__llist_create(ares__llist_destructor_t destruct); +CARES_EXTERN ares__llist_t * + ares__llist_create(ares__llist_destructor_t destruct); /*! Replace destructor for linked list nodes. Typically this is used * when wanting to disable the destructor by using NULL. @@ -67,8 +68,9 @@ ares__llist_t *ares__llist_create(ares__llist_destructor_t destruct); * \param[in] list Initialized linked list object * \param[in] destruct replacement destructor, NULL is allowed */ -void ares__llist_replace_destructor(ares__llist_t *list, - ares__llist_destructor_t destruct); +CARES_EXTERN void + ares__llist_replace_destructor(ares__llist_t *list, + ares__llist_destructor_t destruct); /*! Insert value as the first node in the linked list * @@ -77,7 +79,8 @@ void ares__llist_replace_destructor(ares__llist_t *list * \return node object referencing place in list, or null if out of memory or * misuse */ -ares__llist_node_t *ares__llist_insert_first(ares__llist_t *list, void *val); +CARES_EXTERN ares__llist_node_t *ares__llist_insert_first(ares__llist_t *list, + void *val); /*! Insert value as the last node in the linked list * @@ -86,7 +89,8 @@ ares__llist_node_t *ares__llist_insert_first(ares__llist_t *list, void *val); * \return node object referencing place in list, or null if out of memory or * misuse */ -ares__llist_node_t *ares__llist_insert_last(ares__llist_t *list, void *val); +CARES_EXTERN ares__llist_node_t *ares__llist_insert_last(ares__llist_t *list, + void *val); /*! Insert value before specified node in the linked list * @@ -95,8 +99,8 @@ ares__llist_node_t *ares__llist_insert_last(ares__llist_t *list, void *val); * \return node object referencing place in list, or null if out of memory or * misuse */ -ares__llist_node_t *ares__llist_insert_before(ares__llist_node_t *node, - void *val); +CARES_EXTERN ares__llist_node_t * + ares__llist_insert_before(ares__llist_node_t *node, void *val); /*! Insert value after specified node in the linked list * @@ -105,22 +109,22 @@ ares__llist_node_t *ares__llist_insert_before(ares__llist_node_t *node, * \return node object referencing place in list, or null if out of memory or * misuse */ -ares__llist_node_t *ares__llist_insert_after(ares__llist_node_t *node, - void *val); +CARES_EXTERN ares__llist_node_t * + ares__llist_insert_after(ares__llist_node_t *node, void *val); /*! Obtain first node in list * * \param[in] list Initialized list object * \return first node in list or NULL if none */ -ares__llist_node_t *ares__llist_node_first(ares__llist_t *list); +CARES_EXTERN ares__llist_node_t *ares__llist_node_first(ares__llist_t *list); /*! Obtain last node in list * * \param[in] list Initialized list object * \return last node in list or NULL if none */ -ares__llist_node_t *ares__llist_node_last(ares__llist_t *list); +CARES_EXTERN ares__llist_node_t *ares__llist_node_last(ares__llist_t *list); /*! Obtain a node based on its index. This is an O(n) operation. * @@ -128,21 +132,24 @@ ares__llist_node_t *ares__llist_node_last(ares__llist_t *list); * \param[in] idx Index of node to retrieve * \return node at index or NULL if invalid index */ -ares__llist_node_t *ares__llist_node_idx(ares__llist_t *list, size_t idx); +CARES_EXTERN ares__llist_node_t *ares__llist_node_idx(ares__llist_t *list, + size_t idx); /*! Obtain next node in respect to specified node * * \param[in] node Node referenced * \return node or NULL if none */ -ares__llist_node_t *ares__llist_node_next(ares__llist_node_t *node); +CARES_EXTERN ares__llist_node_t * + ares__llist_node_next(ares__llist_node_t *node); /*! Obtain previous node in respect to specified node * * \param[in] node Node referenced * \return node or NULL if none */ -ares__llist_node_t *ares__llist_node_prev(ares__llist_node_t *node); +CARES_EXTERN ares__llist_node_t * + ares__llist_node_prev(ares__llist_node_t *node); /*! Obtain value from node @@ -150,41 +157,41 @@ ares__llist_node_t *ares__llist_node_prev(ares__llist_node_t *node); * \param[in] node Node referenced * \return user provided value from node */ -void *ares__llist_node_val(ares__llist_node_t *node); +CARES_EXTERN void *ares__llist_node_val(ares__llist_node_t *node); /*! Obtain the number of entries in the list * * \param[in] list Initialized list object * \return count */ -size_t ares__llist_len(const ares__llist_t *list); +CARES_EXTERN size_t ares__llist_len(const ares__llist_t *list); /*! Clear all entries in the list, but don't destroy the list object. * * \param[in] list Initialized list object */ -void ares__llist_clear(ares__llist_t *list); +CARES_EXTERN void ares__llist_clear(ares__llist_t *list); /*! Obtain list object from referenced node * * \param[in] node Node referenced * \return list object node belongs to */ -ares__llist_t *ares__llist_node_parent(ares__llist_node_t *node); +CARES_EXTERN ares__llist_t *ares__llist_node_parent(ares__llist_node_t *node); /*! Obtain the first user-supplied value in the list * * \param[in] list Initialized list object * \return first user supplied value or NULL if none */ -void *ares__llist_first_val(ares__llist_t *list); +CARES_EXTERN void *ares__llist_first_val(ares__llist_t *list); /*! Obtain the last user-supplied value in the list * * \param[in] list Initialized list object * \return last user supplied value or NULL if none */ -void *ares__llist_last_val(ares__llist_t *list); +CARES_EXTERN void *ares__llist_last_val(ares__llist_t *list); /*! Take ownership of user-supplied value in list without calling destructor. * Will unchain entry from list. @@ -192,26 +199,26 @@ void *ares__llist_last_val(ares__llist_t *list); * \param[in] node Node referenced * \return user supplied value */ -void *ares__llist_node_claim(ares__llist_node_t *node); +CARES_EXTERN void *ares__llist_node_claim(ares__llist_node_t *node); /*! Replace user-supplied value for node * * \param[in] node Node referenced * \param[in] val new user-supplied value */ -void ares__llist_node_replace(ares__llist_node_t *node, void *val); +CARES_EXTERN void ares__llist_node_replace(ares__llist_node_t *node, void *val); /*! Destroy the node, removing it from the list and calling destructor. * * \param[in] node Node referenced */ -void ares__llist_node_destroy(ares__llist_node_t *node); +CARES_EXTERN void ares__llist_node_destroy(ares__llist_node_t *node); /*! Destroy the list object and all nodes in the list. * * \param[in] list Initialized list object */ -void ares__llist_destroy(ares__llist_t *list); +CARES_EXTERN void ares__llist_destroy(ares__llist_t *list); /*! Detach node from the current list and re-attach it to the new list as the * last entry. @@ -219,8 +226,8 @@ void ares__llist_destroy(ares__llist_t *list); * \param[in] node node to move * \param[in] new_parent new list */ -void ares__llist_node_move_parent_last(ares__llist_node_t *node, - ares__llist_t *new_parent); +CARES_EXTERN void ares__llist_node_move_parent_last(ares__llist_node_t *node, + ares__llist_t *new_parent); /*! Detach node from the current list and re-attach it to the new list as the * first entry. @@ -228,8 +235,8 @@ void ares__llist_node_move_parent_last(ares__llist_node_t *node, * \param[in] node node to move * \param[in] new_parent new list */ -void ares__llist_node_move_parent_first(ares__llist_node_t *node, - ares__llist_t *new_parent); +CARES_EXTERN void ares__llist_node_move_parent_first(ares__llist_node_t *node, + ares__llist_t *new_parent); /*! @} */ #endif /* __ARES__LLIST_H */ diff --git a/src/lib/str/ares_strcasecmp.h b/src/lib/include/ares_mem.h similarity index 75% rename from src/lib/str/ares_strcasecmp.h rename to src/lib/include/ares_mem.h index a8097d22..371cd426 100644 --- a/src/lib/str/ares_strcasecmp.h +++ b/src/lib/include/ares_mem.h @@ -1,6 +1,5 @@ /* MIT License * - * Copyright (c) 1998 Massachusetts Institute of Technology * Copyright (c) The c-ares project and its contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,15 +23,16 @@ * * SPDX-License-Identifier: MIT */ -#ifndef HEADER_CARES_STRCASECMP_H -#define HEADER_CARES_STRCASECMP_H -#ifndef HAVE_STRCASECMP -extern int ares_strcasecmp(const char *a, const char *b); -#endif +#ifndef __ARES_MEM_H +#define __ARES_MEM_H -#ifndef HAVE_STRNCASECMP -extern int ares_strncasecmp(const char *a, const char *b, size_t n); -#endif +/* Memory management functions */ +CARES_EXTERN void *ares_malloc(size_t size); +CARES_EXTERN void *ares_realloc(void *ptr, size_t size); +CARES_EXTERN void ares_free(void *ptr); +CARES_EXTERN void *ares_malloc_zero(size_t size); +CARES_EXTERN void *ares_realloc_zero(void *ptr, size_t orig_size, + size_t new_size); -#endif /* HEADER_CARES_STRCASECMP_H */ +#endif diff --git a/src/lib/include/ares_str.h b/src/lib/include/ares_str.h new file mode 100644 index 00000000..c90d5af8 --- /dev/null +++ b/src/lib/include/ares_str.h @@ -0,0 +1,185 @@ +/* MIT License + * + * Copyright (c) 1998 Massachusetts Institute of Technology + * Copyright (c) The c-ares project and its contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * SPDX-License-Identifier: MIT + */ +#ifndef __ARES_STR_H +#define __ARES_STR_H + +CARES_EXTERN char *ares_strdup(const char *s1); + +CARES_EXTERN size_t ares_strlen(const char *str); + +/*! Copy string from source to destination with destination buffer size + * provided. The destination is guaranteed to be null terminated, if the + * provided buffer isn't large enough, only those bytes from the source that + * will fit will be copied. + * + * \param[out] dest Destination buffer + * \param[in] src Source to copy + * \param[in] dest_size Size of destination buffer + * \return String length. Will be at most dest_size-1 + */ +CARES_EXTERN size_t ares_strcpy(char *dest, const char *src, size_t dest_size); + +CARES_EXTERN ares_bool_t ares_str_isnum(const char *str); + +CARES_EXTERN void ares__str_ltrim(char *str); +CARES_EXTERN void ares__str_rtrim(char *str); +CARES_EXTERN void ares__str_trim(char *str); + +CARES_EXTERN unsigned char ares__tolower(unsigned char c); +CARES_EXTERN ares_bool_t ares__memeq_ci(const unsigned char *ptr, + const unsigned char *val, size_t len); + +CARES_EXTERN ares_bool_t ares__isspace(int ch); +CARES_EXTERN ares_bool_t ares__isprint(int ch); +CARES_EXTERN ares_bool_t ares__is_hostnamech(int ch); + +CARES_EXTERN ares_bool_t ares__is_hostname(const char *str); + +/*! Validate the string provided is printable. The length specified must be + * at least the size of the buffer provided. If a NULL-terminator is hit + * before the length provided is hit, this will not be considered a valid + * printable string. This does not validate that the string is actually + * NULL terminated. + * + * \param[in] str Buffer containing string to evaluate. + * \param[in] len Number of characters to evaluate within provided buffer. + * If 0, will return TRUE since it did not hit an exception. + * \return ARES_TRUE if the entire string is printable, ARES_FALSE if not. + */ +CARES_EXTERN ares_bool_t ares__str_isprint(const char *str, size_t len); + +/* We only care about ASCII rules */ +#define ares__isascii(x) (((unsigned char)x) <= 127) +#define ares__isdigit(x) \ + (((unsigned char)x) >= '0' && ((unsigned char)x) <= '9') +#define ares__isxdigit(x) \ + (ares__isdigit(x) || \ + (((unsigned char)x) >= 'a' && ((unsigned char)x) <= 'f') || \ + (((unsigned char)x) >= 'A' && ((unsigned char)x) <= 'F')) +#define ares__isupper(x) \ + (((unsigned char)x) >= 'A' && ((unsigned char)x) <= 'Z') +#define ares__islower(x) \ + (((unsigned char)x) >= 'a' && ((unsigned char)x) <= 'z') +#define ares__isalpha(x) (ares__islower(x) || ares__isupper(x)) + +/*! Compare two strings (for sorting) + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \return < 0 if First String less than Second String, + * 0 if First String equal to Second String, + * > 0 if First String greater than Second String + */ +CARES_EXTERN int ares_strcmp(const char *a, const char *b); + +/*! Compare two strings up to specified length (for sorting) + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \param[in] n Length + * \return < 0 if First String less than Second String, + * 0 if First String equal to Second String, + * > 0 if First String greater than Second String + */ +CARES_EXTERN int ares_strncmp(const char *a, const char *b, size_t n); + + +/*! Compare two strings in a case-insensitive manner (for sorting) + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \return < 0 if First String less than Second String, + * 0 if First String equal to Second String, + * > 0 if First String greater than Second String + */ +CARES_EXTERN int ares_strcasecmp(const char *a, const char *b); + +/*! Compare two strings in a case-insensitive manner up to specified length + * (for sorting) + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \param[in] n Length + * \return < 0 if First String less than Second String, + * 0 if First String equal to Second String, + * > 0 if First String greater than Second String + */ +CARES_EXTERN int ares_strncasecmp(const char *a, const char *b, size_t n); + +/*! Compare two strings for equality + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \return ARES_TRUE on match, or ARES_FALSE if no match + */ +CARES_EXTERN ares_bool_t ares_streq(const char *a, const char *b); + +/*! Compare two strings for equality up to specified length + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \param[in] n Length + * \return ARES_TRUE on match, or ARES_FALSE if no match + */ +CARES_EXTERN ares_bool_t ares_streq_max(const char *a, const char *b, size_t n); + +/*! Compare two strings for equality in a case insensitive manner + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \return ARES_TRUE on match, or ARES_FALSE if no match + */ +CARES_EXTERN ares_bool_t ares_strcaseeq(const char *a, const char *b); + +/*! Compare two strings for equality up to specified length in a case + * insensitive manner + * + * Treats NULL and "" strings as equivalent + * + * \param[in] a First String + * \param[in] b Second String + * \param[in] n Length + * \return ARES_TRUE on match, or ARES_FALSE if no match + */ +CARES_EXTERN ares_bool_t ares_strcaseeq_max(const char *a, const char *b, + size_t n); + +#endif /* __ARES_STR_H */ diff --git a/src/lib/legacy/ares_parse_ptr_reply.c b/src/lib/legacy/ares_parse_ptr_reply.c index 56a7b5f9..0e52f9db 100644 --- a/src/lib/legacy/ares_parse_ptr_reply.c +++ b/src/lib/legacy/ares_parse_ptr_reply.c @@ -135,7 +135,7 @@ ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec, * status = ARES_EBADRESP; * goto done; * } - * if (strcasecmp(ptrname, rname) != 0) { + * if (!ares_strcaseeq(ptrname, rname)) { * continue; * } */ diff --git a/src/lib/record/ares_dns_mapping.c b/src/lib/record/ares_dns_mapping.c index 738d2f37..b8af8a6d 100644 --- a/src/lib/record/ares_dns_mapping.c +++ b/src/lib/record/ares_dns_mapping.c @@ -681,7 +681,7 @@ ares_bool_t ares_dns_class_fromstr(ares_dns_class_t *qclass, const char *str) } for (i = 0; list[i].name != NULL; i++) { - if (strcasecmp(list[i].name, str) == 0) { + if (ares_strcaseeq(list[i].name, str)) { *qclass = list[i].qclass; return ARES_TRUE; } @@ -726,7 +726,7 @@ ares_bool_t ares_dns_rec_type_fromstr(ares_dns_rec_type_t *qtype, } for (i = 0; list[i].name != NULL; i++) { - if (strcasecmp(list[i].name, str) == 0) { + if (ares_strcaseeq(list[i].name, str)) { *qtype = list[i].type; return ARES_TRUE; } diff --git a/src/lib/record/ares_dns_multistring.c b/src/lib/record/ares_dns_multistring.c index bff5afb9..aaa0c17a 100644 --- a/src/lib/record/ares_dns_multistring.c +++ b/src/lib/record/ares_dns_multistring.c @@ -222,3 +222,74 @@ const unsigned char * *len = strs->cache_str_len; return strs->cache_str; } + +ares_status_t ares__dns_multistring_parse_buf(ares__buf_t *buf, + size_t remaining_len, + ares__dns_multistring_t **strs, + ares_bool_t validate_printable) +{ + unsigned char len; + ares_status_t status = ARES_EBADRESP; + size_t orig_len = ares__buf_len(buf); + + if (buf == NULL) { + return ARES_EFORMERR; + } + + if (remaining_len == 0) { + return ARES_EBADRESP; + } + + if (strs != NULL) { + *strs = ares__dns_multistring_create(); + if (*strs == NULL) { + return ARES_ENOMEM; + } + } + + while (orig_len - ares__buf_len(buf) < remaining_len) { + status = ares__buf_fetch_bytes(buf, &len, 1); + if (status != ARES_SUCCESS) { + break; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + if (len) { + /* When used by the _str() parser, it really needs to be validated to + * be a valid printable ascii string. Do that here */ + if (validate_printable && ares__buf_len(buf) >= len) { + size_t mylen; + const char *data = (const char *)ares__buf_peek(buf, &mylen); + if (!ares__str_isprint(data, len)) { + status = ARES_EBADSTR; + break; + } + } + + if (strs != NULL) { + unsigned char *data = NULL; + status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &data); + if (status != ARES_SUCCESS) { + break; + } + status = ares__dns_multistring_add_own(*strs, data, len); + if (status != ARES_SUCCESS) { + ares_free(data); + break; + } + } else { + status = ares__buf_consume(buf, len); + if (status != ARES_SUCCESS) { + break; + } + } + } + } + + if (status != ARES_SUCCESS && strs != NULL) { + ares__dns_multistring_destroy(*strs); + *strs = NULL; + } + + return status; +} + diff --git a/src/lib/record/ares_dns_multistring.h b/src/lib/record/ares_dns_multistring.h index d9aa7ae3..8760d791 100644 --- a/src/lib/record/ares_dns_multistring.h +++ b/src/lib/record/ares_dns_multistring.h @@ -26,6 +26,8 @@ #ifndef __ARES_DNS_MULTISTRING_H #define __ARES_DNS_MULTISTRING_H +#include "ares__buf.h" + struct ares__dns_multistring; typedef struct ares__dns_multistring ares__dns_multistring_t; @@ -47,4 +49,25 @@ const unsigned char * ares__dns_multistring_get_combined(ares__dns_multistring_t *strs, size_t *len); +/*! Parse an array of character strings as defined in RFC1035, as binary, + * however, for convenience this does guarantee a NULL terminator (that is + * not included in the length for each value). + * + * \param[in] buf initialized buffer object + * \param[in] remaining_len maximum length that should be used for + * parsing the string, this is often less than + * the remaining buffer and is based on the RR + * record length. + * \param[out] strs Pointer passed by reference to be filled in + * with + * the array of values. + * \param[out] validate_printable Validate the strings contain only printable + * data. + * \return ARES_SUCCESS on success + */ +ares_status_t ares__dns_multistring_parse_buf(ares__buf_t *buf, + size_t remaining_len, + ares__dns_multistring_t **strs, + ares_bool_t validate_printable); + #endif diff --git a/src/lib/record/ares_dns_name.c b/src/lib/record/ares_dns_name.c index a437553b..773d06e5 100644 --- a/src/lib/record/ares_dns_name.c +++ b/src/lib/record/ares_dns_name.c @@ -114,7 +114,7 @@ static const ares_nameoffset_t *ares__nameoffset_find(ares__llist_t *list, /* Due to DNS 0x20, lets not inadvertently mangle things, use case-sensitive * matching instead of case-insensitive. This may result in slightly * larger DNS queries overall. */ - if (strcmp(val->name, name + prefix_len) != 0) { + if (!ares_streq(val->name, name + prefix_len)) { continue; } diff --git a/src/lib/record/ares_dns_parse.c b/src/lib/record/ares_dns_parse.c index 57cb0f71..c9b7bc53 100644 --- a/src/lib/record/ares_dns_parse.c +++ b/src/lib/record/ares_dns_parse.c @@ -95,7 +95,8 @@ static ares_status_t ares_status_t status; ares__dns_multistring_t *strs = NULL; - status = ares__buf_parse_dns_abinstr(buf, max_len, &strs, validate_printable); + status = ares__dns_multistring_parse_buf(buf, max_len, &strs, + validate_printable); if (status != ARES_SUCCESS) { return status; } diff --git a/src/lib/str/ares__buf.c b/src/lib/str/ares__buf.c index 30cc1109..36334a06 100644 --- a/src/lib/str/ares__buf.c +++ b/src/lib/str/ares__buf.c @@ -941,76 +941,6 @@ ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx) return ARES_SUCCESS; } -ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf, - size_t remaining_len, - ares__dns_multistring_t **strs, - ares_bool_t validate_printable) -{ - unsigned char len; - ares_status_t status = ARES_EBADRESP; - size_t orig_len = ares__buf_len(buf); - - if (buf == NULL) { - return ARES_EFORMERR; - } - - if (remaining_len == 0) { - return ARES_EBADRESP; - } - - if (strs != NULL) { - *strs = ares__dns_multistring_create(); - if (*strs == NULL) { - return ARES_ENOMEM; - } - } - - while (orig_len - ares__buf_len(buf) < remaining_len) { - status = ares__buf_fetch_bytes(buf, &len, 1); - if (status != ARES_SUCCESS) { - break; /* LCOV_EXCL_LINE: DefensiveCoding */ - } - - if (len) { - /* When used by the _str() parser, it really needs to be validated to - * be a valid printable ascii string. Do that here */ - if (validate_printable && ares__buf_len(buf) >= len) { - size_t mylen; - const char *data = (const char *)ares__buf_peek(buf, &mylen); - if (!ares__str_isprint(data, len)) { - status = ARES_EBADSTR; - break; - } - } - - if (strs != NULL) { - unsigned char *data = NULL; - status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &data); - if (status != ARES_SUCCESS) { - break; - } - status = ares__dns_multistring_add_own(*strs, data, len); - if (status != ARES_SUCCESS) { - ares_free(data); - break; - } - } else { - status = ares__buf_consume(buf, len); - if (status != ARES_SUCCESS) { - break; - } - } - } - } - - if (status != ARES_SUCCESS && strs != NULL) { - ares__dns_multistring_destroy(*strs); - *strs = NULL; - } - - return status; -} - static ares_status_t ares__buf_parse_dns_binstr_int(ares__buf_t *buf, size_t remaining_len, unsigned char **bin, size_t *bin_len, diff --git a/src/lib/str/ares_str.c b/src/lib/str/ares_str.c index ade61041..b79329b8 100644 --- a/src/lib/str/ares_str.c +++ b/src/lib/str/ares_str.c @@ -286,3 +286,168 @@ ares_bool_t ares__str_isprint(const char *str, size_t len) } return ARES_TRUE; } + +int ares_strcmp(const char *a, const char *b) +{ + if (a == NULL && b == NULL) { + return 0; + } + + if (a != NULL && b == NULL) { + if (*a == 0) { + return 0; + } + return 1; + } + + if (a == NULL && b != NULL) { + if (*b == 0) { + return 0; + } + return -1; + } + + return strcmp(a, b); +} + +int ares_strncmp(const char *a, const char *b, size_t n) +{ + if (n == 0) { + return 0; + } + + if (a == NULL && b == NULL) { + return 0; + } + + if (a != NULL && b == NULL) { + if (*a == 0) { + return 0; + } + return 1; + } + + if (a == NULL && b != NULL) { + if (*b == 0) { + return 0; + } + return -1; + } + + return strncmp(a, b, n); +} + +int ares_strcasecmp(const char *a, const char *b) +{ + if (a == NULL && b == NULL) { + return 0; + } + + if (a != NULL && b == NULL) { + if (*a == 0) { + return 0; + } + return 1; + } + + if (a == NULL && b != NULL) { + if (*b == 0) { + return 0; + } + return -1; + } + +# if defined(HAVE_STRCASECMP) + return strcasecmp(a, b); +# elif defined(HAVE_STRCMPI) + return strcmpi(a, b); +# elif defined(HAVE_STRICMP) + return stricmp(a, b); +# else + { + size_t i; + + for (i = 0; i < (size_t)-1; i++) { + int c1 = ares__tolower(a[i]); + int c2 = ares__tolower(b[i]); + if (c1 != c2) { + return c1 - c2; + } + if (!c1) { + break; + } + } + } + return 0; +# endif +} + +int ares_strncasecmp(const char *a, const char *b, size_t n) +{ + if (n == 0) { + return 0; + } + + if (a == NULL && b == NULL) { + return 0; + } + + if (a != NULL && b == NULL) { + if (*a == 0) { + return 0; + } + return 1; + } + + if (a == NULL && b != NULL) { + if (*b == 0) { + return 0; + } + return -1; + } + +# if defined(HAVE_STRNCASECMP) + return strncasecmp(a,b,n); +# elif defined(HAVE_STRNCMPI) + return strncmpi(a, b, n); +# elif defined(HAVE_STRNICMP) + return strnicmp(a, b, n); +# else + { + size_t i; + + for (i = 0; i < n; i++) { + int c1 = ares__tolower(a[i]); + int c2 = ares__tolower(b[i]); + if (c1 != c2) { + return c1 - c2; + } + if (!c1) { + break; + } + } + } + return 0; +# endif +} + +ares_bool_t ares_strcaseeq(const char *a, const char *b) +{ + return ares_strcasecmp(a,b) == 0?ARES_TRUE:ARES_FALSE; +} + +ares_bool_t ares_strcaseeq_max(const char *a, const char *b, size_t n) +{ + return ares_strncasecmp(a,b,n) == 0?ARES_TRUE:ARES_FALSE; +} + +ares_bool_t ares_streq(const char *a, const char *b) +{ + return ares_strcmp(a,b) == 0?ARES_TRUE:ARES_FALSE; +} + +ares_bool_t ares_streq_max(const char *a, const char *b, size_t n) +{ + return ares_strncmp(a,b,n) == 0?ARES_TRUE:ARES_FALSE; +} + diff --git a/src/lib/str/ares_str.h b/src/lib/str/ares_str.h deleted file mode 100644 index 440758c2..00000000 --- a/src/lib/str/ares_str.h +++ /dev/null @@ -1,89 +0,0 @@ -/* MIT License - * - * Copyright (c) 1998 Massachusetts Institute of Technology - * Copyright (c) The c-ares project and its contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * SPDX-License-Identifier: MIT - */ -#ifndef __ARES_STR_H -#define __ARES_STR_H - -char *ares_strdup(const char *s1); - -size_t ares_strlen(const char *str); - -/*! Copy string from source to destination with destination buffer size - * provided. The destination is guaranteed to be null terminated, if the - * provided buffer isn't large enough, only those bytes from the source that - * will fit will be copied. - * - * \param[out] dest Destination buffer - * \param[in] src Source to copy - * \param[in] dest_size Size of destination buffer - * \return String length. Will be at most dest_size-1 - */ -size_t ares_strcpy(char *dest, const char *src, size_t dest_size); - -ares_bool_t ares_str_isnum(const char *str); - -void ares__str_ltrim(char *str); -void ares__str_rtrim(char *str); -void ares__str_trim(char *str); - -unsigned char ares__tolower(unsigned char c); -ares_bool_t ares__memeq_ci(const unsigned char *ptr, const unsigned char *val, - size_t len); - -ares_bool_t ares__isspace(int ch); -ares_bool_t ares__isprint(int ch); -ares_bool_t ares__is_hostnamech(int ch); - -ares_bool_t ares__is_hostname(const char *str); - -/*! Validate the string provided is printable. The length specified must be - * at least the size of the buffer provided. If a NULL-terminator is hit - * before the length provided is hit, this will not be considered a valid - * printable string. This does not validate that the string is actually - * NULL terminated. - * - * \param[in] str Buffer containing string to evaluate. - * \param[in] len Number of characters to evaluate within provided buffer. - * If 0, will return TRUE since it did not hit an exception. - * \return ARES_TRUE if the entire string is printable, ARES_FALSE if not. - */ -ares_bool_t ares__str_isprint(const char *str, size_t len); - -/* We only care about ASCII rules */ -#define ares__isascii(x) (((unsigned char)x) <= 127) -#define ares__isdigit(x) \ - (((unsigned char)x) >= '0' && ((unsigned char)x) <= '9') -#define ares__isxdigit(x) \ - (ares__isdigit(x) || \ - (((unsigned char)x) >= 'a' && ((unsigned char)x) <= 'f') || \ - (((unsigned char)x) >= 'A' && ((unsigned char)x) <= 'F')) -#define ares__isupper(x) \ - (((unsigned char)x) >= 'A' && ((unsigned char)x) <= 'Z') -#define ares__islower(x) \ - (((unsigned char)x) >= 'a' && ((unsigned char)x) <= 'z') -#define ares__isalpha(x) (ares__islower(x) || ares__isupper(x)) - -#endif /* __ARES_STR_H */ diff --git a/src/lib/str/ares_strcasecmp.c b/src/lib/str/ares_strcasecmp.c deleted file mode 100644 index 76b835fd..00000000 --- a/src/lib/str/ares_strcasecmp.c +++ /dev/null @@ -1,79 +0,0 @@ -/* MIT License - * - * Copyright (c) 1998 Massachusetts Institute of Technology - * Copyright (c) The c-ares project and its contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * SPDX-License-Identifier: MIT - */ - -#include "ares_private.h" -#include "ares_strcasecmp.h" - -#ifndef HAVE_STRCASECMP -int ares_strcasecmp(const char *a, const char *b) -{ -# if defined(HAVE_STRCMPI) - return strcmpi(a, b); -# elif defined(HAVE_STRICMP) - return stricmp(a, b); -# else - size_t i; - - for (i = 0; i < (size_t)-1; i++) { - int c1 = ares__tolower(a[i]); - int c2 = ares__tolower(b[i]); - if (c1 != c2) { - return c1 - c2; - } - if (!c1) { - break; - } - } - return 0; -# endif -} -#endif - -#ifndef HAVE_STRNCASECMP -int ares_strncasecmp(const char *a, const char *b, size_t n) -{ -# if defined(HAVE_STRNCMPI) - return strncmpi(a, b, n); -# elif defined(HAVE_STRNICMP) - return strnicmp(a, b, n); -# else - size_t i; - - for (i = 0; i < n; i++) { - int c1 = ares__tolower(a[i]); - int c2 = ares__tolower(b[i]); - if (c1 != c2) { - return c1 - c2; - } - if (!c1) { - break; - } - } - return 0; -# endif -} -#endif diff --git a/src/lib/util/ares__iface_ips.c b/src/lib/util/ares__iface_ips.c index 56dc2579..efc44525 100644 --- a/src/lib/util/ares__iface_ips.c +++ b/src/lib/util/ares__iface_ips.c @@ -334,7 +334,7 @@ static ares_bool_t name_match(const char *name, const char *adapter_name, return ARES_TRUE; } - if (strcasecmp(name, adapter_name) == 0) { + if (ares_strcaseeq(name, adapter_name)) { return ARES_TRUE; } @@ -515,7 +515,7 @@ static ares_status_t ares__iface_ips_enumerate(ares__iface_ips_t *ips, } /* Name mismatch */ - if (name != NULL && strcasecmp(ifa->ifa_name, name) != 0) { + if (name != NULL && !ares_strcaseeq(ifa->ifa_name, name)) { continue; } diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index e23d0f23..7a6a8de9 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -11,6 +11,7 @@ IF (CARES_BUILD_TOOLS) PUBLIC "$" "$" "$" + "$" "$" "$" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" @@ -39,6 +40,7 @@ IF (CARES_BUILD_TOOLS) PUBLIC "$" "$" "$" + "$" "$" "$" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index ba7a672f..e2d04a44 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -16,6 +16,7 @@ AM_CPPFLAGS += -I$(top_builddir)/include \ -I$(top_builddir)/src/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib/include \ -DCARES_NO_DEPRECATED include Makefile.inc diff --git a/src/tools/Makefile.inc b/src/tools/Makefile.inc index 4c6b6aaa..088c7d4e 100644 --- a/src/tools/Makefile.inc +++ b/src/tools/Makefile.inc @@ -1,7 +1,5 @@ # Copyright (C) The c-ares project and its contributors # SPDX-License-Identifier: MIT -SAMPLESOURCES = ares_getopt.c \ - ../lib/str/ares_strcasecmp.c +SAMPLESOURCES = ares_getopt.c -SAMPLEHEADERS = ares_getopt.h \ - ../lib/str/ares_strcasecmp.h +SAMPLEHEADERS = ares_getopt.h diff --git a/src/tools/adig.c b/src/tools/adig.c index 8b2ad2e9..4688dc56 100644 --- a/src/tools/adig.c +++ b/src/tools/adig.c @@ -44,21 +44,7 @@ #include "ares.h" #include "ares_dns.h" - -#ifndef HAVE_STRDUP -# include "str/ares_str.h" -# define strdup(ptr) ares_strdup(ptr) -#endif - -#ifndef HAVE_STRCASECMP -# include "str/ares_strcasecmp.h" -# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2) -#endif - -#ifndef HAVE_STRNCASECMP -# include "str/ares_strcasecmp.h" -# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n) -#endif +#include "ares_str.h" #include "ares_getopt.h" @@ -99,7 +85,7 @@ static int lookup_flag(const nv_t *nv, size_t num_nv, const char *name) } for (i = 0; i < num_nv; i++) { - if (strcasecmp(nv[i].name, name) == 0) { + if (ares_strcaseeq(nv[i].name, name)) { return nv[i].value; } } diff --git a/src/tools/ahost.c b/src/tools/ahost.c index 73f29002..7d1d4a86 100644 --- a/src/tools/ahost.c +++ b/src/tools/ahost.c @@ -42,20 +42,7 @@ #include "ares_getopt.h" #include "ares_ipv6.h" -#ifndef HAVE_STRDUP -# include "str/ares_str.h" -# define strdup(ptr) ares_strdup(ptr) -#endif - -#ifndef HAVE_STRCASECMP -# include "str/ares_strcasecmp.h" -# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2) -#endif - -#ifndef HAVE_STRNCASECMP -# include "str/ares_strcasecmp.h" -# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n) -#endif +#include "ares_str.h" static void callback(void *arg, int status, int timeouts, struct hostent *host); static void ai_callback(void *arg, int status, int timeouts, @@ -111,11 +98,11 @@ int main(int argc, char **argv) options.domains[options.ndomains - 1] = strdup(state.optarg); break; case 't': - if (!strcasecmp(state.optarg, "a")) { + if (ares_strcaseeq(state.optarg, "a")) { addr_family = AF_INET; - } else if (!strcasecmp(state.optarg, "aaaa")) { + } else if (ares_strcaseeq(state.optarg, "aaaa")) { addr_family = AF_INET6; - } else if (!strcasecmp(state.optarg, "u")) { + } else if (ares_strcaseeq(state.optarg, "u")) { addr_family = AF_UNSPEC; } else { usage(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8bed6018..16024ed5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,6 +26,7 @@ target_include_directories(caresinternal "${PROJECT_BINARY_DIR}/src/lib" "${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/src/lib" + "${PROJECT_SOURCE_DIR}/src/lib/include" "${PROJECT_SOURCE_DIR}/include" ) diff --git a/test/Makefile.am b/test/Makefile.am index 01a8bc30..63d3ac80 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -2,12 +2,13 @@ # SPDX-License-Identifier: MIT AUTOMAKE_OPTIONS = foreign subdir-objects nostdinc 1.9.6 -AM_CPPFLAGS += -I$(top_builddir)/include \ - -I$(top_builddir)/src/lib \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/test \ - -I$(top_builddir)/test \ +AM_CPPFLAGS += -I$(top_builddir)/include \ + -I$(top_builddir)/src/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib/include \ + -I$(top_srcdir)/test \ + -I$(top_builddir)/test \ -I$(top_builddir) -DCARES_NO_DEPRECATED AM_CXXFLAGS := diff --git a/test/Makefile.m32 b/test/Makefile.m32 index 326ac67f..5227f98f 100644 --- a/test/Makefile.m32 +++ b/test/Makefile.m32 @@ -19,7 +19,7 @@ ARES_SRC_DIR = .. # Where to find the built c-ares static library ARES_BLD_DIR = .. ARESLIB = $(ARES_BLD_DIR)/src/lib/libcares.a -CPPFLAGS = -I$(ARES_SRC_DIR)/include -I$(ARES_SRC_DIR)/src/lib -I$(GTEST_ROOT)/include -DCARES_STATICLIB -DCARES_NO_DEPRECATED +CPPFLAGS = -I$(ARES_SRC_DIR)/include -I$(ARES_SRC_DIR)/src/lib -I$(ARES_SRC_DIR)/src/lib/include -I$(GTEST_ROOT)/include -DCARES_STATICLIB -DCARES_NO_DEPRECATED CXXFLAGS = -Wall $(PTHREAD_CFLAGS) -std=gnu++14 LDFLAGS = LDLIBS = -lws2_32 -liphlpapi diff --git a/test/Makefile.msvc b/test/Makefile.msvc index 9c81b6c1..803ea382 100644 --- a/test/Makefile.msvc +++ b/test/Makefile.msvc @@ -150,7 +150,7 @@ EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2 /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS /RTCsu -CC_CFLAGS = $(CFLAGS) /I. /I../src/lib /I../include /I $(GTEST_ROOT)/include /W3 /EHsc /FD +CC_CFLAGS = $(CFLAGS) /I. /I../src/lib /I../src/lib/include /I../include /I $(GTEST_ROOT)/include /W3 /EHsc /FD RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG" RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG" diff --git a/test/ares-test-internal.cc b/test/ares-test-internal.cc index 846839f6..7093d781 100644 --- a/test/ares-test-internal.cc +++ b/test/ares-test-internal.cc @@ -71,9 +71,7 @@ void CheckPtoN4(int size, unsigned int value, const char *input) { << " for input " << input; EXPECT_EQ(expected, a4.s_addr) << " for input " << input; } -#endif -#ifndef CARES_SYMBOL_HIDING TEST_F(LibraryTest, Strsplit) { using std::vector; using std::string; @@ -112,15 +110,11 @@ TEST_F(LibraryTest, Strsplit) { ares__strsplit_free(out, n); } } -#endif -TEST_F(LibraryTest, InetPtoN) { +TEST_F(LibraryTest, InetNetPtoN) { + uint32_t expected; struct in_addr a4; struct in6_addr a6; - -#ifndef CARES_SYMBOL_HIDING - uint32_t expected; - CheckPtoN4(4 * 8, 0x01020304, "1.2.3.4"); CheckPtoN4(4 * 8, 0x81010101, "129.1.1.1"); CheckPtoN4(4 * 8, 0xC0010101, "192.1.1.1"); @@ -220,8 +214,137 @@ TEST_F(LibraryTest, InetPtoN) { EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "0x0xyz", &a4, 0)); EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "0x1122334", &a4, sizeof(a4) - 1)); EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "253", &a4, sizeof(a4) - 1)); -#endif +} + +TEST_F(LibraryTest, FreeLongChain) { + struct ares_addr_node *data = nullptr; + for (int ii = 0; ii < 100000; ii++) { + struct ares_addr_node *prev = (struct ares_addr_node*)ares_malloc_data(ARES_DATATYPE_ADDR_NODE); + prev->next = data; + data = prev; + } + + ares_free_data(data); +} + +TEST_F(LibraryTest, MallocDataFail) { + EXPECT_EQ(nullptr, ares_malloc_data((ares_datatype)99)); + SetAllocSizeFail(sizeof(struct ares_data)); + EXPECT_EQ(nullptr, ares_malloc_data(ARES_DATATYPE_MX_REPLY)); +} + +TEST(Misc, OnionDomain) { + EXPECT_EQ(0, ares__is_onion_domain("onion.no")); + EXPECT_EQ(0, ares__is_onion_domain(".onion.no")); + EXPECT_EQ(1, ares__is_onion_domain(".onion")); + EXPECT_EQ(1, ares__is_onion_domain(".onion.")); + EXPECT_EQ(1, ares__is_onion_domain("yes.onion")); + EXPECT_EQ(1, ares__is_onion_domain("yes.onion.")); + EXPECT_EQ(1, ares__is_onion_domain("YES.ONION")); + EXPECT_EQ(1, ares__is_onion_domain("YES.ONION.")); +} + +TEST_F(LibraryTest, CatDomain) { + char *s; + + ares__cat_domain("foo", "example.net", &s); + EXPECT_STREQ("foo.example.net", s); + ares_free(s); + + ares__cat_domain("foo", ".", &s); + EXPECT_STREQ("foo.", s); + ares_free(s); + + ares__cat_domain("foo", "example.net.", &s); + EXPECT_STREQ("foo.example.net.", s); + ares_free(s); +} + +TEST_F(LibraryTest, SlistMisuse) { + EXPECT_EQ(NULL, ares__slist_create(NULL, NULL, NULL)); + ares__slist_replace_destructor(NULL, NULL); + EXPECT_EQ(NULL, ares__slist_insert(NULL, NULL)); + EXPECT_EQ(NULL, ares__slist_node_find(NULL, NULL)); + EXPECT_EQ(NULL, ares__slist_node_first(NULL)); + EXPECT_EQ(NULL, ares__slist_node_last(NULL)); + EXPECT_EQ(NULL, ares__slist_node_next(NULL)); + EXPECT_EQ(NULL, ares__slist_node_prev(NULL)); + EXPECT_EQ(NULL, ares__slist_node_val(NULL)); + EXPECT_EQ((size_t)0, ares__slist_len(NULL)); + EXPECT_EQ(NULL, ares__slist_node_parent(NULL)); + EXPECT_EQ(NULL, ares__slist_first_val(NULL)); + EXPECT_EQ(NULL, ares__slist_last_val(NULL)); + EXPECT_EQ(NULL, ares__slist_node_claim(NULL)); +} + +TEST_F(LibraryTest, IfaceIPs) { + ares_status_t status; + ares__iface_ips_t *ips = NULL; + size_t i; + + status = ares__iface_ips(&ips, ARES_IFACE_IP_DEFAULT, NULL); + EXPECT_TRUE(status == ARES_SUCCESS || status == ARES_ENOTIMP); + /* Not implemented, can't run tests */ + if (status == ARES_ENOTIMP) + return; + + EXPECT_NE(nullptr, ips); + + for (i=0; inext = data; - data = prev; - } - - ares_free_data(data); -} - TEST(LibraryInit, StrdupFailures) { EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL)); char* copy = ares_strdup("string"); @@ -277,12 +388,6 @@ TEST_F(LibraryTest, StrdupFailures) { EXPECT_EQ(nullptr, copy); } -TEST_F(LibraryTest, MallocDataFail) { - EXPECT_EQ(nullptr, ares_malloc_data((ares_datatype)99)); - SetAllocSizeFail(sizeof(struct ares_data)); - EXPECT_EQ(nullptr, ares_malloc_data(ARES_DATATYPE_MX_REPLY)); -} - TEST_F(FileChannelTest, GetAddrInfoHostsPositive) { TempFile hostsfile("1.2.3.4 example.com \n" " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" @@ -393,19 +498,6 @@ TEST_F(FileChannelTest, GetAddrInfoAllocFail) { } } -TEST(Misc, OnionDomain) { - EXPECT_EQ(0, ares__is_onion_domain("onion.no")); - EXPECT_EQ(0, ares__is_onion_domain(".onion.no")); - EXPECT_EQ(1, ares__is_onion_domain(".onion")); - EXPECT_EQ(1, ares__is_onion_domain(".onion.")); - EXPECT_EQ(1, ares__is_onion_domain("yes.onion")); - EXPECT_EQ(1, ares__is_onion_domain("yes.onion.")); - EXPECT_EQ(1, ares__is_onion_domain("YES.ONION")); - EXPECT_EQ(1, ares__is_onion_domain("YES.ONION.")); -} - -#endif - TEST_F(LibraryTest, DNSRecord) { ares_dns_record_t *dnsrec = NULL; ares_dns_rr_t *rr = NULL; @@ -677,13 +769,11 @@ TEST_F(LibraryTest, DNSRecord) { /* Write */ EXPECT_EQ(ARES_SUCCESS, ares_dns_write(dnsrec, &msg, &msglen)); -#ifndef CARES_SYMBOL_HIDING ares__buf_t *hexdump = ares__buf_create(); EXPECT_EQ(ARES_SUCCESS, ares__buf_hexdump(hexdump, msg, msglen)); char *hexdata = ares__buf_finish_str(hexdump, NULL); //printf("HEXDUMP\n%s", hexdata); ares_free(hexdata); -#endif ares_dns_record_destroy(dnsrec); dnsrec = NULL; @@ -699,7 +789,6 @@ TEST_F(LibraryTest, DNSRecord) { EXPECT_EQ(nscount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_AUTHORITY)); EXPECT_EQ(arcount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ADDITIONAL)); -#ifndef CARES_SYMBOL_HIDING /* Iterate and print */ ares__buf_t *printmsg = ares__buf_create(); ares__buf_append_str(printmsg, ";; ->>HEADER<<- opcode: "); @@ -817,7 +906,6 @@ TEST_F(LibraryTest, DNSRecord) { char *printdata = ares__buf_finish_str(printmsg, NULL); //printf("%s", printdata); ares_free(printdata); -#endif ares_dns_record_destroy(dnsrec); ares_free_string(msg); @@ -983,24 +1071,6 @@ TEST_F(LibraryTest, DNSParseFlags) { ares_free_string(msg); msg = NULL; } -#ifndef CARES_SYMBOL_HIDING - -TEST_F(LibraryTest, CatDomain) { - char *s; - - ares__cat_domain("foo", "example.net", &s); - EXPECT_STREQ("foo.example.net", s); - ares_free(s); - - ares__cat_domain("foo", ".", &s); - EXPECT_STREQ("foo.", s); - ares_free(s); - - ares__cat_domain("foo", "example.net.", &s); - EXPECT_STREQ("foo.example.net.", s); - ares_free(s); -} - TEST_F(LibraryTest, ArrayMisuse) { EXPECT_EQ(NULL, ares__array_create(0, NULL)); ares__array_destroy(NULL); @@ -1043,18 +1113,9 @@ TEST_F(LibraryTest, BufMisuse) { EXPECT_EQ(ARES_FALSE, ares__buf_begins_with(NULL, NULL, 0)); EXPECT_EQ((size_t)0, ares__buf_get_position(NULL)); EXPECT_NE(ARES_SUCCESS, ares__buf_set_position(NULL, 0)); - EXPECT_NE(ARES_SUCCESS, ares__dns_name_parse(NULL, NULL, ARES_FALSE)); EXPECT_NE(ARES_SUCCESS, ares__buf_parse_dns_binstr(NULL, 0, NULL, NULL)); } -TEST_F(LibraryTest, HtableMisuse) { - EXPECT_EQ(NULL, ares__htable_create(NULL, NULL, NULL, NULL)); - EXPECT_EQ(ARES_FALSE, ares__htable_insert(NULL, NULL)); - EXPECT_EQ(NULL, ares__htable_get(NULL, NULL)); - EXPECT_EQ(ARES_FALSE, ares__htable_remove(NULL, NULL)); - EXPECT_EQ((size_t)0, ares__htable_num_keys(NULL)); -} - TEST_F(LibraryTest, HtableAsvpMisuse) { EXPECT_EQ(ARES_FALSE, ares__htable_asvp_insert(NULL, ARES_SOCKET_BAD, NULL)); EXPECT_EQ(ARES_FALSE, ares__htable_asvp_get(NULL, ARES_SOCKET_BAD, NULL)); @@ -1096,23 +1157,6 @@ TEST_F(LibraryTest, LlistMisuse) { ares__llist_node_replace(NULL, NULL); } -TEST_F(LibraryTest, SlistMisuse) { - EXPECT_EQ(NULL, ares__slist_create(NULL, NULL, NULL)); - ares__slist_replace_destructor(NULL, NULL); - EXPECT_EQ(NULL, ares__slist_insert(NULL, NULL)); - EXPECT_EQ(NULL, ares__slist_node_find(NULL, NULL)); - EXPECT_EQ(NULL, ares__slist_node_first(NULL)); - EXPECT_EQ(NULL, ares__slist_node_last(NULL)); - EXPECT_EQ(NULL, ares__slist_node_next(NULL)); - EXPECT_EQ(NULL, ares__slist_node_prev(NULL)); - EXPECT_EQ(NULL, ares__slist_node_val(NULL)); - EXPECT_EQ((size_t)0, ares__slist_len(NULL)); - EXPECT_EQ(NULL, ares__slist_node_parent(NULL)); - EXPECT_EQ(NULL, ares__slist_first_val(NULL)); - EXPECT_EQ(NULL, ares__slist_last_val(NULL)); - EXPECT_EQ(NULL, ares__slist_node_claim(NULL)); -} - typedef struct { unsigned int id; ares__buf_t *buf; @@ -1453,65 +1497,6 @@ TEST_F(LibraryTest, HtableStrvp) { ares__htable_strvp_destroy(h); } -TEST_F(LibraryTest, IfaceIPs) { - ares_status_t status; - ares__iface_ips_t *ips = NULL; - size_t i; - - status = ares__iface_ips(&ips, ARES_IFACE_IP_DEFAULT, NULL); - EXPECT_TRUE(status == ARES_SUCCESS || status == ARES_ENOTIMP); - - /* Not implemented, can't run tests */ - if (status == ARES_ENOTIMP) - return; - - EXPECT_NE(nullptr, ips); - - for (i=0; iservers; channel_->servers = NULL;