aboutsummaryrefslogtreecommitdiffstats
path: root/main/srv.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-21 02:11:39 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-21 02:11:39 +0000
commit8b0c007ad990aa27d9868da49215fd1076ac77cc (patch)
tree270b9c46c1e644483d6d2a35b509f43218ba3252 /main/srv.c
parenta42edc84034f91932a3e12d503e07f76a6eb498a (diff)
merge new_loader_completion branch, including (at least):
- restructured build tree and makefiles to eliminate recursion problems - support for embedded modules - support for static builds - simpler cross-compilation support - simpler module/loader interface (no exported symbols) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@40722 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/srv.c')
-rw-r--r--main/srv.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/main/srv.c b/main/srv.c
new file mode 100644
index 000000000..8b7e76bfc
--- /dev/null
+++ b/main/srv.c
@@ -0,0 +1,140 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster@digium.com>
+ *
+ * Funding provided by nic.at
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief DNS SRV Record Lookup Support for Asterisk
+ *
+ * \author Mark Spencer <markster@digium.com>
+ *
+ * \arg See also \ref AstENUM
+ *
+ * \note Funding provided by nic.at
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#if __APPLE_CC__ >= 1495
+#include <arpa/nameser_compat.h>
+#endif
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "asterisk/channel.h"
+#include "asterisk/logger.h"
+#include "asterisk/srv.h"
+#include "asterisk/dns.h"
+#include "asterisk/options.h"
+#include "asterisk/utils.h"
+
+#ifdef __APPLE__
+#undef T_SRV
+#define T_SRV 33
+#endif
+
+struct srv {
+ unsigned short priority;
+ unsigned short weight;
+ unsigned short portnum;
+} __attribute__ ((__packed__));
+
+static int parse_srv(char *host, int hostlen, int *portno, unsigned char *answer, int len, unsigned char *msg)
+{
+ int res = 0;
+ struct srv *srv = (struct srv *)answer;
+ char repl[256] = "";
+
+ if (len < sizeof(struct srv)) {
+ printf("Length too short\n");
+ return -1;
+ }
+ answer += sizeof(struct srv);
+ len -= sizeof(struct srv);
+
+ if ((res = dn_expand(msg, answer + len, answer, repl, sizeof(repl) - 1)) < 0) {
+ ast_log(LOG_WARNING, "Failed to expand hostname\n");
+ return -1;
+ }
+ if (res && strcmp(repl, ".")) {
+ if (option_verbose > 3)
+ ast_verbose( VERBOSE_PREFIX_3 "parse_srv: SRV mapped to host %s, port %d\n", repl, ntohs(srv->portnum));
+ if (host) {
+ ast_copy_string(host, repl, hostlen);
+ host[hostlen-1] = '\0';
+ }
+ if (portno)
+ *portno = ntohs(srv->portnum);
+ return 0;
+ }
+ return -1;
+}
+
+struct srv_context {
+ char *host;
+ int hostlen;
+ int *port;
+};
+
+static int srv_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
+{
+ struct srv_context *c = (struct srv_context *)context;
+
+ if (parse_srv(c->host, c->hostlen, c->port, answer, len, fullanswer)) {
+ ast_log(LOG_WARNING, "Failed to parse srv\n");
+ return -1;
+ }
+
+ if (!ast_strlen_zero(c->host))
+ return 1;
+
+ return 0;
+}
+
+int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
+{
+ struct srv_context context;
+ int ret;
+
+ context.host = host;
+ context.hostlen = hostlen;
+ context.port = port;
+
+ if (chan && ast_autoservice_start(chan) < 0)
+ return -1;
+
+ ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
+
+ if (chan)
+ ret |= ast_autoservice_stop(chan);
+
+ if (ret <= 0) {
+ host[0] = '\0';
+ *port = -1;
+ return ret;
+ }
+ return ret;
+}