aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2008-04-01 17:53:08 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2008-04-01 17:53:08 +0000
commit62c01ac2d8208301c3563db7465056217eedd06b (patch)
tree8bb7e481848794e991a01f151dcc3c6f65e33b86
parentba5fa5e9191c1ad614e74bc84b55c3af89d7049e (diff)
This adds DNS SRV record support to DNS manager. If there is a SRV record for a given domain, the hostname and port listed in the SRV record will be used. If no SRV record exists or a SRV lookup is not attempted, the DNS lookup on the specified domain will be performed as normal. Chan_sip has been modified to take advantage of the new SRV support.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@112207 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--CHANGES8
-rw-r--r--channels/chan_iax2.c4
-rw-r--r--channels/chan_sip.c78
-rw-r--r--channels/chan_zap.c2
-rw-r--r--include/asterisk/dnsmgr.h5
-rw-r--r--include/asterisk/slinfactory.h4
-rw-r--r--main/dnsmgr.c63
-rw-r--r--main/slinfactory.c3
8 files changed, 89 insertions, 78 deletions
diff --git a/CHANGES b/CHANGES
index 61c0b80da..6b06454f4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -194,7 +194,8 @@ SIP changes
configs/sip.conf.sample for more information on how it is used.
* Added a new configuration option "authfailureevents" that enables manager events when
a peer can't authenticate properly.
- * Added DNS manager support to registrations not referencing a peer entry.
+ * Added DNS manager support to registrations, both for peers referencing
+ and not referencing a peer entry.
IAX2 changes
------------
@@ -535,6 +536,11 @@ Call Detail Records
* The ResetCDR application now has an 'e' option that re-enables a CDR if it
has been disabled using the NoCDR application.
+DNS manager changes
+-------------------
+ * Addresses managed by DNS manager now will check to see if there is a DNS
+ SRV record for a given domain and will use that hostname/port if present.
+
Miscellaneous New Modules
-------------------------
* Added a new CDR module, cdr_sqlite3_custom.
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 61a24c481..0ab1f3bd3 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -6427,7 +6427,7 @@ static int iax2_append_register(const char *hostname, const char *username,
if (!(reg = ast_calloc(1, sizeof(*reg))))
return -1;
- if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
+ if (ast_dnsmgr_lookup(hostname, &reg->addr, &reg->dnsmgr, NULL) < 0) {
ast_free(reg);
return -1;
}
@@ -10095,7 +10095,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
/* Non-dynamic. Make sure we become that way if we're not */
AST_SCHED_DEL(sched, peer->expire);
ast_clear_flag(peer, IAX_DYNAMIC);
- if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr))
+ if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, NULL))
return peer_unref(peer);
if (!peer->addr.sin_port)
peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index e68718646..ba5adb7cb 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1960,7 +1960,7 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, const char *msg
static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p);
static void build_via(struct sip_pvt *p);
static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer);
-static int create_addr(struct sip_pvt *dialog, const char *opeer, struct in_addr *sin);
+static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin);
static char *generate_random_string(char *buf, size_t size);
static void build_callid_pvt(struct sip_pvt *pvt);
static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain);
@@ -2529,7 +2529,7 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
int res = 0;
const struct sockaddr_in *dst = sip_real_dst(p);
- ast_debug(1, "Trying to put '%.10s' onto %s socket destined for %s\n", data->str, get_transport(p->socket.type), ast_inet_ntoa(dst->sin_addr));
+ ast_debug(1, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", data->str, get_transport(p->socket.type), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port));
if (sip_prepare_socket(p) < 0)
return XMIT_ERROR;
@@ -4053,11 +4053,10 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
return 0;
}
-
/*! \brief create address structure from peer name
* Or, if peer not found, find it in the global DNS
* returns TRUE (-1) on failure, FALSE on success */
-static int create_addr(struct sip_pvt *dialog, const char *opeer, struct in_addr *sin)
+static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockaddr_in *sin)
{
struct hostent *hp;
struct ast_hostent ahp;
@@ -4096,26 +4095,32 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct in_addr
if (dialog->outboundproxy)
return 0;
- /* Let's see if we can find the host in DNS. First try DNS SRV records,
- then hostname lookup */
- hostn = peername;
- portno = port ? atoi(port) : (dialog->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT;
- if (global_srvlookup) {
- char service[MAXHOSTNAMELEN];
- int tportno;
+ /* This address should be updated using dnsmgr */
+ if (sin) {
+ memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr));
+ if (!sin->sin_port) {
+ portno = port ? atoi(port) : (dialog->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT;
+ } else {
+ portno = ntohs(sin->sin_port);
+ }
+ } else {
- snprintf(service, sizeof(service), "_sip._%s.%s", get_transport(dialog->socket.type), peername);
- srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service);
- if (srv_ret > 0) {
- hostn = host;
- portno = tportno;
+ /* Let's see if we can find the host in DNS. First try DNS SRV records,
+ then hostname lookup */
+ hostn = peername;
+ portno = port ? atoi(port) : (dialog->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT;
+ if (global_srvlookup) {
+ char service[MAXHOSTNAMELEN];
+ int tportno;
+
+ snprintf(service, sizeof(service), "_sip._%s.%s", get_transport(dialog->socket.type), peername);
+ srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service);
+ if (srv_ret > 0) {
+ hostn = host;
+ portno = tportno;
+ }
}
- }
- if (sin && srv_ret <= 0) {
- memcpy(&dialog->sa.sin_addr, sin, sizeof(dialog->sa.sin_addr));
- ast_log(LOG_DEBUG, "IP lookup for hostname=%s, using dnsmgr resolved to %s...\n", peername, ast_inet_ntoa(*sin));
- } else {
hp = ast_gethostbyname(hostn, &ahp);
if (!hp) {
ast_log(LOG_WARNING, "No such host: %s\n", peername);
@@ -9221,8 +9226,10 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
}
if (r->dnsmgr == NULL) {
- ast_dnsmgr_lookup(r->hostname, &r->us.sin_addr, &r->dnsmgr);
- }
+ char transport[MAXHOSTNAMELEN];
+ snprintf(transport, sizeof(transport), "_sip._%s", get_transport(r->transport)); /* have to use static get_transport function */
+ ast_dnsmgr_lookup(r->hostname, &r->us, &r->dnsmgr, global_srvlookup ? transport : NULL);
+ }
if (r->call) { /* We have a registration */
if (!auth) {
@@ -9250,8 +9257,12 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
p->outboundproxy = obproxy_get(p, NULL);
+ /* Use port number specified if no SRV record was found */
+ if (!r->us.sin_port && r->portno)
+ r->us.sin_port = htons(r->portno);
+
/* Find address to hostname */
- if (create_addr(p, r->hostname, &r->us.sin_addr)) {
+ if (create_addr(p, r->hostname, &r->us)) {
/* we have what we hope is a temporary network error,
* probably DNS. We need to reschedule a registration try */
sip_destroy(p);
@@ -9265,13 +9276,15 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
r->regattempts++;
return 0;
}
+
/* Copy back Call-ID in case create_addr changed it */
ast_string_field_set(r, callid, p->callid);
- if (r->portno) {
+ if (!r->dnsmgr && r->portno) {
p->sa.sin_port = htons(r->portno);
p->recv.sin_port = htons(r->portno);
- } else /* Set registry port to the port set from the peer definition/srv or default */
+ } else { /* Set registry port to the port set from the peer definition/srv or default */
r->portno = ntohs(p->sa.sin_port);
+ }
ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */
r->call = dialog_ref(p); /* Save pointer to SIP dialog */
p->registry = registry_addref(r); /* Add pointer to registry in packet */
@@ -9298,6 +9311,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
/* Set transport and port so the correct contact is built */
p->socket.type = r->transport;
p->socket.port = htons(r->portno);
+
/*
check which address we should use in our contact header
based on whether the remote host is on the external or
@@ -20068,13 +20082,11 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
}
- if (srvlookup) {
- if (ast_get_ip_or_srv(&peer->addr, srvlookup,
- global_srvlookup ?
- ((peer->socket.type & SIP_TRANSPORT_UDP) ? "_sip._udp" :
- (peer->socket.type & SIP_TRANSPORT_TCP) ? "_sip._tcp" :
- "_sip._tls")
- : NULL)) {
+ if (srvlookup && peer->dnsmgr == NULL) {
+ char transport[MAXHOSTNAMELEN];
+ snprintf(transport, sizeof(transport), "_sip._%s", get_transport(peer->socket.type));
+
+ if (ast_dnsmgr_lookup(srvlookup, &peer->addr, &peer->dnsmgr, global_srvlookup ? transport : NULL)) {
unref_peer(peer);
return NULL;
}
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 78bed6250..beb3c33fc 100644
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -14203,8 +14203,6 @@ static int load_module(void)
int y, i;
#endif
- ast_log(LOG_WARNING, "The use of PSTN interfaces with Asterisk has been deprecated. Zaptel trunk has been removed.\n");
-
#ifdef HAVE_PRI
memset(pris, 0, sizeof(pris));
for (y = 0; y < NUM_SPANS; y++) {
diff --git a/include/asterisk/dnsmgr.h b/include/asterisk/dnsmgr.h
index db8be1f3c..2738201f5 100644
--- a/include/asterisk/dnsmgr.h
+++ b/include/asterisk/dnsmgr.h
@@ -28,6 +28,7 @@ extern "C" {
#endif
#include "asterisk/network.h"
+#include "asterisk/srv.h"
/*!
* \brief A DNS manager entry
@@ -50,7 +51,7 @@ struct ast_dnsmgr_entry;
*
* \return a DNS manager entry
*/
-struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct in_addr *result);
+struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service);
/*!
* \brief Free a DNS manager entry
@@ -75,7 +76,7 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry);
* \retval 0 success
* \retval non-zero failure
*/
-int ast_dnsmgr_lookup(const char *name, struct in_addr *result, struct ast_dnsmgr_entry **dnsmgr);
+int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service);
/*!
* \brief Force a refresh of a dnsmgr entry
diff --git a/include/asterisk/slinfactory.h b/include/asterisk/slinfactory.h
index 4d3e8eaf8..386cf51ba 100644
--- a/include/asterisk/slinfactory.h
+++ b/include/asterisk/slinfactory.h
@@ -28,12 +28,10 @@
extern "C" {
#endif
-#define AST_SLINFACTORY_MAX_HOLD 1280
-
struct ast_slinfactory {
AST_LIST_HEAD_NOLOCK(, ast_frame) queue; /*!< A list of unaltered frames */
struct ast_trans_pvt *trans; /*!< Translation path that converts fed frames into signed linear */
- short hold[AST_SLINFACTORY_MAX_HOLD]; /*!< Hold for audio that no longer belongs to a frame (ie: if only some samples were taken from a frame) */
+ short hold[1280]; /*!< Hold for audio that no longer belongs to a frame (ie: if only some samples were taken from a frame) */
short *offset; /*!< Offset into the hold where audio begins */
size_t holdlen; /*!< Number of samples currently in the hold */
unsigned int size; /*!< Number of samples currently in the factory */
diff --git a/main/dnsmgr.c b/main/dnsmgr.c
index ac13a8ab3..cae20f4b7 100644
--- a/main/dnsmgr.c
+++ b/main/dnsmgr.c
@@ -43,16 +43,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
+#include "asterisk/acl.h"
static struct sched_context *sched;
static int refresh_sched = -1;
static pthread_t refresh_thread = AST_PTHREADT_NULL;
struct ast_dnsmgr_entry {
- /*! where we will store the resulting address */
- struct in_addr *result;
- /*! the last result, used to check if address has changed */
- struct in_addr last;
+ /*! where we will store the resulting IP address and port number */
+ struct sockaddr_in *result;
+ /*! the last result, used to check if address/port has changed */
+ struct sockaddr_in last;
+ /*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */
+ char *service;
/*! Set to 1 if the entry changes */
int changed:1;
ast_mutex_t lock;
@@ -82,17 +85,22 @@ static struct refresh_info master_refresh_info = {
.verbose = 0,
};
-struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct in_addr *result)
+struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service)
{
struct ast_dnsmgr_entry *entry;
+ int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0);
- if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, sizeof(*entry) + strlen(name))))
+ if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, total_size)))
return NULL;
entry->result = result;
ast_mutex_init(&entry->lock);
strcpy(entry->name, name);
memcpy(&entry->last, result, sizeof(entry->last));
+ if (service) {
+ entry->service = ((char *) entry) + sizeof(*entry) + strlen(name);
+ strcpy(entry->service, service);
+ }
AST_RWLIST_WRLOCK(&entry_list);
AST_RWLIST_INSERT_HEAD(&entry_list, entry, list);
@@ -115,34 +123,30 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
ast_free(entry);
}
-int ast_dnsmgr_lookup(const char *name, struct in_addr *result, struct ast_dnsmgr_entry **dnsmgr)
+int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
{
- struct ast_hostent ahp;
- struct hostent *hp;
-
if (ast_strlen_zero(name) || !result || !dnsmgr)
return -1;
if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name))
return 0;
- ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name);
-
/* if it's actually an IP address and not a name,
there's no need for a managed lookup */
- if (inet_aton(name, result))
+ if (inet_aton(name, &result->sin_addr))
return 0;
+ ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name);
+
/* do a lookup now but add a manager so it will automagically get updated in the background */
- if ((hp = ast_gethostbyname(name, &ahp)))
- memcpy(result, hp->h_addr, sizeof(result));
+ ast_get_ip_or_srv(result, name, service);
/* if dnsmgr is not enable don't bother adding an entry */
if (!enabled)
return 0;
ast_verb(3, "adding dns manager for '%s'\n", name);
- *dnsmgr = ast_dnsmgr_get(name, result);
+ *dnsmgr = ast_dnsmgr_get(name, result, service);
return !*dnsmgr;
}
@@ -151,31 +155,26 @@ int ast_dnsmgr_lookup(const char *name, struct in_addr *result, struct ast_dnsmg
*/
static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
{
- struct ast_hostent ahp;
- struct hostent *hp;
char iabuf[INET_ADDRSTRLEN];
char iabuf2[INET_ADDRSTRLEN];
- struct in_addr tmp;
+ struct sockaddr_in tmp;
int changed = 0;
ast_mutex_lock(&entry->lock);
if (verbose)
ast_verb(3, "refreshing '%s'\n", entry->name);
- if ((hp = ast_gethostbyname(entry->name, &ahp))) {
- /* check to see if it has changed, do callback if requested (where de callback is defined ????) */
- memcpy(&tmp, hp->h_addr, sizeof(tmp));
- if (tmp.s_addr != entry->last.s_addr) {
- ast_copy_string(iabuf, ast_inet_ntoa(entry->last), sizeof(iabuf));
- ast_copy_string(iabuf2, ast_inet_ntoa(tmp), sizeof(iabuf2));
- ast_log(LOG_NOTICE, "host '%s' changed from %s to %s\n",
- entry->name, iabuf, iabuf2);
- memcpy(entry->result, hp->h_addr, sizeof(entry->result));
- memcpy(&entry->last, hp->h_addr, sizeof(entry->last));
- changed = entry->changed = 1;
- }
-
+ ast_get_ip_or_srv(&tmp, entry->name, entry->service);
+ if (inaddrcmp(&tmp, &entry->last)) {
+ ast_copy_string(iabuf, ast_inet_ntoa(entry->last.sin_addr), sizeof(iabuf));
+ ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2));
+ ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n",
+ entry->name, iabuf, ntohs(entry->last.sin_port), iabuf2, ntohs(tmp.sin_port));
+ *entry->result = tmp;
+ entry->last = tmp;
+ changed = entry->changed = 1;
}
+
ast_mutex_unlock(&entry->lock);
return changed;
}
diff --git a/main/slinfactory.c b/main/slinfactory.c
index af70399e6..6c1bdd6f9 100644
--- a/main/slinfactory.c
+++ b/main/slinfactory.c
@@ -172,9 +172,6 @@ int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
memcpy(offset, frame_data, ineed * sizeof(*offset));
sofar += ineed;
frame_data += ineed;
- if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
- remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
- }
memcpy(sf->hold, frame_data, remain * sizeof(*offset));
sf->holdlen = remain;
}