mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-03 03:02:15 +00:00
Merge "res_pjsip_endpoint_identifier_ip: Add support for SRV lookups." into 13
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -44,6 +44,12 @@ res_pjsip
|
|||||||
ID, AuthenticateQualify, OutboundProxy, Path, QualifyFrequency and
|
ID, AuthenticateQualify, OutboundProxy, Path, QualifyFrequency and
|
||||||
QualifyTimeout. Existing fields have not been disturbed.
|
QualifyTimeout. Existing fields have not been disturbed.
|
||||||
|
|
||||||
|
res_pjsip_endpoint_identifier_ip
|
||||||
|
------------------
|
||||||
|
* SRV lookups can now be done on provided hostnames to determine additional
|
||||||
|
source IP addresses for requests. This is configurable using the
|
||||||
|
"srv_lookups" option on the identify and defaults to "yes".
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes from Asterisk 13.12.0 to Asterisk 13.13.0 ----------
|
--- Functionality changes from Asterisk 13.12.0 to Asterisk 13.13.0 ----------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
@@ -0,0 +1,31 @@
|
|||||||
|
"""add srv_lookups to identify
|
||||||
|
|
||||||
|
Revision ID: 28ab27a7826d
|
||||||
|
Revises: 4468b4a91372
|
||||||
|
Create Date: 2017-01-06 14:53:38.829655
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '28ab27a7826d'
|
||||||
|
down_revision = '4468b4a91372'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects.postgresql import ENUM
|
||||||
|
|
||||||
|
YESNO_NAME = 'yesno_values'
|
||||||
|
YESNO_VALUES = ['yes', 'no']
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
############################# Enums ##############################
|
||||||
|
|
||||||
|
# yesno_values have already been created, so use postgres enum object
|
||||||
|
# type to get around "already created" issue - works okay with mysql
|
||||||
|
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
|
||||||
|
|
||||||
|
op.add_column('ps_endpoint_id_ips', sa.Column('srv_lookups', yesno_values))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('ps_endpoint_id_ips', 'srv_lookups')
|
@@ -51,6 +51,13 @@
|
|||||||
mask with a slash ('/')
|
mask with a slash ('/')
|
||||||
</para></description>
|
</para></description>
|
||||||
</configOption>
|
</configOption>
|
||||||
|
<configOption name="srv_lookups" default="yes">
|
||||||
|
<synopsis>Perform SRV lookups for provided hostnames.</synopsis>
|
||||||
|
<description><para>When enabled, <replaceable>srv_lookups</replaceable> will
|
||||||
|
perform SRV lookups for _sip._udp, _sip._tcp, and _sips._tcp of the given
|
||||||
|
hostnames to determine additional addresses that traffic may originate from.
|
||||||
|
</para></description>
|
||||||
|
</configOption>
|
||||||
<configOption name="type">
|
<configOption name="type">
|
||||||
<synopsis>Must be of type 'identify'.</synopsis>
|
<synopsis>Must be of type 'identify'.</synopsis>
|
||||||
</configOption>
|
</configOption>
|
||||||
@@ -70,6 +77,8 @@ struct ip_identify_match {
|
|||||||
);
|
);
|
||||||
/*! \brief Networks or addresses that should match this */
|
/*! \brief Networks or addresses that should match this */
|
||||||
struct ast_ha *matches;
|
struct ast_ha *matches;
|
||||||
|
/*! \brief Perform SRV resolution of hostnames */
|
||||||
|
unsigned int srv_lookups;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief Destructor function for a matching object */
|
/*! \brief Destructor function for a matching object */
|
||||||
@@ -153,6 +162,72 @@ static struct ast_sip_endpoint_identifier ip_identifier = {
|
|||||||
.identify_endpoint = ip_identify,
|
.identify_endpoint = ip_identify,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief Helper function which performs a host lookup and adds result to identify match */
|
||||||
|
static int ip_identify_match_host_lookup(struct ip_identify_match *identify, const char *host)
|
||||||
|
{
|
||||||
|
struct ast_sockaddr *addrs;
|
||||||
|
int num_addrs = 0, error = 0, i;
|
||||||
|
int results = 0;
|
||||||
|
|
||||||
|
num_addrs = ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC);
|
||||||
|
if (!num_addrs) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_addrs; ++i) {
|
||||||
|
/* Check if the address is already in the list, if so don't bother adding it again */
|
||||||
|
if (identify->matches && (ast_apply_ha(identify->matches, &addrs[i]) != AST_SENSE_ALLOW)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We deny what we actually want to match because there is an implicit permit all rule for ACLs */
|
||||||
|
identify->matches = ast_append_ha("d", ast_sockaddr_stringify_addr(&addrs[i]), identify->matches, &error);
|
||||||
|
|
||||||
|
if (!identify->matches || error) {
|
||||||
|
results = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
results += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_free(addrs);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Helper function which performs an SRV lookup and then resolves the hostname */
|
||||||
|
static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host)
|
||||||
|
{
|
||||||
|
char service[NI_MAXHOST];
|
||||||
|
struct srv_context *context = NULL;
|
||||||
|
int srv_ret;
|
||||||
|
const char *srvhost;
|
||||||
|
unsigned short srvport;
|
||||||
|
int results = 0;
|
||||||
|
|
||||||
|
snprintf(service, sizeof(service), "%s.%s", prefix, host);
|
||||||
|
|
||||||
|
while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
|
||||||
|
int hosts;
|
||||||
|
|
||||||
|
/* In the case of the SRV lookup we don't care if it fails, we will output a log message
|
||||||
|
* when we fallback to a normal lookup.
|
||||||
|
*/
|
||||||
|
hosts = ip_identify_match_host_lookup(identify, srvhost);
|
||||||
|
if (hosts == -1) {
|
||||||
|
results = -1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
results += hosts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_srv_cleanup(&context);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief Custom handler for match field */
|
/*! \brief Custom handler for match field */
|
||||||
static int ip_identify_match_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
static int ip_identify_match_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||||
{
|
{
|
||||||
@@ -165,9 +240,9 @@ static int ip_identify_match_handler(const struct aco_option *opt, struct ast_va
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((current_string = ast_strip(strsep(&input_string, ",")))) {
|
while ((current_string = ast_strip(strsep(&input_string, ",")))) {
|
||||||
struct ast_sockaddr *addrs;
|
|
||||||
int num_addrs = 0, error = 0, i;
|
|
||||||
char *mask = strrchr(current_string, '/');
|
char *mask = strrchr(current_string, '/');
|
||||||
|
struct ast_sockaddr address;
|
||||||
|
int error, results = 0;
|
||||||
|
|
||||||
if (ast_strlen_zero(current_string)) {
|
if (ast_strlen_zero(current_string)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -185,28 +260,28 @@ static int ip_identify_match_handler(const struct aco_option *opt, struct ast_va
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_addrs = ast_sockaddr_resolve(&addrs, current_string, PARSE_PORT_FORBID, AST_AF_UNSPEC);
|
/* If the provided string is not an IP address perform SRV resolution on it */
|
||||||
if (!num_addrs) {
|
if (identify->srv_lookups && !ast_sockaddr_parse(&address, current_string, 0)) {
|
||||||
ast_log(LOG_ERROR, "Address '%s' provided on ip endpoint identifier '%s' did not resolve to any address\n",
|
results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string);
|
||||||
var->value, ast_sorcery_object_get_id(obj));
|
if (results != -1) {
|
||||||
return -1;
|
results += ip_identify_match_srv_lookup(identify, "_sip._tcp", current_string);
|
||||||
}
|
}
|
||||||
|
if (results != -1) {
|
||||||
for (i = 0; i < num_addrs; ++i) {
|
results += ip_identify_match_srv_lookup(identify, "_sips._tcp", current_string);
|
||||||
/* We deny what we actually want to match because there is an implicit permit all rule for ACLs */
|
|
||||||
identify->matches = ast_append_ha("d", ast_sockaddr_stringify_addr(&addrs[i]), identify->matches, &error);
|
|
||||||
|
|
||||||
if (!identify->matches || error) {
|
|
||||||
ast_log(LOG_ERROR, "Failed to add address '%s' to ip endpoint identifier '%s'\n",
|
|
||||||
ast_sockaddr_stringify_addr(&addrs[i]), ast_sorcery_object_get_id(obj));
|
|
||||||
error = -1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_free(addrs);
|
/* If SRV falls fall back to a normal lookup on the host itself */
|
||||||
|
if (!results) {
|
||||||
|
results = ip_identify_match_host_lookup(identify, current_string);
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
if (results == 0) {
|
||||||
|
ast_log(LOG_ERROR, "Address '%s' provided on ip endpoint identifier '%s' did not resolve to any address\n",
|
||||||
|
current_string, ast_sorcery_object_get_id(obj));
|
||||||
|
} else if (results == -1) {
|
||||||
|
ast_log(LOG_ERROR, "An error occurred when adding resolution results of '%s' on '%s'\n",
|
||||||
|
current_string, ast_sorcery_object_get_id(obj));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,6 +544,7 @@ static int load_module(void)
|
|||||||
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "type", "", OPT_NOOP_T, 0, 0);
|
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "type", "", OPT_NOOP_T, 0, 0);
|
||||||
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, endpoint_name));
|
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, endpoint_name));
|
||||||
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0);
|
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0);
|
||||||
|
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "srv_lookups", "yes", OPT_BOOL_T, 1, FLDSET(struct ip_identify_match, srv_lookups));
|
||||||
ast_sorcery_load_object(ast_sip_get_sorcery(), "identify");
|
ast_sorcery_load_object(ast_sip_get_sorcery(), "identify");
|
||||||
|
|
||||||
ast_sip_register_endpoint_identifier_with_name(&ip_identifier, "ip");
|
ast_sip_register_endpoint_identifier_with_name(&ip_identifier, "ip");
|
||||||
|
Reference in New Issue
Block a user