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 }