00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <sys/types.h>
00015
#include <netinet/in.h>
00016
#include <arpa/nameser.h>
00017
#if __APPLE_CC__ >= 1495
00018
#include <arpa/nameser_compat.h>
00019
#endif
00020
#include <resolv.h>
00021
#include <stdio.h>
00022
#include <string.h>
00023
#include <unistd.h>
00024
00025
#include <asterisk/channel.h>
00026
#include <asterisk/logger.h>
00027
#include <asterisk/srv.h>
00028
#include <asterisk/dns.h>
00029
#include <asterisk/options.h>
00030
#include <asterisk/utils.h>
00031
00032
#ifdef __APPLE__
00033
#undef T_SRV
00034
#define T_SRV 33
00035
#endif
00036
00037 struct srv {
00038 unsigned short priority;
00039 unsigned short weight;
00040 unsigned short portnum;
00041 } __attribute__ ((__packed__));
00042
00043
static int parse_srv(
unsigned char *host,
int hostlen,
int *portno,
unsigned char *answer,
int len,
unsigned char *msg)
00044 {
00045
int res = 0;
00046
struct srv *
srv = (
struct srv *)answer;
00047
char repl[256] =
"";
00048
00049
if (len <
sizeof(
struct srv)) {
00050 printf(
"Length too short\n");
00051
return -1;
00052 }
00053 answer +=
sizeof(
struct srv);
00054 len -=
sizeof(
struct srv);
00055
00056
if ((res = dn_expand(msg,answer + len,answer, repl,
sizeof(repl) - 1)) < 0) {
00057
ast_log(LOG_WARNING,
"Failed to expand hostname\n");
00058
return -1;
00059 }
00060
if (res && strcmp(repl,
".")) {
00061
ast_verbose( VERBOSE_PREFIX_3
"parse_srv: SRV mapped to host %s, port %d\n", repl, ntohs(
srv->portnum));
00062
if (host) {
00063 strncpy(host, repl, hostlen - 2);
00064 host[hostlen-1] =
'\0';
00065 }
00066
if (portno)
00067 *portno = ntohs(
srv->portnum);
00068
return(0);
00069 }
00070
return(-1);
00071 }
00072
00073 struct srv_context {
00074 char *host;
00075 int hostlen;
00076 int *
port;
00077 };
00078
00079
static int srv_callback(
void *context, u_char *answer,
int len, u_char *fullanswer)
00080 {
00081
struct srv_context *c = (
struct srv_context *)context;
00082
00083
if (parse_srv(c->host, c->hostlen, c->port, answer, len, fullanswer)) {
00084
ast_log(
LOG_WARNING,
"Failed to parse srv\n");
00085
return -1;
00086 }
00087
00088
if (!ast_strlen_zero(c->host))
00089
return 1;
00090
00091
return 0;
00092 }
00093
00094 int ast_get_srv(
struct ast_channel *chan,
char *host,
int hostlen,
int *port,
const char *service)
00095 {
00096
struct srv_context context;
00097
int ret;
00098
00099 context.
host = host;
00100 context.
hostlen = hostlen;
00101 context.
port = port;
00102
00103
if (chan &&
ast_autoservice_start(chan) < 0)
00104
return -1;
00105
00106 ret =
ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
00107
00108
if (chan)
00109 ret |=
ast_autoservice_stop(chan);
00110
00111
if (ret <= 0) {
00112 strcpy(host,
"");
00113 *port = -1;
00114
return ret;
00115 }
00116
return ret;
00117 }