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
if (
option_verbose > 3)
00062
ast_verbose( VERBOSE_PREFIX_3
"parse_srv: SRV mapped to host %s, port %d\n", repl, ntohs(
srv->portnum));
00063
if (host) {
00064 strncpy(host, repl, hostlen - 1);
00065 host[hostlen-1] =
'\0';
00066 }
00067
if (portno)
00068 *portno = ntohs(
srv->portnum);
00069
return(0);
00070 }
00071
return(-1);
00072 }
00073
00074 struct srv_context {
00075 char *host;
00076 int hostlen;
00077 int *
port;
00078 };
00079
00080
static int srv_callback(
void *context, u_char *answer,
int len, u_char *fullanswer)
00081 {
00082
struct srv_context *c = (
struct srv_context *)context;
00083
00084
if (parse_srv(c->host, c->hostlen, c->port, answer, len, fullanswer)) {
00085
ast_log(
LOG_WARNING,
"Failed to parse srv\n");
00086
return -1;
00087 }
00088
00089
if (!ast_strlen_zero(c->host))
00090
return 1;
00091
00092
return 0;
00093 }
00094
00095 int ast_get_srv(
struct ast_channel *chan,
char *host,
int hostlen,
int *port,
const char *service)
00096 {
00097
struct srv_context context;
00098
int ret;
00099
00100 context.
host = host;
00101 context.
hostlen = hostlen;
00102 context.
port = port;
00103
00104
if (chan &&
ast_autoservice_start(chan) < 0)
00105
return -1;
00106
00107 ret =
ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
00108
00109
if (chan)
00110 ret |=
ast_autoservice_stop(chan);
00111
00112
if (ret <= 0) {
00113 host[0] =
'\0';
00114 *port = -1;
00115
return ret;
00116 }
00117
return ret;
00118 }