mirror of https://github.com/getdnsapi/getdns.git
Merge pull request #191 from wtoorop/devel/decompose-getdns_query
Devel/decompose getdns query
This commit is contained in:
commit
8318766593
|
@ -143,14 +143,14 @@ ACX_ARG_RPATH
|
|||
AC_ARG_ENABLE(debug-sched, AC_HELP_STRING([--enable-debug-sched], [Enable scheduling debugging messages]))
|
||||
AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub debugging messages]))
|
||||
AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages]))
|
||||
AC_ARG_ENABLE(debug-trace, AC_HELP_STRING([--enable-debug-trace], [Enable trace debugging of individual dns messages]))
|
||||
AC_ARG_ENABLE(debug-server, AC_HELP_STRING([--enable-debug-server], [Enable server debugging messages]))
|
||||
AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable scheduling, stub and dnssec debugging]))
|
||||
case "$enable_all_debugging" in
|
||||
yes)
|
||||
enable_debug_sched=yes
|
||||
enable_debug_stub=yes
|
||||
enable_debug_sec=yes
|
||||
enable_debug_trace=yes
|
||||
enable_debug_server=yes
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
|
@ -176,9 +176,9 @@ case "$enable_debug_sec" in
|
|||
no|*)
|
||||
;;
|
||||
esac
|
||||
case "$enable_debug_trace" in
|
||||
case "$enable_debug_server" in
|
||||
yes)
|
||||
AC_DEFINE_UNQUOTED([TRACE_DEBUG], [1], [Define this enable printing of transaction ids of individual dns messages.])
|
||||
AC_DEFINE_UNQUOTED([SERVER_DEBUG], [1], [Define this enable printing of server debugging messages.])
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
|
|
|
@ -274,7 +274,7 @@ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/ge
|
|||
$(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
|
||||
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h
|
||||
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h getdns/getdns.h $(srcdir)/rr-dict.h config.h \
|
||||
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h
|
||||
stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \
|
||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \
|
||||
|
|
209
src/const-info.c
209
src/const-info.c
|
@ -95,196 +95,6 @@ static struct const_info consts_info[] = {
|
|||
{ 1301, "GETDNS_AUTHENTICATION_REQUIRED", GETDNS_AUTHENTICATION_REQUIRED_TEXT },
|
||||
};
|
||||
|
||||
struct const_name_info { const char *name; int code; };
|
||||
static struct const_name_info consts_name_info[] = {
|
||||
{ "GETDNS_APPEND_NAME_ALWAYS", 550 },
|
||||
{ "GETDNS_APPEND_NAME_NEVER", 553 },
|
||||
{ "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", 552 },
|
||||
{ "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", 551 },
|
||||
{ "GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST", 554 },
|
||||
{ "GETDNS_AUTHENTICATION_NONE", 1300 },
|
||||
{ "GETDNS_AUTHENTICATION_REQUIRED", 1301 },
|
||||
{ "GETDNS_BAD_DNS_ALL_NUMERIC_LABEL", 1101 },
|
||||
{ "GETDNS_BAD_DNS_CNAME_IN_TARGET", 1100 },
|
||||
{ "GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE", 1102 },
|
||||
{ "GETDNS_CALLBACK_CANCEL", 701 },
|
||||
{ "GETDNS_CALLBACK_COMPLETE", 700 },
|
||||
{ "GETDNS_CALLBACK_ERROR", 703 },
|
||||
{ "GETDNS_CALLBACK_TIMEOUT", 702 },
|
||||
{ "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", 609 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS", 604 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNS_TRANSPORT", 605 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", 619 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_DO_BIT", 613 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE", 611 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE", 610 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_VERSION", 612 },
|
||||
{ "GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS", 602 },
|
||||
{ "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", 617 },
|
||||
{ "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", 606 },
|
||||
{ "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", 615 },
|
||||
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
|
||||
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
|
||||
{ "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 },
|
||||
{ "GETDNS_CONTEXT_CODE_SUFFIX", 608 },
|
||||
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
|
||||
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
|
||||
{ "GETDNS_DNSSEC_BOGUS", 401 },
|
||||
{ "GETDNS_DNSSEC_INDETERMINATE", 402 },
|
||||
{ "GETDNS_DNSSEC_INSECURE", 403 },
|
||||
{ "GETDNS_DNSSEC_NOT_PERFORMED", 404 },
|
||||
{ "GETDNS_DNSSEC_SECURE", 400 },
|
||||
{ "GETDNS_EXTENSION_FALSE", 1001 },
|
||||
{ "GETDNS_EXTENSION_TRUE", 1000 },
|
||||
{ "GETDNS_NAMESPACE_DNS", 500 },
|
||||
{ "GETDNS_NAMESPACE_LOCALNAMES", 501 },
|
||||
{ "GETDNS_NAMESPACE_MDNS", 503 },
|
||||
{ "GETDNS_NAMESPACE_NETBIOS", 502 },
|
||||
{ "GETDNS_NAMESPACE_NIS", 504 },
|
||||
{ "GETDNS_NAMETYPE_DNS", 800 },
|
||||
{ "GETDNS_NAMETYPE_WINS", 801 },
|
||||
{ "GETDNS_OPCODE_IQUERY", 1 },
|
||||
{ "GETDNS_OPCODE_NOTIFY", 4 },
|
||||
{ "GETDNS_OPCODE_QUERY", 0 },
|
||||
{ "GETDNS_OPCODE_STATUS", 2 },
|
||||
{ "GETDNS_OPCODE_UPDATE", 5 },
|
||||
{ "GETDNS_RCODE_BADALG", 21 },
|
||||
{ "GETDNS_RCODE_BADKEY", 17 },
|
||||
{ "GETDNS_RCODE_BADMODE", 19 },
|
||||
{ "GETDNS_RCODE_BADNAME", 20 },
|
||||
{ "GETDNS_RCODE_BADSIG", 16 },
|
||||
{ "GETDNS_RCODE_BADTIME", 18 },
|
||||
{ "GETDNS_RCODE_BADTRUNC", 22 },
|
||||
{ "GETDNS_RCODE_BADVERS", 16 },
|
||||
{ "GETDNS_RCODE_FORMERR", 1 },
|
||||
{ "GETDNS_RCODE_NOERROR", 0 },
|
||||
{ "GETDNS_RCODE_NOTAUTH", 9 },
|
||||
{ "GETDNS_RCODE_NOTIMP", 4 },
|
||||
{ "GETDNS_RCODE_NOTZONE", 10 },
|
||||
{ "GETDNS_RCODE_NXDOMAIN", 3 },
|
||||
{ "GETDNS_RCODE_NXRRSET", 8 },
|
||||
{ "GETDNS_RCODE_REFUSED", 5 },
|
||||
{ "GETDNS_RCODE_SERVFAIL", 2 },
|
||||
{ "GETDNS_RCODE_YXDOMAIN", 6 },
|
||||
{ "GETDNS_RCODE_YXRRSET", 7 },
|
||||
{ "GETDNS_REDIRECTS_DO_NOT_FOLLOW", 531 },
|
||||
{ "GETDNS_REDIRECTS_FOLLOW", 530 },
|
||||
{ "GETDNS_RESOLUTION_RECURSING", 521 },
|
||||
{ "GETDNS_RESOLUTION_STUB", 520 },
|
||||
{ "GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS", 904 },
|
||||
{ "GETDNS_RESPSTATUS_ALL_TIMEOUT", 902 },
|
||||
{ "GETDNS_RESPSTATUS_GOOD", 900 },
|
||||
{ "GETDNS_RESPSTATUS_NO_NAME", 901 },
|
||||
{ "GETDNS_RESPSTATUS_NO_SECURE_ANSWERS", 903 },
|
||||
{ "GETDNS_RETURN_BAD_CONTEXT", 301 },
|
||||
{ "GETDNS_RETURN_BAD_DOMAIN_NAME", 300 },
|
||||
{ "GETDNS_RETURN_CONTEXT_UPDATE_FAIL", 302 },
|
||||
{ "GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED", 309 },
|
||||
{ "GETDNS_RETURN_EXTENSION_MISFORMAT", 308 },
|
||||
{ "GETDNS_RETURN_GENERIC_ERROR", 1 },
|
||||
{ "GETDNS_RETURN_GOOD", 0 },
|
||||
{ "GETDNS_RETURN_INVALID_PARAMETER", 311 },
|
||||
{ "GETDNS_RETURN_MEMORY_ERROR", 310 },
|
||||
{ "GETDNS_RETURN_NEED_MORE_SPACE", 399 },
|
||||
{ "GETDNS_RETURN_NOT_IMPLEMENTED", 312 },
|
||||
{ "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 },
|
||||
{ "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 },
|
||||
{ "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 },
|
||||
{ "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 },
|
||||
{ "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 },
|
||||
{ "GETDNS_RRCLASS_ANY", 255 },
|
||||
{ "GETDNS_RRCLASS_CH", 3 },
|
||||
{ "GETDNS_RRCLASS_HS", 4 },
|
||||
{ "GETDNS_RRCLASS_IN", 1 },
|
||||
{ "GETDNS_RRCLASS_NONE", 254 },
|
||||
{ "GETDNS_RRTYPE_A", 1 },
|
||||
{ "GETDNS_RRTYPE_AAAA", 28 },
|
||||
{ "GETDNS_RRTYPE_AFSDB", 18 },
|
||||
{ "GETDNS_RRTYPE_ANY", 255 },
|
||||
{ "GETDNS_RRTYPE_APL", 42 },
|
||||
{ "GETDNS_RRTYPE_ATMA", 34 },
|
||||
{ "GETDNS_RRTYPE_AXFR", 252 },
|
||||
{ "GETDNS_RRTYPE_CAA", 257 },
|
||||
{ "GETDNS_RRTYPE_CDNSKEY", 60 },
|
||||
{ "GETDNS_RRTYPE_CDS", 59 },
|
||||
{ "GETDNS_RRTYPE_CERT", 37 },
|
||||
{ "GETDNS_RRTYPE_CNAME", 5 },
|
||||
{ "GETDNS_RRTYPE_CSYNC", 62 },
|
||||
{ "GETDNS_RRTYPE_DHCID", 49 },
|
||||
{ "GETDNS_RRTYPE_DLV", 32769 },
|
||||
{ "GETDNS_RRTYPE_DNAME", 39 },
|
||||
{ "GETDNS_RRTYPE_DNSKEY", 48 },
|
||||
{ "GETDNS_RRTYPE_DS", 43 },
|
||||
{ "GETDNS_RRTYPE_EID", 31 },
|
||||
{ "GETDNS_RRTYPE_GID", 102 },
|
||||
{ "GETDNS_RRTYPE_GPOS", 27 },
|
||||
{ "GETDNS_RRTYPE_HINFO", 13 },
|
||||
{ "GETDNS_RRTYPE_HIP", 55 },
|
||||
{ "GETDNS_RRTYPE_IPSECKEY", 45 },
|
||||
{ "GETDNS_RRTYPE_ISDN", 20 },
|
||||
{ "GETDNS_RRTYPE_IXFR", 251 },
|
||||
{ "GETDNS_RRTYPE_KEY", 25 },
|
||||
{ "GETDNS_RRTYPE_KX", 36 },
|
||||
{ "GETDNS_RRTYPE_LOC", 29 },
|
||||
{ "GETDNS_RRTYPE_LP", 107 },
|
||||
{ "GETDNS_RRTYPE_MAILA", 254 },
|
||||
{ "GETDNS_RRTYPE_MAILB", 253 },
|
||||
{ "GETDNS_RRTYPE_MB", 7 },
|
||||
{ "GETDNS_RRTYPE_MD", 3 },
|
||||
{ "GETDNS_RRTYPE_MF", 4 },
|
||||
{ "GETDNS_RRTYPE_MG", 8 },
|
||||
{ "GETDNS_RRTYPE_MINFO", 14 },
|
||||
{ "GETDNS_RRTYPE_MR", 9 },
|
||||
{ "GETDNS_RRTYPE_MX", 15 },
|
||||
{ "GETDNS_RRTYPE_NAPTR", 35 },
|
||||
{ "GETDNS_RRTYPE_NID", 104 },
|
||||
{ "GETDNS_RRTYPE_NIMLOC", 32 },
|
||||
{ "GETDNS_RRTYPE_NINFO", 56 },
|
||||
{ "GETDNS_RRTYPE_NS", 2 },
|
||||
{ "GETDNS_RRTYPE_NSAP", 22 },
|
||||
{ "GETDNS_RRTYPE_NSEC", 47 },
|
||||
{ "GETDNS_RRTYPE_NULL", 10 },
|
||||
{ "GETDNS_RRTYPE_NXT", 30 },
|
||||
{ "GETDNS_RRTYPE_OPENPGPKEY", 61 },
|
||||
{ "GETDNS_RRTYPE_OPT", 41 },
|
||||
{ "GETDNS_RRTYPE_PTR", 12 },
|
||||
{ "GETDNS_RRTYPE_PX", 26 },
|
||||
{ "GETDNS_RRTYPE_RKEY", 57 },
|
||||
{ "GETDNS_RRTYPE_RP", 17 },
|
||||
{ "GETDNS_RRTYPE_RRSIG", 46 },
|
||||
{ "GETDNS_RRTYPE_RT", 21 },
|
||||
{ "GETDNS_RRTYPE_SIG", 24 },
|
||||
{ "GETDNS_RRTYPE_SINK", 40 },
|
||||
{ "GETDNS_RRTYPE_SOA", 6 },
|
||||
{ "GETDNS_RRTYPE_SPF", 99 },
|
||||
{ "GETDNS_RRTYPE_SRV", 33 },
|
||||
{ "GETDNS_RRTYPE_SSHFP", 44 },
|
||||
{ "GETDNS_RRTYPE_TA", 32768 },
|
||||
{ "GETDNS_RRTYPE_TALINK", 58 },
|
||||
{ "GETDNS_RRTYPE_TKEY", 249 },
|
||||
{ "GETDNS_RRTYPE_TLSA", 52 },
|
||||
{ "GETDNS_RRTYPE_TSIG", 250 },
|
||||
{ "GETDNS_RRTYPE_TXT", 16 },
|
||||
{ "GETDNS_RRTYPE_UID", 101 },
|
||||
{ "GETDNS_RRTYPE_UINFO", 100 },
|
||||
{ "GETDNS_RRTYPE_UNSPEC", 103 },
|
||||
{ "GETDNS_RRTYPE_URI", 256 },
|
||||
{ "GETDNS_RRTYPE_WKS", 11 },
|
||||
{ "GETDNS_TRANSPORT_TCP", 1201 },
|
||||
{ "GETDNS_TRANSPORT_TCP_ONLY", 542 },
|
||||
{ "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 },
|
||||
{ "GETDNS_TRANSPORT_TLS", 1202 },
|
||||
{ "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", 545 },
|
||||
{ "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", 544 },
|
||||
{ "GETDNS_TRANSPORT_UDP", 1200 },
|
||||
{ "GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP", 540 },
|
||||
{ "GETDNS_TRANSPORT_UDP_ONLY", 541 },
|
||||
};
|
||||
|
||||
static int const_info_cmp(const void *a, const void *b)
|
||||
{
|
||||
return ((struct const_info *) a)->code - ((struct const_info *) b)->code;
|
||||
|
@ -301,25 +111,6 @@ _getdns_get_const_info(int value)
|
|||
return consts_info;
|
||||
}
|
||||
|
||||
static int const_name_info_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcmp( ((struct const_name_info *) a)->name
|
||||
, ((struct const_name_info *) b)->name );
|
||||
}
|
||||
int
|
||||
_getdns_get_const_name_info(const char *name, int *code)
|
||||
{
|
||||
struct const_name_info key = { name, 0 };
|
||||
struct const_name_info *i = bsearch(&key, consts_name_info,
|
||||
sizeof(consts_name_info) / sizeof(struct const_name_info),
|
||||
sizeof(struct const_name_info), const_name_info_cmp);
|
||||
if (!i)
|
||||
return 0;
|
||||
if (code)
|
||||
*code = i->code;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *
|
||||
getdns_get_errorstr_by_id(uint16_t err)
|
||||
{
|
||||
|
|
|
@ -46,7 +46,6 @@ struct const_info {
|
|||
};
|
||||
|
||||
struct const_info *_getdns_get_const_info(int value);
|
||||
int _getdns_get_const_name_info(const char *name, int *code);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3266,6 +3266,20 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop)
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop)
|
||||
{
|
||||
if (!context || !loop)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!context->extension)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
else
|
||||
*loop = context->extension;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static in_port_t
|
||||
upstream_port(getdns_upstream *upstream)
|
||||
{
|
||||
|
|
|
@ -95,11 +95,11 @@
|
|||
#define DEBUG_SEC(...) DEBUG_OFF(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if defined(TRACE_DEBUG) && TRACE_DEBUG
|
||||
#if defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
#include <time.h>
|
||||
#define DEBUG_TRACE(...) DEBUG_ON(__VA_ARGS__)
|
||||
#define DEBUG_SERVER(...) DEBUG_ON(__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_TRACE(...) DEBUG_OFF(__VA_ARGS__)
|
||||
#define DEBUG_SERVER(...) DEBUG_OFF(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,6 +119,11 @@ getdns_return_t
|
|||
getdns_context_set_eventloop(getdns_context* context,
|
||||
getdns_eventloop *eventloop);
|
||||
|
||||
/* get the currently active (pluggable) eventloop from the context */
|
||||
getdns_return_t
|
||||
getdns_context_get_eventloop(getdns_context* context,
|
||||
getdns_eventloop **eventloop);
|
||||
|
||||
/* detach the eventloop from the context */
|
||||
getdns_return_t
|
||||
getdns_context_detach_eventloop(getdns_context *context);
|
||||
|
|
|
@ -18,6 +18,7 @@ getdns_context_get_edns_do_bit
|
|||
getdns_context_get_edns_extended_rcode
|
||||
getdns_context_get_edns_maximum_udp_payload_size
|
||||
getdns_context_get_edns_version
|
||||
getdns_context_get_eventloop
|
||||
getdns_context_get_follow_redirects
|
||||
getdns_context_get_idle_timeout
|
||||
getdns_context_get_limit_outstanding_queries
|
||||
|
@ -145,4 +146,3 @@ getdns_wire2rr_dict_buf
|
|||
getdns_wire2rr_dict_scan
|
||||
plain_mem_funcs_user_arg
|
||||
priv_getdns_context_mf
|
||||
_getdns_get_const_name_info
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd `dirname $0`
|
||||
cat > const-info.c << END_OF_HEAD
|
||||
/* WARNING! This file is generated by the mk-const-info.c.sh program.
|
||||
* Do not edit manually!
|
||||
|
@ -14,13 +15,6 @@ static struct const_info consts_info[] = {
|
|||
{ -1, NULL, "/* <unknown getdns value> */" },
|
||||
END_OF_HEAD
|
||||
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%4d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%4d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%4d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> const-info.c
|
||||
cat >> const-info.c << END_OF_MIDDLE
|
||||
};
|
||||
|
||||
struct const_name_info { const char *name; int code; };
|
||||
static struct const_name_info consts_name_info[] = {
|
||||
END_OF_MIDDLE
|
||||
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> const-info.c
|
||||
cat >> const-info.c << END_OF_TAIL
|
||||
};
|
||||
|
||||
|
@ -40,25 +34,6 @@ _getdns_get_const_info(int value)
|
|||
return consts_info;
|
||||
}
|
||||
|
||||
static int const_name_info_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcmp( ((struct const_name_info *) a)->name
|
||||
, ((struct const_name_info *) b)->name );
|
||||
}
|
||||
int
|
||||
_getdns_get_const_name_info(const char *name, int *code)
|
||||
{
|
||||
struct const_name_info key = { name, 0 };
|
||||
struct const_name_info *i = bsearch(&key, consts_name_info,
|
||||
sizeof(consts_name_info) / sizeof(struct const_name_info),
|
||||
sizeof(struct const_name_info), const_name_info_cmp);
|
||||
if (!i)
|
||||
return 0;
|
||||
if (code)
|
||||
*code = i->code;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *
|
||||
getdns_get_errorstr_by_id(uint16_t err)
|
||||
{
|
||||
|
@ -72,3 +47,29 @@ getdns_get_errorstr_by_id(uint16_t err)
|
|||
return NULL;
|
||||
}
|
||||
END_OF_TAIL
|
||||
|
||||
gawk 'BEGIN{p=1}{if(p)print}/^static struct const_name_info consts_name_info\[\] = {$/{p=0}' test/getdns_str2dict.c > test/new-getdns_str2dict.c
|
||||
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> test/new-getdns_str2dict.c
|
||||
cat >> test/new-getdns_str2dict.c << END_OF_TAIL
|
||||
};
|
||||
static int const_name_info_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcmp( ((struct const_name_info *) a)->name
|
||||
, ((struct const_name_info *) b)->name );
|
||||
}
|
||||
static int
|
||||
_getdns_get_const_name_info(const char *name, uint32_t *code)
|
||||
{
|
||||
struct const_name_info key = { name, 0 };
|
||||
struct const_name_info *i = bsearch(&key, consts_name_info,
|
||||
sizeof(consts_name_info) / sizeof(struct const_name_info),
|
||||
sizeof(struct const_name_info), const_name_info_cmp);
|
||||
if (!i)
|
||||
return 0;
|
||||
if (code)
|
||||
*code = i->code;
|
||||
return 1;
|
||||
}
|
||||
END_OF_TAIL
|
||||
mv test/new-getdns_str2dict.c test/getdns_str2dict.c
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ write_symbols() {
|
|||
write_symbols libgetdns.symbols getdns/getdns.h.in getdns/getdns_extra.h.in
|
||||
echo plain_mem_funcs_user_arg >> libgetdns.symbols
|
||||
echo priv_getdns_context_mf >> libgetdns.symbols
|
||||
echo _getdns_get_const_name_info >> libgetdns.symbols
|
||||
write_symbols extension/libevent.symbols getdns/getdns_ext_libevent.h
|
||||
write_symbols extension/libev.symbols getdns/getdns_ext_libev.h
|
||||
write_symbols extension/libuv.symbols getdns/getdns_ext_libuv.h
|
||||
|
|
|
@ -66,10 +66,16 @@ CHECK_CFLAGS=@CHECK_CFLAGS@
|
|||
CHECK_OBJS=check_getdns_common.lo check_getdns_context_set_timeout.lo \
|
||||
check_getdns.lo check_getdns_transport.lo
|
||||
|
||||
DECOMPOSED_OBJS_WITHOUT_JSMN=getdns_str2dict.lo getdns_context_config.lo \
|
||||
getdns_context_set_listen_addresses.lo
|
||||
|
||||
DECOMPOSED_OBJS=$(DECOMPOSED_OBJS_WITHOUT_JSMN) jsmn.lo
|
||||
|
||||
ALL_OBJS=$(CHECK_OBJS) check_getdns_libevent.lo check_getdns_libev.lo \
|
||||
check_getdns_selectloop.lo getdns_query.lo scratchpad.lo \
|
||||
testmessages.lo tests_dict.lo tests_list.lo tests_namespaces.lo \
|
||||
tests_stub_async.lo tests_stub_sync.lo
|
||||
tests_stub_async.lo tests_stub_sync.lo \
|
||||
$(DECOMPOSED_OBJS_WITHOUT_JSMN)
|
||||
|
||||
NON_C99_OBJS=check_getdns_libuv.lo
|
||||
|
||||
|
@ -88,15 +94,15 @@ default: all
|
|||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
jsmn.lo:
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/jsmn.c -o $@
|
||||
|
||||
$(ALL_OBJS):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@
|
||||
|
||||
$(NON_C99_OBJS):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -c $(srcdir)/$(@:.lo=.c) -o $@
|
||||
|
||||
jsmn.lo:
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/jsmn.c -o $@
|
||||
|
||||
tests_dict: tests_dict.lo testmessages.lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_dict.lo testmessages.lo
|
||||
|
||||
|
@ -127,8 +133,8 @@ check_getdns_uv: check_getdns.lo check_getdns_common.lo check_getdns_context_set
|
|||
check_getdns_ev: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo ../libgetdns_ext_ev.la
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) ../libgetdns_ext_ev.la $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS)
|
||||
|
||||
getdns_query: getdns_query.lo jsmn.lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo jsmn.lo $(LDFLAGS) $(LDLIBS)
|
||||
getdns_query: getdns_query.lo $(DECOMPOSED_OBJS)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(DECOMPOSED_OBJS) $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
scratchpad: scratchpad.lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ scratchpad.lo $(LDFLAGS) $(LDLIBS)
|
||||
|
@ -208,21 +214,18 @@ depend:
|
|||
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
|
||||
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I.. -I"$$blddir"/.. *.c | \
|
||||
sed -e "s? $$blddir/? ?g" \
|
||||
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
|
||||
-e 's? \([a-z0-9_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
|
||||
-e 's? \.\./\([a-z0-9_-]*\)\.h? $$(srcdir)/../\1.h?g' \
|
||||
-e 's? \.\./\([a-z0-9_-]*\)/\([a-z0-9_-]*\)\.h? $$(srcdir)/../\1/\2.h?g' \
|
||||
-e 's? \$$(srcdir)/config\.h? ../config.h?g' \
|
||||
-e 's? $$(srcdir)/\.\./getdns/getdns_extra\.h? ../getdns/getdns_extra.h?g' \
|
||||
-e 's? \.\./getdns/getdns_ext_libevent\.h? $$(srcdir)/../getdns/getdns_ext_libevent.h?g' \
|
||||
-e 's? \.\./getdns/getdns_ext_libev\.h? $$(srcdir)/../getdns/getdns_ext_libev.h?g' \
|
||||
-e 's? \.\./getdns/getdns_ext_libuv\.h? $$(srcdir)/../getdns/getdns_ext_libuv.h?g' \
|
||||
-e 's? \.\./debug\.h? $$(srcdir)/../debug.h?g' \
|
||||
-e 's? \.\./const-info\.h? $$(srcdir)/../const-info.h?g' \
|
||||
-e 's? \$$(srcdir)/\.\./config\.h? ../config.h?g' \
|
||||
-e 's? \$$(srcdir)/\.\./getdns/getdns\.h? ../getdns/getdns.h?g' \
|
||||
-e 's? \$$(srcdir)/\.\./getdns/getdns_extra\.h? ../getdns/getdns_extra.h?g' \
|
||||
-e 's? jsmn/jsmn\.h? $$(srcdir)/jsmn/jsmn.h?g' \
|
||||
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new )
|
||||
(cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \
|
||||
|| mv Makefile.in.new Makefile.in )
|
||||
|
||||
|
||||
|
||||
.PHONY: clean test
|
||||
|
||||
# Dependencies for the unit tests
|
||||
|
@ -270,8 +273,20 @@ check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_sel
|
|||
check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \
|
||||
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h
|
||||
getdns_context_config.lo getdns_context_config.o: $(srcdir)/getdns_context_config.c $(srcdir)/getdns_context_config.h \
|
||||
../getdns/getdns.h ../getdns/getdns_extra.h
|
||||
getdns_context_set_listen_addresses.lo getdns_context_set_listen_addresses.o: \
|
||||
$(srcdir)/getdns_context_set_listen_addresses.c ../config.h \
|
||||
$(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h $(srcdir)/../types-internal.h ../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h $(srcdir)/../util/rbtree.h
|
||||
getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \
|
||||
$(srcdir)/../const-info.h $(srcdir)/jsmn/jsmn.h ../getdns/getdns.h ../getdns/getdns_extra.h
|
||||
$(srcdir)/getdns_str2dict.h ../getdns/getdns.h $(srcdir)/getdns_context_config.h \
|
||||
$(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns_extra.h
|
||||
getdns_str2dict.lo getdns_str2dict.o: $(srcdir)/getdns_str2dict.c ../config.h $(srcdir)/../const-info.h \
|
||||
$(srcdir)/jsmn/jsmn.h $(srcdir)/getdns_str2dict.h ../getdns/getdns.h $(srcdir)/../types-internal.h \
|
||||
../getdns/getdns.h ../getdns/getdns_extra.h $(srcdir)/../util/rbtree.h $(srcdir)/../list.h \
|
||||
$(srcdir)/../types-internal.h $(srcdir)/../dict.h
|
||||
scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h
|
||||
testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "getdns_context_config.h"
|
||||
#include "getdns/getdns_extra.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
static int _streq(const getdns_bindata *name, const char *str)
|
||||
{
|
||||
if (strlen(str) != name->size)
|
||||
return 0;
|
||||
else return strncmp((const char *)name->data, str, name->size) == 0;
|
||||
}
|
||||
|
||||
static getdns_return_t _get_list_or_read_file(const getdns_dict *config_dict,
|
||||
const char *setting, getdns_list **r_list, int *destroy_list)
|
||||
{
|
||||
getdns_bindata *fn_bd;
|
||||
char fn[FILENAME_MAX];
|
||||
FILE *fh;
|
||||
getdns_return_t r;
|
||||
|
||||
assert(r_list);
|
||||
assert(destroy_list);
|
||||
|
||||
*destroy_list = 0;
|
||||
if (!(r = getdns_dict_get_list(config_dict, setting, r_list)))
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
||||
else if ((r = getdns_dict_get_bindata(config_dict, setting, &fn_bd)))
|
||||
return r;
|
||||
|
||||
else if (fn_bd->size >= FILENAME_MAX)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
(void)memcpy(fn, fn_bd->data, fn_bd->size);
|
||||
fn[fn_bd->size] = 0;
|
||||
|
||||
if (!(fh = fopen(fn, "r")))
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
if (!(r = getdns_fp2rr_list(fh, r_list, NULL, 3600)))
|
||||
*destroy_list = 1;
|
||||
|
||||
fclose(fh);
|
||||
return r;
|
||||
}
|
||||
|
||||
#define CONTEXT_SETTING_INT(X) \
|
||||
} else if (_streq(setting, #X)) { \
|
||||
if (!(r = getdns_dict_get_int(config_dict, #X , &n))) \
|
||||
r = getdns_context_set_ ## X (context, n);
|
||||
|
||||
#define CONTEXT_SETTING_LIST(X) \
|
||||
} else if (_streq(setting, #X)) { \
|
||||
if (!(r = getdns_dict_get_list(config_dict, #X , &list))) \
|
||||
r = getdns_context_set_ ## X (context, list);
|
||||
|
||||
#define CONTEXT_SETTING_LIST_OR_ZONEFILE(X) \
|
||||
} else if (_streq(setting, #X)) { \
|
||||
if (!(r = _get_list_or_read_file( \
|
||||
config_dict, #X , &list, &destroy_list))) \
|
||||
r = getdns_context_set_ ## X(context, list); \
|
||||
if (destroy_list) getdns_list_destroy(list);
|
||||
|
||||
#define CONTEXT_SETTING_ARRAY(X, T) \
|
||||
} else if (_streq(setting, #X )) { \
|
||||
if (!(r = getdns_dict_get_list(config_dict, #X , &list)) && \
|
||||
!(r = getdns_list_get_length(list, &count))) { \
|
||||
for (i=0; i<count && i<(sizeof(X)/sizeof(*X)); i++) { \
|
||||
if ((r = getdns_list_get_int(list, i, &n))) \
|
||||
break; \
|
||||
X[i] = (getdns_ ## T ## _t)n; \
|
||||
} \
|
||||
r = getdns_context_set_ ##X (context, count, X); \
|
||||
}
|
||||
|
||||
#define EXTENSION_SETTING_INT(X) \
|
||||
} else if (_streq(setting, #X )) { \
|
||||
if (!(r = getdns_dict_get_int(config_dict, #X , &n))) \
|
||||
r = getdns_dict_set_int(extensions, #X , n);
|
||||
|
||||
#define EXTENSION_SETTING_DICT(X) \
|
||||
} else if (_streq(setting, #X )) { \
|
||||
if (!(r = getdns_dict_get_dict(config_dict, #X , &dict))) \
|
||||
r = getdns_dict_set_dict(extensions, #X , dict);
|
||||
|
||||
static getdns_return_t
|
||||
_getdns_context_config_setting_(
|
||||
getdns_context *context, getdns_dict *extensions,
|
||||
const getdns_dict *config_dict, const getdns_bindata *setting)
|
||||
{
|
||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||
getdns_dict *dict;
|
||||
getdns_list *list;
|
||||
getdns_namespace_t namespaces[100];
|
||||
getdns_transport_list_t dns_transport_list[100];
|
||||
size_t count, i;
|
||||
uint32_t n;
|
||||
int destroy_list = 0;
|
||||
|
||||
if (_streq(setting, "all_context")) {
|
||||
if (!(r = getdns_dict_get_dict(config_dict, "all_context", &dict)))
|
||||
r = _getdns_context_config_(context, extensions, dict);
|
||||
|
||||
CONTEXT_SETTING_INT(resolution_type)
|
||||
CONTEXT_SETTING_ARRAY(namespaces, namespace)
|
||||
CONTEXT_SETTING_INT(dns_transport)
|
||||
CONTEXT_SETTING_ARRAY(dns_transport_list, transport_list)
|
||||
CONTEXT_SETTING_INT(idle_timeout)
|
||||
CONTEXT_SETTING_INT(limit_outstanding_queries)
|
||||
CONTEXT_SETTING_INT(timeout)
|
||||
CONTEXT_SETTING_INT(follow_redirects)
|
||||
CONTEXT_SETTING_LIST_OR_ZONEFILE(dns_root_servers)
|
||||
CONTEXT_SETTING_INT(append_name)
|
||||
CONTEXT_SETTING_LIST(suffix)
|
||||
CONTEXT_SETTING_LIST_OR_ZONEFILE(dnssec_trust_anchors)
|
||||
CONTEXT_SETTING_INT(dnssec_allowed_skew)
|
||||
CONTEXT_SETTING_LIST(upstream_recursive_servers)
|
||||
CONTEXT_SETTING_INT(edns_maximum_udp_payload_size)
|
||||
CONTEXT_SETTING_INT(edns_extended_rcode)
|
||||
CONTEXT_SETTING_INT(edns_version)
|
||||
CONTEXT_SETTING_INT(edns_do_bit)
|
||||
|
||||
/***************************************/
|
||||
/**** ****/
|
||||
/**** Unofficial context settings ****/
|
||||
/**** ****/
|
||||
/***************************************/
|
||||
|
||||
CONTEXT_SETTING_INT(edns_client_subnet_private)
|
||||
CONTEXT_SETTING_INT(tls_authentication)
|
||||
CONTEXT_SETTING_INT(tls_query_padding_blocksize)
|
||||
|
||||
/**************************************/
|
||||
/**** ****/
|
||||
/**** Default extensions setting ****/
|
||||
/**** ****/
|
||||
/**************************************/
|
||||
EXTENSION_SETTING_DICT(add_opt_parameters)
|
||||
EXTENSION_SETTING_INT(add_warning_for_bad_dns)
|
||||
EXTENSION_SETTING_INT(dnssec_return_all_statuses)
|
||||
EXTENSION_SETTING_INT(dnssec_return_full_validation_chain)
|
||||
EXTENSION_SETTING_INT(dnssec_return_only_secure)
|
||||
EXTENSION_SETTING_INT(dnssec_return_status)
|
||||
EXTENSION_SETTING_INT(dnssec_return_validation_chain)
|
||||
#if defined(DNSSEC_ROADBLOCK_AVOIDANCE) && defined(HAVE_LIBUNBOUND)
|
||||
EXTENSION_SETTING_INT(dnssec_roadblock_avoidance)
|
||||
#endif
|
||||
#ifdef EDNS_COOKIES
|
||||
EXTENSION_SETTING_INT(edns_cookies)
|
||||
#endif
|
||||
EXTENSION_SETTING_DICT(header)
|
||||
EXTENSION_SETTING_INT(return_api_information)
|
||||
EXTENSION_SETTING_INT(return_both_v4_and_v6)
|
||||
EXTENSION_SETTING_INT(return_call_reporting)
|
||||
EXTENSION_SETTING_INT(specify_class)
|
||||
|
||||
/************************************/
|
||||
/**** ****/
|
||||
/**** Ignored context settings ****/
|
||||
/**** ****/
|
||||
/************************************/
|
||||
} else if (!_streq(setting, "implementation_string") &&
|
||||
!_streq(setting, "version_string")) {
|
||||
r = GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_context_config_(getdns_context *context,
|
||||
getdns_dict *extensions, const getdns_dict *config_dict)
|
||||
{
|
||||
getdns_list *settings;
|
||||
getdns_return_t r;
|
||||
getdns_bindata *setting;
|
||||
size_t i;
|
||||
|
||||
if ((r = getdns_dict_get_names(config_dict, &settings)))
|
||||
return r;
|
||||
|
||||
for (i = 0; !(r = getdns_list_get_bindata(settings,i,&setting)); i++) {
|
||||
if ((r = _getdns_context_config_setting_(
|
||||
context, extensions, config_dict, setting)))
|
||||
break;
|
||||
}
|
||||
if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
|
||||
r = GETDNS_RETURN_GOOD;
|
||||
|
||||
getdns_list_destroy(settings);
|
||||
return r;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "getdns/getdns.h"
|
||||
|
||||
#ifndef GETDNS_CONTEXT_CONFIG_H_
|
||||
#define GETDNS_CONTEXT_CONFIG_H_
|
||||
|
||||
/*
|
||||
getdns_return_t getdns_context_config(
|
||||
getdns_context *context, const getdns_dict *config_dict);
|
||||
*/
|
||||
getdns_return_t _getdns_context_config_(getdns_context *context,
|
||||
getdns_dict *extensions, const getdns_dict *config_dict);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,880 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "getdns_context_set_listen_addresses.h"
|
||||
#include "getdns/getdns_extra.h"
|
||||
#include "types-internal.h"
|
||||
#include "debug.h"
|
||||
#include <netdb.h>
|
||||
|
||||
#define DNS_REQUEST_SZ 4096
|
||||
#define DOWNSTREAM_IDLE_TIMEOUT 5000
|
||||
#define TCP_LISTEN_BACKLOG 16
|
||||
|
||||
typedef struct listen_set listen_set;
|
||||
typedef enum listen_set_action {
|
||||
to_stay, to_add, to_remove
|
||||
} listen_set_action;
|
||||
|
||||
typedef struct connection connection;
|
||||
typedef struct listener listener;
|
||||
struct listener {
|
||||
getdns_eventloop_event event;
|
||||
socklen_t addr_len;
|
||||
struct sockaddr_storage addr;
|
||||
int fd;
|
||||
getdns_transport_list_t transport;
|
||||
|
||||
listen_set_action action;
|
||||
listener *to_replace;
|
||||
listen_set *set;
|
||||
|
||||
/* Should be per context eventually */
|
||||
connection *connections;
|
||||
};
|
||||
|
||||
/* listen set is temporarily a singly linked list node, to associate the set
|
||||
* with a context. Eventually it has to become a context attribute.
|
||||
*/
|
||||
struct listen_set {
|
||||
getdns_context *context;
|
||||
listen_set *next;
|
||||
getdns_request_handler_t handler;
|
||||
|
||||
size_t count;
|
||||
listener items[];
|
||||
};
|
||||
|
||||
typedef struct tcp_to_write tcp_to_write;
|
||||
struct tcp_to_write {
|
||||
size_t write_buf_len;
|
||||
size_t written;
|
||||
tcp_to_write *next;
|
||||
uint8_t write_buf[];
|
||||
};
|
||||
|
||||
struct connection {
|
||||
listener *l;
|
||||
struct sockaddr_storage remote_in;
|
||||
socklen_t addrlen;
|
||||
|
||||
connection *next;
|
||||
connection **prev_next;
|
||||
};
|
||||
|
||||
typedef struct tcp_connection {
|
||||
/* A TCP connection is a connection */
|
||||
listener *l;
|
||||
struct sockaddr_storage remote_in;
|
||||
socklen_t addrlen;
|
||||
|
||||
connection *next;
|
||||
connection **prev_next;
|
||||
/************************************/
|
||||
|
||||
int fd;
|
||||
getdns_eventloop_event event;
|
||||
|
||||
uint8_t *read_buf;
|
||||
size_t read_buf_len;
|
||||
uint8_t *read_pos;
|
||||
size_t to_read;
|
||||
|
||||
tcp_to_write *to_write;
|
||||
size_t to_answer;
|
||||
} tcp_connection;
|
||||
|
||||
|
||||
static void free_listen_set_when_done(listen_set *set);
|
||||
static void tcp_connection_destroy(tcp_connection *conn)
|
||||
{
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
|
||||
tcp_to_write *cur, *next;
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
|
||||
return;
|
||||
|
||||
if (getdns_context_get_eventloop(conn->l->set->context, &loop))
|
||||
return;
|
||||
|
||||
if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb)
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
|
||||
if (conn->fd >= 0)
|
||||
(void) close(conn->fd);
|
||||
GETDNS_FREE(*mf, conn->read_buf);
|
||||
|
||||
for (cur = conn->to_write; cur; cur = next) {
|
||||
next = cur->next;
|
||||
GETDNS_FREE(*mf, cur);
|
||||
}
|
||||
if (conn->to_answer > 0)
|
||||
return;
|
||||
|
||||
/* Unlink this connection */
|
||||
if ((*conn->prev_next = conn->next))
|
||||
conn->next->prev_next = conn->prev_next;
|
||||
|
||||
free_listen_set_when_done(conn->l->set);
|
||||
GETDNS_FREE(*mf, conn);
|
||||
}
|
||||
|
||||
static void tcp_write_cb(void *userarg)
|
||||
{
|
||||
tcp_connection *conn = (tcp_connection *)userarg;
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
|
||||
tcp_to_write *to_write;
|
||||
ssize_t written;
|
||||
|
||||
assert(userarg);
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
|
||||
return;
|
||||
|
||||
if (getdns_context_get_eventloop(conn->l->set->context, &loop))
|
||||
return;
|
||||
|
||||
/* Reset tcp_connection idle timeout */
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
|
||||
if (!conn->to_write) {
|
||||
conn->event.write_cb = NULL;
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
return;
|
||||
}
|
||||
to_write = conn->to_write;
|
||||
if (conn->fd == -1 ||
|
||||
(written = write(conn->fd, &to_write->write_buf[to_write->written],
|
||||
to_write->write_buf_len - to_write->written)) == -1) {
|
||||
|
||||
/* IO error, close connection */
|
||||
conn->event.read_cb = conn->event.write_cb =
|
||||
conn->event.timeout_cb = NULL;
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
to_write->written += written;
|
||||
if (to_write->written == to_write->write_buf_len) {
|
||||
conn->to_write = to_write->next;
|
||||
GETDNS_FREE(*mf, to_write);
|
||||
}
|
||||
if (!conn->to_write)
|
||||
conn->event.write_cb = NULL;
|
||||
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
}
|
||||
|
||||
void
|
||||
_getdns_cancel_reply(getdns_context *context, getdns_transaction_t request_id)
|
||||
{
|
||||
/* TODO: Check request_id at context->outbound_requests */
|
||||
connection *conn = (connection *)(intptr_t)request_id;
|
||||
struct mem_funcs *mf;
|
||||
|
||||
if (!context || !conn)
|
||||
return;
|
||||
|
||||
if (conn->l->transport == GETDNS_TRANSPORT_TCP) {
|
||||
tcp_connection *conn = (tcp_connection *)(intptr_t)request_id;
|
||||
|
||||
if (conn->to_answer > 0 && --conn->to_answer == 0 &&
|
||||
conn->fd == -1)
|
||||
tcp_connection_destroy(conn);
|
||||
|
||||
} else if (conn->l->transport == GETDNS_TRANSPORT_UDP &&
|
||||
(mf = priv_getdns_context_mf(conn->l->set->context))) {
|
||||
listen_set *set = conn->l->set;
|
||||
|
||||
/* Unlink this connection */
|
||||
if ((*conn->prev_next = conn->next))
|
||||
conn->next->prev_next = conn->prev_next;
|
||||
GETDNS_FREE(*mf, conn);
|
||||
free_listen_set_when_done(set);
|
||||
}
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_reply(
|
||||
getdns_context *context, getdns_transaction_t request_id, getdns_dict *reply)
|
||||
{
|
||||
/* TODO: Check request_id at context->outbound_requests */
|
||||
connection *conn = (connection *)(intptr_t)request_id;
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
uint8_t buf[65536];
|
||||
size_t len;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!context || !reply || !conn)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
|
||||
return GETDNS_RETURN_GENERIC_ERROR;;
|
||||
|
||||
if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop)))
|
||||
return r;
|
||||
|
||||
len = sizeof(buf);
|
||||
if ((r = getdns_msg_dict2wire_buf(reply, buf, &len)))
|
||||
return r;
|
||||
|
||||
else if (conn->l->transport == GETDNS_TRANSPORT_UDP) {
|
||||
listener *l = conn->l;
|
||||
|
||||
if (conn->l->fd >= 0 && sendto(conn->l->fd, buf, len, 0,
|
||||
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
|
||||
/* IO error, cleanup this listener */
|
||||
loop->vmt->clear(loop, &conn->l->event);
|
||||
close(conn->l->fd);
|
||||
conn->l->fd = -1;
|
||||
}
|
||||
/* Unlink this connection */
|
||||
if ((*conn->prev_next = conn->next))
|
||||
conn->next->prev_next = conn->prev_next;
|
||||
|
||||
GETDNS_FREE(*mf, conn);
|
||||
if (l->fd < 0)
|
||||
free_listen_set_when_done(l->set);
|
||||
|
||||
} else if (conn->l->transport == GETDNS_TRANSPORT_TCP) {
|
||||
tcp_connection *conn = (tcp_connection *)(intptr_t)request_id;
|
||||
tcp_to_write **to_write_p;
|
||||
tcp_to_write *to_write;
|
||||
|
||||
if (conn->fd == -1) {
|
||||
if (conn->to_answer > 0)
|
||||
--conn->to_answer;
|
||||
tcp_connection_destroy(conn);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
if (!(to_write = (tcp_to_write *)GETDNS_XMALLOC(
|
||||
*mf, uint8_t, sizeof(tcp_to_write) + len + 2)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
to_write->write_buf_len = len + 2;
|
||||
to_write->write_buf[0] = (len >> 8) & 0xFF;
|
||||
to_write->write_buf[1] = len & 0xFF;
|
||||
to_write->written = 0;
|
||||
to_write->next = NULL;
|
||||
(void) memcpy(to_write->write_buf + 2, buf, len);
|
||||
|
||||
/* Appen to_write to conn->to_write list */
|
||||
for ( to_write_p = &conn->to_write
|
||||
; *to_write_p
|
||||
; to_write_p = &(*to_write_p)->next)
|
||||
; /* pass */
|
||||
*to_write_p = to_write;
|
||||
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
conn->event.write_cb = tcp_write_cb;
|
||||
if (conn->to_answer > 0)
|
||||
conn->to_answer--;
|
||||
(void) loop->vmt->schedule(loop,
|
||||
conn->fd, DOWNSTREAM_IDLE_TIMEOUT,
|
||||
&conn->event);
|
||||
}
|
||||
/* TODO: other transport types */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void tcp_read_cb(void *userarg)
|
||||
{
|
||||
tcp_connection *conn = (tcp_connection *)userarg;
|
||||
ssize_t bytes_read;
|
||||
getdns_return_t r;
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
getdns_dict *request_dict;
|
||||
|
||||
assert(userarg);
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
|
||||
return;
|
||||
|
||||
if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop)))
|
||||
return;
|
||||
|
||||
/* Reset tcp_connection idle timeout */
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
|
||||
if ((bytes_read = read(conn->fd, conn->read_pos, conn->to_read)) == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return; /* Come back to do the read later */
|
||||
|
||||
/* IO error, close connection */
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
if (bytes_read == 0) {
|
||||
/* remote end closed connection, cleanup */
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
assert(bytes_read <= conn->to_read);
|
||||
|
||||
conn->to_read -= bytes_read;
|
||||
conn->read_pos += bytes_read;
|
||||
if (conn->to_read)
|
||||
return; /* More to read */
|
||||
|
||||
if (conn->read_pos - conn->read_buf == 2) {
|
||||
/* read length of dns msg to read */
|
||||
conn->to_read = (conn->read_buf[0] << 8) | conn->read_buf[1];
|
||||
if (conn->to_read > conn->read_buf_len) {
|
||||
GETDNS_FREE(*mf, conn->read_buf);
|
||||
while (conn->to_read > conn->read_buf_len)
|
||||
conn->read_buf_len *= 2;
|
||||
if (!(conn->read_buf = GETDNS_XMALLOC(
|
||||
*mf, uint8_t, conn->read_buf_len))) {
|
||||
/* Memory error */
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (conn->to_read < 12) {
|
||||
/* Request smaller than DNS header, FORMERR */
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
conn->read_pos = conn->read_buf;
|
||||
return; /* Read DNS message */
|
||||
}
|
||||
if ((r = getdns_wire2msg_dict(conn->read_buf,
|
||||
(conn->read_pos - conn->read_buf), &request_dict)))
|
||||
; /* FROMERR on input, ignore */
|
||||
|
||||
else {
|
||||
conn->to_answer++;
|
||||
|
||||
/* Call request handler */
|
||||
conn->l->set->handler(
|
||||
conn->l->set->context, request_dict, (intptr_t)conn);
|
||||
|
||||
conn->read_pos = conn->read_buf;
|
||||
conn->to_read = 2;
|
||||
return; /* Read more requests */
|
||||
}
|
||||
conn->read_pos = conn->read_buf;
|
||||
conn->to_read = 2;
|
||||
/* Read more requests */
|
||||
}
|
||||
|
||||
static void tcp_timeout_cb(void *userarg)
|
||||
{
|
||||
tcp_connection *conn = (tcp_connection *)userarg;
|
||||
|
||||
assert(userarg);
|
||||
|
||||
if (conn->to_answer) {
|
||||
getdns_eventloop *loop;
|
||||
|
||||
if (getdns_context_get_eventloop(conn->l->set->context, &loop))
|
||||
return;
|
||||
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
(void) loop->vmt->schedule(loop,
|
||||
conn->fd, DOWNSTREAM_IDLE_TIMEOUT,
|
||||
&conn->event);
|
||||
} else
|
||||
tcp_connection_destroy(conn);
|
||||
}
|
||||
|
||||
static void tcp_accept_cb(void *userarg)
|
||||
{
|
||||
listener *l = (listener *)userarg;
|
||||
tcp_connection *conn;
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
getdns_return_t r;
|
||||
|
||||
assert(userarg);
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(l->set->context)))
|
||||
return;
|
||||
|
||||
if ((r = getdns_context_get_eventloop(l->set->context, &loop)))
|
||||
return;
|
||||
|
||||
if (!(conn = GETDNS_MALLOC(*mf, tcp_connection)))
|
||||
return;
|
||||
|
||||
(void) memset(conn, 0, sizeof(tcp_connection));
|
||||
|
||||
conn->l = l;
|
||||
conn->addrlen = sizeof(conn->remote_in);
|
||||
if ((conn->fd = accept(l->fd,
|
||||
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
|
||||
/* IO error, cleanup this listener */
|
||||
loop->vmt->clear(loop, &l->event);
|
||||
close(l->fd);
|
||||
l->fd = -1;
|
||||
GETDNS_FREE(*mf, conn);
|
||||
return;
|
||||
}
|
||||
if (!(conn->read_buf = malloc(DNS_REQUEST_SZ))) {
|
||||
/* Memory error */
|
||||
GETDNS_FREE(*mf, conn);
|
||||
return;
|
||||
}
|
||||
conn->read_buf_len = DNS_REQUEST_SZ;
|
||||
conn->read_pos = conn->read_buf;
|
||||
conn->to_read = 2;
|
||||
conn->event.userarg = conn;
|
||||
conn->event.read_cb = tcp_read_cb;
|
||||
conn->event.timeout_cb = tcp_timeout_cb;
|
||||
|
||||
/* Insert connection */
|
||||
if ((conn->next = l->connections))
|
||||
conn->next->prev_next = &conn->next;
|
||||
conn->prev_next = &l->connections;
|
||||
l->connections = (connection *)conn;
|
||||
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
}
|
||||
|
||||
static void udp_read_cb(void *userarg)
|
||||
{
|
||||
listener *l = (listener *)userarg;
|
||||
connection *conn;
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
getdns_dict *request_dict;
|
||||
|
||||
/* Maximum reasonable size for requests */
|
||||
uint8_t buf[4096];
|
||||
ssize_t len;
|
||||
getdns_return_t r;
|
||||
|
||||
assert(userarg);
|
||||
|
||||
if (l->fd == -1)
|
||||
return;
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(l->set->context)))
|
||||
return;
|
||||
|
||||
if ((r = getdns_context_get_eventloop(l->set->context, &loop)))
|
||||
return;
|
||||
|
||||
if (!(conn = GETDNS_MALLOC(*mf, connection)))
|
||||
return;
|
||||
|
||||
conn->l = l;
|
||||
conn->addrlen = sizeof(conn->remote_in);
|
||||
if ((len = recvfrom(l->fd, buf, sizeof(buf), 0,
|
||||
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
|
||||
/* IO error, cleanup this listener. */
|
||||
loop->vmt->clear(loop, &l->event);
|
||||
close(l->fd);
|
||||
l->fd = -1;
|
||||
|
||||
} else if ((r = getdns_wire2msg_dict(buf, len, &request_dict)))
|
||||
; /* FROMERR on input, ignore */
|
||||
|
||||
else {
|
||||
/* Insert connection */
|
||||
if ((conn->next = l->connections))
|
||||
conn->next->prev_next = &conn->next;
|
||||
conn->prev_next = &l->connections;
|
||||
l->connections = conn;
|
||||
|
||||
/* Call request handler */
|
||||
l->set->handler(l->set->context, request_dict, (intptr_t)conn);
|
||||
return;
|
||||
}
|
||||
GETDNS_FREE(*mf, conn);
|
||||
}
|
||||
|
||||
static void rm_listen_set(listen_set **root, listen_set *set)
|
||||
{
|
||||
assert(root);
|
||||
|
||||
while (*root && *root != set)
|
||||
root = &(*root)->next;
|
||||
|
||||
*root = set->next;
|
||||
set->next = NULL;
|
||||
}
|
||||
|
||||
static listen_set *lookup_listen_set(listen_set *root, getdns_context *key)
|
||||
{
|
||||
while (root && root->context != key)
|
||||
root = root->next;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
static void free_listen_set_when_done(listen_set *set)
|
||||
{
|
||||
struct mem_funcs *mf;
|
||||
size_t i;
|
||||
|
||||
assert(set);
|
||||
assert(set->context);
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(set->context)))
|
||||
return;
|
||||
|
||||
DEBUG_SERVER("To free listen set: %p\n", set);
|
||||
for (i = 0; i < set->count; i++) {
|
||||
listener *l = &set->items[i];
|
||||
|
||||
if (l->fd >= 0)
|
||||
return;
|
||||
|
||||
if (l->connections)
|
||||
return;
|
||||
}
|
||||
GETDNS_FREE(*mf, set);
|
||||
DEBUG_SERVER("Listen set: %p freed\n", set);
|
||||
}
|
||||
|
||||
static void remove_listeners(listen_set *set)
|
||||
{
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
size_t i;
|
||||
|
||||
assert(set);
|
||||
assert(set->context);
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(set->context)))
|
||||
return;
|
||||
|
||||
if (getdns_context_get_eventloop(set->context, &loop))
|
||||
return;
|
||||
|
||||
for (i = 0; i < set->count; i++) {
|
||||
listener *l = &set->items[i];
|
||||
tcp_connection **conn_p;
|
||||
|
||||
if (l->action != to_remove || l->fd == -1)
|
||||
continue;
|
||||
|
||||
loop->vmt->clear(loop, &l->event);
|
||||
close(l->fd);
|
||||
l->fd = -1;
|
||||
|
||||
if (l->transport != GETDNS_TRANSPORT_TCP)
|
||||
continue;
|
||||
|
||||
conn_p = (tcp_connection **)&l->connections;
|
||||
while (*conn_p) {
|
||||
tcp_connection_destroy(*conn_p);
|
||||
if (*conn_p && (*conn_p)->to_answer > 0)
|
||||
conn_p = (tcp_connection **)&(*conn_p)->next;
|
||||
}
|
||||
}
|
||||
free_listen_set_when_done(set);
|
||||
}
|
||||
|
||||
static getdns_return_t add_listeners(listen_set *set)
|
||||
{
|
||||
static const int enable = 1;
|
||||
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
size_t i;
|
||||
getdns_return_t r;
|
||||
|
||||
assert(set);
|
||||
assert(set->context);
|
||||
|
||||
if (!(mf = priv_getdns_context_mf(set->context)))
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
if ((r = getdns_context_get_eventloop(set->context, &loop)))
|
||||
return r;
|
||||
|
||||
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
for (i = 0; i < set->count; i++) {
|
||||
listener *l = &set->items[i];
|
||||
|
||||
if (l->action != to_add)
|
||||
continue;
|
||||
|
||||
if (l->transport != GETDNS_TRANSPORT_UDP &&
|
||||
l->transport != GETDNS_TRANSPORT_TCP)
|
||||
continue;
|
||||
|
||||
if ((l->fd = socket(l->addr.ss_family,
|
||||
( l->transport == GETDNS_TRANSPORT_UDP
|
||||
? SOCK_DGRAM : SOCK_STREAM), 0)) == -1)
|
||||
/* IO error */
|
||||
break;
|
||||
|
||||
if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&enable, sizeof(int)) < 0)
|
||||
; /* Ignore */
|
||||
|
||||
if (bind(l->fd, (struct sockaddr *)&l->addr,
|
||||
l->addr_len) == -1)
|
||||
/* IO error */
|
||||
break;
|
||||
|
||||
if (l->transport == GETDNS_TRANSPORT_UDP) {
|
||||
l->event.userarg = l;
|
||||
l->event.read_cb = udp_read_cb;
|
||||
if ((r = loop->vmt->schedule(
|
||||
loop, l->fd, -1, &l->event)))
|
||||
break;
|
||||
|
||||
} else if (listen(l->fd, TCP_LISTEN_BACKLOG) == -1)
|
||||
/* IO error */
|
||||
break;
|
||||
|
||||
else {
|
||||
l->event.userarg = l;
|
||||
l->event.read_cb = tcp_accept_cb;
|
||||
if ((r = loop->vmt->schedule(
|
||||
loop, l->fd, -1, &l->event)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < set->count)
|
||||
return r;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
|
||||
getdns_request_handler_t request_handler, getdns_list *listen_addresses)
|
||||
{
|
||||
static const getdns_transport_list_t listen_transports[]
|
||||
= { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP };
|
||||
static const uint32_t transport_ports[] = { 53, 53 };
|
||||
static const size_t n_transports = sizeof( listen_transports)
|
||||
/ sizeof(*listen_transports);
|
||||
static listen_set *root = NULL;
|
||||
|
||||
listen_set *current_set;
|
||||
listen_set *new_set;
|
||||
size_t new_set_count;
|
||||
|
||||
struct mem_funcs *mf;
|
||||
getdns_eventloop *loop;
|
||||
|
||||
/* auxiliary variables */
|
||||
getdns_return_t r;
|
||||
size_t i;
|
||||
struct addrinfo hints;
|
||||
|
||||
DEBUG_SERVER("getdns_context_set_listen_addresses(%p, %p, %p)\n", context, request_handler,
|
||||
listen_addresses);
|
||||
if (!(mf = priv_getdns_context_mf(context)))
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
if ((r = getdns_context_get_eventloop(context, &loop)))
|
||||
return r;
|
||||
|
||||
if (listen_addresses == NULL)
|
||||
new_set_count = 0;
|
||||
|
||||
else if ((r = getdns_list_get_length(listen_addresses, &new_set_count)))
|
||||
return r;
|
||||
|
||||
if ((current_set = lookup_listen_set(root, context))) {
|
||||
for (i = 0; i < current_set->count; i++)
|
||||
current_set->items[i].action = to_remove;
|
||||
}
|
||||
if (new_set_count == 0) {
|
||||
if (!current_set)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
||||
rm_listen_set(&root, current_set);
|
||||
/* action is already to_remove */
|
||||
remove_listeners(current_set);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
if (!request_handler)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!(new_set = (listen_set *)GETDNS_XMALLOC(*mf, uint8_t,
|
||||
sizeof(listen_set) +
|
||||
sizeof(listener) * new_set_count * n_transports)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
DEBUG_SERVER("New listen set: %p, current_set: %p\n", new_set, current_set);
|
||||
|
||||
new_set->context = context;
|
||||
new_set->next = root;
|
||||
new_set->handler = request_handler;
|
||||
new_set->count = new_set_count * n_transports;
|
||||
(void) memset(new_set->items, 0,
|
||||
sizeof(listener) * new_set_count * n_transports);
|
||||
|
||||
(void) memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
for (i = 0; !r && i < new_set_count; i++) {
|
||||
getdns_dict *dict = NULL;
|
||||
getdns_bindata *address_data;
|
||||
struct sockaddr_storage addr;
|
||||
getdns_bindata *scope_id;
|
||||
char addrstr[1024], *eos;
|
||||
size_t t;
|
||||
|
||||
if ((r = getdns_list_get_dict(listen_addresses, i, &dict))) {
|
||||
if ((r = getdns_list_get_bindata(
|
||||
listen_addresses, i, &address_data)))
|
||||
break;
|
||||
|
||||
} else if ((r = getdns_dict_get_bindata(
|
||||
dict, "address_data", &address_data)))
|
||||
break;
|
||||
|
||||
if (address_data->size == 4)
|
||||
addr.ss_family = AF_INET;
|
||||
else if (address_data->size == 16)
|
||||
addr.ss_family = AF_INET6;
|
||||
else {
|
||||
r = GETDNS_RETURN_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
if (inet_ntop(addr.ss_family,
|
||||
address_data->data, addrstr, 1024) == NULL) {
|
||||
r = GETDNS_RETURN_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
if (dict && getdns_dict_get_bindata(dict,"scope_id",&scope_id)
|
||||
== GETDNS_RETURN_GOOD) {
|
||||
if (strlen(addrstr) + scope_id->size > 1022) {
|
||||
r = GETDNS_RETURN_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
eos = &addrstr[strlen(addrstr)];
|
||||
*eos++ = '%';
|
||||
(void) memcpy(eos, scope_id->data, scope_id->size);
|
||||
eos[scope_id->size] = 0;
|
||||
}
|
||||
for (t = 0; !r && t < n_transports; t++) {
|
||||
char portstr[1024];
|
||||
getdns_transport_list_t transport
|
||||
= listen_transports[t];
|
||||
uint32_t port = transport_ports[t];
|
||||
struct addrinfo *ai;
|
||||
listener *l = &new_set->items[i*n_transports + t];
|
||||
size_t j;
|
||||
listener *cl;
|
||||
|
||||
l->fd = -1;
|
||||
if (dict)
|
||||
(void) getdns_dict_get_int(dict,
|
||||
( transport == GETDNS_TRANSPORT_TLS
|
||||
? "tls_port" : "port" ), &port);
|
||||
|
||||
(void) snprintf(portstr, 1024, "%d", (int)port);
|
||||
|
||||
if (getaddrinfo(addrstr, portstr, &hints, &ai)) {
|
||||
r = GETDNS_RETURN_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
if (!ai)
|
||||
continue;
|
||||
|
||||
l->addr.ss_family = addr.ss_family;
|
||||
l->addr_len = ai->ai_addrlen;
|
||||
(void) memcpy(&l->addr, ai->ai_addr, ai->ai_addrlen);
|
||||
l->transport = transport;
|
||||
l->set = new_set;
|
||||
l->connections = NULL;
|
||||
freeaddrinfo(ai);
|
||||
|
||||
/* Now determine the action */
|
||||
if (!current_set) {
|
||||
l->action = to_add;
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < current_set->count; j++) {
|
||||
cl = ¤t_set->items[j];
|
||||
|
||||
if (l->transport == cl->transport &&
|
||||
l->addr_len == cl->addr_len &&
|
||||
!memcmp(&l->addr, &cl->addr, l->addr_len))
|
||||
break;
|
||||
}
|
||||
if (j == current_set->count) {
|
||||
/* Not found */
|
||||
l->action = to_add;
|
||||
continue;
|
||||
}
|
||||
l->action = to_stay;
|
||||
l->to_replace = cl;
|
||||
/* So the event can be rescheduled */
|
||||
}
|
||||
}
|
||||
if ((r = add_listeners(new_set))) {
|
||||
for (i = 0; i < new_set->count; i++)
|
||||
new_set->items[i].action = to_remove;
|
||||
|
||||
remove_listeners(new_set);
|
||||
return r;
|
||||
}
|
||||
/* Reschedule all stayers */
|
||||
for (i = 0; i < new_set->count; i++) {
|
||||
listener *l = &new_set->items[i];
|
||||
|
||||
if (l->action == to_stay) {
|
||||
connection *conn;
|
||||
|
||||
loop->vmt->clear(loop, &l->to_replace->event);
|
||||
(void) memset(&l->to_replace->event, 0,
|
||||
sizeof(getdns_eventloop_event));
|
||||
|
||||
l->fd = l->to_replace->fd;
|
||||
l->event = l->to_replace->event;
|
||||
l->connections = l->to_replace->connections;
|
||||
for (conn = l->connections; conn; conn = conn->next)
|
||||
conn->l = l;
|
||||
|
||||
l->to_replace->connections = NULL;
|
||||
l->to_replace->fd = -1;
|
||||
|
||||
/* assume success on reschedule */
|
||||
(void) loop->vmt->schedule(loop, l->fd, -1, &l->event);
|
||||
}
|
||||
}
|
||||
if (current_set) {
|
||||
rm_listen_set(&root, current_set);
|
||||
remove_listeners(current_set); /* Is already remove */
|
||||
}
|
||||
root = new_set;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GETDNS_CONTEXT_SET_LISTEN_ADDRESSES_H_
|
||||
#define GETDNS_CONTEXT_SET_LISTEN_ADDRESSES_H_
|
||||
#include "getdns/getdns.h"
|
||||
|
||||
typedef void (*getdns_request_handler_t)(
|
||||
getdns_context *context,
|
||||
getdns_dict *request,
|
||||
getdns_transaction_t request_id
|
||||
);
|
||||
|
||||
getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
|
||||
getdns_request_handler_t request_handler, getdns_list *listen_addresses);
|
||||
|
||||
getdns_return_t getdns_reply(getdns_context *context,
|
||||
getdns_transaction_t request_id, getdns_dict *reply);
|
||||
|
||||
void _getdns_cancel_reply(getdns_context *context,
|
||||
getdns_transaction_t request_id);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,926 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "const-info.h"
|
||||
#include "jsmn/jsmn.h"
|
||||
#include "getdns_str2dict.h"
|
||||
#include "types-internal.h" /* For getdns_item */
|
||||
#include "list.h" /* For _getdns_list_create_from_mf() */
|
||||
#include "dict.h" /* For _getdns_dict_create_from_mf() */
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
|
||||
static struct mem_funcs _getdns_plain_mem_funcs = {
|
||||
MF_PLAIN, .mf.pln = { malloc, realloc, free }
|
||||
};
|
||||
|
||||
/* TODO: Replace with gldns_b64_pton
|
||||
* once getdns_ipaddr_dict becomes part of the library
|
||||
*/
|
||||
static int _gldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
|
||||
{
|
||||
const uint8_t pad64 = 64; /* is 64th in the b64 array */
|
||||
const char* s = src;
|
||||
uint8_t in[4];
|
||||
size_t o = 0, incount = 0;
|
||||
|
||||
while(*s) {
|
||||
/* skip any character that is not base64 */
|
||||
/* conceptually we do:
|
||||
const char* b64 = pad'=' is appended to array
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
const char* d = strchr(b64, *s++);
|
||||
and use d-b64;
|
||||
*/
|
||||
char d = *s++;
|
||||
if(d <= 'Z' && d >= 'A')
|
||||
d -= 'A';
|
||||
else if(d <= 'z' && d >= 'a')
|
||||
d = d - 'a' + 26;
|
||||
else if(d <= '9' && d >= '0')
|
||||
d = d - '0' + 52;
|
||||
else if(d == '+')
|
||||
d = 62;
|
||||
else if(d == '/')
|
||||
d = 63;
|
||||
else if(d == '=')
|
||||
d = 64;
|
||||
else continue;
|
||||
in[incount++] = (uint8_t)d;
|
||||
if(incount != 4)
|
||||
continue;
|
||||
/* process whole block of 4 characters into 3 output bytes */
|
||||
if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
|
||||
if(o+1 > targsize)
|
||||
return -1;
|
||||
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
|
||||
o += 1;
|
||||
break; /* we are done */
|
||||
} else if(in[3] == pad64) { /* A B C = */
|
||||
if(o+2 > targsize)
|
||||
return -1;
|
||||
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
|
||||
target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
|
||||
o += 2;
|
||||
break; /* we are done */
|
||||
} else {
|
||||
if(o+3 > targsize)
|
||||
return -1;
|
||||
/* write xxxxxxyy yyyyzzzz zzwwwwww */
|
||||
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
|
||||
target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
|
||||
target[o+2]= ((in[2]&0x03)<<6) | in[3];
|
||||
o += 3;
|
||||
}
|
||||
incount = 0;
|
||||
}
|
||||
return (int)o;
|
||||
}
|
||||
|
||||
static getdns_dict *
|
||||
_getdns_ipaddr_dict_mf(struct mem_funcs *mf, char *ipstr)
|
||||
{
|
||||
getdns_dict *r = _getdns_dict_create_with_mf(mf);
|
||||
char *s = strchr(ipstr, '%'), *scope_id_str = "";
|
||||
char *p = strchr(ipstr, '@'), *portstr = "";
|
||||
char *t = strchr(ipstr, '#'), *tls_portstr = "";
|
||||
char *n = strchr(ipstr, '~'), *tls_namestr = "";
|
||||
/* ^[alg:]name:key */
|
||||
char *T = strchr(ipstr, '^'), *tsig_name_str = ""
|
||||
, *tsig_secret_str = ""
|
||||
, *tsig_algorithm_str = "";
|
||||
char *br, *c;
|
||||
int tsig_secret_size;
|
||||
uint8_t tsig_secret_buf[256]; /* 4 times SHA512 */
|
||||
getdns_bindata tsig_secret;
|
||||
uint8_t buf[sizeof(struct in6_addr)];
|
||||
getdns_bindata addr;
|
||||
|
||||
addr.data = buf;
|
||||
|
||||
if (!r) return NULL;
|
||||
|
||||
if (*ipstr == '[') {
|
||||
char *br = strchr(ipstr, ']');
|
||||
if (br) {
|
||||
ipstr += 1;
|
||||
*br = 0;
|
||||
if ((c = strchr(br + 1, ':'))) {
|
||||
p = c;
|
||||
}
|
||||
}
|
||||
} else if ((br = strchr(ipstr, '.')) && (c = strchr(br + 1, ':'))
|
||||
&& (T == NULL || c < T))
|
||||
p = c;
|
||||
|
||||
else if ((*ipstr == '*') && (c = strchr(ipstr+1, ':')))
|
||||
p = c;
|
||||
|
||||
if (s) {
|
||||
*s = 0;
|
||||
scope_id_str = s + 1;
|
||||
}
|
||||
if (p) {
|
||||
*p = 0;
|
||||
portstr = p + 1;
|
||||
}
|
||||
if (t) {
|
||||
*t = 0;
|
||||
tls_portstr = t + 1;
|
||||
}
|
||||
if (n) {
|
||||
*n = 0;
|
||||
tls_namestr = n + 1;
|
||||
}
|
||||
if (T) {
|
||||
*T = 0;
|
||||
tsig_name_str = T + 1;
|
||||
if ((T = strchr(tsig_name_str, ':'))) {
|
||||
*T = 0;
|
||||
tsig_secret_str = T + 1;
|
||||
if ((T = strchr(tsig_secret_str, ':'))) {
|
||||
*T = 0;
|
||||
tsig_algorithm_str = tsig_name_str;
|
||||
tsig_name_str = tsig_secret_str;
|
||||
tsig_secret_str = T + 1;
|
||||
}
|
||||
} else {
|
||||
tsig_name_str = "";
|
||||
}
|
||||
}
|
||||
if (*ipstr == '*') {
|
||||
getdns_dict_util_set_string(r, "address_type", "IPv6");
|
||||
addr.size = 16;
|
||||
(void) memset(buf, 0, 16);
|
||||
} else if (strchr(ipstr, ':')) {
|
||||
getdns_dict_util_set_string(r, "address_type", "IPv6");
|
||||
addr.size = 16;
|
||||
if (inet_pton(AF_INET6, ipstr, buf) <= 0) {
|
||||
getdns_dict_destroy(r);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
getdns_dict_util_set_string(r, "address_type", "IPv4");
|
||||
addr.size = 4;
|
||||
if (inet_pton(AF_INET, ipstr, buf) <= 0) {
|
||||
getdns_dict_destroy(r);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
getdns_dict_set_bindata(r, "address_data", &addr);
|
||||
if (*portstr)
|
||||
getdns_dict_set_int(r, "port", (int32_t)atoi(portstr));
|
||||
if (*tls_portstr)
|
||||
getdns_dict_set_int(r, "tls_port", (int32_t)atoi(tls_portstr));
|
||||
if (*tls_namestr) {
|
||||
getdns_dict_util_set_string(r, "tls_auth_name", tls_namestr);
|
||||
}
|
||||
if (*scope_id_str)
|
||||
getdns_dict_util_set_string(r, "scope_id", scope_id_str);
|
||||
if (*tsig_name_str)
|
||||
getdns_dict_util_set_string(r, "tsig_name", tsig_name_str);
|
||||
if (*tsig_algorithm_str)
|
||||
getdns_dict_util_set_string(r, "tsig_algorithm", tsig_algorithm_str);
|
||||
if (*tsig_secret_str) {
|
||||
tsig_secret_size = _gldns_b64_pton(
|
||||
tsig_secret_str, tsig_secret_buf, sizeof(tsig_secret_buf));
|
||||
if (tsig_secret_size > 0) {
|
||||
tsig_secret.size = tsig_secret_size;
|
||||
tsig_secret.data = tsig_secret_buf;
|
||||
getdns_dict_set_bindata(r, "tsig_secret", &tsig_secret);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
getdns_dict **value)
|
||||
{
|
||||
char value_str[3072];
|
||||
int size = t->end - t->start;
|
||||
|
||||
if (size <= 0 || size >= sizeof(value_str))
|
||||
return 0;
|
||||
|
||||
(void) memcpy(value_str, js + t->start, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
*value = _getdns_ipaddr_dict_mf(mf, value_str);
|
||||
return *value != NULL;
|
||||
}
|
||||
|
||||
getdns_dict *
|
||||
_getdns_ipaddr_dict(const char *ipstr)
|
||||
{
|
||||
char value_str[3072];
|
||||
size_t size = strlen(ipstr);
|
||||
|
||||
if (size >= sizeof(value_str))
|
||||
return NULL;
|
||||
|
||||
(void) memcpy(value_str, ipstr, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
return _getdns_ipaddr_dict_mf(&_getdns_plain_mem_funcs, value_str);
|
||||
}
|
||||
|
||||
static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
getdns_bindata **value)
|
||||
{
|
||||
size_t i, j;
|
||||
uint8_t h, l;
|
||||
|
||||
if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1 ||
|
||||
js[t->start] != '0' || js[t->start + 1] != 'x')
|
||||
return 0;
|
||||
|
||||
for (i = t->start + 2; i < t->end; i++)
|
||||
if (!((js[i] >= '0' && js[i] <= '9')
|
||||
||(js[i] >= 'a' && js[i] <= 'f')
|
||||
||(js[i] >= 'A' && js[i] <= 'F')))
|
||||
return 0;
|
||||
|
||||
if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
|
||||
return 0;
|
||||
|
||||
else if (!((*value)->data = GETDNS_XMALLOC(
|
||||
*mf, uint8_t, (t->end - t->start) / 2 - 1))) {
|
||||
GETDNS_FREE(*mf, *value);
|
||||
return 0;
|
||||
}
|
||||
for (i = t->start + 2, j = 0; i < t->end; i++, j++) {
|
||||
h = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
|
||||
: js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
|
||||
: js[i] + 10 - 'a';
|
||||
h <<= 4;
|
||||
i++;
|
||||
l = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
|
||||
: js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
|
||||
: js[i] + 10 - 'a';
|
||||
(*value)->data[j] = h | l;
|
||||
}
|
||||
(*value)->size = j;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _jsmn_get_dname(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
getdns_bindata **value)
|
||||
{
|
||||
char value_str[1025];
|
||||
int size = t->end - t->start;
|
||||
|
||||
if (size <= 0 || size >= sizeof(value_str) || js[t->end - 1] != '.')
|
||||
return 0;
|
||||
|
||||
(void) memcpy(value_str, js + t->start, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
return !getdns_convert_fqdn_to_dns_name(value_str, value);
|
||||
}
|
||||
|
||||
static int _jsmn_get_ipv4(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
getdns_bindata **value)
|
||||
{
|
||||
char value_str[16];
|
||||
int size = t->end - t->start;
|
||||
uint8_t buf[4];
|
||||
|
||||
if (size <= 0 || size >= sizeof(value_str))
|
||||
return 0;
|
||||
|
||||
(void) memcpy(value_str, js + t->start, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
if (inet_pton(AF_INET, value_str, buf) <= 0)
|
||||
; /* pass */
|
||||
|
||||
else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
|
||||
; /* pass */
|
||||
|
||||
else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 4)))
|
||||
GETDNS_FREE(*mf, *value);
|
||||
|
||||
else {
|
||||
(*value)->size = 4;
|
||||
(void) memcpy((*value)->data, buf, 4);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _jsmn_get_ipv6(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
getdns_bindata **value)
|
||||
{
|
||||
char value_str[40];
|
||||
int size = t->end - t->start;
|
||||
uint8_t buf[16];
|
||||
|
||||
if (size <= 0 || size >= sizeof(value_str))
|
||||
return 0;
|
||||
|
||||
(void) memcpy(value_str, js + t->start, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
if (inet_pton(AF_INET6, value_str, buf) <= 0)
|
||||
; /* pass */
|
||||
|
||||
else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
|
||||
; /* pass */
|
||||
|
||||
else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 16)))
|
||||
GETDNS_FREE(*mf, *value);
|
||||
|
||||
else {
|
||||
(*value)->size = 16;
|
||||
(void) memcpy((*value)->data, buf, 16);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _jsmn_get_int(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
uint32_t *value)
|
||||
{
|
||||
char value_str[11];
|
||||
int size = t->end - t->start;
|
||||
char *endptr;
|
||||
|
||||
if (size <= 0 || size >= sizeof(value_str))
|
||||
return 0;
|
||||
|
||||
(void) memcpy(value_str, js + t->start, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
*value = (uint32_t)strtoul(value_str, &endptr, 10);
|
||||
return *value_str != '\0' && *endptr == '\0';
|
||||
}
|
||||
|
||||
static int _getdns_get_const_name_info(const char *name, uint32_t *code);
|
||||
|
||||
static int _jsmn_get_const(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
uint32_t *value)
|
||||
{
|
||||
char value_str[80];
|
||||
int size = t->end - t->start;
|
||||
|
||||
if (size <= 0 || size >= sizeof(value_str))
|
||||
return 0;
|
||||
|
||||
(void) memcpy(value_str, js + t->start, size);
|
||||
value_str[size] = '\0';
|
||||
|
||||
return _getdns_get_const_name_info(value_str, value);
|
||||
}
|
||||
|
||||
static void
|
||||
_getdns_destroy_item_data(struct mem_funcs *mf, getdns_item *item)
|
||||
{
|
||||
switch (item->dtype) {
|
||||
case t_dict:
|
||||
getdns_dict_destroy(item->data.dict);
|
||||
break;
|
||||
|
||||
case t_list:
|
||||
getdns_list_destroy(item->data.list);
|
||||
break;
|
||||
|
||||
case t_bindata:
|
||||
GETDNS_FREE(*mf, item->data.bindata->data);
|
||||
GETDNS_FREE(*mf, item->data.bindata);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
size_t count, getdns_item *item, getdns_return_t *r);
|
||||
|
||||
static int _jsmn_get_dict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
size_t count, getdns_dict *dict, getdns_return_t *r)
|
||||
{
|
||||
size_t i, j = 1;
|
||||
char key_spc[1024], *key = NULL;
|
||||
getdns_item child_item;
|
||||
|
||||
for (i = 0; i < t->size; i++) {
|
||||
if (t[j].type != JSMN_STRING &&
|
||||
t[j].type != JSMN_PRIMITIVE) {
|
||||
|
||||
/* Key must be string or primitive */
|
||||
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
break;
|
||||
}
|
||||
if (t[j].end <= t[j].start) {
|
||||
/* Key must be at least 1 character */
|
||||
*r = GETDNS_RETURN_GENERIC_ERROR; /* range error */
|
||||
break;
|
||||
}
|
||||
if (t[j].end - t[j].start < sizeof(key_spc))
|
||||
key = key_spc;
|
||||
|
||||
else if (!(key = GETDNS_XMALLOC(
|
||||
*mf, char, t[j].end - t[j].start + 1))) {
|
||||
|
||||
*r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
break;
|
||||
}
|
||||
(void) memcpy(key, js + t[j].start, t[j].end - t[j].start);
|
||||
key[t[j].end - t[j].start] = '\0';
|
||||
j += 1;
|
||||
|
||||
j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
|
||||
if (*r) break;
|
||||
|
||||
switch (child_item.dtype) {
|
||||
case t_int:
|
||||
*r = getdns_dict_set_int(dict, key,
|
||||
child_item.data.n);
|
||||
break;
|
||||
case t_bindata:
|
||||
*r = getdns_dict_set_bindata(dict, key,
|
||||
child_item.data.bindata);
|
||||
break;
|
||||
case t_list:
|
||||
*r = getdns_dict_set_list(dict, key,
|
||||
child_item.data.list);
|
||||
break;
|
||||
case t_dict:
|
||||
*r = getdns_dict_set_dict(dict, key,
|
||||
child_item.data.dict);
|
||||
break;
|
||||
default:
|
||||
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
break;
|
||||
|
||||
}
|
||||
_getdns_destroy_item_data(mf, &child_item);
|
||||
if (*r) break;
|
||||
if (key && key != key_spc) {
|
||||
GETDNS_FREE(*mf, key);
|
||||
key = NULL;
|
||||
}
|
||||
}
|
||||
if (key && key != key_spc)
|
||||
GETDNS_FREE(*mf, key);
|
||||
|
||||
if (*r) {
|
||||
getdns_dict_destroy(dict);
|
||||
return 0;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
static int _jsmn_get_list(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
size_t count, getdns_list *list, getdns_return_t *r)
|
||||
{
|
||||
size_t i, j = 1, index = 0;
|
||||
getdns_item child_item;
|
||||
|
||||
for (i = 0; i < t->size; i++) {
|
||||
j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
|
||||
if (*r) break;
|
||||
|
||||
switch (child_item.dtype) {
|
||||
case t_int:
|
||||
*r = getdns_list_set_int(list, index++,
|
||||
child_item.data.n);
|
||||
break;
|
||||
case t_bindata:
|
||||
*r = getdns_list_set_bindata(list, index++,
|
||||
child_item.data.bindata);
|
||||
break;
|
||||
case t_list:
|
||||
*r = getdns_list_set_list(list, index++,
|
||||
child_item.data.list);
|
||||
break;
|
||||
case t_dict:
|
||||
*r = getdns_list_set_dict(list, index++,
|
||||
child_item.data.dict);
|
||||
break;
|
||||
default:
|
||||
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
break;
|
||||
|
||||
}
|
||||
_getdns_destroy_item_data(mf, &child_item);
|
||||
if (*r) break;
|
||||
}
|
||||
if (*r) {
|
||||
getdns_list_destroy(list);
|
||||
return 0;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
|
||||
size_t count, getdns_item *item, getdns_return_t *r)
|
||||
{
|
||||
assert(item);
|
||||
|
||||
switch (t->type) {
|
||||
case JSMN_STRING:
|
||||
if (t->end < t->start)
|
||||
*r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
else if (!(item->data.bindata =
|
||||
GETDNS_MALLOC(*mf, getdns_bindata)))
|
||||
*r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
else if (!(item->data.bindata->data = GETDNS_XMALLOC(
|
||||
*mf, uint8_t, t->end - t->start + 1))) {
|
||||
GETDNS_FREE(*mf, item->data.bindata);
|
||||
*r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
} else {
|
||||
item->dtype = t_bindata;
|
||||
if (t->end - t->start) {
|
||||
(void) memcpy(item->data.bindata->data,
|
||||
js + t->start, t->end - t->start);
|
||||
}
|
||||
item->data.bindata->data[t->end - t->start] = '\0';
|
||||
item->data.bindata->size = t->end - t->start;
|
||||
*r = GETDNS_RETURN_GOOD;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case JSMN_PRIMITIVE:
|
||||
/* There is no such thing as an empty primitive */
|
||||
if (t->end <= t->start) {
|
||||
*r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
break;
|
||||
|
||||
} else if (_jsmn_get_int(mf, js, t, &item->data.n)
|
||||
|| _jsmn_get_const(mf, js, t, &item->data.n)) {
|
||||
|
||||
item->dtype = t_int;
|
||||
}
|
||||
else if (_jsmn_get_data(mf, js, t, &item->data.bindata)
|
||||
|| _jsmn_get_dname(mf, js, t, &item->data.bindata)
|
||||
|| _jsmn_get_ipv4(mf, js, t, &item->data.bindata)
|
||||
|| _jsmn_get_ipv6(mf, js, t, &item->data.bindata))
|
||||
|
||||
item->dtype = t_bindata;
|
||||
|
||||
else if (_jsmn_get_ipdict(mf, js, t, &item->data.dict))
|
||||
|
||||
item->dtype = t_dict;
|
||||
else {
|
||||
*r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
break;
|
||||
}
|
||||
*r = GETDNS_RETURN_GOOD;
|
||||
return 1;
|
||||
|
||||
case JSMN_OBJECT:
|
||||
if (!(item->data.dict = _getdns_dict_create_with_mf(mf))) {
|
||||
*r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
break;
|
||||
}
|
||||
item->dtype = t_dict;
|
||||
return _jsmn_get_dict(mf, js, t, count, item->data.dict, r);
|
||||
|
||||
case JSMN_ARRAY:
|
||||
if (!(item->data.list = _getdns_list_create_with_mf(mf))) {
|
||||
*r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
break;
|
||||
}
|
||||
item->dtype = t_list;
|
||||
return _jsmn_get_list(mf, js, t, count, item->data.list, r);
|
||||
|
||||
default:
|
||||
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
_getdns_str2item_mf(struct mem_funcs *mf, const char *str, getdns_item *item)
|
||||
{
|
||||
jsmn_parser p;
|
||||
jsmntok_t *tok = NULL, *new_tok;
|
||||
size_t tokcount = 100;
|
||||
int r;
|
||||
getdns_return_t gr;
|
||||
|
||||
jsmn_init(&p);
|
||||
tok = GETDNS_XMALLOC(*mf, jsmntok_t, tokcount);
|
||||
do {
|
||||
r = jsmn_parse(&p, str, strlen(str), tok, tokcount);
|
||||
if (r == JSMN_ERROR_NOMEM) {
|
||||
tokcount *= 2;
|
||||
if (!(new_tok = GETDNS_XREALLOC(
|
||||
*mf, tok, jsmntok_t, tokcount))) {
|
||||
GETDNS_FREE(*mf, tok);
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
}
|
||||
tok = new_tok;
|
||||
}
|
||||
} while (r == JSMN_ERROR_NOMEM);
|
||||
if (r < 0)
|
||||
gr = GETDNS_RETURN_GENERIC_ERROR;
|
||||
else
|
||||
(void) _jsmn_get_item(mf, str, tok, p.toknext, item, &gr);
|
||||
GETDNS_FREE(*mf, tok);
|
||||
return gr;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_str2dict(const char *str, getdns_dict **dict)
|
||||
{
|
||||
getdns_item item;
|
||||
getdns_return_t r;
|
||||
|
||||
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
|
||||
return r;
|
||||
|
||||
else if (item.dtype != t_dict) {
|
||||
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
|
||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
}
|
||||
*dict = item.data.dict;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_str2list(const char *str, getdns_list **list)
|
||||
{
|
||||
getdns_item item;
|
||||
getdns_return_t r;
|
||||
|
||||
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
|
||||
return r;
|
||||
|
||||
else if (item.dtype != t_list) {
|
||||
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
|
||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
}
|
||||
*list = item.data.list;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_str2bindata(const char *str, getdns_bindata **bindata)
|
||||
{
|
||||
getdns_item item;
|
||||
getdns_return_t r;
|
||||
|
||||
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
|
||||
return r;
|
||||
|
||||
else if (item.dtype != t_bindata) {
|
||||
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
|
||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
}
|
||||
*bindata = item.data.bindata;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_str2int(const char *str, uint32_t *value)
|
||||
{
|
||||
getdns_item item;
|
||||
getdns_return_t r;
|
||||
|
||||
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
|
||||
return r;
|
||||
|
||||
else if (item.dtype != t_int) {
|
||||
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
|
||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||
}
|
||||
*value = item.data.n;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
||||
struct const_name_info { const char *name; uint32_t code; };
|
||||
static struct const_name_info consts_name_info[] = {
|
||||
{ "GETDNS_APPEND_NAME_ALWAYS", 550 },
|
||||
{ "GETDNS_APPEND_NAME_NEVER", 553 },
|
||||
{ "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", 552 },
|
||||
{ "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", 551 },
|
||||
{ "GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST", 554 },
|
||||
{ "GETDNS_AUTHENTICATION_NONE", 1300 },
|
||||
{ "GETDNS_AUTHENTICATION_REQUIRED", 1301 },
|
||||
{ "GETDNS_BAD_DNS_ALL_NUMERIC_LABEL", 1101 },
|
||||
{ "GETDNS_BAD_DNS_CNAME_IN_TARGET", 1100 },
|
||||
{ "GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE", 1102 },
|
||||
{ "GETDNS_CALLBACK_CANCEL", 701 },
|
||||
{ "GETDNS_CALLBACK_COMPLETE", 700 },
|
||||
{ "GETDNS_CALLBACK_ERROR", 703 },
|
||||
{ "GETDNS_CALLBACK_TIMEOUT", 702 },
|
||||
{ "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", 609 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS", 604 },
|
||||
{ "GETDNS_CONTEXT_CODE_DNS_TRANSPORT", 605 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", 619 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_DO_BIT", 613 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE", 611 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE", 610 },
|
||||
{ "GETDNS_CONTEXT_CODE_EDNS_VERSION", 612 },
|
||||
{ "GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS", 602 },
|
||||
{ "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", 617 },
|
||||
{ "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", 606 },
|
||||
{ "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", 615 },
|
||||
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
|
||||
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
|
||||
{ "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 },
|
||||
{ "GETDNS_CONTEXT_CODE_SUFFIX", 608 },
|
||||
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
|
||||
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
|
||||
{ "GETDNS_DNSSEC_BOGUS", 401 },
|
||||
{ "GETDNS_DNSSEC_INDETERMINATE", 402 },
|
||||
{ "GETDNS_DNSSEC_INSECURE", 403 },
|
||||
{ "GETDNS_DNSSEC_NOT_PERFORMED", 404 },
|
||||
{ "GETDNS_DNSSEC_SECURE", 400 },
|
||||
{ "GETDNS_EXTENSION_FALSE", 1001 },
|
||||
{ "GETDNS_EXTENSION_TRUE", 1000 },
|
||||
{ "GETDNS_NAMESPACE_DNS", 500 },
|
||||
{ "GETDNS_NAMESPACE_LOCALNAMES", 501 },
|
||||
{ "GETDNS_NAMESPACE_MDNS", 503 },
|
||||
{ "GETDNS_NAMESPACE_NETBIOS", 502 },
|
||||
{ "GETDNS_NAMESPACE_NIS", 504 },
|
||||
{ "GETDNS_NAMETYPE_DNS", 800 },
|
||||
{ "GETDNS_NAMETYPE_WINS", 801 },
|
||||
{ "GETDNS_OPCODE_IQUERY", 1 },
|
||||
{ "GETDNS_OPCODE_NOTIFY", 4 },
|
||||
{ "GETDNS_OPCODE_QUERY", 0 },
|
||||
{ "GETDNS_OPCODE_STATUS", 2 },
|
||||
{ "GETDNS_OPCODE_UPDATE", 5 },
|
||||
{ "GETDNS_RCODE_BADALG", 21 },
|
||||
{ "GETDNS_RCODE_BADKEY", 17 },
|
||||
{ "GETDNS_RCODE_BADMODE", 19 },
|
||||
{ "GETDNS_RCODE_BADNAME", 20 },
|
||||
{ "GETDNS_RCODE_BADSIG", 16 },
|
||||
{ "GETDNS_RCODE_BADTIME", 18 },
|
||||
{ "GETDNS_RCODE_BADTRUNC", 22 },
|
||||
{ "GETDNS_RCODE_BADVERS", 16 },
|
||||
{ "GETDNS_RCODE_FORMERR", 1 },
|
||||
{ "GETDNS_RCODE_NOERROR", 0 },
|
||||
{ "GETDNS_RCODE_NOTAUTH", 9 },
|
||||
{ "GETDNS_RCODE_NOTIMP", 4 },
|
||||
{ "GETDNS_RCODE_NOTZONE", 10 },
|
||||
{ "GETDNS_RCODE_NXDOMAIN", 3 },
|
||||
{ "GETDNS_RCODE_NXRRSET", 8 },
|
||||
{ "GETDNS_RCODE_REFUSED", 5 },
|
||||
{ "GETDNS_RCODE_SERVFAIL", 2 },
|
||||
{ "GETDNS_RCODE_YXDOMAIN", 6 },
|
||||
{ "GETDNS_RCODE_YXRRSET", 7 },
|
||||
{ "GETDNS_REDIRECTS_DO_NOT_FOLLOW", 531 },
|
||||
{ "GETDNS_REDIRECTS_FOLLOW", 530 },
|
||||
{ "GETDNS_RESOLUTION_RECURSING", 521 },
|
||||
{ "GETDNS_RESOLUTION_STUB", 520 },
|
||||
{ "GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS", 904 },
|
||||
{ "GETDNS_RESPSTATUS_ALL_TIMEOUT", 902 },
|
||||
{ "GETDNS_RESPSTATUS_GOOD", 900 },
|
||||
{ "GETDNS_RESPSTATUS_NO_NAME", 901 },
|
||||
{ "GETDNS_RESPSTATUS_NO_SECURE_ANSWERS", 903 },
|
||||
{ "GETDNS_RETURN_BAD_CONTEXT", 301 },
|
||||
{ "GETDNS_RETURN_BAD_DOMAIN_NAME", 300 },
|
||||
{ "GETDNS_RETURN_CONTEXT_UPDATE_FAIL", 302 },
|
||||
{ "GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED", 309 },
|
||||
{ "GETDNS_RETURN_EXTENSION_MISFORMAT", 308 },
|
||||
{ "GETDNS_RETURN_GENERIC_ERROR", 1 },
|
||||
{ "GETDNS_RETURN_GOOD", 0 },
|
||||
{ "GETDNS_RETURN_INVALID_PARAMETER", 311 },
|
||||
{ "GETDNS_RETURN_MEMORY_ERROR", 310 },
|
||||
{ "GETDNS_RETURN_NEED_MORE_SPACE", 399 },
|
||||
{ "GETDNS_RETURN_NOT_IMPLEMENTED", 312 },
|
||||
{ "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 },
|
||||
{ "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 },
|
||||
{ "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 },
|
||||
{ "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 },
|
||||
{ "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 },
|
||||
{ "GETDNS_RRCLASS_ANY", 255 },
|
||||
{ "GETDNS_RRCLASS_CH", 3 },
|
||||
{ "GETDNS_RRCLASS_HS", 4 },
|
||||
{ "GETDNS_RRCLASS_IN", 1 },
|
||||
{ "GETDNS_RRCLASS_NONE", 254 },
|
||||
{ "GETDNS_RRTYPE_A", 1 },
|
||||
{ "GETDNS_RRTYPE_AAAA", 28 },
|
||||
{ "GETDNS_RRTYPE_AFSDB", 18 },
|
||||
{ "GETDNS_RRTYPE_ANY", 255 },
|
||||
{ "GETDNS_RRTYPE_APL", 42 },
|
||||
{ "GETDNS_RRTYPE_ATMA", 34 },
|
||||
{ "GETDNS_RRTYPE_AXFR", 252 },
|
||||
{ "GETDNS_RRTYPE_CAA", 257 },
|
||||
{ "GETDNS_RRTYPE_CDNSKEY", 60 },
|
||||
{ "GETDNS_RRTYPE_CDS", 59 },
|
||||
{ "GETDNS_RRTYPE_CERT", 37 },
|
||||
{ "GETDNS_RRTYPE_CNAME", 5 },
|
||||
{ "GETDNS_RRTYPE_CSYNC", 62 },
|
||||
{ "GETDNS_RRTYPE_DHCID", 49 },
|
||||
{ "GETDNS_RRTYPE_DLV", 32769 },
|
||||
{ "GETDNS_RRTYPE_DNAME", 39 },
|
||||
{ "GETDNS_RRTYPE_DNSKEY", 48 },
|
||||
{ "GETDNS_RRTYPE_DS", 43 },
|
||||
{ "GETDNS_RRTYPE_EID", 31 },
|
||||
{ "GETDNS_RRTYPE_GID", 102 },
|
||||
{ "GETDNS_RRTYPE_GPOS", 27 },
|
||||
{ "GETDNS_RRTYPE_HINFO", 13 },
|
||||
{ "GETDNS_RRTYPE_HIP", 55 },
|
||||
{ "GETDNS_RRTYPE_IPSECKEY", 45 },
|
||||
{ "GETDNS_RRTYPE_ISDN", 20 },
|
||||
{ "GETDNS_RRTYPE_IXFR", 251 },
|
||||
{ "GETDNS_RRTYPE_KEY", 25 },
|
||||
{ "GETDNS_RRTYPE_KX", 36 },
|
||||
{ "GETDNS_RRTYPE_LOC", 29 },
|
||||
{ "GETDNS_RRTYPE_LP", 107 },
|
||||
{ "GETDNS_RRTYPE_MAILA", 254 },
|
||||
{ "GETDNS_RRTYPE_MAILB", 253 },
|
||||
{ "GETDNS_RRTYPE_MB", 7 },
|
||||
{ "GETDNS_RRTYPE_MD", 3 },
|
||||
{ "GETDNS_RRTYPE_MF", 4 },
|
||||
{ "GETDNS_RRTYPE_MG", 8 },
|
||||
{ "GETDNS_RRTYPE_MINFO", 14 },
|
||||
{ "GETDNS_RRTYPE_MR", 9 },
|
||||
{ "GETDNS_RRTYPE_MX", 15 },
|
||||
{ "GETDNS_RRTYPE_NAPTR", 35 },
|
||||
{ "GETDNS_RRTYPE_NID", 104 },
|
||||
{ "GETDNS_RRTYPE_NIMLOC", 32 },
|
||||
{ "GETDNS_RRTYPE_NINFO", 56 },
|
||||
{ "GETDNS_RRTYPE_NS", 2 },
|
||||
{ "GETDNS_RRTYPE_NSAP", 22 },
|
||||
{ "GETDNS_RRTYPE_NSEC", 47 },
|
||||
{ "GETDNS_RRTYPE_NULL", 10 },
|
||||
{ "GETDNS_RRTYPE_NXT", 30 },
|
||||
{ "GETDNS_RRTYPE_OPENPGPKEY", 61 },
|
||||
{ "GETDNS_RRTYPE_OPT", 41 },
|
||||
{ "GETDNS_RRTYPE_PTR", 12 },
|
||||
{ "GETDNS_RRTYPE_PX", 26 },
|
||||
{ "GETDNS_RRTYPE_RKEY", 57 },
|
||||
{ "GETDNS_RRTYPE_RP", 17 },
|
||||
{ "GETDNS_RRTYPE_RRSIG", 46 },
|
||||
{ "GETDNS_RRTYPE_RT", 21 },
|
||||
{ "GETDNS_RRTYPE_SIG", 24 },
|
||||
{ "GETDNS_RRTYPE_SINK", 40 },
|
||||
{ "GETDNS_RRTYPE_SOA", 6 },
|
||||
{ "GETDNS_RRTYPE_SPF", 99 },
|
||||
{ "GETDNS_RRTYPE_SRV", 33 },
|
||||
{ "GETDNS_RRTYPE_SSHFP", 44 },
|
||||
{ "GETDNS_RRTYPE_TA", 32768 },
|
||||
{ "GETDNS_RRTYPE_TALINK", 58 },
|
||||
{ "GETDNS_RRTYPE_TKEY", 249 },
|
||||
{ "GETDNS_RRTYPE_TLSA", 52 },
|
||||
{ "GETDNS_RRTYPE_TSIG", 250 },
|
||||
{ "GETDNS_RRTYPE_TXT", 16 },
|
||||
{ "GETDNS_RRTYPE_UID", 101 },
|
||||
{ "GETDNS_RRTYPE_UINFO", 100 },
|
||||
{ "GETDNS_RRTYPE_UNSPEC", 103 },
|
||||
{ "GETDNS_RRTYPE_URI", 256 },
|
||||
{ "GETDNS_RRTYPE_WKS", 11 },
|
||||
{ "GETDNS_TRANSPORT_TCP", 1201 },
|
||||
{ "GETDNS_TRANSPORT_TCP_ONLY", 542 },
|
||||
{ "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 },
|
||||
{ "GETDNS_TRANSPORT_TLS", 1202 },
|
||||
{ "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", 545 },
|
||||
{ "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", 544 },
|
||||
{ "GETDNS_TRANSPORT_UDP", 1200 },
|
||||
{ "GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP", 540 },
|
||||
{ "GETDNS_TRANSPORT_UDP_ONLY", 541 },
|
||||
};
|
||||
static int const_name_info_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcmp( ((struct const_name_info *) a)->name
|
||||
, ((struct const_name_info *) b)->name );
|
||||
}
|
||||
static int
|
||||
_getdns_get_const_name_info(const char *name, uint32_t *code)
|
||||
{
|
||||
struct const_name_info key = { name, 0 };
|
||||
struct const_name_info *i = bsearch(&key, consts_name_info,
|
||||
sizeof(consts_name_info) / sizeof(struct const_name_info),
|
||||
sizeof(struct const_name_info), const_name_info_cmp);
|
||||
if (!i)
|
||||
return 0;
|
||||
if (code)
|
||||
*code = i->code;
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GETDNS_STR2DICT_H_
|
||||
#define GETDNS_STR2DICT_H_
|
||||
#include "getdns/getdns.h"
|
||||
|
||||
getdns_dict *_getdns_ipaddr_dict(const char *ipstr);
|
||||
|
||||
getdns_return_t getdns_str2dict(const char *str, getdns_dict **dict);
|
||||
getdns_return_t getdns_str2list(const char *str, getdns_list **list);
|
||||
getdns_return_t getdns_str2bindata(const char *str, getdns_bindata **bindata);
|
||||
getdns_return_t getdns_str2int(const char *str, uint32_t *value);
|
||||
|
||||
#endif
|
|
@ -7,6 +7,10 @@ export BUILDDIR=`pwd`
|
|||
export BUILDROOT=`(cd "${BUILDDIR}/../../.."; pwd)`
|
||||
export LIBTOOL="${BUILDROOT}/libtool"
|
||||
|
||||
if [ ! -f "${SRCROOT}/src/test/jsmn/jsmn.c" ]
|
||||
then
|
||||
(cd "${SRCROOT}"; git submodule update --init)
|
||||
fi
|
||||
if [ ! -f "${SRCROOT}/libtool" ]
|
||||
then
|
||||
(cd "${SRCROOT}"; libtoolize -fic)
|
||||
|
|
Loading…
Reference in New Issue