From b99b7511ecad1148dbe6b5907b282b28077cbe06 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 4 Jul 2016 12:58:23 +0200 Subject: [PATCH 01/13] Generalize str2ipaddr_dict conversion --- src/test/getdns_query.c | 84 ++++++++++++++++++++++++++++---------- src/test/getdns_str2dict.c | 57 ++++++++++++++++++-------- src/test/getdns_str2dict.h | 2 - src/test/jsmn | 2 +- 4 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index f38306a8..a2a463c0 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -499,8 +499,23 @@ getdns_return_t parse_args(int argc, char **argv) continue; } else if (arg[0] == '@') { - getdns_dict *upstream = _getdns_ipaddr_dict(arg + 1); - if (upstream) { + getdns_dict *upstream; + getdns_bindata *address; + + if ((r = getdns_str2dict(arg + 1, &upstream))) + fprintf(stderr, "Could not convert \"%s\" to " + "an IP dict: %s\n", arg + 1, + getdns_get_errorstr_by_id(r)); + + else if ((r = getdns_dict_get_bindata( + upstream, "address_data", &address))) { + + fprintf(stderr, "\"%s\" did not translate to " + "an IP dict: %s\n", arg + 1, + getdns_get_errorstr_by_id(r)); + + getdns_dict_destroy(upstream); + } else { if (!upstream_list && !(upstream_list = getdns_list_create_with_context(context))){ @@ -521,6 +536,9 @@ getdns_return_t parse_args(int argc, char **argv) continue; } for (c = arg+1; *c; c++) { + getdns_dict *downstream; + getdns_bindata *address; + switch (*c) { case 'a': async = 1; @@ -896,23 +914,33 @@ getdns_return_t parse_args(int argc, char **argv) DEBUG_SERVER("Clear listen list\n"); break; } - getdns_dict *downstream = - _getdns_ipaddr_dict(argv[i]); - if (!downstream) { - fprintf(stderr, "could not parse " - "listen address: %s", argv[i]); + + if ((r = getdns_str2dict(argv[i], &downstream))) + fprintf(stderr, "Could not convert \"%s\" to " + "an IP dict: %s\n", argv[i], + getdns_get_errorstr_by_id(r)); + + else if ((r = getdns_dict_get_bindata( + downstream, "address_data", &address))) { + + fprintf(stderr, "\"%s\" did not translate to " + "an IP dict: %s\n", argv[i], + getdns_get_errorstr_by_id(r)); + + getdns_dict_destroy(downstream); + } else { + if (!listen_list && + !(listen_list = + getdns_list_create_with_context(context))){ + fprintf(stderr, "Could not create " + "downstream list\n"); + return GETDNS_RETURN_MEMORY_ERROR; + } + getdns_list_set_dict(listen_list, + listen_count++, downstream); + getdns_dict_destroy(downstream); + touched_listen_list = 1; } - if (!listen_list && - !(listen_list = - getdns_list_create_with_context(context))){ - fprintf(stderr, "Could not create " - "downstram list\n"); - return GETDNS_RETURN_MEMORY_ERROR; - } - getdns_list_set_dict(listen_list, - listen_count++, downstream); - getdns_dict_destroy(downstream); - touched_listen_list = 1; break; default: fprintf(stderr, "Unknown option " @@ -976,14 +1004,26 @@ getdns_return_t do_the_call(void) { getdns_return_t r; getdns_dict *address = NULL; + getdns_bindata *address_bindata; getdns_dict *response = NULL; char *response_str; uint32_t status; - if (calltype == HOSTNAME && - !(address = _getdns_ipaddr_dict(name))) { - fprintf(stderr, "Could not convert \"%s\" " - "to an IP address", name); + if (calltype != HOSTNAME) + ; /* pass */ + + else if ((r = getdns_str2dict(name, &address))) { + + fprintf(stderr, "Could not convert \"%s\" to an IP dict: %s\n" + , name, getdns_get_errorstr_by_id(r)); + return GETDNS_RETURN_GOOD; + + } else if ((r = getdns_dict_get_bindata( + address, "address_data", &address_bindata))) { + + fprintf(stderr, "Could not convert \"%s\" to an IP dict: %s\n" + , name, getdns_get_errorstr_by_id(r)); + getdns_dict_destroy(address); return GETDNS_RETURN_GOOD; } if (async) { diff --git a/src/test/getdns_str2dict.c b/src/test/getdns_str2dict.c index 7cfc875c..ae5fb1d9 100644 --- a/src/test/getdns_str2dict.c +++ b/src/test/getdns_str2dict.c @@ -233,21 +233,6 @@ static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t, 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) { @@ -658,8 +643,48 @@ getdns_str2dict(const char *str, getdns_dict **dict) return r; else if (item.dtype != t_dict) { + uint8_t buf[16]; + getdns_dict *dict_r; + + if (item.dtype != t_bindata) + r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + else if (item.data.bindata->size == 4 && + inet_pton(AF_INET, str, buf) == 1) { + + if (!(dict_r = getdns_dict_create())) + r = GETDNS_RETURN_MEMORY_ERROR; + + else if ((r = getdns_dict_util_set_string( + dict_r, "address_type", "IPv4"))) + getdns_dict_destroy(dict_r); + + else if ((r = getdns_dict_set_bindata( + dict_r, "address_data", item.data.bindata))) + getdns_dict_destroy(dict_r); + else + *dict = dict_r; + + } else if (item.data.bindata->size == 16 && + inet_pton(AF_INET6, str, buf) == 1) { + + if (!(dict_r = getdns_dict_create())) + r = GETDNS_RETURN_MEMORY_ERROR; + + else if ((r = getdns_dict_util_set_string( + dict_r, "address_type", "IPv6"))) + getdns_dict_destroy(dict_r); + + else if ((r = getdns_dict_set_bindata( + dict_r, "address_data", item.data.bindata))) + getdns_dict_destroy(dict_r); + else + *dict = dict_r; + } else + r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; + _getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item); - return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + return r; } *dict = item.data.dict; return GETDNS_RETURN_GOOD; diff --git a/src/test/getdns_str2dict.h b/src/test/getdns_str2dict.h index f8d7e926..71cb26c8 100644 --- a/src/test/getdns_str2dict.h +++ b/src/test/getdns_str2dict.h @@ -29,8 +29,6 @@ #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); diff --git a/src/test/jsmn b/src/test/jsmn index daa17063..49024a6e 160000 --- a/src/test/jsmn +++ b/src/test/jsmn @@ -1 +1 @@ -Subproject commit daa17063c67f0dfe873af25ab6b664641c8cf90c +Subproject commit 49024a6e11739c866bce0e9f3617278b98906ad0 From 91f3494a8ad0d66819b9ae4d5f59cfc77fd66c97 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 4 Jul 2016 14:49:45 +0200 Subject: [PATCH 02/13] Bumb version to 1.0.0b2 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index cddf86ac..da1dccd3 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/pkg.m4) AC_INIT([getdns], [1.0.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) -AC_SUBST(RELEASE_CANDIDATE, [b1]) +AC_SUBST(RELEASE_CANDIDATE, [b2]) # Set current date from system if not set AC_ARG_WITH([current-date], @@ -47,7 +47,7 @@ AC_ARG_WITH([current-date], [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) -AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00100100]) +AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00100200]) AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" From 92fd79ff5501ac66c08b94bb4ef947178285cc5d Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 4 Jul 2016 14:50:02 +0200 Subject: [PATCH 03/13] Update Changelog --- ChangeLog | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b3a1dbc1..8459cd74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,47 @@ -* 2016-??-??: Version 1.0.0 +* 2016-??-??: Version 1.0.0b2 + * Collect coverage information from the unit tests + Thanks Shane Kerr + * pkg-config for the getdns_ext_event library + Thanks Tom Pusateri + * Bugfix: Multiple requests on the same upstream with a transport + that keeps connections open in synchronous stub mode. + * Canonicalized DNSSEC chain with dnssec_return_validation_chain + (when validated) + * A dnssec_return_full_validation_chain extension which includes + then validated resource records. + * Bugfix: Callbacks fired while scheduling (answer from cache) + with the unbound plugable event API + * header extension to set opcode and flags in stub mode + * Unit tests that cover more code + * Static checking with the clang analyzer + * getdns_pretty_print_dict prints dname's as primitives + * Accept just bindata's instead of address dicts. + Allow misshing "address_type" in address dicts. + * TLS session resumption + * -C option to getdns_query to configure context + from a json like formated file. The output of -i (print API + information) can be used as config file directly. + Settings may also be given in this format as arguments of + the getdns_query command directly. + * DNS server mode for getdns_query. Enable by providing addresses + to listen on, either by giving "-z " options or by + providing "listen_addresses" in the config file or settings. + * Bugfixes from deckard testing: CNAME loop protection. + * "srv_addresses" in response dict with getdns_service() + * use libbsd when available + Thanks Guillem Jover + * Bugfix: DNSSEC wildcard validation issue + * Bugfix: TLS timeouts not re-using a connection + * A getdns_context_get_eventloop(), to get the current + (pluggable) eventloop from context + * getdns_query now uses the default event loop (instead of custom) + * Return call_reporting info in case of timeout + Thanks Robert Groenenberg + * Bugfix: Build fails with autoconf 2.63, works with 2.68. + Thanks Robert Groenenberg + * Doxygen output for getdns.h and getdns_extra.h only + +* 2016-03-31: Version 1.0.0b1 * openssl 1.1.0 support * GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST default suffix handling * getdns_context_set_follow_redirects() From cc104320e8dad93d4186aa50c54064c96cd2447d Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 4 Jul 2016 15:54:05 +0200 Subject: [PATCH 04/13] Get RR types and classes from constant names --- src/test/getdns_query.c | 536 ++++------------------------------------ 1 file changed, 53 insertions(+), 483 deletions(-) diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index a2a463c0..09184e6d 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #ifndef USE_WINSOCK @@ -70,7 +71,55 @@ static int timeout, edns0_size, padding_blocksize; static int async = 0, interactive = 0; static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL; -int get_rrtype(const char *t); +static int get_rrtype(const char *t) +{ + char buf[1024] = "GETDNS_RRTYPE_"; + uint32_t rrtype; + long int l; + size_t i; + char *endptr; + + if (strlen(t) > sizeof(buf) - 15) + return -1; + for (i = 14; *t && i < sizeof(buf) - 1; i++, t++) + buf[i] = toupper(*t); + buf[i] = '\0'; + + if (!getdns_str2int(buf, &rrtype)) + return (int)rrtype; + + if (strncasecmp(buf + 14, "TYPE", 4) == 0) { + l = strtol(buf + 18, &endptr, 10); + if (!*endptr && l >= 0 && l < 65536) + return l; + } + return -1; +} + +static int get_rrclass(const char *t) +{ + char buf[1024] = "GETDNS_RRCLASS_"; + uint32_t rrclass; + long int l; + size_t i; + char *endptr; + + if (strlen(t) > sizeof(buf) - 16) + return -1; + for (i = 15; *t && i < sizeof(buf) - 1; i++, t++) + buf[i] = toupper(*t); + buf[i] = '\0'; + + if (!getdns_str2int(buf, &rrclass)) + return (int)rrclass; + + if (strncasecmp(buf + 15, "CLASS", 5) == 0) { + l = strtol(buf + 20, &endptr, 10); + if (!*endptr && l >= 0 && l < 65536) + return l; + } + return -1; +} static getdns_return_t fill_transport_list(getdns_context *context, char *transport_list_str, @@ -457,34 +506,13 @@ getdns_return_t parse_args(int argc, char **argv) break; } } else if (strncmp(arg+1, "specify_class=", 14) == 0) { - if (strncasecmp(arg+15, "IN", 3) == 0) + if ((klass = get_rrclass(arg+15)) >= 0) r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_IN); - else if (strncasecmp(arg+15, "CH", 3) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_CH); - else if (strncasecmp(arg+15, "HS", 3) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_HS); - else if (strncasecmp(arg+15, "NONE", 5) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_NONE); - else if (strncasecmp(arg+15, "ANY", 4) == 0) - r = getdns_dict_set_int(extensions, - "specify_class", GETDNS_RRCLASS_ANY); - else if (strncasecmp(arg+15, "CLASS", 5) == 0) { - klass = strtol(arg + 20, &endptr, 10); - if (*endptr || klass > 255) - fprintf(stderr, - "Unknown class: %s\n", - arg+15); - else - r = getdns_dict_set_int(extensions, "specify_class", klass); - - } else + else fprintf(stderr, "Unknown class: %s\n", arg+15); + } else if (arg[1] == '0') { /* Unset all existing extensions*/ getdns_dict_destroy(extensions); @@ -1503,462 +1531,4 @@ done_destroy_context: return r; } -int get_rrtype(const char *t) { - char *endptr; - int r; - - switch (t[0]) { - case 'A': - case 'a': switch (t[1]) { - case '\0': return GETDNS_RRTYPE_A; - case '6': if (t[2] == '\0') return GETDNS_RRTYPE_A6; - return -1; - case 'A': - case 'a': /* before "AA", final "AA" (GETDNS_RRTYPE_AAAA) */ - if ((t[2]|0x20) == 'a' && (t[3]|0x20) == 'a' && t[4] == '\0') - return GETDNS_RRTYPE_AAAA; - return -1; - case 'F': - case 'f': /* before "AF", final "SDB" (GETDNS_RRTYPE_AFSDB) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'd' && (t[4]|0x20) == 'b' && t[5] == '\0') - return GETDNS_RRTYPE_AFSDB; - return -1; - case 'P': - case 'p': /* before "AP", final "L" (GETDNS_RRTYPE_APL) */ - if ((t[2]|0x20) == 'l' && t[3] == '\0') - return GETDNS_RRTYPE_APL; - return -1; - case 'T': - case 't': /* before "AT", final "MA" (GETDNS_RRTYPE_ATMA) */ - if ((t[2]|0x20) == 'm' && (t[3]|0x20) == 'a' && t[4] == '\0') - return GETDNS_RRTYPE_ATMA; - return -1; - case 'X': - case 'x': /* before "AX", final "FR" (GETDNS_RRTYPE_AXFR) */ - if ((t[2]|0x20) == 'f' && (t[3]|0x20) == 'r' && t[4] == '\0') - return GETDNS_RRTYPE_AXFR; - return -1; - default : return -1; - }; - case 'C': - case 'c': switch (t[1]) { - case 'A': - case 'a': /* before "CA", final "A" (GETDNS_RRTYPE_CAA) */ - if ((t[2]|0x20) == 'a' && t[3] == '\0') - return GETDNS_RRTYPE_CAA; - return -1; - case 'D': - case 'd': switch (t[2]) { - case 'N': - case 'n': /* before "CDN", final "SKEY" (GETDNS_RRTYPE_CDNSKEY) */ - if ((t[3]|0x20) == 's' && (t[4]|0x20) == 'k' && (t[5]|0x20) == 'e' && (t[6]|0x20) == 'y' && t[7] == '\0') - return GETDNS_RRTYPE_CDNSKEY; - return -1; - case 'S': - case 's': if (t[3] == '\0') return GETDNS_RRTYPE_CDS; - return -1; - default : return -1; - }; - case 'E': - case 'e': /* before "CE", final "RT" (GETDNS_RRTYPE_CERT) */ - if ((t[2]|0x20) == 'r' && (t[3]|0x20) == 't' && t[4] == '\0') - return GETDNS_RRTYPE_CERT; - return -1; - case 'N': - case 'n': /* before "CN", final "AME" (GETDNS_RRTYPE_CNAME) */ - if ((t[2]|0x20) == 'a' && (t[3]|0x20) == 'm' && (t[4]|0x20) == 'e' && t[5] == '\0') - return GETDNS_RRTYPE_CNAME; - return -1; - case 'S': - case 's': /* before "CS", final "YNC" (GETDNS_RRTYPE_CSYNC) */ - if ((t[2]|0x20) == 'y' && (t[3]|0x20) == 'n' && (t[4]|0x20) == 'c' && t[5] == '\0') - return GETDNS_RRTYPE_CSYNC; - return -1; - - default : return -1; - }; - case 'D': - case 'd': switch (t[1]) { - case 'H': - case 'h': /* before "DH", final "CID" (GETDNS_RRTYPE_DHCID) */ - if ((t[2]|0x20) == 'c' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'd' && t[5] == '\0') - return GETDNS_RRTYPE_DHCID; - return -1; - case 'L': - case 'l': /* before "DL", final "V" (GETDNS_RRTYPE_DLV) */ - if ((t[2]|0x20) == 'v' && t[3] == '\0') - return GETDNS_RRTYPE_DLV; - return -1; - case 'N': - case 'n': switch (t[2]) { - case 'A': - case 'a': /* before "DNA", final "ME" (GETDNS_RRTYPE_DNAME) */ - if ((t[3]|0x20) == 'm' && (t[4]|0x20) == 'e' && t[5] == '\0') - return GETDNS_RRTYPE_DNAME; - return -1; - case 'S': - case 's': /* before "DNS", final "KEY" (GETDNS_RRTYPE_DNSKEY) */ - if ((t[3]|0x20) == 'k' && (t[4]|0x20) == 'e' && (t[5]|0x20) == 'y' && t[6] == '\0') - return GETDNS_RRTYPE_DNSKEY; - return -1; - default : return -1; - }; - case 'S': - case 's': if (t[2] == '\0') return GETDNS_RRTYPE_DS; - return -1; - default : return -1; - }; - case 'E': - case 'e': switch (t[1]) { - case 'I': - case 'i': /* before "EI", final "D" (GETDNS_RRTYPE_EID) */ - if ((t[2]|0x20) == 'd' && t[3] == '\0') - return GETDNS_RRTYPE_EID; - return -1; - case 'U': - case 'u': /* before "EU", next "I" */ - if ((t[2]|0x20) != 'i') - return -1; - switch (t[3]) { - case '4': /* before "EUI4", final "8" (GETDNS_RRTYPE_EUI48) */ - if (t[4] == '8' && t[5] == '\0') - return GETDNS_RRTYPE_EUI48; - return -1; - case '6': /* before "EUI6", final "4" (GETDNS_RRTYPE_EUI64) */ - if (t[4] == '4' && t[5] == '\0') - return GETDNS_RRTYPE_EUI64; - return -1; - default : return -1; - }; - default : return -1; - }; - case 'G': - case 'g': switch (t[1]) { - case 'I': - case 'i': /* before "GI", final "D" (GETDNS_RRTYPE_GID) */ - if ((t[2]|0x20) == 'd' && t[3] == '\0') - return GETDNS_RRTYPE_GID; - return -1; - case 'P': - case 'p': /* before "GP", final "OS" (GETDNS_RRTYPE_GPOS) */ - if ((t[2]|0x20) == 'o' && (t[3]|0x20) == 's' && t[4] == '\0') - return GETDNS_RRTYPE_GPOS; - return -1; - default : return -1; - }; - case 'H': - case 'h': /* before "H", next "I" */ - if ((t[1]|0x20) != 'i') - return -1; - switch (t[2]) { - case 'N': - case 'n': /* before "HIN", final "FO" (GETDNS_RRTYPE_HINFO) */ - if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_HINFO; - return -1; - case 'P': - case 'p': if (t[3] == '\0') return GETDNS_RRTYPE_HIP; - return -1; - default : return -1; - }; - case 'I': - case 'i': switch (t[1]) { - case 'P': - case 'p': /* before "IP", final "SECKEY" (GETDNS_RRTYPE_IPSECKEY) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'e' && (t[4]|0x20) == 'c' && (t[5]|0x20) == 'k' && (t[6]|0x20) == 'e' && (t[7]|0x20) == 'y' && t[8] == '\0') - return GETDNS_RRTYPE_IPSECKEY; - return -1; - case 'S': - case 's': /* before "IS", final "DN" (GETDNS_RRTYPE_ISDN) */ - if ((t[2]|0x20) == 'd' && (t[3]|0x20) == 'n' && t[4] == '\0') - return GETDNS_RRTYPE_ISDN; - return -1; - case 'X': - case 'x': /* before "IX", final "FR" (GETDNS_RRTYPE_IXFR) */ - if ((t[2]|0x20) == 'f' && (t[3]|0x20) == 'r' && t[4] == '\0') - return GETDNS_RRTYPE_IXFR; - return -1; - default : return -1; - }; - case 'K': - case 'k': switch (t[1]) { - case 'E': - case 'e': /* before "KE", final "Y" (GETDNS_RRTYPE_KEY) */ - if ((t[2]|0x20) == 'y' && t[3] == '\0') - return GETDNS_RRTYPE_KEY; - return -1; - case 'X': - case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_KX; - return -1; - default : return -1; - }; - case 'L': - case 'l': switch (t[1]) { - case '3': /* before "L3", final "2" (GETDNS_RRTYPE_L32) */ - if (t[2] == '2' && t[3] == '\0') - return GETDNS_RRTYPE_L32; - return -1; - case '6': /* before "L6", final "4" (GETDNS_RRTYPE_L64) */ - if (t[2] == '4' && t[3] == '\0') - return GETDNS_RRTYPE_L64; - return -1; - case 'O': - case 'o': /* before "LO", final "C" (GETDNS_RRTYPE_LOC) */ - if ((t[2]|0x20) == 'c' && t[3] == '\0') - return GETDNS_RRTYPE_LOC; - return -1; - case 'P': - case 'p': if (t[2] == '\0') return GETDNS_RRTYPE_LP; - return -1; - default : return -1; - }; - case 'M': - case 'm': switch (t[1]) { - case 'A': - case 'a': /* before "MA", next "IL" */ - if ((t[2]|0x20) != 'i' && (t[3]|0x20) != 'l') - return -1; - switch (t[4]) { - case 'A': - case 'a': if (t[5] == '\0') return GETDNS_RRTYPE_MAILA; - return -1; - case 'B': - case 'b': if (t[5] == '\0') return GETDNS_RRTYPE_MAILB; - return -1; - default : return -1; - }; - case 'B': - case 'b': if (t[2] == '\0') return GETDNS_RRTYPE_MB; - return -1; - case 'D': - case 'd': if (t[2] == '\0') return GETDNS_RRTYPE_MD; - return -1; - case 'F': - case 'f': if (t[2] == '\0') return GETDNS_RRTYPE_MF; - return -1; - case 'G': - case 'g': if (t[2] == '\0') return GETDNS_RRTYPE_MG; - return -1; - case 'I': - case 'i': /* before "MI", final "NFO" (GETDNS_RRTYPE_MINFO) */ - if ((t[2]|0x20) == 'n' && (t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_MINFO; - return -1; - case 'R': - case 'r': if (t[2] == '\0') return GETDNS_RRTYPE_MR; - return -1; - case 'X': - case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_MX; - return -1; - default : return -1; - }; - case 'N': - case 'n': switch (t[1]) { - case 'A': - case 'a': /* before "NA", final "PTR" (GETDNS_RRTYPE_NAPTR) */ - if ((t[2]|0x20) == 'p' && (t[3]|0x20) == 't' && (t[4]|0x20) == 'r' && t[5] == '\0') - return GETDNS_RRTYPE_NAPTR; - return -1; - case 'I': - case 'i': switch (t[2]) { - case 'D': - case 'd': if (t[3] == '\0') return GETDNS_RRTYPE_NID; - return -1; - case 'M': - case 'm': /* before "NIM", final "LOC" (GETDNS_RRTYPE_NIMLOC) */ - if ((t[3]|0x20) == 'l' && (t[4]|0x20) == 'o' && (t[5]|0x20) == 'c' && t[6] == '\0') - return GETDNS_RRTYPE_NIMLOC; - return -1; - case 'N': - case 'n': /* before "NIN", final "FO" (GETDNS_RRTYPE_NINFO) */ - if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_NINFO; - return -1; - default : return -1; - }; - case 'S': - case 's': switch (t[2]) { - case '\0': return GETDNS_RRTYPE_NS; - case 'A': - case 'a': /* before "NSA", final "P" (GETDNS_RRTYPE_NSAP) */ - if ((t[3]|0x20) == 'p' && t[4] == '\0') - return GETDNS_RRTYPE_NSAP; - return -1; - case 'E': - case 'e': /* before "NSE", final "C3PARAM" (GETDNS_RRTYPE_NSEC3PARAM) */ - if ((t[3]|0x20) == 'c' && t[4] == '3' && (t[5]|0x20) == 'p' && (t[6]|0x20) == 'a' && (t[7]|0x20) == 'r' && (t[8]|0x20) == 'a' && (t[9]|0x20) == 'm' && t[10] == '\0') - return GETDNS_RRTYPE_NSEC3PARAM; - return -1; - default : return -1; - }; - case 'U': - case 'u': /* before "NU", final "LL" (GETDNS_RRTYPE_NULL) */ - if ((t[2]|0x20) == 'l' && (t[3]|0x20) == 'l' && t[4] == '\0') - return GETDNS_RRTYPE_NULL; - return -1; - case 'X': - case 'x': /* before "NX", final "T" (GETDNS_RRTYPE_NXT) */ - if ((t[2]|0x20) == 't' && t[3] == '\0') - return GETDNS_RRTYPE_NXT; - return -1; - default : return -1; - }; - case 'O': - case 'o': /* before "O", next "P" */ - if ((t[1]|0x20) != 'p') - return -1; - switch (t[2]) { - case 'E': - case 'e': /* before "OPE", final "NPGPKEY" (GETDNS_RRTYPE_OPENPGPKEY) */ - if ((t[3]|0x20) == 'n' && (t[4]|0x20) == 'p' && (t[5]|0x20) == 'g' && (t[6]|0x20) == 'p' && (t[7]|0x20) == 'k' && (t[8]|0x20) == 'e' && (t[9]|0x20) == 'y' && t[10] == '\0') - return GETDNS_RRTYPE_OPENPGPKEY; - return -1; - case 'T': - case 't': if (t[3] == '\0') return GETDNS_RRTYPE_OPT; - return -1; - default : return -1; - }; - case 'P': - case 'p': switch (t[1]) { - case 'T': - case 't': /* before "PT", final "R" (GETDNS_RRTYPE_PTR) */ - if ((t[2]|0x20) == 'r' && t[3] == '\0') - return GETDNS_RRTYPE_PTR; - return -1; - case 'X': - case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_PX; - return -1; - default : return -1; - }; - case 'R': - case 'r': switch (t[1]) { - case 'K': - case 'k': /* before "RK", final "EY" (GETDNS_RRTYPE_RKEY) */ - if ((t[2]|0x20) == 'e' && (t[3]|0x20) == 'y' && t[4] == '\0') - return GETDNS_RRTYPE_RKEY; - return -1; - case 'P': - case 'p': if (t[2] == '\0') return GETDNS_RRTYPE_RP; - return -1; - case 'R': - case 'r': /* before "RR", final "SIG" (GETDNS_RRTYPE_RRSIG) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'g' && t[5] == '\0') - return GETDNS_RRTYPE_RRSIG; - return -1; - case 'T': - case 't': if (t[2] == '\0') return GETDNS_RRTYPE_RT; - return -1; - default : return -1; - }; - case 'S': - case 's': switch (t[1]) { - case 'I': - case 'i': switch (t[2]) { - case 'G': - case 'g': if (t[3] == '\0') return GETDNS_RRTYPE_SIG; - return -1; - case 'N': - case 'n': /* before "SIN", final "K" (GETDNS_RRTYPE_SINK) */ - if ((t[3]|0x20) == 'k' && t[4] == '\0') - return GETDNS_RRTYPE_SINK; - return -1; - default : return -1; - }; - case 'O': - case 'o': /* before "SO", final "A" (GETDNS_RRTYPE_SOA) */ - if ((t[2]|0x20) == 'a' && t[3] == '\0') - return GETDNS_RRTYPE_SOA; - return -1; - case 'P': - case 'p': /* before "SP", final "F" (GETDNS_RRTYPE_SPF) */ - if ((t[2]|0x20) == 'f' && t[3] == '\0') - return GETDNS_RRTYPE_SPF; - return -1; - case 'R': - case 'r': /* before "SR", final "V" (GETDNS_RRTYPE_SRV) */ - if ((t[2]|0x20) == 'v' && t[3] == '\0') - return GETDNS_RRTYPE_SRV; - return -1; - case 'S': - case 's': /* before "SS", final "HFP" (GETDNS_RRTYPE_SSHFP) */ - if ((t[2]|0x20) == 'h' && (t[3]|0x20) == 'f' && (t[4]|0x20) == 'p' && t[5] == '\0') - return GETDNS_RRTYPE_SSHFP; - return -1; - default : return -1; - }; - case 'T': - case 't': switch (t[1]) { - case 'A': - case 'a': /* before "TA", final "LINK" (GETDNS_RRTYPE_TALINK) */ - if ((t[2]|0x20) == 'l' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'n' && (t[5]|0x20) == 'k' && t[6] == '\0') - return GETDNS_RRTYPE_TALINK; - return -1; - case 'K': - case 'k': /* before "TK", final "EY" (GETDNS_RRTYPE_TKEY) */ - if ((t[2]|0x20) == 'e' && (t[3]|0x20) == 'y' && t[4] == '\0') - return GETDNS_RRTYPE_TKEY; - return -1; - case 'L': - case 'l': /* before "TL", final "SA" (GETDNS_RRTYPE_TLSA) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'a' && t[4] == '\0') - return GETDNS_RRTYPE_TLSA; - return -1; - case 'S': - case 's': /* before "TS", final "IG" (GETDNS_RRTYPE_TSIG) */ - if ((t[2]|0x20) == 'i' && (t[3]|0x20) == 'g' && t[4] == '\0') - return GETDNS_RRTYPE_TSIG; - return -1; - case 'X': - case 'x': /* before "TX", final "T" (GETDNS_RRTYPE_TXT) */ - if ((t[2]|0x20) == 't' && t[3] == '\0') - return GETDNS_RRTYPE_TXT; - return -1; - case 'Y': - case 'y': /* before "TY", then "PE" followed by a number */ - if ((t[2]|0x20) == 'p' && (t[3]|0x20) == 'e' && t[4] != '\0') { - r = (int) strtol(t + 4, &endptr, 10); - if (*endptr == '\0') return r; - } - return -1; - default : return -1; - }; - case 'U': - case 'u': switch (t[1]) { - case 'I': - case 'i': switch (t[2]) { - case 'D': - case 'd': if (t[3] == '\0') return GETDNS_RRTYPE_UID; - return -1; - case 'N': - case 'n': /* before "UIN", final "FO" (GETDNS_RRTYPE_UINFO) */ - if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0') - return GETDNS_RRTYPE_UINFO; - return -1; - default : return -1; - }; - case 'N': - case 'n': /* before "UN", final "SPEC" (GETDNS_RRTYPE_UNSPEC) */ - if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'p' && (t[4]|0x20) == 'e' && (t[5]|0x20) == 'c' && t[6] == '\0') - return GETDNS_RRTYPE_UNSPEC; - return -1; - case 'R': - case 'r': /* before "UR", final "I" (GETDNS_RRTYPE_URI) */ - if ((t[2]|0x20) == 'i' && t[3] == '\0') - return GETDNS_RRTYPE_URI; - return -1; - default : return -1; - }; - case 'W': - case 'w': /* before "W", final "KS" (GETDNS_RRTYPE_WKS) */ - if ((t[1]|0x20) == 'k' && (t[2]|0x20) == 's' && t[3] == '\0') - return GETDNS_RRTYPE_WKS; - return -1; - case 'X': - case 'x': /* before "X", final "25" (GETDNS_RRTYPE_X25) */ - if (t[1] == '2' && t[2] == '5' && t[3] == '\0') - return GETDNS_RRTYPE_X25; - return -1; - default : return -1; - }; -} From df540ad5ca454116d886a032d659f47bd40ce74c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 4 Jul 2016 16:13:30 +0200 Subject: [PATCH 05/13] Bumb version --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index da1dccd3..468178ce 100644 --- a/configure.ac +++ b/configure.ac @@ -36,8 +36,8 @@ sinclude(./m4/acx_getaddrinfo.m4) sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/pkg.m4) -AC_INIT([getdns], [1.0.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) -AC_SUBST(RELEASE_CANDIDATE, [b2]) +AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) +AC_SUBST(RELEASE_CANDIDATE, [a1]) # Set current date from system if not set AC_ARG_WITH([current-date], @@ -47,7 +47,7 @@ AC_ARG_WITH([current-date], [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) -AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00100200]) +AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100A100]) AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" From e0eb39a295fada487de58fe0890ab19bdba9843e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 4 Jul 2016 16:57:27 +0200 Subject: [PATCH 06/13] Move str2getdns type functions in the library --- .gitmodules | 2 +- src/Makefile.in | 16 +- src/const-info.c | 209 ++++++++ src/const-info.h | 7 + src/convert.c | 644 +++++++++++++++++++++++- src/getdns/getdns_extra.h.in | 4 + src/{test => }/jsmn | 0 src/libgetdns.symbols | 4 + src/mk-const-info.c.sh | 13 +- src/test/Makefile.in | 21 +- src/test/getdns_query.c | 1 - src/test/getdns_str2dict.c | 951 ----------------------------------- src/test/getdns_str2dict.h | 37 -- 13 files changed, 893 insertions(+), 1016 deletions(-) rename src/{test => }/jsmn (100%) delete mode 100644 src/test/getdns_str2dict.c delete mode 100644 src/test/getdns_str2dict.h diff --git a/.gitmodules b/.gitmodules index 06b16b93..a79d3846 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "src/test/jsmn"] - path = src/test/jsmn + path = src/jsmn url = https://github.com/getdnsapi/jsmn.git branch = getdns diff --git a/src/Makefile.in b/src/Makefile.in index 3766b318..1c66530c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -76,6 +76,8 @@ COMPAT_OBJ=$(LIBOBJS:.o=.lo) UTIL_OBJ=rbtree.lo val_secalgo.lo +JSMN_OBJ=jsmn.lo + EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo NON_C99_OBJS=context.lo libuv.lo @@ -104,6 +106,9 @@ $(COMPAT_OBJ): $(UTIL_OBJ): $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/util/$(@:.lo=.c) -o $@ +$(JSMN_OBJ): + $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@ + $(EXTENSION_OBJ): $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/extension/$(@:.lo=.c) -o $@ @@ -144,8 +149,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols -libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols +libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols test: all @@ -203,11 +208,12 @@ configure.status: configure 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"$$blddir" *.c gldns/*.c compat/*.c util/*.c extension/*.c| \ + (blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" *.c gldns/*.c compat/*.c util/*.c jsmn/*.c extension/*.c| \ sed -e "s? $$blddir/? ?g" \ -e 's?gldns/?$$(srcdir)/gldns/?g' \ -e 's?compat/?$$(srcdir)/compat/?g' \ -e 's?util/?$$(srcdir)/util/?g' \ + -e 's?jsmn/?$$(srcdir)/jsmn/?g' \ -e 's?extension/?$$(srcdir)/extension/?g' \ -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \ -e 's? \$$(srcdir)/config\.h? config.h?g' \ @@ -237,7 +243,8 @@ convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.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)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/const-info.h $(srcdir)/dict.h \ + $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ @@ -324,6 +331,7 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcd $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h +jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns.h \ getdns/getdns_extra.h $(srcdir)/debug.h config.h diff --git a/src/const-info.c b/src/const-info.c index 200100c2..0294e281 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -123,3 +123,212 @@ getdns_get_errorstr_by_id(uint16_t err) else return NULL; } + +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 ); +} + +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; +} diff --git a/src/const-info.h b/src/const-info.h index 39d7c98e..379e2512 100644 --- a/src/const-info.h +++ b/src/const-info.h @@ -47,6 +47,13 @@ struct const_info { struct const_info *_getdns_get_const_info(int value); +struct const_name_info { + const char *name; + uint32_t code; +}; + +int _getdns_get_const_name_info(const char *name, uint32_t *code); + #endif /* const-info.h */ diff --git a/src/convert.c b/src/convert.c index 2539d7bd..c5bc98c4 100644 --- a/src/convert.c +++ b/src/convert.c @@ -48,9 +48,15 @@ #include "util-internal.h" #include "gldns/wire2str.h" #include "gldns/str2wire.h" +#include "gldns/parseutil.h" +#include "const-info.h" +#include "types-internal.h" /* For getdns_item */ #include "dict.h" #include "list.h" +#include "jsmn/jsmn.h" #include "convert.h" +#include /* For bsearch */ + /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) @@ -1031,5 +1037,641 @@ getdns_msg_dict2str_scan( return r; } +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; +} + +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 _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) { + uint8_t buf[16]; + getdns_dict *dict_r; + + if (item.dtype != t_bindata) + r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + else if (item.data.bindata->size == 4 && + inet_pton(AF_INET, str, buf) == 1) { + + if (!(dict_r = getdns_dict_create())) + r = GETDNS_RETURN_MEMORY_ERROR; + + else if ((r = getdns_dict_util_set_string( + dict_r, "address_type", "IPv4"))) + getdns_dict_destroy(dict_r); + + else if ((r = getdns_dict_set_bindata( + dict_r, "address_data", item.data.bindata))) + getdns_dict_destroy(dict_r); + else + *dict = dict_r; + + } else if (item.data.bindata->size == 16 && + inet_pton(AF_INET6, str, buf) == 1) { + + if (!(dict_r = getdns_dict_create())) + r = GETDNS_RETURN_MEMORY_ERROR; + + else if ((r = getdns_dict_util_set_string( + dict_r, "address_type", "IPv6"))) + getdns_dict_destroy(dict_r); + + else if ((r = getdns_dict_set_bindata( + dict_r, "address_data", item.data.bindata))) + getdns_dict_destroy(dict_r); + else + *dict = dict_r; + } else + r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + _getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item); + return r; + } + *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; +} -/* convert.c */ diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index c8a3713f..a8d9740b 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -822,6 +822,10 @@ getdns_validate_dnssec2(getdns_list *to_validate, #define GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST ((getdns_append_name_t) 554 ) #define GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST_TEXT "See getdns_context_set_append_name()" +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); #ifdef __cplusplus } diff --git a/src/test/jsmn b/src/jsmn similarity index 100% rename from src/test/jsmn rename to src/jsmn diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index 2eb8e381..88d1cebe 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -134,6 +134,10 @@ getdns_service getdns_service_sync getdns_snprint_json_dict getdns_snprint_json_list +getdns_str2bindata +getdns_str2dict +getdns_str2int +getdns_str2list getdns_str2rr_dict getdns_strerror getdns_validate_dnssec diff --git a/src/mk-const-info.c.sh b/src/mk-const-info.c.sh index 9e8b2826..f9c54323 100755 --- a/src/mk-const-info.c.sh +++ b/src/mk-const-info.c.sh @@ -46,18 +46,20 @@ getdns_get_errorstr_by_id(uint16_t err) else 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 struct const_name_info consts_name_info[] = { +END_OF_TAIL +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 }; + 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 + +int _getdns_get_const_name_info(const char *name, uint32_t *code) { struct const_name_info key = { name, 0 }; @@ -71,5 +73,4 @@ _getdns_get_const_name_info(const char *name, uint32_t *code) return 1; } END_OF_TAIL -mv test/new-getdns_str2dict.c test/getdns_str2dict.c diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 797f2e6e..f66494e7 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -66,16 +66,13 @@ 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 +DECOMPOSED_OBJS=getdns_context_config.lo getdns_context_set_listen_addresses.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 \ - $(DECOMPOSED_OBJS_WITHOUT_JSMN) + $(DECOMPOSED_OBJS) NON_C99_OBJS=check_getdns_libuv.lo @@ -94,9 +91,6 @@ 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 $@ @@ -221,7 +215,6 @@ depend: -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 ) @@ -273,20 +266,18 @@ 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 +const-info.lo const-info.o: $(srcdir)/const-info.c 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/getdns_extra.h $(srcdir)/../util/rbtree.h $(srcdir)/../debug.h ../config.h getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - $(srcdir)/getdns_str2dict.h ../getdns/getdns.h $(srcdir)/getdns_context_config.h \ + $(srcdir)/getdns_context_config.h ../getdns/getdns.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 +new-getdns_str2dict.lo new-getdns_str2dict.o: $(srcdir)/new-getdns_str2dict.c 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 diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 09184e6d..ced608bb 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -27,7 +27,6 @@ #include "config.h" #include "debug.h" -#include "getdns_str2dict.h" #include "getdns_context_config.h" #include "getdns_context_set_listen_addresses.h" #include diff --git a/src/test/getdns_str2dict.c b/src/test/getdns_str2dict.c deleted file mode 100644 index ae5fb1d9..00000000 --- a/src/test/getdns_str2dict.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - * 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 /* 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; -} - -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) { - uint8_t buf[16]; - getdns_dict *dict_r; - - if (item.dtype != t_bindata) - r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - - else if (item.data.bindata->size == 4 && - inet_pton(AF_INET, str, buf) == 1) { - - if (!(dict_r = getdns_dict_create())) - r = GETDNS_RETURN_MEMORY_ERROR; - - else if ((r = getdns_dict_util_set_string( - dict_r, "address_type", "IPv4"))) - getdns_dict_destroy(dict_r); - - else if ((r = getdns_dict_set_bindata( - dict_r, "address_data", item.data.bindata))) - getdns_dict_destroy(dict_r); - else - *dict = dict_r; - - } else if (item.data.bindata->size == 16 && - inet_pton(AF_INET6, str, buf) == 1) { - - if (!(dict_r = getdns_dict_create())) - r = GETDNS_RETURN_MEMORY_ERROR; - - else if ((r = getdns_dict_util_set_string( - dict_r, "address_type", "IPv6"))) - getdns_dict_destroy(dict_r); - - else if ((r = getdns_dict_set_bindata( - dict_r, "address_data", item.data.bindata))) - getdns_dict_destroy(dict_r); - else - *dict = dict_r; - } else - r = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - - _getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item); - return r; - } - *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; -} diff --git a/src/test/getdns_str2dict.h b/src/test/getdns_str2dict.h deleted file mode 100644 index 71cb26c8..00000000 --- a/src/test/getdns_str2dict.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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_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 From d0f01b6bc459e88fb1d8dd090f9e55006a621b49 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 7 Jul 2016 14:47:38 +0200 Subject: [PATCH 07/13] Default values for extensions in context --- src/context.c | 31 +++++++++++++++--- src/context.h | 20 ++++++++++-- src/request-internal.c | 71 ++++++++++++++++++++++++------------------ 3 files changed, 85 insertions(+), 37 deletions(-) diff --git a/src/context.c b/src/context.c index b46dc3bd..160b1c01 100644 --- a/src/context.c +++ b/src/context.c @@ -1272,6 +1272,27 @@ getdns_context_create_with_extended_memory_functions( _getdns_default_eventloop_init(&result->default_eventloop); _getdns_default_eventloop_init(&result->sync_eventloop); + /* request extension defaults + */ + result->header = NULL; + result->add_opt_parameters = NULL; + result->add_warning_for_bad_dns = 0; + result->dnssec_return_all_statuses = 0; + result->dnssec_return_full_validation_chain = 0; + result->dnssec_return_only_secure = 0; + result->dnssec_return_status = 0; + result->dnssec_return_validation_chain = 0; +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + result->dnssec_roadblock_avoidance = 0; +#endif + result->edns_cookies = 0; + result->return_api_information = 0; + result->return_both_v4_and_v6 = 0; + result->return_call_reporting = 0; + result->specify_class = GETDNS_RRCLASS_IN; + + /* state data used to detect changes to the system config files + */ result->fchg_resolvconf = NULL; result->fchg_hosts = NULL; @@ -1291,7 +1312,6 @@ getdns_context_create_with_extended_memory_functions( result->tls_auth = GETDNS_AUTHENTICATION_NONE; result->tls_auth_min = GETDNS_AUTHENTICATION_NONE; result->limit_outstanding_queries = 0; - result->return_dnssec_status = GETDNS_EXTENSION_FALSE; /* unbound context is initialized here */ /* Unbound needs SSL to be init'ed this early when TLS is used. However we @@ -1401,8 +1421,7 @@ getdns_context_destroy(struct getdns_context *context) if (context->tls_ctx) SSL_CTX_free(context->tls_ctx); - if (context->dns_root_servers) - getdns_list_destroy(context->dns_root_servers); + getdns_list_destroy(context->dns_root_servers); #if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB) if (context->root_servers_fn[0]) @@ -1419,6 +1438,10 @@ getdns_context_destroy(struct getdns_context *context) _getdns_traverse_postorder(&context->local_hosts, destroy_local_host, context); + + getdns_dict_destroy(context->header); + getdns_dict_destroy(context->add_opt_parameters); + #ifdef USE_WINSOCK WSACleanup(); #endif @@ -3416,7 +3439,7 @@ getdns_context_set_return_dnssec_status(getdns_context* context, int enabled) { enabled != GETDNS_EXTENSION_FALSE) { return GETDNS_RETURN_INVALID_PARAMETER; } - context->return_dnssec_status = enabled; + context->dnssec_return_status = enabled == GETDNS_EXTENSION_TRUE; return GETDNS_RETURN_GOOD; } diff --git a/src/context.h b/src/context.h index 46ed6c88..2ccea5c4 100644 --- a/src/context.h +++ b/src/context.h @@ -250,8 +250,6 @@ struct getdns_context { /* A tree to hold local host information*/ _getdns_rbtree_t local_hosts; - int return_dnssec_status; - /* which resolution type the contexts are configured for * 0 means nothing set */ @@ -275,6 +273,24 @@ struct getdns_context { _getdns_default_eventloop default_eventloop; _getdns_default_eventloop sync_eventloop; + /* request extension defaults */ + getdns_dict *header; + getdns_dict *add_opt_parameters; + int add_warning_for_bad_dns : 1; + int dnssec_return_all_statuses : 1; + int dnssec_return_full_validation_chain : 1; + int dnssec_return_only_secure : 1; + int dnssec_return_status : 1; + int dnssec_return_validation_chain : 1; +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + int dnssec_roadblock_avoidance : 1; +#endif + int edns_cookies : 1; + int return_api_information : 1; /* Not used */ + int return_both_v4_and_v6 : 1; + int return_call_reporting : 1; + uint16_t specify_class; + /* * state data used to detect changes to the system config files */ diff --git a/src/request-internal.c b/src/request-internal.c index 797fde50..b35b3cae 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -85,20 +85,20 @@ getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks static int -is_extension_set(getdns_dict *extensions, const char *extension) +is_extension_set(getdns_dict *extensions, const char *name, int default_value) { getdns_return_t r; uint32_t value; - if (! extensions) - return 0; - else if (extensions == dnssec_ok_checking_disabled + if ( ! extensions + || extensions == dnssec_ok_checking_disabled || extensions == dnssec_ok_checking_disabled_roadblock_avoidance || extensions == dnssec_ok_checking_disabled_avoid_roadblocks) return 0; - r = getdns_dict_get_int(extensions, extension, &value); - return r == GETDNS_RETURN_GOOD && value == GETDNS_EXTENSION_TRUE; + r = getdns_dict_get_int(extensions, name, &value); + return r == GETDNS_RETURN_GOOD ? ( value == GETDNS_EXTENSION_TRUE ) + : default_value; } static void @@ -206,6 +206,8 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, buf = netreq_reset(net_req); gldns_buffer_init_frm_data( &gbuf, net_req->query, net_req->wire_data_sz - 2); + if (owner->context->header) + _getdns_reply_dict2wire(owner->context->header, &gbuf, 1); _getdns_reply_dict2wire(extensions, &gbuf, 1); if (dnssec_extension_set) /* We will do validation ourselves */ GLDNS_CD_SET(net_req->query); @@ -658,28 +660,32 @@ getdns_dns_req * _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions) { - int dnssec_return_status - = context->return_dnssec_status == GETDNS_EXTENSION_TRUE - || is_extension_set(extensions, "dnssec_return_status"); - int dnssec_return_only_secure - = is_extension_set(extensions, "dnssec_return_only_secure"); - int dnssec_return_all_statuses - = is_extension_set(extensions, "dnssec_return_all_statuses"); - int dnssec_return_full_validation_chain - = is_extension_set(extensions, "dnssec_return_full_validation_chain"); - int dnssec_return_validation_chain - = is_extension_set(extensions, "dnssec_return_validation_chain"); - int edns_cookies - = is_extension_set(extensions, "edns_cookies"); + int dnssec_return_status = is_extension_set( + extensions, "dnssec_return_status", + context->dnssec_return_status); + int dnssec_return_only_secure = is_extension_set( + extensions, "dnssec_return_only_secure", + context->dnssec_return_only_secure); + int dnssec_return_all_statuses = is_extension_set( + extensions, "dnssec_return_all_statuses", + context->dnssec_return_all_statuses); + int dnssec_return_full_validation_chain = is_extension_set( + extensions, "dnssec_return_full_validation_chain", + context->dnssec_return_full_validation_chain); + int dnssec_return_validation_chain = is_extension_set( + extensions, "dnssec_return_validation_chain", + context->dnssec_return_validation_chain); + int edns_cookies = is_extension_set( + extensions, "edns_cookies", + context->edns_cookies); #ifdef DNSSEC_ROADBLOCK_AVOIDANCE int avoid_dnssec_roadblocks = (extensions == dnssec_ok_checking_disabled_avoid_roadblocks); - int dnssec_roadblock_avoidance - = is_extension_set(extensions, "dnssec_roadblock_avoidance") + int dnssec_roadblock_avoidance = avoid_dnssec_roadblocks || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance) - || avoid_dnssec_roadblocks; + || is_extension_set(extensions, "dnssec_roadblock_avoidance", + context->dnssec_roadblock_avoidance); #endif - int dnssec_extension_set = dnssec_return_status || dnssec_return_only_secure || dnssec_return_all_statuses || dnssec_return_validation_chain @@ -713,9 +719,9 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, int with_opt; getdns_dns_req *result = NULL; - uint32_t klass = GLDNS_RR_CLASS_IN; - int a_aaaa_query = - is_extension_set(extensions, "return_both_v4_and_v6") && + uint32_t klass = context->specify_class; + int a_aaaa_query = is_extension_set(extensions, + "return_both_v4_and_v6", context->return_both_v4_and_v6) && ( request_type == GETDNS_RRTYPE_A || request_type == GETDNS_RRTYPE_AAAA ); /* Reserve for the buffer at least one more byte @@ -732,7 +738,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, have_add_opt_parameters = getdns_dict_get_dict(extensions, "add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD; - + if (!have_add_opt_parameters && context->add_opt_parameters) { + add_opt_parameters = context->add_opt_parameters; + have_add_opt_parameters = 1; + } if (dnssec_extension_set) { edns_maximum_udp_payload_size = -1; edns_extended_rcode = 0; @@ -895,10 +904,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, #endif result->edns_client_subnet_private = context->edns_client_subnet_private; result->tls_query_padding_blocksize = context->tls_query_padding_blocksize; - result->return_call_reporting = - is_extension_set(extensions, "return_call_reporting"); - result->add_warning_for_bad_dns = - is_extension_set(extensions, "add_warning_for_bad_dns"); + result->return_call_reporting = is_extension_set(extensions, + "return_call_reporting" , context->return_call_reporting); + result->add_warning_for_bad_dns = is_extension_set(extensions, + "add_warning_for_bad_dns", context->add_warning_for_bad_dns); /* will be set by caller */ result->user_pointer = NULL; From 7e614bc534b2c69ae70dbf7a93d4441b7b42da46 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 11 Jul 2016 15:13:40 +0200 Subject: [PATCH 08/13] More conventional server DNSSEC behaviour + documentation of behaviour --- project-doc/getdns_query-deamon-behaviour.ods | Bin 0 -> 17609 bytes project-doc/getdns_query-deamon-behaviour.pdf | Bin 0 -> 13995 bytes src/convert.c | 35 ++++- .../getdns_context_set_listen_addresses.c | 66 +++++++++ src/test/getdns_query.c | 128 ++++++++++++++---- 5 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 project-doc/getdns_query-deamon-behaviour.ods create mode 100644 project-doc/getdns_query-deamon-behaviour.pdf diff --git a/project-doc/getdns_query-deamon-behaviour.ods b/project-doc/getdns_query-deamon-behaviour.ods new file mode 100644 index 0000000000000000000000000000000000000000..041cebc754bfe60ac255409c9d2c70f5e6687f21 GIT binary patch literal 17609 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 N4ML`+l~e*F|3AzLS^@w7 literal 0 HcmV?d00001 diff --git a/src/convert.c b/src/convert.c index 2539d7bd..5eb1a513 100644 --- a/src/convert.c +++ b/src/convert.c @@ -611,6 +611,15 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf, if (!wire || !*wire || !wire_len || !msg_dict) return GETDNS_RETURN_INVALID_PARAMETER; +#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG + do { + char *str = gldns_wire2str_pkt((uint8_t *)*wire, *wire_len); + DEBUG_SERVER("_getdns_wire2msg_dict_scan for a packet size: %d: %s\n", + (int)*wire_len, str); + free(str); + } while(0); +#endif + if (!(result = _getdns_dict_create_with_mf(mf)) || !(header = _getdns_dict_create_with_mf(mf)) || !(sections[SECTION_ANSWER] @@ -768,11 +777,12 @@ _getdns_reply_dict2wire( const getdns_dict *reply, gldns_buffer *buf, int reuse_header) { uint8_t header_spc[GLDNS_HEADER_SIZE], *header; - uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN; + uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN, rr_type; size_t pkt_start, i; getdns_list *section; getdns_dict *rr_dict; getdns_bindata *qname; + int remove_dnssec; pkt_start = gldns_buffer_position(buf); if (reuse_header) { @@ -814,11 +824,18 @@ _getdns_reply_dict2wire( buf, pkt_start+GLDNS_ARCOUNT_OFF, 0); } } + remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0; + DEBUG_SERVER("remove_dnssec: %d\n", remove_dnssec); + if (!getdns_dict_get_list(reply, "answer", §ion)) { for ( n = 0, i = 0 ; !getdns_list_get_dict(section, i, &rr_dict); i++) { - if (!_getdns_rr_dict2wire(rr_dict, buf)) + if (remove_dnssec && + !getdns_dict_get_int(rr_dict, "type", &rr_type) && + rr_type == GETDNS_RRTYPE_RRSIG) + continue; + if (!_getdns_rr_dict2wire(rr_dict, buf)) n++; } gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n); @@ -827,7 +844,15 @@ _getdns_reply_dict2wire( for ( n = 0, i = 0 ; !getdns_list_get_dict(section, i, &rr_dict); i++) { - if (!_getdns_rr_dict2wire(rr_dict, buf)) + if (remove_dnssec && + !getdns_dict_get_int(rr_dict, "type", &rr_type) && + ( rr_type == GETDNS_RRTYPE_RRSIG + || rr_type == GETDNS_RRTYPE_NSEC + || rr_type == GETDNS_RRTYPE_NSEC3 + || rr_type == GETDNS_RRTYPE_DS + )) + continue; + if (!_getdns_rr_dict2wire(rr_dict, buf)) n++; } gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_NSCOUNT_OFF, n); @@ -836,6 +861,10 @@ _getdns_reply_dict2wire( for ( n = 0, i = 0 ; !getdns_list_get_dict(section, i, &rr_dict); i++) { + if (remove_dnssec && + !getdns_dict_get_int(rr_dict, "type", &rr_type) && + rr_type == GETDNS_RRTYPE_RRSIG) + continue; if (!_getdns_rr_dict2wire(rr_dict, buf)) n++; } diff --git a/src/test/getdns_context_set_listen_addresses.c b/src/test/getdns_context_set_listen_addresses.c index eeeac3ad..fcfe9057 100644 --- a/src/test/getdns_context_set_listen_addresses.c +++ b/src/test/getdns_context_set_listen_addresses.c @@ -503,6 +503,72 @@ static void udp_read_cb(void *userarg) close(l->fd); l->fd = -1; +#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG + } else { + char addrbuf[100]; + char hexbuf[4096], *hexptr; + size_t l, i, j; + + if (conn->remote_in.ss_family == AF_INET) { + if (inet_ntop(AF_INET, + &((struct sockaddr_in*)&conn->remote_in)->sin_addr, + addrbuf, sizeof(addrbuf))) { + + l = strlen(addrbuf); + (void) snprintf(addrbuf + l, + sizeof(addrbuf) - l, ":%d", + (int)((struct sockaddr_in*) + &conn->remote_in)->sin_port); + } else + (void) strncpy( + addrbuf, "error ipv4", sizeof(addrbuf)); + + } else if (conn->remote_in.ss_family == AF_INET6) { + addrbuf[0] = '['; + if (inet_ntop(AF_INET6, + &((struct sockaddr_in6*) + &conn->remote_in)->sin6_addr, + addrbuf, sizeof(addrbuf))) { + + l = strlen(addrbuf); + (void) snprintf(addrbuf + l, + sizeof(addrbuf) - l, ":%d", + (int)((struct sockaddr_in6*) + &conn->remote_in)->sin6_port); + } else + (void) strncpy( + addrbuf, "error ipv6", sizeof(addrbuf)); + + } else { + (void) strncpy( + addrbuf, "unknown address", sizeof(addrbuf)); + } + *(hexptr = hexbuf) = 0; + for (i = 0; i < len; i++) { + if (i % 12 == 0) { + hexptr += snprintf(hexptr, + sizeof(hexbuf) - (hexptr - hexbuf) - 1, + "\n%.4x", (int)i); + } else if (i % 4 == 0) { + hexptr += snprintf(hexptr, + sizeof(hexbuf) - (hexptr - hexbuf) - 1, + " "); + } + if (hexptr - hexbuf > sizeof(hexbuf)) + break; + hexptr += snprintf(hexptr, + sizeof(hexbuf) - (hexptr - hexbuf) - 1, + " %.2x", (int)buf[i]); + if (hexptr - hexbuf > sizeof(hexbuf)) + break; + } + DEBUG_SERVER("Received %d bytes from %s: %s\n", + (int)len, addrbuf, hexbuf); + } + if (len == -1) { + ; /* pass */ +#endif + } else if ((r = getdns_wire2msg_dict(buf, len, &request_dict))) ; /* FROMERR on input, ignore */ diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 09184e6d..54464bcd 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -1200,8 +1200,10 @@ typedef struct dns_msg { getdns_transaction_t request_id; getdns_dict *request; uint32_t rt; + uint32_t ad_bit; uint32_t do_bit; uint32_t cd_bit; + int has_edns0; } dns_msg; #if defined(SERVER_DEBUG) && SERVER_DEBUG @@ -1236,15 +1238,53 @@ void servfail(dns_msg *msg, getdns_dict **resp_p) (void) getdns_dict_set_int(*resp_p, "/header/ad", 0); } -void request_cb(getdns_context *context, getdns_callback_type_t callback_type, +static getdns_return_t _handle_edns0( + getdns_dict *response, int has_edns0, uint32_t do_bit) +{ + getdns_return_t r; + getdns_list *additional; + size_t len, i; + getdns_dict *rr; + uint32_t rr_type; + char remove_str[100] = "/replies_tree/0/additional/"; + + if ((r = getdns_dict_set_int( + response, "/replies_tree/0/header/do", do_bit))) + return r; + if (has_edns0) + return GETDNS_RETURN_GOOD; + if ((r = getdns_dict_get_list(response, "/replies_tree/0/additional", + &additional))) + return r; + if ((r = getdns_list_get_length(additional, &len))) + return r; + for (i = 0; i < len; i++) { + if ((r = getdns_list_get_dict(additional, i, &rr))) + return r; + if ((r = getdns_dict_get_int(rr, "type", &rr_type))) + return r; + if (rr_type != GETDNS_RRTYPE_OPT) + continue; + (void) snprintf(remove_str + 27, 60, "%d", (int)i); + if ((r = getdns_dict_remove_name(response, remove_str))) + return r; + break; + } + return GETDNS_RETURN_GOOD; +} + +static void request_cb( + getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) { dns_msg *msg = (dns_msg *)userarg; uint32_t qid; getdns_return_t r = GETDNS_RETURN_GOOD; - uint32_t n; + uint32_t n, rcode, dnssec_status; - DEBUG_SERVER("reply for: %p %"PRIu64" %d\n", msg, transaction_id, (int)callback_type); + DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d," + " cd: %d)\n", msg, transaction_id, (int)callback_type, + msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit); assert(msg); #if 0 @@ -1263,21 +1303,36 @@ void request_cb(getdns_context *context, getdns_callback_type_t callback_type, SERVFAIL("Could not copy QID", r, msg, &response); else if (getdns_dict_get_int( - response, "/replies_tree/0/header/rcode", &n)) + response, "/replies_tree/0/header/rcode", &rcode)) SERVFAIL("No reply in replies tree", 0, msg, &response); - else if (msg->cd_bit != 1 && !getdns_dict_get_int( - response, "/replies_tree/0/dnssec_status", &n) - && n == GETDNS_DNSSEC_BOGUS) + /* ansers when CD or not BOGUS */ + else if (!msg->cd_bit && !getdns_dict_get_int( + response, "/replies_tree/0/dnssec_status", &dnssec_status) + && dnssec_status == GETDNS_DNSSEC_BOGUS) SERVFAIL("DNSSEC status was bogus", 0, msg, &response); - else if ((r = getdns_dict_get_int( - response, "/replies_tree/0/header/rcode", &n))) - SERVFAIL("Could not get rcode from reply", r, msg, &response); - - else if (n == GETDNS_RCODE_SERVFAIL) + else if (rcode == GETDNS_RCODE_SERVFAIL) servfail(msg, &response); + /* RRsigs when DO and (CD or not BOGUS) + * Implemented in conversion to wireformat function by checking for DO + * bit. In recursing resolution mode we have to copy the do bit from + * the request, because libunbound has it in the answer always. + */ + else if (msg->rt == GETDNS_RESOLUTION_RECURSING && + (r = _handle_edns0(response, msg->has_edns0, msg->do_bit))) + SERVFAIL("Could not handle EDNS0", r, msg, &response); + + /* AD when (DO or AD) and SECURE */ + else if ((r = getdns_dict_set_int(response,"/replies_tree/0/header/ad", + ((msg->do_bit || msg->ad_bit) + && ( (!msg->cd_bit && dnssec_status == GETDNS_DNSSEC_SECURE) + || ( msg->cd_bit && !getdns_dict_get_int(response, + "/replies_tree/0/dnssec_status", &dnssec_status) + && dnssec_status == GETDNS_DNSSEC_SECURE ))) ? 1 : 0))) + SERVFAIL("Could not set AD bit", r, msg, &response); + else if (msg->rt == GETDNS_RESOLUTION_STUB) ; /* following checks are for RESOLUTION_RECURSING only */ @@ -1324,6 +1379,10 @@ static void incoming_request_handler(getdns_context *context, getdns_dict *qext = NULL; dns_msg *msg = NULL; getdns_dict *response = NULL; + size_t i, len; + getdns_list *additional; + getdns_dict *rr; + uint32_t rr_type; if (!query_extensions_spc && !(query_extensions_spc = getdns_dict_create())) @@ -1345,10 +1404,26 @@ static void incoming_request_handler(getdns_context *context, n = 0; msg->request_id = request_id; msg->request = request; - msg->do_bit = msg->cd_bit = 0; - msg->rt = GETDNS_RESOLUTION_STUB; - (void) getdns_dict_get_int(request, "/additional/0/do", &msg->do_bit); + msg->ad_bit = msg->do_bit = msg->cd_bit = 0; + msg->has_edns0 = 0; + msg->rt = GETDNS_RESOLUTION_RECURSING; + (void) getdns_dict_get_int(request, "/header/ad", &msg->ad_bit); (void) getdns_dict_get_int(request, "/header/cd", &msg->cd_bit); + if (!getdns_dict_get_list(request, "additional", &additional)) { + if (getdns_list_get_length(additional, &len)) + len = 0; + for (i = 0; i < len; i++) { + if (getdns_list_get_dict(additional, i, &rr)) + break; + if (getdns_dict_get_int(rr, "type", &rr_type)) + break; + if (rr_type != GETDNS_RRTYPE_OPT) + continue; + msg->has_edns0 = 1; + (void) getdns_dict_get_int(rr, "do", &msg->do_bit); + break; + } + } if ((r = getdns_context_get_resolution_type(context, &msg->rt))) fprintf(stderr, "Could get resolution type from context: %s\n", getdns_get_errorstr_by_id(r)); @@ -1359,15 +1434,10 @@ static void incoming_request_handler(getdns_context *context, if (!getdns_dict_get_dict(request, "header", &header)) (void)getdns_dict_set_dict(qext, "header", header); - } else if (getdns_dict_get_int(extensions,"dnssec_return_status",&n) || - n == GETDNS_EXTENSION_FALSE) - (void)getdns_dict_set_int(qext, "dnssec_return_status", - msg->do_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE); - - if (!getdns_dict_get_int(qext, "dnssec_return_status", &n) && - n == GETDNS_EXTENSION_TRUE) - (void) getdns_dict_set_int(qext, "dnssec_return_all_statuses", - msg->cd_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE); + } + if (msg->cd_bit) + getdns_dict_set_int(qext, "dnssec_return_all_statuses", + GETDNS_EXTENSION_TRUE); if (!getdns_dict_get_int(request, "/additional/0/extended_rcode",&n)) (void)getdns_dict_set_int( @@ -1431,6 +1501,16 @@ error: if (qname_str) free(qname_str); servfail(msg, &response); +#if defined(SERVER_DEBUG) && SERVER_DEBUG + do { + char *request_str = getdns_pretty_print_dict(request); + char *response_str = getdns_pretty_print_dict(response); + DEBUG_SERVER("request error, request: %s\n, response: %s\n" + , request_str, response_str); + free(response_str); + free(request_str); + } while(0); +#endif if (!response) /* No response, no reply */ _getdns_cancel_reply(context, request_id); From b98d91f7455cd951ecf72c0e5a1d09709f989261 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 11 Jul 2016 15:43:42 +0200 Subject: [PATCH 09/13] Daemon edns0 handling bugfix --- src/convert.c | 1 + src/test/getdns_query.c | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/convert.c b/src/convert.c index 5eb1a513..9ce2fa39 100644 --- a/src/convert.c +++ b/src/convert.c @@ -51,6 +51,7 @@ #include "dict.h" #include "list.h" #include "convert.h" +#include "debug.h" /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 54464bcd..99f04ca5 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -1239,7 +1239,7 @@ void servfail(dns_msg *msg, getdns_dict **resp_p) } static getdns_return_t _handle_edns0( - getdns_dict *response, int has_edns0, uint32_t do_bit) + getdns_dict *response, int has_edns0) { getdns_return_t r; getdns_list *additional; @@ -1249,10 +1249,8 @@ static getdns_return_t _handle_edns0( char remove_str[100] = "/replies_tree/0/additional/"; if ((r = getdns_dict_set_int( - response, "/replies_tree/0/header/do", do_bit))) + response, "/replies_tree/0/header/do", 0))) return r; - if (has_edns0) - return GETDNS_RETURN_GOOD; if ((r = getdns_dict_get_list(response, "/replies_tree/0/additional", &additional))) return r; @@ -1265,6 +1263,10 @@ static getdns_return_t _handle_edns0( return r; if (rr_type != GETDNS_RRTYPE_OPT) continue; + if (has_edns0) { + (void) getdns_dict_set_int(rr, "do", 0); + break; + } (void) snprintf(remove_str + 27, 60, "%d", (int)i); if ((r = getdns_dict_remove_name(response, remove_str))) return r; @@ -1320,8 +1322,8 @@ static void request_cb( * bit. In recursing resolution mode we have to copy the do bit from * the request, because libunbound has it in the answer always. */ - else if (msg->rt == GETDNS_RESOLUTION_RECURSING && - (r = _handle_edns0(response, msg->has_edns0, msg->do_bit))) + else if (msg->rt == GETDNS_RESOLUTION_RECURSING && !msg->do_bit && + (r = _handle_edns0(response, msg->has_edns0))) SERVFAIL("Could not handle EDNS0", r, msg, &response); /* AD when (DO or AD) and SECURE */ From a523838cc6a7f651005756498f3a5921855f1cc0 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 11 Jul 2016 16:05:05 +0200 Subject: [PATCH 10/13] set_listen_addresses does not change listen_list --- src/test/getdns_context_set_listen_addresses.c | 3 ++- src/test/getdns_context_set_listen_addresses.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/getdns_context_set_listen_addresses.c b/src/test/getdns_context_set_listen_addresses.c index fcfe9057..3b05e803 100644 --- a/src/test/getdns_context_set_listen_addresses.c +++ b/src/test/getdns_context_set_listen_addresses.c @@ -739,7 +739,8 @@ static getdns_return_t add_listeners(listen_set *set) } getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, - getdns_request_handler_t request_handler, getdns_list *listen_addresses) + getdns_request_handler_t request_handler, + const getdns_list *listen_addresses) { static const getdns_transport_list_t listen_transports[] = { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP }; diff --git a/src/test/getdns_context_set_listen_addresses.h b/src/test/getdns_context_set_listen_addresses.h index 116634f4..fac16f48 100644 --- a/src/test/getdns_context_set_listen_addresses.h +++ b/src/test/getdns_context_set_listen_addresses.h @@ -35,8 +35,9 @@ typedef void (*getdns_request_handler_t)( 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_context_set_listen_addresses( + getdns_context *context, getdns_request_handler_t request_handler, + const getdns_list *listen_addresses); getdns_return_t getdns_reply(getdns_context *context, getdns_transaction_t request_id, getdns_dict *reply); From 69b607176ce3bb95a451408d4d68be32a1136bbc Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 11 Jul 2016 20:42:50 +0200 Subject: [PATCH 11/13] Move getdns_context_config into the library --- src/Makefile.in | 4 +- src/context.c | 205 ++++++++++++++++++++++++++++ src/getdns/getdns_extra.h.in | 3 + src/libgetdns.symbols | 1 + src/request-internal.c | 1 + src/test/Makefile.in | 8 +- src/test/getdns_context_config.c | 220 ------------------------------- src/test/getdns_context_config.h | 41 ------ src/test/getdns_query.c | 4 +- 9 files changed, 216 insertions(+), 271 deletions(-) delete mode 100644 src/test/getdns_context_config.c delete mode 100644 src/test/getdns_context_config.h diff --git a/src/Makefile.in b/src/Makefile.in index 1c66530c..5960c7ff 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -243,8 +243,8 @@ convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.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)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/const-info.h $(srcdir)/dict.h \ - $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \ + $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ diff --git a/src/context.c b/src/context.c index 160b1c01..0618814a 100644 --- a/src/context.c +++ b/src/context.c @@ -3914,4 +3914,209 @@ getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t return GETDNS_RETURN_GOOD; } +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; iX = 1; \ + else if (n == GETDNS_EXTENSION_FALSE) context->X = 0; \ + else r = GETDNS_RETURN_INVALID_PARAMETER; \ + } + +static getdns_return_t +_getdns_context_config_setting(getdns_context *context, + 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, 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_BOOL(add_warning_for_bad_dns) + EXTENSION_SETTING_BOOL(dnssec_return_all_statuses) + EXTENSION_SETTING_BOOL(dnssec_return_full_validation_chain) + EXTENSION_SETTING_BOOL(dnssec_return_only_secure) + EXTENSION_SETTING_BOOL(dnssec_return_status) + EXTENSION_SETTING_BOOL(dnssec_return_validation_chain) +#if defined(DNSSEC_ROADBLOCK_AVOIDANCE) && defined(HAVE_LIBUNBOUND) + EXTENSION_SETTING_BOOL(dnssec_roadblock_avoidance) +#endif +#ifdef EDNS_COOKIES + EXTENSION_SETTING_BOOL(edns_cookies) +#endif + EXTENSION_SETTING_BOOL(return_api_information) + EXTENSION_SETTING_BOOL(return_both_v4_and_v6) + EXTENSION_SETTING_BOOL(return_call_reporting) + + } else if (_streq(setting, "add_opt_parameters")) { + if (!(r = getdns_dict_get_dict(config_dict, "add_opt_parameters" , &dict))) { + if (context->add_opt_parameters) + getdns_dict_destroy(context->add_opt_parameters); + context->add_opt_parameters = NULL; + r = _getdns_dict_copy(dict, &context->add_opt_parameters); + } + + } else if (_streq(setting, "header")) { + if (!(r = getdns_dict_get_dict(config_dict, "header" , &dict))) { + if (context->header) + getdns_dict_destroy(context->header); + if (!(context->header = + getdns_dict_create_with_context(context))) + r = GETDNS_RETURN_MEMORY_ERROR; + else r = getdns_dict_set_dict( + context->header, "header", dict); + } + + } else if (_streq(setting, "specify_class")) { + if (!(r = getdns_dict_get_int( + config_dict, "specify_class" , &n))) + context->specify_class = (uint16_t)n; + + + /************************************/ + /**** ****/ + /**** 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, 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, config_dict, setting))) + break; + } + if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM) + r = GETDNS_RETURN_GOOD; + + getdns_list_destroy(settings); + return r; +} + /* context.c */ diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index a8d9740b..011275cd 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -827,6 +827,9 @@ 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); +getdns_return_t +getdns_context_config(getdns_context *context, const getdns_dict *config_dict); + #ifdef __cplusplus } #endif diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index 88d1cebe..6b5a28fe 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -1,6 +1,7 @@ getdns_address getdns_address_sync getdns_cancel_callback +getdns_context_config getdns_context_create getdns_context_create_with_extended_memory_functions getdns_context_create_with_memory_functions diff --git a/src/request-internal.c b/src/request-internal.c index b35b3cae..8e4ec303 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -208,6 +208,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, &gbuf, net_req->query, net_req->wire_data_sz - 2); if (owner->context->header) _getdns_reply_dict2wire(owner->context->header, &gbuf, 1); + gldns_buffer_rewind(&gbuf); _getdns_reply_dict2wire(extensions, &gbuf, 1); if (dnssec_extension_set) /* We will do validation ourselves */ GLDNS_CD_SET(net_req->query); diff --git a/src/test/Makefile.in b/src/test/Makefile.in index f66494e7..e3906eb8 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -66,7 +66,7 @@ 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=getdns_context_config.lo getdns_context_set_listen_addresses.lo +DECOMPOSED_OBJS=getdns_context_set_listen_addresses.lo ALL_OBJS=$(CHECK_OBJS) check_getdns_libevent.lo check_getdns_libev.lo \ check_getdns_selectloop.lo getdns_query.lo scratchpad.lo \ @@ -266,7 +266,6 @@ 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 -const-info.lo const-info.o: $(srcdir)/const-info.c 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: \ @@ -275,9 +274,8 @@ getdns_context_set_listen_addresses.lo getdns_context_set_listen_addresses.o: \ ../getdns/getdns_extra.h $(srcdir)/../types-internal.h ../getdns/getdns.h \ ../getdns/getdns_extra.h $(srcdir)/../util/rbtree.h $(srcdir)/../debug.h ../config.h getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - $(srcdir)/getdns_context_config.h ../getdns/getdns.h \ - $(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns_extra.h -new-getdns_str2dict.lo new-getdns_str2dict.o: $(srcdir)/new-getdns_str2dict.c + $(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns.h \ + ../getdns/getdns_extra.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 diff --git a/src/test/getdns_context_config.c b/src/test/getdns_context_config.c deleted file mode 100644 index 3cb7e272..00000000 --- a/src/test/getdns_context_config.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * 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 -#include -#include - -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 #include @@ -463,8 +462,7 @@ static void parse_config(const char *config_str) touched_listen_list = 1; } - if ((r = _getdns_context_config_( - context, extensions, config_dict))) { + if ((r = getdns_context_config(context, config_dict))) { fprintf(stderr, "Could not configure context with " "config dict: %s\n", getdns_get_errorstr_by_id(r)); } From be97bd1d71a16ab5757eb8c29fa5f5b6aac410a1 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 13 Jul 2016 14:50:44 +0200 Subject: [PATCH 12/13] Mv getdns_context_set_listen_addresses in the lib Also, check for request_id + cancel a reply by specifying NULL as response to getdns_reply --- src/Makefile.in | 48 +++-- src/context.c | 5 + src/context.h | 3 + src/getdns/getdns_extra.h.in | 13 ++ src/libgetdns.symbols | 2 + ...ontext_set_listen_addresses.c => server.c} | 177 ++++++++++-------- ...ontext_set_listen_addresses.h => server.h} | 32 ++-- src/test/Makefile.in | 19 +- src/test/getdns_query.c | 19 +- 9 files changed, 176 insertions(+), 142 deletions(-) rename src/{test/getdns_context_set_listen_addresses.c => server.c} (86%) rename src/{test/getdns_context_set_listen_addresses.h => server.h} (70%) diff --git a/src/Makefile.in b/src/Makefile.in index 5960c7ff..c9ff78db 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,7 +65,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@ GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \ - rr-iter.lo stub.lo sync.lo ub_loop.lo util-internal.lo + rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \ str2wire.lo @@ -237,70 +237,78 @@ context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/g $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ + $(srcdir)/pubkey-pinning.h convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.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)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \ $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h + $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ - $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ - $(srcdir)/util/val_secalgo.h + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \ + $(srcdir)/list.h $(srcdir)/util/val_secalgo.h general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/list.h $(srcdir)/dict.h pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h + getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ $(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 + getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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 $(srcdir)/rr-dict.h config.h getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h +server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ + $(srcdir)/context.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)/server.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 \ $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.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)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ + $(srcdir)/gldns/wire2str.h ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ $(srcdir)/debug.h util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \ $(srcdir)/gldns/rrdef.h version.lo version.o: version.c diff --git a/src/context.c b/src/context.c index 0618814a..a47124de 100644 --- a/src/context.c +++ b/src/context.c @@ -1216,6 +1216,8 @@ getdns_context_create_with_extended_memory_functions( _getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp); _getdns_rbtree_init(&result->local_hosts, local_host_cmp); + result->server = NULL; + #ifdef HAVE_LIBUNBOUND result->resolution_type = GETDNS_RESOLUTION_RECURSING; #else @@ -1389,6 +1391,9 @@ getdns_context_destroy(struct getdns_context *context) /* cancel all outstanding requests */ cancel_outstanding_requests(context, 1); + /* Destroy listening addresses */ + (void) getdns_context_set_listen_addresses(context, NULL, NULL); + /* This needs to be done before cleaning the extension, because there * might be an idle_timeout schedules, which will not get unscheduled * with cancel_outstanding_requests. diff --git a/src/context.h b/src/context.h index 2ccea5c4..fd603b6d 100644 --- a/src/context.h +++ b/src/context.h @@ -44,6 +44,7 @@ #include "extension/default_eventloop.h" #include "util/rbtree.h" #include "ub_loop.h" +#include "server.h" struct getdns_dns_req; struct ub_ctx; @@ -260,6 +261,8 @@ struct getdns_context { */ _getdns_rbtree_t outbound_requests; + struct listen_set *server; + /* Event loop extension. */ getdns_eventloop *extension; diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 011275cd..d2bcd290 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -830,6 +830,19 @@ getdns_return_t getdns_str2int(const char *str, uint32_t *value); getdns_return_t getdns_context_config(getdns_context *context, const getdns_dict *config_dict); +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 handler, const getdns_list *listen_addresses); + +getdns_return_t getdns_reply(getdns_context *context, + getdns_transaction_t request_id, getdns_dict *reply); + #ifdef __cplusplus } #endif diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index 6b5a28fe..6e3cb128 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -51,6 +51,7 @@ getdns_context_set_extended_memory_functions getdns_context_set_follow_redirects getdns_context_set_idle_timeout getdns_context_set_limit_outstanding_queries +getdns_context_set_listen_addresses getdns_context_set_memory_functions getdns_context_set_namespaces getdns_context_set_resolution_type @@ -124,6 +125,7 @@ getdns_print_json_dict getdns_print_json_list getdns_pubkey_pin_create_from_string getdns_pubkey_pinset_sanity_check +getdns_reply getdns_root_trust_anchor getdns_rr_dict2str getdns_rr_dict2str_buf diff --git a/src/test/getdns_context_set_listen_addresses.c b/src/server.c similarity index 86% rename from src/test/getdns_context_set_listen_addresses.c rename to src/server.c index 3b05e803..c42008dd 100644 --- a/src/test/getdns_context_set_listen_addresses.c +++ b/src/server.c @@ -26,11 +26,13 @@ */ #include "config.h" -#include "getdns_context_set_listen_addresses.h" +#include #include "getdns/getdns_extra.h" +#include "context.h" #include "types-internal.h" #include "debug.h" -#include +#include "util/rbtree.h" +#include "server.h" #define DNS_REQUEST_SZ 4096 #define DOWNSTREAM_IDLE_TIMEOUT 5000 @@ -63,9 +65,9 @@ struct listener { */ struct listen_set { getdns_context *context; - listen_set *next; getdns_request_handler_t handler; + _getdns_rbtree_t connections_set; size_t count; listener items[]; }; @@ -79,6 +81,9 @@ struct tcp_to_write { }; struct connection { + /* struct connection is a sub struct of _getdns_rbnode_t */ + _getdns_rbnode_t super; + listener *l; struct sockaddr_storage remote_in; socklen_t addrlen; @@ -88,14 +93,8 @@ struct connection { }; 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; - /************************************/ + /* struct tcp_connection is a sub struct of connection */ + connection super; int fd; getdns_eventloop_event event; @@ -118,10 +117,10 @@ static void tcp_connection_destroy(tcp_connection *conn) tcp_to_write *cur, *next; - if (!(mf = priv_getdns_context_mf(conn->l->set->context))) + if (!(mf = &conn->super.l->set->context->mf)) return; - if (getdns_context_get_eventloop(conn->l->set->context, &loop)) + if (getdns_context_get_eventloop(conn->super.l->set->context, &loop)) return; if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb) @@ -139,10 +138,14 @@ static void tcp_connection_destroy(tcp_connection *conn) return; /* Unlink this connection */ - if ((*conn->prev_next = conn->next)) - conn->next->prev_next = conn->prev_next; + (void) _getdns_rbtree_delete( + &conn->super.l->set->connections_set, conn); + DEBUG_SERVER("[connection del] count: %d\n", + (int)conn->super.l->set->connections_set.count); + if ((*conn->super.prev_next = conn->super.next)) + conn->super.next->prev_next = conn->super.prev_next; - free_listen_set_when_done(conn->l->set); + free_listen_set_when_done(conn->super.l->set); GETDNS_FREE(*mf, conn); } @@ -157,10 +160,10 @@ static void tcp_write_cb(void *userarg) assert(userarg); - if (!(mf = priv_getdns_context_mf(conn->l->set->context))) + if (!(mf = &conn->super.l->set->context->mf)) return; - if (getdns_context_get_eventloop(conn->l->set->context, &loop)) + if (getdns_context_get_eventloop(conn->super.l->set->context, &loop)) return; /* Reset tcp_connection idle timeout */ @@ -195,28 +198,30 @@ static void tcp_write_cb(void *userarg) DOWNSTREAM_IDLE_TIMEOUT, &conn->event); } -void -_getdns_cancel_reply(getdns_context *context, getdns_transaction_t request_id) +static void +_getdns_cancel_reply(getdns_context *context, connection *conn) { - /* 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; + tcp_connection *conn = (tcp_connection *)conn; 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))) { + (mf = &conn->l->set->context->mf)) { listen_set *set = conn->l->set; /* Unlink this connection */ + (void) _getdns_rbtree_delete( + &set->connections_set, conn); + DEBUG_SERVER("[connection del] count: %d\n", + (int)set->connections_set.count); if ((*conn->prev_next = conn->next)) conn->next->prev_next = conn->prev_next; GETDNS_FREE(*mf, conn); @@ -236,10 +241,21 @@ getdns_reply( size_t len; getdns_return_t r; - if (!context || !reply || !conn) + if (!context || !conn) return GETDNS_RETURN_INVALID_PARAMETER; - if (!(mf = priv_getdns_context_mf(conn->l->set->context))) + if (!context->server) + return GETDNS_RETURN_GENERIC_ERROR;; + + if (_getdns_rbtree_search(&context->server->connections_set, conn) + != &conn->super) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (!reply) { + _getdns_cancel_reply(context, conn); + return GETDNS_RETURN_GOOD; + } + if (!(mf = &conn->l->set->context->mf)) return GETDNS_RETURN_GENERIC_ERROR;; if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop))) @@ -260,6 +276,10 @@ getdns_reply( conn->l->fd = -1; } /* Unlink this connection */ + (void) _getdns_rbtree_delete( + &l->set->connections_set, conn); + DEBUG_SERVER("[connection del] count: %d\n", + (int)l->set->connections_set.count); if ((*conn->prev_next = conn->next)) conn->next->prev_next = conn->prev_next; @@ -320,10 +340,10 @@ static void tcp_read_cb(void *userarg) assert(userarg); - if (!(mf = priv_getdns_context_mf(conn->l->set->context))) + if (!(mf = &conn->super.l->set->context->mf)) return; - if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop))) + if ((r = getdns_context_get_eventloop(conn->super.l->set->context, &loop))) return; /* Reset tcp_connection idle timeout */ @@ -381,8 +401,8 @@ static void tcp_read_cb(void *userarg) conn->to_answer++; /* Call request handler */ - conn->l->set->handler( - conn->l->set->context, request_dict, (intptr_t)conn); + conn->super.l->set->handler( + conn->super.l->set->context, request_dict, (intptr_t)conn); conn->read_pos = conn->read_buf; conn->to_read = 2; @@ -402,7 +422,8 @@ static void tcp_timeout_cb(void *userarg) if (conn->to_answer) { getdns_eventloop *loop; - if (getdns_context_get_eventloop(conn->l->set->context, &loop)) + if (getdns_context_get_eventloop( + conn->super.l->set->context, &loop)) return; loop->vmt->clear(loop, &conn->event); @@ -423,7 +444,7 @@ static void tcp_accept_cb(void *userarg) assert(userarg); - if (!(mf = priv_getdns_context_mf(l->set->context))) + if (!(mf = &l->set->context->mf)) return; if ((r = getdns_context_get_eventloop(l->set->context, &loop))) @@ -433,11 +454,10 @@ static void tcp_accept_cb(void *userarg) 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) { + conn->super.l = l; + conn->super.addrlen = sizeof(conn->super.remote_in); + if ((conn->fd = accept(l->fd, (struct sockaddr *) + &conn->super.remote_in, &conn->super.addrlen)) == -1) { /* IO error, cleanup this listener */ loop->vmt->clear(loop, &l->event); close(l->fd); @@ -458,10 +478,20 @@ static void tcp_accept_cb(void *userarg) 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; + conn->super.super.key = conn; + if (!_getdns_rbtree_insert( + &l->set->connections_set, &conn->super.super)) { + /* Memory error */ + GETDNS_FREE(*mf, conn); + return; + } + DEBUG_SERVER("[connection add] count: %d\n", + (int)l->set->connections_set.count); + if ((conn->super.next = l->connections)) + conn->super.next->prev_next = &conn->super.next; + conn->super.prev_next = &l->connections; l->connections = (connection *)conn; + (void) loop->vmt->schedule(loop, conn->fd, DOWNSTREAM_IDLE_TIMEOUT, &conn->event); @@ -485,7 +515,7 @@ static void udp_read_cb(void *userarg) if (l->fd == -1) return; - if (!(mf = priv_getdns_context_mf(l->set->context))) + if (!(mf = &l->set->context->mf)) return; if ((r = getdns_context_get_eventloop(l->set->context, &loop))) @@ -574,6 +604,15 @@ static void udp_read_cb(void *userarg) else { /* Insert connection */ + conn->super.key = conn; + if (!_getdns_rbtree_insert( + &l->set->connections_set, &conn->super)) { + /* Memory error */ + GETDNS_FREE(*mf, conn); + return; + } + DEBUG_SERVER("[connection add] count: %d\n", + (int)l->set->connections_set.count); if ((conn->next = l->connections)) conn->next->prev_next = &conn->next; conn->prev_next = &l->connections; @@ -586,25 +625,6 @@ static void udp_read_cb(void *userarg) 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; @@ -613,7 +633,7 @@ static void free_listen_set_when_done(listen_set *set) assert(set); assert(set->context); - if (!(mf = priv_getdns_context_mf(set->context))) + if (!(mf = &set->context->mf)) return; DEBUG_SERVER("To free listen set: %p\n", set); @@ -639,7 +659,7 @@ static void remove_listeners(listen_set *set) assert(set); assert(set->context); - if (!(mf = priv_getdns_context_mf(set->context))) + if (!(mf = &set->context->mf)) return; if (getdns_context_get_eventloop(set->context, &loop)) @@ -663,7 +683,8 @@ static void remove_listeners(listen_set *set) while (*conn_p) { tcp_connection_destroy(*conn_p); if (*conn_p && (*conn_p)->to_answer > 0) - conn_p = (tcp_connection **)&(*conn_p)->next; + conn_p = (tcp_connection **) + &(*conn_p)->super.next; } } free_listen_set_when_done(set); @@ -681,7 +702,7 @@ static getdns_return_t add_listeners(listen_set *set) assert(set); assert(set->context); - if (!(mf = priv_getdns_context_mf(set->context))) + if (!(mf = &set->context->mf)) return GETDNS_RETURN_GENERIC_ERROR; if ((r = getdns_context_get_eventloop(set->context, &loop))) @@ -738,6 +759,12 @@ static getdns_return_t add_listeners(listen_set *set) return GETDNS_RETURN_GOOD; } +static int +ptr_cmp(const void *a, const void *b) +{ + return a == b ? 0 : (a < b ? -1 : 1); +} + getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, getdns_request_handler_t request_handler, const getdns_list *listen_addresses) @@ -747,8 +774,6 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, 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; @@ -761,9 +786,11 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, size_t i; struct addrinfo hints; - DEBUG_SERVER("getdns_context_set_listen_addresses(%p, %p, %p)\n", context, request_handler, + DEBUG_SERVER("getdns_context_set_listen_addresses(%p, %p, %p)\n", + context, request_handler, + listen_addresses); - if (!(mf = priv_getdns_context_mf(context))) + if (!(mf = &context->mf)) return GETDNS_RETURN_GENERIC_ERROR; if ((r = getdns_context_get_eventloop(context, &loop))) @@ -775,7 +802,7 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, else if ((r = getdns_list_get_length(listen_addresses, &new_set_count))) return r; - if ((current_set = lookup_listen_set(root, context))) { + if ((current_set = context->server)) { for (i = 0; i < current_set->count; i++) current_set->items[i].action = to_remove; } @@ -783,7 +810,7 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, if (!current_set) return GETDNS_RETURN_GOOD; - rm_listen_set(&root, current_set); + context->server = NULL; /* action is already to_remove */ remove_listeners(current_set); return GETDNS_RETURN_GOOD; @@ -796,10 +823,12 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, 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); + _getdns_rbtree_init(&new_set->connections_set, ptr_cmp); + + 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, @@ -938,10 +967,10 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, } } if (current_set) { - rm_listen_set(&root, current_set); + context->server = NULL; remove_listeners(current_set); /* Is already remove */ } - root = new_set; + context->server = new_set; return GETDNS_RETURN_GOOD; } diff --git a/src/test/getdns_context_set_listen_addresses.h b/src/server.h similarity index 70% rename from src/test/getdns_context_set_listen_addresses.h rename to src/server.h index fac16f48..f60f267e 100644 --- a/src/test/getdns_context_set_listen_addresses.h +++ b/src/server.h @@ -1,3 +1,11 @@ +/** + * \file server.h + * @brief Functions for serving requests + * + * getdns_context_set_listen_addresses() and getdns_reply() are implemented + * here. + */ + /* * Copyright (c) 2013, NLNet Labs, Verisign, Inc. * All rights reserved. @@ -24,25 +32,9 @@ * (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_SERVER_H_ +#define _GETDNS_SERVER_H_ -#ifndef GETDNS_CONTEXT_SET_LISTEN_ADDRESSES_H_ -#define GETDNS_CONTEXT_SET_LISTEN_ADDRESSES_H_ -#include "getdns/getdns.h" +struct listen_set; -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, - const 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 +#endif /* _GETDNS_SERVER_H_ */ diff --git a/src/test/Makefile.in b/src/test/Makefile.in index e3906eb8..a33ec15f 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -66,13 +66,10 @@ 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=getdns_context_set_listen_addresses.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 \ - $(DECOMPOSED_OBJS) + tests_stub_async.lo tests_stub_sync.lo NON_C99_OBJS=check_getdns_libuv.lo @@ -127,8 +124,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 $(DECOMPOSED_OBJS) - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(DECOMPOSED_OBJS) $(LDFLAGS) $(LDLIBS) +getdns_query: getdns_query.lo + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS) scratchpad: scratchpad.lo $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ scratchpad.lo $(LDFLAGS) $(LDLIBS) @@ -266,16 +263,8 @@ 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 $(srcdir)/../debug.h ../config.h getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - $(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns.h \ - ../getdns/getdns_extra.h + ../getdns/getdns.h ../getdns/getdns_extra.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 diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 6df3fdc9..2bc21332 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -27,7 +27,6 @@ #include "config.h" #include "debug.h" -#include "getdns_context_set_listen_addresses.h" #include #include #include @@ -1346,14 +1345,11 @@ static void request_cb( else if (n == 0) SERVFAIL("Recursion not available", 0, msg, &response); - if (!response) - /* No response, no reply */ - _getdns_cancel_reply(context, msg->request_id); - - else if ((r = getdns_reply(context, msg->request_id, response))) { + if ((r = getdns_reply(context, msg->request_id, response))) { fprintf(stderr, "Could not reply: %s\n", getdns_get_errorstr_by_id(r)); - _getdns_cancel_reply(context, msg->request_id); + /* Cancel reply */ + (void) getdns_reply(context, msg->request_id, NULL); } if (msg) { getdns_dict_destroy(msg->request); @@ -1510,14 +1506,11 @@ error: free(request_str); } while(0); #endif - if (!response) - /* No response, no reply */ - _getdns_cancel_reply(context, request_id); - - else if ((r = getdns_reply(context, request_id, response))) { + if ((r = getdns_reply(context, request_id, response))) { fprintf(stderr, "Could not reply: %s\n", getdns_get_errorstr_by_id(r)); - _getdns_cancel_reply(context, request_id); + /* Cancel reply */ + getdns_reply(context, request_id, NULL); } if (msg) { if (msg->request) From 9f7ceeded32ffe935a89015c876ac2932ec46c71 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 13 Jul 2016 15:28:08 +0200 Subject: [PATCH 13/13] Don't SSL_library_init() on every context create It will not be called when the second bit from the set_from_os parameter is set. This deals with issue #117 --- ChangeLog | 2 ++ src/context.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8459cd74..4dae9ffb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -40,6 +40,8 @@ * Bugfix: Build fails with autoconf 2.63, works with 2.68. Thanks Robert Groenenberg * Doxygen output for getdns.h and getdns_extra.h only + * Do not call SSL_library_init() from getdns_context_create() when + the second bit from the set_from_os parameter is set. * 2016-03-31: Version 1.0.0b1 * openssl 1.1.0 support diff --git a/src/context.c b/src/context.c index b46dc3bd..b0c9a198 100644 --- a/src/context.c +++ b/src/context.c @@ -1297,7 +1297,9 @@ getdns_context_create_with_extended_memory_functions( /* Unbound needs SSL to be init'ed this early when TLS is used. However we * don't know that till later so we will have to do this every time. */ - SSL_library_init(); + if (set_from_os & 2 == 0) + SSL_library_init(); + #ifdef HAVE_LIBUNBOUND result->unbound_ctx = NULL; if ((r = rebuild_ub_ctx(result)))