Pārlūkot izejas kodu

Merge branch 'master' of ssh://git.sip-router.org/kamailio

* 'master' of ssh://git.sip-router.org/kamailio:
  permissions: fixed previous commit which used invalid variable
  presence_dialoginfo: handle all states to get most relevant xml
  tls: the pointer of cfg structure
  websocket: store sub protocol value for later use in encode_and_send_ws_frame()
  htable: free temporary slots used to reload hash table via rpc command
  htable: use system malloc for temporary allocation of hash table realod slots
  permissions: refreshed the README file
  permissions: note about peer tag mode that applies only for allow_trusted()
  permissions: set peer tag avp for allow_address_group()
Hugh Waite 11 gadi atpakaļ
vecāks
revīzija
3a5af040ed

+ 30 - 3
modules/htable/htable.c

@@ -490,7 +490,8 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 		return init_mi_tree( 500, "no such hash table", 18);
 		return init_mi_tree( 500, "no such hash table", 18);
 	}
 	}
 	memcpy(&nht, ht, sizeof(ht_t));
 	memcpy(&nht, ht, sizeof(ht_t));
-	nht.entries = (ht_entry_t*)pkg_malloc(nht.htsize*sizeof(ht_entry_t));
+	/* it's temporary operation - use system malloc */
+	nht.entries = (ht_entry_t*)malloc(nht.htsize*sizeof(ht_entry_t));
 	if(nht.entries == NULL)
 	if(nht.entries == NULL)
 	{
 	{
 		ht_db_close_con();
 		ht_db_close_con();
@@ -500,6 +501,18 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 
 
 	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
 	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
 	{
 	{
+		/* free any entry set if it was a partial load */
+		for(i=0; i<nht.htsize; i++)
+		{
+			first = nht.entries[i].first;
+			while(first)
+			{
+				it = first;
+				first = first->next;
+				ht_cell_free(it);
+			}
+		}
+		free(nht.entries);
 		ht_db_close_con();
 		ht_db_close_con();
 		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
 		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
 	}
 	}
@@ -525,7 +538,7 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 			ht_cell_free(it);
 			ht_cell_free(it);
 		}
 		}
 	}
 	}
-	pkg_free(nht.entries);
+	free(nht.entries);
 	ht_db_close_con();
 	ht_db_close_con();
 	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
 	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
 }
 }
@@ -1036,7 +1049,8 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 
 
 
 
 	memcpy(&nht, ht, sizeof(ht_t));
 	memcpy(&nht, ht, sizeof(ht_t));
-	nht.entries = (ht_entry_t*)shm_malloc(nht.htsize*sizeof(ht_entry_t));
+	/* it's temporary operation - use system malloc */
+	nht.entries = (ht_entry_t*)malloc(nht.htsize*sizeof(ht_entry_t));
 	if(nht.entries == NULL)
 	if(nht.entries == NULL)
 	{
 	{
 		ht_db_close_con();
 		ht_db_close_con();
@@ -1047,6 +1061,18 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 
 
 	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
 	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
 	{
 	{
+		/* free any entry set if it was a partial load */
+		for(i=0; i<nht.htsize; i++)
+		{
+			first = nht.entries[i].first;
+			while(first)
+			{
+				it = first;
+				first = first->next;
+				ht_cell_free(it);
+			}
+		}
+		free(nht.entries);
 		ht_db_close_con();
 		ht_db_close_con();
 		rpc->fault(c, 500, "Mtree reload failed");
 		rpc->fault(c, 500, "Mtree reload failed");
 		return;
 		return;
@@ -1073,6 +1099,7 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 			ht_cell_free(it);
 			ht_cell_free(it);
 		}
 		}
 	}
 	}
+	free(nht.entries);
 	ht_db_close_con();
 	ht_db_close_con();
 	return;
 	return;
 }
 }

+ 59 - 58
modules/permissions/README

@@ -14,9 +14,9 @@ Edited by
 
 
 Juha Heinanen
 Juha Heinanen
 
 
-   Copyright © 2003 Miklos Tirpak
+   Copyright © 2003 Miklos Tirpak
 
 
-   Copyright © 2006-2008 Juha Heinanen
+   Copyright © 2006-2008 Juha Heinanen
      __________________________________________________________________
      __________________________________________________________________
 
 
    Table of Contents
    Table of Contents
@@ -250,7 +250,7 @@ Chapter 1. Admin Guide
 
 
    Function for registration checking is called allow_register and the
    Function for registration checking is called allow_register and the
    algorithm is very similar to the algorithm described in Section 1.1,
    algorithm is very similar to the algorithm described in Section 1.1,
-   “Call Routing�. The only difference is in the way how pairs are
+   "Call Routing". The only difference is in the way how pairs are
    created.
    created.
 
 
    Instead of From header field the function uses To header field because
    Instead of From header field the function uses To header field because
@@ -261,8 +261,8 @@ Chapter 1. Admin Guide
    Thus, pairs used in matching will look like this: (To, Contact 1), (To,
    Thus, pairs used in matching will look like this: (To, Contact 1), (To,
    Contact 2), (To, Contact 3), and so on..
    Contact 2), (To, Contact 3), and so on..
 
 
-   The algorithm of matching is same as described in Section 1.1, “Call
-   Routing�.
+   The algorithm of matching is same as described in Section 1.1, "Call
+   Routing".
 
 
 1.3. URI Permissions
 1.3. URI Permissions
 
 
@@ -387,7 +387,7 @@ Chapter 1. Admin Guide
    specify full pathname then the directory in which is the main config
    specify full pathname then the directory in which is the main config
    file is located will be used.
    file is located will be used.
 
 
-   Default value is “permissions.allow�.
+   Default value is "permissions.allow".
 
 
    Example 1.1. Set default_allow_file parameter
    Example 1.1. Set default_allow_file parameter
 ...
 ...
@@ -400,7 +400,7 @@ modparam("permissions", "default_allow_file", "/etc/permissions.allow")
    without parameters. If you don't specify full pathname then the
    without parameters. If you don't specify full pathname then the
    directory in which the main config file is located will be used.
    directory in which the main config file is located will be used.
 
 
-   Default value is “permissions.deny�.
+   Default value is "permissions.deny".
 
 
    Example 1.2. Set default_deny_file parameter
    Example 1.2. Set default_deny_file parameter
 ...
 ...
@@ -435,7 +435,7 @@ Note
 
 
    Including leading dot.
    Including leading dot.
 
 
-   Default value is “.allow�.
+   Default value is ".allow".
 
 
    Example 1.4. Set allow_suffix parameter
    Example 1.4. Set allow_suffix parameter
 ...
 ...
@@ -452,7 +452,7 @@ Note
 
 
    Including leading dot.
    Including leading dot.
 
 
-   Default value is “.deny�.
+   Default value is ".deny".
 
 
    Example 1.5. Set deny_suffix parameter
    Example 1.5. Set deny_suffix parameter
 ...
 ...
@@ -464,7 +464,7 @@ modparam("permissions", "deny_suffix", ".deny")
    This is URL of the database to be used to store rules used by
    This is URL of the database to be used to store rules used by
    allow_trusted function.
    allow_trusted function.
 
 
-   Default value is “NULL�.
+   Default value is "NULL".
 
 
    Example 1.6. Set db_url parameter
    Example 1.6. Set db_url parameter
 ...
 ...
@@ -476,7 +476,7 @@ modparam("permissions", "db_url", "dbdriver://username:password@dbhost/dbname")
    Name of database table containing IP subnets and DNS domain names used
    Name of database table containing IP subnets and DNS domain names used
    by allow_address and allow_source_address functions.
    by allow_address and allow_source_address functions.
 
 
-   Default value is “address�.
+   Default value is "address".
 
 
    Example 1.7. Set address_table parameter
    Example 1.7. Set address_table parameter
 ...
 ...
@@ -488,7 +488,7 @@ modparam("permissions", "address_table", "addr")
    Name of address table column containing group identifier of the
    Name of address table column containing group identifier of the
    address.
    address.
 
 
-   Default value is “grp�.
+   Default value is "grp".
 
 
    Example 1.8. Set grp_col parameter
    Example 1.8. Set grp_col parameter
 ...
 ...
@@ -499,7 +499,7 @@ modparam("permissions", "grp_col", "group_id")
 
 
    Name of address table column containing IP address part of the address.
    Name of address table column containing IP address part of the address.
 
 
-   Default value is “ip_addr�.
+   Default value is "ip_addr".
 
 
    Example 1.9. Set ip_addr_col parameter
    Example 1.9. Set ip_addr_col parameter
 ...
 ...
@@ -511,7 +511,7 @@ modparam("permissions", "ip_addr_col", "ip_address")
    Name of address table column containing network mask of the address.
    Name of address table column containing network mask of the address.
    Possible values are 0-32.
    Possible values are 0-32.
 
 
-   Default value is “mask�.
+   Default value is "mask".
 
 
    Example 1.10. Set mask_col parameter
    Example 1.10. Set mask_col parameter
 ...
 ...
@@ -522,7 +522,7 @@ modparam("permissions", "mask_col", "subnet_length")
 
 
    Name of address table column containing port part of the address.
    Name of address table column containing port part of the address.
 
 
-   Default value is “port�.
+   Default value is "port".
 
 
    Example 1.11. Set port_col parameter
    Example 1.11. Set port_col parameter
 ...
 ...
@@ -546,7 +546,7 @@ modparam("permissions", "db_mode", 1)
    Name of database table containing matching rules used by allow_trusted
    Name of database table containing matching rules used by allow_trusted
    function.
    function.
 
 
-   Default value is “trusted�.
+   Default value is "trusted".
 
 
    Example 1.13. Set trusted_table parameter
    Example 1.13. Set trusted_table parameter
 ...
 ...
@@ -558,7 +558,7 @@ modparam("permissions", "trusted_table", "pbx")
    Name of trusted table column containing source IP address that is
    Name of trusted table column containing source IP address that is
    matched against source IP address of received request.
    matched against source IP address of received request.
 
 
-   Default value is “src_ip�.
+   Default value is "src_ip".
 
 
    Example 1.14. Set source_col parameter
    Example 1.14. Set source_col parameter
 ...
 ...
@@ -569,10 +569,10 @@ modparam("permissions", "source_col", "source_ip_address")
 
 
    Name of trusted table column containing transport protocol that is
    Name of trusted table column containing transport protocol that is
    matched against transport protocol of received request. Possible values
    matched against transport protocol of received request. Possible values
-   that can be stored in proto_col are “any�, “udp�, “tcp�, “tls�, “sctp�,
-   and “none�. Value “any� matches always and value “none� never.
+   that can be stored in proto_col are "any", "udp", "tcp", "tls", "sctp",
+   and "none". Value "any" matches always and value "none" never.
 
 
-   Default value is “proto�.
+   Default value is "proto".
 
 
    Example 1.15. Set proto_col parameter
    Example 1.15. Set proto_col parameter
 ...
 ...
@@ -584,7 +584,7 @@ modparam("permissions", "proto_col", "transport")
    Name of trusted table column containing regular expression that is
    Name of trusted table column containing regular expression that is
    matched against From URI.
    matched against From URI.
 
 
-   Default value is “from_pattern�.
+   Default value is "from_pattern".
 
 
    Example 1.16. Set from_col parameter
    Example 1.16. Set from_col parameter
 ...
 ...
@@ -597,7 +597,7 @@ modparam("permissions", "from_col", "regexp")
    added as value to peer_tag AVP if peer_tag AVP has been defined and if
    added as value to peer_tag AVP if peer_tag AVP has been defined and if
    the address or peer matches.
    the address or peer matches.
 
 
-   Default value is “tag�.
+   Default value is "tag".
 
 
    Example 1.17. Set tag_col parameter
    Example 1.17. Set tag_col parameter
 ...
 ...
@@ -609,7 +609,7 @@ modparam("permissions", "tag_col", "peer_tag")
    If defined, the AVP will be set as side effect of allow_trusted() call
    If defined, the AVP will be set as side effect of allow_trusted() call
    to not NULL tag column value of the matching peer.
    to not NULL tag column value of the matching peer.
 
 
-   Default value is “undefined�.
+   Default value is "undefined".
 
 
    Example 1.18. Set peer_tag_avp parameter
    Example 1.18. Set peer_tag_avp parameter
 ...
 ...
@@ -620,9 +620,10 @@ modparam("permissions", "peer_tag_avp", "$avp(i:707)")
 
 
    Tag mode for allow_trusted(). 0 sets only the tag of the first match. 1
    Tag mode for allow_trusted(). 0 sets only the tag of the first match. 1
    adds the tags of all matches to the avp. In addition the return value
    adds the tags of all matches to the avp. In addition the return value
-   of allow_trusted() is the number of matches.
+   of allow_trusted() is the number of matches. This parameter is not used
+   for address table matching functions.
 
 
-   Default value is “0�.
+   Default value is "0".
 
 
    Example 1.19. Set peer_tag_mode parameter
    Example 1.19. Set peer_tag_mode parameter
 ...
 ...
@@ -643,10 +644,10 @@ modparam("permissions", "peer_tag_mode", "1")
    4.10. allow_address_group(addr, port)
    4.10. allow_address_group(addr, port)
    4.11. allow_trusted([src_ip_pvar, proto_pvar])
    4.11. allow_trusted([src_ip_pvar, proto_pvar])
 
 
-4.1.  allow_routing()
+4.1. allow_routing()
 
 
    Returns true if all pairs constructed as described in Section 1.1,
    Returns true if all pairs constructed as described in Section 1.1,
-   “Call Routing� have appropriate permissions according to the
+   "Call Routing" have appropriate permissions according to the
    configuration files. This function uses default configuration files
    configuration files. This function uses default configuration files
    specified in default_allow_file and default_deny_file.
    specified in default_allow_file and default_deny_file.
 
 
@@ -659,10 +660,10 @@ if (allow_routing()) {
 };
 };
 ...
 ...
 
 
-4.2.  allow_routing(basename)
+4.2. allow_routing(basename)
 
 
    Returns true if all pairs constructed as described in Section 1.1,
    Returns true if all pairs constructed as described in Section 1.1,
-   “Call Routing� have appropriate permissions according to the
+   "Call Routing" have appropriate permissions according to the
    configuration files given as parameters.
    configuration files given as parameters.
 
 
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
@@ -682,10 +683,10 @@ if (allow_routing("basename")) {
 };
 };
 ...
 ...
 
 
-4.3.  allow_routing(allow_file,deny_file)
+4.3. allow_routing(allow_file,deny_file)
 
 
    Returns true if all pairs constructed as described in Section 1.1,
    Returns true if all pairs constructed as described in Section 1.1,
-   “Call Routing� have appropriate permissions according to the
+   "Call Routing" have appropriate permissions according to the
    configuration files given as parameters.
    configuration files given as parameters.
 
 
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
@@ -707,10 +708,10 @@ if (allow_routing("rules.allow", "rules.deny")) {
 };
 };
 ...
 ...
 
 
-4.4.  allow_register(basename)
+4.4. allow_register(basename)
 
 
    The function returns true if all pairs constructed as described in
    The function returns true if all pairs constructed as described in
-   Section 1.2, “Registration Permissions� have appropriate permissions
+   Section 1.2, "Registration Permissions" have appropriate permissions
    according to the configuration files given as parameters.
    according to the configuration files given as parameters.
 
 
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
@@ -735,10 +736,10 @@ if (method=="REGISTER") {
 };
 };
 ...
 ...
 
 
-4.5.  allow_register(allow_file, deny_file)
+4.5. allow_register(allow_file, deny_file)
 
 
    The function returns true if all pairs constructed as described in
    The function returns true if all pairs constructed as described in
-   Section 1.2, “Registration Permissions� have appropriate permissions
+   Section 1.2, "Registration Permissions" have appropriate permissions
    according to the configuration files given as parameters.
    according to the configuration files given as parameters.
 
 
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
@@ -765,10 +766,10 @@ if (method=="REGISTER") {
 };
 };
 ...
 ...
 
 
-4.6.  allow_uri(basename, pvar)
+4.6. allow_uri(basename, pvar)
 
 
-   Returns true if the pair constructed as described in Section 1.3, “URI
-   Permissions� have appropriate permissions according to the
+   Returns true if the pair constructed as described in Section 1.3, "URI
+   Permissions" have appropriate permissions according to the
    configuration files specified by the parameter.
    configuration files specified by the parameter.
 
 
    Meaning of the parameter is as follows:
    Meaning of the parameter is as follows:
@@ -792,7 +793,7 @@ if (allow_uri("basename", "$avp(i:705)") {  // Check URI stored in $avp(i:705)
 };
 };
 ...
 ...
 
 
-4.7.  allow_address(group_id, ip_addr_pvar, port_pvar)
+4.7. allow_address(group_id, ip_addr_pvar, port_pvar)
 
 
    Returns true if address and port given as values of pvar arguments
    Returns true if address and port given as values of pvar arguments
    belonging to a group given as group_id argument matches an IP subnet or
    belonging to a group given as group_id argument matches an IP subnet or
@@ -821,7 +822,7 @@ if (!allow_address("2", "$avp(dst_adr)", "$avp(dst_port)") {
 };
 };
 ...
 ...
 
 
-4.8.  allow_source_address([group_id])
+4.8. allow_source_address([group_id])
 
 
    Equal to allow_address(group_id, "$si", "$sp"). If 'group_id' is
    Equal to allow_address(group_id, "$si", "$sp"). If 'group_id' is
    missing, the function is equal to allow_address("1", "$si", "$sp").
    missing, the function is equal to allow_address("1", "$si", "$sp").
@@ -837,7 +838,7 @@ if (!allow_source_address("1")) {
 };
 };
 ...
 ...
 
 
-4.9.  allow_source_address_group()
+4.9. allow_source_address_group()
 
 
    Checks if source address/port is found in cached address or subnet
    Checks if source address/port is found in cached address or subnet
    table in any group. If yes, returns that group. If not returns -1. Port
    table in any group. If yes, returns that group. If not returns -1. Port
@@ -854,7 +855,7 @@ if ($var(group) != -1) {
 };
 };
 ...
 ...
 
 
-4.10.  allow_address_group(addr, port)
+4.10. allow_address_group(addr, port)
 
 
    Checks if address/port is found in cached address or subnet table in
    Checks if address/port is found in cached address or subnet table in
    any group. If yes, returns that group. If not returns -1. Port value 0
    any group. If yes, returns that group. If not returns -1. Port value 0
@@ -872,19 +873,19 @@ if ($var(group) != -1) {
 };
 };
 ...
 ...
 
 
-4.11.  allow_trusted([src_ip_pvar, proto_pvar])
+4.11. allow_trusted([src_ip_pvar, proto_pvar])
 
 
    Checks based either on request's source address and transport protocol
    Checks based either on request's source address and transport protocol
    or source address and transport protocol given in pvar arguments, and
    or source address and transport protocol given in pvar arguments, and
    From URI of request if request can be trusted without authentication.
    From URI of request if request can be trusted without authentication.
-   Returns 1 if a match is found as described in Section 1.5, “Trusted
-   Requests� and -1 otherwise. If a match is found and peer_tag_avp has
+   Returns 1 if a match is found as described in Section 1.5, "Trusted
+   Requests" and -1 otherwise. If a match is found and peer_tag_avp has
    been defined, adds a non-NULL tag column value of the matching peer to
    been defined, adds a non-NULL tag column value of the matching peer to
    AVP peer_tag_avp.
    AVP peer_tag_avp.
 
 
    Source address and transport protocol given in pvar arguments must be
    Source address and transport protocol given in pvar arguments must be
    in string format. Valid transport protocol values are (ignoring case)
    in string format. Valid transport protocol values are (ignoring case)
-   "any", "udp, "tcp", "tls", and "sctp".
+   "any", "udp, "tcp", "tls", "ws", "wss" and "sctp".
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
@@ -908,7 +909,7 @@ if (allow_trusted("$si", "$proto")) {
    5.5. trusted_dump
    5.5. trusted_dump
    5.6. allow_uri
    5.6. allow_uri
 
 
-5.1.  address_reload
+5.1. address_reload
 
 
    Causes permissions module to re-read the contents of address database
    Causes permissions module to re-read the contents of address database
    table into cache memory. In cache memory the entries are for
    table into cache memory. In cache memory the entries are for
@@ -917,35 +918,35 @@ if (allow_trusted("$si", "$proto")) {
 
 
    Parameters: none
    Parameters: none
 
 
-5.2.  address_dump
+5.2. address_dump
 
 
    Causes permissions module to dump contents of cache memory address
    Causes permissions module to dump contents of cache memory address
    table.
    table.
 
 
    Parameters: none
    Parameters: none
 
 
-5.3.  subnet_dump
+5.3. subnet_dump
 
 
    Causes permissions module to dump contents of cache memory subnet
    Causes permissions module to dump contents of cache memory subnet
    table.
    table.
 
 
    Parameters: none
    Parameters: none
 
 
-5.4.  trusted_reload
+5.4. trusted_reload
 
 
    Causes permissions module to re-read the contents of trusted table into
    Causes permissions module to re-read the contents of trusted table into
    cache memory.
    cache memory.
 
 
    Parameters: none
    Parameters: none
 
 
-5.5.  trusted_dump
+5.5. trusted_dump
 
 
    Causes permissions module to dump contents of trusted table from cache
    Causes permissions module to dump contents of trusted table from cache
    memory.
    memory.
 
 
    Parameters: none
    Parameters: none
 
 
-5.6.  allow_uri
+5.6. allow_uri
 
 
    Tests if (URI, Contact) pair is allowed according to allow/deny files.
    Tests if (URI, Contact) pair is allowed according to allow/deny files.
    The files must already have been loaded by Kamailio.
    The files must already have been loaded by Kamailio.
@@ -966,7 +967,7 @@ if (allow_trusted("$si", "$proto")) {
    6.5. trustedReload
    6.5. trustedReload
    6.6. trustedDump
    6.6. trustedDump
 
 
-6.1.  addressReload
+6.1. addressReload
 
 
    Causes permissions module to re-read the contents of address database
    Causes permissions module to re-read the contents of address database
    table into cache memory. In cache memory the entries are for
    table into cache memory. In cache memory the entries are for
@@ -975,21 +976,21 @@ if (allow_trusted("$si", "$proto")) {
 
 
    Parameters: none
    Parameters: none
 
 
-6.2.  addressDump
+6.2. addressDump
 
 
    Causes permissions module to dump contents of cache memory address
    Causes permissions module to dump contents of cache memory address
    table. (Not the subnet table).
    table. (Not the subnet table).
 
 
    Parameters: none
    Parameters: none
 
 
-6.3.  subnetDump
+6.3. subnetDump
 
 
    Causes permissions module to dump contents of cache memory subnet
    Causes permissions module to dump contents of cache memory subnet
    table.
    table.
 
 
    Parameters: none
    Parameters: none
 
 
-6.4.  testUri basename uri contact
+6.4. testUri basename uri contact
 
 
    Tests if (URI, Contact) pair is allowed according to allow/deny files.
    Tests if (URI, Contact) pair is allowed according to allow/deny files.
    The files must already have been loaded by Kamailio.
    The files must already have been loaded by Kamailio.
@@ -1001,14 +1002,14 @@ if (allow_trusted("$si", "$proto")) {
      * URI - URI to be tested
      * URI - URI to be tested
      * Contact - Contact to be tested
      * Contact - Contact to be tested
 
 
-6.5.  trustedReload
+6.5. trustedReload
 
 
    Causes permissions module to re-read the contents of trusted table into
    Causes permissions module to re-read the contents of trusted table into
    cache memory.
    cache memory.
 
 
    Parameters: none
    Parameters: none
 
 
-6.6.  trustedDump
+6.6. trustedDump
 
 
    Causes permissions module to dump contents of trusted table from cache
    Causes permissions module to dump contents of trusted table from cache
    memory.
    memory.

+ 2 - 1
modules/permissions/doc/permissions_admin.xml

@@ -687,7 +687,8 @@ modparam("permissions", "peer_tag_avp", "$avp(i:707)")
 		<para>
 		<para>
 		Tag mode for allow_trusted(). 0 sets only the tag of the
 		Tag mode for allow_trusted(). 0 sets only the tag of the
 		first match. 1 adds the tags of all matches to the avp. In addition
 		first match. 1 adds the tags of all matches to the avp. In addition
-		the return value of allow_trusted() is the number of matches.
+		the return value of allow_trusted() is the number of matches. This
+		parameter is not used for address table matching functions.
 		</para>
 		</para>
 		<para>
 		<para>
 		<emphasis>
 		<emphasis>

+ 20 - 0
modules/permissions/hash.c

@@ -486,6 +486,7 @@ int find_group_in_addr_hash_table(struct addr_list** table,
 {
 {
 	struct addr_list *np;
 	struct addr_list *np;
 	str addr_str;
 	str addr_str;
+	avp_value_t val;
 
 
 	addr_str.s = (char*)addr->u.addr;
 	addr_str.s = (char*)addr->u.addr;
 	addr_str.len = 4;
 	addr_str.len = 4;
@@ -493,6 +494,15 @@ int find_group_in_addr_hash_table(struct addr_list** table,
 	for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
 	for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
 		if (((np->port == 0) || (np->port == port))
 		if (((np->port == 0) || (np->port == port))
 				&& ip_addr_cmp(&np->addr, addr)) {
 				&& ip_addr_cmp(&np->addr, addr)) {
+
+			if (tag_avp.n && np->tag.s) {
+				val.s = np->tag;
+				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
+					LM_ERR("setting of tag_avp failed\n");
+					return -1;
+				}
+			}
+
 			return np->grp;
 			return np->grp;
 		}
 		}
 	}
 	}
@@ -710,6 +720,7 @@ int find_group_in_subnet_table(struct subnet* table,
 		ip_addr_t *addr, unsigned int port)
 		ip_addr_t *addr, unsigned int port)
 {
 {
 	unsigned int count, i;
 	unsigned int count, i;
+	avp_value_t val;
 
 
 	count = table[PERM_MAX_SUBNETS].grp;
 	count = table[PERM_MAX_SUBNETS].grp;
 
 
@@ -717,7 +728,16 @@ int find_group_in_subnet_table(struct subnet* table,
 	while (i < count) {
 	while (i < count) {
 		if ( ((table[i].port == port) || (table[i].port == 0))
 		if ( ((table[i].port == port) || (table[i].port == 0))
 			&& (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
 			&& (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
+		{
+			if (tag_avp.n && table[i].tag.s) {
+				val.s = table[i].tag;
+				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
+					LM_ERR("setting of tag_avp failed\n");
+					return -1;
+				}
+			}
 			return table[i].grp;
 			return table[i].grp;
+		}
 		i++;
 		i++;
 	}
 	}
 
 

+ 70 - 15
modules/presence_dialoginfo/notify_body.c

@@ -32,6 +32,12 @@
  */
  */
 
 
 #define MAX_INT_LEN 11 /* 2^32: 10 chars + 1 char sign */
 #define MAX_INT_LEN 11 /* 2^32: 10 chars + 1 char sign */
+#define DEF_TRYING_NODE 1
+#define DEF_PROCEEDING_NODE 2
+#define DEF_EARLY_NODE 4
+#define DEF_CONFIRMED_NODE 8
+#define DEF_TERMINATED_NODE 16
+
 
 
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -103,6 +109,9 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
 	xmlNodePtr terminated_node = NULL;
 	xmlNodePtr terminated_node = NULL;
 	xmlNodePtr early_node = NULL;
 	xmlNodePtr early_node = NULL;
 	xmlNodePtr confirmed_node = NULL;
 	xmlNodePtr confirmed_node = NULL;
+	xmlNodePtr proceed_node = NULL;
+	xmlNodePtr trying_node = NULL;
+
 
 
 	char *state = NULL;
 	char *state = NULL;
 	xmlChar *dialog_id = NULL;
 	xmlChar *dialog_id = NULL;
@@ -236,39 +245,61 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
 							LM_DBG("state element content = %s\n", state);
 							LM_DBG("state element content = %s\n", state);
 							if (strcasecmp(state,"terminated") == 0)
 							if (strcasecmp(state,"terminated") == 0)
 							{
 							{
+								LM_DBG("found terminated state\n" );
 								terminated_node = node;
 								terminated_node = node;
 							} else if (strcasecmp(state,"confirmed") == 0 && node_id == i) {
 							} else if (strcasecmp(state,"confirmed") == 0 && node_id == i) {
 								/*  here we check if confirmed is terminated or not
 								/*  here we check if confirmed is terminated or not
 								 *  if it is not we are in the middle of the conversation
 								 *  if it is not we are in the middle of the conversation
 								 */
 								 */
-								if(check_relevant_state(dialog_id, xml_array, j) > 1)
+								if(check_relevant_state(dialog_id, xml_array, j) >= DEF_TERMINATED_NODE)
 								{
 								{
-									LM_DBG("confirmed state for dialog %s, but it was terminated\n", dialog_id );
+									LM_DBG("confirmed state for dialog %s, but it is not latest state\n", dialog_id );
 								}else{
 								}else{
-									LM_DBG("confirmed state for dialog %s, and it is not terminated\n", dialog_id );
+									LM_DBG("confirmed state for dialog %s and latest state for this dialog\n", dialog_id );
 									confirmed_node = node;
 									confirmed_node = node;
 								}
 								}
 
 
 
 
 							} else if (strcasecmp(state,"early") == 0 && node_id == i) {
 							} else if (strcasecmp(state,"early") == 0 && node_id == i) {
-								if(check_relevant_state(dialog_id, xml_array, j)  > 0)
+								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_CONFIRMED_NODE)
 								{
 								{
-									LM_DBG("early state for dialog %s, but it was confirmed or terminated\n", dialog_id );
+									LM_DBG("early state for dialog %s, but it is not latest state\n", dialog_id );
 								}else{
 								}else{
-									LM_DBG("early state for dialog %s and it is still relevant\n", dialog_id );
+									LM_DBG("early state for dialog %s and latest state for this dialog\n", dialog_id );
 									early_node = node;
 									early_node = node;
 								}
 								}
+							} else if (strcasecmp(state,"proceeding") == 0 && node_id == i) {
+								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_EARLY_NODE)
+								{
+									LM_DBG("proceeding state for dialog %s, but it is not latest state\n", dialog_id );
+								}else{
+									LM_DBG("proceeding state for dialog %s and latest state for this dialog\n", dialog_id );
+									proceed_node = node;
+								}
+							} else if (strcasecmp(state,"trying") == 0 && node_id == i) {
+								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_PROCEEDING_NODE)
+								{
+									LM_DBG("trying state for dialog %s, but it is not latest state\n", dialog_id );
+								}else{
+									LM_DBG("trying state for dialog %s and latest state for this dialog\n", dialog_id );
+									trying_node = node;
+								}
 							}
 							}
 							if(early_node != NULL) {
 							if(early_node != NULL) {
 								winner_dialog_node = early_node;
 								winner_dialog_node = early_node;
-							} else {
-								if(confirmed_node != NULL)
-								{
+							} else if(confirmed_node != NULL) {
 									winner_dialog_node = confirmed_node;
 									winner_dialog_node = confirmed_node;
-								}else {
+							} else if(proceed_node != NULL) {
+									winner_dialog_node = proceed_node;
+							} else if(trying_node != NULL) {
+									winner_dialog_node = trying_node;
+							} else if(terminated_node != NULL) {
 									winner_dialog_node = terminated_node;
 									winner_dialog_node = terminated_node;
-								}
+							} else {
+								/* assume a failure somewhere and all above nodes are NULL */
+								winner_dialog_node = node;
 							}
 							}
+							/*
 							if(winner_dialog_node == NULL) {
 							if(winner_dialog_node == NULL) {
 								priority = get_dialog_state_priority(state);
 								priority = get_dialog_state_priority(state);
 								if (priority > winner_priority) {
 								if (priority > winner_priority) {
@@ -277,6 +308,7 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
 									winner_dialog_node = node;
 									winner_dialog_node = node;
 								}
 								}
 							}
 							}
+							*/
 							xmlFree(state);
 							xmlFree(state);
 						}
 						}
 					}
 					}
@@ -336,7 +368,7 @@ error:
 	return NULL;
 	return NULL;
 }
 }
 
 
-
+/*
 int get_dialog_state_priority(char *state) {
 int get_dialog_state_priority(char *state) {
 	if (strcasecmp(state,"terminated") == 0)
 	if (strcasecmp(state,"terminated") == 0)
 		return 0;
 		return 0;
@@ -351,8 +383,9 @@ int get_dialog_state_priority(char *state) {
 
 
 	return 0;
 	return 0;
 }
 }
+*/
 
 
-/* returns 2 -> terminated, 1 -> confirmed, 3 -> both */
+/* returns 16 -> terminated, 8 -> confirmed, 4 -> early */
 int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_nodes)
 int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_nodes)
 {
 {
 	int result = 0;
 	int result = 0;
@@ -391,7 +424,7 @@ int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_
 							{
 							{
 								LM_DBG ("Found terminated in dialog %s\n",
 								LM_DBG ("Found terminated in dialog %s\n",
 										dialog_id);
 										dialog_id);
-								result += 2;
+								result += DEF_TERMINATED_NODE;
 							}
 							}
 							/* check if state is confirmed for this dialog. */
 							/* check if state is confirmed for this dialog. */
 							if ((strcasecmp (state, "confirmed") == 0)
 							if ((strcasecmp (state, "confirmed") == 0)
@@ -399,8 +432,30 @@ int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_
 									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
 									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
 							{
 							{
 								LM_DBG ("Found confirmed in dialog %s\n", dialog_id);
 								LM_DBG ("Found confirmed in dialog %s\n", dialog_id);
-								result += 1;
+								result += DEF_CONFIRMED_NODE;
 							}
 							}
+							if ((strcasecmp (state, "early") == 0)
+									&& (node_id == i) && (node_id >= 0)
+									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
+							{
+								LM_DBG ("Found early in dialog %s\n", dialog_id);
+								result += DEF_EARLY_NODE;
+							}
+							if ((strcasecmp (state, "proceeding") == 0)
+									&& (node_id == i) && (node_id >= 0)
+									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
+							{
+								LM_DBG ("Found proceeding in dialog %s\n", dialog_id);
+								result += DEF_PROCEEDING_NODE;
+							}
+							if ((strcasecmp (state, "trying") == 0)
+									&& (node_id == i) && (node_id >= 0)
+									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
+							{
+								LM_DBG ("Found trying in dialog %s\n", dialog_id);
+								result += DEF_TRYING_NODE;
+							}
+
 
 
 							xmlFree (state);
 							xmlFree (state);
 						}
 						}

+ 2 - 1
modules/tls/tls_cfg.c

@@ -2,6 +2,7 @@
  * TLS module
  * TLS module
  *
  *
  * Copyright (C) 2010 iptelorg GmbH
  * Copyright (C) 2010 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -76,7 +77,7 @@ struct cfg_group_tls default_tls_cfg = {
 	0 /* send_close_notify (off by default)*/
 	0 /* send_close_notify (off by default)*/
 };
 };
 
 
-void* tls_cfg = &default_tls_cfg;
+volatile void* tls_cfg = &default_tls_cfg;
 
 
 
 
 /* if *to<0 to=default_val, else if to>max_val to=max_val */
 /* if *to<0 to=default_val, else if to>max_val to=max_val */

+ 2 - 1
modules/tls/tls_cfg.h

@@ -2,6 +2,7 @@
  * TLS module
  * TLS module
  * 
  * 
  * Copyright (C) 2010 iptelorg GmbH
  * Copyright (C) 2010 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -101,7 +102,7 @@ struct cfg_group_tls {
 
 
 
 
 extern struct cfg_group_tls default_tls_cfg;
 extern struct cfg_group_tls default_tls_cfg;
-extern void* tls_cfg;
+extern volatile void* tls_cfg;
 extern cfg_def_t tls_cfg_def[];
 extern cfg_def_t tls_cfg_def[];
 
 
 
 

+ 2 - 1
modules/tls/tls_domain.c

@@ -2,6 +2,7 @@
  * TLS module
  * TLS module
  *
  *
  * Copyright (C) 2005,2006 iptelorg GmbH
  * Copyright (C) 2005,2006 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -23,7 +24,6 @@
  * Module: @ref tls
  * Module: @ref tls
  */
  */
 
 
-
 #include <stdlib.h>
 #include <stdlib.h>
 #include <openssl/ssl.h>
 #include <openssl/ssl.h>
 #include <openssl/opensslv.h>
 #include <openssl/opensslv.h>
@@ -119,6 +119,7 @@ void tls_free_cfg(tls_domains_cfg_t* cfg)
 	}
 	}
 	if (cfg->srv_default) tls_free_domain(cfg->srv_default);
 	if (cfg->srv_default) tls_free_domain(cfg->srv_default);
 	if (cfg->cli_default) tls_free_domain(cfg->cli_default);
 	if (cfg->cli_default) tls_free_domain(cfg->cli_default);
+	shm_free(cfg);
 }
 }
 
 
 
 

+ 2 - 1
modules/tls/tls_domain.h

@@ -2,6 +2,7 @@
  * TLS module
  * TLS module
  *
  *
  * Copyright (C) 2005,2006 iptelorg GmbH
  * Copyright (C) 2005,2006 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -99,7 +100,7 @@ typedef struct tls_domains_cfg {
 	tls_domain_t* srv_list;    /**< Server domain list */
 	tls_domain_t* srv_list;    /**< Server domain list */
 	tls_domain_t* cli_list;    /**< Client domain list */
 	tls_domain_t* cli_list;    /**< Client domain list */
 	struct tls_domains_cfg* next; /**< Next element in the garbage list */
 	struct tls_domains_cfg* next; /**< Next element in the garbage list */
-	int ref_count;             /**< How many connections use this configuration */
+	volatile int ref_count;             /**< How many connections use this configuration */
 } tls_domains_cfg_t;
 } tls_domains_cfg_t;
 
 
 
 

+ 2 - 1
modules/tls/tls_mod.c

@@ -2,6 +2,7 @@
  * TLS module
  * TLS module
  *
  *
  * Copyright (C) 2007 iptelorg GmbH 
  * Copyright (C) 2007 iptelorg GmbH 
+ * Copyright (C) Motorola Solutions, Inc.
  *
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -278,7 +279,7 @@ static int mod_init(void)
 	}
 	}
 	/* declare configuration */
 	/* declare configuration */
 	if (cfg_declare("tls", tls_cfg_def, &default_tls_cfg,
 	if (cfg_declare("tls", tls_cfg_def, &default_tls_cfg,
-							cfg_sizeof(tls), &tls_cfg)) {
+							cfg_sizeof(tls), (void **)&tls_cfg)) {
 		ERR("failed to register the configuration\n");
 		ERR("failed to register the configuration\n");
 		return -1;
 		return -1;
 	}
 	}

+ 9 - 1
modules/tls/tls_rpc.c

@@ -2,6 +2,7 @@
  * TLS module - management interface
  * TLS module - management interface
  *
  *
  * Copyright (C) 2005 iptelorg GmbH
  * Copyright (C) 2005 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * This file is part of sip-router, a free SIP server.
  * This file is part of sip-router, a free SIP server.
  *
  *
@@ -56,10 +57,11 @@ static void tls_reload(rpc_t* rpc, void* ctx)
 		return;
 		return;
 	}
 	}
 
 
-	     /* Try to delete old configurations first */
+	/* Try to delete old configurations first */
 	collect_garbage();
 	collect_garbage();
 
 
 	cfg = tls_load_config(&tls_domains_cfg_file);
 	cfg = tls_load_config(&tls_domains_cfg_file);
+
 	if (!cfg) {
 	if (!cfg) {
 		rpc->fault(ctx, 500, "Error while loading TLS configuration file"
 		rpc->fault(ctx, 500, "Error while loading TLS configuration file"
 							" (consult server log)");
 							" (consult server log)");
@@ -78,8 +80,14 @@ static void tls_reload(rpc_t* rpc, void* ctx)
 	}
 	}
 
 
 	DBG("TLS configuration successfuly loaded");
 	DBG("TLS configuration successfuly loaded");
+
+	lock_get(tls_domains_cfg_lock);
+
 	cfg->next = (*tls_domains_cfg);
 	cfg->next = (*tls_domains_cfg);
 	*tls_domains_cfg = cfg;
 	*tls_domains_cfg = cfg;
+
+	lock_release(tls_domains_cfg_lock);
+
 	return;
 	return;
 
 
  error:
  error:

+ 5 - 6
modules/tls/tls_server.c

@@ -2,6 +2,7 @@
  * TLS module - main server part
  * TLS module - main server part
  *
  *
  * Copyright (C) 2005-2010 iptelorg GmbH
  * Copyright (C) 2005-2010 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * This file is part of SIP-router, a free SIP server.
  * This file is part of SIP-router, a free SIP server.
  *
  *
@@ -148,13 +149,10 @@ static int tls_complete_init(struct tcp_connection* c)
 		goto error2;
 		goto error2;
 	}
 	}
 	     /* Get current TLS configuration and increase reference
 	     /* Get current TLS configuration and increase reference
-	      * count immediately. There is no need to lock the structure
-	      * here, because it does not get deleted immediately. When
-	      * SER reloads TLS configuration it will put the old configuration
-	      * on a garbage queue and delete it later, so we know here that
-	      * the pointer we get from *tls_domains_cfg will be valid for a while,
-		  * at least by the time this function finishes
+	      * count immediately.
 	      */
 	      */
+
+	lock_get(tls_domains_cfg_lock);
 	cfg = *tls_domains_cfg;
 	cfg = *tls_domains_cfg;
 
 
 	     /* Increment the reference count in the configuration structure, this
 	     /* Increment the reference count in the configuration structure, this
@@ -162,6 +160,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	      * not get deleted if there are still connection referencing its SSL_CTX
 	      * not get deleted if there are still connection referencing its SSL_CTX
 	      */
 	      */
 	cfg->ref_count++;
 	cfg->ref_count++;
+	lock_release(tls_domains_cfg_lock);
 
 
 	if (c->flags & F_CONN_PASSIVE) {
 	if (c->flags & F_CONN_PASSIVE) {
 		state=S_TLS_ACCEPTING;
 		state=S_TLS_ACCEPTING;

+ 9 - 5
modules/tls/tls_util.c

@@ -2,6 +2,7 @@
  * TLS module
  * TLS module
  *
  *
  * Copyright (C) 2005 iptelorg GmbH
  * Copyright (C) 2005 iptelorg GmbH
+ * Copyright (C) 2013 Motorola Solutions, Inc.
  *
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,6 +17,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
  */
 
 
+
 #define _GNU_SOURCE 1 /* Needed for strndup */
 #define _GNU_SOURCE 1 /* Needed for strndup */
 
 
 #include <string.h>
 #include <string.h>
@@ -66,7 +68,7 @@ int shm_asciiz_dup(char** dest, char* val)
  */
  */
 void collect_garbage(void)
 void collect_garbage(void)
 {
 {
-	tls_domains_cfg_t* prev, *cur;
+	tls_domains_cfg_t *prev, *cur, *next;
 
 
 	     /* Make sure we do not run two garbage collectors
 	     /* Make sure we do not run two garbage collectors
 	      * at the same time
 	      * at the same time
@@ -80,14 +82,16 @@ void collect_garbage(void)
 	cur = (*tls_domains_cfg)->next;
 	cur = (*tls_domains_cfg)->next;
 
 
 	while(cur) {
 	while(cur) {
+		next = cur->next;
 		if (cur->ref_count == 0) {
 		if (cur->ref_count == 0) {
-			     /* Not referenced by any existing connection */
+			/* Not referenced by any existing connection */
 			prev->next = cur->next;
 			prev->next = cur->next;
 			tls_free_cfg(cur);
 			tls_free_cfg(cur);
+		} else {
+			/* Only update prev if we didn't remove cur */
+			prev = cur;
 		}
 		}
-
-		prev = cur;
-		cur = cur->next;
+		cur = next;
 	}
 	}
 
 
 	lock_release(tls_domains_cfg_lock);
 	lock_release(tls_domains_cfg_lock);

+ 5 - 2
modules/websocket/ws_frame.c

@@ -141,6 +141,7 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 	struct dest_info dst;
 	struct dest_info dst;
 	union sockaddr_union *from = NULL;
 	union sockaddr_union *from = NULL;
 	union sockaddr_union local_addr;
 	union sockaddr_union local_addr;
+	int sub_proto;
 
 
 	LM_DBG("encoding WebSocket frame\n");
 	LM_DBG("encoding WebSocket frame\n");
 
 
@@ -166,6 +167,8 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 		return -1;
 		return -1;
 	}
 	}
 
 
+	sub_proto = frame->wsc->sub_protocol;
+
 	switch(frame->opcode)
 	switch(frame->opcode)
 	{
 	{
 	case OPCODE_TEXT_FRAME:
 	case OPCODE_TEXT_FRAME:
@@ -299,9 +302,9 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 		LM_ERR("sending WebSocket frame\n");
 		LM_ERR("sending WebSocket frame\n");
 		pkg_free(send_buf);
 		pkg_free(send_buf);
 		update_stat(ws_failed_connections, 1);
 		update_stat(ws_failed_connections, 1);
-		if (frame->wsc->sub_protocol == SUB_PROTOCOL_SIP)
+		if (sub_proto == SUB_PROTOCOL_SIP)
 			update_stat(ws_sip_failed_connections, 1);
 			update_stat(ws_sip_failed_connections, 1);
-		else if (frame->wsc->sub_protocol == SUB_PROTOCOL_MSRP)
+		else if (sub_proto == SUB_PROTOCOL_MSRP)
 			update_stat(ws_msrp_failed_connections, 1);
 			update_stat(ws_msrp_failed_connections, 1);
 		if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
 		if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
 			LM_ERR("removing WebSocket connection\n");
 			LM_ERR("removing WebSocket connection\n");