38 #include <netinet/in.h>
39 #include <arpa/nameser.h>
41 #include <arpa/nameser_compat.h>
57 unsigned short priority;
58 unsigned short weight;
60 unsigned int weight_sum;
66 unsigned int have_weights:1;
68 unsigned int num_records;
72 static
int parse_srv(
unsigned char *answer,
int len,
unsigned char *msg, struct
srv_entry **result)
75 unsigned short priority;
76 unsigned short weight;
78 } __attribute__((__packed__)) *srv = (
struct srv *) answer;
84 if (len <
sizeof(*srv))
87 answer +=
sizeof(*srv);
90 if ((res = dn_expand(msg, answer + len, answer, repl,
sizeof(repl) - 1)) <= 0) {
91 ast_log(LOG_WARNING,
"Failed to expand hostname\n");
97 if (!strcmp(repl,
"."))
100 if (!(entry =
ast_calloc(1,
sizeof(*entry) + strlen(repl))))
103 entry->priority = ntohs(srv->priority);
104 entry->weight = ntohs(srv->weight);
105 entry->port = ntohs(srv->port);
106 strcpy(entry->host, repl);
113 static int srv_callback(
void *context,
unsigned char *answer,
int len,
unsigned char *fullanswer)
119 if (parse_srv(answer, len, fullanswer, &entry))
128 if (current->priority <= entry->priority)
150 static void process_weights(
struct srv_context *context)
156 unsigned int random_weight;
157 unsigned int weight_sum;
158 unsigned short cur_priority =
AST_LIST_FIRST(&context->entries)->priority;
163 if (current->priority != cur_priority)
173 current->weight_sum = weight_sum += current->weight;
177 if (weight_sum == 0) {
182 random_weight = 1 + (
unsigned int) ((
float) weight_sum * (ast_random() / ((float) RAND_MAX + 1.0)));
185 if (current->weight < random_weight)
206 if (*context == NULL) {
212 if (((
ast_search_dns(*context, service, C_IN, T_SRV, srv_callback)) < 1) ||
219 if ((*context)->have_weights) {
220 process_weights(*context);
224 *host = (*context)->prev->host;
225 *port = (*context)->prev->port;
227 ++((*context)->num_records);
232 if (((*context)->prev =
AST_LIST_NEXT((*context)->prev, list))) {
234 *host = (*context)->prev->host;
235 *port = (*context)->prev->port;
270 ret =
ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
272 if (context.have_weights) {
273 process_weights(&context);
288 *port = current->port;
290 ast_debug(4,
"ast_get_srv: SRV lookup for '%s' mapped to host %s, port %d\n",
291 service, host, *port);
306 return context->num_records;
310 unsigned short *port,
unsigned short *priority,
unsigned short *weight)
316 if (record_num < 1 || record_num > context->num_records) {
321 if (i == record_num) {
324 *priority = entry->priority;
325 *weight = entry->weight;
Main Channel structure associated with a channel.
void ast_srv_cleanup(struct srv_context **context)
Cleanup resources associated with ast_srv_lookup.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Support for DNS SRV records, used in to locate SIP services.
int ast_search_dns(void *context, const char *dname, int class, int type, int(*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
Perform DNS lookup (used by DNS, enum and SRV lookups)
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
General Asterisk PBX channel definitions.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define ast_calloc(num, len)
A wrapper for calloc()
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
unsigned int ast_srv_get_record_count(struct srv_context *context)
Get the number of records for a given SRV context.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int ast_srv_lookup(struct srv_context **context, const char *service, const char **host, unsigned short *port)
Retrieve set of SRV lookups, in order.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
int ast_srv_get_nth_record(struct srv_context *context, int record_num, const char **host, unsigned short *port, unsigned short *priority, unsigned short *weight)
Retrieve details from a specific SRV record.
int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
Lookup entry in SRV records Returns 1 if found, 0 if not found, -1 on hangup.
DNS support for Asterisk.
#define AST_LIST_APPEND_LIST(head, list, field)
Appends a whole list to the tail of a list.