diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 9492d5c2fb..6eae6823c8 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -2625,11 +2625,13 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in struct iax2_peer *peer=NULL; time_t regseconds, nowtime; int dynamic=0; + char iabuf[INET_ADDRSTRLEN]; - if (peername) - var = ast_load_realtime("iaxpeers", "name", peername, NULL); - else { - char iabuf[INET_ADDRSTRLEN]; + if (peername) { + var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL); + if (!var) + var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr)); + } else { char porta[25]; ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr); sprintf(porta, "%d", ntohs(sin->sin_port)); @@ -2644,6 +2646,29 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in } } } + if (!var) { /* Last ditch effort */ + var = ast_load_realtime("iaxpeers", "name", peername, NULL); + /*!\note + * If this one loaded something, then we need to ensure that the host + * field matched. The only reason why we can't have this as a criteria + * is because we only have the IP address and the host field might be + * set as a name (and the reverse PTR might not match). + */ + if (var) { + for (tmp = var; tmp; tmp = tmp->next) { + if (!strcasecmp(tmp->name, "host")) { + struct in_addr sin2 = { 0, }; + struct ast_dnsmgr_entry *dnsmgr = NULL; + if ((ast_dnsmgr_lookup(tmp->value, &sin2, &dnsmgr) < 0) || (memcmp(&sin2, &sin->sin_addr, sizeof(sin2)) != 0)) { + /* No match */ + ast_variables_destroy(var); + var = NULL; + } + break; + } + } + } + } if (!var) return NULL; @@ -2720,13 +2745,46 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in return peer; } -static struct iax2_user *realtime_user(const char *username) +static struct iax2_user *realtime_user(const char *username, struct sockaddr_in *sin) { struct ast_variable *var; struct ast_variable *tmp; struct iax2_user *user=NULL; + char iabuf[INET_ADDRSTRLEN]; - var = ast_load_realtime("iaxusers", "name", username, NULL); + var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL); + if (!var && sin) + var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr)); + if (!var && sin) { + char porta[6]; + snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); + var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), "port", porta, NULL); + if (!var) + var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), "port", porta, NULL); + } + if (!var) { /* Last ditch effort */ + var = ast_load_realtime("iaxusers", "name", username, NULL); + /*!\note + * If this one loaded something, then we need to ensure that the host + * field matched. The only reason why we can't have this as a criteria + * is because we only have the IP address and the host field might be + * set as a name (and the reverse PTR might not match). + */ + if (var) { + for (tmp = var; tmp; tmp = tmp->next) { + if (!strcasecmp(tmp->name, "host")) { + struct in_addr sin2 = { 0, }; + struct ast_dnsmgr_entry *dnsmgr = NULL; + if ((ast_dnsmgr_lookup(tmp->value, &sin2, &dnsmgr) < 0) || (memcmp(&sin2, &sin->sin_addr, sizeof(sin2)) != 0)) { + /* No match */ + ast_variables_destroy(var); + var = NULL; + } + break; + } + } + } + } if (!var) return NULL; @@ -4878,7 +4936,7 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies ast_mutex_unlock(&userl.lock); user = best; if (!user && !ast_strlen_zero(iaxs[callno]->username)) { - user = realtime_user(iaxs[callno]->username); + user = realtime_user(iaxs[callno]->username, sin); if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ destroy_user(user); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 44d5519408..58b6aef6cd 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -81,6 +81,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/dnsmgr.h" #include "asterisk/devicestate.h" #include "asterisk/linkedlists.h" +#include "asterisk/dnsmgr.h" #ifdef OSP_SUPPORT #include "asterisk/astosp.h" @@ -1698,9 +1699,35 @@ static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in * char iabuf[80]; /* First check on peer name */ - if (newpeername) - var = ast_load_realtime("sippeers", "name", peername, NULL); - else if (sin) { /* Then check on IP address */ + if (newpeername) { + var = ast_load_realtime("sippeers", "name", newpeername, "host", "dynamic", NULL); + if (!var && sin) { + var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), NULL); + if (!var) { + var = ast_load_realtime("sippeers", "name", newpeername, NULL); + /*!\note + * If this one loaded something, then we need to ensure that the host + * field matched. The only reason why we can't have this as a criteria + * is because we only have the IP address and the host field might be + * set as a name (and the reverse PTR might not match). + */ + if (var) { + for (tmp = var; tmp; tmp = tmp->next) { + if (!strcasecmp(var->name, "host")) { + struct in_addr sin2 = { 0, }; + struct ast_dnsmgr_entry *dnsmgr = NULL; + if ((ast_dnsmgr_lookup(tmp->value, &sin2, &dnsmgr) < 0) || (memcmp(&sin2, &sin->sin_addr, sizeof(sin2)) != 0)) { + /* No match */ + ast_variables_destroy(var); + var = NULL; + } + break; + } + } + } + } + } + } else if (sin) { /* Then check on IP address */ ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr); var = ast_load_realtime("sippeers", "host", iabuf, NULL); /* First check for fixed IP hosts */ if (!var)