summaryrefslogtreecommitdiff
path: root/res/res_rtp_asterisk.c
diff options
context:
space:
mode:
authorMichael Walton <mike@farsouthnet.com>2016-10-05 12:24:54 +1300
committerJoshua Colp <jcolp@digium.com>2016-10-19 07:15:13 -0500
commit494bebeb6f362666150493580154fd0c6bc38c16 (patch)
treec738f4eb63bab1bd2affa60f722c07784c66302d /res/res_rtp_asterisk.c
parentab030fcc1fe0a7dfd4c435feb7f36a94b12e4e32 (diff)
res_rtp_asterisk: Add ice_blacklist option
Introduces ice_blacklist configuration in rtp.conf. Subnets listed in the form ice_blacklist = <subnet spec>, e.g. ice_blacklist = 192.168.1.0/255.255.255.0, are excluded from ICE host, srflx and relay discovery. This is useful for optimizing the ICE process where a system has multiple host address ranges and/or physical interfaces and certain of them are not expected to be used for RTP. Multiple ice_blacklist configuration lines may be used. If left unconfigured, all discovered host addresses are used, as per previous behavior. Documention in rtp.conf.sample. ASTERISK-26418 #close Change-Id: Ibee88f80d7693874fda1cceaef94a03bd86012c9
Diffstat (limited to 'res/res_rtp_asterisk.c')
-rw-r--r--res/res_rtp_asterisk.c87
1 files changed, 81 insertions, 6 deletions
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 520fd7602..4bf625260 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -51,6 +51,7 @@ ASTERISK_REGISTER_FILE()
#include <pjlib.h>
#include <pjlib-util.h>
#include <pjnath.h>
+#include <ifaddrs.h>
#endif
#include "asterisk/stun.h"
@@ -145,6 +146,9 @@ static pj_str_t turnaddr;
static int turnport = DEFAULT_TURN_PORT;
static pj_str_t turnusername;
static pj_str_t turnpassword;
+static struct ast_ha *ice_blacklist = NULL; /*!< Blacklisted ICE networks */
+static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE;
+
/*! \brief Pool factory used by pjlib to allocate memory. */
static pj_caching_pool cachingpool;
@@ -2446,11 +2450,38 @@ static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t
}
#ifdef HAVE_PJPROJECT
+/*!
+ * \internal
+ * \brief Checks an address against the ICE blacklist
+ * \note If there is no ice_blacklist list, always returns 0
+ *
+ * \param address The address to consider
+ * \retval 0 if address is not ICE blacklisted
+ * \retval 1 if address is ICE blacklisted
+ */
+static int rtp_address_is_ice_blacklisted(const pj_sockaddr_t *address)
+{
+ char buf[PJ_INET6_ADDRSTRLEN];
+ struct ast_sockaddr saddr;
+ int result = 1;
+
+ ast_sockaddr_parse(&saddr, pj_sockaddr_print(address, buf, sizeof(buf), 0), 0);
+
+ ast_rwlock_rdlock(&ice_blacklist_lock);
+ if (!ice_blacklist || (ast_apply_ha(ice_blacklist, &saddr) == AST_SENSE_ALLOW)) {
+ result = 0;
+ }
+ ast_rwlock_unlock(&ice_blacklist_lock);
+
+ return result;
+}
+
static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *addr, int port, int component,
int transport)
{
pj_sockaddr address[16];
unsigned int count = PJ_ARRAY_SIZE(address), pos = 0;
+ int basepos = -1;
/* Add all the local interface IP addresses */
if (ast_sockaddr_is_ipv4(addr)) {
@@ -2464,9 +2495,18 @@ static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct
host_candidate_overrides_apply(count, address);
for (pos = 0; pos < count; pos++) {
- pj_sockaddr_set_port(&address[pos], port);
- ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_HOST, 65535, &address[pos], &address[pos], NULL,
+ if (!rtp_address_is_ice_blacklisted(&address[pos])) {
+ if (basepos == -1) {
+ basepos = pos;
+ }
+ pj_sockaddr_set_port(&address[pos], port);
+ ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_HOST, 65535, &address[pos], &address[pos], NULL,
pj_sockaddr_get_len(&address[pos]));
+ }
+ }
+ if (basepos == -1) {
+ /* start with first address unless excluded above */
+ basepos = 0;
}
/* If configured to use a STUN server to get our external mapped address do so */
@@ -2475,15 +2515,27 @@ static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct
if (!ast_stun_request(component == AST_RTP_ICE_COMPONENT_RTCP ? rtp->rtcp->s : rtp->s, &stunaddr, NULL, &answer)) {
pj_sockaddr base;
+ pj_sockaddr ext;
pj_str_t mapped = pj_str(ast_strdupa(ast_inet_ntoa(answer.sin_addr)));
+ int srflx = 1;
/* Use the first local host candidate as the base */
- pj_sockaddr_cp(&base, &address[0]);
+ pj_sockaddr_cp(&base, &address[basepos]);
+
+ pj_sockaddr_init(pj_AF_INET(), &ext, &mapped, ntohs(answer.sin_port));
- pj_sockaddr_init(pj_AF_INET(), &address[0], &mapped, ntohs(answer.sin_port));
+ /* If the returned address is the same as one of our host candidates, don't send the srflx */
+ for (pos = 0; pos < count; pos++) {
+ if ((pj_sockaddr_cmp(&address[pos], &ext) == 0) && !rtp_address_is_ice_blacklisted(&address[pos])) {
+ srflx = 0;
+ break;
+ }
+ }
- ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_SRFLX, 65535, &address[0], &base,
- &base, pj_sockaddr_get_len(&address[0]));
+ if (srflx) {
+ ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_SRFLX, 65535, &ext, &base,
+ &base, pj_sockaddr_get_len(&ext));
+ }
}
}
@@ -5393,6 +5445,10 @@ static int rtp_reload(int reload)
turnusername = pj_str(NULL);
turnpassword = pj_str(NULL);
host_candidate_overrides_clear();
+ ast_rwlock_wrlock(&ice_blacklist_lock);
+ ast_free_ha(ice_blacklist);
+ ice_blacklist = NULL;
+ ast_rwlock_unlock(&ice_blacklist_lock);
#endif
if (cfg) {
@@ -5502,6 +5558,25 @@ static int rtp_reload(int reload)
AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
}
AST_RWLIST_UNLOCK(&host_candidates);
+
+ /* Read ICE blacklist configuration lines */
+ ast_rwlock_wrlock(&ice_blacklist_lock);
+ for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
+ if (!strcasecmp(var->name, "ice_blacklist")) {
+ struct ast_ha *na;
+ int ha_error = 0;
+ if (!(na = ast_append_ha("d", var->value, ice_blacklist, &ha_error))) {
+ ast_log(LOG_WARNING, "Invalid ice_blacklist value: %s\n", var->value);
+ } else {
+ ice_blacklist = na;
+ }
+ if (ha_error) {
+ ast_log(LOG_ERROR, "Bad ice_blacklist configuration value line %d : %s\n", var->lineno, var->value);
+ }
+ }
+ }
+ ast_rwlock_unlock(&ice_blacklist_lock);
+
#endif
ast_config_destroy(cfg);
}