Author: mmichelson Date: Mon Mar 23 12:30:55 2015 New Revision: 433314 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433314 Log: Add sorting to DNS NAPTR records.
I modeled this after the method being done in the SRV branch. That is, I have an internal function that is defined in dns_naptr.c to sort the records. I opted to sort records after they are collected in order to make the code more uniform: SRV and NAPTR work the same way. In order to test this, I added some more NAPTR records to the nominal NAPTR resolution test and gave it a shot. This pointed to an error where I needed to cast to unsigned char when getting the order and preference from the NAPTR record. Modified: team/group/dns_naptr/include/asterisk/dns_internal.h team/group/dns_naptr/main/dns_core.c team/group/dns_naptr/main/dns_naptr.c team/group/dns_naptr/res/res_resolver_unbound.c Modified: team/group/dns_naptr/include/asterisk/dns_internal.h URL: http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/include/asterisk/dns_internal.h?view=diff&rev=433314&r1=433313&r2=433314 ============================================================================== --- team/group/dns_naptr/include/asterisk/dns_internal.h (original) +++ team/group/dns_naptr/include/asterisk/dns_internal.h Mon Mar 23 12:30:55 2015 @@ -147,3 +147,10 @@ * \return scheduler context */ struct ast_sched_context *ast_dns_get_sched(void); + +/*! + * \brief Sort the NAPTR records on a result + * + * \param result The DNS result + */ +void ast_dns_naptr_sort(struct ast_dns_result *result); Modified: team/group/dns_naptr/main/dns_core.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/main/dns_core.c?view=diff&rev=433314&r1=433313&r2=433314 ============================================================================== --- team/group/dns_naptr/main/dns_core.c (original) +++ team/group/dns_naptr/main/dns_core.c Mon Mar 23 12:30:55 2015 @@ -485,7 +485,7 @@ end_of_record = ptr + size; /* ORDER */ - order = (ptr[1] << 0) | (ptr[0] << 8); + order = ((unsigned char)(ptr[1]) << 0) | ((unsigned char)(ptr[0]) << 8); ptr += 2; if (ptr >= end_of_record) { @@ -493,7 +493,7 @@ } /* PREFERENCE */ - preference = (ptr[1] << 0) | (ptr[0] << 8); + preference = ((unsigned char) (ptr[1]) << 0) | ((unsigned char)(ptr[0]) << 8); ptr += 2; if (ptr >= end_of_record) { @@ -633,6 +633,9 @@ void ast_dns_resolver_completed(struct ast_dns_query *query) { + if (ast_dns_query_get_rr_type(query) == ns_t_naptr) { + ast_dns_naptr_sort(query->result); + } query->callback(query); } Modified: team/group/dns_naptr/main/dns_naptr.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/main/dns_naptr.c?view=diff&rev=433314&r1=433313&r2=433314 ============================================================================== --- team/group/dns_naptr/main/dns_naptr.c (original) +++ team/group/dns_naptr/main/dns_naptr.c Mon Mar 23 12:30:55 2015 @@ -38,6 +38,78 @@ #include "asterisk/linkedlists.h" #include "asterisk/dns_internal.h" #include "asterisk/utils.h" + +static int compare_order(const void *record1, const void *record2) +{ + const struct ast_dns_naptr_record **left = (const struct ast_dns_naptr_record **)record1; + const struct ast_dns_naptr_record **right = (const struct ast_dns_naptr_record **)record2; + + if ((*left)->order < (*right)->order) { + return -1; + } else if ((*left)->order > (*right)->order) { + return 1; + } else { + return 0; + } +} + +static int compare_preference(const void *record1, const void *record2) +{ + const struct ast_dns_naptr_record **left = (const struct ast_dns_naptr_record **)record1; + const struct ast_dns_naptr_record **right = (const struct ast_dns_naptr_record **)record2; + + if ((*left)->preference < (*right)->preference) { + return -1; + } else if ((*left)->preference > (*right)->preference) { + return 1; + } else { + return 0; + } +} + +void ast_dns_naptr_sort(struct ast_dns_result *result) +{ + struct ast_dns_record *current; + size_t num_records = 0; + struct ast_dns_naptr_record **records; + int i = 0; + int j = 0; + int cur_order; + + /* Determine the number of records */ + AST_LIST_TRAVERSE(&result->records, current, list) { + ++num_records; + } + + /* Allocate an array with that number of records */ + records = ast_alloca(num_records * sizeof(*records)); + + /* Move records from the list to the array */ + AST_LIST_TRAVERSE_SAFE_BEGIN(&result->records, current, list) { + records[i++] = (struct ast_dns_naptr_record *) current; + AST_LIST_REMOVE_CURRENT(list); + } + AST_LIST_TRAVERSE_SAFE_END; + + /* Sort the array by order */ + qsort(records, num_records, sizeof(*records), compare_order); + + /* Sort subarrays by preference */ + for (i = 0; i < num_records; i = j) { + cur_order = records[i]->order; + for (j = i + 1; j < num_records; ++j) { + if (records[j]->order != cur_order) { + break; + } + } + qsort(&records[i], j - i, sizeof(*records), compare_preference); + } + + /* Place sorted records back into the original list */ + for (i = 0; i < num_records; ++i) { + AST_LIST_INSERT_TAIL(&result->records, (struct ast_dns_record *)(records[i]), list); + } +} const char *ast_dns_naptr_get_flags(const struct ast_dns_record *record) { Modified: team/group/dns_naptr/res/res_resolver_unbound.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/res/res_resolver_unbound.c?view=diff&rev=433314&r1=433313&r2=433314 ============================================================================== --- team/group/dns_naptr/res/res_resolver_unbound.c (original) +++ team/group/dns_naptr/res/res_resolver_unbound.c Mon Mar 23 12:30:55 2015 @@ -1210,7 +1210,10 @@ ub_ctx_zone_add(resolver->context, DOMAIN1, "static"); - ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 100 100 A \"Fake service\" \"\" goose.down"); + ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 200 200 A \"Fake service\" \"\" goose.down"); + ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 200 100 A \"Fake service\" \"\" duck.down"); + ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 100 200 A \"Fake service\" \"\" pheasant.down"); + ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 100 100 A \"Fake service\" \"\" platypus.fur"); if (ast_dns_resolve(DOMAIN1, ns_t_naptr, ns_c_in, &result)) { ast_test_status_update(test, "Failed to resolve domain\n"); @@ -1228,16 +1231,18 @@ return AST_TEST_FAIL; } - /* XXX This just prints data for my own inspection right now. It will need to actually - * perform a check in order to really pass. This will be done once more NAPTR records - * are added so I can check ordering as well as individual data - */ - ast_log(LOG_NOTICE, "order is %hu\n", ast_dns_naptr_get_order(record)); - ast_log(LOG_NOTICE, "preference is %hu\n", ast_dns_naptr_get_preference(record)); - ast_log(LOG_NOTICE, "flags is %s\n", ast_dns_naptr_get_flags(record)); - ast_log(LOG_NOTICE, "service is %s\n", ast_dns_naptr_get_service(record)); - ast_log(LOG_NOTICE, "regexp is %s\n", ast_dns_naptr_get_regexp(record)); - ast_log(LOG_NOTICE, "replacement is %s\n", ast_dns_naptr_get_replacement(record)); + for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) { + /* XXX This just prints data for my own inspection right now. It will need to actually + * perform a check in order to really pass. This will be done once more NAPTR records + * are added so I can check ordering as well as individual data + */ + ast_log(LOG_NOTICE, "order is %hu\n", ast_dns_naptr_get_order(record)); + ast_log(LOG_NOTICE, "preference is %hu\n", ast_dns_naptr_get_preference(record)); + ast_log(LOG_NOTICE, "flags is %s\n", ast_dns_naptr_get_flags(record)); + ast_log(LOG_NOTICE, "service is %s\n", ast_dns_naptr_get_service(record)); + ast_log(LOG_NOTICE, "regexp is %s\n", ast_dns_naptr_get_regexp(record)); + ast_log(LOG_NOTICE, "replacement is %s\n", ast_dns_naptr_get_replacement(record)); + } return AST_TEST_PASS; -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits