diff --git a/src/context.c b/src/context.c index 847fb041..37f056bf 100644 --- a/src/context.c +++ b/src/context.c @@ -1309,6 +1309,7 @@ getdns_context_create_with_extended_memory_functions( result->header = NULL; result->add_opt_parameters = NULL; result->add_warning_for_bad_dns = 0; + result->dns64 = 0; result->dnssec_return_all_statuses = 0; result->dnssec_return_full_validation_chain = 0; result->dnssec_return_only_secure = 0; @@ -1321,6 +1322,7 @@ getdns_context_create_with_extended_memory_functions( result->return_api_information = 0; result->return_both_v4_and_v6 = 0; result->return_call_reporting = 0; + (void) memset(result->dns64_prefix, 0, 16); result->specify_class = GETDNS_RRCLASS_IN; /* state data used to detect changes to the system config files @@ -4036,6 +4038,7 @@ _getdns_context_config_setting(getdns_context *context, getdns_return_t r = GETDNS_RETURN_GOOD; getdns_dict *dict; getdns_list *list; + getdns_bindata *bindata; getdns_namespace_t namespaces[100]; getdns_transport_list_t dns_transport_list[100]; size_t count, i; @@ -4081,6 +4084,7 @@ _getdns_context_config_setting(getdns_context *context, /**** ****/ /**************************************/ EXTENSION_SETTING_BOOL(add_warning_for_bad_dns) + EXTENSION_SETTING_BOOL(dns64) EXTENSION_SETTING_BOOL(dnssec_return_all_statuses) EXTENSION_SETTING_BOOL(dnssec_return_full_validation_chain) EXTENSION_SETTING_BOOL(dnssec_return_only_secure) @@ -4097,13 +4101,25 @@ _getdns_context_config_setting(getdns_context *context, 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 (!(r = getdns_dict_get_dict(config_dict, + "add_opt_parameters", &dict))) { if (context->add_opt_parameters) - getdns_dict_destroy(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); + r = _getdns_dict_copy( + dict, &context->add_opt_parameters); } + } else if (_streq(setting, "dns64_prefix")) { + if (!(r = getdns_dict_get_bindata(config_dict, "dns64_prefix", + &bindata))) { + if (bindata->size != 16) + r = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + else + (void) memcpy(context->dns64_prefix, + bindata->data, 16); + } } else if (_streq(setting, "header")) { if (!(r = getdns_dict_get_dict(config_dict, "header" , &dict))) { if (context->header) diff --git a/src/context.h b/src/context.h index 84a2c40c..c6288965 100644 --- a/src/context.h +++ b/src/context.h @@ -301,6 +301,7 @@ struct getdns_context { getdns_dict *header; getdns_dict *add_opt_parameters; int add_warning_for_bad_dns : 1; + int dns64 : 1; int dnssec_return_all_statuses : 1; int dnssec_return_full_validation_chain : 1; int dnssec_return_only_secure : 1; @@ -314,6 +315,7 @@ struct getdns_context { int return_both_v4_and_v6 : 1; int return_call_reporting : 1; uint16_t specify_class; + uint8_t dns64_prefix[16]; /* * state data used to detect changes to the system config files diff --git a/src/general.c b/src/general.c index 99e4cff5..882a0ba2 100644 --- a/src/general.c +++ b/src/general.c @@ -360,6 +360,8 @@ validate_extensions(struct getdns_dict * extensions) static getdns_extension_format extformats[] = { {"add_opt_parameters" , t_dict, 1}, {"add_warning_for_bad_dns" , t_int , 1}, + {"dns64" , t_int , 1}, + {"dns64_prefix" , t_bindata, 1}, {"dnssec_return_all_statuses" , t_int , 1}, {"dnssec_return_full_validation_chain", t_int , 1}, {"dnssec_return_only_secure" , t_int , 1}, diff --git a/src/request-internal.c b/src/request-internal.c index 141f977a..66e14656 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -720,6 +720,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, getdns_dns_req *result = NULL; uint32_t klass = context->specify_class; + getdns_bindata *dns64_prefix = NULL; int a_aaaa_query = is_extension_set(extensions, "return_both_v4_and_v6", context->return_both_v4_and_v6) && ( request_type == GETDNS_RRTYPE_A || @@ -908,6 +909,12 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, "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); + + result->dns64 = is_extension_set(extensions, "dns64", context->dns64); + if (!getdns_dict_get_bindata(extensions, "dns64_prefix", &dns64_prefix) + && dns64_prefix->size == 16) + (void) memcpy(result->dns64_prefix, dns64_prefix->data, 16); + else (void) memcpy(result->dns64_prefix, context->dns64_prefix, 16); /* will be set by caller */ result->user_pointer = NULL; diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 7acc77d9..f5d19fc3 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -164,6 +164,8 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\ntsig spec: [:]:\n"); fprintf(out, "\nextensions:\n"); fprintf(out, "\t+add_warning_for_bad_dns\n"); + fprintf(out, "\t+dns64\n"); + fprintf(out, "\t+dns64_prefix=\n"); fprintf(out, "\t+dnssec_return_status\n"); fprintf(out, "\t+dnssec_return_only_secure\n"); fprintf(out, "\t+dnssec_return_all_statuses\n"); @@ -477,10 +479,10 @@ getdns_return_t parse_args(int argc, char **argv) int t, print_api_info = 0, print_trust_anchors = 0; getdns_list *upstream_list = NULL; getdns_list *tas = NULL, *hints = NULL; - getdns_dict *pubkey_pin = NULL; + getdns_dict *pubkey_pin = NULL, *addr_dict; getdns_list *suffixes; char *suffix; - getdns_bindata bindata; + getdns_bindata bindata, *address; size_t upstream_count = 0; FILE *fh; char *config_file = NULL; @@ -508,6 +510,14 @@ getdns_return_t parse_args(int argc, char **argv) fprintf(stderr, "Unknown class: %s\n", arg+15); + } else if (strncmp(arg+1, "dns64_prefix=", 13) == 0) { + if (!(r = getdns_str2dict(arg+14, &addr_dict)) + && !(r = getdns_dict_get_bindata( + addr_dict, "address_data", &address))) { + r = getdns_dict_set_bindata(extensions, + "dns64_prefix", address); + getdns_dict_destroy(addr_dict); + } } else if (arg[1] == '0') { /* Unset all existing extensions*/ getdns_dict_destroy(extensions); diff --git a/src/types-internal.h b/src/types-internal.h index f6c3cf5b..1ccadcf4 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -289,6 +289,7 @@ typedef struct getdns_dns_req { int canceled : 1; /* request extensions */ + int dns64 : 1; int dnssec_return_status : 1; int dnssec_return_only_secure : 1; int dnssec_return_all_statuses : 1; @@ -318,6 +319,8 @@ typedef struct getdns_dns_req { int validating : 1; int *freed; + /* Non boolean request extensions */ + uint8_t dns64_prefix[16]; uint16_t tls_query_padding_blocksize; /* internally scheduled request */