Asterisk - The Open Source Telephony Project GIT-master-a358458
Functions
dns_srv.c File Reference

DNS SRV Record Support. More...

#include "asterisk.h"
#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"
Include dependency graph for dns_srv.c:

Go to the source code of this file.

Functions

const char * ast_dns_srv_get_host (const struct ast_dns_record *record)
 Get the hostname from an SRV record. More...
 
unsigned short ast_dns_srv_get_port (const struct ast_dns_record *record)
 Get the port from an SRV record. More...
 
unsigned short ast_dns_srv_get_priority (const struct ast_dns_record *record)
 Get the priority from an SRV record. More...
 
unsigned short ast_dns_srv_get_weight (const struct ast_dns_record *record)
 Get the weight from an SRV record. 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...
 

Detailed Description

DNS SRV Record Support.

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

Definition in file dns_srv.c.

Function Documentation

◆ ast_dns_srv_get_host()

const char * ast_dns_srv_get_host ( const struct ast_dns_record record)

Get the hostname from an SRV record.

Parameters
recordThe DNS record
Returns
the hostname

Definition at line 188 of file dns_srv.c.

189{
190 struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
191
192 ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
193 return srv->host;
194}
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
Definition: dns_core.c:145
An SRV record.
Definition: dns_internal.h:74
const char * host
The hostname in the SRV record.
Definition: dns_internal.h:78
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_srv_record::host.

Referenced by AST_TEST_DEFINE(), and nominal_test().

◆ ast_dns_srv_get_port()

unsigned short ast_dns_srv_get_port ( const struct ast_dns_record record)

Get the port from an SRV record.

Parameters
recordThe DNS record
Returns
the port

Definition at line 212 of file dns_srv.c.

213{
214 struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
215
216 ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
217 return srv->port;
218}
unsigned short port
The port in the SRV record.
Definition: dns_internal.h:84

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_srv_record::port.

Referenced by AST_TEST_DEFINE(), and nominal_test().

◆ ast_dns_srv_get_priority()

unsigned short ast_dns_srv_get_priority ( const struct ast_dns_record record)

Get the priority from an SRV record.

Parameters
recordThe DNS record
Returns
the priority

Definition at line 196 of file dns_srv.c.

197{
198 struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
199
200 ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
201 return srv->priority;
202}
unsigned short priority
The priority of the SRV record.
Definition: dns_internal.h:80

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_srv_record::priority.

Referenced by AST_TEST_DEFINE(), and nominal_test().

◆ ast_dns_srv_get_weight()

unsigned short ast_dns_srv_get_weight ( const struct ast_dns_record record)

Get the weight from an SRV record.

Parameters
recordThe DNS record
Returns
the weight

Definition at line 204 of file dns_srv.c.

205{
206 struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
207
208 ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
209 return srv->weight;
210}
unsigned short weight
The weight of the SRV record.
Definition: dns_internal.h:82

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_srv_record::weight.

Referenced by AST_TEST_DEFINE(), and nominal_test().

◆ 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
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static int priority
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
#define LOG_ERROR
int errno
#define NULL
Definition: resample.c:96
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
For AST_LIST.
Definition: dns_internal.h:39
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58
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
struct ast_dns_record generic
Generic DNS record information.
Definition: dns_internal.h:76
char data[0]
Additional data.
Definition: dns_internal.h:88

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}
static PGresult * result
Definition: cel_pgsql.c:84
#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_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#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_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
#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
size_t current
Definition: main/cli.c:113
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.