summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Bright <sean@malleable.com>2012-02-29 20:31:48 +0000
committerSean Bright <sean@malleable.com>2012-02-29 20:31:48 +0000
commit62aae5014294c2a44c887541e43b927aef2b4b29 (patch)
treeb8466b3e9e1be0b579d6f04f36294e69ce9d36cc
parent571cef491f18be173da3a0dae0cfda4416155e28 (diff)
Add IPv6 support to FastAGI.
Review: https://reviewboard.asterisk.org/r/1774/ Reviewed by: Simon Perreault, Mark Michelson git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@357610 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--CHANGES3
-rw-r--r--res/res_agi.c74
2 files changed, 47 insertions, 30 deletions
diff --git a/CHANGES b/CHANGES
index b72862606..443f1acb0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -205,6 +205,9 @@ AGI
* A new channel variable, AGIEXITONHANGUP, has been added which allows
Asterisk to behave like it did in Asterisk 1.4 and earlier where the
AGI application would exit immediately after a channel hangup is detected.
+ * IPv6 addresses are now supported when using FastAGI (agi://). Hostnames
+ are resolved and each address is attempted in turn until one succeeds or
+ all fail.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 1.8 to Asterisk 10 -------------------
diff --git a/res/res_agi.c b/res/res_agi.c
index 1f4c1cab2..acac4c89a 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/xmldoc.h"
#include "asterisk/srv.h"
#include "asterisk/test.h"
+#include "asterisk/netsock2.h"
#define AST_API_MODULE
#include "asterisk/agi.h"
@@ -1445,15 +1446,15 @@ async_agi_abort:
FastAGI defaults to port 4573 */
static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
{
- int s, flags, res, port = AGI_PORT;
+ int s = 0, flags, res;
struct pollfd pfds[1];
- char *host, *c, *script;
- struct sockaddr_in addr_in;
- struct hostent *hp;
- struct ast_hostent ahp;
+ char *host, *script;
+ int num_addrs = 0, i = 0;
+ struct ast_sockaddr *addrs;
/* agiurl is "agi://host.domain[:port][/script/name]" */
host = ast_strdupa(agiurl + 6); /* Remove agi:// */
+
/* Strip off any script name */
if ((script = strchr(host, '/'))) {
*script++ = '\0';
@@ -1461,35 +1462,48 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
script = "";
}
- if ((c = strchr(host, ':'))) {
- *c++ = '\0';
- port = atoi(c);
- }
- if (!(hp = ast_gethostbyname(host, &ahp))) {
+ if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
return AGI_RESULT_FAILURE;
}
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
- return AGI_RESULT_FAILURE;
- }
- if ((flags = fcntl(s, F_GETFL)) < 0) {
- ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
- close(s);
- return AGI_RESULT_FAILURE;
- }
- if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
- close(s);
- return AGI_RESULT_FAILURE;
+
+ for (i = 0; i < num_addrs; i++) {
+ if (!ast_sockaddr_port(&addrs[i])) {
+ ast_sockaddr_set_port(&addrs[i], AGI_PORT);
+ }
+
+ if ((s = socket(addrs[i].ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
+ continue;
+ }
+
+ if ((flags = fcntl(s, F_GETFL)) < 0) {
+ ast_log(LOG_WARNING, "fcntl(F_GETFL) failed: %s\n", strerror(errno));
+ close(s);
+ continue;
+ }
+
+ if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
+ ast_log(LOG_WARNING, "fnctl(F_SETFL) failed: %s\n", strerror(errno));
+ close(s);
+ continue;
+ }
+
+ if (ast_connect(s, &addrs[i]) && (errno != EINPROGRESS)) {
+ ast_log(LOG_WARNING, "Connection to %s failed with unexpected error: %s\n",
+ ast_sockaddr_stringify(&addrs[i]),
+ strerror(errno));
+ close(s);
+ continue;
+ }
+
+ break;
}
- memset(&addr_in, 0, sizeof(addr_in));
- addr_in.sin_family = AF_INET;
- addr_in.sin_port = htons(port);
- memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr));
- if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) {
- ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
- close(s);
+
+ ast_free(addrs);
+
+ if (i == num_addrs) {
+ ast_log(LOG_WARNING, "Couldn't connect to any host. FastAGI failed.\n");
return AGI_RESULT_FAILURE;
}