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
<varname>dr_number_routing</varname> - 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.");