aboutsummaryrefslogtreecommitdiffstats
path: root/main/acl.c
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-08 22:08:07 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-08 22:08:07 +0000
commitc3c2e5edfd715b3a99aac1567623a0b1b7d49de0 (patch)
treec05335b563c3f7cb9a3edbf3e101d8e1b80e0be4 /main/acl.c
parentaf344f1a5be5b43f1d10b95ea6e57ebfa761cf50 (diff)
Add IPv6 to Asterisk.
This adds a generic API for accommodating IPv6 and IPv4 addresses within Asterisk. While many files have been updated to make use of the API, chan_sip and the RTP code are the files which actually support IPv6 addresses at the time of this commit. The way has been paved for easier upgrading for other files in the near future, though. Big thanks go to Simon Perrault, Marc Blanchet, and Jean-Philippe Dionne for their hard work on this. (closes issue #17565) Reported by: russell Patches: asteriskv6-test-report.pdf uploaded by russell (license 2) Review: https://reviewboard.asterisk.org/r/743 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@274783 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/acl.c')
-rw-r--r--main/acl.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/main/acl.c b/main/acl.c
index caa1d56f0..082048a16 100644
--- a/main/acl.c
+++ b/main/acl.c
@@ -48,7 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/srv.h"
#if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
-static int get_local_address(struct in_addr *ourip)
+static int get_local_address(struct ast_sockaddr *ourip)
{
return -1;
}
@@ -112,7 +112,7 @@ static void score_address(const struct sockaddr_in *sin, struct in_addr *best_ad
}
}
-static int get_local_address(struct in_addr *ourip)
+static int get_local_address(struct ast_sockaddr *ourip)
{
int s, res = -1;
#ifdef SOLARIS
@@ -207,7 +207,9 @@ static int get_local_address(struct in_addr *ourip)
#endif /* BSD_OR_LINUX */
if (res == 0 && ourip) {
- memcpy(ourip, &best_addr, sizeof(*ourip));
+ ast_sockaddr_setnull(ourip);
+ ourip->ss.ss_family = AF_INET;
+ ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
}
return res;
}
@@ -372,27 +374,49 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
return res;
}
-int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service)
+static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag,
+ int family)
+{
+ struct ast_sockaddr *addrs;
+ int addrs_cnt;
+
+ addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
+ if (addrs_cnt > 0) {
+ if (addrs_cnt > 1) {
+ ast_debug(1, "Multiple addresses. Using the first only\n");
+ }
+ ast_sockaddr_copy(addr, &addrs[0]);
+ ast_free(addrs);
+ } else {
+ ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *value, const char *service)
{
- struct hostent *hp;
- struct ast_hostent ahp;
char srv[256];
char host[256];
- int tportno = ntohs(sin->sin_port);
+ int srv_ret = 0;
+ int tportno;
+
if (service) {
snprintf(srv, sizeof(srv), "%s.%s", service, value);
- if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) {
- sin->sin_port = htons(tportno);
+ if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
value = host;
}
}
- if ((hp = ast_gethostbyname(value, &ahp))) {
- sin->sin_family = hp->h_addrtype;
- memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
- } else {
- ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
+
+ if (resolve_first(addr, value, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
return -1;
}
+
+ if (srv_ret > 0) {
+ ast_sockaddr_set_port(addr, tportno);
+ }
+
return 0;
}
@@ -474,51 +498,53 @@ const char *ast_tos2str(unsigned int tos)
return "unknown";
}
-int ast_get_ip(struct sockaddr_in *sin, const char *value)
+int ast_get_ip(struct ast_sockaddr *addr, const char *value)
{
- return ast_get_ip_or_srv(sin, value, NULL);
+ return ast_get_ip_or_srv(addr, value, NULL);
}
-int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
+int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
{
+ int port;
int s;
- struct sockaddr_in sin;
- socklen_t slen;
- if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+ port = ast_sockaddr_port(us);
+
+ if ((s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET,
+ SOCK_DGRAM, 0)) < 0) {
ast_log(LOG_ERROR, "Cannot create socket\n");
return -1;
}
- sin.sin_family = AF_INET;
- sin.sin_port = htons(5060);
- sin.sin_addr = *them;
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) {
+
+ if (ast_connect(s, them)) {
ast_log(LOG_WARNING, "Cannot connect\n");
close(s);
return -1;
}
- slen = sizeof(sin);
- if (getsockname(s, (struct sockaddr *)&sin, &slen)) {
+ if (ast_getsockname(s, us)) {
+
ast_log(LOG_WARNING, "Cannot get socket name\n");
close(s);
return -1;
}
close(s);
- ast_debug(3, "Found IP address for this socket\n");
- *us = sin.sin_addr;
+ ast_debug(3, "For destination '%s', our source address is '%s'.\n",
+ ast_sockaddr_stringify_addr(them),
+ ast_sockaddr_stringify_addr(us));
+
+ ast_sockaddr_set_port(us, port);
+
return 0;
}
-int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
+int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr)
{
char ourhost[MAXHOSTNAMELEN] = "";
- struct ast_hostent ahp;
- struct hostent *hp;
- struct in_addr saddr;
+ struct ast_sockaddr root;
/* just use the bind address if it is nonzero */
- if (ntohl(bindaddr.sin_addr.s_addr)) {
- memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
+ if (!ast_sockaddr_is_any(bindaddr)) {
+ ast_sockaddr_copy(ourip, bindaddr);
ast_debug(3, "Attached to given IP address\n");
return 0;
}
@@ -526,15 +552,14 @@ int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
if (gethostname(ourhost, sizeof(ourhost) - 1)) {
ast_log(LOG_WARNING, "Unable to get hostname\n");
} else {
- if ((hp = ast_gethostbyname(ourhost, &ahp))) {
- memcpy(ourip, hp->h_addr, sizeof(*ourip));
- ast_debug(3, "Found one IP address based on local hostname %s.\n", ourhost);
+ if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, 0) == 0) {
return 0;
}
}
ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
/* A.ROOT-SERVERS.NET. */
- if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) {
+ if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
+ !ast_ouraddrfor(&root, ourip)) {
return 0;
}
return get_local_address(ourip);