[asterisk-commits] file: branch group/dns_srv r433297 - in /team/group/dns_srv: include/asterisk...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 23 07:23:21 CDT 2015
Author: file
Date: Mon Mar 23 07:23:20 2015
New Revision: 433297
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433297
Log:
Add SRV recording parsing and sorting.
Modified:
team/group/dns_srv/include/asterisk/dns_internal.h
team/group/dns_srv/main/dns_core.c
team/group/dns_srv/main/dns_srv.c
Modified: team/group/dns_srv/include/asterisk/dns_internal.h
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_srv/include/asterisk/dns_internal.h?view=diff&rev=433297&r1=433296&r2=433297
==============================================================================
--- team/group/dns_srv/include/asterisk/dns_internal.h (original)
+++ team/group/dns_srv/include/asterisk/dns_internal.h Mon Mar 23 07:23:20 2015
@@ -44,14 +44,14 @@
struct ast_dns_srv_record {
/*! \brief Generic DNS record information */
struct ast_dns_record generic;
- /*! \brief The hostname in the SRV record */
- const char *host;
/*! \brief The priority of the SRV record */
unsigned short priority;
/*! \brief The weight of the SRV record */
unsigned short weight;
/*! \brief The port in the SRV record */
unsigned short port;
+ /*! \brief The hostname in the SRV record */
+ char host[0];
};
/*! \brief A NAPTR record */
@@ -82,7 +82,7 @@
/*! \brief Optional rcode, set if an error occurred */
unsigned int rcode;
/*! \brief Records returned */
- AST_LIST_HEAD_NOLOCK(, ast_dns_record) records;
+ AST_LIST_HEAD_NOLOCK(dns_records, ast_dns_record) records;
/*! \brief The canonical name */
const char *canonical;
/*! \brief The raw DNS answer */
@@ -147,3 +147,22 @@
* \return scheduler context
*/
struct ast_sched_context *ast_dns_get_sched(void);
+
+/*!
+ * \brief Allocate and parse a DNS SRV record
+ *
+ * \param query The DNS query
+ * \param data This specific SRV record
+ * \param size The size of the SRV record
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ */
+struct ast_dns_record *ast_dns_srv_alloc(struct ast_dns_query *query, const char *data, const size_t size);
+
+/*!
+ * \brief Sort the SRV records on a result
+ *
+ * \param result The DNS result
+ */
+void ast_dns_srv_sort(struct ast_dns_result *result);
Modified: team/group/dns_srv/main/dns_core.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_srv/main/dns_core.c?view=diff&rev=433297&r1=433296&r2=433297
==============================================================================
--- team/group/dns_srv/main/dns_core.c (original)
+++ team/group/dns_srv/main/dns_core.c Mon Mar 23 07:23:20 2015
@@ -583,6 +583,8 @@
if (rr_type == ns_t_naptr) {
record = naptr_record_alloc(query, data, size);
+ } else if (rr_type == ns_t_srv) {
+ record = ast_dns_srv_alloc(query, data, size);
} else {
record = generic_record_alloc(query, data, size);
}
@@ -604,6 +606,10 @@
void ast_dns_resolver_completed(struct ast_dns_query *query)
{
+ if (ast_dns_query_get_rr_type(query) == ns_t_srv) {
+ ast_dns_srv_sort(query->result);
+ }
+
query->callback(query);
}
Modified: team/group/dns_srv/main/dns_srv.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_srv/main/dns_srv.c?view=diff&rev=433297&r1=433296&r2=433297
==============================================================================
--- team/group/dns_srv/main/dns_srv.c (original)
+++ team/group/dns_srv/main/dns_srv.c Mon Mar 23 07:23:20 2015
@@ -31,25 +31,158 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
#include "asterisk/dns_core.h"
#include "asterisk/dns_srv.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/dns_internal.h"
+#include "asterisk/utils.h"
+
+struct ast_dns_record *ast_dns_srv_alloc(struct ast_dns_query *query, const char *data, const size_t size)
+{
+ const char *ptr = data;
+ size_t remaining = size;
+ struct ast_dns_srv_record *srv;
+ unsigned short priority;
+ unsigned short weight;
+ unsigned short port;
+ int host_size;
+ char host[256] = "";
+
+ if (remaining < 2) {
+ return NULL;
+ }
+ priority = (ptr[1] << 0) | (ptr[0] << 8);
+ ptr += 2;
+ remaining -= 2;
+
+ if (remaining < 2) {
+ return NULL;
+ }
+ weight = (ptr[1] << 0) | (ptr[0] << 8);
+ ptr += 2;
+ remaining -= 2;
+
+ if (remaining < 2) {
+ return NULL;
+ }
+ port = (ptr[1] << 0) | (ptr[0] << 8);
+ ptr += 2;
+
+ /* This currently assumes that the DNS core will provide a record within the full answer, which I'm going to talk to
+ * Mark about in a few hours
+ */
+ host_size = dn_expand((unsigned char *)query->result->answer, (unsigned char *) data, (unsigned char *) ptr, host, sizeof(host) - 1);
+ if (host_size < 0) {
+ ast_log(LOG_ERROR, "Failed to expand domain name: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ if (!strcmp(host, ".")) {
+ return NULL;
+ }
+
+ srv = ast_calloc(1, sizeof(*srv) + host_size + 1);
+ if (!srv) {
+ return NULL;
+ }
+
+ srv->priority = ntohs(priority);
+ srv->weight = ntohs(weight);
+ srv->port = ntohs(port);
+ strcpy(srv->host, host); /* SAFE */
+
+ return (struct ast_dns_record *)srv;
+}
+
+/* This implementation was taken from the existing srv.c which, after reading the RFC, implements it
+ * as it should.
+ */
+void ast_dns_srv_sort(struct ast_dns_result *result)
+{
+ struct ast_dns_record *current;
+ struct dns_records newlist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+
+ while (AST_LIST_FIRST(&result->records)) {
+ unsigned int random_weight;
+ unsigned int weight_sum;
+ unsigned short cur_priority = ((struct ast_dns_srv_record *)AST_LIST_FIRST(&result->records))->priority;
+ struct dns_records temp_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ weight_sum = 0;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&result->records, current, list) {
+ if (((struct ast_dns_srv_record *)current)->priority != cur_priority)
+ break;
+
+ AST_LIST_MOVE_CURRENT(&temp_list, list);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ while (AST_LIST_FIRST(&temp_list)) {
+ weight_sum = 0;
+
+ AST_LIST_TRAVERSE(&temp_list, current, list) {
+ weight_sum += ((struct ast_dns_srv_record *)current)->weight;
+ }
+
+ /* if all the remaining entries have weight == 0,
+ then just append them to the result list and quit */
+ if (weight_sum == 0) {
+ AST_LIST_APPEND_LIST(&newlist, &temp_list, list);
+ break;
+ }
+
+ random_weight = 1 + (unsigned int) ((float) weight_sum * (ast_random() / ((float) RAND_MAX + 1.0)));
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&temp_list, current, list) {
+ if (((struct ast_dns_srv_record *)current)->weight < random_weight)
+ continue;
+
+ AST_LIST_MOVE_CURRENT(&newlist, list);
+ break;
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+ }
+
+ }
+
+ /* now that the new list has been ordered,
+ put it in place */
+
+ AST_LIST_APPEND_LIST(&result->records, &newlist, list);
+}
const char *ast_dns_srv_get_host(const struct ast_dns_record *record)
{
- return NULL;
+ struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+ ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ return srv->host;
}
unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
{
- return 0;
+ struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+ ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ return srv->priority;
}
unsigned short ast_dns_srv_get_weight(const struct ast_dns_record *record)
{
- return 0;
+ struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+ ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ return srv->weight;
}
unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
{
- return 0;
-}
+ struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+ ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ return srv->port;
+}
More information about the asterisk-commits
mailing list