diff --git a/modules/drouting/README b/modules/drouting/README
index 7306c957e14..3b9dc566022 100644
--- a/modules/drouting/README
+++ b/modules/drouting/README
@@ -872,7 +872,8 @@ modparam("drouting", "db_partitions_table", "partition_defs")
name and the groupId may be statical values or AVP
specifications. If no group is specified the function
will try to query the dr_group table for the given
- partition to get this information.
+ partition to get this information. If * (wildcard)
+ operator is used all partitions shall be checked.
* flags - Controls the behavior of the function. Possible
flags are:
+ W - Instead of using the destination (from the rule
@@ -1203,7 +1204,8 @@ if (goes_to_gw("my_partition", "1", , "$var(gw_attrs)")) {
marks "," are properly placed.
* partition (mandatory if use_partitions parameter is 1,
otherwise it will be omitted altogether) - Partition
- containing the destination/gw to be checked.
+ containing the destination/gw to be checked. If *(wildcard)
+ operator is used all partitions shall be checked.
* type (optional) - GW/destination type to be checked; when
omitting this parameter or specifying a negative value i.e.
"-1", matching will be done against all groups
diff --git a/modules/drouting/doc/drouting_admin.xml b/modules/drouting/doc/drouting_admin.xml
index e86e19451a7..66a99f8ee28 100644
--- a/modules/drouting/doc/drouting_admin.xml
+++ b/modules/drouting/doc/drouting_admin.xml
@@ -818,7 +818,7 @@ modparam("drouting", "persistent_state", 0)
If enabled, the module will not allow do run multiple dr_reload
MI commands in parallel (with overlapping) Any new reload will
- be rejected (and discarded) while an existing reload is in
+ be rejected (and discarded) while an existing reload is in
progress.
@@ -1117,6 +1117,7 @@ modparam("drouting", "db_partitions_table", "partition_defs")
parameter is 1 - both the partition name and the groupId may be statical
values or AVP specifications. If no group is specified the function will
try to query the dr_group table for the given partition to get this information.
+ If * (wildcard) operator is used all partitions shall be checked.
@@ -1648,7 +1649,8 @@ if (goes_to_gw("my_partition", "1", , "$var(gw_attrs)")) {
partition (mandatory if use_partitions
parameter is 1, otherwise it will be omitted altogether) - Partition
- containing the destination/gw to be checked.
+ containing the destination/gw to be checked. If *(wildcard)
+ operator is used all partitions shall be checked.
@@ -2094,7 +2096,7 @@ Partition:: part_test Date=Tue Aug 12 12:24:13 2014
dr_number_routing
- Gets the matched prefix along with the list of the gateways / carriers to which a number
+ Gets the matched prefix along with the list of the gateways / carriers to which a number
would be routed when using the do_routing function
diff --git a/modules/drouting/drouting.c b/modules/drouting/drouting.c
index 3d158f49e57..33f58a40e84 100644
--- a/modules/drouting/drouting.c
+++ b/modules/drouting/drouting.c
@@ -186,7 +186,7 @@ typedef struct dr_partition {
gparam_p part_name;
} v;
- enum dr_partition_type { DR_PTR_PART, DR_GPARAM_PART, DR_NO_PART } type;
+ enum dr_partition_type { DR_PTR_PART, DR_GPARAM_PART, DR_WILDCARD_PART, DR_NO_PART } type;
} dr_partition_t;
typedef struct dr_part_group {
@@ -2549,10 +2549,12 @@ static int do_routing(struct sip_msg* msg, dr_part_group_t * part_group,
str ruri;
str next_carrier_attrs = {NULL, 0};
str next_gw_attrs = {NULL, 0};
- int ret;
+ int ret, fret;
char tmp;
char *ruri_buf;
+ gparam_p tmp_gparam = NULL;
+
ret = -1;
ruri_buf = NULL;
wl_list = NULL;
@@ -2564,13 +2566,42 @@ static int do_routing(struct sip_msg* msg, dr_part_group_t * part_group,
LM_ERR("Partition name is mandatory for do_routing\n");
return -1;
}
+
if(part_group->dr_part->type == DR_GPARAM_PART) {
- if (to_partition(msg, part_group->dr_part, ¤t_partition)<0) {
+ if ((fret=to_partition(msg, part_group->dr_part, ¤t_partition))<0) {
return -1;
+ } else if (fret == 1) {
+ tmp_gparam = part_group->dr_part->v.part_name;
+ part_group->dr_part->type = DR_WILDCARD_PART;
}
+
} else if(part_group->dr_part->type == DR_PTR_PART) {
current_partition = part_group->dr_part->v.part;
}
+
+
+ if (part_group->dr_part->type == DR_WILDCARD_PART) {
+ for (current_partition = head_db_start;
+ current_partition; current_partition = current_partition->next) {
+ part_group->dr_part->v.part = current_partition;
+ part_group->dr_part->type = DR_PTR_PART;
+
+ ret=do_routing( msg, part_group, flags, whitelist);
+ if (ret > 0)
+ break;
+ }
+
+ /* restore to initial state */
+ if (tmp_gparam) {
+ part_group->dr_part->type = DR_GPARAM_PART;
+ } else {
+ memset(part_group->dr_part, 0, sizeof(dr_partition_t));
+ part_group->dr_part->type = DR_WILDCARD_PART;
+ }
+
+ /* ret must be less than 0 here if nothing found */
+ return ret;
+ }
} else {
if(part_group->dr_part->type == DR_PTR_PART) {
current_partition = part_group->dr_part->v.part;
@@ -3390,6 +3421,12 @@ int fxup_get_partition(void ** part_name, dr_partition_t ** x) {
if( ((gparam_p)(*part_name))->type==GPARAM_TYPE_STR ) { /* was
defined statically */
str_part_name = (( (gparam_p) (*part_name))->v.sval);
+ str_trim_spaces_lr(str_part_name);
+ if (str_part_name.len == 1 && str_part_name.s[0] == '*') {
+ (*x)->type = DR_WILDCARD_PART;
+ return 0;
+ }
+
if((part = get_partition(&str_part_name)) == NULL) {
LM_CRIT("Partition <%.*s> was not found.\n", str_part_name.len,
str_part_name.s);
@@ -3413,6 +3450,14 @@ static int to_partition(struct sip_msg* msg, dr_partition_t *part,
LM_ERR("Failed to parse avp/pve.\n");
return -1;
}
+
+ str_trim_spaces_lr(part_name);
+
+ /* check for wildcard operator */
+ if ( part_name.len == 1 && part_name.s[0] == '*') {
+ return 1;
+ }
+
if((*current_partition = get_partition(&part_name)) == NULL) {
LM_ERR("Partition <%.*s> was not found.\n", part_name.len, part_name.s);
return -1;
@@ -3923,20 +3968,37 @@ static int gw_matches_ip(pgw_t *pgwa, struct ip_addr *ip, unsigned short port)
static int _is_dr_gw(struct sip_msg* msg, char * part,
char * flags_pv, int type, struct ip_addr *ip,
unsigned int port) {
+
+ int ret=-1;
+
struct head_db * it;
if(use_partitions) {
if(part == NULL || ((dr_partition_t*)part)->type == DR_NO_PART) {
LM_ERR("Partition is mandatory!\n");
return -1;
- } else if(((dr_partition_t*)part)->type == DR_PTR_PART) {
+ }
+
+ if(((dr_partition_t*)part)->type == DR_PTR_PART) {
return _is_dr_gw_w_part(msg, (char*)((dr_partition_t*)part)->v.part,
flags_pv, type, ip, port);
} else if(((dr_partition_t*)part)->type == DR_GPARAM_PART) {
- if(to_partition(msg, (dr_partition_t*)part, &it) < 0) {
+ if((ret=to_partition(msg, (dr_partition_t*)part, &it) < 0)) {
return -1;
+ } else if (ret == 0) {
+ return _is_dr_gw_w_part(msg, (char*)it,flags_pv, type, ip, port);
}
- return _is_dr_gw_w_part(msg, (char*)it,flags_pv, type, ip, port);
}
+
+ /* if we got here we have the wildcard operator */
+ for (it = head_db_start; it; it = it->next) {
+ ret = _is_dr_gw_w_part(msg, (char *)it, flags_pv, type, ip, port);
+ if (ret > 0)
+ return ret;
+ }
+
+ return ret;
+
+
} else {
if( head_db_start == NULL ) {
LM_ERR("Error loading config.");