Asterisk - The Open Source Telephony Project GIT-master-f3e88d3
Data Structures | Functions
dns_internal.h File Reference

Internal DNS structure definitions. More...

#include "asterisk/linkedlists.h"
#include "asterisk/vector.h"
#include "asterisk/dns_query_set.h"
Include dependency graph for dns_internal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_dns_naptr_record
 A NAPTR record. More...
 
struct  ast_dns_query
 A DNS query. More...
 
struct  ast_dns_query_active
 An active DNS query. More...
 
struct  ast_dns_query_recurring
 A recurring DNS query. More...
 
struct  ast_dns_query_set
 A set of DNS queries. More...
 
struct  ast_dns_record
 For AST_LIST. More...
 
struct  ast_dns_result
 The result of a DNS query. More...
 
struct  ast_dns_srv_record
 An SRV record. More...
 
struct  ast_dns_txt_record
 A TXT record. More...
 
struct  dns_query_set_query
 A DNS query set query, which includes its state. More...
 
struct  ast_dns_result::dns_records
 Records returned. More...
 

Functions

struct ast_sched_contextast_dns_get_sched (void)
 Retrieve the DNS scheduler context. More...
 
char * dns_find_record (const char *record, size_t record_size, const char *response, size_t response_size)
 Find the location of a DNS record within the entire DNS answer. More...
 
struct ast_dns_recorddns_naptr_alloc (struct ast_dns_query *query, const char *data, const size_t size)
 Allocate and parse a DNS NAPTR record. More...
 
void dns_naptr_sort (struct ast_dns_result *result)
 Sort the NAPTR records on a result. More...
 
int dns_parse_short (unsigned char *cur, uint16_t *val)
 Parse a 16-bit unsigned value from a DNS record. More...
 
int dns_parse_string (char *cur, uint8_t *size, char **val)
 Parse a DNS string from a DNS record. More...
 
struct ast_dns_querydns_query_alloc (const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
 Allocate a DNS query (but do not start resolution) More...
 
struct ast_dns_recorddns_srv_alloc (struct ast_dns_query *query, const char *data, const size_t size)
 Allocate and parse a DNS SRV record. More...
 
void dns_srv_sort (struct ast_dns_result *result)
 Sort the SRV records on a result. More...
 
struct ast_dns_recorddns_txt_alloc (struct ast_dns_query *query, const char *data, const size_t size)
 Allocate and parse a DNS TXT record. More...
 

Detailed Description

Internal DNS structure definitions.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file dns_internal.h.

Function Documentation

◆ ast_dns_get_sched()

struct ast_sched_context * ast_dns_get_sched ( void  )

Retrieve the DNS scheduler context.

Returns
scheduler context

Definition at line 52 of file dns_core.c.

53{
54 return sched;
55}
static struct ast_sched_context * sched
Definition: dns_core.c:50

References sched.

Referenced by ast_dns_resolve_recurring(), ast_dns_resolve_recurring_cancel(), and dns_query_recurring_resolution_callback().

◆ dns_find_record()

char * dns_find_record ( const char *  record,
size_t  record_size,
const char *  response,
size_t  response_size 
)

Find the location of a DNS record within the entire DNS answer.

The DNS record that has been returned by the resolver may be a copy of the record that was found in the complete DNS response. If so, then some DNS record types (specifically those that parse domains) will need to locate the DNS record within the complete DNS response. This is so that if the domain contains pointers to other sections of the DNS response, then the referenced domains may be located.

Parameters
recordThe DNS record returned by a resolver implementation
record_sizeThe size of the DNS record in bytes
responseThe complete DNS answer
response_sizeThe size of the complete DNS response

Definition at line 701 of file dns_core.c.

702{
703 size_t remaining_size = response_size;
704 const char *search_base = response;
705 char *record_offset;
706
707 while (1) {
708 record_offset = memchr(search_base, record[0], remaining_size);
709
710 ast_assert(record_offset != NULL);
711 ast_assert(search_base + remaining_size - record_offset >= record_size);
712
713 if (!memcmp(record_offset, record, record_size)) {
714 return record_offset;
715 }
716
717 remaining_size -= record_offset - search_base;
718 search_base = record_offset + 1;
719 }
720}
#define NULL
Definition: resample.c:96
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, and NULL.

Referenced by dns_naptr_alloc(), and dns_srv_alloc().

◆ dns_naptr_alloc()

struct ast_dns_record * dns_naptr_alloc ( struct ast_dns_query query,
const char *  data,
const size_t  size 
)

Allocate and parse a DNS NAPTR record.

Parameters
queryThe DNS query
dataThis specific NAPTR record
sizeThe size of the NAPTR record
Return values
non-NULLsuccess
NULLfailure

Definition at line 380 of file dns_naptr.c.

381{
383 char *ptr = NULL;
384 uint16_t order;
385 uint16_t preference;
386 uint8_t flags_size;
387 char *flags;
388 uint8_t services_size;
389 char *services;
390 uint8_t regexp_size;
391 char *regexp;
392 char replacement[256] = "";
393 int replacement_size;
394 const char *end_of_record;
395 enum flags_result flags_res;
396 size_t naptr_len;
397
398 ptr = dns_find_record(data, size, query->result->answer, query->result->answer_size);
399 ast_assert(ptr != NULL);
400
401 end_of_record = ptr + size;
402
403 /* ORDER */
404 /* This assignment takes a big-endian 16-bit value and stores it in the
405 * machine's native byte order. Using this method allows us to avoid potential
406 * alignment issues in case the order is not on a short-addressable boundary.
407 * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
408 * more information
409 */
410 ptr += dns_parse_short((unsigned char *) ptr, &order);
411 if (PAST_END_OF_RECORD) {
412 return NULL;
413 }
414
415 /* PREFERENCE */
416 ptr += dns_parse_short((unsigned char *) ptr, &preference);
417 if (PAST_END_OF_RECORD) {
418 return NULL;
419 }
420
421 /* FLAGS */
422 ptr += dns_parse_string(ptr, &flags_size, &flags);
423 if (PAST_END_OF_RECORD) {
424 return NULL;
425 }
426
427 /* SERVICES */
428 ptr += dns_parse_string(ptr, &services_size, &services);
429 if (PAST_END_OF_RECORD) {
430 return NULL;
431 }
432
433 /* REGEXP */
434 ptr += dns_parse_string(ptr, &regexp_size, &regexp);
435 if (PAST_END_OF_RECORD) {
436 return NULL;
437 }
438
439 /*
440 * The return value from dn_expand represents the size of the replacement
441 * in the buffer which MAY be compressed. Since the expanded replacement
442 * is NULL terminated, you can use strlen() to get the expanded size.
443 */
444 replacement_size = dn_expand((unsigned char *)query->result->answer,
445 (unsigned char *) end_of_record, (unsigned char *) ptr,
446 replacement, sizeof(replacement) - 1);
447 if (replacement_size < 0) {
448 ast_log(LOG_ERROR, "Failed to expand domain name: %s\n", strerror(errno));
449 return NULL;
450 }
451
452 ptr += replacement_size;
453
454 if (ptr != end_of_record) {
455 ast_log(LOG_ERROR, "NAPTR record gave undersized string indications.\n");
456 return NULL;
457 }
458
459 /* We've validated the size of the NAPTR record. Now we can validate
460 * the individual parts
461 */
462 flags_res = interpret_flags(flags, flags_size);
463 if (flags_res == FLAGS_INVALID) {
464 ast_log(LOG_ERROR, "NAPTR Record contained invalid flags %.*s\n", flags_size, flags);
465 return NULL;
466 }
467
468 if (services_invalid(services, services_size)) {
469 ast_log(LOG_ERROR, "NAPTR record contained invalid services %.*s\n", services_size, services);
470 return NULL;
471 }
472
473 if (regexp_invalid(regexp, regexp_size)) {
474 ast_log(LOG_ERROR, "NAPTR record contained invalid regexp %.*s\n", regexp_size, regexp);
475 return NULL;
476 }
477
478 /* replacement_size takes into account the NULL label, so a NAPTR record with no replacement
479 * will have a replacement_size of 1.
480 */
481 if (regexp_size && replacement_size > 1) {
482 ast_log(LOG_ERROR, "NAPTR record contained both a regexp and replacement\n");
483 return NULL;
484 }
485
486 naptr_len = sizeof(*naptr) + size + flags_size + 1 + services_size + 1
487 + regexp_size + 1 + strlen(replacement) + 1;
488 naptr = ast_calloc(1, naptr_len);
489 if (!naptr) {
490 return NULL;
491 }
492
493 naptr->order = order;
494 naptr->preference = preference;
495
496 ptr = naptr->data;
497 ptr += size;
498
499 strncpy(ptr, flags, flags_size);
500 ptr[flags_size] = '\0';
501 naptr->flags = ptr;
502 ptr += flags_size + 1;
503
504 strncpy(ptr, services, services_size);
505 ptr[services_size] = '\0';
506 naptr->service = ptr;
507 ptr += services_size + 1;
508
509 strncpy(ptr, regexp, regexp_size);
510 ptr[regexp_size] = '\0';
511 naptr->regexp = ptr;
512 ptr += regexp_size + 1;
513
514 strcpy(ptr, replacement);
515 naptr->replacement = ptr;
516
517 naptr->generic.data_ptr = naptr->data;
518
519 return (struct ast_dns_record *)naptr;
520}
integer order
Definition: analys.c:66
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
char * dns_find_record(const char *record, size_t record_size, const char *response, size_t response_size)
Find the location of a DNS record within the entire DNS answer.
Definition: dns_core.c:701
int dns_parse_short(unsigned char *cur, uint16_t *val)
Parse a 16-bit unsigned value from a DNS record.
Definition: dns_core.c:722
int dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
Definition: dns_core.c:734
#define PAST_END_OF_RECORD
Definition: dns_naptr.c:378
static int services_invalid(const char *services, uint8_t services_size)
Analyze NAPTR services for validity as defined by RFC 3404.
Definition: dns_naptr.c:130
static int regexp_invalid(const char *regexp, uint8_t regexp_size)
Determine if the regexp in a NAPTR record is invalid.
Definition: dns_naptr.c:309
static enum flags_result interpret_flags(const char *flags, uint8_t flags_size)
Analyze and interpret NAPTR flags as per RFC 3404.
Definition: dns_naptr.c:66
flags_result
Result of analyzing NAPTR flags on a record.
Definition: dns_naptr.c:46
@ FLAGS_INVALID
Definition: dns_naptr.c:54
#define LOG_ERROR
int errno
A NAPTR record.
Definition: dns_internal.h:92
unsigned short preference
The preference of the NAPTR record.
Definition: dns_internal.h:106
const char * regexp
The regular expression from the NAPTR record.
Definition: dns_internal.h:100
char data[0]
Buffer for NAPTR-specific data.
Definition: dns_internal.h:113
const char * flags
The flags from the NAPTR record.
Definition: dns_internal.h:96
const char * replacement
The replacement from the NAPTR record.
Definition: dns_internal.h:102
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
For AST_LIST.
Definition: dns_internal.h:39
size_t answer_size
The size of the raw DNS answer.
Definition: dns_internal.h:131
const char * answer
The raw DNS answer.
Definition: dns_internal.h:129
Definition: enum.h:30
unsigned short order
Definition: enum.h:31

References ast_dns_result::answer, ast_dns_result::answer_size, ast_assert, ast_calloc, ast_log, ast_dns_naptr_record::data, dns_find_record(), dns_parse_short(), dns_parse_string(), errno, ast_dns_naptr_record::flags, FLAGS_INVALID, interpret_flags(), LOG_ERROR, NULL, order, naptr::order, PAST_END_OF_RECORD, ast_dns_naptr_record::preference, ast_dns_naptr_record::regexp, regexp_invalid(), ast_dns_naptr_record::replacement, ast_dns_query::result, and services_invalid().

◆ dns_naptr_sort()

void dns_naptr_sort ( struct ast_dns_result result)

Sort the NAPTR records on a result.

Parameters
resultThe DNS result

Definition at line 551 of file dns_naptr.c.

552{
553 struct ast_dns_record *current;
554 size_t num_records = 0;
556 int i = 0;
557 int j = 0;
558 int cur_order;
559
560 /* Determine the number of records */
561 AST_LIST_TRAVERSE(&result->records, current, list) {
562 ++num_records;
563 }
564
565 /* No point in continuing if there are no records */
566 if (num_records == 0) {
567 return;
568 }
569
570 /* Allocate an array with that number of records */
571 records = ast_alloca(num_records * sizeof(*records));
572
573 /* Move records from the list to the array */
575 records[i++] = (struct ast_dns_naptr_record *) current;
577 }
579
580 /* Sort the array by order */
581 qsort(records, num_records, sizeof(*records), compare_order);
582
583 /* Sort subarrays by preference */
584 for (i = 0; i < num_records; i = j) {
585 cur_order = records[i]->order;
586 for (j = i + 1; j < num_records; ++j) {
587 if (records[j]->order != cur_order) {
588 break;
589 }
590 }
591 qsort(&records[i], j - i, sizeof(*records), compare_preference);
592 }
593
594 /* Place sorted records back into the original list */
595 for (i = 0; i < num_records; ++i) {
596 AST_LIST_INSERT_TAIL(&result->records, (struct ast_dns_record *)(records[i]), list);
597 }
598}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
static int records
Definition: cdr_pgsql.c:78
static PGresult * result
Definition: cel_pgsql.c:84
static int compare_order(const void *record1, const void *record2)
Definition: dns_naptr.c:523
static int compare_preference(const void *record1, const void *record2)
Definition: dns_naptr.c:537
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
size_t current
Definition: main/cli.c:113

References ast_alloca, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, compare_order(), compare_preference(), current, order, records, and result.

◆ dns_parse_short()

int dns_parse_short ( unsigned char *  cur,
uint16_t *  val 
)

Parse a 16-bit unsigned value from a DNS record.

Parameters
curPointer to the location of the 16-bit value in the DNS record
[out]valThe parsed 16-bit unsigned integer
Returns
The number of bytes consumed while parsing

Definition at line 722 of file dns_core.c.

723{
724 /* This assignment takes a big-endian 16-bit value and stores it in the
725 * machine's native byte order. Using this method allows us to avoid potential
726 * alignment issues in case the order is not on a short-addressable boundary.
727 * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
728 * more information
729 */
730 *val = (cur[1] << 0) | (cur[0] << 8);
731 return sizeof(*val);
732}
Definition: ast_expr2.c:325

Referenced by dns_naptr_alloc(), and dns_srv_alloc().

◆ dns_parse_string()

int dns_parse_string ( char *  cur,
uint8_t *  size,
char **  val 
)

Parse a DNS string from a DNS record.

A DNS string consists of an 8-bit size, followed by the string value (not NULL-terminated).

Parameters
curPointer to the location of the DNS string
[out]sizeThe parsed size of the DNS string
[out]valThe contained string (not NULL-terminated)
Returns
The number of bytes consumed while parsing

Definition at line 734 of file dns_core.c.

735{
736 *size = *cur++;
737 *val = cur;
738 return *size + 1;
739}

Referenced by dns_naptr_alloc().

◆ dns_query_alloc()

struct ast_dns_query * dns_query_alloc ( const char *  name,
int  rr_type,
int  rr_class,
ast_dns_resolve_callback  callback,
void *  data 
)

Allocate a DNS query (but do not start resolution)

Parameters
nameThe name of what to resolve
rr_typeResource record type
rr_classResource record class
callbackThe callback to invoke upon completion
dataUser data to make available on the query
Return values
non-NULLsuccess
NULLfailure
Note
The result passed to the callback does not need to be freed
The user data MUST be an ao2 object
This function increments the reference count of the user data, it does NOT steal
The query must be released upon completion or cancellation using ao2_ref

Definition at line 193 of file dns_core.c.

194{
195 struct ast_dns_query *query;
196
197 if (ast_strlen_zero(name)) {
198 ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n");
199 return NULL;
200 } else if (rr_type > 65536) {
201 ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
202 name, rr_type);
203 return NULL;
204 } else if (rr_type < 0) {
205 ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
206 name, rr_type);
207 return NULL;
208 } else if (rr_class > 65536) {
209 ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
210 name, rr_class);
211 return NULL;
212 } else if (rr_class < 0) {
213 ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource class '%d'\n",
214 name, rr_class);
215 return NULL;
216 } else if (!callback) {
217 ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', no callback provided\n",
218 name);
219 return NULL;
220 }
221
222 query = ao2_alloc_options(sizeof(*query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
223 if (!query) {
224 return NULL;
225 }
226
227 query->callback = callback;
228 query->user_data = ao2_bump(data);
229 query->rr_type = rr_type;
230 query->rr_class = rr_class;
231 strcpy(query->name, name); /* SAFE */
232
236
237 if (!query->resolver) {
238 ast_log(LOG_ERROR, "Attempted to do a DNS query for '%s' of class '%d' and type '%d' but no resolver is available\n",
240 ao2_ref(query, -1);
241 return NULL;
242 }
243
244 return query;
245}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static void dns_query_destroy(void *data)
Destructor for a DNS query.
Definition: dns_core.c:184
static const char name[]
Definition: format_mp3.c:68
#define LOG_WARNING
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_FIRST
Definition: linkedlists.h:423
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
A DNS query.
Definition: dns_internal.h:137
void * user_data
User-specific data.
Definition: dns_internal.h:141
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:139
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
int rr_class
Resource record class.
Definition: dns_internal.h:151
int rr_type
Resource record type.
Definition: dns_internal.h:149
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:153

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, ao2_ref, ast_log, AST_RWLIST_FIRST, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strlen_zero(), ast_dns_query::callback, dns_query_destroy(), LOG_ERROR, LOG_WARNING, ast_dns_query::name, name, NULL, ast_dns_query::resolver, ast_dns_query::rr_class, ast_dns_query::rr_type, and ast_dns_query::user_data.

Referenced by ast_dns_query_set_add(), ast_dns_resolve_async(), and dns_query_recurring_resolution_callback().

◆ dns_srv_alloc()

struct ast_dns_record * dns_srv_alloc ( struct ast_dns_query query,
const char *  data,
const size_t  size 
)

Allocate and parse a DNS SRV record.

Parameters
queryThe DNS query
dataThis specific SRV record
sizeThe size of the SRV record
Return values
non-NULLsuccess
NULLfailure

Definition at line 42 of file dns_srv.c.

43{
44 uint16_t priority;
45 uint16_t weight;
46 uint16_t port;
47 const char *ptr;
48 const char *end_of_record;
49 struct ast_dns_srv_record *srv;
50 int host_size;
51 char host[NI_MAXHOST] = "";
52 size_t host_len;
53
54 ptr = dns_find_record(data, size, query->result->answer, query->result->answer_size);
55 ast_assert(ptr != NULL);
56
57 end_of_record = ptr + size;
58
59 /* PRIORITY */
60 ptr += dns_parse_short((unsigned char *) ptr, &priority);
61 if (ptr >= end_of_record) {
62 return NULL;
63 }
64
65 /* WEIGHT */
66 ptr += dns_parse_short((unsigned char *) ptr, &weight);
67 if (ptr >= end_of_record) {
68 return NULL;
69 }
70
71 /* PORT */
72 ptr += dns_parse_short((unsigned char *) ptr, &port);
73 if (ptr >= end_of_record) {
74 return NULL;
75 }
76
77 /*
78 * The return value from dn_expand represents the size of the replacement
79 * in the buffer which MAY be compressed. Since the expanded replacement
80 * is NULL terminated, you can use strlen() to get the expanded size.
81 */
82 host_size = dn_expand((unsigned char *)query->result->answer,
83 (unsigned char *) end_of_record, (unsigned char *) ptr, host, sizeof(host) - 1);
84 if (host_size < 0) {
85 ast_log(LOG_ERROR, "Failed to expand domain name: %s\n", strerror(errno));
86 return NULL;
87 }
88
89 if (!strcmp(host, ".")) {
90 return NULL;
91 }
92
93 host_len = strlen(host) + 1;
94 srv = ast_calloc(1, sizeof(*srv) + size + host_len);
95 if (!srv) {
96 return NULL;
97 }
98
99 srv->priority = priority;
100 srv->weight = weight;
101 srv->port = port;
102
103 srv->host = srv->data + size;
104 ast_copy_string((char *)srv->host, host, host_len); /* SAFE */
105 srv->generic.data_ptr = srv->data;
106
107 return (struct ast_dns_record *)srv;
108}
char weight
static int priority
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58
An SRV record.
Definition: dns_internal.h:74
struct ast_dns_record generic
Generic DNS record information.
Definition: dns_internal.h:76
unsigned short weight
The weight of the SRV record.
Definition: dns_internal.h:82
unsigned short priority
The priority of the SRV record.
Definition: dns_internal.h:80
char data[0]
Additional data.
Definition: dns_internal.h:88
unsigned short port
The port in the SRV record.
Definition: dns_internal.h:84
const char * host
The hostname in the SRV record.
Definition: dns_internal.h:78

References ast_dns_result::answer, ast_dns_result::answer_size, ast_assert, ast_calloc, ast_copy_string(), ast_log, ast_dns_srv_record::data, ast_dns_record::data_ptr, dns_find_record(), dns_parse_short(), errno, ast_dns_srv_record::generic, ast_dns_srv_record::host, LOG_ERROR, NULL, ast_dns_srv_record::port, priority, ast_dns_srv_record::priority, ast_dns_query::result, weight, and ast_dns_srv_record::weight.

◆ dns_srv_sort()

void dns_srv_sort ( struct ast_dns_result result)

Sort the SRV records on a result.

Parameters
resultThe DNS result

Definition at line 113 of file dns_srv.c.

114{
115 struct ast_dns_record *current;
116 struct dns_records newlist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
117
118 while (AST_LIST_FIRST(&result->records)) {
119 unsigned short cur_priority = ((struct ast_dns_srv_record *)(AST_LIST_FIRST(&result->records)))->priority;
120 struct dns_records temp_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
121
122 /* Find the lowest current priority to work on, but if the priority is already zero there is no lower priority */
123 if (cur_priority) {
124 AST_LIST_TRAVERSE(&result->records, current, list) {
125 if (((struct ast_dns_srv_record *)current)->priority < cur_priority) {
126 cur_priority = ((struct ast_dns_srv_record *)current)->priority;
127 }
128 }
129 }
130
131 /* Find all records which match this priority */
133 if (((struct ast_dns_srv_record *)current)->priority != cur_priority) {
134 continue;
135 }
136
138
139 /* Records with a weight of zero must always be at the head */
140 if (((struct ast_dns_srv_record *)current)->weight == 0) {
141 AST_LIST_INSERT_HEAD(&temp_list, current, list);
142 } else {
143 AST_LIST_INSERT_TAIL(&temp_list, current, list);
144 }
145 }
147
148 /* Apply weighting - as each record is passed the sum of all previous weights (plus its own) is stored away, and then a random weight
149 * is calculated. The first record with a weight sum greater than the random weight is put in the new list and the whole thing starts
150 * once again.
151 */
152 while (AST_LIST_FIRST(&temp_list)) {
153 unsigned int weight_sum = 0;
154 unsigned int random_weight;
155
156 AST_LIST_TRAVERSE(&temp_list, current, list) {
157 ((struct ast_dns_srv_record *)current)->weight_sum = weight_sum += ((struct ast_dns_srv_record *)current)->weight;
158 }
159
160 /* if all the remaining entries have weight == 0,
161 then just append them to the result list and quit */
162 if (weight_sum == 0) {
163 AST_LIST_APPEND_LIST(&newlist, &temp_list, list);
164 break;
165 }
166
167 random_weight = 1 + (unsigned int) ((float) weight_sum * (ast_random() / ((float) RAND_MAX + 1.0)));
168
169 AST_LIST_TRAVERSE_SAFE_BEGIN(&temp_list, current, list) {
170 if (((struct ast_dns_srv_record *)current)->weight_sum < random_weight) {
171 continue;
172 }
173
174 AST_LIST_MOVE_CURRENT(&newlist, list);
175 break;
176 }
178 }
179
180 }
181
182 /* now that the new list has been ordered,
183 put it in place */
184
185 AST_LIST_APPEND_LIST(&result->records, &newlist, list);
186}
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
Definition: linkedlists.h:582
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_APPEND_LIST(head, list, field)
Appends a whole list to the tail of a list.
Definition: linkedlists.h:783
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
unsigned int weight_sum
The running weight sum.
Definition: dns_internal.h:86
long int ast_random(void)
Definition: utils.c:2312

References AST_LIST_APPEND_LIST, AST_LIST_FIRST, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_MOVE_CURRENT, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_random(), current, priority, result, weight, and ast_dns_srv_record::weight_sum.

◆ dns_txt_alloc()

struct ast_dns_record * dns_txt_alloc ( struct ast_dns_query query,
const char *  data,
const size_t  size 
)

Allocate and parse a DNS TXT record.

Since
16.10.0, 17.4.0
Parameters
queryThe DNS query
dataThis specific TXT record
sizeThe size of the TXT record
Return values
non-NULLsuccess
NULLfailure

Definition at line 38 of file dns_txt.c.

39{
40 struct ast_dns_txt_record *txt;
41 const char *end_of_record = data + size;
42 size_t count = 0;
43
44 /* Because we can't allocate additional memory, the best we can do here is just
45 * validate that this conforms to a TXT record. */
46 while (data < end_of_record) {
47 uint8_t byte_count = (uint8_t) *data;
48 count++;
49 data += byte_count + 1;
50 }
51
52 if (data != end_of_record) {
53 /* This is not a valid TXT record, so we can bail out */
54 return NULL;
55 }
56
57 txt = ast_calloc(1, sizeof(*txt) + size);
58 if (!txt) {
59 return NULL;
60 }
61
62 txt->count = count;
63 txt->generic.data_ptr = txt->data;
64
65 return (struct ast_dns_record *) txt;
66}
A TXT record.
Definition: dns_internal.h:64
struct ast_dns_record generic
Generic DNS record information.
Definition: dns_internal.h:66
size_t count
The number of character strings in the TXT record.
Definition: dns_internal.h:68
char data[0]
The raw DNS record.
Definition: dns_internal.h:70

References ast_calloc, ast_dns_txt_record::count, ast_dns_txt_record::data, ast_dns_record::data_ptr, ast_dns_txt_record::generic, and NULL.