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
00031 #ifdef __APPLE__
00032 #undef T_SRV
00033 #define T_SRV 33
00034 #endif
00035
00036 struct srv {
00037 unsigned short priority;
00038 unsigned short weight;
00039 unsigned short portnum;
00040 } __attribute__ ((__packed__));
00041
00042 static int parse_srv(unsigned char *host, int hostlen, int *portno, unsigned char *answer, int len, unsigned char *msg)
00043 {
00044 int res = 0;
00045 struct srv *srv = (struct srv *)answer;
00046 char repl[256] = "";
00047
00048 if (len < sizeof(struct srv)) {
00049 printf("Length too short\n");
00050 return -1;
00051 }
00052 answer += sizeof(struct srv);
00053 len -= sizeof(struct srv);
00054
00055 if ((res = dn_expand(msg,answer + len,answer, repl, sizeof(repl) - 1)) < 0) {
00056 ast_log(LOG_WARNING, "Failed to expand hostname\n");
00057 return -1;
00058 }
00059 if (res && strcmp(repl, ".")) {
00060 ast_verbose( VERBOSE_PREFIX_3 "parse_srv: SRV mapped to host %s, port %d\n", repl, ntohs(srv->portnum));
00061 if (host) {
00062 strncpy(host, repl, hostlen - 2);
00063 host[hostlen-1] = '\0';
00064 }
00065 if (portno)
00066 *portno = ntohs(srv->portnum);
00067 return(0);
00068 }
00069 return(-1);
00070 }
00071
00072 struct srv_context {
00073 char *host;
00074 int hostlen;
00075 int *port;
00076 };
00077
00078 static int srv_callback(void *context, u_char *answer, int len, u_char *fullanswer)
00079 {
00080 struct srv_context *c = (struct srv_context *)context;
00081
00082 if (parse_srv(c->host, c->hostlen, c->port, answer, len, fullanswer)) {
00083 ast_log(LOG_WARNING, "Failed to parse srv\n");
00084 return -1;
00085 }
00086
00087 if (strlen(c->host))
00088 return 1;
00089
00090 return 0;
00091 }
00092
00093 int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
00094 {
00095 struct srv_context context;
00096 int ret;
00097
00098 context.host = host;
00099 context.hostlen = hostlen;
00100 context.port = port;
00101
00102 if (chan && ast_autoservice_start(chan) < 0)
00103 return -1;
00104
00105 ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
00106
00107 if (chan)
00108 ret |= ast_autoservice_stop(chan);
00109
00110 if (ret <= 0) {
00111 strcpy(host, "");
00112 *port = -1;
00113 return ret;
00114 }
00115 return ret;
00116 }