aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-03-27 18:04:02 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-03-27 18:04:02 +0000
commit95fcfdc94d26dd9bfff45161c51e707ab59a8c8e (patch)
treec1fc6e23fbbce74c0ec18ca1cb1e9403f775c262 /channels/chan_iax2.c
parentdad113695fd1a2e7291d21b482985703b77f8cd4 (diff)
Fix the use of the "sourceaddress" option when "bindaddr" is set to 0.0.0.0
instead of having each interface explicitly listed. (issue #7874, patch by stevens) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2@59258 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index b9d536aab..c8c4221df 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -176,6 +176,7 @@ static int max_reg_expire;
static int timingfd = -1; /* Timing file descriptor */
static struct ast_netsock_list *netsock;
+static struct ast_netsock_list *outsock; /*!< used if sourceaddress specified and bindaddr == INADDR_ANY */
static int defaultsockfd = -1;
static int usecnt;
@@ -8225,20 +8226,40 @@ static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr)
if (res == 0) {
/* ip address valid. */
sin.sin_port = htons(port);
- sock = ast_netsock_find(netsock, &sin);
+ if (!(sock = ast_netsock_find(netsock, &sin)))
+ sock = ast_netsock_find(outsock, &sin);
if (sock) {
sockfd = ast_netsock_sockfd(sock);
nonlocal = 0;
+ } else {
+ unsigned int orig_saddr = sin.sin_addr.s_addr;
+ /* INADDR_ANY matches anyway! */
+ sin.sin_addr.s_addr = INADDR_ANY;
+ if (ast_netsock_find(netsock, &sin)) {
+ sin.sin_addr.s_addr = orig_saddr;
+ sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
+ if (sock) {
+ sockfd = ast_netsock_sockfd(sock);
+ ast_netsock_unref(sock);
+ nonlocal = 0;
+ } else {
+ nonlocal = 2;
+ }
+ }
}
}
}
peer->sockfd = sockfd;
- if (nonlocal) {
+ if (nonlocal == 1) {
ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
srcaddr, peer->name);
return -1;
+ } else if (nonlocal == 2) {
+ ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
+ srcaddr, peer->name);
+ return -1;
} else {
ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
return 0;
@@ -8942,7 +8963,16 @@ static int set_config(char *config_file, int reload)
ast_netsock_unref(ns);
}
}
-
+ if (reload) {
+ ast_netsock_release(outsock);
+ outsock = ast_netsock_list_alloc();
+ if (!outsock) {
+ ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
+ return -1;
+ }
+ ast_netsock_init(outsock);
+ }
+
if (min_reg_expire > max_reg_expire) {
ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
min_reg_expire, max_reg_expire, max_reg_expire);
@@ -9665,6 +9695,7 @@ static int __unload_module(void)
pthread_join(netthreadid, NULL);
}
ast_netsock_release(netsock);
+ ast_netsock_release(outsock);
for (x=0;x<IAX_MAX_CALLS;x++)
if (iaxs[x])
iax2_destroy(x);
@@ -9743,6 +9774,13 @@ int load_module(void)
}
ast_netsock_init(netsock);
+ outsock = ast_netsock_list_alloc();
+ if (!outsock) {
+ ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
+ return -1;
+ }
+ ast_netsock_init(outsock);
+
ast_mutex_init(&iaxq.lock);
ast_mutex_init(&userl.lock);
ast_mutex_init(&peerl.lock);
@@ -9773,6 +9811,7 @@ int load_module(void)
} else {
ast_log(LOG_ERROR, "Unable to start network thread\n");
ast_netsock_release(netsock);
+ ast_netsock_release(outsock);
}
ast_mutex_lock(&reg_lock);