Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Functions
srv.c File Reference

DNS SRV Record Lookup Support for Asterisk. More...

#include "asterisk.h"
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "asterisk/channel.h"
#include "asterisk/srv.h"
#include "asterisk/dns.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"

Go to the source code of this file.

Data Structures

struct  srv_context
 
struct  srv_context::srv_entries
 
struct  srv_entry
 

Functions

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. More...
 
void ast_srv_cleanup (struct srv_context **context)
 Cleanup resources associated with ast_srv_lookup. More...
 
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. More...
 
unsigned int ast_srv_get_record_count (struct srv_context *context)
 Get the number of records for a given SRV context. More...
 
int ast_srv_lookup (struct srv_context **context, const char *service, const char **host, unsigned short *port)
 Retrieve set of SRV lookups, in order. More...
 
static int parse_srv (unsigned char *answer, int len, unsigned char *msg, struct srv_entry **result)
 
static void process_weights (struct srv_context *context)
 
static int srv_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 

Detailed Description

DNS SRV Record Lookup Support for Asterisk.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
Funding provided by nic.at

Definition in file srv.c.

Function Documentation

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.

Only do SRV record lookup if you get a domain without a port. If you get a port #, it's a DNS host name.

Parameters
chanAst channel
hosthost name (return value)
hostlenLength of string "host"
portPort number (return value)
serviceService tag for SRV lookup (like "_sip._udp" or "_stun._udp"

Definition at line 260 of file srv.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_REMOVE_HEAD, and ast_search_dns().

Referenced by ast_get_ip_or_srv().

261 {
262  struct srv_context context = { .entries = AST_LIST_HEAD_NOLOCK_INIT_VALUE };
263  struct srv_entry *current;
264  int ret;
265 
266  if (chan && ast_autoservice_start(chan) < 0) {
267  return -1;
268  }
269 
270  ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
271 
272  if (context.have_weights) {
273  process_weights(&context);
274  }
275 
276  if (chan) {
277  ret |= ast_autoservice_stop(chan);
278  }
279 
280  /* TODO: there could be a "." entry in the returned list of
281  answers... if so, this requires special handling */
282 
283  /* the list of entries will be sorted in the proper selection order
284  already, so we just need the first one (if any) */
285 
286  if ((ret > 0) && (current = AST_LIST_REMOVE_HEAD(&context.entries, list))) {
287  ast_copy_string(host, current->host, hostlen);
288  *port = current->port;
289  ast_free(current);
290  ast_debug(4, "ast_get_srv: SRV lookup for '%s' mapped to host %s, port %d\n",
291  service, host, *port);
292  } else {
293  host[0] = '\0';
294  *port = -1;
295  }
296 
297  while ((current = AST_LIST_REMOVE_HEAD(&context.entries, list))) {
298  ast_free(current);
299  }
300 
301  return ret;
302 }
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
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)
Definition: dns.c:491
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
Definition: srv.c:56
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
void ast_srv_cleanup ( struct srv_context **  context)

Cleanup resources associated with ast_srv_lookup.

Parameters
contextPointer passed into ast_srv_lookup

Definition at line 248 of file srv.c.

References ast_srv_lookup().

249 {
250  const char *host;
251  unsigned short port;
252 
253  if (*context) {
254  /* We have a context to clean up. */
255  while (!(ast_srv_lookup(context, NULL, &host, &port))) {
256  }
257  }
258 }
int ast_srv_lookup(struct srv_context **context, const char *service, const char **host, unsigned short *port)
Retrieve set of SRV lookups, in order.
Definition: srv.c:202
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.

After calling ast_srv_lookup, the srv_context will contain the data from several records. You can retrieve the data of a specific one by asking for a specific record number. The records are sorted based on priority and secondarily based on weight. See RFC 2782 for the exact sorting rules.

Parameters
contextThe context returned by ast_srv_lookup
record_numThe 1-indexed record number to retrieve
[out]hostThe host portion of the record
[out]portThe port portion of the record
[out]priorityThe priority portion of the record
[out]weightThe weight portion of the record
Return values
-1Failed to retrieve information. Likely due to an out of range record_num
0Success

Definition at line 309 of file srv.c.

References AST_LIST_TRAVERSE.

311 {
312  int i = 1;
313  int res = -1;
314  struct srv_entry *entry;
315 
316  if (record_num < 1 || record_num > context->num_records) {
317  return res;
318  }
319 
320  AST_LIST_TRAVERSE(&context->entries, entry, list) {
321  if (i == record_num) {
322  *host = entry->host;
323  *port = entry->port;
324  *priority = entry->priority;
325  *weight = entry->weight;
326  res = 0;
327  break;
328  }
329  ++i;
330  }
331 
332  return res;
333 }
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Definition: srv.c:56
Definition: search.h:40
unsigned int ast_srv_get_record_count ( struct srv_context context)

Get the number of records for a given SRV context.

This is meant to be used after calling ast_srv_lookup, so that one may retrieve the number of records returned during a specific SRV lookup.

Parameters
contextThe context returned by ast_srv_lookup
Returns
Number of records in context

Definition at line 304 of file srv.c.

305 {
306  return context->num_records;
307 }
int ast_srv_lookup ( struct srv_context **  context,
const char *  service,
const char **  host,
unsigned short *  port 
)

Retrieve set of SRV lookups, in order.

Parameters
[in]contextA pointer in which to hold the result
[in]serviceThe service name to look up
[out]hostResult host
[out]portAssociated TCP portnum
Return values
-1Query failed
0Result exists in host and port
1No more results

Definition at line 202 of file srv.c.

References ast_calloc, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, and ast_search_dns().

Referenced by ast_srv_cleanup().

203 {
204  struct srv_entry *cur;
205 
206  if (*context == NULL) {
207  if (!(*context = ast_calloc(1, sizeof(struct srv_context)))) {
208  return -1;
209  }
210  AST_LIST_HEAD_INIT_NOLOCK(&(*context)->entries);
211 
212  if (((ast_search_dns(*context, service, C_IN, T_SRV, srv_callback)) < 1) ||
213  AST_LIST_EMPTY(&(*context)->entries)) {
214  ast_free(*context);
215  *context = NULL;
216  return -1;
217  }
218 
219  if ((*context)->have_weights) {
220  process_weights(*context);
221  }
222 
223  (*context)->prev = AST_LIST_FIRST(&(*context)->entries);
224  *host = (*context)->prev->host;
225  *port = (*context)->prev->port;
226  AST_LIST_TRAVERSE(&(*context)->entries, cur, list) {
227  ++((*context)->num_records);
228  }
229  return 0;
230  }
231 
232  if (((*context)->prev = AST_LIST_NEXT((*context)->prev, list))) {
233  /* Retrieve next item in result */
234  *host = (*context)->prev->host;
235  *port = (*context)->prev->port;
236  return 0;
237  } else {
238  /* No more results */
239  while ((cur = AST_LIST_REMOVE_HEAD(&(*context)->entries, list))) {
240  ast_free(cur);
241  }
242  ast_free(*context);
243  *context = NULL;
244  return 1;
245  }
246 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
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)
Definition: dns.c:491
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Definition: srv.c:56
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681