2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * Funding provided by nic.at
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
23 * \brief DNS SRV Record Lookup Support for Asterisk
25 * \author Mark Spencer <markster@digium.com>
27 * \arg See also \ref AstENUM
29 * \note Funding provided by nic.at
34 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
36 #include <sys/types.h>
37 #include <netinet/in.h>
38 #include <arpa/nameser.h>
39 #if __APPLE_CC__ >= 1495
40 #include <arpa/nameser_compat.h>
47 #include "asterisk/channel.h"
48 #include "asterisk/logger.h"
49 #include "asterisk/srv.h"
50 #include "asterisk/dns.h"
51 #include "asterisk/options.h"
52 #include "asterisk/utils.h"
60 unsigned short priority
;
61 unsigned short weight
;
62 unsigned short portnum
;
63 } __attribute__ ((__packed__
));
65 static int parse_srv(char *host
, int hostlen
, int *portno
, unsigned char *answer
, int len
, unsigned char *msg
)
68 struct srv
*srv
= (struct srv
*)answer
;
71 if (len
< sizeof(struct srv
)) {
72 printf("Length too short\n");
75 answer
+= sizeof(struct srv
);
76 len
-= sizeof(struct srv
);
78 if ((res
= dn_expand(msg
, answer
+ len
, answer
, repl
, sizeof(repl
) - 1)) < 0) {
79 ast_log(LOG_WARNING
, "Failed to expand hostname\n");
82 if (res
&& strcmp(repl
, ".")) {
83 if (option_verbose
> 3)
84 ast_verbose( VERBOSE_PREFIX_3
"parse_srv: SRV mapped to host %s, port %d\n", repl
, ntohs(srv
->portnum
));
86 ast_copy_string(host
, repl
, hostlen
);
87 host
[hostlen
-1] = '\0';
90 *portno
= ntohs(srv
->portnum
);
102 static int srv_callback(void *context
, unsigned char *answer
, int len
, unsigned char *fullanswer
)
104 struct srv_context
*c
= (struct srv_context
*)context
;
106 if (parse_srv(c
->host
, c
->hostlen
, c
->port
, answer
, len
, fullanswer
)) {
107 ast_log(LOG_WARNING
, "Failed to parse srv\n");
111 if (!ast_strlen_zero(c
->host
))
117 int ast_get_srv(struct ast_channel
*chan
, char *host
, int hostlen
, int *port
, const char *service
)
119 struct srv_context context
;
123 context
.hostlen
= hostlen
;
126 if (chan
&& ast_autoservice_start(chan
) < 0)
129 ret
= ast_search_dns(&context
, service
, C_IN
, T_SRV
, srv_callback
);
132 ret
|= ast_autoservice_stop(chan
);