summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c167
1 files changed, 131 insertions, 36 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 3cc0a93f2..6cc7cbb64 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1651,12 +1651,15 @@ static int sip_poke_peer_s(void *data);
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
static void reg_source_db(struct sip_peer *peer);
static void destroy_association(struct sip_peer *peer);
+static void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno);
static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v);
/* Realtime device support */
static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expirey);
static struct sip_user *realtime_user(const char *username);
static void update_peer(struct sip_peer *p, int expiry);
+static struct ast_variable *get_insecure_variable_from_config(struct ast_config *config);
+static const char *get_name_from_variable(struct ast_variable *var, const char *newpeername);
static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
@@ -2933,12 +2936,36 @@ static void update_peer(struct sip_peer *p, int expiry)
}
}
+static struct ast_variable *get_insecure_variable_from_config(struct ast_config *config)
+{
+ struct ast_variable *var;
+ struct ast_flags flags = {0};
+ char *cat = NULL;
+ const char *insecure;
+ while ((cat = ast_category_browse(config, cat))) {
+ insecure = ast_variable_retrieve(config, cat, "insecure");
+ set_insecure_flags(&flags, insecure, -1);
+ if (ast_test_flag(&flags, SIP_INSECURE_PORT)) {
+ var = ast_category_root(config, cat);
+ break;
+ }
+ }
+ return var;
+}
+
+static const char *get_name_from_variable(struct ast_variable *var, const char *newpeername)
+{
+ struct ast_variable *tmp;
+ for (tmp = var; tmp; tmp = tmp->next) {
+ if (!newpeername && !strcasecmp(tmp->name, "name"))
+ newpeername = tmp->value;
+ }
+ return newpeername;
+}
/*! \brief realtime_peer: Get peer from realtime storage
* Checks the "sippeers" realtime family from extconfig.conf
* Checks the "sipregs" realtime family from extconfig.conf if it's configured.
- * \todo Consider adding check of port address when matching here to follow the same
- * algorithm as for static peers. Will we break anything by adding that?
*/
static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_in *sin)
{
@@ -2946,7 +2973,11 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
struct ast_variable *var = NULL;
struct ast_variable *varregs = NULL;
struct ast_variable *tmp;
+ struct ast_config *peerlist = NULL;
char ipaddr[INET_ADDRSTRLEN];
+ char portstring[6]; /*up to 5 digits plus null terminator*/
+ char *cat = NULL;
+ unsigned short portnum;
int realtimeregs = ast_check_realtime("sipregs");
/* First check on peer name */
@@ -2956,39 +2987,87 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
varregs = ast_load_realtime("sipregs", "name", newpeername, NULL);
} else if (sin) { /* Then check on IP address for dynamic peers */
ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
- var = ast_load_realtime("sippeers", "host", ipaddr, NULL); /* First check for fixed IP hosts */
+ portnum = ntohs(sin->sin_port);
+ sprintf(portstring, "%u", portnum);
+ var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, NULL); /* First check for fixed IP hosts */
if (var) {
if (realtimeregs) {
- for (tmp = var; tmp; tmp = tmp->next) {
- if (!newpeername && !strcasecmp(tmp->name, "name"))
- newpeername = tmp->value;
- }
+ newpeername = get_name_from_variable(var, newpeername);
varregs = ast_load_realtime("sipregs", "name", newpeername, NULL);
}
} else {
if (realtimeregs)
- varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, NULL); /* Then check for registered hosts */
+ varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, "port", portstring, NULL); /* Then check for registered hosts */
else
- var = ast_load_realtime("sippeers", "ipaddr", ipaddr, NULL); /* Then check for registered hosts */
+ var = ast_load_realtime("sippeers", "ipaddr", ipaddr, "port", portstring, NULL); /* Then check for registered hosts */
if (varregs) {
- for (tmp = varregs; tmp; tmp = tmp->next) {
- if (!newpeername && !strcasecmp(tmp->name, "name"))
- newpeername = tmp->value;
- }
+ newpeername = get_name_from_variable(varregs, newpeername);
var = ast_load_realtime("sippeers", "name", newpeername, NULL);
}
}
+ if(!var) { /*We couldn't match on ipaddress and port, so we need to check if port is insecure*/
+ peerlist = ast_load_realtime_multientry("sippeers", "host", ipaddr, NULL);
+ if (peerlist) {
+ var = get_insecure_variable_from_config(peerlist);
+ if(var) {
+ if (realtimeregs) {
+ newpeername = get_name_from_variable(var, newpeername);
+ varregs = ast_load_realtime("sipregs", "name", newpeername, NULL);
+ }
+ } else { /*var wasn't found in the list of "hosts", so try "ipaddr"*/
+ peerlist = NULL;
+ cat = NULL;
+ peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, NULL);
+ if(peerlist) {
+ var = get_insecure_variable_from_config(peerlist);
+ if(var) {
+ if (realtimeregs) {
+ newpeername = get_name_from_variable(var, newpeername);
+ varregs = ast_load_realtime("sipregs", "name", newpeername, NULL);
+ }
+ }
+ }
+ }
+ } else {
+ if(realtimeregs) {
+ peerlist = ast_load_realtime_multientry("sipregs", "ipaddr", ipaddr, NULL);
+ if (peerlist) {
+ varregs = get_insecure_variable_from_config(peerlist);
+ if (varregs) {
+ newpeername = get_name_from_variable(varregs, newpeername);
+ var = ast_load_realtime("sippeers", "name", newpeername, NULL);
+ }
+ }
+ } else {
+ peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, NULL);
+ if (peerlist) {
+ var = get_insecure_variable_from_config(peerlist);
+ if (var) {
+ newpeername = get_name_from_variable(var, newpeername);
+ varregs = ast_load_realtime("sipregs", "name", newpeername, NULL);
+ }
+ }
+ }
+ }
+ }
}
- if (!var)
+ if (!var) {
+ if (peerlist)
+ ast_config_destroy(peerlist);
return NULL;
+ }
for (tmp = var; tmp; tmp = tmp->next) {
/* If this is type=user, then skip this object. */
if (!strcasecmp(tmp->name, "type") &&
!strcasecmp(tmp->value, "user")) {
- ast_variables_destroy(var);
- ast_variables_destroy(varregs);
+ if(peerlist)
+ ast_config_destroy(peerlist);
+ else {
+ ast_variables_destroy(var);
+ ast_variables_destroy(varregs);
+ }
return NULL;
} else if (!newpeername && !strcasecmp(tmp->name, "name")) {
newpeername = tmp->value;
@@ -2997,7 +3076,10 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
if (!newpeername) { /* Did not find peer in realtime */
ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr);
- ast_variables_destroy(var);
+ if(peerlist)
+ ast_config_destroy(peerlist);
+ else
+ ast_variables_destroy(var);
return NULL;
}
@@ -3005,8 +3087,12 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
/* Peer found in realtime, now build it in memory */
peer = build_peer(newpeername, var, varregs, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS));
if (!peer) {
- ast_variables_destroy(var);
- ast_variables_destroy(varregs);
+ if(peerlist)
+ ast_config_destroy(peerlist);
+ else {
+ ast_variables_destroy(var);
+ ast_variables_destroy(varregs);
+ }
return NULL;
}
@@ -3025,8 +3111,12 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
} else {
peer->is_realtime = 1;
}
- ast_variables_destroy(var);
- ast_variables_destroy(varregs);
+ if (peerlist)
+ ast_config_destroy(peerlist);
+ else {
+ ast_variables_destroy(var);
+ ast_variables_destroy(varregs);
+ }
return peer;
}
@@ -16656,6 +16746,25 @@ static struct ast_channel *sip_request_call(const char *type, int format, void *
return tmpc;
}
+static void set_insecure_flags (struct ast_flags *flags, const char *value, int lineno)
+{
+ if (!ast_false(value)) {
+ char buf[64];
+ char *word, *next;
+
+ ast_copy_string(buf, value, sizeof(buf));
+ next = buf;
+ while ((word = strsep(&next, ","))) {
+ if (!strcasecmp(word, "port"))
+ ast_set_flag(&flags[0], SIP_INSECURE_PORT);
+ else if (!strcasecmp(word, "invite"))
+ ast_set_flag(&flags[0], SIP_INSECURE_INVITE);
+ else
+ ast_log(LOG_WARNING, "Unknown insecure mode '%s' on line %d\n", value, lineno);
+ }
+ }
+}
+
/*!
\brief Handle flag-type options common to configuration of devices - users and peers
\param flags array of two struct ast_flags
@@ -16729,21 +16838,7 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "insecure")) {
ast_set_flag(&mask[0], SIP_INSECURE);
ast_clear_flag(&flags[0], SIP_INSECURE);
- if (!ast_false(v->value)) {
- char buf[64];
- char *word, *next;
-
- ast_copy_string(buf, v->value, sizeof(buf));
- next = buf;
- while ((word = strsep(&next, ","))) {
- if (!strcasecmp(word, "port"))
- ast_set_flag(&flags[0], SIP_INSECURE_PORT);
- else if (!strcasecmp(word, "invite"))
- ast_set_flag(&flags[0], SIP_INSECURE_INVITE);
- else
- ast_log(LOG_WARNING, "Unknown insecure mode '%s' on line %d\n", v->value, v->lineno);
- }
- }
+ set_insecure_flags(&flags[0], v->value, v->lineno);
} else if (!strcasecmp(v->name, "progressinband")) {
ast_set_flag(&mask[0], SIP_PROG_INBAND);
ast_clear_flag(&flags[0], SIP_PROG_INBAND);