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)
pull/863/head
Brad House 3 months ago committed by GitHub
parent 538a4866be
commit 7f19f162db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      .reuse/dep5
  2. 3
      Makefile.Watcom
  3. 2
      Makefile.dj
  4. 2
      Makefile.m32
  5. 11
      Makefile.msvc
  6. 2
      src/lib/CMakeLists.txt
  7. 3
      src/lib/Makefile.am
  8. 19
      src/lib/Makefile.inc
  9. 4
      src/lib/ares__hosts_file.c
  10. 4
      src/lib/ares__parse_into_addrinfo.c
  11. 4
      src/lib/ares_getaddrinfo.c
  12. 40
      src/lib/ares_library_init.c
  13. 2
      src/lib/ares_platform.c
  14. 34
      src/lib/ares_private.h
  15. 4
      src/lib/ares_process.c
  16. 4
      src/lib/ares_search.c
  17. 38
      src/lib/ares_sysconfig_files.c
  18. 2
      src/lib/ares_sysconfig_mac.c
  19. 9
      src/lib/dsa/ares__htable_strvp.c
  20. 4
      src/lib/event/ares_event_configchg.c
  21. 8
      src/lib/include/README.md
  22. 49
      src/lib/include/ares__array.h
  23. 157
      src/lib/include/ares__buf.h
  24. 22
      src/lib/include/ares__htable_asvp.h
  25. 18
      src/lib/include/ares__htable_strvp.h
  26. 22
      src/lib/include/ares__htable_szvp.h
  27. 20
      src/lib/include/ares__htable_vpvp.h
  28. 57
      src/lib/include/ares__llist.h
  29. 20
      src/lib/include/ares_mem.h
  30. 185
      src/lib/include/ares_str.h
  31. 2
      src/lib/legacy/ares_parse_ptr_reply.c
  32. 4
      src/lib/record/ares_dns_mapping.c
  33. 71
      src/lib/record/ares_dns_multistring.c
  34. 23
      src/lib/record/ares_dns_multistring.h
  35. 2
      src/lib/record/ares_dns_name.c
  36. 3
      src/lib/record/ares_dns_parse.c
  37. 70
      src/lib/str/ares__buf.c
  38. 165
      src/lib/str/ares_str.c
  39. 89
      src/lib/str/ares_str.h
  40. 79
      src/lib/str/ares_strcasecmp.c
  41. 4
      src/lib/util/ares__iface_ips.c
  42. 2
      src/tools/CMakeLists.txt
  43. 1
      src/tools/Makefile.am
  44. 6
      src/tools/Makefile.inc
  45. 18
      src/tools/adig.c
  46. 21
      src/tools/ahost.c
  47. 1
      test/CMakeLists.txt
  48. 1
      test/Makefile.am
  49. 2
      test/Makefile.m32
  50. 2
      test/Makefile.msvc
  51. 279
      test/ares-test-internal.cc

@ -9,7 +9,7 @@ Copyright: The c-ares project and its contributors.
License: MIT License: MIT
# Docs # 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. Copyright: The c-ares project and its contributors.
License: MIT License: MIT

@ -43,7 +43,8 @@ CP = copy
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm -aa & CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm -aa &
-wcd=201 -bt=nt -d+ -dCARES_BUILDING_LIBRARY & -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 LFLAGS = option quiet, map, caseexact, eliminate

@ -23,7 +23,7 @@ VPATH = src/lib src/tools
WATT32_ROOT = $(realpath $(WATT_ROOT)) WATT32_ROOT = $(realpath $(WATT_ROOT))
WATT32_LIB = $(WATT32_ROOT)/lib/libwatt.a 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 \ -I$(WATT32_ROOT)/inc \
-Wall \ -Wall \
-Wextra \ -Wextra \

@ -19,7 +19,7 @@ RANLIB = $(CROSSPREFIX)ranlib
#RM = rm -f #RM = rm -f
CP = cp -afv 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 CFLAGS += -DCARES_STATICLIB
LDFLAGS = $(CARES_LDFLAG_EXTRAS) -s LDFLAGS = $(CARES_LDFLAG_EXTRAS) -s
LIBS = -lws2_32 -liphlpapi LIBS = -lws2_32 -liphlpapi

@ -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_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /RTCsu 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_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG" 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: {$(SRCDIR)\src\tools}.c{$(PROG3_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(PROG3_OBJDIR)\ /c $< $(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, # # Default target when no CFG library type has been specified, #

@ -53,6 +53,7 @@ IF (CARES_SHARED)
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/include"
) )
TARGET_COMPILE_DEFINITIONS (${PROJECT_NAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY) TARGET_COMPILE_DEFINITIONS (${PROJECT_NAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY)
@ -110,6 +111,7 @@ IF (CARES_STATIC)
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/include"
) )
TARGET_COMPILE_DEFINITIONS (${LIBNAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY) TARGET_COMPILE_DEFINITIONS (${LIBNAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY)

@ -11,7 +11,8 @@ ACLOCAL_AMFLAGS = -I m4 --install
AM_CPPFLAGS += -I$(top_builddir)/include \ AM_CPPFLAGS += -I$(top_builddir)/include \
-I$(top_builddir)/src/lib \ -I$(top_builddir)/src/lib \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
-I$(top_srcdir)/src/lib -I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include
lib_LTLIBRARIES = libcares.la lib_LTLIBRARIES = libcares.la

@ -81,7 +81,6 @@ CSOURCES = ares__addrinfo2hostent.c \
record/ares_dns_record.c \ record/ares_dns_record.c \
record/ares_dns_write.c \ record/ares_dns_write.c \
str/ares__buf.c \ str/ares__buf.c \
str/ares_strcasecmp.c \
str/ares_str.c \ str/ares_str.c \
str/ares_strsplit.c \ str/ares_strsplit.c \
util/ares__iface_ips.c \ util/ares__iface_ips.c \
@ -98,23 +97,21 @@ HHEADERS = ares_android.h \
ares_platform.h \ ares_platform.h \
ares_private.h \ ares_private.h \
ares_setup.h \ ares_setup.h \
dsa/ares__array.h \
dsa/ares__htable.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 \ dsa/ares__slist.h \
event/ares_event.h \ event/ares_event.h \
event/ares_event_win32.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_multistring.h \
record/ares_dns_private.h \ record/ares_dns_private.h \
str/ares__buf.h \
str/ares_strcasecmp.h \
str/ares_str.h \
str/ares_strsplit.h \ str/ares_strsplit.h \
util/ares__iface_ips.h \ util/ares__iface_ips.h \
util/ares__threads.h \ util/ares__threads.h \
thirdparty/apple/dnsinfo.h thirdparty/apple/dnsinfo.h

@ -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; for (node = ares__llist_node_first(entry->ips); node != NULL;
node = ares__llist_node_next(node)) { node = ares__llist_node_next(node)) {
const char *myhost = ares__llist_node_val(node); const char *myhost = ares__llist_node_val(node);
if (strcasecmp(myhost, host) == 0) { if (ares_strcaseeq(myhost, host)) {
return ARES_TRUE; return ARES_TRUE;
} }
} }
@ -620,7 +620,7 @@ static ares_bool_t ares__hosts_expired(const char *filename,
} }
/* If filenames are different, its expired */ /* If filenames are different, its expired */
if (strcasecmp(hf->filename, filename) != 0) { if (!ares_strcaseeq(hf->filename, filename)) {
return ARES_TRUE; return ARES_TRUE;
} }

@ -90,7 +90,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
* *
* rname = ares_dns_rr_get_name(rr); * rname = ares_dns_rr_get_name(rr);
* if ((rtype == ARES_REC_TYPE_A || rtype == ARES_REC_TYPE_AAAA) && * if ((rtype == ARES_REC_TYPE_A || rtype == ARES_REC_TYPE_AAAA) &&
* strcasecmp(rname, hostname) != 0) { * !ares_strcaseeq(rname, hostname)) {
* continue; * continue;
* } * }
*/ */
@ -147,7 +147,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
} }
/* save the hostname as ai->name */ /* 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); ares_free(ai->name);
ai->name = ares_strdup(hostname); ai->name = ares_strdup(hostname);
if (ai->name == NULL) { if (ai->name == NULL) {

@ -371,7 +371,7 @@ ares_bool_t ares__is_localhost(const char *name)
return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
} }
if (strcmp(name, "localhost") == 0) { if (ares_strcaseeq(name, "localhost")) {
return ARES_TRUE; return ARES_TRUE;
} }
@ -380,7 +380,7 @@ ares_bool_t ares__is_localhost(const char *name)
return ARES_FALSE; return ARES_FALSE;
} }
if (strcmp(name + (len - 10 /* strlen(".localhost") */), ".localhost") == 0) { if (ares_strcaseeq(name + (len - 10 /* strlen(".localhost") */), ".localhost")) {
return ARES_TRUE; return ARES_TRUE;
} }

@ -52,8 +52,6 @@ static void *default_malloc(size_t size)
return malloc(size); return malloc(size);
} }
#if defined(_WIN32)
/* We need indirections to handle Windows DLL rules. */
static void *default_realloc(void *p, size_t size) static void *default_realloc(void *p, size_t size)
{ {
return realloc(p, size); return realloc(p, size);
@ -63,13 +61,25 @@ static void default_free(void *p)
{ {
free(p); free(p);
} }
#else
# define default_realloc realloc static void *(*__ares_malloc)(size_t size) = default_malloc;
# define default_free free static void *(*__ares_realloc)(void *ptr, size_t size) = default_realloc;
#endif static void (*__ares_free)(void *ptr) = default_free;
void *(*ares_malloc)(size_t size) = default_malloc;
void *(*ares_realloc)(void *ptr, size_t size) = default_realloc; void *ares_malloc(size_t size)
void (*ares_free)(void *ptr) = default_free; {
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) 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)) void *(*arealloc)(void *ptr, size_t size))
{ {
if (amalloc) { if (amalloc) {
ares_malloc = amalloc; __ares_malloc = amalloc;
} }
if (arealloc) { if (arealloc) {
ares_realloc = arealloc; __ares_realloc = arealloc;
} }
if (afree) { if (afree) {
ares_free = afree; __ares_free = afree;
} }
return ares_library_init(flags); return ares_library_init(flags);
} }
@ -143,9 +153,9 @@ void ares_library_cleanup(void)
#endif #endif
ares_init_flags = ARES_LIB_INIT_NONE; ares_init_flags = ARES_LIB_INIT_NONE;
ares_malloc = malloc; __ares_malloc = default_malloc;
ares_realloc = realloc; __ares_realloc = default_realloc;
ares_free = free; __ares_free = default_free;
} }
int ares_library_initialized(void) int ares_library_initialized(void)

@ -11032,7 +11032,7 @@ struct servent *getservbyport(int port, const char *proto)
if (!error) { if (!error) {
for (i = 0; i < (sizeof(IANAports) / sizeof(IANAports[0])) - 1; i++) { for (i = 0; i < (sizeof(IANAports) / sizeof(IANAports[0])) - 1; i++) {
if (u_port == IANAports[i].s_port) { 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]; return (struct servent *)&IANAports[i];
} }
} }

@ -100,20 +100,21 @@ W32_FUNC const char *_w32_GetHostsFile(void);
#endif #endif
#include "ares_mem.h"
#include "ares_ipv6.h" #include "ares_ipv6.h"
struct ares_rand_state; struct ares_rand_state;
typedef struct ares_rand_state ares_rand_state; typedef struct ares_rand_state ares_rand_state;
#include "dsa/ares__array.h" #include "ares__array.h"
#include "dsa/ares__llist.h" #include "ares__llist.h"
#include "dsa/ares__slist.h" #include "dsa/ares__slist.h"
#include "dsa/ares__htable_strvp.h" #include "ares__htable_strvp.h"
#include "dsa/ares__htable_szvp.h" #include "ares__htable_szvp.h"
#include "dsa/ares__htable_asvp.h" #include "ares__htable_asvp.h"
#include "dsa/ares__htable_vpvp.h" #include "ares__htable_vpvp.h"
#include "record/ares_dns_multistring.h" #include "record/ares_dns_multistring.h"
#include "str/ares__buf.h" #include "ares__buf.h"
#include "record/ares_dns_private.h" #include "record/ares_dns_private.h"
#include "util/ares__iface_ips.h" #include "util/ares__iface_ips.h"
#include "util/ares__threads.h" #include "util/ares__threads.h"
@ -123,19 +124,9 @@ typedef struct ares_rand_state ares_rand_state;
# define getenv(ptr) ares_getenv(ptr) # define getenv(ptr) ares_getenv(ptr)
#endif #endif
#include "str/ares_str.h" #include "ares_str.h"
#include "str/ares_strsplit.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 ******/ /********* EDNS defines section ******/
#define EDNSPACKETSZ \ #define EDNSPACKETSZ \
1232 /* Reasonable UDP payload size, as agreed by operators \ 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. */ /* Does the domain end in ".onion" or ".onion."? Case-insensitive. */
ares_bool_t ares__is_onion_domain(const char *name); 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 */ /* return true if now is exactly check time or later */
ares_bool_t ares__timedout(const ares_timeval_t *now, ares_bool_t ares__timedout(const ares_timeval_t *now,
const ares_timeval_t *check); const ares_timeval_t *check);

@ -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. * server to preserve the case of the name in the response packet.
* https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00 * https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00
*/ */
if (strcmp(qname, aname) != 0) { if (!ares_streq(qname, aname)) {
goto done; goto done;
} }
} else { } else {
/* without DNS0x20 use case-insensitive matching */ /* without DNS0x20 use case-insensitive matching */
if (strcasecmp(qname, aname) != 0) { if (!ares_strcaseeq(qname, aname)) {
goto done; goto done;
} }
} }

@ -474,7 +474,7 @@ ares_status_t ares__cat_domain(const char *name, const char *domain, char **s)
} }
memcpy(*s, name, nlen); memcpy(*s, name, nlen);
(*s)[nlen] = '.'; (*s)[nlen] = '.';
if (strcmp(domain, ".") == 0) { if (ares_streq(domain, ".")) {
/* Avoid appending the root domain to the separator, which would set *s to /* Avoid appending the root domain to the separator, which would set *s to
an ill-formed value (ending in two consecutive dots). */ an ill-formed value (ending in two consecutive dots). */
dlen = 0; dlen = 0;
@ -555,7 +555,7 @@ ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel,
} }
/* Match hostname */ /* Match hostname */
if (strcasecmp(hostname, name) != 0) { if (!ares_strcaseeq(hostname, name)) {
continue; continue;
} }

@ -346,12 +346,12 @@ static ares_status_t config_lookup(ares_sysconfig_t *sysconfig,
continue; continue;
} }
if (strcasecmp(value, "dns") == 0 || strcasecmp(value, "bind") == 0 || if (ares_strcaseeq(value, "dns") || ares_strcaseeq(value, "bind") ||
strcasecmp(value, "resolv") == 0 || strcasecmp(value, "resolve") == 0) { ares_strcaseeq(value, "resolv") || ares_strcaseeq(value, "resolve")) {
ch = 'b'; ch = 'b';
} else if (strcasecmp(value, "files") == 0 || } else if (ares_strcaseeq(value, "files") ||
strcasecmp(value, "file") == 0 || ares_strcaseeq(value, "file") ||
strcasecmp(value, "local") == 0) { ares_strcaseeq(value, "local")) {
ch = 'f'; ch = 'f';
} else { } else {
continue; continue;
@ -409,21 +409,21 @@ static ares_status_t process_option(ares_sysconfig_t *sysconfig,
valint = (unsigned int)strtoul(val, NULL, 10); valint = (unsigned int)strtoul(val, NULL, 10);
} }
if (strcmp(key, "ndots") == 0) { if (ares_streq(key, "ndots")) {
sysconfig->ndots = valint; 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) { if (valint == 0) {
return ARES_EFORMERR; return ARES_EFORMERR;
} }
sysconfig->timeout_ms = valint * 1000; 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) { if (valint == 0) {
return ARES_EFORMERR; return ARES_EFORMERR;
} }
sysconfig->tries = valint; sysconfig->tries = valint;
} else if (strcmp(key, "rotate") == 0) { } else if (ares_streq(key, "rotate")) {
sysconfig->rotate = ARES_TRUE; 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; 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 /* At this point we have a string option and a string value, both trimmed
* of leading and trailing whitespace. Lets try to evaluate them */ * 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 */ /* Domain is legacy, don't overwrite an existing config set by search */
if (sysconfig->domains == NULL) { if (sysconfig->domains == NULL) {
status = config_search(sysconfig, value, 1); status = config_search(sysconfig, value, 1);
} }
} else if (strcmp(option, "lookup") == 0 || } else if (ares_streq(option, "lookup") ||
strcmp(option, "hostresorder") == 0) { ares_streq(option, "hostresorder")) {
ares__buf_tag_rollback(line); ares__buf_tag_rollback(line);
status = config_lookup(sysconfig, line, " \t"); status = config_lookup(sysconfig, line, " \t");
} else if (strcmp(option, "search") == 0) { } else if (ares_streq(option, "search")) {
status = config_search(sysconfig, value, 0); status = config_search(sysconfig, value, 0);
} else if (strcmp(option, "nameserver") == 0) { } else if (ares_streq(option, "nameserver")) {
status = status =
ares__sconfig_append_fromstr(&sysconfig->sconfig, value, ARES_TRUE); 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 /* Ignore all failures except ENOMEM. If the sysadmin set a bad
* sortlist, just ignore the sortlist, don't cause an inoperable * sortlist, just ignore the sortlist, don't cause an inoperable
* channel */ * channel */
@ -613,7 +613,7 @@ static ares_status_t parse_resolvconf_line(ares_sysconfig_t *sysconfig,
if (status != ARES_ENOMEM) { if (status != ARES_ENOMEM) {
status = ARES_SUCCESS; status = ARES_SUCCESS;
} }
} else if (strcmp(option, "options") == 0) { } else if (ares_streq(option, "options")) {
status = ares__sysconfig_set_options(sysconfig, value); 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:" */ /* Only support "hosts:" */
if (strcmp(option, "hosts") != 0) { if (!ares_streq(option, "hosts")) {
goto done; goto done;
} }
@ -698,7 +698,7 @@ static ares_status_t parse_svcconf_line(ares_sysconfig_t *sysconfig,
} }
/* Only support "hosts=" */ /* Only support "hosts=" */
if (strcmp(option, "hosts") != 0) { if (!ares_streq(option, "hosts")) {
goto done; goto done;
} }

@ -154,7 +154,7 @@ static ares_bool_t search_is_duplicate(const ares_sysconfig_t *sysconfig,
{ {
size_t i; size_t i;
for (i = 0; i < sysconfig->ndomains; 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; return ARES_TRUE;
} }
} }

@ -74,14 +74,7 @@ static void bucket_free(void *bucket)
static ares_bool_t key_eq(const void *key1, const void *key2) static ares_bool_t key_eq(const void *key1, const void *key2)
{ {
const char *k1 = key1; return ares_strcaseeq(key1, key2);
const char *k2 = key2;
if (strcasecmp(k1, k2) == 0) {
return ARES_TRUE;
}
return ARES_FALSE;
} }
ares__htable_strvp_t * ares__htable_strvp_t *

@ -116,8 +116,8 @@ static void ares_event_configchg_cb(ares_event_thread_t *e, ares_socket_t fd,
continue; continue;
} }
if (strcasecmp(event->name, "resolv.conf") == 0 || if (ares_strcaseeq(event->name, "resolv.conf") ||
strcasecmp(event->name, "nsswitch.conf") == 0) { ares_strcaseeq(event->name, "nsswitch.conf")) {
triggered = ARES_TRUE; triggered = ARES_TRUE;
} }
} }

@ -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.

@ -26,6 +26,8 @@
#ifndef __ARES__ARRAY_H #ifndef __ARES__ARRAY_H
#define __ARES__ARRAY_H #define __ARES__ARRAY_H
#include "ares.h"
/*! \addtogroup ares__array Array Data Structure /*! \addtogroup ares__array Array Data Structure
* *
* This is an array with helpers. It is meant to have as little overhead * 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 * \return array object or NULL on out of memory
*/ */
ares__array_t *ares__array_create(size_t member_size, CARES_EXTERN ares__array_t *
ares__array_destructor_t destruct); 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 /*! 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 * \param[in] size Minimum number of members
* \return ARES_SUCCESS on success, ARES_EFORMERR on misuse, * \return ARES_SUCCESS on success, ARES_EFORMERR on misuse,
* ARES_ENOMEM on out of memory */ * 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 /*! Sort the array using the given comparison function. This is not
* persistent, any future elements inserted will not maintain this sort. * 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 * \param[in] cb Sort callback
* \return ARES_SUCCESS on success * \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 /*! Destroy an array object. If a destructor is set, will be called on each
* member of the array. * member of the array.
* *
* \param[in] arr Initialized array object. * \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 /*! Retrieve the array in the native format. This will also destroy the
* container. It is the responsibility of the caller to free the returned * 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 * \param[out] num_members the number of members in the returned array
* \return pointer to native array on success, NULL on failure. * \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 /*! Retrieve the number of members in the array
* *
* \param[in] arr Initialized array object. * \param[in] arr Initialized array object.
* \return numbrer of members * \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 /*! Insert a new array member at the given index
* *
@ -127,7 +131,8 @@ size_t ares__array_len(const ares__array_t *arr);
* \return ARES_SUCCESS on success, ARES_EFORMERR on bad index, * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index,
* ARES_ENOMEM on out of memory. * ARES_ENOMEM on out of memory.
*/ */
ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr, CARES_EXTERN ares_status_t ares__array_insert_at(void **elem_ptr,
ares__array_t *arr,
size_t idx); size_t idx);
/*! Insert a new array member at the end of the array /*! 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. * \param[in] arr Initialized array object.
* \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory. * \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 /*! 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. * \param[in] arr Initialized array object.
* \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory. * \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 /*! Fetch a pointer to the given element in the array
* \param[in] array Initialized array object * \param[in] array Initialized array object
* \param[in] idx Index to fetch * \param[in] idx Index to fetch
* \return pointer on success, NULL on failure */ * \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 /*! Fetch a pointer to the first element in the array
* \param[in] array Initialized array object * \param[in] array Initialized array object
* \return pointer on success, NULL on failure */ * \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 /*! Fetch a pointer to the last element in the array
* \param[in] array Initialized array object * \param[in] array Initialized array object
* \return pointer on success, NULL on failure */ * \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 /*! Fetch a constant pointer to the given element in the array
* \param[in] array Initialized array object * \param[in] array Initialized array object
* \param[in] idx Index to fetch * \param[in] idx Index to fetch
* \return pointer on success, NULL on failure */ * \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 /*! Fetch a constant pointer to the first element in the array
* \param[in] array Initialized array object * \param[in] array Initialized array object
* \return pointer on success, NULL on failure */ * \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 /*! Fetch a constant pointer to the last element in the array
* \param[in] array Initialized array object * \param[in] array Initialized array object
* \return pointer on success, NULL on failure */ * \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 /*! 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 * provided by the caller. The index specified in the array will then be
@ -192,7 +200,7 @@ const void *ares__array_last_const(const ares__array_t *arr);
* \param[in] idx Index to claim * \param[in] idx Index to claim
* \return ARES_SUCCESS on success, ARES_EFORMERR on usage failure. * \return ARES_SUCCESS on success, ARES_EFORMERR on usage failure.
*/ */
ares_status_t ares__array_claim_at(void *dest, size_t dest_size, CARES_EXTERN ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
ares__array_t *arr, size_t idx); ares__array_t *arr, size_t idx);
/*! Remove the member at the specified array index. The destructor will be /*! Remove the member at the specified array index. The destructor will be
@ -202,21 +210,22 @@ ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
* \param[in] idx Index to remove * \param[in] idx Index to remove
* \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use * \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. /*! Remove the first member of the array.
* *
* \param[in] arr Initialized array object * \param[in] arr Initialized array object
* \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use * \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. /*! Remove the last member of the array.
* *
* \param[in] arr Initialized array object * \param[in] arr Initialized array object
* \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use * \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);
/*! @} */ /*! @} */

@ -26,6 +26,8 @@
#ifndef __ARES__BUF_H #ifndef __ARES__BUF_H
#define __ARES__BUF_H #define __ARES__BUF_H
#include "ares.h"
/*! \addtogroup ares__buf Safe Data Builder and buffer /*! \addtogroup ares__buf Safe Data Builder and buffer
* *
* This is a buffer building and parsing framework with a focus on security over * This is a buffer building and parsing framework with a focus on security over
@ -51,7 +53,7 @@ typedef struct ares__buf ares__buf_t;
* *
* \return initialized buffer object or NULL if out of memory. * \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 /*! 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 * 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. * \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. /*! Destroy an initialized buffer object.
* *
* \param[in] buf Initialized buf 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 /*! Append multiple bytes to a dynamic buffer object
@ -79,7 +82,8 @@ void ares__buf_destroy(ares__buf_t *buf);
* \param[in] data_len Length of data to copy to buffer object. * \param[in] data_len Length of data to copy to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes * \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, CARES_EXTERN ares_status_t ares__buf_append(ares__buf_t *buf,
const unsigned char *data,
size_t data_len); size_t data_len);
/*! Append a single byte to the dynamic buffer object /*! 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. * \param[in] b Single byte to append to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes * \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 /*! 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. * \param[in] str String to append to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes * \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. /*! 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 * \param[out] u16 16bit integer
* \return ARES_SUCCESS or one of the c-ares error codes * \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. /*! 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 * \param[out] u32 32bit integer
* \return ARES_SUCCESS or one of the c-ares error codes * \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. /*! 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 * \param[in] len Length to output, use 0 for no padding
* \return ARES_SUCCESS on success * \return ARES_SUCCESS on success
*/ */
ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, CARES_EXTERN ares_status_t ares__buf_append_num_dec(ares__buf_t *buf,
size_t len); size_t num, size_t len);
/*! Append a number in ASCII hexadecimal form. /*! 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 * \param[in] len Length to output, use 0 for no padding
* \return ARES_SUCCESS on success * \return ARES_SUCCESS on success
*/ */
ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num, CARES_EXTERN ares_status_t ares__buf_append_num_hex(ares__buf_t *buf,
size_t len); size_t num, size_t len);
/*! Sets the current buffer length. This *may* be used if there is a need to /*! 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 * 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 * \param[in] len Length to set
* \return ARES_SUCCESS or one of the c-ares error codes * \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 /*! 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. * returned.
* \return Pointer to writable buffer or NULL on failure (usage, out of mem) * \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 /*! Finish a dynamic append operation. Called after
* ares__buf_append_start() once desired data is written. * 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 * operation. Must not be greater than returned from
* ares__buf_append_start(). * 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. /*! Write the data provided to the buffer in a hexdump format.
* *
@ -180,7 +189,8 @@ void ares__buf_append_finish(ares__buf_t *buf, size_t len);
* \param[in] len Length of data to hexdump * \param[in] len Length of data to hexdump
* \return ARES_SUCCESS on success. * \return ARES_SUCCESS on success.
*/ */
ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, CARES_EXTERN ares_status_t ares__buf_hexdump(ares__buf_t *buf,
const unsigned char *data,
size_t len); size_t len);
/*! Clean up ares__buf_t and return allocated pointer to unprocessed data. It /*! Clean up ares__buf_t and return allocated pointer to unprocessed data. It
@ -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 * \param[out] len Length of data returned
* \return pointer to unprocessed data (may be zero length) or NULL on error. * \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 /*! 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 * 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. * \param[out] len Optional. Length of data returned, or NULL if not needed.
* \return pointer to unprocessed data or NULL on error. * \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, /*! 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 * 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 * \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. /*! Rollback to a tagged position. Will automatically clear the tag.
* *
* \param[in] buf Initialized buffer object * \param[in] buf Initialized buffer object
* \return ARES_SUCCESS or one of the c-ares error codes * \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 /*! 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 * 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 * \param[in] buf Initialized buffer object
* \return ARES_SUCCESS or one of the c-ares error codes * \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 /*! 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 * 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 * \return NULL on failure (such as no tag), otherwise pointer to start of
* buffer * 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. /*! Get the length of the current tag offset to the current position.
* *
* \param[in] buf Initialized buffer object * \param[in] buf Initialized buffer object
* \return length * \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_ /*! Fetch the bytes starting from the tagged position up to the _current_
* position using the provided buffer. It will not unset the tagged position. * 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. * buffer.
* \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size * \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size
*/ */
ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf, CARES_EXTERN ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf,
unsigned char *bytes, size_t *len); unsigned char *bytes,
size_t *len);
/*! Fetch the bytes starting from the tagged position up to the _current_ /*! Fetch the bytes starting from the tagged position up to the _current_
* position as a NULL-terminated string using the provided buffer. The data * 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, * \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size,
* ARES_EBADSTR if not printable ASCII * ARES_EBADSTR if not printable ASCII
*/ */
ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str, CARES_EXTERN ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf,
size_t len); char *str, size_t len);
/*! Consume the given number of bytes without reading them. /*! 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 * \param[in] len Length to consume
* \return ARES_SUCCESS or one of the c-ares error codes * \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. /*! 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 * \param[out] u16 Buffer to hold 16bit integer
* \return ARES_SUCCESS or one of the c-ares error codes * \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. /*! 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 * \param[out] u32 Buffer to hold 32bit integer
* \return ARES_SUCCESS or one of the c-ares error codes * \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 /*! Fetch the requested number of bytes into the provided buffer
@ -311,7 +325,8 @@ ares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32);
* \param[in] len Requested number of bytes (must be > 0) * \param[in] len Requested number of bytes (must be > 0)
* \return ARES_SUCCESS or one of the c-ares error codes * \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, CARES_EXTERN ares_status_t ares__buf_fetch_bytes(ares__buf_t *buf,
unsigned char *bytes,
size_t len); size_t len);
@ -326,7 +341,8 @@ ares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, unsigned char *bytes,
* \param[out] bytes Pointer passed by reference. Will be allocated. * \param[out] bytes Pointer passed by reference. Will be allocated.
* \return ARES_SUCCESS or one of the c-ares error codes * \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, CARES_EXTERN ares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf,
size_t len,
ares_bool_t null_term, ares_bool_t null_term,
unsigned char **bytes); unsigned char **bytes);
@ -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) * \param[in] len Requested number of bytes (must be > 0)
* \return ARES_SUCCESS or one of the c-ares error codes * \return ARES_SUCCESS or one of the c-ares error codes
*/ */
ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, CARES_EXTERN ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf,
ares__buf_t *dest, size_t len); ares__buf_t *dest,
size_t len);
/*! Fetch the requested number of bytes and return a new buffer that must be /*! 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 * 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. * \param[out] str Pointer passed by reference. Will be allocated.
* \return ARES_SUCCESS or one of the c-ares error codes * \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 /*! Consume whitespace characters (0x09, 0x0B, 0x0C, 0x0D, 0x20, and optionally
* 0x0A). * 0x0A).
@ -360,7 +378,7 @@ ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str);
* ARES_FALSE otherwise. * ARES_FALSE otherwise.
* \return number of whitespace characters consumed * \return number of whitespace characters consumed
*/ */
size_t ares__buf_consume_whitespace(ares__buf_t *buf, CARES_EXTERN size_t ares__buf_consume_whitespace(ares__buf_t *buf,
ares_bool_t include_linefeed); ares_bool_t include_linefeed);
@ -370,7 +388,7 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf,
* \param[in] buf Initialized buffer object * \param[in] buf Initialized buffer object
* \return number of characters consumed * \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 /*! Consume until a character in the character set provided is reached. Does
@ -385,8 +403,8 @@ size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf);
* 0 if not found. * 0 if not found.
* \return number of characters consumed * \return number of characters consumed
*/ */
size_t ares__buf_consume_until_charset(ares__buf_t *buf, CARES_EXTERN size_t ares__buf_consume_until_charset(
const unsigned char *charset, size_t len, ares__buf_t *buf, const unsigned char *charset, size_t len,
ares_bool_t require_charset); ares_bool_t require_charset);
@ -397,7 +415,8 @@ size_t ares__buf_consume_until_charset(ares__buf_t *buf,
* \param[in] len length of character set * \param[in] len length of character set
* \return number of characters consumed * \return number of characters consumed
*/ */
size_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset, CARES_EXTERN size_t ares__buf_consume_charset(ares__buf_t *buf,
const unsigned char *charset,
size_t len); size_t len);
@ -409,7 +428,8 @@ size_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset,
* ARES_FALSE otherwise. * ARES_FALSE otherwise.
* \return number of characters consumed * \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 { typedef enum {
/*! No flags */ /*! No flags */
@ -457,9 +477,9 @@ typedef enum {
* objects. * objects.
* \return ARES_SUCCESS on success, or error like ARES_ENOMEM. * \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
*/ */
ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, CARES_EXTERN ares_status_t ares__buf_split(
size_t delims_len, ares__buf_split_t flags, ares__buf_t *buf, const unsigned char *delims, size_t delims_len,
size_t max_sections, ares__llist_t **list); 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 /*! 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. * \param[in] data_len Length of data to compare.
* \return ARES_TRUE on match, ARES_FALSE otherwise. * \return ARES_TRUE on match, ARES_FALSE otherwise.
*/ */
ares_bool_t ares__buf_begins_with(const ares__buf_t *buf, CARES_EXTERN ares_bool_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data, size_t data_len); const unsigned char *data,
size_t data_len);
/*! Size of unprocessed remaining data length /*! 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 * \param[in] buf Initialized buffer object
* \return length remaining * \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 /*! Retrieve a pointer to the currently unprocessed data. Generally this isn't
* recommended to be used in practice. The returned pointer may be invalidated * 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 * \param[out] len Length of available data
* \return Pointer to buffer of unprocessed 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 /*! 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 * \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. /*! 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 * \param[in] idx Index to set position
* \return ARES_SUCCESS if valid index * \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. /*! 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 * \param[in] buf Initialized buffer object
* \return index of current position * \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 /*! Parse a character-string as defined in RFC1035, as a null-terminated
* string. * string.
@ -556,29 +578,9 @@ size_t ares__buf_get_position(const ares__buf_t *buf);
* ares_free()'d by the caller. * ares_free()'d by the caller.
* \return ARES_SUCCESS on success * \return ARES_SUCCESS on success
*/ */
ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len, CARES_EXTERN ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf,
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, size_t remaining_len,
ares__dns_multistring_t **strs, char **name);
ares_bool_t validate_printable);
/*! Parse a character-string as defined in RFC1035, as binary, however for /*! Parse a character-string as defined in RFC1035, as binary, however for
* convenience this does guarantee a NULL terminator (that is not included * 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. * \param[out] bin_len Length of returned string.
* \return ARES_SUCCESS on success * \return ARES_SUCCESS on success
*/ */
ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, CARES_EXTERN ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf,
unsigned char **bin, size_t *bin_len); size_t remaining_len,
unsigned char **bin,
size_t *bin_len);
/*! Load data from specified file path into provided buffer. The entire file /*! Load data from specified file path into provided buffer. The entire file
* is loaded into memory. * 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 * \return ARES_ENOTFOUND if file not found, ARES_EFILE if issues reading
* file, ARES_ENOMEM if out of memory, ARES_SUCCESS on success. * 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);
/*! @} */ /*! @} */

@ -57,7 +57,7 @@ typedef void (*ares__htable_asvp_val_free_t)(void *val);
* *
* \param[in] htable Initialized hashtable * \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 /*! 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 * NULL it is expected the caller will clean up any user
* supplied values. * supplied values.
*/ */
ares__htable_asvp_t * CARES_EXTERN ares__htable_asvp_t *
ares__htable_asvp_create(ares__htable_asvp_val_free_t val_free); ares__htable_asvp_create(ares__htable_asvp_val_free_t val_free);
/*! Retrieve an array of keys from the hashtable. /*! Retrieve an array of keys from the hashtable.
@ -74,8 +74,8 @@ ares__htable_asvp_t *
* \param[out] num Count of returned keys * \param[out] num Count of returned keys
* \return Array of keys in the hashtable. Must be free'd with ares_free(). * \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, CARES_EXTERN ares_socket_t *
size_t *num); ares__htable_asvp_keys(const ares__htable_asvp_t *htable, size_t *num);
/*! Insert key/value into hash table /*! Insert key/value into hash table
@ -85,7 +85,7 @@ ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable,
* \param[in] val value to store (takes ownership). May be NULL. * \param[in] val value to store (takes ownership). May be NULL.
* \return ARES_TRUE on success, ARES_FALSE on out of memory or misuse * \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, CARES_EXTERN ares_bool_t ares__htable_asvp_insert(ares__htable_asvp_t *htable,
ares_socket_t key, void *val); ares_socket_t key, void *val);
/*! Retrieve value from hashtable based on key /*! 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. * \param[out] val Optional. Pointer to store value.
* \return ARES_TRUE on success, ARES_FALSE on failure * \return ARES_TRUE on success, ARES_FALSE on failure
*/ */
ares_bool_t ares__htable_asvp_get(const ares__htable_asvp_t *htable, CARES_EXTERN ares_bool_t ares__htable_asvp_get(
ares_socket_t key, void **val); const ares__htable_asvp_t *htable, ares_socket_t key, void **val);
/*! Retrieve value from hashtable directly as return value. Caveat to this /*! 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 * function over ares__htable_asvp_get() is that if a NULL value is stored
@ -106,7 +106,8 @@ ares_bool_t ares__htable_asvp_get(const ares__htable_asvp_t *htable,
* \param[in] key key to use to search * \param[in] key key to use to search
* \return value associated with key in hashtable or NULL * \return value associated with key in hashtable or NULL
*/ */
void *ares__htable_asvp_get_direct(const ares__htable_asvp_t *htable, CARES_EXTERN void *
ares__htable_asvp_get_direct(const ares__htable_asvp_t *htable,
ares_socket_t key); ares_socket_t key);
/*! Remove a value from the hashtable by key /*! Remove a value from the hashtable by key
@ -115,7 +116,7 @@ void *ares__htable_asvp_get_direct(const ares__htable_asvp_t *htable,
* \param[in] key key to use to search * \param[in] key key to use to search
* \return ARES_TRUE if found, ARES_FALSE if not found * \return ARES_TRUE if found, ARES_FALSE if not found
*/ */
ares_bool_t ares__htable_asvp_remove(ares__htable_asvp_t *htable, CARES_EXTERN ares_bool_t ares__htable_asvp_remove(ares__htable_asvp_t *htable,
ares_socket_t key); ares_socket_t key);
/*! Retrieve the number of keys stored in the hash table /*! Retrieve the number of keys stored in the hash table
@ -123,7 +124,8 @@ ares_bool_t ares__htable_asvp_remove(ares__htable_asvp_t *htable,
* \param[in] htable Initialized hash table * \param[in] htable Initialized hash table
* \return count * \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);
/*! @} */ /*! @} */

@ -55,7 +55,7 @@ typedef void (*ares__htable_strvp_val_free_t)(void *val);
* *
* \param[in] htable Initialized hashtable * \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 /*! 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 * NULL it is expected the caller will clean up any user
* supplied values. * supplied values.
*/ */
ares__htable_strvp_t * CARES_EXTERN ares__htable_strvp_t *
ares__htable_strvp_create(ares__htable_strvp_val_free_t val_free); ares__htable_strvp_create(ares__htable_strvp_val_free_t val_free);
/*! Insert key/value into hash table /*! Insert key/value into hash table
@ -73,7 +73,7 @@ ares__htable_strvp_t *
* \param[in] val value to store (takes ownership). May be NULL. * \param[in] val value to store (takes ownership). May be NULL.
* \return ARES_TRUE on success, ARES_FALSE on failure or out of memory * \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, CARES_EXTERN ares_bool_t ares__htable_strvp_insert(ares__htable_strvp_t *htable,
const char *key, void *val); const char *key, void *val);
/*! Retrieve value from hashtable based on key /*! 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. * \param[out] val Optional. Pointer to store value.
* \return ARES_TRUE on success, ARES_FALSE on failure * \return ARES_TRUE on success, ARES_FALSE on failure
*/ */
ares_bool_t ares__htable_strvp_get(const ares__htable_strvp_t *htable, CARES_EXTERN ares_bool_t ares__htable_strvp_get(
const char *key, void **val); const ares__htable_strvp_t *htable, const char *key, void **val);
/*! Retrieve value from hashtable directly as return value. Caveat to this /*! 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 * function over ares__htable_strvp_get() is that if a NULL value is stored
@ -94,7 +94,8 @@ ares_bool_t ares__htable_strvp_get(const ares__htable_strvp_t *htable,
* \param[in] key key to use to search * \param[in] key key to use to search
* \return value associated with key in hashtable or NULL * \return value associated with key in hashtable or NULL
*/ */
void *ares__htable_strvp_get_direct(const ares__htable_strvp_t *htable, CARES_EXTERN void *
ares__htable_strvp_get_direct(const ares__htable_strvp_t *htable,
const char *key); const char *key);
/*! Remove a value from the hashtable by key /*! Remove a value from the hashtable by key
@ -103,7 +104,7 @@ void *ares__htable_strvp_get_direct(const ares__htable_strvp_t *htable,
* \param[in] key key to use to search * \param[in] key key to use to search
* \return ARES_TRUE if found, ARES_FALSE if not * \return ARES_TRUE if found, ARES_FALSE if not
*/ */
ares_bool_t ares__htable_strvp_remove(ares__htable_strvp_t *htable, CARES_EXTERN ares_bool_t ares__htable_strvp_remove(ares__htable_strvp_t *htable,
const char *key); const char *key);
/*! Retrieve the number of keys stored in the hash table /*! Retrieve the number of keys stored in the hash table
@ -111,7 +112,8 @@ ares_bool_t ares__htable_strvp_remove(ares__htable_strvp_t *htable,
* \param[in] htable Initialized hash table * \param[in] htable Initialized hash table
* \return count * \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);
/*! @} */ /*! @} */

@ -55,7 +55,7 @@ typedef void (*ares__htable_szvp_val_free_t)(void *val);
* *
* \param[in] htable Initialized hashtable * \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 /*! 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 * NULL it is expected the caller will clean up any user
* supplied values. * supplied values.
*/ */
ares__htable_szvp_t * CARES_EXTERN ares__htable_szvp_t *
ares__htable_szvp_create(ares__htable_szvp_val_free_t val_free); ares__htable_szvp_create(ares__htable_szvp_val_free_t val_free);
/*! Insert key/value into hash table /*! 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. * \param[in] val value to store (takes ownership). May be NULL.
* \return ARES_TRUE on success, ARES_FALSE on failure or out of memory * \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, CARES_EXTERN ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable,
void *val); size_t key, void *val);
/*! Retrieve value from hashtable based on key /*! 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. * \param[out] val Optional. Pointer to store value.
* \return ARES_TRUE on success, ARES_FALSE on failure * \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, CARES_EXTERN ares_bool_t ares__htable_szvp_get(
void **val); const ares__htable_szvp_t *htable, size_t key, void **val);
/*! Retrieve value from hashtable directly as return value. Caveat to this /*! 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 * 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 * \param[in] key key to use to search
* \return value associated with key in hashtable or NULL * \return value associated with key in hashtable or NULL
*/ */
void *ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable, CARES_EXTERN void *
size_t key); ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable, size_t key);
/*! Remove a value from the hashtable by 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 * \param[in] key key to use to search
* \return ARES_TRUE if found, ARES_FALSE if not * \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 /*! Retrieve the number of keys stored in the hash table
* *
* \param[in] htable Initialized hash table * \param[in] htable Initialized hash table
* \return count * \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);
/*! @} */ /*! @} */

@ -61,7 +61,7 @@ typedef void (*ares__htable_vpvp_val_free_t)(void *val);
* *
* \param[in] htable Initialized hashtable * \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 /*! Create size_t key, void pointer value hash table
* *
@ -72,7 +72,7 @@ void ares__htable_vpvp_destroy(ares__htable_vpvp_t *htable);
* NULL it is expected the caller will clean up any user * NULL it is expected the caller will clean up any user
* supplied values. * 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_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);
@ -83,8 +83,8 @@ ares__htable_vpvp_t *
* \param[in] val value to store (takes ownership). May be NULL. * \param[in] val value to store (takes ownership). May be NULL.
* \return ARES_TRUE on success, ARES_FALSE on failure or out of memory * \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, CARES_EXTERN ares_bool_t ares__htable_vpvp_insert(ares__htable_vpvp_t *htable,
void *val); void *key, void *val);
/*! Retrieve value from hashtable based on key /*! 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. * \param[out] val Optional. Pointer to store value.
* \return ARES_TRUE on success, ARES_FALSE on failure * \return ARES_TRUE on success, ARES_FALSE on failure
*/ */
ares_bool_t ares__htable_vpvp_get(const ares__htable_vpvp_t *htable, CARES_EXTERN ares_bool_t ares__htable_vpvp_get(
const void *key, void **val); const ares__htable_vpvp_t *htable, const void *key, void **val);
/*! Retrieve value from hashtable directly as return value. Caveat to this /*! 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 * function over ares__htable_vpvp_get() is that if a NULL value is stored
@ -104,7 +104,8 @@ ares_bool_t ares__htable_vpvp_get(const ares__htable_vpvp_t *htable,
* \param[in] key key to use to search * \param[in] key key to use to search
* \return value associated with key in hashtable or NULL * \return value associated with key in hashtable or NULL
*/ */
void *ares__htable_vpvp_get_direct(const ares__htable_vpvp_t *htable, CARES_EXTERN void *
ares__htable_vpvp_get_direct(const ares__htable_vpvp_t *htable,
const void *key); const void *key);
/*! Remove a value from the hashtable by key /*! Remove a value from the hashtable by key
@ -113,7 +114,7 @@ void *ares__htable_vpvp_get_direct(const ares__htable_vpvp_t *htable,
* \param[in] key key to use to search * \param[in] key key to use to search
* \return ARES_TRUE if found, ARES_FALSE if not * \return ARES_TRUE if found, ARES_FALSE if not
*/ */
ares_bool_t ares__htable_vpvp_remove(ares__htable_vpvp_t *htable, CARES_EXTERN ares_bool_t ares__htable_vpvp_remove(ares__htable_vpvp_t *htable,
const void *key); const void *key);
/*! Retrieve the number of keys stored in the hash table /*! Retrieve the number of keys stored in the hash table
@ -121,7 +122,8 @@ ares_bool_t ares__htable_vpvp_remove(ares__htable_vpvp_t *htable,
* \param[in] htable Initialized hash table * \param[in] htable Initialized hash table
* \return count * \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);
/*! @} */ /*! @} */

@ -59,7 +59,8 @@ typedef void (*ares__llist_destructor_t)(void *data);
* \param[in] destruct Optional. Destructor to call on all removed nodes * \param[in] destruct Optional. Destructor to call on all removed nodes
* \return linked list object or NULL on out of memory * \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 /*! Replace destructor for linked list nodes. Typically this is used
* when wanting to disable the destructor by using NULL. * when wanting to disable the destructor by using NULL.
@ -67,7 +68,8 @@ ares__llist_t *ares__llist_create(ares__llist_destructor_t destruct);
* \param[in] list Initialized linked list object * \param[in] list Initialized linked list object
* \param[in] destruct replacement destructor, NULL is allowed * \param[in] destruct replacement destructor, NULL is allowed
*/ */
void ares__llist_replace_destructor(ares__llist_t *list, CARES_EXTERN void
ares__llist_replace_destructor(ares__llist_t *list,
ares__llist_destructor_t destruct); ares__llist_destructor_t destruct);
/*! Insert value as the first node in the linked list /*! 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 * \return node object referencing place in list, or null if out of memory or
* misuse * 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 /*! 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 * \return node object referencing place in list, or null if out of memory or
* misuse * 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 /*! 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 * \return node object referencing place in list, or null if out of memory or
* misuse * misuse
*/ */
ares__llist_node_t *ares__llist_insert_before(ares__llist_node_t *node, CARES_EXTERN ares__llist_node_t *
void *val); ares__llist_insert_before(ares__llist_node_t *node, void *val);
/*! Insert value after specified node in the linked list /*! 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 * \return node object referencing place in list, or null if out of memory or
* misuse * misuse
*/ */
ares__llist_node_t *ares__llist_insert_after(ares__llist_node_t *node, CARES_EXTERN ares__llist_node_t *
void *val); ares__llist_insert_after(ares__llist_node_t *node, void *val);
/*! Obtain first node in list /*! Obtain first node in list
* *
* \param[in] list Initialized list object * \param[in] list Initialized list object
* \return first node in list or NULL if none * \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 /*! Obtain last node in list
* *
* \param[in] list Initialized list object * \param[in] list Initialized list object
* \return last node in list or NULL if none * \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. /*! 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 * \param[in] idx Index of node to retrieve
* \return node at index or NULL if invalid index * \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 /*! Obtain next node in respect to specified node
* *
* \param[in] node Node referenced * \param[in] node Node referenced
* \return node or NULL if none * \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 /*! Obtain previous node in respect to specified node
* *
* \param[in] node Node referenced * \param[in] node Node referenced
* \return node or NULL if none * \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 /*! 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 * \param[in] node Node referenced
* \return user provided value from node * \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 /*! Obtain the number of entries in the list
* *
* \param[in] list Initialized list object * \param[in] list Initialized list object
* \return count * \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. /*! Clear all entries in the list, but don't destroy the list object.
* *
* \param[in] list Initialized 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 /*! Obtain list object from referenced node
* *
* \param[in] node Node referenced * \param[in] node Node referenced
* \return list object node belongs to * \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 /*! Obtain the first user-supplied value in the list
* *
* \param[in] list Initialized list object * \param[in] list Initialized list object
* \return first user supplied value or NULL if none * \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 /*! Obtain the last user-supplied value in the list
* *
* \param[in] list Initialized list object * \param[in] list Initialized list object
* \return last user supplied value or NULL if none * \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. /*! Take ownership of user-supplied value in list without calling destructor.
* Will unchain entry from list. * Will unchain entry from list.
@ -192,26 +199,26 @@ void *ares__llist_last_val(ares__llist_t *list);
* \param[in] node Node referenced * \param[in] node Node referenced
* \return user supplied value * \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 /*! Replace user-supplied value for node
* *
* \param[in] node Node referenced * \param[in] node Node referenced
* \param[in] val new user-supplied value * \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. /*! Destroy the node, removing it from the list and calling destructor.
* *
* \param[in] node Node referenced * \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. /*! Destroy the list object and all nodes in the list.
* *
* \param[in] list Initialized list object * \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 /*! Detach node from the current list and re-attach it to the new list as the
* last entry. * last entry.
@ -219,7 +226,7 @@ void ares__llist_destroy(ares__llist_t *list);
* \param[in] node node to move * \param[in] node node to move
* \param[in] new_parent new list * \param[in] new_parent new list
*/ */
void ares__llist_node_move_parent_last(ares__llist_node_t *node, CARES_EXTERN void ares__llist_node_move_parent_last(ares__llist_node_t *node,
ares__llist_t *new_parent); ares__llist_t *new_parent);
/*! Detach node from the current list and re-attach it to the new list as the /*! Detach node from the current list and re-attach it to the new list as the
@ -228,7 +235,7 @@ void ares__llist_node_move_parent_last(ares__llist_node_t *node,
* \param[in] node node to move * \param[in] node node to move
* \param[in] new_parent new list * \param[in] new_parent new list
*/ */
void ares__llist_node_move_parent_first(ares__llist_node_t *node, CARES_EXTERN void ares__llist_node_move_parent_first(ares__llist_node_t *node,
ares__llist_t *new_parent); ares__llist_t *new_parent);
/*! @} */ /*! @} */

@ -1,6 +1,5 @@
/* MIT License /* MIT License
* *
* Copyright (c) 1998 Massachusetts Institute of Technology
* Copyright (c) The c-ares project and its contributors * Copyright (c) The c-ares project and its contributors
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
@ -24,15 +23,16 @@
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#ifndef HEADER_CARES_STRCASECMP_H
#define HEADER_CARES_STRCASECMP_H
#ifndef HAVE_STRCASECMP #ifndef __ARES_MEM_H
extern int ares_strcasecmp(const char *a, const char *b); #define __ARES_MEM_H
#endif
#ifndef HAVE_STRNCASECMP /* Memory management functions */
extern int ares_strncasecmp(const char *a, const char *b, size_t n); CARES_EXTERN void *ares_malloc(size_t size);
#endif 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

@ -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 */

@ -135,7 +135,7 @@ ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec,
* status = ARES_EBADRESP; * status = ARES_EBADRESP;
* goto done; * goto done;
* } * }
* if (strcasecmp(ptrname, rname) != 0) { * if (!ares_strcaseeq(ptrname, rname)) {
* continue; * continue;
* } * }
*/ */

@ -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++) { 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; *qclass = list[i].qclass;
return ARES_TRUE; 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++) { 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; *qtype = list[i].type;
return ARES_TRUE; return ARES_TRUE;
} }

@ -222,3 +222,74 @@ const unsigned char *
*len = strs->cache_str_len; *len = strs->cache_str_len;
return strs->cache_str; 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;
}

@ -26,6 +26,8 @@
#ifndef __ARES_DNS_MULTISTRING_H #ifndef __ARES_DNS_MULTISTRING_H
#define __ARES_DNS_MULTISTRING_H #define __ARES_DNS_MULTISTRING_H
#include "ares__buf.h"
struct ares__dns_multistring; struct ares__dns_multistring;
typedef struct ares__dns_multistring ares__dns_multistring_t; 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, ares__dns_multistring_get_combined(ares__dns_multistring_t *strs,
size_t *len); 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 #endif

@ -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 /* Due to DNS 0x20, lets not inadvertently mangle things, use case-sensitive
* matching instead of case-insensitive. This may result in slightly * matching instead of case-insensitive. This may result in slightly
* larger DNS queries overall. */ * larger DNS queries overall. */
if (strcmp(val->name, name + prefix_len) != 0) { if (!ares_streq(val->name, name + prefix_len)) {
continue; continue;
} }

@ -95,7 +95,8 @@ static ares_status_t
ares_status_t status; ares_status_t status;
ares__dns_multistring_t *strs = NULL; 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) { if (status != ARES_SUCCESS) {
return status; return status;
} }

@ -941,76 +941,6 @@ ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx)
return ARES_SUCCESS; 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 static ares_status_t
ares__buf_parse_dns_binstr_int(ares__buf_t *buf, size_t remaining_len, ares__buf_parse_dns_binstr_int(ares__buf_t *buf, size_t remaining_len,
unsigned char **bin, size_t *bin_len, unsigned char **bin, size_t *bin_len,

@ -286,3 +286,168 @@ ares_bool_t ares__str_isprint(const char *str, size_t len)
} }
return ARES_TRUE; 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;
}

@ -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 */

@ -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

@ -334,7 +334,7 @@ static ares_bool_t name_match(const char *name, const char *adapter_name,
return ARES_TRUE; return ARES_TRUE;
} }
if (strcasecmp(name, adapter_name) == 0) { if (ares_strcaseeq(name, adapter_name)) {
return ARES_TRUE; return ARES_TRUE;
} }
@ -515,7 +515,7 @@ static ares_status_t ares__iface_ips_enumerate(ares__iface_ips_t *ips,
} }
/* Name mismatch */ /* Name mismatch */
if (name != NULL && strcasecmp(ifa->ifa_name, name) != 0) { if (name != NULL && !ares_strcaseeq(ifa->ifa_name, name)) {
continue; continue;
} }

@ -11,6 +11,7 @@ IF (CARES_BUILD_TOOLS)
PUBLIC "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>" PUBLIC "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/lib>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/lib>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/lib/include>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"
@ -39,6 +40,7 @@ IF (CARES_BUILD_TOOLS)
PUBLIC "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>" PUBLIC "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/lib>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/lib>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/lib/include>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"

@ -16,6 +16,7 @@ AM_CPPFLAGS += -I$(top_builddir)/include \
-I$(top_builddir)/src/lib \ -I$(top_builddir)/src/lib \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
-I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include \
-DCARES_NO_DEPRECATED -DCARES_NO_DEPRECATED
include Makefile.inc include Makefile.inc

@ -1,7 +1,5 @@
# Copyright (C) The c-ares project and its contributors # Copyright (C) The c-ares project and its contributors
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
SAMPLESOURCES = ares_getopt.c \ SAMPLESOURCES = ares_getopt.c
../lib/str/ares_strcasecmp.c
SAMPLEHEADERS = ares_getopt.h \ SAMPLEHEADERS = ares_getopt.h
../lib/str/ares_strcasecmp.h

@ -44,21 +44,7 @@
#include "ares.h" #include "ares.h"
#include "ares_dns.h" #include "ares_dns.h"
#include "ares_str.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_getopt.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++) { 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; return nv[i].value;
} }
} }

@ -42,20 +42,7 @@
#include "ares_getopt.h" #include "ares_getopt.h"
#include "ares_ipv6.h" #include "ares_ipv6.h"
#ifndef HAVE_STRDUP #include "ares_str.h"
# 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
static void callback(void *arg, int status, int timeouts, struct hostent *host); static void callback(void *arg, int status, int timeouts, struct hostent *host);
static void ai_callback(void *arg, int status, int timeouts, 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); options.domains[options.ndomains - 1] = strdup(state.optarg);
break; break;
case 't': case 't':
if (!strcasecmp(state.optarg, "a")) { if (ares_strcaseeq(state.optarg, "a")) {
addr_family = AF_INET; addr_family = AF_INET;
} else if (!strcasecmp(state.optarg, "aaaa")) { } else if (ares_strcaseeq(state.optarg, "aaaa")) {
addr_family = AF_INET6; addr_family = AF_INET6;
} else if (!strcasecmp(state.optarg, "u")) { } else if (ares_strcaseeq(state.optarg, "u")) {
addr_family = AF_UNSPEC; addr_family = AF_UNSPEC;
} else { } else {
usage(); usage();

@ -26,6 +26,7 @@ target_include_directories(caresinternal
"${PROJECT_BINARY_DIR}/src/lib" "${PROJECT_BINARY_DIR}/src/lib"
"${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}"
"${PROJECT_SOURCE_DIR}/src/lib" "${PROJECT_SOURCE_DIR}/src/lib"
"${PROJECT_SOURCE_DIR}/src/lib/include"
"${PROJECT_SOURCE_DIR}/include" "${PROJECT_SOURCE_DIR}/include"
) )

1
test/Makefile.am vendored

@ -6,6 +6,7 @@ AM_CPPFLAGS += -I$(top_builddir)/include \
-I$(top_builddir)/src/lib \ -I$(top_builddir)/src/lib \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
-I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include \
-I$(top_srcdir)/test \ -I$(top_srcdir)/test \
-I$(top_builddir)/test \ -I$(top_builddir)/test \
-I$(top_builddir) -DCARES_NO_DEPRECATED -I$(top_builddir) -DCARES_NO_DEPRECATED

2
test/Makefile.m32 vendored

@ -19,7 +19,7 @@ ARES_SRC_DIR = ..
# Where to find the built c-ares static library # Where to find the built c-ares static library
ARES_BLD_DIR = .. ARES_BLD_DIR = ..
ARESLIB = $(ARES_BLD_DIR)/src/lib/libcares.a 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 CXXFLAGS = -Wall $(PTHREAD_CFLAGS) -std=gnu++14
LDFLAGS = LDFLAGS =
LDLIBS = -lws2_32 -liphlpapi LDLIBS = -lws2_32 -liphlpapi

@ -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_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_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_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG" RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG"

@ -71,9 +71,7 @@ void CheckPtoN4(int size, unsigned int value, const char *input) {
<< " for input " << input; << " for input " << input;
EXPECT_EQ(expected, a4.s_addr) << " for input " << input; EXPECT_EQ(expected, a4.s_addr) << " for input " << input;
} }
#endif
#ifndef CARES_SYMBOL_HIDING
TEST_F(LibraryTest, Strsplit) { TEST_F(LibraryTest, Strsplit) {
using std::vector; using std::vector;
using std::string; using std::string;
@ -112,15 +110,11 @@ TEST_F(LibraryTest, Strsplit) {
ares__strsplit_free(out, n); ares__strsplit_free(out, n);
} }
} }
#endif
TEST_F(LibraryTest, InetPtoN) { TEST_F(LibraryTest, InetNetPtoN) {
uint32_t expected;
struct in_addr a4; struct in_addr a4;
struct in6_addr a6; struct in6_addr a6;
#ifndef CARES_SYMBOL_HIDING
uint32_t expected;
CheckPtoN4(4 * 8, 0x01020304, "1.2.3.4"); CheckPtoN4(4 * 8, 0x01020304, "1.2.3.4");
CheckPtoN4(4 * 8, 0x81010101, "129.1.1.1"); CheckPtoN4(4 * 8, 0x81010101, "129.1.1.1");
CheckPtoN4(4 * 8, 0xC0010101, "192.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, "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, "0x1122334", &a4, sizeof(a4) - 1));
EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "253", &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; i<ares__iface_ips_cnt(ips); i++) {
const char *name = ares__iface_ips_get_name(ips, i);
EXPECT_NE(nullptr, name);
int flags = (int)ares__iface_ips_get_flags(ips, i);
EXPECT_NE(0, (int)flags);
EXPECT_NE(nullptr, ares__iface_ips_get_addr(ips, i));
EXPECT_NE(0, ares__iface_ips_get_netmask(ips, i));
if (flags & ARES_IFACE_IP_LINKLOCAL && flags & ARES_IFACE_IP_V6) {
/* Hmm, seems not to work at least on MacOS
* EXPECT_NE(0, ares__iface_ips_get_ll_scope(ips, i));
*/
} else {
EXPECT_EQ(0, ares__iface_ips_get_ll_scope(ips, i));
}
unsigned int idx = ares__if_nametoindex(name);
EXPECT_NE(0, idx);
char namebuf[256];
EXPECT_EQ(std::string(ares__if_indextoname(idx, namebuf, sizeof(namebuf))), std::string(name));
}
/* Negative checking */
ares__iface_ips_get_name(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_flags(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_addr(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_netmask(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_ll_scope(ips, ares__iface_ips_cnt(ips));
ares__iface_ips(NULL, ARES_IFACE_IP_DEFAULT, NULL);
ares__iface_ips_cnt(NULL);
ares__iface_ips_get_name(NULL, 0);
ares__iface_ips_get_flags(NULL, 0);
ares__iface_ips_get_addr(NULL, 0);
ares__iface_ips_get_netmask(NULL, 0);
ares__iface_ips_get_ll_scope(NULL, 0);
ares__iface_ips_destroy(NULL);
ares__if_nametoindex(NULL);
ares__if_indextoname(0, NULL, 0);
ares__iface_ips_destroy(ips);
}
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));
}
#endif /* !CARES_SYMBOL_HIDING */
TEST_F(LibraryTest, InetPtoN) {
struct in_addr a4;
struct in6_addr a6;
EXPECT_EQ(1, ares_inet_pton(AF_INET, "1.2.3.4", &a4)); EXPECT_EQ(1, ares_inet_pton(AF_INET, "1.2.3.4", &a4));
EXPECT_EQ(1, ares_inet_pton(AF_INET6, "12:34::ff", &a6)); EXPECT_EQ(1, ares_inet_pton(AF_INET6, "12:34::ff", &a6));
EXPECT_EQ(1, ares_inet_pton(AF_INET6, "12:34::ffff:1.2.3.4", &a6)); EXPECT_EQ(1, ares_inet_pton(AF_INET6, "12:34::ffff:1.2.3.4", &a6));
@ -251,18 +374,6 @@ TEST_F(LibraryTest, FreeCorruptData) {
free(data); free(data);
} }
#ifndef CARES_SYMBOL_HIDING
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(LibraryInit, StrdupFailures) { TEST(LibraryInit, StrdupFailures) {
EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL)); EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
char* copy = ares_strdup("string"); char* copy = ares_strdup("string");
@ -277,12 +388,6 @@ TEST_F(LibraryTest, StrdupFailures) {
EXPECT_EQ(nullptr, copy); 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) { TEST_F(FileChannelTest, GetAddrInfoHostsPositive) {
TempFile hostsfile("1.2.3.4 example.com \n" TempFile hostsfile("1.2.3.4 example.com \n"
" 2.3.4.5\tgoogle.com www.google.com\twww2.google.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) { TEST_F(LibraryTest, DNSRecord) {
ares_dns_record_t *dnsrec = NULL; ares_dns_record_t *dnsrec = NULL;
ares_dns_rr_t *rr = NULL; ares_dns_rr_t *rr = NULL;
@ -677,13 +769,11 @@ TEST_F(LibraryTest, DNSRecord) {
/* Write */ /* Write */
EXPECT_EQ(ARES_SUCCESS, ares_dns_write(dnsrec, &msg, &msglen)); EXPECT_EQ(ARES_SUCCESS, ares_dns_write(dnsrec, &msg, &msglen));
#ifndef CARES_SYMBOL_HIDING
ares__buf_t *hexdump = ares__buf_create(); ares__buf_t *hexdump = ares__buf_create();
EXPECT_EQ(ARES_SUCCESS, ares__buf_hexdump(hexdump, msg, msglen)); EXPECT_EQ(ARES_SUCCESS, ares__buf_hexdump(hexdump, msg, msglen));
char *hexdata = ares__buf_finish_str(hexdump, NULL); char *hexdata = ares__buf_finish_str(hexdump, NULL);
//printf("HEXDUMP\n%s", hexdata); //printf("HEXDUMP\n%s", hexdata);
ares_free(hexdata); ares_free(hexdata);
#endif
ares_dns_record_destroy(dnsrec); dnsrec = NULL; 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(nscount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_AUTHORITY));
EXPECT_EQ(arcount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ADDITIONAL)); EXPECT_EQ(arcount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ADDITIONAL));
#ifndef CARES_SYMBOL_HIDING
/* Iterate and print */ /* Iterate and print */
ares__buf_t *printmsg = ares__buf_create(); ares__buf_t *printmsg = ares__buf_create();
ares__buf_append_str(printmsg, ";; ->>HEADER<<- opcode: "); ares__buf_append_str(printmsg, ";; ->>HEADER<<- opcode: ");
@ -817,7 +906,6 @@ TEST_F(LibraryTest, DNSRecord) {
char *printdata = ares__buf_finish_str(printmsg, NULL); char *printdata = ares__buf_finish_str(printmsg, NULL);
//printf("%s", printdata); //printf("%s", printdata);
ares_free(printdata); ares_free(printdata);
#endif
ares_dns_record_destroy(dnsrec); ares_dns_record_destroy(dnsrec);
ares_free_string(msg); ares_free_string(msg);
@ -983,24 +1071,6 @@ TEST_F(LibraryTest, DNSParseFlags) {
ares_free_string(msg); msg = NULL; 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) { TEST_F(LibraryTest, ArrayMisuse) {
EXPECT_EQ(NULL, ares__array_create(0, NULL)); EXPECT_EQ(NULL, ares__array_create(0, NULL));
ares__array_destroy(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(ARES_FALSE, ares__buf_begins_with(NULL, NULL, 0));
EXPECT_EQ((size_t)0, ares__buf_get_position(NULL)); 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__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)); 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) { TEST_F(LibraryTest, HtableAsvpMisuse) {
EXPECT_EQ(ARES_FALSE, ares__htable_asvp_insert(NULL, ARES_SOCKET_BAD, NULL)); 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)); 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); 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 { typedef struct {
unsigned int id; unsigned int id;
ares__buf_t *buf; ares__buf_t *buf;
@ -1453,65 +1497,6 @@ TEST_F(LibraryTest, HtableStrvp) {
ares__htable_strvp_destroy(h); 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; i<ares__iface_ips_cnt(ips); i++) {
const char *name = ares__iface_ips_get_name(ips, i);
EXPECT_NE(nullptr, name);
int flags = (int)ares__iface_ips_get_flags(ips, i);
EXPECT_NE(0, (int)flags);
EXPECT_NE(nullptr, ares__iface_ips_get_addr(ips, i));
EXPECT_NE(0, ares__iface_ips_get_netmask(ips, i));
if (flags & ARES_IFACE_IP_LINKLOCAL && flags & ARES_IFACE_IP_V6) {
/* Hmm, seems not to work at least on MacOS
* EXPECT_NE(0, ares__iface_ips_get_ll_scope(ips, i));
*/
} else {
EXPECT_EQ(0, ares__iface_ips_get_ll_scope(ips, i));
}
unsigned int idx = ares__if_nametoindex(name);
EXPECT_NE(0, idx);
char namebuf[256];
EXPECT_EQ(std::string(ares__if_indextoname(idx, namebuf, sizeof(namebuf))), std::string(name));
}
/* Negative checking */
ares__iface_ips_get_name(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_flags(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_addr(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_netmask(ips, ares__iface_ips_cnt(ips));
ares__iface_ips_get_ll_scope(ips, ares__iface_ips_cnt(ips));
ares__iface_ips(NULL, ARES_IFACE_IP_DEFAULT, NULL);
ares__iface_ips_cnt(NULL);
ares__iface_ips_get_name(NULL, 0);
ares__iface_ips_get_flags(NULL, 0);
ares__iface_ips_get_addr(NULL, 0);
ares__iface_ips_get_netmask(NULL, 0);
ares__iface_ips_get_ll_scope(NULL, 0);
ares__iface_ips_destroy(NULL);
ares__if_nametoindex(NULL);
ares__if_indextoname(0, NULL, 0);
ares__iface_ips_destroy(ips);
}
#endif
TEST_F(DefaultChannelTest, SaveInvalidChannel) { TEST_F(DefaultChannelTest, SaveInvalidChannel) {
ares__slist_t *saved = channel_->servers; ares__slist_t *saved = channel_->servers;
channel_->servers = NULL; channel_->servers = NULL;

Loading…
Cancel
Save