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
# Docs
Files: AUTHORS CHANGES CHANGES.0 CONTRIBUTING.md GIT-INFO NEWS README.cares README.md README.msvc RELEASE-NOTES RELEASE-PROCEDURE.md SECURITY.md DEVELOPER-NOTES.md TODO INSTALL.md test/README.md test/gmock-1.11.0/README.md src/lib/thirdparty/apple/README.md
Files: AUTHORS CONTRIBUTING.md GIT-INFO README.md README.msvc RELEASE-PROCEDURE.md RELEASE-NOTES.md SECURITY.md DEVELOPER-NOTES.md INSTALL.md test/README.md src/lib/include/README.md src/lib/thirdparty/apple/README.md
Copyright: The c-ares project and its contributors.
License: MIT

@ -43,7 +43,8 @@ CP = copy
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm -aa &
-wcd=201 -bt=nt -d+ -dCARES_BUILDING_LIBRARY &
-dNTDDI_VERSION=0x06020000 -I. -I.\include -I.\src\lib $(SYS_INCL)
-dNTDDI_VERSION=0x06020000 -I. -I.\include -I.\src\lib -I.\src\lib\include &
$(SYS_INCL)
LFLAGS = option quiet, map, caseexact, eliminate

@ -23,7 +23,7 @@ VPATH = src/lib src/tools
WATT32_ROOT = $(realpath $(WATT_ROOT))
WATT32_LIB = $(WATT32_ROOT)/lib/libwatt.a
CFLAGS = -g -O2 -I./include -I./src/lib \
CFLAGS = -g -O2 -I./include -I./src/lib -I./src/lib/include \
-I$(WATT32_ROOT)/inc \
-Wall \
-Wextra \

@ -19,7 +19,7 @@ RANLIB = $(CROSSPREFIX)ranlib
#RM = rm -f
CP = cp -afv
CFLAGS = $(CARES_CFLAG_EXTRAS) -O2 -Wall -I./include -I./src/lib -D_WIN32_WINNT=0x0602
CFLAGS = $(CARES_CFLAG_EXTRAS) -O2 -Wall -I./include -I./src/lib -I./src/lib/include -D_WIN32_WINNT=0x0602
CFLAGS += -DCARES_STATICLIB
LDFLAGS = $(CARES_LDFLAG_EXTRAS) -s
LIBS = -lws2_32 -liphlpapi

@ -192,7 +192,7 @@ EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib
CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /RTCsu
CC_CFLAGS = $(CFLAGS) /D_REENTRANT /I.\src\lib /I.\include /W3 /EHsc /FD
CC_CFLAGS = $(CFLAGS) /D_REENTRANT /I.\src\lib /I.\include /I.\src\lib\include /W3 /EHsc /FD
RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG"
@ -344,15 +344,6 @@ PROG3_OBJS = $(PROG3_OBJS) $(PROG3_OBJDIR)\ahost.obj
{$(SRCDIR)\src\tools}.c{$(PROG3_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(PROG3_OBJDIR)\ /c $<
# Hack Alert! we reference ../lib/str files in the Makefile.inc for tools as they
# share some files with the library itself. We need to hack around that here.
{$(SRCDIR)\src\lib\str}.c{$(PROG2_OBJDIR)\..\lib\str}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG2_OBJDIR)\str\$(@F) /Fd$(PROG2_OBJDIR)\str\ /c $<
{$(SRCDIR)\src\lib\str}.c{$(PROG3_OBJDIR)\..\lib\str}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG3_OBJDIR)\str\$(@F) /Fd$(PROG3_OBJDIR)\str\ /c $<
# ------------------------------------------------------------- #
# ------------------------------------------------------------- #
# Default target when no CFG library type has been specified, #

@ -53,6 +53,7 @@ IF (CARES_SHARED)
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
TARGET_COMPILE_DEFINITIONS (${PROJECT_NAME} PRIVATE HAVE_CONFIG_H=1 CARES_BUILDING_LIBRARY)
@ -110,6 +111,7 @@ IF (CARES_STATIC)
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
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 \
-I$(top_builddir)/src/lib \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src/lib
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include
lib_LTLIBRARIES = libcares.la

@ -81,7 +81,6 @@ CSOURCES = ares__addrinfo2hostent.c \
record/ares_dns_record.c \
record/ares_dns_write.c \
str/ares__buf.c \
str/ares_strcasecmp.c \
str/ares_str.c \
str/ares_strsplit.c \
util/ares__iface_ips.c \
@ -98,23 +97,21 @@ HHEADERS = ares_android.h \
ares_platform.h \
ares_private.h \
ares_setup.h \
dsa/ares__array.h \
dsa/ares__htable.h \
dsa/ares__htable_asvp.h \
dsa/ares__htable_strvp.h \
dsa/ares__htable_szvp.h \
dsa/ares__htable_vpvp.h \
dsa/ares__llist.h \
dsa/ares__slist.h \
event/ares_event.h \
event/ares_event_win32.h \
include/ares__array.h \
include/ares__buf.h \
include/ares__htable_asvp.h \
include/ares__htable_strvp.h \
include/ares__htable_szvp.h \
include/ares__htable_vpvp.h \
include/ares__llist.h \
include/ares_str.h \
record/ares_dns_multistring.h \
record/ares_dns_private.h \
str/ares__buf.h \
str/ares_strcasecmp.h \
str/ares_str.h \
str/ares_strsplit.h \
util/ares__iface_ips.h \
util/ares__threads.h \
thirdparty/apple/dnsinfo.h

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

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

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

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

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

@ -100,20 +100,21 @@ W32_FUNC const char *_w32_GetHostsFile(void);
#endif
#include "ares_mem.h"
#include "ares_ipv6.h"
struct ares_rand_state;
typedef struct ares_rand_state ares_rand_state;
#include "dsa/ares__array.h"
#include "dsa/ares__llist.h"
#include "ares__array.h"
#include "ares__llist.h"
#include "dsa/ares__slist.h"
#include "dsa/ares__htable_strvp.h"
#include "dsa/ares__htable_szvp.h"
#include "dsa/ares__htable_asvp.h"
#include "dsa/ares__htable_vpvp.h"
#include "ares__htable_strvp.h"
#include "ares__htable_szvp.h"
#include "ares__htable_asvp.h"
#include "ares__htable_vpvp.h"
#include "record/ares_dns_multistring.h"
#include "str/ares__buf.h"
#include "ares__buf.h"
#include "record/ares_dns_private.h"
#include "util/ares__iface_ips.h"
#include "util/ares__threads.h"
@ -123,19 +124,9 @@ typedef struct ares_rand_state ares_rand_state;
# define getenv(ptr) ares_getenv(ptr)
#endif
#include "str/ares_str.h"
#include "ares_str.h"
#include "str/ares_strsplit.h"
#ifndef HAVE_STRCASECMP
# include "str/ares_strcasecmp.h"
# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2)
#endif
#ifndef HAVE_STRNCASECMP
# include "str/ares_strcasecmp.h"
# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n)
#endif
/********* EDNS defines section ******/
#define EDNSPACKETSZ \
1232 /* Reasonable UDP payload size, as agreed by operators \
@ -469,13 +460,6 @@ struct ares_channeldata {
/* Does the domain end in ".onion" or ".onion."? Case-insensitive. */
ares_bool_t ares__is_onion_domain(const char *name);
/* Memory management functions */
extern void *(*ares_malloc)(size_t size);
extern void *(*ares_realloc)(void *ptr, size_t size);
extern void (*ares_free)(void *ptr);
void *ares_malloc_zero(size_t size);
void *ares_realloc_zero(void *ptr, size_t orig_size, size_t new_size);
/* return true if now is exactly check time or later */
ares_bool_t ares__timedout(const ares_timeval_t *now,
const ares_timeval_t *check);

@ -1190,12 +1190,12 @@ static ares_bool_t same_questions(const ares_query_t *query,
* server to preserve the case of the name in the response packet.
* https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00
*/
if (strcmp(qname, aname) != 0) {
if (!ares_streq(qname, aname)) {
goto done;
}
} else {
/* without DNS0x20 use case-insensitive matching */
if (strcasecmp(qname, aname) != 0) {
if (!ares_strcaseeq(qname, aname)) {
goto done;
}
}

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

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

@ -154,7 +154,7 @@ static ares_bool_t search_is_duplicate(const ares_sysconfig_t *sysconfig,
{
size_t i;
for (i = 0; i < sysconfig->ndomains; i++) {
if (strcasecmp(sysconfig->domains[i], name) == 0) {
if (ares_strcaseeq(sysconfig->domains[i], name)) {
return ARES_TRUE;
}
}

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

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

@ -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
#define __ARES__ARRAY_H
#include "ares.h"
/*! \addtogroup ares__array Array Data Structure
*
* This is an array with helpers. It is meant to have as little overhead
@ -72,8 +74,8 @@ typedef int (*ares__array_cmp_t)(const void *data1, const void *data2);
*
* \return array object or NULL on out of memory
*/
ares__array_t *ares__array_create(size_t member_size,
ares__array_destructor_t destruct);
CARES_EXTERN ares__array_t *
ares__array_create(size_t member_size, ares__array_destructor_t destruct);
/*! Request the array be at least the requested size. Useful if the desired
@ -83,7 +85,8 @@ ares__array_t *ares__array_create(size_t member_size,
* \param[in] size Minimum number of members
* \return ARES_SUCCESS on success, ARES_EFORMERR on misuse,
* ARES_ENOMEM on out of memory */
ares_status_t ares__array_set_size(ares__array_t *arr, size_t size);
CARES_EXTERN ares_status_t ares__array_set_size(ares__array_t *arr,
size_t size);
/*! Sort the array using the given comparison function. This is not
* persistent, any future elements inserted will not maintain this sort.
@ -92,14 +95,15 @@ ares_status_t ares__array_set_size(ares__array_t *arr, size_t size);
* \param[in] cb Sort callback
* \return ARES_SUCCESS on success
*/
ares_status_t ares__array_sort(ares__array_t *arr, ares__array_cmp_t cmp);
CARES_EXTERN ares_status_t ares__array_sort(ares__array_t *arr,
ares__array_cmp_t cmp);
/*! Destroy an array object. If a destructor is set, will be called on each
* member of the array.
*
* \param[in] arr Initialized array object.
*/
void ares__array_destroy(ares__array_t *arr);
CARES_EXTERN void ares__array_destroy(ares__array_t *arr);
/*! Retrieve the array in the native format. This will also destroy the
* container. It is the responsibility of the caller to free the returned
@ -109,14 +113,14 @@ void ares__array_destroy(ares__array_t *arr);
* \param[out] num_members the number of members in the returned array
* \return pointer to native array on success, NULL on failure.
*/
void *ares__array_finish(ares__array_t *arr, size_t *num_members);
CARES_EXTERN void *ares__array_finish(ares__array_t *arr, size_t *num_members);
/*! Retrieve the number of members in the array
*
* \param[in] arr Initialized array object.
* \return numbrer of members
*/
size_t ares__array_len(const ares__array_t *arr);
CARES_EXTERN size_t ares__array_len(const ares__array_t *arr);
/*! Insert a new array member at the given index
*
@ -127,7 +131,8 @@ size_t ares__array_len(const ares__array_t *arr);
* \return ARES_SUCCESS on success, ARES_EFORMERR on bad index,
* ARES_ENOMEM on out of memory.
*/
ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr,
CARES_EXTERN ares_status_t ares__array_insert_at(void **elem_ptr,
ares__array_t *arr,
size_t idx);
/*! Insert a new array member at the end of the array
@ -136,7 +141,8 @@ ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr,
* \param[in] arr Initialized array object.
* \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory.
*/
ares_status_t ares__array_insert_last(void **elem_ptr, ares__array_t *arr);
CARES_EXTERN ares_status_t ares__array_insert_last(void **elem_ptr,
ares__array_t *arr);
/*! Insert a new array member at the beginning of the array
*
@ -144,39 +150,41 @@ ares_status_t ares__array_insert_last(void **elem_ptr, ares__array_t *arr);
* \param[in] arr Initialized array object.
* \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory.
*/
ares_status_t ares__array_insert_first(void **elem_ptr, ares__array_t *arr);
CARES_EXTERN ares_status_t ares__array_insert_first(void **elem_ptr,
ares__array_t *arr);
/*! Fetch a pointer to the given element in the array
* \param[in] array Initialized array object
* \param[in] idx Index to fetch
* \return pointer on success, NULL on failure */
void *ares__array_at(ares__array_t *arr, size_t idx);
CARES_EXTERN void *ares__array_at(ares__array_t *arr, size_t idx);
/*! Fetch a pointer to the first element in the array
* \param[in] array Initialized array object
* \return pointer on success, NULL on failure */
void *ares__array_first(ares__array_t *arr);
CARES_EXTERN void *ares__array_first(ares__array_t *arr);
/*! Fetch a pointer to the last element in the array
* \param[in] array Initialized array object
* \return pointer on success, NULL on failure */
void *ares__array_last(ares__array_t *arr);
CARES_EXTERN void *ares__array_last(ares__array_t *arr);
/*! Fetch a constant pointer to the given element in the array
* \param[in] array Initialized array object
* \param[in] idx Index to fetch
* \return pointer on success, NULL on failure */
const void *ares__array_at_const(const ares__array_t *arr, size_t idx);
CARES_EXTERN const void *ares__array_at_const(const ares__array_t *arr,
size_t idx);
/*! Fetch a constant pointer to the first element in the array
* \param[in] array Initialized array object
* \return pointer on success, NULL on failure */
const void *ares__array_first_const(const ares__array_t *arr);
CARES_EXTERN const void *ares__array_first_const(const ares__array_t *arr);
/*! Fetch a constant pointer to the last element in the array
* \param[in] array Initialized array object
* \return pointer on success, NULL on failure */
const void *ares__array_last_const(const ares__array_t *arr);
CARES_EXTERN const void *ares__array_last_const(const ares__array_t *arr);
/*! Claim the data from the specified array index, copying it to the buffer
* provided by the caller. The index specified in the array will then be
@ -192,7 +200,7 @@ const void *ares__array_last_const(const ares__array_t *arr);
* \param[in] idx Index to claim
* \return ARES_SUCCESS on success, ARES_EFORMERR on usage failure.
*/
ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
CARES_EXTERN ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
ares__array_t *arr, size_t idx);
/*! Remove the member at the specified array index. The destructor will be
@ -202,21 +210,22 @@ ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
* \param[in] idx Index to remove
* \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use
*/
ares_status_t ares__array_remove_at(ares__array_t *arr, size_t idx);
CARES_EXTERN ares_status_t ares__array_remove_at(ares__array_t *arr,
size_t idx);
/*! Remove the first member of the array.
*
* \param[in] arr Initialized array object
* \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use
*/
ares_status_t ares__array_remove_first(ares__array_t *arr);
CARES_EXTERN ares_status_t ares__array_remove_first(ares__array_t *arr);
/*! Remove the last member of the array.
*
* \param[in] arr Initialized array object
* \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use
*/
ares_status_t ares__array_remove_last(ares__array_t *arr);
CARES_EXTERN ares_status_t ares__array_remove_last(ares__array_t *arr);
/*! @} */

@ -26,6 +26,8 @@
#ifndef __ARES__BUF_H
#define __ARES__BUF_H
#include "ares.h"
/*! \addtogroup ares__buf Safe Data Builder and buffer
*
* This is a buffer building and parsing framework with a focus on security over
@ -51,7 +53,7 @@ typedef struct ares__buf ares__buf_t;
*
* \return initialized buffer object or NULL if out of memory.
*/
ares__buf_t *ares__buf_create(void);
CARES_EXTERN ares__buf_t *ares__buf_create(void);
/*! Create a new buffer object that uses a user-provided data pointer. The
* data provided will not be manipulated, and cannot be appended to. This
@ -62,14 +64,15 @@ ares__buf_t *ares__buf_create(void);
*
* \return initialized buffer object or NULL if out of memory or misuse.
*/
ares__buf_t *ares__buf_create_const(const unsigned char *data, size_t data_len);
CARES_EXTERN ares__buf_t *ares__buf_create_const(const unsigned char *data,
size_t data_len);
/*! Destroy an initialized buffer object.
*
* \param[in] buf Initialized buf object
*/
void ares__buf_destroy(ares__buf_t *buf);
CARES_EXTERN void ares__buf_destroy(ares__buf_t *buf);
/*! Append multiple bytes to a dynamic buffer object
@ -79,7 +82,8 @@ void ares__buf_destroy(ares__buf_t *buf);
* \param[in] data_len Length of data to copy to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data,
CARES_EXTERN ares_status_t ares__buf_append(ares__buf_t *buf,
const unsigned char *data,
size_t data_len);
/*! Append a single byte to the dynamic buffer object
@ -88,7 +92,8 @@ ares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data,
* \param[in] b Single byte to append to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char b);
CARES_EXTERN ares_status_t ares__buf_append_byte(ares__buf_t *buf,
unsigned char b);
/*! Append a null-terminated string to the dynamic buffer object
*
@ -96,7 +101,8 @@ ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char b);
* \param[in] str String to append to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str);
CARES_EXTERN ares_status_t ares__buf_append_str(ares__buf_t *buf,
const char *str);
/*! Append a 16bit Big Endian number to the buffer.
*
@ -104,7 +110,8 @@ ares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str);
* \param[out] u16 16bit integer
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16);
CARES_EXTERN ares_status_t ares__buf_append_be16(ares__buf_t *buf,
unsigned short u16);
/*! Append a 32bit Big Endian number to the buffer.
*
@ -112,7 +119,8 @@ ares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16);
* \param[out] u32 32bit integer
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32);
CARES_EXTERN ares_status_t ares__buf_append_be32(ares__buf_t *buf,
unsigned int u32);
/*! Append a number in ASCII decimal form.
*
@ -121,8 +129,8 @@ ares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32);
* \param[in] len Length to output, use 0 for no padding
* \return ARES_SUCCESS on success
*/
ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num,
size_t len);
CARES_EXTERN ares_status_t ares__buf_append_num_dec(ares__buf_t *buf,
size_t num, size_t len);
/*! Append a number in ASCII hexadecimal form.
*
@ -131,8 +139,8 @@ ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num,
* \param[in] len Length to output, use 0 for no padding
* \return ARES_SUCCESS on success
*/
ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num,
size_t len);
CARES_EXTERN ares_status_t ares__buf_append_num_hex(ares__buf_t *buf,
size_t num, size_t len);
/*! Sets the current buffer length. This *may* be used if there is a need to
* override a prior position in the buffer, such as if there is a length
@ -147,7 +155,7 @@ ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num,
* \param[in] len Length to set
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len);
CARES_EXTERN ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len);
/*! Start a dynamic append operation that returns a buffer suitable for
@ -161,7 +169,8 @@ ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len);
* returned.
* \return Pointer to writable buffer or NULL on failure (usage, out of mem)
*/
unsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len);
CARES_EXTERN unsigned char *ares__buf_append_start(ares__buf_t *buf,
size_t *len);
/*! Finish a dynamic append operation. Called after
* ares__buf_append_start() once desired data is written.
@ -171,7 +180,7 @@ unsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len);
* operation. Must not be greater than returned from
* ares__buf_append_start().
*/
void ares__buf_append_finish(ares__buf_t *buf, size_t len);
CARES_EXTERN void ares__buf_append_finish(ares__buf_t *buf, size_t len);
/*! Write the data provided to the buffer in a hexdump format.
*
@ -180,7 +189,8 @@ void ares__buf_append_finish(ares__buf_t *buf, size_t len);
* \param[in] len Length of data to hexdump
* \return ARES_SUCCESS on success.
*/
ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data,
CARES_EXTERN ares_status_t ares__buf_hexdump(ares__buf_t *buf,
const unsigned char *data,
size_t len);
/*! Clean up ares__buf_t and return allocated pointer to unprocessed data. It
@ -191,7 +201,7 @@ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data,
* \param[out] len Length of data returned
* \return pointer to unprocessed data (may be zero length) or NULL on error.
*/
unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len);
CARES_EXTERN unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len);
/*! Clean up ares__buf_t and return allocated pointer to unprocessed data and
* return it as a string (null terminated). It is the responsibility of the
@ -207,7 +217,7 @@ unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len);
* \param[out] len Optional. Length of data returned, or NULL if not needed.
* \return pointer to unprocessed data or NULL on error.
*/
char *ares__buf_finish_str(ares__buf_t *buf, size_t *len);
CARES_EXTERN char *ares__buf_finish_str(ares__buf_t *buf, size_t *len);
/*! Tag a position to save in the buffer in case parsing needs to rollback,
* such as if insufficient data is available, but more data may be added in
@ -216,14 +226,14 @@ char *ares__buf_finish_str(ares__buf_t *buf, size_t *len);
*
* \param[in] buf Initialized buffer object
*/
void ares__buf_tag(ares__buf_t *buf);
CARES_EXTERN void ares__buf_tag(ares__buf_t *buf);
/*! Rollback to a tagged position. Will automatically clear the tag.
*
* \param[in] buf Initialized buffer object
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_tag_rollback(ares__buf_t *buf);
CARES_EXTERN ares_status_t ares__buf_tag_rollback(ares__buf_t *buf);
/*! Clear the tagged position without rolling back. You should do this any
* time a tag is no longer needed as future append operations can reclaim
@ -232,7 +242,7 @@ ares_status_t ares__buf_tag_rollback(ares__buf_t *buf);
* \param[in] buf Initialized buffer object
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_tag_clear(ares__buf_t *buf);
CARES_EXTERN ares_status_t ares__buf_tag_clear(ares__buf_t *buf);
/*! Fetch the buffer and length of data starting from the tagged position up
* to the _current_ position. It will not unset the tagged position. The
@ -243,14 +253,15 @@ ares_status_t ares__buf_tag_clear(ares__buf_t *buf);
* \return NULL on failure (such as no tag), otherwise pointer to start of
* buffer
*/
const unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf, size_t *len);
CARES_EXTERN const unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf,
size_t *len);
/*! Get the length of the current tag offset to the current position.
*
* \param[in] buf Initialized buffer object
* \return length
*/
size_t ares__buf_tag_length(const ares__buf_t *buf);
CARES_EXTERN size_t ares__buf_tag_length(const ares__buf_t *buf);
/*! Fetch the bytes starting from the tagged position up to the _current_
* position using the provided buffer. It will not unset the tagged position.
@ -261,8 +272,9 @@ size_t ares__buf_tag_length(const ares__buf_t *buf);
* buffer.
* \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size
*/
ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf,
unsigned char *bytes, size_t *len);
CARES_EXTERN ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf,
unsigned char *bytes,
size_t *len);
/*! Fetch the bytes starting from the tagged position up to the _current_
* position as a NULL-terminated string using the provided buffer. The data
@ -276,8 +288,8 @@ ares_status_t ares__buf_tag_fetch_bytes(const ares__buf_t *buf,
* \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size,
* ARES_EBADSTR if not printable ASCII
*/
ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str,
size_t len);
CARES_EXTERN ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf,
char *str, size_t len);
/*! Consume the given number of bytes without reading them.
*
@ -285,7 +297,7 @@ ares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str,
* \param[in] len Length to consume
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_consume(ares__buf_t *buf, size_t len);
CARES_EXTERN ares_status_t ares__buf_consume(ares__buf_t *buf, size_t len);
/*! Fetch a 16bit Big Endian number from the buffer.
*
@ -293,7 +305,8 @@ ares_status_t ares__buf_consume(ares__buf_t *buf, size_t len);
* \param[out] u16 Buffer to hold 16bit integer
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16);
CARES_EXTERN ares_status_t ares__buf_fetch_be16(ares__buf_t *buf,
unsigned short *u16);
/*! Fetch a 32bit Big Endian number from the buffer.
*
@ -301,7 +314,8 @@ ares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16);
* \param[out] u32 Buffer to hold 32bit integer
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32);
CARES_EXTERN ares_status_t ares__buf_fetch_be32(ares__buf_t *buf,
unsigned int *u32);
/*! Fetch the requested number of bytes into the provided buffer
@ -311,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)
* \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);
@ -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.
* \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,
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)
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf,
ares__buf_t *dest, size_t len);
CARES_EXTERN ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf,
ares__buf_t *dest,
size_t len);
/*! Fetch the requested number of bytes and return a new buffer that must be
* ares_free()'d by the caller. The returned buffer is a null terminated
@ -350,7 +367,8 @@ ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf,
* \param[out] str Pointer passed by reference. Will be allocated.
* \return ARES_SUCCESS or one of the c-ares error codes
*/
ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str);
CARES_EXTERN ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len,
char **str);
/*! Consume whitespace characters (0x09, 0x0B, 0x0C, 0x0D, 0x20, and optionally
* 0x0A).
@ -360,7 +378,7 @@ ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str);
* ARES_FALSE otherwise.
* \return number of whitespace characters consumed
*/
size_t ares__buf_consume_whitespace(ares__buf_t *buf,
CARES_EXTERN size_t ares__buf_consume_whitespace(ares__buf_t *buf,
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
* \return number of characters consumed
*/
size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf);
CARES_EXTERN size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf);
/*! Consume until a character in the character set provided is reached. Does
@ -385,8 +403,8 @@ size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf);
* 0 if not found.
* \return number of characters consumed
*/
size_t ares__buf_consume_until_charset(ares__buf_t *buf,
const unsigned char *charset, size_t len,
CARES_EXTERN size_t ares__buf_consume_until_charset(
ares__buf_t *buf, const unsigned char *charset, size_t len,
ares_bool_t require_charset);
@ -397,7 +415,8 @@ size_t ares__buf_consume_until_charset(ares__buf_t *buf,
* \param[in] len length of character set
* \return number of characters consumed
*/
size_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset,
CARES_EXTERN size_t ares__buf_consume_charset(ares__buf_t *buf,
const unsigned char *charset,
size_t len);
@ -409,7 +428,8 @@ size_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset,
* ARES_FALSE otherwise.
* \return number of characters consumed
*/
size_t ares__buf_consume_line(ares__buf_t *buf, ares_bool_t include_linefeed);
CARES_EXTERN size_t ares__buf_consume_line(ares__buf_t *buf,
ares_bool_t include_linefeed);
typedef enum {
/*! No flags */
@ -457,9 +477,9 @@ typedef enum {
* objects.
* \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
*/
ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
size_t delims_len, ares__buf_split_t flags,
size_t max_sections, ares__llist_t **list);
CARES_EXTERN ares_status_t ares__buf_split(
ares__buf_t *buf, const unsigned char *delims, size_t delims_len,
ares__buf_split_t flags, size_t max_sections, ares__llist_t **list);
/*! Check the unprocessed buffer to see if it begins with the sequence of
@ -470,8 +490,9 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
* \param[in] data_len Length of data to compare.
* \return ARES_TRUE on match, ARES_FALSE otherwise.
*/
ares_bool_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data, size_t data_len);
CARES_EXTERN ares_bool_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data,
size_t data_len);
/*! Size of unprocessed remaining data length
@ -479,7 +500,7 @@ ares_bool_t ares__buf_begins_with(const ares__buf_t *buf,
* \param[in] buf Initialized buffer object
* \return length remaining
*/
size_t ares__buf_len(const ares__buf_t *buf);
CARES_EXTERN size_t ares__buf_len(const ares__buf_t *buf);
/*! Retrieve a pointer to the currently unprocessed data. Generally this isn't
* recommended to be used in practice. The returned pointer may be invalidated
@ -489,7 +510,8 @@ size_t ares__buf_len(const ares__buf_t *buf);
* \param[out] len Length of available data
* \return Pointer to buffer of unprocessed data
*/
const unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len);
CARES_EXTERN const unsigned char *ares__buf_peek(const ares__buf_t *buf,
size_t *len);
/*! Wipe any processed data from the beginning of the buffer. This will
@ -512,7 +534,7 @@ const unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len);
*
* \param[in] buf Initialized buffer object
*/
void ares__buf_reclaim(ares__buf_t *buf);
CARES_EXTERN void ares__buf_reclaim(ares__buf_t *buf);
/*! Set the current offset within the internal buffer.
*
@ -528,7 +550,7 @@ void ares__buf_reclaim(ares__buf_t *buf);
* \param[in] idx Index to set position
* \return ARES_SUCCESS if valid index
*/
ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx);
CARES_EXTERN ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx);
/*! Get the current offset within the internal buffer.
*
@ -542,7 +564,7 @@ ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx);
* \param[in] buf Initialized buffer object
* \return index of current position
*/
size_t ares__buf_get_position(const ares__buf_t *buf);
CARES_EXTERN size_t ares__buf_get_position(const ares__buf_t *buf);
/*! Parse a character-string as defined in RFC1035, as a null-terminated
* string.
@ -556,29 +578,9 @@ size_t ares__buf_get_position(const ares__buf_t *buf);
* ares_free()'d by the caller.
* \return ARES_SUCCESS on success
*/
ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len,
char **name);
/*! Parse an array of character strings as defined in RFC1035, as binary,
* however, for convenience this does guarantee a NULL terminator (that is
* not included in the length for each value).
*
* \param[in] buf initialized buffer object
* \param[in] remaining_len maximum length that should be used for
* parsing the string, this is often less than
* the remaining buffer and is based on the RR
* record length.
* \param[out] strs Pointer passed by reference to be filled in
* with
* the array of values.
* \param[out] validate_printable Validate the strings contain only printable
* data.
* \return ARES_SUCCESS on success
*/
ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf,
CARES_EXTERN ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf,
size_t remaining_len,
ares__dns_multistring_t **strs,
ares_bool_t validate_printable);
char **name);
/*! Parse a character-string as defined in RFC1035, as binary, however for
* convenience this does guarantee a NULL terminator (that is not included
@ -594,8 +596,10 @@ ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf,
* \param[out] bin_len Length of returned string.
* \return ARES_SUCCESS on success
*/
ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len,
unsigned char **bin, size_t *bin_len);
CARES_EXTERN ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf,
size_t remaining_len,
unsigned char **bin,
size_t *bin_len);
/*! Load data from specified file path into provided buffer. The entire file
* is loaded into memory.
@ -606,7 +610,8 @@ ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len,
* \return ARES_ENOTFOUND if file not found, ARES_EFILE if issues reading
* file, ARES_ENOMEM if out of memory, ARES_SUCCESS on success.
*/
ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf);
CARES_EXTERN ares_status_t ares__buf_load_file(const char *filename,
ares__buf_t *buf);
/*! @} */

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

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

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

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

@ -59,7 +59,8 @@ typedef void (*ares__llist_destructor_t)(void *data);
* \param[in] destruct Optional. Destructor to call on all removed nodes
* \return linked list object or NULL on out of memory
*/
ares__llist_t *ares__llist_create(ares__llist_destructor_t destruct);
CARES_EXTERN ares__llist_t *
ares__llist_create(ares__llist_destructor_t destruct);
/*! Replace destructor for linked list nodes. Typically this is used
* when wanting to disable the destructor by using NULL.
@ -67,7 +68,8 @@ ares__llist_t *ares__llist_create(ares__llist_destructor_t destruct);
* \param[in] list Initialized linked list object
* \param[in] destruct replacement destructor, NULL is allowed
*/
void ares__llist_replace_destructor(ares__llist_t *list,
CARES_EXTERN void
ares__llist_replace_destructor(ares__llist_t *list,
ares__llist_destructor_t destruct);
/*! Insert value as the first node in the linked list
@ -77,7 +79,8 @@ void ares__llist_replace_destructor(ares__llist_t *list
* \return node object referencing place in list, or null if out of memory or
* misuse
*/
ares__llist_node_t *ares__llist_insert_first(ares__llist_t *list, void *val);
CARES_EXTERN ares__llist_node_t *ares__llist_insert_first(ares__llist_t *list,
void *val);
/*! Insert value as the last node in the linked list
*
@ -86,7 +89,8 @@ ares__llist_node_t *ares__llist_insert_first(ares__llist_t *list, void *val);
* \return node object referencing place in list, or null if out of memory or
* misuse
*/
ares__llist_node_t *ares__llist_insert_last(ares__llist_t *list, void *val);
CARES_EXTERN ares__llist_node_t *ares__llist_insert_last(ares__llist_t *list,
void *val);
/*! Insert value before specified node in the linked list
*
@ -95,8 +99,8 @@ ares__llist_node_t *ares__llist_insert_last(ares__llist_t *list, void *val);
* \return node object referencing place in list, or null if out of memory or
* misuse
*/
ares__llist_node_t *ares__llist_insert_before(ares__llist_node_t *node,
void *val);
CARES_EXTERN ares__llist_node_t *
ares__llist_insert_before(ares__llist_node_t *node, void *val);
/*! Insert value after specified node in the linked list
*
@ -105,22 +109,22 @@ ares__llist_node_t *ares__llist_insert_before(ares__llist_node_t *node,
* \return node object referencing place in list, or null if out of memory or
* misuse
*/
ares__llist_node_t *ares__llist_insert_after(ares__llist_node_t *node,
void *val);
CARES_EXTERN ares__llist_node_t *
ares__llist_insert_after(ares__llist_node_t *node, void *val);
/*! Obtain first node in list
*
* \param[in] list Initialized list object
* \return first node in list or NULL if none
*/
ares__llist_node_t *ares__llist_node_first(ares__llist_t *list);
CARES_EXTERN ares__llist_node_t *ares__llist_node_first(ares__llist_t *list);
/*! Obtain last node in list
*
* \param[in] list Initialized list object
* \return last node in list or NULL if none
*/
ares__llist_node_t *ares__llist_node_last(ares__llist_t *list);
CARES_EXTERN ares__llist_node_t *ares__llist_node_last(ares__llist_t *list);
/*! Obtain a node based on its index. This is an O(n) operation.
*
@ -128,21 +132,24 @@ ares__llist_node_t *ares__llist_node_last(ares__llist_t *list);
* \param[in] idx Index of node to retrieve
* \return node at index or NULL if invalid index
*/
ares__llist_node_t *ares__llist_node_idx(ares__llist_t *list, size_t idx);
CARES_EXTERN ares__llist_node_t *ares__llist_node_idx(ares__llist_t *list,
size_t idx);
/*! Obtain next node in respect to specified node
*
* \param[in] node Node referenced
* \return node or NULL if none
*/
ares__llist_node_t *ares__llist_node_next(ares__llist_node_t *node);
CARES_EXTERN ares__llist_node_t *
ares__llist_node_next(ares__llist_node_t *node);
/*! Obtain previous node in respect to specified node
*
* \param[in] node Node referenced
* \return node or NULL if none
*/
ares__llist_node_t *ares__llist_node_prev(ares__llist_node_t *node);
CARES_EXTERN ares__llist_node_t *
ares__llist_node_prev(ares__llist_node_t *node);
/*! Obtain value from node
@ -150,41 +157,41 @@ ares__llist_node_t *ares__llist_node_prev(ares__llist_node_t *node);
* \param[in] node Node referenced
* \return user provided value from node
*/
void *ares__llist_node_val(ares__llist_node_t *node);
CARES_EXTERN void *ares__llist_node_val(ares__llist_node_t *node);
/*! Obtain the number of entries in the list
*
* \param[in] list Initialized list object
* \return count
*/
size_t ares__llist_len(const ares__llist_t *list);
CARES_EXTERN size_t ares__llist_len(const ares__llist_t *list);
/*! Clear all entries in the list, but don't destroy the list object.
*
* \param[in] list Initialized list object
*/
void ares__llist_clear(ares__llist_t *list);
CARES_EXTERN void ares__llist_clear(ares__llist_t *list);
/*! Obtain list object from referenced node
*
* \param[in] node Node referenced
* \return list object node belongs to
*/
ares__llist_t *ares__llist_node_parent(ares__llist_node_t *node);
CARES_EXTERN ares__llist_t *ares__llist_node_parent(ares__llist_node_t *node);
/*! Obtain the first user-supplied value in the list
*
* \param[in] list Initialized list object
* \return first user supplied value or NULL if none
*/
void *ares__llist_first_val(ares__llist_t *list);
CARES_EXTERN void *ares__llist_first_val(ares__llist_t *list);
/*! Obtain the last user-supplied value in the list
*
* \param[in] list Initialized list object
* \return last user supplied value or NULL if none
*/
void *ares__llist_last_val(ares__llist_t *list);
CARES_EXTERN void *ares__llist_last_val(ares__llist_t *list);
/*! Take ownership of user-supplied value in list without calling destructor.
* Will unchain entry from list.
@ -192,26 +199,26 @@ void *ares__llist_last_val(ares__llist_t *list);
* \param[in] node Node referenced
* \return user supplied value
*/
void *ares__llist_node_claim(ares__llist_node_t *node);
CARES_EXTERN void *ares__llist_node_claim(ares__llist_node_t *node);
/*! Replace user-supplied value for node
*
* \param[in] node Node referenced
* \param[in] val new user-supplied value
*/
void ares__llist_node_replace(ares__llist_node_t *node, void *val);
CARES_EXTERN void ares__llist_node_replace(ares__llist_node_t *node, void *val);
/*! Destroy the node, removing it from the list and calling destructor.
*
* \param[in] node Node referenced
*/
void ares__llist_node_destroy(ares__llist_node_t *node);
CARES_EXTERN void ares__llist_node_destroy(ares__llist_node_t *node);
/*! Destroy the list object and all nodes in the list.
*
* \param[in] list Initialized list object
*/
void ares__llist_destroy(ares__llist_t *list);
CARES_EXTERN void ares__llist_destroy(ares__llist_t *list);
/*! Detach node from the current list and re-attach it to the new list as the
* last entry.
@ -219,7 +226,7 @@ void ares__llist_destroy(ares__llist_t *list);
* \param[in] node node to move
* \param[in] new_parent new list
*/
void ares__llist_node_move_parent_last(ares__llist_node_t *node,
CARES_EXTERN void ares__llist_node_move_parent_last(ares__llist_node_t *node,
ares__llist_t *new_parent);
/*! Detach node from the current list and re-attach it to the new list as the
@ -228,7 +235,7 @@ void ares__llist_node_move_parent_last(ares__llist_node_t *node,
* \param[in] node node to move
* \param[in] new_parent new list
*/
void ares__llist_node_move_parent_first(ares__llist_node_t *node,
CARES_EXTERN void ares__llist_node_move_parent_first(ares__llist_node_t *node,
ares__llist_t *new_parent);
/*! @} */

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

@ -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;
* goto done;
* }
* if (strcasecmp(ptrname, rname) != 0) {
* if (!ares_strcaseeq(ptrname, rname)) {
* 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++) {
if (strcasecmp(list[i].name, str) == 0) {
if (ares_strcaseeq(list[i].name, str)) {
*qclass = list[i].qclass;
return ARES_TRUE;
}
@ -726,7 +726,7 @@ ares_bool_t ares_dns_rec_type_fromstr(ares_dns_rec_type_t *qtype,
}
for (i = 0; list[i].name != NULL; i++) {
if (strcasecmp(list[i].name, str) == 0) {
if (ares_strcaseeq(list[i].name, str)) {
*qtype = list[i].type;
return ARES_TRUE;
}

@ -222,3 +222,74 @@ const unsigned char *
*len = strs->cache_str_len;
return strs->cache_str;
}
ares_status_t ares__dns_multistring_parse_buf(ares__buf_t *buf,
size_t remaining_len,
ares__dns_multistring_t **strs,
ares_bool_t validate_printable)
{
unsigned char len;
ares_status_t status = ARES_EBADRESP;
size_t orig_len = ares__buf_len(buf);
if (buf == NULL) {
return ARES_EFORMERR;
}
if (remaining_len == 0) {
return ARES_EBADRESP;
}
if (strs != NULL) {
*strs = ares__dns_multistring_create();
if (*strs == NULL) {
return ARES_ENOMEM;
}
}
while (orig_len - ares__buf_len(buf) < remaining_len) {
status = ares__buf_fetch_bytes(buf, &len, 1);
if (status != ARES_SUCCESS) {
break; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (len) {
/* When used by the _str() parser, it really needs to be validated to
* be a valid printable ascii string. Do that here */
if (validate_printable && ares__buf_len(buf) >= len) {
size_t mylen;
const char *data = (const char *)ares__buf_peek(buf, &mylen);
if (!ares__str_isprint(data, len)) {
status = ARES_EBADSTR;
break;
}
}
if (strs != NULL) {
unsigned char *data = NULL;
status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &data);
if (status != ARES_SUCCESS) {
break;
}
status = ares__dns_multistring_add_own(*strs, data, len);
if (status != ARES_SUCCESS) {
ares_free(data);
break;
}
} else {
status = ares__buf_consume(buf, len);
if (status != ARES_SUCCESS) {
break;
}
}
}
}
if (status != ARES_SUCCESS && strs != NULL) {
ares__dns_multistring_destroy(*strs);
*strs = NULL;
}
return status;
}

@ -26,6 +26,8 @@
#ifndef __ARES_DNS_MULTISTRING_H
#define __ARES_DNS_MULTISTRING_H
#include "ares__buf.h"
struct ares__dns_multistring;
typedef struct ares__dns_multistring ares__dns_multistring_t;
@ -47,4 +49,25 @@ const unsigned char *
ares__dns_multistring_get_combined(ares__dns_multistring_t *strs,
size_t *len);
/*! Parse an array of character strings as defined in RFC1035, as binary,
* however, for convenience this does guarantee a NULL terminator (that is
* not included in the length for each value).
*
* \param[in] buf initialized buffer object
* \param[in] remaining_len maximum length that should be used for
* parsing the string, this is often less than
* the remaining buffer and is based on the RR
* record length.
* \param[out] strs Pointer passed by reference to be filled in
* with
* the array of values.
* \param[out] validate_printable Validate the strings contain only printable
* data.
* \return ARES_SUCCESS on success
*/
ares_status_t ares__dns_multistring_parse_buf(ares__buf_t *buf,
size_t remaining_len,
ares__dns_multistring_t **strs,
ares_bool_t validate_printable);
#endif

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

@ -95,7 +95,8 @@ static ares_status_t
ares_status_t status;
ares__dns_multistring_t *strs = NULL;
status = ares__buf_parse_dns_abinstr(buf, max_len, &strs, validate_printable);
status = ares__dns_multistring_parse_buf(buf, max_len, &strs,
validate_printable);
if (status != ARES_SUCCESS) {
return status;
}

@ -941,76 +941,6 @@ ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx)
return ARES_SUCCESS;
}
ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf,
size_t remaining_len,
ares__dns_multistring_t **strs,
ares_bool_t validate_printable)
{
unsigned char len;
ares_status_t status = ARES_EBADRESP;
size_t orig_len = ares__buf_len(buf);
if (buf == NULL) {
return ARES_EFORMERR;
}
if (remaining_len == 0) {
return ARES_EBADRESP;
}
if (strs != NULL) {
*strs = ares__dns_multistring_create();
if (*strs == NULL) {
return ARES_ENOMEM;
}
}
while (orig_len - ares__buf_len(buf) < remaining_len) {
status = ares__buf_fetch_bytes(buf, &len, 1);
if (status != ARES_SUCCESS) {
break; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (len) {
/* When used by the _str() parser, it really needs to be validated to
* be a valid printable ascii string. Do that here */
if (validate_printable && ares__buf_len(buf) >= len) {
size_t mylen;
const char *data = (const char *)ares__buf_peek(buf, &mylen);
if (!ares__str_isprint(data, len)) {
status = ARES_EBADSTR;
break;
}
}
if (strs != NULL) {
unsigned char *data = NULL;
status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &data);
if (status != ARES_SUCCESS) {
break;
}
status = ares__dns_multistring_add_own(*strs, data, len);
if (status != ARES_SUCCESS) {
ares_free(data);
break;
}
} else {
status = ares__buf_consume(buf, len);
if (status != ARES_SUCCESS) {
break;
}
}
}
}
if (status != ARES_SUCCESS && strs != NULL) {
ares__dns_multistring_destroy(*strs);
*strs = NULL;
}
return status;
}
static ares_status_t
ares__buf_parse_dns_binstr_int(ares__buf_t *buf, size_t remaining_len,
unsigned char **bin, size_t *bin_len,

@ -286,3 +286,168 @@ ares_bool_t ares__str_isprint(const char *str, size_t len)
}
return ARES_TRUE;
}
int ares_strcmp(const char *a, const char *b)
{
if (a == NULL && b == NULL) {
return 0;
}
if (a != NULL && b == NULL) {
if (*a == 0) {
return 0;
}
return 1;
}
if (a == NULL && b != NULL) {
if (*b == 0) {
return 0;
}
return -1;
}
return strcmp(a, b);
}
int ares_strncmp(const char *a, const char *b, size_t n)
{
if (n == 0) {
return 0;
}
if (a == NULL && b == NULL) {
return 0;
}
if (a != NULL && b == NULL) {
if (*a == 0) {
return 0;
}
return 1;
}
if (a == NULL && b != NULL) {
if (*b == 0) {
return 0;
}
return -1;
}
return strncmp(a, b, n);
}
int ares_strcasecmp(const char *a, const char *b)
{
if (a == NULL && b == NULL) {
return 0;
}
if (a != NULL && b == NULL) {
if (*a == 0) {
return 0;
}
return 1;
}
if (a == NULL && b != NULL) {
if (*b == 0) {
return 0;
}
return -1;
}
# if defined(HAVE_STRCASECMP)
return strcasecmp(a, b);
# elif defined(HAVE_STRCMPI)
return strcmpi(a, b);
# elif defined(HAVE_STRICMP)
return stricmp(a, b);
# else
{
size_t i;
for (i = 0; i < (size_t)-1; i++) {
int c1 = ares__tolower(a[i]);
int c2 = ares__tolower(b[i]);
if (c1 != c2) {
return c1 - c2;
}
if (!c1) {
break;
}
}
}
return 0;
# endif
}
int ares_strncasecmp(const char *a, const char *b, size_t n)
{
if (n == 0) {
return 0;
}
if (a == NULL && b == NULL) {
return 0;
}
if (a != NULL && b == NULL) {
if (*a == 0) {
return 0;
}
return 1;
}
if (a == NULL && b != NULL) {
if (*b == 0) {
return 0;
}
return -1;
}
# if defined(HAVE_STRNCASECMP)
return strncasecmp(a,b,n);
# elif defined(HAVE_STRNCMPI)
return strncmpi(a, b, n);
# elif defined(HAVE_STRNICMP)
return strnicmp(a, b, n);
# else
{
size_t i;
for (i = 0; i < n; i++) {
int c1 = ares__tolower(a[i]);
int c2 = ares__tolower(b[i]);
if (c1 != c2) {
return c1 - c2;
}
if (!c1) {
break;
}
}
}
return 0;
# endif
}
ares_bool_t ares_strcaseeq(const char *a, const char *b)
{
return ares_strcasecmp(a,b) == 0?ARES_TRUE:ARES_FALSE;
}
ares_bool_t ares_strcaseeq_max(const char *a, const char *b, size_t n)
{
return ares_strncasecmp(a,b,n) == 0?ARES_TRUE:ARES_FALSE;
}
ares_bool_t ares_streq(const char *a, const char *b)
{
return ares_strcmp(a,b) == 0?ARES_TRUE:ARES_FALSE;
}
ares_bool_t ares_streq_max(const char *a, const char *b, size_t n)
{
return ares_strncmp(a,b,n) == 0?ARES_TRUE:ARES_FALSE;
}

@ -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;
}
if (strcasecmp(name, adapter_name) == 0) {
if (ares_strcaseeq(name, adapter_name)) {
return ARES_TRUE;
}
@ -515,7 +515,7 @@ static ares_status_t ares__iface_ips_enumerate(ares__iface_ips_t *ips,
}
/* Name mismatch */
if (name != NULL && strcasecmp(ifa->ifa_name, name) != 0) {
if (name != NULL && !ares_strcaseeq(ifa->ifa_name, name)) {
continue;
}

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

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

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

@ -44,21 +44,7 @@
#include "ares.h"
#include "ares_dns.h"
#ifndef HAVE_STRDUP
# include "str/ares_str.h"
# define strdup(ptr) ares_strdup(ptr)
#endif
#ifndef HAVE_STRCASECMP
# include "str/ares_strcasecmp.h"
# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2)
#endif
#ifndef HAVE_STRNCASECMP
# include "str/ares_strcasecmp.h"
# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n)
#endif
#include "ares_str.h"
#include "ares_getopt.h"
@ -99,7 +85,7 @@ static int lookup_flag(const nv_t *nv, size_t num_nv, const char *name)
}
for (i = 0; i < num_nv; i++) {
if (strcasecmp(nv[i].name, name) == 0) {
if (ares_strcaseeq(nv[i].name, name)) {
return nv[i].value;
}
}

@ -42,20 +42,7 @@
#include "ares_getopt.h"
#include "ares_ipv6.h"
#ifndef HAVE_STRDUP
# include "str/ares_str.h"
# define strdup(ptr) ares_strdup(ptr)
#endif
#ifndef HAVE_STRCASECMP
# include "str/ares_strcasecmp.h"
# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2)
#endif
#ifndef HAVE_STRNCASECMP
# include "str/ares_strcasecmp.h"
# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n)
#endif
#include "ares_str.h"
static void callback(void *arg, int status, int timeouts, struct hostent *host);
static void ai_callback(void *arg, int status, int timeouts,
@ -111,11 +98,11 @@ int main(int argc, char **argv)
options.domains[options.ndomains - 1] = strdup(state.optarg);
break;
case 't':
if (!strcasecmp(state.optarg, "a")) {
if (ares_strcaseeq(state.optarg, "a")) {
addr_family = AF_INET;
} else if (!strcasecmp(state.optarg, "aaaa")) {
} else if (ares_strcaseeq(state.optarg, "aaaa")) {
addr_family = AF_INET6;
} else if (!strcasecmp(state.optarg, "u")) {
} else if (ares_strcaseeq(state.optarg, "u")) {
addr_family = AF_UNSPEC;
} else {
usage();

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

1
test/Makefile.am vendored

@ -6,6 +6,7 @@ AM_CPPFLAGS += -I$(top_builddir)/include \
-I$(top_builddir)/src/lib \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include \
-I$(top_srcdir)/test \
-I$(top_builddir)/test \
-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
ARES_BLD_DIR = ..
ARESLIB = $(ARES_BLD_DIR)/src/lib/libcares.a
CPPFLAGS = -I$(ARES_SRC_DIR)/include -I$(ARES_SRC_DIR)/src/lib -I$(GTEST_ROOT)/include -DCARES_STATICLIB -DCARES_NO_DEPRECATED
CPPFLAGS = -I$(ARES_SRC_DIR)/include -I$(ARES_SRC_DIR)/src/lib -I$(ARES_SRC_DIR)/src/lib/include -I$(GTEST_ROOT)/include -DCARES_STATICLIB -DCARES_NO_DEPRECATED
CXXFLAGS = -Wall $(PTHREAD_CFLAGS) -std=gnu++14
LDFLAGS =
LDLIBS = -lws2_32 -liphlpapi

@ -150,7 +150,7 @@ EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib
CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2 /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS /RTCsu
CC_CFLAGS = $(CFLAGS) /I. /I../src/lib /I../include /I $(GTEST_ROOT)/include /W3 /EHsc /FD
CC_CFLAGS = $(CFLAGS) /I. /I../src/lib /I../src/lib/include /I../include /I $(GTEST_ROOT)/include /W3 /EHsc /FD
RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG"

@ -71,9 +71,7 @@ void CheckPtoN4(int size, unsigned int value, const char *input) {
<< " for input " << input;
EXPECT_EQ(expected, a4.s_addr) << " for input " << input;
}
#endif
#ifndef CARES_SYMBOL_HIDING
TEST_F(LibraryTest, Strsplit) {
using std::vector;
using std::string;
@ -112,15 +110,11 @@ TEST_F(LibraryTest, Strsplit) {
ares__strsplit_free(out, n);
}
}
#endif
TEST_F(LibraryTest, InetPtoN) {
TEST_F(LibraryTest, InetNetPtoN) {
uint32_t expected;
struct in_addr a4;
struct in6_addr a6;
#ifndef CARES_SYMBOL_HIDING
uint32_t expected;
CheckPtoN4(4 * 8, 0x01020304, "1.2.3.4");
CheckPtoN4(4 * 8, 0x81010101, "129.1.1.1");
CheckPtoN4(4 * 8, 0xC0010101, "192.1.1.1");
@ -220,8 +214,137 @@ TEST_F(LibraryTest, InetPtoN) {
EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "0x0xyz", &a4, 0));
EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "0x1122334", &a4, sizeof(a4) - 1));
EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "253", &a4, sizeof(a4) - 1));
#endif
}
TEST_F(LibraryTest, FreeLongChain) {
struct ares_addr_node *data = nullptr;
for (int ii = 0; ii < 100000; ii++) {
struct ares_addr_node *prev = (struct ares_addr_node*)ares_malloc_data(ARES_DATATYPE_ADDR_NODE);
prev->next = data;
data = prev;
}
ares_free_data(data);
}
TEST_F(LibraryTest, MallocDataFail) {
EXPECT_EQ(nullptr, ares_malloc_data((ares_datatype)99));
SetAllocSizeFail(sizeof(struct ares_data));
EXPECT_EQ(nullptr, ares_malloc_data(ARES_DATATYPE_MX_REPLY));
}
TEST(Misc, OnionDomain) {
EXPECT_EQ(0, ares__is_onion_domain("onion.no"));
EXPECT_EQ(0, ares__is_onion_domain(".onion.no"));
EXPECT_EQ(1, ares__is_onion_domain(".onion"));
EXPECT_EQ(1, ares__is_onion_domain(".onion."));
EXPECT_EQ(1, ares__is_onion_domain("yes.onion"));
EXPECT_EQ(1, ares__is_onion_domain("yes.onion."));
EXPECT_EQ(1, ares__is_onion_domain("YES.ONION"));
EXPECT_EQ(1, ares__is_onion_domain("YES.ONION."));
}
TEST_F(LibraryTest, CatDomain) {
char *s;
ares__cat_domain("foo", "example.net", &s);
EXPECT_STREQ("foo.example.net", s);
ares_free(s);
ares__cat_domain("foo", ".", &s);
EXPECT_STREQ("foo.", s);
ares_free(s);
ares__cat_domain("foo", "example.net.", &s);
EXPECT_STREQ("foo.example.net.", s);
ares_free(s);
}
TEST_F(LibraryTest, SlistMisuse) {
EXPECT_EQ(NULL, ares__slist_create(NULL, NULL, NULL));
ares__slist_replace_destructor(NULL, NULL);
EXPECT_EQ(NULL, ares__slist_insert(NULL, NULL));
EXPECT_EQ(NULL, ares__slist_node_find(NULL, NULL));
EXPECT_EQ(NULL, ares__slist_node_first(NULL));
EXPECT_EQ(NULL, ares__slist_node_last(NULL));
EXPECT_EQ(NULL, ares__slist_node_next(NULL));
EXPECT_EQ(NULL, ares__slist_node_prev(NULL));
EXPECT_EQ(NULL, ares__slist_node_val(NULL));
EXPECT_EQ((size_t)0, ares__slist_len(NULL));
EXPECT_EQ(NULL, ares__slist_node_parent(NULL));
EXPECT_EQ(NULL, ares__slist_first_val(NULL));
EXPECT_EQ(NULL, ares__slist_last_val(NULL));
EXPECT_EQ(NULL, ares__slist_node_claim(NULL));
}
TEST_F(LibraryTest, IfaceIPs) {
ares_status_t status;
ares__iface_ips_t *ips = NULL;
size_t i;
status = ares__iface_ips(&ips, ARES_IFACE_IP_DEFAULT, NULL);
EXPECT_TRUE(status == ARES_SUCCESS || status == ARES_ENOTIMP);
/* Not implemented, can't run tests */
if (status == ARES_ENOTIMP)
return;
EXPECT_NE(nullptr, ips);
for (i=0; 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_INET6, "12:34::ff", &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);
}
#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) {
EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
char* copy = ares_strdup("string");
@ -277,12 +388,6 @@ TEST_F(LibraryTest, StrdupFailures) {
EXPECT_EQ(nullptr, copy);
}
TEST_F(LibraryTest, MallocDataFail) {
EXPECT_EQ(nullptr, ares_malloc_data((ares_datatype)99));
SetAllocSizeFail(sizeof(struct ares_data));
EXPECT_EQ(nullptr, ares_malloc_data(ARES_DATATYPE_MX_REPLY));
}
TEST_F(FileChannelTest, GetAddrInfoHostsPositive) {
TempFile hostsfile("1.2.3.4 example.com \n"
" 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n"
@ -393,19 +498,6 @@ TEST_F(FileChannelTest, GetAddrInfoAllocFail) {
}
}
TEST(Misc, OnionDomain) {
EXPECT_EQ(0, ares__is_onion_domain("onion.no"));
EXPECT_EQ(0, ares__is_onion_domain(".onion.no"));
EXPECT_EQ(1, ares__is_onion_domain(".onion"));
EXPECT_EQ(1, ares__is_onion_domain(".onion."));
EXPECT_EQ(1, ares__is_onion_domain("yes.onion"));
EXPECT_EQ(1, ares__is_onion_domain("yes.onion."));
EXPECT_EQ(1, ares__is_onion_domain("YES.ONION"));
EXPECT_EQ(1, ares__is_onion_domain("YES.ONION."));
}
#endif
TEST_F(LibraryTest, DNSRecord) {
ares_dns_record_t *dnsrec = NULL;
ares_dns_rr_t *rr = NULL;
@ -677,13 +769,11 @@ TEST_F(LibraryTest, DNSRecord) {
/* Write */
EXPECT_EQ(ARES_SUCCESS, ares_dns_write(dnsrec, &msg, &msglen));
#ifndef CARES_SYMBOL_HIDING
ares__buf_t *hexdump = ares__buf_create();
EXPECT_EQ(ARES_SUCCESS, ares__buf_hexdump(hexdump, msg, msglen));
char *hexdata = ares__buf_finish_str(hexdump, NULL);
//printf("HEXDUMP\n%s", hexdata);
ares_free(hexdata);
#endif
ares_dns_record_destroy(dnsrec); dnsrec = NULL;
@ -699,7 +789,6 @@ TEST_F(LibraryTest, DNSRecord) {
EXPECT_EQ(nscount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_AUTHORITY));
EXPECT_EQ(arcount, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ADDITIONAL));
#ifndef CARES_SYMBOL_HIDING
/* Iterate and print */
ares__buf_t *printmsg = ares__buf_create();
ares__buf_append_str(printmsg, ";; ->>HEADER<<- opcode: ");
@ -817,7 +906,6 @@ TEST_F(LibraryTest, DNSRecord) {
char *printdata = ares__buf_finish_str(printmsg, NULL);
//printf("%s", printdata);
ares_free(printdata);
#endif
ares_dns_record_destroy(dnsrec);
ares_free_string(msg);
@ -983,24 +1071,6 @@ TEST_F(LibraryTest, DNSParseFlags) {
ares_free_string(msg); msg = NULL;
}
#ifndef CARES_SYMBOL_HIDING
TEST_F(LibraryTest, CatDomain) {
char *s;
ares__cat_domain("foo", "example.net", &s);
EXPECT_STREQ("foo.example.net", s);
ares_free(s);
ares__cat_domain("foo", ".", &s);
EXPECT_STREQ("foo.", s);
ares_free(s);
ares__cat_domain("foo", "example.net.", &s);
EXPECT_STREQ("foo.example.net.", s);
ares_free(s);
}
TEST_F(LibraryTest, ArrayMisuse) {
EXPECT_EQ(NULL, ares__array_create(0, NULL));
ares__array_destroy(NULL);
@ -1043,18 +1113,9 @@ TEST_F(LibraryTest, BufMisuse) {
EXPECT_EQ(ARES_FALSE, ares__buf_begins_with(NULL, NULL, 0));
EXPECT_EQ((size_t)0, ares__buf_get_position(NULL));
EXPECT_NE(ARES_SUCCESS, ares__buf_set_position(NULL, 0));
EXPECT_NE(ARES_SUCCESS, ares__dns_name_parse(NULL, NULL, ARES_FALSE));
EXPECT_NE(ARES_SUCCESS, ares__buf_parse_dns_binstr(NULL, 0, NULL, NULL));
}
TEST_F(LibraryTest, HtableMisuse) {
EXPECT_EQ(NULL, ares__htable_create(NULL, NULL, NULL, NULL));
EXPECT_EQ(ARES_FALSE, ares__htable_insert(NULL, NULL));
EXPECT_EQ(NULL, ares__htable_get(NULL, NULL));
EXPECT_EQ(ARES_FALSE, ares__htable_remove(NULL, NULL));
EXPECT_EQ((size_t)0, ares__htable_num_keys(NULL));
}
TEST_F(LibraryTest, HtableAsvpMisuse) {
EXPECT_EQ(ARES_FALSE, ares__htable_asvp_insert(NULL, ARES_SOCKET_BAD, NULL));
EXPECT_EQ(ARES_FALSE, ares__htable_asvp_get(NULL, ARES_SOCKET_BAD, NULL));
@ -1096,23 +1157,6 @@ TEST_F(LibraryTest, LlistMisuse) {
ares__llist_node_replace(NULL, NULL);
}
TEST_F(LibraryTest, SlistMisuse) {
EXPECT_EQ(NULL, ares__slist_create(NULL, NULL, NULL));
ares__slist_replace_destructor(NULL, NULL);
EXPECT_EQ(NULL, ares__slist_insert(NULL, NULL));
EXPECT_EQ(NULL, ares__slist_node_find(NULL, NULL));
EXPECT_EQ(NULL, ares__slist_node_first(NULL));
EXPECT_EQ(NULL, ares__slist_node_last(NULL));
EXPECT_EQ(NULL, ares__slist_node_next(NULL));
EXPECT_EQ(NULL, ares__slist_node_prev(NULL));
EXPECT_EQ(NULL, ares__slist_node_val(NULL));
EXPECT_EQ((size_t)0, ares__slist_len(NULL));
EXPECT_EQ(NULL, ares__slist_node_parent(NULL));
EXPECT_EQ(NULL, ares__slist_first_val(NULL));
EXPECT_EQ(NULL, ares__slist_last_val(NULL));
EXPECT_EQ(NULL, ares__slist_node_claim(NULL));
}
typedef struct {
unsigned int id;
ares__buf_t *buf;
@ -1453,65 +1497,6 @@ TEST_F(LibraryTest, HtableStrvp) {
ares__htable_strvp_destroy(h);
}
TEST_F(LibraryTest, IfaceIPs) {
ares_status_t status;
ares__iface_ips_t *ips = NULL;
size_t i;
status = ares__iface_ips(&ips, ARES_IFACE_IP_DEFAULT, NULL);
EXPECT_TRUE(status == ARES_SUCCESS || status == ARES_ENOTIMP);
/* Not implemented, can't run tests */
if (status == ARES_ENOTIMP)
return;
EXPECT_NE(nullptr, ips);
for (i=0; 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) {
ares__slist_t *saved = channel_->servers;
channel_->servers = NULL;

Loading…
Cancel
Save