Bläddra i källkod

Merge branch 'master' into rfuchs/rtpproxy-ng

Richard Fuchs 12 år sedan
förälder
incheckning
dd76f37bff

+ 1 - 1
Makefile.defs

@@ -165,7 +165,7 @@ INSTALL_FLAVOUR=$(FLAVOUR)
 VERSION = 4
 PATCHLEVEL = 1
 SUBLEVEL =  0
-EXTRAVERSION = -dev6
+EXTRAVERSION = -dev7
 
 # memory manager switcher
 # 0 - f_malloc (fast malloc)

+ 1 - 1
modules/db_unixodbc/con.c → modules/db_unixodbc/connection.c

@@ -31,7 +31,7 @@
  *  2006-05-05  extract_error passes back last error state on return (sgupta)
  */
 
-#include "con.h"
+#include "connection.h"
 #include "../../mem/mem.h"
 #include "../../dprint.h"
 #include "../../ut.h"

+ 0 - 0
modules/db_unixodbc/con.h → modules/db_unixodbc/connection.h


+ 1 - 1
modules/db_unixodbc/dbase.c

@@ -38,7 +38,7 @@
 #include "../../dprint.h"
 #include "../../lib/srdb1/db_query.h"
 #include "val.h"
-#include "con.h"
+#include "connection.h"
 #include "row.h"
 #include "res.h"
 #include "list.h"

+ 1 - 1
modules/db_unixodbc/list.h

@@ -35,7 +35,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "con.h"
+#include "connection.h"
 
 
 typedef struct list

+ 1 - 1
modules/db_unixodbc/res.c

@@ -34,7 +34,7 @@
 #include "../../dprint.h"
 #include "row.h"
 #include "../../lib/srdb1/db_res.h"
-#include "con.h"
+#include "connection.h"
 #include "res.h"
 #include "list.h"
 #include <stdlib.h>

+ 1 - 1
modules/db_unixodbc/row.c

@@ -35,7 +35,7 @@
 #include "../../lib/srdb1/db_val.h"
 #include "val.h"
 #include "row.h"
-#include "con.h"
+#include "connection.h"
 
 /*
  * Convert a row from result into db API representation

+ 1 - 1
modules/db_unixodbc/val.c

@@ -34,7 +34,7 @@
 #include "../../lib/srdb1/db_ut.h"
 #include "db_unixodbc.h"
 #include "val.h"
-#include "con.h"
+#include "connection.h"
 
 /*
  * Used when converting the query to a result

+ 0 - 4
modules/dialplan/dialplan.c

@@ -218,10 +218,6 @@ static void mod_destroy(void)
 		shm_free(default_par2);
 		default_par2 = NULL;
 	}
-	if(attr_pvar){
-		shm_free(attr_pvar);
-		attr_pvar = NULL;
-	}
 	destroy_data();
 }
 

+ 113 - 95
modules/dispatcher/README

@@ -14,7 +14,7 @@ Edited by
 
 Carsten Bock
 
-   ng-voice.com
+   ng-voice GmbH
 
    Copyright © 2004 FhG FOKUS
 
@@ -52,17 +52,18 @@ Carsten Bock
               3.15. attrs_avp (str)
               3.16. hash_pvar (str)
               3.17. setid_pvname (str)
-              3.18. ds_ping_method (string)
-              3.19. ds_ping_from (string)
-              3.20. ds_ping_interval (int)
-              3.21. ds_probing_threshhold (int)
-              3.22. ds_ping_reply_codes (string)
-              3.23. ds_probing_mode (int)
-              3.24. ds_hash_size (int)
-              3.25. ds_hash_expire (int)
-              3.26. ds_hash_initexpire (int)
-              3.27. ds_hash_check_interval (int)
-              3.28. outbound_proxy (str)
+              3.18. attrs_pvname (str)
+              3.19. ds_ping_method (string)
+              3.20. ds_ping_from (string)
+              3.21. ds_ping_interval (int)
+              3.22. ds_probing_threshhold (int)
+              3.23. ds_ping_reply_codes (string)
+              3.24. ds_probing_mode (int)
+              3.25. ds_hash_size (int)
+              3.26. ds_hash_expire (int)
+              3.27. ds_hash_initexpire (int)
+              3.28. ds_hash_check_interval (int)
+              3.29. outbound_proxy (str)
 
         4. Functions
 
@@ -119,23 +120,24 @@ Carsten Bock
    1.16. Use $avp(i:273) for hashing:
    1.17. Use combination of PVs for hashing:
    1.18. Set the "setid_pvname" parameter
-   1.19. Set the "ds_ping_method" parameter
-   1.20. Set the "ds_ping_from" parameter
-   1.21. Set the "ds_ping_interval" parameter
-   1.22. Set the "ds_probing_threshhold" parameter
-   1.23. Set the "ds_ping_reply_codes" parameter
-   1.24. Set the "ds_probing_mode" parameter
-   1.25. Set the "ds_hash_size" parameter
-   1.26. Set the "ds_hash_expire" parameter
-   1.27. Set the "ds_hash_initexpire" parameter
-   1.28. Set the "ds_hash_check_interval" parameter
-   1.29. Set the "outbound_proxy" parameter
-   1.30. ds_select_dst usage
-   1.31. ds_mark_dst usage
+   1.19. Set the "attrs_pvname" parameter
+   1.20. Set the "ds_ping_method" parameter
+   1.21. Set the "ds_ping_from" parameter
+   1.22. Set the "ds_ping_interval" parameter
+   1.23. Set the "ds_probing_threshhold" parameter
+   1.24. Set the "ds_ping_reply_codes" parameter
+   1.25. Set the "ds_probing_mode" parameter
+   1.26. Set the "ds_hash_size" parameter
+   1.27. Set the "ds_hash_expire" parameter
+   1.28. Set the "ds_hash_initexpire" parameter
+   1.29. Set the "ds_hash_check_interval" parameter
+   1.30. Set the "outbound_proxy" parameter
+   1.31. ds_select_dst usage
    1.32. ds_mark_dst usage
-   1.33. ds_load_unset usage
-   1.34. dispatcher list file
-   1.35. Kamailio config script - sample dispatcher usage
+   1.33. ds_mark_dst usage
+   1.34. ds_load_unset usage
+   1.35. dispatcher list file
+   1.36. Kamailio config script - sample dispatcher usage
 
 Chapter 1. Admin Guide
 
@@ -166,17 +168,18 @@ Chapter 1. Admin Guide
         3.15. attrs_avp (str)
         3.16. hash_pvar (str)
         3.17. setid_pvname (str)
-        3.18. ds_ping_method (string)
-        3.19. ds_ping_from (string)
-        3.20. ds_ping_interval (int)
-        3.21. ds_probing_threshhold (int)
-        3.22. ds_ping_reply_codes (string)
-        3.23. ds_probing_mode (int)
-        3.24. ds_hash_size (int)
-        3.25. ds_hash_expire (int)
-        3.26. ds_hash_initexpire (int)
-        3.27. ds_hash_check_interval (int)
-        3.28. outbound_proxy (str)
+        3.18. attrs_pvname (str)
+        3.19. ds_ping_method (string)
+        3.20. ds_ping_from (string)
+        3.21. ds_ping_interval (int)
+        3.22. ds_probing_threshhold (int)
+        3.23. ds_ping_reply_codes (string)
+        3.24. ds_probing_mode (int)
+        3.25. ds_hash_size (int)
+        3.26. ds_hash_expire (int)
+        3.27. ds_hash_initexpire (int)
+        3.28. ds_hash_check_interval (int)
+        3.29. outbound_proxy (str)
 
    4. Functions
 
@@ -264,17 +267,18 @@ Chapter 1. Admin Guide
    3.15. attrs_avp (str)
    3.16. hash_pvar (str)
    3.17. setid_pvname (str)
-   3.18. ds_ping_method (string)
-   3.19. ds_ping_from (string)
-   3.20. ds_ping_interval (int)
-   3.21. ds_probing_threshhold (int)
-   3.22. ds_ping_reply_codes (string)
-   3.23. ds_probing_mode (int)
-   3.24. ds_hash_size (int)
-   3.25. ds_hash_expire (int)
-   3.26. ds_hash_initexpire (int)
-   3.27. ds_hash_check_interval (int)
-   3.28. outbound_proxy (str)
+   3.18. attrs_pvname (str)
+   3.19. ds_ping_method (string)
+   3.20. ds_ping_from (string)
+   3.21. ds_ping_interval (int)
+   3.22. ds_probing_threshhold (int)
+   3.23. ds_ping_reply_codes (string)
+   3.24. ds_probing_mode (int)
+   3.25. ds_hash_size (int)
+   3.26. ds_hash_expire (int)
+   3.27. ds_hash_initexpire (int)
+   3.28. ds_hash_check_interval (int)
+   3.29. outbound_proxy (str)
 
 3.1. list_file (string)
 
@@ -521,7 +525,19 @@ Note
  modparam("dispatcher", "setid_pvname", "$var(setid)")
  ...
 
-3.18. ds_ping_method (string)
+3.18. attrs_pvname (str)
+
+   The name of the PV where to store the attributes of matching address
+   when calling ds_is_from_list().
+
+   Default value is "null" - don't set PV.
+
+   Example 1.19. Set the "attrs_pvname" parameter
+ ...
+ modparam("dispatcher", "attrs_pvname", "$var(attrs)")
+ ...
+
+3.19. ds_ping_method (string)
 
    With this method you can define, with which method you want to probe
    the gateways. Pinging gateways feature depends on ds_ping_interval
@@ -529,12 +545,12 @@ Note
 
    Default value is "OPTIONS".
 
-   Example 1.19. Set the "ds_ping_method" parameter
+   Example 1.20. Set the "ds_ping_method" parameter
  ...
  modparam("dispatcher", "ds_ping_method", "INFO")
  ...
 
-3.19. ds_ping_from (string)
+3.20. ds_ping_from (string)
 
    With this Method you can define the "From:"-Line for the request, sent
    to the failed gateways. This method is only available, if compiled with
@@ -542,12 +558,12 @@ Note
 
    Default value is "sip:dispatcher@localhost".
 
-   Example 1.20. Set the "ds_ping_from" parameter
+   Example 1.21. Set the "ds_ping_from" parameter
  ...
  modparam("dispatcher", "ds_ping_from", "sip:[email protected]")
  ...
 
-3.20. ds_ping_interval (int)
+3.21. ds_ping_interval (int)
 
    With this parameter you can define the interval for sending a request
    to a gateway marked as inactive upon a failed request routing to it.
@@ -556,12 +572,12 @@ Note
 
    Default value is "0".
 
-   Example 1.21. Set the "ds_ping_interval" parameter
+   Example 1.22. Set the "ds_ping_interval" parameter
  ...
  modparam("dispatcher", "ds_ping_interval", 30)
  ...
 
-3.21. ds_probing_threshhold (int)
+3.22. ds_probing_threshhold (int)
 
    If you want to set a gateway into inactive mode, there can be a
    specific number of failed requests until it will change from "active"
@@ -572,12 +588,12 @@ Note
 
    Default value is "1" (set inactive with first failure).
 
-   Example 1.22. Set the "ds_probing_threshhold" parameter
+   Example 1.23. Set the "ds_probing_threshhold" parameter
  ...
  modparam("dispatcher", "ds_probing_threshhold", 10)
  ...
 
-3.22. ds_ping_reply_codes (string)
+3.23. ds_ping_reply_codes (string)
 
    This parameter defines the valid response codes, which are accepted as
    a valid reply to the PING-Method. It is a list separated by colons,
@@ -589,13 +605,13 @@ Note
 
    Default value is "" (only 200 OK is accepted).
 
-   Example 1.23. Set the "ds_ping_reply_codes" parameter
+   Example 1.24. Set the "ds_ping_reply_codes" parameter
  ...
  modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=403;code=488;class=
 3")
  ...
 
-3.23. ds_probing_mode (int)
+3.24. ds_probing_mode (int)
 
    Controls what gateways are tested to see if they are reachable. If set
    to 0, only the gateways with state PROBING are tested; if set to 1, all
@@ -605,12 +621,12 @@ Note
 
    Default value is "0".
 
-   Example 1.24. Set the "ds_probing_mode" parameter
+   Example 1.25. Set the "ds_probing_mode" parameter
  ...
  modparam("dispatcher", "ds_probing_mode", 1)
  ...
 
-3.24. ds_hash_size (int)
+3.25. ds_hash_size (int)
 
    The value to be used as power of two to set the number of slots to hash
    table storing data for call load dispatching (e.g., value 8 will create
@@ -619,24 +635,24 @@ Note
 
    Default value is "0".
 
-   Example 1.25. Set the "ds_hash_size" parameter
+   Example 1.26. Set the "ds_hash_size" parameter
  ...
  modparam("dispatcher", "ds_hash_size", 9)
  ...
 
-3.25. ds_hash_expire (int)
+3.26. ds_hash_expire (int)
 
    Expiration time in seconds to remove the load on a destination if no
    BYE was received meanwhile.
 
    Default value is "7200".
 
-   Example 1.26. Set the "ds_hash_expire" parameter
+   Example 1.27. Set the "ds_hash_expire" parameter
  ...
  modparam("dispatcher", "ds_hash_expire", 3600)
  ...
 
-3.26. ds_hash_initexpire (int)
+3.27. ds_hash_initexpire (int)
 
    Expiration time in seconds to remove the load on a destination if no
    200 for INVITE was received meanwhile and state updated with
@@ -644,30 +660,30 @@ Note
 
    Default value is "7200".
 
-   Example 1.27. Set the "ds_hash_initexpire" parameter
+   Example 1.28. Set the "ds_hash_initexpire" parameter
  ...
  modparam("dispatcher", "ds_hash_initexpire", 60)
  ...
 
-3.27. ds_hash_check_interval (int)
+3.28. ds_hash_check_interval (int)
 
    Time interval in seconds to scan internal hash table with call load
    dispatching data for expired items.
 
    Default value is "30".
 
-   Example 1.28. Set the "ds_hash_check_interval" parameter
+   Example 1.29. Set the "ds_hash_check_interval" parameter
  ...
  modparam("dispatcher", "ds_hash_check_interval", 60)
  ...
 
-3.28. outbound_proxy (str)
+3.29. outbound_proxy (str)
 
    SIP URI of outbound proxy to be used when sending pings.
 
    By default no outbound proxy is defined.
 
-   Example 1.29. Set the "outbound_proxy" parameter
+   Example 1.30. Set the "outbound_proxy" parameter
  ...
  modparam("dispatcher", "outbound_proxy", "sip:outbound.example.com")
  ...
@@ -683,7 +699,7 @@ Note
    4.7. ds_load_update()
    4.8. ds_load_unset()
 
-4.1.  ds_select_dst(set, alg)
+4.1. ds_select_dst(set, alg)
 
    The method selects a destination from addresses set. It returns true if
    a new destination is set.
@@ -733,7 +749,7 @@ Note
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.30. ds_select_dst usage
+   Example 1.31. ds_select_dst usage
 ...
 ds_select_dst("1", "0");
 ...
@@ -741,7 +757,7 @@ $var(a) = 4;
 ds_select_dst("1", "$var(a)");
 ...
 
-4.2.  ds_select_domain(set, alg)
+4.2. ds_select_domain(set, alg)
 
    The method selects a destination from addresses set and rewrites the
    host and port from R-URI. The parameters have same meaning as for
@@ -754,21 +770,21 @@ ds_select_dst("1", "$var(a)");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-4.3.  ds_next_dst()
+4.3. ds_next_dst()
 
    Takes the next destination address from the AVPs with id 'dst_avp_id'
    and sets the dst_uri (outbound proxy address).
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-4.4.  ds_next_domain()
+4.4. ds_next_domain()
 
    Takes the next destination address from the AVPs with id 'dst_avp_id'
    and sets the domain part of the request URI.
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-4.5.  ds_mark_dst([state])
+4.5. ds_mark_dst([state])
 
    Mark the last used address from destination set as inactive ("i"/"I"),
    active ("a"/"A"), disabled ("d"/"D") or trying ("t"/"T"). Apart of
@@ -795,7 +811,7 @@ ds_select_dst("1", "$var(a)");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.31. ds_mark_dst usage
+   Example 1.32. ds_mark_dst usage
 ...
 failure_route[tryagain] {
 ...
@@ -805,7 +821,7 @@ failure_route[tryagain] {
 }
 ...
 
-4.6.  ds_is_from_list([groupid])
+4.6. ds_is_from_list([groupid])
 
    This function returns true, if the current request comes from a host in
    the given group of the dispatcher-list; otherwise false.
@@ -813,18 +829,20 @@ failure_route[tryagain] {
    Parameter groupid is optional, when it is missing, then the matching
    will be done against all addresses in all groups. Upon a match, the
    variable specified by 'setid_pvname' parameter will be set to groupid
-   of matching address.
+   of matching address and the attributes will be set in variable
+   specified by 'attrs_pvname'. The parameter can be an integer or a
+   variable holding an integer value.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.32. ds_mark_dst usage
+   Example 1.33. ds_mark_dst usage
 ...
 if(ds_is_from_list("10")) {
     ...
 }
 ...
 
-4.7.  ds_load_update()
+4.7. ds_load_update()
 
    Updates the load state:
      * if it is a BYE or CANCEL - remove the load from destination address
@@ -835,14 +853,14 @@ if(ds_is_from_list("10")) {
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE and ONREPLY_ROUTE.
 
-4.8.  ds_load_unset()
+4.8. ds_load_unset()
 
    Remove the call load for the destination that routed the call.
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE and ONREPLY_ROUTE.
 
-   Example 1.33. ds_load_unset usage
+   Example 1.34. ds_load_unset usage
 ...
 route {
     ...
@@ -872,7 +890,7 @@ onreply_route {
    5.2. ds_list
    5.3. ds_reload
 
-5.1.  ds_set_state
+5.1. ds_set_state
 
    Sets the status for a destination address (can be use to mark the
    destination as active or inactive).
@@ -897,7 +915,7 @@ onreply_route {
                 _address_
                 _empty_line_
 
-5.2.  ds_list
+5.2. ds_list
 
    It lists the groups and included destinations.
 
@@ -909,7 +927,7 @@ onreply_route {
                 :ds_list:_reply_fifo_file_
                 _empty_line_
 
-5.3.  ds_reload
+5.3. ds_reload
 
    It reloads the groups and included destinations. For algorithm 10 (call
    load distribution), old internal list of active calls is destroyed
@@ -929,7 +947,7 @@ onreply_route {
    6.2. dispatcher.list
    6.3. dispatcher.reload
 
-6.1.  dispatcher.set_state
+6.1. dispatcher.set_state
 
    Sets the state for a destination address (can be use to mark the
    destination as active or inactive).
@@ -953,7 +971,7 @@ onreply_route {
 kamcmd dispatcher.set_state ip 2 sip:127.0.0.1:5080
 ...
 
-6.2.  dispatcher.list
+6.2. dispatcher.list
 
    Lists the groups and included destinations.
 
@@ -964,7 +982,7 @@ kamcmd dispatcher.set_state ip 2 sip:127.0.0.1:5080
    Example:
                 kamcmd dispatcher.list
 
-6.3.  dispatcher.reload
+6.3. dispatcher.reload
 
    Reloads the groups and included destinations. The command is disabled
    for call load based dispatching (algorithm 10) since removal of
@@ -1014,7 +1032,7 @@ setid(int) destination(sip uri) flags(int,opt) priority(int,opt) attrs(str,opt)
    For database, each element of a line resides in a different column.
    Next is a dispatcher.list file example:
 
-   Example 1.34. dispatcher list file
+   Example 1.35. dispatcher list file
 ...
 # $Id$
 # dispatcher destination sets
@@ -1039,7 +1057,7 @@ r,opt)
 
    Next picture shows a sample usage of the dispatcher module.
 
-   Example 1.35. Kamailio config script - sample dispatcher usage
+   Example 1.36. Kamailio config script - sample dispatcher usage
 ...
 #!KAMAILIO
 #
@@ -1329,7 +1347,7 @@ failure_route[RTF_DISPATCH] {
    8.1. dispatcher:dst-down
    8.2. dispatcher:dst-up
 
-8.1.  dispatcher:dst-down
+8.1. dispatcher:dst-down
 
    When defined, the module calls event_route[dispatcher:ds-down] when a
    destination goes down (becomes probing). A typical use case is to
@@ -1340,7 +1358,7 @@ event_route[dispatcher:dst-down] {
 }
 ...
 
-8.2.  dispatcher:dst-up
+8.2. dispatcher:dst-up
 
    When defined, the module calls event_route[dispatcher:ds-up] when a
    destination that was previously down (probing) comes up. A typical use

+ 12 - 0
modules/dispatcher/dispatch.c

@@ -2244,6 +2244,18 @@ int ds_is_from_list(struct sip_msg *_m, int group)
 							return -2;
 						}
 					}
+					if(ds_attrs_pvname.s!=0 && list->dlist[j].attrs.body.len>0)
+					{
+						memset(&val, 0, sizeof(pv_value_t));
+						val.flags = PV_VAL_STR;
+						val.rs = list->dlist[j].attrs.body;
+						if(ds_attrs_pv.setf(_m, &ds_attrs_pv.pvp,
+									(int)EQ_T, &val)<0)
+						{
+							LM_ERR("setting attrs pv failed\n");
+							return -3;
+						}
+					}
 					return 1;
 				}
 			}

+ 2 - 0
modules/dispatcher/dispatch.h

@@ -87,6 +87,8 @@ extern pv_elem_t * hash_param_model;
 
 extern str ds_setid_pvname;
 extern pv_spec_t ds_setid_pv;
+extern str ds_attrs_pvname;
+extern pv_spec_t ds_attrs_pv;
 
 /* Structure containing pointers to TM-functions */
 extern struct tm_binds tmb;

+ 24 - 2
modules/dispatcher/dispatcher.c

@@ -136,6 +136,8 @@ str ds_table_name        = str_init(DS_TABLE_NAME);
 
 str ds_setid_pvname   = {NULL, 0};
 pv_spec_t ds_setid_pv;
+str ds_attrs_pvname   = {NULL, 0};
+pv_spec_t ds_attrs_pv;
 
 /** module functions */
 static int mod_init(void);
@@ -181,7 +183,7 @@ static cmd_export_t cmds[]={
 	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list0, 0,
 		0, 0, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE},
 	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list1, 1,
-		fixup_uint_null, 0, ANY_ROUTE},
+		fixup_igp_null, 0, ANY_ROUTE},
 	{"ds_load_unset",    (cmd_function)w_ds_load_unset,   0,
 		0, 0, ANY_ROUTE},
 	{"ds_load_update",   (cmd_function)w_ds_load_update,  0,
@@ -211,6 +213,7 @@ static param_export_t params[]={
 	{"attrs_avp",       STR_PARAM, &attrs_avp_param.s},
 	{"hash_pvar",       STR_PARAM, &hash_pvar_param.s},
 	{"setid_pvname",    STR_PARAM, &ds_setid_pvname.s},
+	{"attrs_pvname",    STR_PARAM, &ds_attrs_pvname.s},
 	{"ds_probing_threshhold", INT_PARAM, &probing_threshhold},
 	{"ds_ping_method",     STR_PARAM, &ds_ping_method.s},
 	{"ds_ping_from",       STR_PARAM, &ds_ping_from.s},
@@ -282,6 +285,8 @@ static int mod_init(void)
 		hash_pvar_param.len = strlen(hash_pvar_param.s);
 	if (ds_setid_pvname.s)
 		ds_setid_pvname.len = strlen(ds_setid_pvname.s);
+	if (ds_attrs_pvname.s)
+		ds_attrs_pvname.len = strlen(ds_attrs_pvname.s);
 	if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s);
 	if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s);
 	if (ds_outbound_proxy.s) ds_outbound_proxy.len = strlen(ds_outbound_proxy.s);
@@ -462,6 +467,17 @@ static int mod_init(void)
 			return -1;
 		}
 	}
+
+	if(ds_attrs_pvname.s!=0)
+	{
+		if(pv_parse_spec(&ds_attrs_pvname, &ds_attrs_pv)==NULL
+				|| !pv_is_w(&ds_attrs_pv))
+		{
+			LM_ERR("[%s]- invalid attrs_pvname\n", ds_attrs_pvname.s);
+			return -1;
+		}
+	}
+
 	if (dstid_avp_param.s && dstid_avp_param.len > 0)
 	{
 		if(ds_hash_size>0)
@@ -791,7 +807,13 @@ static int w_ds_is_from_list0(struct sip_msg *msg, char *str1, char *str2)
 
 static int w_ds_is_from_list1(struct sip_msg *msg, char *set, char *str2)
 {
-	return ds_is_from_list(msg, (int)(long)set);
+	int s;
+	if(fixup_get_ivalue(msg, (gparam_p)set, &s)!=0)
+	{
+		LM_ERR("cannot get set id value\n");
+		return -1;
+	}
+	return ds_is_from_list(msg, s);
 }
 
 static int ds_parse_reply_codes() {

+ 24 - 3
modules/dispatcher/doc/dispatcher_admin.xml

@@ -473,8 +473,27 @@ modparam("dispatcher", "force_dst", 1)
  ...
  </programlisting>
  		</example>
- 	</section>
-
+	</section>
+	<section id="dispatcher.p.attrs_pvname">
+		<title><varname>attrs_pvname</varname> (str)</title>
+		<para>
+		The name of the PV where to store the attributes of matching address
+		when calling ds_is_from_list().
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>null</quote> - don't set PV.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set the <quote>attrs_pvname</quote> parameter</title>
+ <programlisting format="linespecific">
+ ...
+ modparam("dispatcher", "attrs_pvname", "$var(attrs)")
+ ...
+ </programlisting>
+		</example>
+	</section>
  	<section>
  		<title><varname>ds_ping_method</varname> (string)</title>
  		<para>
@@ -967,7 +986,9 @@ failure_route[tryagain] {
 		Parameter groupid is optional, when it is missing, then the matching
 		will be done against all addresses in all groups. Upon a match, the
 		variable specified by 'setid_pvname' parameter will be set to groupid
-		of matching address.
+		of matching address and the attributes will be set in variable
+		specified by 'attrs_pvname'. The parameter can be an integer or a
+		variable holding an integer value.
  		</para>
 		<para>
 			This function can be used from ANY_ROUTE.

+ 32 - 0
modules/htable/README

@@ -51,6 +51,8 @@ Alex Balashov
               4.1. sht_print()
               4.2. sht_rm_name_re(htable=>regexp)
               4.3. sht_rm_value_re(htable=>regexp)
+              4.4. sht_lock(htable=>key)
+              4.5. sht_unlock(htable=>key)
 
         5. Exported pseudo-variables
         6. MI Commands
@@ -92,6 +94,8 @@ Alex Balashov
    1.15. sht_print usage
    1.16. sht_rm_name_re usage
    1.17. sht_rm_value_re usage
+   1.18. sht_lock usage
+   1.19. sht_unlock usage
 
 Chapter 1. Admin Guide
 
@@ -124,6 +128,8 @@ Chapter 1. Admin Guide
         4.1. sht_print()
         4.2. sht_rm_name_re(htable=>regexp)
         4.3. sht_rm_value_re(htable=>regexp)
+        4.4. sht_lock(htable=>key)
+        4.5. sht_unlock(htable=>key)
 
    5. Exported pseudo-variables
    6. MI Commands
@@ -450,6 +456,8 @@ modparam("htable", "db_expires", 1)
    4.1. sht_print()
    4.2. sht_rm_name_re(htable=>regexp)
    4.3. sht_rm_value_re(htable=>regexp)
+   4.4. sht_lock(htable=>key)
+   4.5. sht_unlock(htable=>key)
 
 4.1.  sht_print()
 
@@ -490,6 +498,30 @@ sht_rm_name_re("ha=>.*");
 sht_rm_value_re("ha=>.*");
 ...
 
+4.4.  sht_lock(htable=>key)
+
+   Lock the slot in htable corespoding to the key item.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.18. sht_lock usage
+...
+sht_lock("ha=>test");
+...
+
+4.5.  sht_unlock(htable=>key)
+
+   Unlock the slot in htable corespoding to the key item.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.19. sht_unlock usage
+...
+sht_lock("ha=>test");
+$sht(ha=>test) = $sht(ha=>test) + 10;
+sht_unlock("ha=>test");
+...
+
 5. Exported pseudo-variables
 
      * $sht(htable=>key)

+ 40 - 0
modules/htable/doc/htable_admin.xml

@@ -567,6 +567,46 @@ sht_rm_name_re("ha=>.*");
 ...
 sht_rm_value_re("ha=>.*");
 ...
+</programlisting>
+		</example>
+	</section>
+	<section id="htable.f.sht_lock">
+		<title>
+		<function moreinfo="none">sht_lock(htable=>key)</function>
+		</title>
+		<para>
+			Lock the slot in htable corespoding to the key item.
+		</para>
+		<para>
+			This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>sht_lock</function> usage</title>
+		<programlisting format="linespecific">
+...
+sht_lock("ha=>test");
+...
+</programlisting>
+		</example>
+	</section>
+	<section id="htable.f.sht_unlock">
+		<title>
+		<function moreinfo="none">sht_unlock(htable=>key)</function>
+		</title>
+		<para>
+			Unlock the slot in htable corespoding to the key item.
+		</para>
+		<para>
+			This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>sht_unlock</function> usage</title>
+		<programlisting format="linespecific">
+...
+sht_lock("ha=>test");
+$sht(ha=>test) = $sht(ha=>test) + 10;
+sht_unlock("ha=>test");
+...
 </programlisting>
 		</example>
 	</section>

+ 0 - 4
modules/htable/ht_api.c

@@ -36,10 +36,6 @@
 #include "ht_db.h"
 
 
-#define ht_compute_hash(_s)        core_case_hash(_s,0,0)
-#define ht_get_entry(_h,_size)    (_h)&((_size)-1)
-
-
 ht_t *_ht_root = NULL;
 
 typedef struct _keyvalue {

+ 3 - 0
modules/htable/ht_api.h

@@ -29,6 +29,9 @@
 #include "../../locking.h"
 #include "../../pvar.h"
 
+#define ht_compute_hash(_s)        core_case_hash(_s,0,0)
+#define ht_get_entry(_h,_size)    (_h)&((_size)-1)
+
 typedef struct _ht_cell
 {
     unsigned int cellid;

+ 94 - 4
modules/htable/htable.c

@@ -32,6 +32,7 @@
 #include "../../timer.h"
 #include "../../route.h"
 #include "../../dprint.h"
+#include "../../hashes.h"
 #include "../../ut.h"
 #include "../../rpc.h"
 #include "../../rpc_lookup.h"
@@ -58,9 +59,11 @@ static int mod_init(void);
 static int child_init(int rank);
 static void destroy(void);
 
-static int fixup_ht_rm(void** param, int param_no);
+static int fixup_ht_key(void** param, int param_no);
 static int ht_rm_name_re(struct sip_msg* msg, char* key, char* foo);
 static int ht_rm_value_re(struct sip_msg* msg, char* key, char* foo);
+static int ht_slot_lock(struct sip_msg* msg, char* key, char* foo);
+static int ht_slot_unlock(struct sip_msg* msg, char* key, char* foo);
 
 int ht_param(modparam_t type, void* val);
 
@@ -96,9 +99,13 @@ static mi_export_t mi_cmds[] = {
 static cmd_export_t cmds[]={
 	{"sht_print",       (cmd_function)ht_print,        0, 0, 0,
 		ANY_ROUTE},
-	{"sht_rm_name_re",  (cmd_function)ht_rm_name_re,   1, fixup_ht_rm, 0,
+	{"sht_rm_name_re",  (cmd_function)ht_rm_name_re,   1, fixup_ht_key, 0,
 		ANY_ROUTE},
-	{"sht_rm_value_re", (cmd_function)ht_rm_value_re,  1, fixup_ht_rm, 0,
+	{"sht_rm_value_re", (cmd_function)ht_rm_value_re,  1, fixup_ht_key, 0,
+		ANY_ROUTE},
+	{"sht_lock",        (cmd_function)ht_slot_lock,    1, fixup_ht_key, 0,
+		ANY_ROUTE},
+	{"sht_unlock",      (cmd_function)ht_slot_unlock,  1, fixup_ht_key, 0,
 		ANY_ROUTE},
 	{"bind_htable",     (cmd_function)bind_htable,     0, 0, 0,
 		ANY_ROUTE},
@@ -245,7 +252,7 @@ static int ht_print(struct sip_msg *msg, char *s1, char *s2)
 	return 1;
 }
 
-static int fixup_ht_rm(void** param, int param_no)
+static int fixup_ht_key(void** param, int param_no)
 {
 	pv_spec_t *sp;
 	str s;
@@ -324,6 +331,89 @@ static int ht_rm_value_re(struct sip_msg* msg, char* key, char* foo)
 	return 1;
 }
 
+/**
+ * lock the slot for a given key in a hash table
+ */
+static int ht_slot_lock(struct sip_msg* msg, char* key, char* foo)
+{
+	ht_pv_t *hpv;
+	str skey;
+	pv_spec_t *sp;
+	unsigned int hid;
+	unsigned int idx;
+
+	sp = (pv_spec_t*)key;
+
+	hpv = (ht_pv_t*)sp->pvp.pvn.u.dname;
+
+	if(hpv->ht==NULL)
+	{
+		hpv->ht = ht_get_table(&hpv->htname);
+		if(hpv->ht==NULL) {
+			LM_ERR("cannot get $ht root\n");
+			return -11;
+		}
+	}
+	if(pv_printf_s(msg, hpv->pve, &skey)!=0)
+	{
+		LM_ERR("cannot get $ht key\n");
+		return -1;
+	}
+
+	hid = ht_compute_hash(&skey);
+
+	idx = ht_get_entry(hid, hpv->ht->htsize);
+
+	LM_DBG("unlocking slot %.*s[%u] for key %.*s\n",
+			hpv->htname.len, hpv->htname.s,
+			idx, skey.len, skey.s);
+
+	lock_get(&hpv->ht->entries[idx].lock);
+
+	return 1;
+}
+
+/**
+ * unlock the slot for a given key in a hash table
+ */
+static int ht_slot_unlock(struct sip_msg* msg, char* key, char* foo)
+{
+	ht_pv_t *hpv;
+	str skey;
+	pv_spec_t *sp;
+	unsigned int hid;
+	unsigned int idx;
+
+	sp = (pv_spec_t*)key;
+
+	hpv = (ht_pv_t*)sp->pvp.pvn.u.dname;
+
+	if(hpv->ht==NULL)
+	{
+		hpv->ht = ht_get_table(&hpv->htname);
+		if(hpv->ht==NULL) {
+			LM_ERR("cannot get $ht root\n");
+			return -11;
+		}
+	}
+	if(pv_printf_s(msg, hpv->pve, &skey)!=0)
+	{
+		LM_ERR("cannot get $ht key\n");
+		return -1;
+	}
+
+	hid = ht_compute_hash(&skey);
+
+	idx = ht_get_entry(hid, hpv->ht->htsize);
+
+	LM_DBG("unlocking slot %.*s[%u] for key %.*s\n",
+			hpv->htname.len, hpv->htname.s,
+			idx, skey.len, skey.s);
+
+	lock_release(&hpv->ht->entries[idx].lock);
+
+	return 1;
+}
 
 int ht_param(modparam_t type, void *val)
 {

+ 55 - 0
modules/ipops/README

@@ -36,6 +36,8 @@ I
               4.8. compare_pure_ips (ip1, ip2)
               4.9. is_ip_rfc1918 (ip)
               4.10. is_in_subnet (ip, subnet)
+              4.11. dns_sys_match_ip(hostname, ipaddr)
+              4.12. dns_int_match_ip(hostname, ipaddr)
 
    List of Examples
 
@@ -49,6 +51,8 @@ I
    1.8. compare_pure_ips usage
    1.9. is_ip_rfc1918 usage
    1.10. is_in_subnet usage
+   1.11. dns_sys_match_ip usage
+   1.12. dns_int_match_ip usage
 
 Chapter 1. Admin Guide
 
@@ -73,6 +77,8 @@ Chapter 1. Admin Guide
         4.8. compare_pure_ips (ip1, ip2)
         4.9. is_ip_rfc1918 (ip)
         4.10. is_in_subnet (ip, subnet)
+        4.11. dns_sys_match_ip(hostname, ipaddr)
+        4.12. dns_int_match_ip(hostname, ipaddr)
 
 1. Overview
 
@@ -124,6 +130,8 @@ Chapter 1. Admin Guide
    4.8. compare_pure_ips (ip1, ip2)
    4.9. is_ip_rfc1918 (ip)
    4.10. is_in_subnet (ip, subnet)
+   4.11. dns_sys_match_ip(hostname, ipaddr)
+   4.12. dns_int_match_ip(hostname, ipaddr)
 
 4.1. is_ip (ip)
 
@@ -329,3 +337,50 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
   xlog("L_INFO", "it's in the subnet\n");
 }
 ...
+
+4.11. dns_sys_match_ip(hostname, ipaddr)
+
+   Returns TRUE if ipaddr is associated by DNS to hostname. FALSE
+   otherwise. It does not use the internal DNS resolver, but directly
+   getaddrinfo(...). All addresses returned for the hostname are checked.
+   Note that some hosts may return different lists of IP addresses for
+   each query, if the DNS server is configured in that way (e.g., for
+   providing load balancing through DNS).
+
+   Parameters:
+     * ipaddr - string or pseudo-variable containing the ip address.
+     * hostname - string or pseudo-variable containing the hostname. The
+       resulting IP addresses from DNS query are compared with ipaddr.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.11. dns_sys_match_ip usage
+...
+if (!dns_sys_match_ip("myhost.com", "1.2.3.4")) {
+    xdbg("ip address not associated with hostname\n");
+}
+...
+
+4.12. dns_int_match_ip(hostname, ipaddr)
+
+   Returns TRUE if ipaddr is associated by DNS to hostname. FALSE
+   otherwise. It uses internal DNS resolver. At this moment, the function
+   might not check all the IP addresses as returned by dns_sys_match_ip(),
+   because the internal resolver targets to discover the first address to
+   be used for relaying SIP traffic. Thus is better to use
+   dns_sys_match_ip() if the host you want to check has many IP addresses,
+   in different address famililies (IPv4/6).
+
+   Parameters:
+     * ipaddr - string or pseudo-variable containing the ip address.
+     * hostname - string or pseudo-variable containing the hostname. The
+       resulting IP addresses from DNS query are compared with ipaddr.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.12. dns_int_match_ip usage
+...
+if (!dns_int_match_ip("myhost.com", "1.2.3.4")) {
+    xdbg("ip address not associated with hostname\n");
+}
+...

+ 97 - 0
modules/ipops/doc/ipops_admin.xml

@@ -523,6 +523,103 @@ if (is_ip_rfc1918("10.0.123.123")) {
 if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
   xlog("L_INFO", "it's in the subnet\n");
 }
+...
+        </programlisting>
+      </example>
+
+    </section>
+
+    <section id="ipops.f.dns_sys_match_ip">
+      <title>
+        <function moreinfo="none">dns_sys_match_ip(hostname, ipaddr)</function>
+      </title>
+
+      <para>
+		  Returns TRUE if ipaddr is associated by DNS to hostname. FALSE otherwise. It
+		  does not use the internal DNS resolver, but directly getaddrinfo(...). All
+		  addresses returned for the hostname are checked. Note that some hosts may
+		  return different lists of IP addresses for each query, if the DNS server
+		  is configured in that way (e.g., for providing load balancing through DNS).
+      </para>
+
+      <para>Parameters:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            <emphasis>ipaddr</emphasis> - string or pseudo-variable containing the ip address.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+			  <emphasis>hostname</emphasis> - string or pseudo-variable containing the hostname.
+			  The resulting IP addresses from DNS query are compared with ipaddr.
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <para>
+        This function can be used from ANY_ROUTE.
+      </para>
+
+      <example>
+        <title>
+          <function>dns_sys_match_ip</function> usage
+        </title>
+        <programlisting format="linespecific">
+...
+if (!dns_sys_match_ip("myhost.com", "1.2.3.4")) {
+    xdbg("ip address not associated with hostname\n");
+}
+...
+        </programlisting>
+      </example>
+
+    </section>
+
+    <section id="ipops.f.dns_int_match_ip">
+      <title>
+        <function moreinfo="none">dns_int_match_ip(hostname, ipaddr)</function>
+      </title>
+
+      <para>
+		  Returns TRUE if ipaddr is associated by DNS to hostname. FALSE otherwise. It
+		  uses internal DNS resolver. At this moment, the function might not check all
+		  the IP addresses as returned by dns_sys_match_ip(), because the internal
+		  resolver targets to discover the first address to be used for relaying
+		  SIP traffic. Thus is better to use dns_sys_match_ip() if the host you want
+		  to check has many IP addresses, in different address famililies (IPv4/6).
+      </para>
+
+      <para>Parameters:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            <emphasis>ipaddr</emphasis> - string or pseudo-variable containing the ip address.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+			  <emphasis>hostname</emphasis> - string or pseudo-variable containing the hostname.
+			  The resulting IP addresses from DNS query are compared with ipaddr.
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <para>
+        This function can be used from ANY_ROUTE.
+      </para>
+
+      <example>
+        <title>
+          <function>dns_int_match_ip</function> usage
+        </title>
+        <programlisting format="linespecific">
+...
+if (!dns_int_match_ip("myhost.com", "1.2.3.4")) {
+    xdbg("ip address not associated with hostname\n");
+}
 ...
         </programlisting>
       </example>

+ 136 - 0
modules/ipops/ipops_mod.c

@@ -40,12 +40,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 #include <arpa/inet.h>
 #include "../../sr_module.h"
 #include "../../dprint.h"
 #include "../../str.h"
 #include "../../mod_fix.h"
 #include "../../pvar.h"
+#include "../../resolve.h"
 #include "api.h"
 #include "ip_parser.h"
 #include "rfc1918_parser.h"
@@ -83,6 +87,8 @@ static int w_compare_ips(struct sip_msg*, char*, char*);
 static int w_compare_pure_ips(struct sip_msg*, char*, char*);
 static int w_is_ip_rfc1918(struct sip_msg*, char*);
 static int w_ip_is_in_subnet(struct sip_msg*, char*, char*);
+static int w_dns_sys_match_ip(sip_msg_t*, char*, char*);
+static int w_dns_int_match_ip(sip_msg_t*, char*, char*);
 
 
 /*
@@ -110,6 +116,10 @@ static cmd_export_t cmds[] =
   REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
   { "is_in_subnet", (cmd_function)w_ip_is_in_subnet, 2, fixup_spve_spve, 0,
   REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+  { "dns_sys_match_ip", (cmd_function)w_dns_sys_match_ip, 2, fixup_spve_spve, 0,
+  ANY_ROUTE },
+  { "dns_int_match_ip", (cmd_function)w_dns_int_match_ip, 2, fixup_spve_spve, 0,
+  ANY_ROUTE },
   { "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0 }
 };
@@ -596,3 +606,129 @@ static int w_is_ip_rfc1918(struct sip_msg* _msg, char* _s)
   else
     return -1;
 }
+
+static inline ip_addr_t *strtoipX(str *ips)
+{
+	/* try to figure out INET class */
+	if(ips->s[0] == '[' || memchr(ips->s, ':', ips->len)!=NULL)
+	{
+		/* IPv6 */
+		return str2ip6(ips);
+	} else {
+		/* IPv4 */
+		return str2ip(ips);
+	}
+}
+
+static int w_dns_sys_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
+{
+	struct addrinfo hints, *res, *p;
+	int status;
+	ip_addr_t *ipa;
+	void *addr;
+	str hns;
+	str ips;
+	struct sockaddr_in *ipv4;
+	struct sockaddr_in6 *ipv6;
+
+	if (fixup_get_svalue(msg, (gparam_p)hnp, &hns))
+	{
+		LM_ERR("cannot evaluate hostname parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(msg, (gparam_p)ipp, &ips))
+	{
+		LM_ERR("cannot evaluate ip address parameter\n");
+		return -2;
+	}
+
+	ipa = strtoipX(&ips);
+	if(ipa==NULL)
+	{
+		LM_ERR("invalid ip address: %.*s\n", ips.len, ips.s);
+		return -3;
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_UNSPEC; /* allow any of AF_INET or AF_INET6 */
+
+	if ((status = getaddrinfo(hns.s, NULL, &hints, &res)) != 0)
+	{
+        LM_ERR("getaddrinfo: %s\n", gai_strerror(status));
+        return -4;
+    }
+
+	for(p = res;p != NULL; p = p->ai_next)
+	{
+		if(p->ai_family==ipa->af)
+		{
+			if (p->ai_family==AF_INET)
+			{
+				ipv4 = (struct sockaddr_in *)p->ai_addr;
+				addr = &(ipv4->sin_addr);
+			} else {
+				ipv6 = (struct sockaddr_in6 *)p->ai_addr;
+				addr = &(ipv6->sin6_addr);
+			}
+			if(memcmp(ipa->u.addr, addr, ipa->len)==0)
+			{
+				/* matched IP */
+				freeaddrinfo(res);
+				return 1;
+			}
+		}
+    }
+	freeaddrinfo(res);
+
+	return -1;
+}
+
+static int w_dns_int_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
+{
+	ip_addr_t *ipa;
+	str hns;
+	str ips;
+	struct hostent* he;
+	char ** h;
+	int ret;
+
+	if (fixup_get_svalue(msg, (gparam_p)hnp, &hns))
+	{
+		LM_ERR("cannot evaluate hostname parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(msg, (gparam_p)ipp, &ips))
+	{
+		LM_ERR("cannot evaluate ip address parameter\n");
+		return -2;
+	}
+
+	ipa = strtoipX(&ips);
+	if(ipa==NULL)
+	{
+		LM_ERR("invalid ip address: %.*s\n", ips.len, ips.s);
+		return -3;
+	}
+
+	he=resolvehost(hns.s);
+	if (he==0) {
+		DBG("could not resolve %s\n", hns.s);
+		return -4;
+	}
+	ret = 0;
+	if (he->h_addrtype==ipa->af)
+	{
+		for(h=he->h_addr_list; (*h); h++)
+		{
+			if(memcmp(ipa->u.addr, *h, ipa->len)==0)
+			{
+				/* match */
+				return 1;
+			}
+		}
+	}
+	/* no match */
+	return -1;
+}

+ 2 - 3
modules/nathelper/nathelper.c

@@ -671,9 +671,8 @@ mod_init(void)
 				" set in usrloc module\n");
 			return -1;
 		}
-		if (natping_processes>=8) {
-			LM_ERR("too many natping processes (%d) max=8\n",
-				natping_processes);
+		if (natping_processes<0) {
+			LM_ERR("bad config - natping_processes must be >= 0\n");
 			return -1;
 		}
 

+ 3 - 6
modules/pipelimit/pl_ht.c

@@ -566,16 +566,15 @@ struct mi_root* mi_set_pipe(struct mi_root* cmd_tree, void* param)
 	it->algo = algo_id;
 	it->limit = limit;
 
+	pl_pipe_release(&pipeid);
+
 	if (check_feedback_setpoints(0)) {
-		pl_pipe_release(&pipeid);
 		LM_ERR("feedback limits don't match\n");
 		goto error;
 	} else {
 		*_pl_pid_setpoint = 0.01 * (double)_pl_cfg_setpoint;
 	}
 
-	pl_pipe_release(&pipeid);
-
 	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
 error:
 	return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
@@ -676,16 +675,14 @@ void rpc_pl_set_pipe(rpc_t *rpc, void *c)
 
 	it->algo = algo_id;
 	it->limit = limit;
+	pl_pipe_release(&pipeid);
 
 	if (check_feedback_setpoints(0)) {
-		pl_pipe_release(&pipeid);
 		LM_ERR("feedback limits don't match\n");
 		rpc->fault(c, 400, "Feedback limits don't match");
 		return;
 	} else {
 		*_pl_pid_setpoint = 0.01 * (double)_pl_cfg_setpoint;
 	}
-
-	pl_pipe_release(&pipeid);
 }
 

+ 110 - 0
modules/pv/pv_trans.c

@@ -104,6 +104,82 @@ char *tr_set_crt_buffer(void)
 		val->rs.s = _tr_buffer; \
 	} while(0);
 
+/* -- helper functions */
+
+/* Converts a hex character to its integer value */
+static char pv_from_hex(char ch)
+{
+	return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/* Converts an integer value to its hex character */
+static char pv_to_hex(char code)
+{
+	static char hex[] = "0123456789abcdef";
+	return hex[code & 15];
+}
+
+/*! \brief
+ *  URL Encodes a string for use in a HTTP query
+ */
+static int urlencode_param(str *sin, str *sout)
+{
+	char *at, *p;
+
+	at = sout->s;
+	p  = sin->s;
+
+	if (sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL ||
+			sin->len<0 || sout->len < 3*sin->len+1)
+		return -1;
+
+	while (p < sin->s+sin->len) {
+		if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p == '~')
+			*at++ = *p;
+		else if (*p == ' ')
+			*at++ = '+';
+		else
+			*at++ = '%', *at++ = pv_to_hex(*p >> 4), *at++ = pv_to_hex(*p & 15);
+		p++;
+	}
+
+	*at = 0;
+	sout->len = at - sout->s;
+	LM_DBG("urlencoded string is <%s>\n", sout->s);
+
+	return 0;
+}
+
+/* URL Decode a string */
+static int urldecode_param(str *sin, str *sout) {
+	char *at, *p;
+
+	at = sout->s;
+	p  = sin->s;
+
+	while (p < sin->s+sin->len) {
+		if (*p == '%') {
+			if (p[1] && p[2]) {
+				*at++ = pv_from_hex(p[1]) << 4 | pv_from_hex(p[2]);
+				p += 2;
+			}
+		} else if (*p == '+') {
+			*at++ = ' ';
+		} else {
+			*at++ = *p;
+		}
+		p++;
+	}
+
+	*at = 0;
+	sout->len = at - sout->s;
+
+	LM_DBG("urldecoded string is <%s>\n", sout->s);
+	return 0;
+}
+
+/* -- transformations functions */
+
 /*!
  * \brief Evaluate string transformations
  * \param msg SIP message
@@ -827,6 +903,34 @@ int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype,
 			val->rs.len = j;
 			break;
 
+		case TR_S_URLENCODEPARAM:
+			if(!(val->flags&PV_VAL_STR))
+				val->rs.s = int2str(val->ri, &val->rs.len);
+			if(val->rs.len>TR_BUFFER_SIZE-1)
+				return -1;
+			st.s = _tr_buffer;
+			st.len = TR_BUFFER_SIZE;
+			if (urlencode_param(&val->rs, &st) < 0)
+				return -1;
+			memset(val, 0, sizeof(pv_value_t));
+			val->flags = PV_VAL_STR;
+			val->rs = st;
+			break;
+
+		case TR_S_URLDECODEPARAM:
+			if(!(val->flags&PV_VAL_STR))
+				val->rs.s = int2str(val->ri, &val->rs.len);
+			if(val->rs.len>TR_BUFFER_SIZE-1)
+				return -1;
+			st.s = _tr_buffer;
+			st.len = TR_BUFFER_SIZE;
+			if (urldecode_param(&val->rs, &st) < 0)
+				return -1;
+			memset(val, 0, sizeof(pv_value_t));
+			val->flags = PV_VAL_STR;
+			val->rs = st;
+			break;
+
 		default:
 			LM_ERR("unknown subtype %d\n",
 					subtype);
@@ -2061,6 +2165,12 @@ char* tr_parse_string(str* in, trans_t *t)
 			goto error;
 		}
 		goto done;
+	} else if(name.len==15 && strncasecmp(name.s, "urlencode.param", 15)==0) {
+		t->subtype = TR_S_URLENCODEPARAM;
+		goto done;
+	} else if(name.len==15 && strncasecmp(name.s, "urldecode.param", 15)==0) {
+		t->subtype = TR_S_URLDECODEPARAM;
+		goto done;
 	}
 
 	LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,

+ 2 - 1
modules/pv/pv_trans.h

@@ -41,7 +41,8 @@ enum _tr_s_subtype {
 	TR_S_ESCAPECOMMON, TR_S_UNESCAPECOMMON, TR_S_ESCAPEUSER, TR_S_UNESCAPEUSER,
 	TR_S_ESCAPEPARAM, TR_S_UNESCAPEPARAM, TR_S_TOLOWER, TR_S_TOUPPER,
 	TR_S_STRIP, TR_S_STRIPTAIL, TR_S_PREFIXES, TR_S_PREFIXES_QUOT, TR_S_REPLACE,
-	TR_S_TIMEFORMAT, TR_S_TRIM, TR_S_RTRIM, TR_S_LTRIM, TR_S_RM, TR_S_STRIPTO
+	TR_S_TIMEFORMAT, TR_S_TRIM, TR_S_RTRIM, TR_S_LTRIM, TR_S_RM, TR_S_STRIPTO,
+	TR_S_URLENCODEPARAM, TR_S_URLDECODEPARAM
 };
 enum _tr_uri_subtype {
 	TR_URI_NONE=0, TR_URI_USER, TR_URI_HOST, TR_URI_PASSWD, TR_URI_PORT,

+ 1 - 1
modules/sipcapture/sipcapture.c

@@ -721,7 +721,7 @@ static int sip_capture_prepare(sip_msg_t *msg)
         /* We need parse all headers */
         if (parse_headers(msg, HDR_CALLID_F|HDR_EOH_F, 0) != 0) {
                 LM_ERR("cannot parse headers\n");
-                return -1;
+                return 0;
         }
 
         return 0;

+ 257 - 265
modules/tls/README

@@ -1,12 +1,11 @@
-
 TLS Module
 
 Andrei Pelinescu-Onciul
 
    iptelorg GmbH
 
-   Copyright © 2007 iptelorg GmbH
-     _________________________________________________________________
+   Copyright (c) 2007 iptelorg GmbH
+     __________________________________________________________________
 
    Table of Contents
 
@@ -171,17 +170,17 @@ Chapter 1. Admin Guide
 
 1. Overview
 
-   This  module  implements  the  TLS  transport  for  Kamailio using the
-   OpenSSL  library  (http://www.openssl.org).  To enable the TLS support
-   this  module  must  be  loaded and enable_tls=yes must be added to the
-   Kamailio config file
+   This module implements the TLS transport for Kamailio using the OpenSSL
+   library (http://www.openssl.org). To enable the TLS support this module
+   must be loaded and enable_tls=yes must be added to the Kamailio config
+   file
 
 2. Quick Start
 
    Make sure you have a proper certificate and private key and either use
-   the  certificate  and  private_key module parameters, or make sure the
+   the certificate and private_key module parameters, or make sure the
    certificate and key are in the same PEM file, named cert.pem an placed
-   in  [your-cfg-install-prefix]/etc/kamailio/.  Don't forget to load the
+   in [your-cfg-install-prefix]/etc/kamailio/. Don't forget to load the
    tls module and to enable TLS (add enable_tls=yes to your config).
 
    Example 1.1. quick start config
@@ -200,51 +199,50 @@ route{
 
 3. Important Notes
 
-   The  TLS  module  needs  some  special  options enabled when compiling
+   The TLS module needs some special options enabled when compiling
    Kamailio. These options are enabled by default, however in case you're
-   using  a  modified  Kamailio  version  or Makefile, make sure that you
-   enable  -DUSE_TLS  and  -DTLS_HOOKS  (or compile with make TLS_HOOKS=1
-   which  will  take  care  of  both  options).  To quickly check if your
-   Kamailio  version was compiled with these options, run kamailio -V and
+   using a modified Kamailio version or Makefile, make sure that you
+   enable -DUSE_TLS and -DTLS_HOOKS (or compile with make TLS_HOOKS=1
+   which will take care of both options). To quickly check if your
+   Kamailio version was compiled with these options, run kamailio -V and
    look for USE_TLS and TLS_HOOKS among the flags.
 
-   This  module  includes  several  workarounds  for various Openssl bugs
-   (like  compression  and  Kerberos  using  the wrong memory allocations
-   functions,  low  memory  problems  a.s.o).  On  startup it will try to
-   enable  the  needed  workarounds based on the openssl library version.
-   Each  time  a known problem is detected and a workaround is enabled, a
-   message  will  be logged. In general it is recommended to compile this
-   module on the same machine or a similar machine to where kamailio will
-   be  run  or  to  link it statically with libssl. For example if on the
-   compile  machine  openssl  does not have the kerberos support enabled,
-   but  on  the  target  machine  a  kerberos  enabled openssl library is
-   installed,  kamailio  cannot  apply  the  needed  workarounds and will
-   refuse  to  start.  The same thing will happen if the openssl versions
-   are   too  different  (to  force  kamailio  startup  anyway,  see  the
-   tls_force_run module parameter).
-
-   Try   to   avoid  using  keys  larger  then  1024  bytes.  Large  keys
-   significantly  slow  down  the TLS connection handshake, thus limiting
-   the maximum Kamailio TLS connection rate.
-
-   Compression  is  fully  supported  if  you  have  a new enough Openssl
-   version  (starting  with 0.9.8). Although there are some problems with
-   zlib  compression  in  currently  deployed Openssl versions (up to and
-   including  0.9.8d,  see  openssl  bug  #1468),  the  TLS  module  will
-   automatically  switch  to  its  own  fixed  version. Note however that
-   starting with sr 3.1 compression is not enabled by default, due to the
-   huge  extra memory consumption that it causes (about 10x more memory).
-   To  enable  it  use modparam("tls", "tls_disable_compression", 0) (see
+   This module includes several workarounds for various Openssl bugs (like
+   compression and Kerberos using the wrong memory allocations functions,
+   low memory problems a.s.o). On startup it will try to enable the needed
+   workarounds based on the openssl library version. Each time a known
+   problem is detected and a workaround is enabled, a message will be
+   logged. In general it is recommended to compile this module on the same
+   machine or a similar machine to where kamailio will be run or to link
+   it statically with libssl. For example if on the compile machine
+   openssl does not have the kerberos support enabled, but on the target
+   machine a kerberos enabled openssl library is installed, kamailio
+   cannot apply the needed workarounds and will refuse to start. The same
+   thing will happen if the openssl versions are too different (to force
+   kamailio startup anyway, see the tls_force_run module parameter).
+
+   Try to avoid using keys larger then 1024 bytes. Large keys
+   significantly slow down the TLS connection handshake, thus limiting the
+   maximum Kamailio TLS connection rate.
+
+   Compression is fully supported if you have a new enough Openssl version
+   (starting with 0.9.8). Although there are some problems with zlib
+   compression in currently deployed Openssl versions (up to and including
+   0.9.8d, see openssl bug #1468), the TLS module will automatically
+   switch to its own fixed version. Note however that starting with sr 3.1
+   compression is not enabled by default, due to the huge extra memory
+   consumption that it causes (about 10x more memory). To enable it use
+   modparam("tls", "tls_disable_compression", 0) (see
    tls_disable_compression).
 
-   The  TLS  module  includes workarounds for the following known openssl
-   bugs:    openssl   #1204   (disable   SS_OP_TLS_BLOCK_PADDING_BUG   if
-   compression  is  enabled,  for  versions  between  0.9.8  and 0.9.8c),
-   openssl  #1468 (fix zlib compression memory allocation), openssl #1467
-   (kerberos support will be disabled if the openssl version is less than
-   0.9.8e-beta1)  and  openssl  #1491  (stop  using  tls  in  low  memory
-   situations  due  to  the very high risk of openssl crashing or leaking
-   memory). The bug reports can be viewed at http://rt.openssl.org/.
+   The TLS module includes workarounds for the following known openssl
+   bugs: openssl #1204 (disable SS_OP_TLS_BLOCK_PADDING_BUG if compression
+   is enabled, for versions between 0.9.8 and 0.9.8c), openssl #1468 (fix
+   zlib compression memory allocation), openssl #1467 (kerberos support
+   will be disabled if the openssl version is less than 0.9.8e-beta1) and
+   openssl #1491 (stop using tls in low memory situations due to the very
+   high risk of openssl crashing or leaking memory). The bug reports can
+   be viewed at http://rt.openssl.org/.
 
 4. Compiling the TLS Module
 
@@ -259,33 +257,33 @@ make all include_modules=tls
 
    .
 
-   However  in some cases the openssl library requires linking with other
+   However in some cases the openssl library requires linking with other
    libraries. For example compiling the openssl library with kerberos and
-   zlib-shared  support  will require linking the tls module with libkrb5
-   and  libz.  In  this  case  just  add TLS_EXTRA_LIBS="library list" to
-   make's command line. E.g.:
+   zlib-shared support will require linking the tls module with libkrb5
+   and libz. In this case just add TLS_EXTRA_LIBS="library list" to make's
+   command line. E.g.:
 make TLS_EXTRA_LIBS="-lkrb5 -lz" all include_modules=tls
 
-   In  general,  if Kamailio fails to start with a symbol not found error
-   when  trying  to  load  the  tls module (check the log), it means some
+   In general, if Kamailio fails to start with a symbol not found error
+   when trying to load the tls module (check the log), it means some
    needed library was not linked and it must be added to TLS_EXTRA_LIBS
 
 5. TLS and Low Memory
 
    The openssl library doesn't handle very well low memory situations. If
    memory allocations start to fail (due to memory shortage), openssl can
-   crash  or  cause memory leaks (making the memory shortage even worse).
-   As  of  this  writing  all  openssl  versions were affected (includind
-   0.9.8e),  see  openssl  bug #1491. The tls module has some workarounds
-   for    preventing    this    problem    (see   low_mem_treshold1   and
-   low_mem_threshold2),  however  starting  Kamailio  with  enough shared
-   memory  is higly recommended. When this is not possible a quick way to
-   significantly  reduce  openssl  memory usage it to disable compression
-   (see tls_disable_compression).
+   crash or cause memory leaks (making the memory shortage even worse). As
+   of this writing all openssl versions were affected (includind 0.9.8e),
+   see openssl bug #1491. The tls module has some workarounds for
+   preventing this problem (see low_mem_treshold1 and low_mem_threshold2),
+   however starting Kamailio with enough shared memory is higly
+   recommended. When this is not possible a quick way to significantly
+   reduce openssl memory usage it to disable compression (see
+   tls_disable_compression).
 
 6. TLS Debugging
 
-   Debugging  messages  can be selectively enabled by recompiling the tls
+   Debugging messages can be selectively enabled by recompiling the tls
    module with a combination of the following defines:
      * TLS_WR_DEBUG - debug messages for the write/send part.
      * TLS_RD_DEBUG - debug messages for the read/receive part.
@@ -299,39 +297,39 @@ make -C modules/tls extra_defs="-DTLS_WR_DEBUG -DTLS_RD_DEBUG"
 
 7. Known Limitations
 
-   The  private  key  must  not  encrypted (Kamailio cannot ask you for a
+   The private key must not encrypted (Kamailio cannot ask you for a
    password on startup).
 
-   The  TLS  certificate  verifications  ignores  the  certificate  name,
-   subject  altname  and ip extensions, it just checks if the certificate
-   is  signed by a recognized CA. One can use the select framework to try
-   to  overcome  this limitation (check in the script for the contents of
-   various  certificate  fields), but this is not only slow, but also not
-   exactly standard conforming (the verification should happen during TLS
+   The TLS certificate verifications ignores the certificate name, subject
+   altname and ip extensions, it just checks if the certificate is signed
+   by a recognized CA. One can use the select framework to try to overcome
+   this limitation (check in the script for the contents of various
+   certificate fields), but this is not only slow, but also not exactly
+   standard conforming (the verification should happen during TLS
    connection establishment and not after).
 
    TLS specific config reloading is not safe, so for now better don't use
    it, especially under heavy traffic.
 
-   This  documentation  is  incomplete.  The  provided  selects  are  not
+   This documentation is incomplete. The provided selects are not
    documented. A list with all the ones implemented by the TLS module can
-   be     seen     under     doc/select_list/select_tls.txt     or     or
-   http://sip-router.org/docbook/sip-router/branch/master/select_list/sel
-   ect_list.html#select_list.tls.
+   be seen under doc/select_list/select_tls.txt or or
+   http://sip-router.org/docbook/sip-router/branch/master/select_list/sele
+   ct_list.html#select_list.tls.
 
 8. Quick Certificate Howto
 
-   There  are  various ways to create, sign certificates and manage small
-   CAs   (Certificate  Authorities).  If  you  want  a  GUI,  try  tinyca
-   (http://tinyca.sm-zone.net/),  a  very  nice  and  small CA management
-   application.  If  you  are  in a hurry and everything you have are the
+   There are various ways to create, sign certificates and manage small
+   CAs (Certificate Authorities). If you want a GUI, try tinyca
+   (http://tinyca.sm-zone.net/), a very nice and small CA management
+   application. If you are in a hurry and everything you have are the
    installed openssl libraries and utilities, read on.
 
    Assumptions: we run our own CA.
 
-   Warning:  in  this  example no key is encrypted. The client and server
+   Warning: in this example no key is encrypted. The client and server
    private keys must not be encrypted (Kamailio doesn't support encrypted
-   keys),  so  make  sure  the  corresponding  files are readable only by
+   keys), so make sure the corresponding files are readable only by
    trusted people. You should use a password for your CA private key.
 
 Assumptions
@@ -367,8 +365,8 @@ RANDFILE        = $dir/private/.rand    # private random number file
 If this is not the case create a new openssl config file that uses the above
 paths for the default CA and add to all the openssl commands:
  -config filename. E.g.:
-        openssl ca -config my_openssl.cnf -in kamailio1_cert_req.pem -out kamai
-lio1_cert.pem
+        openssl ca -config my_openssl.cnf -in kamailio1_cert_req.pem -out kamail
+io1_cert.pem
 
 
 Creating CA certificate
@@ -390,16 +388,16 @@ Creating CA certificate
         chmod 600 demoCA/private/cakey.pem
 
 3. create CA self-signed certificate
-        openssl req -out demoCA/cacert.pem   -x509 -new -key demoCA/private/cak
-ey.pem
+        openssl req -out demoCA/cacert.pem   -x509 -new -key demoCA/private/cake
+y.pem
 
 
 Creating a server/client certificate
 ------------------------------------
 1. create a certificate request (and its private key in privkey.pem)
         openssl req -out kamailio1_cert_req.pem -new -nodes
-        WARNING: the organization name should be the same as in the CA certific
-ate.
+        WARNING: the organization name should be the same as in the CA certifica
+te.
 
 2. sign it with the ca certificate
         openssl ca -in kamailio1_cert_req.pem -out kamailio1_cert.pem
@@ -418,14 +416,13 @@ Setting Kamailio to use the certificate
          this is the default place Kamailio searches for).
 
 3. set up Kamailio.cfg to use the certificate
-        if your Kamailio certificate name is different from cert.pem or it is n
-ot
+        if your Kamailio certificate name is different from cert.pem or it is no
+t
         placed in Kamailio cfg. directory, add to your kamailio.cfg:
                 modparam("tls", "certificate", "/path/cert_file_name")
 
 4. set up Kamailio to use the private key
-        if your private key is not contained in the same file as the certificat
-e
+        if your private key is not contained in the same file as the certificate
         (or the certificate name is not the default cert.pem), add to your
          Kamailio.cfg:
                 modparam("tls", "private_key", "/path/private_key_file")
@@ -489,20 +486,19 @@ Revoking a certificate and using a CRL
 9.1. tls_method (string)
 
    Sets the SSL/TLS protocol method. Possible values are:
-     * TLSv1  -  only TLSv1 connections are accepted. This is the default
+     * TLSv1 - only TLSv1 connections are accepted. This is the default
        and recommended method (if you want to be rfc3261 conformant don't
        change it).
      * SSLv3 - only SSLv3 connections are accepted
-     * SSLv2  -  only  SSLv2  connections,  for  old  clients.  Note: you
+     * SSLv2 - only SSLv2 connections, for old clients. Note: you
        shouldn't use SSLv2 for anything which should be highly secure.
-     * SSLv23  -  any  of  the  above  methods will be accepted, with the
+     * SSLv23 - any of the above methods will be accepted, with the
        following limitation: the initial SSL hello message must be V2 (in
-       the  initial  hello  all  the  supported  protocols are advertised
-       enabling  switching  to  a  higher  and more secure version). This
-       means  connections  from  SSLv3  or  TLSv1  clients  will  not  be
-       accepted.
+       the initial hello all the supported protocols are advertised
+       enabling switching to a higher and more secure version). This means
+       connections from SSLv3 or TLSv1 clients will not be accepted.
 
-   If   rfc3261   conformance   is  desired,  TLSv1  must  be  used.  For
+   If rfc3261 conformance is desired, TLSv1 must be used. For
    compatibility with older clients SSLv23 is a good option.
 
    Example 1.3. Set tls_method parameter
@@ -512,17 +508,17 @@ modparam("tls", "tls_method", "TLSv1")
 
 9.2. certificate (string)
 
-   Sets  the certificate file name. The certificate file can also contain
+   Sets the certificate file name. The certificate file can also contain
    the private key in PEM format.
 
-   If  the  file  name starts with a '.' the path will be relative to the
-   working  directory (at runtime). If it starts with a '/' it will be an
-   absolute  path  and  if  it starts with anything else the path will be
-   relative  to  the  main  config  file directory (e.g.: for kamailio -f
+   If the file name starts with a '.' the path will be relative to the
+   working directory (at runtime). If it starts with a '/' it will be an
+   absolute path and if it starts with anything else the path will be
+   relative to the main config file directory (e.g.: for kamailio -f
    /etc/kamailio/kamailio.cfg it will be relative to /etc/kamailio/).
 
-   Warning:  try not to use certificate with keys longer then 1024 bytes.
-   Longer  keys  will  severely impact performance, in particular the TLS
+   Warning: try not to use certificate with keys longer then 1024 bytes.
+   Longer keys will severely impact performance, in particular the TLS
    connection rate.
 
    The default value is [SER_CFG_DIR]/cert.pem.
@@ -536,15 +532,15 @@ modparam("tls", "certificate", "/usr/local/etc/kamailio/my_certificate.pem")
 
    Sets the private key file name.
 
-   If  the  file  name starts with a '.' the path will be relative to the
-   working  directory (at runtime). If it starts with a '/' it will be an
-   absolute  path  and  if  it starts with anything else the path will be
-   relative  to  the  main  config  file directory (e.g.: for kamailio -f
+   If the file name starts with a '.' the path will be relative to the
+   working directory (at runtime). If it starts with a '/' it will be an
+   absolute path and if it starts with anything else the path will be
+   relative to the main config file directory (e.g.: for kamailio -f
    /etc/kamailio/kamailio.cfg it will be relative to /etc/kamailio/).
 
-   Note:  the  private  key  can  be  contained  in  the same file as the
-   certificate  (just  append  it  to  the  certificate  file,  e.g.: cat
-   pkey.pem >> cert.pem)
+   Note: the private key can be contained in the same file as the
+   certificate (just append it to the certificate file, e.g.: cat pkey.pem
+   >> cert.pem)
 
    The default value is [SER_CFG_DIR]/cert.pem.
 
@@ -555,24 +551,23 @@ modparam("tls", "private", "/usr/local/etc/kamailio/my_pkey.pem")
 
 9.4. ca_list (string)
 
-   Sets  the  CA  list  file  name.  This file contains a list of all the
-   trusted  CAs  certificates.  If  a  signature  in  a certificate chain
-   belongs to one of the listed CAs, the authentication will succeed.
+   Sets the CA list file name. This file contains a list of all the
+   trusted CAs certificates. If a signature in a certificate chain belongs
+   to one of the listed CAs, the authentication will succeed.
 
-   If  the  file  name starts with a '.' the path will be relative to the
-   working  directory (at runtime). If it starts with a '/' it will be an
-   absolute  path  and  if  it starts with anything else the path will be
-   relative  to  the  main  config  file directory (e.g.: for kamailio -f
+   If the file name starts with a '.' the path will be relative to the
+   working directory (at runtime). If it starts with a '/' it will be an
+   absolute path and if it starts with anything else the path will be
+   relative to the main config file directory (e.g.: for kamailio -f
    /etc/kamailio/kamailio.cfg it will be relative to /etc/kamailio/).
 
    By default the CA file is not set.
 
    An easy way to create the CA list is to append each trusted trusted CA
-   certificate   in   the  PEM  format  to  one  file,  e.g.:  for  f  in
+   certificate in the PEM format to one file, e.g.: for f in
    trusted_cas/*.pem ; do cat "$f" >> ca_list.pem ; done .
 
-   See  also  verify_certificate,  verify_depth,  require_certificate and
-   crl.
+   See also verify_certificate, verify_depth, require_certificate and crl.
 
    Example 1.6. Set ca_list parameter
 ...
@@ -581,16 +576,16 @@ modparam("tls", "ca_list", "/usr/local/etc/kamailio/ca_list.pem")
 
 9.5. crl (string)
 
-   Sets  the  certificate revocation list file name. This file contains a
-   list  of  revoked  certificates.  Any  attempt  to  verify  a  revoked
+   Sets the certificate revocation list file name. This file contains a
+   list of revoked certificates. Any attempt to verify a revoked
    certificate will fail.
 
    If not set, no crl list will be used.
 
-   If  the  file  name starts with a '.' the path will be relative to the
-   working  directory (at runtime). If it starts with a '/' it will be an
-   absolute  path  and  if  it starts with anything else the path will be
-   relative  to  the  main  config  file directory (e.g.: for kamailio -f
+   If the file name starts with a '.' the path will be relative to the
+   working directory (at runtime). If it starts with a '/' it will be an
+   absolute path and if it starts with anything else the path will be
+   relative to the main config file directory (e.g.: for kamailio -f
    /etc/kamailio/kamailio.cfg it will be relative to /etc/kamailio/).
 
 Note
@@ -600,8 +595,8 @@ Note
 
    By default the crl file is not set.
 
-   To  update  the crl in a running Kamailio, make sure you configure tls
-   via  a  separate  tls  config  file  (the config modparam) and issue a
+   To update the crl in a running Kamailio, make sure you configure tls
+   via a separate tls config file (the config modparam) and issue a
    tls.reload RPC call, e.g.:
  $ kamcmd tls.reload
 
@@ -618,7 +613,7 @@ Note
    To display the CRL contents use:
  $ openssl crl -in crl.pem -noout -text
 
-   See     also    ca_list,    verify_certificate,    verify_depth    and
+   See also ca_list, verify_certificate, verify_depth and
    require_certificate.
 
    Example 1.7. Set crl parameter
@@ -628,10 +623,10 @@ modparam("tls", "crl", "/usr/local/etc/kamailio/crl.pem")
 
 9.6. verify_certificate (boolean)
 
-   If   enabled   it   will  force  certificate  verification.  For  more
-   information see the verify(1) openssl man page.
+   If enabled it will force certificate verification. For more information
+   see the verify(1) openssl man page.
 
-   Note:  the certificate verification will always fail if the ca_list is
+   Note: the certificate verification will always fail if the ca_list is
    empty.
 
    See also: ca_list, require_certificate, verify_depth.
@@ -645,8 +640,8 @@ modparam("tls", "verify_certificate", 1)
 
 9.7. verify_depth (integer)
 
-   Sets   how   far   up  the  certificate  chain  will  the  certificate
-   verification go in the search for a trusted CA.
+   Sets how far up the certificate chain will the certificate verification
+   go in the search for a trusted CA.
 
    See also: ca_list, require_certificate, verify_certificate,
 
@@ -659,8 +654,8 @@ modparam("tls", "verify_depth", 9)
 
 9.8. require_certificate (boolean)
 
-   When  enabled  it  will  require  a  certificate from a client. If the
-   client  does not offer a certificate and verify_certificate is on, the
+   When enabled it will require a certificate from a client. If the client
+   does not offer a certificate and verify_certificate is on, the
    certificate verification will fail.
 
    The default value is off.
@@ -673,10 +668,10 @@ modparam("tls", "require_certificate", 1)
 9.9. cipher_list (string)
 
    Sets the list of accepted ciphers. The list consists of cipher strings
-   separated  by  colons.  For more information on the cipher list format
-   see the cipher(1) openssl man page.
+   separated by colons. For more information on the cipher list format see
+   the cipher(1) openssl man page.
 
-   The  default  value  is not set (all the Openssl supported ciphers are
+   The default value is not set (all the Openssl supported ciphers are
    enabled).
 
    Example 1.11. Set cipher_list parameter
@@ -687,18 +682,18 @@ modparam("tls", "cipher_list", "HIGH")
 9.10. send_timeout (int)
 
    This parameter is obsolete and cannot be used in newer TLS versions (>
-   Kamailio  3.0).  In  these  versions  the  send_timeout is replaced by
+   Kamailio 3.0). In these versions the send_timeout is replaced by
    tcp_send_timeout (common with all the tcp connections).
 
 9.11. handshake_timeout (int)
 
    This parameter is obsolete and cannot be used in newer TLS versions (>
-   Kamailio  3.0). In these versions the handshake_timeout is replaced by
+   Kamailio 3.0). In these versions the handshake_timeout is replaced by
    tcp_connect_timeout (common with all the tcp connections).
 
 9.12. connection_timeout (int)
 
-   Sets  the  amount  of  time after which an idle TLS connection will be
+   Sets the amount of time after which an idle TLS connection will be
    closed, if no I/O ever occured after the initial open. If an I/O event
    occurs, the timeout will be extended with tcp_connection_lifetime. The
    value is expressed in seconds.
@@ -707,7 +702,7 @@ modparam("tls", "cipher_list", "HIGH")
 
    If the value set is -1, the connection will never be close on idle.
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.connection_timeout.
 
    Example 1.12. Set connection_timeout parameter
@@ -720,10 +715,10 @@ modparam("tls", "connection_timeout", 60)
 
 9.13. tls_disable_compression (boolean)
 
-   If   set   compression  over  SSL/TLS  will  be  disabled.  Note  that
-   compression  uses  a  lot  of  memory  (about  10x  more then with the
-   compression  disabled),  so  if you want to minimize memory usage is a
-   good idea to disable it.
+   If set compression over SSL/TLS will be disabled. Note that compression
+   uses a lot of memory (about 10x more then with the compression
+   disabled), so if you want to minimize memory usage is a good idea to
+   disable it.
 
    By default compression is disabled.
 
@@ -734,83 +729,80 @@ modparam("tls", "tls_disable_compression", 0) # enable
 
 9.14. ssl_release_buffers (integer)
 
-   Release  internal OpenSSL read or write buffers as soon as they are no
-   longer  needed.  Combined with ssl_free_list_max_len has the potential
-   of  saving  a  lot  of  memory  (  ~ 32k per connection in the default
-   configuration,  or 16k + ssl_max_send_fragment). For sr versions > 3.0
-   it  makes  little sense to disable it (0) since the tls module already
+   Release internal OpenSSL read or write buffers as soon as they are no
+   longer needed. Combined with ssl_free_list_max_len has the potential of
+   saving a lot of memory ( ~ 32k per connection in the default
+   configuration, or 16k + ssl_max_send_fragment). For sr versions > 3.0
+   it makes little sense to disable it (0) since the tls module already
    has its own internal buffering.
 
-   A  value  of -1 would not change this option from its openssl default.
+   A value of -1 would not change this option from its openssl default.
    Use 0 or 1 for enable/disable.
 
    By default the value is 1 (enabled).
 
 Note
 
-   This  option  is  supported only for OpenSSL versions >= 1.0.0. On all
-   the  other  versions  attempting to change the default will trigger an
-   error.
+   This option is supported only for OpenSSL versions >= 1.0.0. On all the
+   other versions attempting to change the default will trigger an error.
 
    Example 1.15. Set ssl_release_buffers parameter
 modparam("tls", "ssl_release_buffers", 1)
 
 9.15. ssl_free_list_max_len (integer)
 
-   Sets  the maximum number of free memory chunks, that OpenSSL will keep
+   Sets the maximum number of free memory chunks, that OpenSSL will keep
    per connection. Setting it to 0 would cause any unused memory chunk to
    be immediately freed, reducing the memory footprint. A too large value
    would result in extra memory consumption.
 
    Should be combined with ssl_release_buffers.
 
-   A  value of -1 has a special meaning: the OpenSSL default will be used
-   (no  attempt  on changing the value will be made). For OpenSSL 1.0 the
+   A value of -1 has a special meaning: the OpenSSL default will be used
+   (no attempt on changing the value will be made). For OpenSSL 1.0 the
    internal default is 32.
 
    By default the value is 0 (no freelist).
 
 Note
 
-   This  option  is  supported only for OpenSSL versions >= 1.0.0. On all
-   the  other  versions  attempting to change the default will trigger an
-   error.
+   This option is supported only for OpenSSL versions >= 1.0.0. On all the
+   other versions attempting to change the default will trigger an error.
 
    Example 1.16. Set ssl_freelist_max_len parameter
 modparam("tls", "ssl_freelist_max_len", 0)
 
 9.16. ssl_max_send_fragment (integer)
 
-   Sets  the  maximum number of bytes (from the clear text) sent into one
-   TLS  or  SSL  record.  Valid  values  are  between 512 and 16384. Note
-   however  that even valid low values might not be big enough to allow a
+   Sets the maximum number of bytes (from the clear text) sent into one
+   TLS or SSL record. Valid values are between 512 and 16384. Note however
+   that even valid low values might not be big enough to allow a
    succesfull handshake (try minimum 1024).
 
-   Lower  values  would  lead to less memory usage, but values lower then
-   the  typical  Kamailio  write  size  would  incur a slight performance
-   penalty.  Good  values  are  bigger  then  the size of the biggest SIP
-   packet  one  normally  expects  to forward. For example in most setups
-   2048 would be a good value.
+   Lower values would lead to less memory usage, but values lower then the
+   typical Kamailio write size would incur a slight performance penalty.
+   Good values are bigger then the size of the biggest SIP packet one
+   normally expects to forward. For example in most setups 2048 would be a
+   good value.
 
 Note
 
    Values on the lower side, even if valid (> 512), might not allow for a
    succesfull initial handshake. This happens if the certificate does not
-   fit  inside  one  send  fragment. Values lower then 1024 should not be
-   used.  Even with higher values, if the handshake fails, try increasing
+   fit inside one send fragment. Values lower then 1024 should not be
+   used. Even with higher values, if the handshake fails, try increasing
    the value.
 
-   A  value of -1 has a special meaning: the OpenSSL default will be used
+   A value of -1 has a special meaning: the OpenSSL default will be used
    (no attempt on changing the value will be made).
 
-   By  default  the  value  is -1 (the OpenSSL default, which at least in
+   By default the value is -1 (the OpenSSL default, which at least in
    OpenSSL 1.0.0 is ~ 16k).
 
 Note
 
-   This  option  is  supported only for OpenSSL versions >= 0.9.9. On all
-   the  other  versions  attempting to change the default will trigger an
-   error.
+   This option is supported only for OpenSSL versions >= 0.9.9. On all the
+   other versions attempting to change the default will trigger an error.
 
    Example 1.17. Set ssl_max_send_fragment parameter
 modparam("tls", "ssl_max_send_fragment", 4096)
@@ -818,18 +810,18 @@ modparam("tls", "ssl_max_send_fragment", 4096)
 9.17. ssl_read_ahead (boolean)
 
    Enables read ahead, reducing the number of internal OpenSSL BIO read()
-   calls.  This  option has only debugging value, in normal circumstances
-   it should not be changed from the default.
+   calls. This option has only debugging value, in normal circumstances it
+   should not be changed from the default.
 
-   When  disabled  OpenSSL  will  make  at  least  2 BIO read() calls per
-   received  record: one to get the record header and one to get the rest
+   When disabled OpenSSL will make at least 2 BIO read() calls per
+   received record: one to get the record header and one to get the rest
    of the record.
 
    The TLS module buffers internally all read()s and defines its own fast
-   BIO  so  enabling this option would only cause more memory consumption
+   BIO so enabling this option would only cause more memory consumption
    and a minor slow-down (extra memcpy).
 
-   A  value of -1 has a special meaning: the OpenSSL default will be used
+   A value of -1 has a special meaning: the OpenSSL default will be used
    (no attempt on changing the value will be made).
 
    By default the value is 0 (disabled).
@@ -839,15 +831,15 @@ modparam("tls", "ssl_read_ahead", 1)
 
 9.18. send_close_notify (boolean)
 
-   Enables/disables  sending  close  notify  alerts  prior to closing the
-   corresponding  TCP  connection.  Sending the close notify prior to tcp
-   shutdown  is "nicer" from a TLS point of view, but it has a measurable
-   performance   impact.   Default:   off.   Can   be   set   at  runtime
+   Enables/disables sending close notify alerts prior to closing the
+   corresponding TCP connection. Sending the close notify prior to tcp
+   shutdown is "nicer" from a TLS point of view, but it has a measurable
+   performance impact. Default: off. Can be set at runtime
    (tls.send_close_notify).
 
    The default value is 0 (off).
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.send_close_notify.
 
    Example 1.19. Set send_close_notify parameter
@@ -860,13 +852,13 @@ modparam("tls", "send_close_notify", 1)
 
 9.19. con_ct_wq_max (integer)
 
-   Sets  the maximum allowed per connection clear-text send queue size in
-   bytes.  This  queue  is  used  when  data cannot be encrypted and sent
+   Sets the maximum allowed per connection clear-text send queue size in
+   bytes. This queue is used when data cannot be encrypted and sent
    immediately because of an ongoing TLS/SSL level renegotiation.
 
    The default value is 65536 (64 Kb).
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.con_ct_wq_max.
 
    Example 1.21. Set con_ct_wq_max parameter
@@ -879,13 +871,13 @@ modparam("tls", "con_ct_wq_max", 1048576)
 
 9.20. ct_wq_max (integer)
 
-   Sets  the  maximum  total number of bytes queued in all the clear-text
-   send  queues.  These queues are used when data cannot be encrypted and
+   Sets the maximum total number of bytes queued in all the clear-text
+   send queues. These queues are used when data cannot be encrypted and
    sent immediately because of an ongoing TLS/SSL level renegotiation.
 
    The default value is 10485760 (10 Mb).
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.ct_wq_max.
 
    Example 1.23. Set ct_wq_max parameter
@@ -898,13 +890,12 @@ modparam("tls", "ct_wq_max", 4194304)
 
 9.21. ct_wq_blk_size (integer)
 
-   Minimum  block size for the internal clear-text send queues (debugging
-   /  advanced  tunning).  Good  values  are multiple of typical datagram
-   sizes.
+   Minimum block size for the internal clear-text send queues (debugging /
+   advanced tunning). Good values are multiple of typical datagram sizes.
 
    The default value is 4096.
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.ct_wq_blk_size.
 
    Example 1.25. Set ct_wq_blk_size parameter
@@ -921,7 +912,7 @@ modparam("tls", "ct_wq_blk_size", 2048)
 
    The default value is 3 (L_DBG).
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.log.
 
    Example 1.27. Set tls_log parameter
@@ -935,14 +926,14 @@ modparam("tls", "tls_log", 10)
 
 9.23. tls_debug (int)
 
-   Sets  the  log  level at which TLS debug messages will be logged. Note
+   Sets the log level at which TLS debug messages will be logged. Note
    that TLS debug messages are enabled only if the TLS module is compiled
-   with   debugging   enabled  (e.g.  -DTLS_WR_DEBUG,  -DTLS_RD_DEBUG  or
+   with debugging enabled (e.g. -DTLS_WR_DEBUG, -DTLS_RD_DEBUG or
    -DTLS_BIO_DEBUG).
 
    The default value is 3 (L_DBG).
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.debug.
 
    Example 1.29. Set tls_debug parameter
@@ -959,20 +950,20 @@ modparam("tls", "tls_debug", 10)
    Sets the minimal free memory from which attempts to open or accept new
    TLS connections will start to fail. The value is expressed in KB.
 
-   The  default value depends on whether the openssl library used handles
-   well  low  memory  situations  (openssl bug #1491). As of this writing
-   this is not true for any openssl version (including 0.9.8e).
+   The default value depends on whether the openssl library used handles
+   well low memory situations (openssl bug #1491). As of this writing this
+   is not true for any openssl version (including 0.9.8e).
 
-   If  an  ill-behaved  openssl  version is detected, a very conservative
-   value  is  choosed,  which  depends  on the maximum possible number of
-   simultaneously  created  TLS  connections  (and  hence  on the process
+   If an ill-behaved openssl version is detected, a very conservative
+   value is choosed, which depends on the maximum possible number of
+   simultaneously created TLS connections (and hence on the process
    number).
 
    The following values have a special meaning:
      * -1 - use the default value
      * 0 - disable (TLS connections will not fail preemptively)
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.low_mem_threshold1.
 
    See also low_mem_threshold2.
@@ -987,24 +978,24 @@ modparam("tls", "low_mem_threshold1", -1)
 
 9.25. low_mem_threshold2 (integer)
 
-   Sets  the  minimal  free  memory  from which TLS operations on already
+   Sets the minimal free memory from which TLS operations on already
    established TLS connections will start to fail preemptively. The value
    is expressed in KB.
 
-   The  default value depends on whether the openssl library used handles
-   well  low  memory  situations  (openssl bug #1491). As of this writing
-   this is not true for any openssl version (including 0.9.8e).
+   The default value depends on whether the openssl library used handles
+   well low memory situations (openssl bug #1491). As of this writing this
+   is not true for any openssl version (including 0.9.8e).
 
-   If  an  ill-behaved  openssl  version is detected, a very conservative
-   value  is  choosed,  which  depends  on the maximum possible number of
-   simultaneously  created  TLS  connections  (and  hence  on the process
+   If an ill-behaved openssl version is detected, a very conservative
+   value is choosed, which depends on the maximum possible number of
+   simultaneously created TLS connections (and hence on the process
    number).
 
    The following values have a special meaning:
      * -1 - use the default value
      * 0 - disable (TLS operations will not fail preemptively)
 
-   It  can  be  changed also at runtime, via the RPC interface and config
+   It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.low_mem_threshold2.
 
    See also low_mem_threshold1.
@@ -1019,16 +1010,16 @@ modparam("tls", "low_mem_threshold2", -1)
 
 9.26. tls_force_run (boolean)
 
-   If  enabled  Kamailio  will  start  even if some of the openssl sanity
+   If enabled Kamailio will start even if some of the openssl sanity
    checks fail (turn it on at your own risk).
 
-   Currently  failing  any  of the following sanity checks will not allow
+   Currently failing any of the following sanity checks will not allow
    Kamailio to start:
-     * the  version  of  the  library the TLS module was compiled with is
-       "too  different"  from  the  library used at runtime. The versions
-       should  have the same major, minor and fix level (e.g.: 0.9.8a and
-       0.9.8c are ok, but 0.9.8 and 0.9.9 are not)
-     * the  openssl  library  used  at  compile  time and the one used at
+     * the version of the library the TLS module was compiled with is "too
+       different" from the library used at runtime. The versions should
+       have the same major, minor and fix level (e.g.: 0.9.8a and 0.9.8c
+       are ok, but 0.9.8 and 0.9.9 are not)
+     * the openssl library used at compile time and the one used at
        runtime have different kerberos options
 
    By default tls_force_run is disabled.
@@ -1040,7 +1031,7 @@ modparam("tls", "tls_force_run", 11)
 
 9.27. session_cache (boolean)
 
-   If  enabled  Kamailio  will  do  caching  of  the  TLS  sessions data,
+   If enabled Kamailio will do caching of the TLS sessions data,
    generation a session_id and sending it back to client.
 
    By default TLS session caching is disabled (0).
@@ -1064,10 +1055,10 @@ modparam("tls", "session_id", "my-session-id-context")
 
 9.29. renegotiation (boolean)
 
-   If  enabled  Kamailio  will  allow  renegotiations  of  TLS connection
-   initiated  by  the  client.  This may expose to a security risk if the
-   client  is  not  a trusted peer and keeps renegotiating, consuming CPU
-   and bandwidth resources.
+   If enabled Kamailio will allow renegotiations of TLS connection
+   initiated by the client. This may expose to a security risk if the
+   client is not a trusted peer and keeps renegotiating, consuming CPU and
+   bandwidth resources.
 
    By default TLS renegotiation is disabled (0).
 
@@ -1078,22 +1069,23 @@ modparam("tls", "renegotiation", 1)
 
 9.30. config (string)
 
-   Sets the name of the TLS specific config file.
+   Sets the name of the TLS specific config file or config directory.
 
-   If  set  the  TLS  module  will  load  a special config file, in which
-   different  TLS  parameters  can  be specified on a per role (server or
-   client)  and domain basis (for now only IPs). The corresponding module
-   parameters will be ignored.
+   If set the TLS module will load a special config file or config files
+   from config directory, in which different TLS parameters can be
+   specified on a per role (server or client) and domain basis (for now
+   only IPs). The corresponding module parameters will be ignored.
 
-   If  the  file  name starts with a '.' the path will be relative to the
-   working  directory (at runtime). If it starts with a '/' it will be an
-   absolute  path  and  if  it starts with anything else the path will be
-   relative  to  the  main  config  file directory (e.g.: for kamailio -f
-   /etc/kamailio/kamailio.cfg it will be relative to /etc/kamailio/).
+   If the file or directory name starts with a '.' the path will be
+   relative to the working directory (at runtime). If it starts with a '/'
+   it will be an absolute path and if it starts with anything else the
+   path will be relative to the main config file directory (e.g.: for
+   kamailio -f /etc/kamailio/kamailio.cfg it will be relative to
+   /etc/kamailio/).
 
    By default no config file is specified.
 
-   The  following  parameters  can  be  set  in the config file, for each
+   The following parameters can be set in the config file, for each
    domain:
      * tls_method
      * verify_certificate
@@ -1105,14 +1097,14 @@ modparam("tls", "renegotiation", 1)
      * crl
      * cipher_list
 
-   All  the  parameters  that  take  filenames as values will be resolved
-   using  the  same rules as for the tls config filename itself: starting
-   with  a  '.'  means  relative to the working directory, a '/' means an
-   absolute  path  and  anything else a path relative to the directory of
-   the current Kamailio main config file.
+   All the parameters that take filenames as values will be resolved using
+   the same rules as for the tls config filename itself: starting with a
+   '.' means relative to the working directory, a '/' means an absolute
+   path and anything else a path relative to the directory of the current
+   Kamailio main config file.
 
    Kamailio acts as a server when it accepts a connection and as a client
-   when  it  initiates  a  new  connection  by  itself  (it  connects  to
+   when it initiates a new connection by itself (it connects to
    something).
 
    Example 1.39. Short config file
@@ -1139,7 +1131,7 @@ certificate = local_cert.pem
 verify_depth = 3
 ca_list = local_ca.pem
 
-   For  a  more  complete  example check the tls.cfg distributed with the
+   For a more complete example check the tls.cfg distributed with the
    Kamailio source (kamailio/modules/tls/tls.cfg).
 
    Example 1.40. Set config parameter
@@ -1147,7 +1139,7 @@ ca_list = local_ca.pem
 modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
 ...
 
-   It  can  be changed also at runtime. The new config will not be loaded
+   It can be changed also at runtime. The new config will not be loaded
    immediately, but after the first tls.reload RPC call.
 
    Example 1.41. Change and reload tls config at runtime
@@ -1160,8 +1152,8 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
 
 10.1. is_peer_verified()
 
-   Returns  true  if  the connection on which the message was received is
-   TLS , the peer presented an X509 certificate and the certificate chain
+   Returns true if the connection on which the message was received is TLS
+   , the peer presented an X509 certificate and the certificate chain
    verified ok. It can be used only in a request route.
 
    Example 1.42. is_peer_verified usage
@@ -1179,7 +1171,7 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
 
 11.1. tls.info
 
-   List  internal information related to the TLS module in a short list -
+   List internal information related to the TLS module in a short list -
    max connections, opened connections and the write queue size.
 
    Parameters:
@@ -1201,26 +1193,26 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
 
 11.4. tls.reload
 
-   Reload   the   external  TLS  configuration  file.  (Does  not  reload
-   modparam() parameters)
+   Reload the external TLS configuration file. (Does not reload modparam()
+   parameters)
 
    Parameters:
      * None.
 
 12. History
 
-   This  module  was  put together by Jan Janak <[email protected]> from code
+   This module was put together by Jan Janak <[email protected]> from code
    based on the experimental tls core addon
-   (http://cvs.berlios.de/cgi-bin/viewcvs.cgi/ser/experimental/tls/),
-   code  originally  written  by  Peter Griffiths and later maintained by
-   Cesc  Santasusana  and  from  an  iptelorg  tls code addon, written by
-   Andrei Pelinescu-Onciul <[email protected]>. Jan also added support for
-   multiple  domains,  a  tls specific config, config reloading and a tls
+   (http://cvs.berlios.de/cgi-bin/viewcvs.cgi/ser/experimental/tls/), code
+   originally written by Peter Griffiths and later maintained by Cesc
+   Santasusana and from an iptelorg tls code addon, written by Andrei
+   Pelinescu-Onciul <[email protected]>. Jan also added support for
+   multiple domains, a tls specific config, config reloading and a tls
    specific select framework.
 
-   For  Kamailio  3.1  most  of  the  TLS  specific  code  was completely
-   re-written  to  add  support for asynchronous TLS and fix several long
+   For Kamailio 3.1 most of the TLS specific code was completely
+   re-written to add support for asynchronous TLS and fix several long
    standing bugs.
 
-   The   code   is   currently   maintained  by  Andrei  Pelinescu-Onciul
+   The code is currently maintained by Andrei Pelinescu-Onciul
    <[email protected]>.

+ 3 - 3
modules/tls/doc/params.xml

@@ -915,16 +915,16 @@ modparam("tls", "renegotiation", 1)
 	<section id="tls.p.config">
 	<title><varname>config</varname> (string)</title>
 	<para>
-		Sets the name of the TLS specific config file.
+		Sets the name of the TLS specific config file or config directory.
 	</para>
 	<para>
-		If set the TLS module will load a special config file, in which
+		If set the TLS module will load a special config file or config files from config directory, in which
 		different TLS parameters can be specified on a per role (server or
 		client) and domain basis (for now only IPs). The corresponding module
 		parameters will be ignored.
 	</para>
 	<para>
-		If the file name starts with a '.' the path will be relative to the
+		If the file or directory name starts with a '.' the path will be relative to the
 		working directory (<emphasis>at runtime</emphasis>). If it starts
 		with a '/' it will be an absolute path and if it starts with anything
 		else the path will be relative to the main config file directory

+ 98 - 17
modules/tls/tls_config.c

@@ -45,6 +45,10 @@
 #include "../../trim.h"
 #include "../../ut.h"
 #include "../../cfg/cfg.h"
+#include "../../stats.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
 
 static tls_domains_cfg_t* cfg = NULL;
 static tls_domain_t* domain = NULL;
@@ -336,29 +340,106 @@ static int parse_domain(void* param, cfg_parser_t* st, unsigned int flags)
  */
 tls_domains_cfg_t* tls_load_config(str* filename)
 {
-	cfg_parser_t* parser;
-	str empty;
-
-	parser = NULL;
-	if ((cfg = tls_new_cfg()) == NULL) goto error;
-
-	empty.s = 0;
-	empty.len = 0;
-	if ((parser = cfg_parser_init(&empty, filename)) == NULL) {
-		ERR("tls: Error while initializing configuration file parser.\n");
+    cfg_parser_t* parser;
+    str empty;
+    struct stat file_status;
+    char tmp_name[13] = "configXXXXXX";
+    str filename_str;
+    DIR *dir;
+    struct dirent *ent;
+    int out_fd, in_fd, filename_is_directory;
+    char *file_path, ch;
+
+    parser = NULL;
+    memset(&file_status, 0, sizeof(struct stat));
+    dir = (DIR *)NULL;
+    in_fd = out_fd = filename_is_directory = 0;
+    file_path = (char *)0;
+
+    if ((cfg = tls_new_cfg()) == NULL) goto error;
+
+    if (stat(filename->s, &file_status) != 0) {
+	LOG(L_ERR, "cannot stat config file %s\n", filename->s);
+	goto error;
+    }
+    if (S_ISDIR(file_status.st_mode)) {
+	filename_is_directory = 1;
+	dir = opendir(filename->s);
+	if (dir == NULL) {
+	    LOG(L_ERR, "cannot open directory file %s\n", filename->s);
+	    goto error;
+	}
+	out_fd = mkstemp(&(tmp_name[0]));
+	if (out_fd == -1) {
+	    LOG(L_ERR, "cannot make tmp file %s\n", &(tmp_name[0]));
+	    goto error;
+	}
+	while ((ent = readdir(dir)) != NULL) {
+	    file_path = pkg_malloc(filename->len + 1 + 256);
+	    memcpy(file_path, filename->s, filename->len);
+	    file_path[filename->len] = '/';
+	    strcpy(file_path + filename->len + 1, ent->d_name);
+	    if (stat(file_path, &file_status) != 0) {
+		LOG(L_ERR, "cannot get status of config file %s\n",
+		    file_path);
 		goto error;
+	    }
+	    if (S_ISREG(file_status.st_mode)) {
+		in_fd = open(file_path, O_RDONLY);
+		if (in_fd == -1) {
+		    LOG(L_ERR, "cannot open config file %s\n",
+			file_path);
+		    goto error;
+		}
+		pkg_free(file_path);
+		while (read(in_fd, &ch, 1)) {
+		    write(out_fd, &ch, 1);
+		}
+		close(in_fd);
+		in_fd = 0;
+		ch = '\n';
+		write(out_fd, &ch, 1);
+	    }
 	}
+	closedir(dir);
+	close(out_fd);
+	dir = (DIR *)NULL;
+	out_fd = 0;
+    }
 
-	cfg_section_parser(parser, parse_domain, NULL);
+    empty.s = 0;
+    empty.len = 0;
+    if (filename_is_directory) {
+	filename_str.s = &(tmp_name[0]);
+	filename_str.len = strlen(&(tmp_name[0]));
+	if ((parser = cfg_parser_init(&empty, &filename_str)) == NULL) {
+	    ERR("tls: Error while initializing configuration file parser.\n");
+	    unlink(&(tmp_name[0]));
+	    goto error;
+	}
+	unlink(&(tmp_name[0]));
+    } else {
+	if ((parser = cfg_parser_init(&empty, filename)) == NULL) {
+	    ERR("tls: Error while initializing configuration file parser.\n");
+	    goto error;
+	}	
+    }
 
-	if (sr_cfg_parse(parser)) goto error;
-	cfg_parser_close(parser);
-	return cfg;
+    cfg_section_parser(parser, parse_domain, NULL);
+    if (sr_cfg_parse(parser)) goto error;
+    cfg_parser_close(parser);
+    return cfg;
 
  error:
-	if (parser) cfg_parser_close(parser);
-	if (cfg) tls_free_cfg(cfg);
-	return 0;
+    if (dir) closedir(dir);
+    if (out_fd > 0) {
+	close(out_fd);
+	unlink(&(tmp_name[0]));
+    }
+    if (file_path) pkg_free(file_path);
+    if (parser) cfg_parser_close(parser);
+    if (cfg) tls_free_cfg(cfg);
+    return 0;
 }
 
 

+ 1 - 0
resolve.c

@@ -1679,6 +1679,7 @@ struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto)
 #ifdef USE_NAPTR
 	if (cfg_get(core, core_cfg, dns_try_naptr))
 		res = naptr_sip_resolvehost(name, port, proto);
+	else
 #endif
 	res = srv_sip_resolvehost(name, 0, port, proto, 0, 0);
 	if( unlikely(!res) ){