diff --git a/CHANGES b/CHANGES index 61c0b80daf..6b06454f4a 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 61a24c481e..0ab1f3bd3e 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, ®->addr.sin_addr, ®->dnsmgr) < 0) { + if (ast_dnsmgr_lookup(hostname, ®->addr, ®->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 e68718646a..ba5adb7cb6 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 78bed62509..beb3c33fc9 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 db8be1f3ca..2738201f53 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 4d3e8eaf83..386cf51bae 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 ac13a8ab3c..cae20f4b7c 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 af70399e67..6c1bdd6f9d 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; }