summaryrefslogtreecommitdiff
path: root/res/res_pjsip_endpoint_identifier_ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip_endpoint_identifier_ip.c')
-rw-r--r--res/res_pjsip_endpoint_identifier_ip.c120
1 files changed, 77 insertions, 43 deletions
diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c
index 14716234a..14f4cfd1a 100644
--- a/res/res_pjsip_endpoint_identifier_ip.c
+++ b/res/res_pjsip_endpoint_identifier_ip.c
@@ -105,7 +105,7 @@ struct ip_identify_match {
struct ast_ha *matches;
/*! \brief Perform SRV resolution of hostnames */
unsigned int srv_lookups;
- /*! \brief Hosts to be resolved after applying configuration */
+ /*! \brief Hosts to be resolved when applying configuration */
struct ao2_container *hosts;
};
@@ -150,8 +150,8 @@ static int header_identify_match_check(void *obj, void *arg, int flags)
c_header = ast_strdupa(identify->match_header);
c_value = strchr(c_header, ':');
if (!c_value) {
- ast_log(LOG_WARNING, "Identify '%s' has invalid header_match: No ':' separator found!\n",
- ast_sorcery_object_get_id(identify));
+ /* This should not be possible. The object cannot be created if so. */
+ ast_assert(0);
return 0;
}
*c_value = '\0';
@@ -161,17 +161,19 @@ static int header_identify_match_check(void *obj, void *arg, int flags)
pj_header_name = pj_str(c_header);
header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pj_header_name, NULL);
if (!header) {
- ast_debug(3, "SIP message does not contain header '%s'\n", c_header);
+ ast_debug(3, "Identify '%s': SIP message does not have header '%s'\n",
+ ast_sorcery_object_get_id(identify),
+ c_header);
return 0;
}
pj_header_value = pj_str(c_value);
if (pj_strcmp(&pj_header_value, &header->hvalue)) {
- ast_debug(3, "SIP message contains header '%s' but value '%.*s' does not match value '%s' for endpoint '%s'\n",
+ ast_debug(3, "Identify '%s': SIP message has header '%s' but value '%.*s' does not match '%s'\n",
+ ast_sorcery_object_get_id(identify),
c_header,
(int) pj_strlen(&header->hvalue), pj_strbuf(&header->hvalue),
- c_value,
- identify->endpoint_name);
+ c_value);
return 0;
}
@@ -261,7 +263,7 @@ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, con
}
for (i = 0; i < num_addrs; ++i) {
- /* Check if the address is already in the list, if so don't bother adding it again */
+ /* Check if the address is already in the list, if so don't add it again */
if (identify->matches && (ast_apply_ha(identify->matches, &addrs[i]) != AST_SENSE_ALLOW)) {
continue;
}
@@ -283,14 +285,13 @@ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, con
}
/*! \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)
+static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host, int results)
{
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);
@@ -372,10 +373,33 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj)
char *current_string;
struct ao2_iterator i;
+ /* Validate the identify object configuration */
+ if (ast_strlen_zero(identify->endpoint_name)) {
+ ast_log(LOG_ERROR, "Identify '%s' missing required endpoint name.\n",
+ ast_sorcery_object_get_id(identify));
+ return -1;
+ }
+ if (ast_strlen_zero(identify->match_header) /* No header to match */
+ /* and no static IP addresses with a mask */
+ && !identify->matches
+ /* and no addresses to resolve */
+ && (!identify->hosts || !ao2_container_count(identify->hosts))) {
+ ast_log(LOG_ERROR, "Identify '%s' is not configured to match anything.\n",
+ ast_sorcery_object_get_id(identify));
+ return -1;
+ }
+ if (!ast_strlen_zero(identify->match_header)
+ && !strchr(identify->match_header, ':')) {
+ ast_log(LOG_ERROR, "Identify '%s' missing ':' separator in match_header '%s'.\n",
+ ast_sorcery_object_get_id(identify), identify->match_header);
+ return -1;
+ }
+
if (!identify->hosts) {
return 0;
}
+ /* Resolve the match addresses now */
i = ao2_iterator_init(identify->hosts, 0);
while ((current_string = ao2_iterator_next(&i))) {
struct ast_sockaddr address;
@@ -383,26 +407,29 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj)
/* If the provided string is not an IP address perform SRV resolution on it */
if (identify->srv_lookups && !ast_sockaddr_parse(&address, current_string, 0)) {
- results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string);
+ results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string,
+ results);
if (results != -1) {
- results += ip_identify_match_srv_lookup(identify, "_sip._tcp", current_string);
+ results = ip_identify_match_srv_lookup(identify, "_sip._tcp",
+ current_string, results);
}
if (results != -1) {
- results += ip_identify_match_srv_lookup(identify, "_sips._tcp", current_string);
+ results = ip_identify_match_srv_lookup(identify, "_sips._tcp",
+ current_string, results);
}
}
- /* If SRV falls fall back to a normal lookup on the host itself */
+ /* If SRV fails fall back to a normal lookup on the host itself */
if (!results) {
results = ip_identify_match_host_lookup(identify, current_string);
}
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));
+ ast_log(LOG_WARNING, "Identify '%s' provided address '%s' did not resolve to any address\n",
+ ast_sorcery_object_get_id(identify), current_string);
} 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));
+ ast_log(LOG_ERROR, "Identify '%s' failed when adding resolution results of '%s'\n",
+ ast_sorcery_object_get_id(identify), current_string);
ao2_ref(current_string, -1);
ao2_iterator_destroy(&i);
return -1;
@@ -457,47 +484,54 @@ static int sip_identify_to_ami(const struct ip_identify_match *identify,
return ast_sip_sorcery_object_to_ami(identify, buf);
}
-static int find_identify_by_endpoint(void *obj, void *arg, int flags)
+static int send_identify_ami_event(void *obj, void *arg, void *data, int flags)
{
struct ip_identify_match *identify = obj;
const char *endpoint_name = arg;
+ struct ast_sip_ami *ami = data;
+ struct ast_str *buf;
+
+ /* Build AMI event */
+ buf = ast_sip_create_ami_event("IdentifyDetail", ami);
+ if (!buf) {
+ return CMP_STOP;
+ }
+ if (sip_identify_to_ami(identify, &buf)) {
+ ast_free(buf);
+ return CMP_STOP;
+ }
+ ast_str_append(&buf, 0, "EndpointName: %s\r\n", endpoint_name);
+
+ /* Send AMI event */
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+ ++ami->count;
- return strcmp(identify->endpoint_name, endpoint_name) ? 0 : CMP_MATCH;
+ ast_free(buf);
+ return 0;
}
static int format_ami_endpoint_identify(const struct ast_sip_endpoint *endpoint,
struct ast_sip_ami *ami)
{
- RAII_VAR(struct ao2_container *, identifies, NULL, ao2_cleanup);
- RAII_VAR(struct ip_identify_match *, identify, NULL, ao2_cleanup);
- RAII_VAR(struct ast_str *, buf, NULL, ast_free);
+ struct ao2_container *identifies;
+ struct ast_variable fields = {
+ .name = "endpoint",
+ .value = ast_sorcery_object_get_id(endpoint),
+ };
identifies = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ AST_RETRIEVE_FLAG_MULTIPLE, &fields);
if (!identifies) {
return -1;
}
- identify = ao2_callback(identifies, 0, find_identify_by_endpoint,
- (void *) ast_sorcery_object_get_id(endpoint));
- if (!identify) {
- return 1;
- }
-
- if (!(buf = ast_sip_create_ami_event("IdentifyDetail", ami))) {
- return -1;
- }
-
- if (sip_identify_to_ami(identify, &buf)) {
- return -1;
- }
-
- ast_str_append(&buf, 0, "EndpointName: %s\r\n",
- ast_sorcery_object_get_id(endpoint));
-
- astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
- ami->count++;
+ /* Build and send any found identify object's AMI IdentifyDetail event. */
+ ao2_callback_data(identifies, OBJ_MULTIPLE | OBJ_NODATA,
+ send_identify_ami_event,
+ (void *) ast_sorcery_object_get_id(endpoint),
+ ami);
+ ao2_ref(identifies, -1);
return 0;
}