implement RE matching against request URI

3.1_post-ngcp-2.5
Richard Fuchs 13 years ago
parent 2ae869ea18
commit f23a449aa3

@ -38,7 +38,9 @@ int rule_hash_table_insert(struct rule_info **hash_table,
unsigned int lcr_id, unsigned int rule_id, unsigned int lcr_id, unsigned int rule_id,
unsigned short prefix_len, char *prefix, unsigned short prefix_len, char *prefix,
unsigned short from_uri_len, char *from_uri, unsigned short from_uri_len, char *from_uri,
pcre *from_uri_re, unsigned short stopper) pcre *from_uri_re, unsigned short request_uri_len,
char *request_uri, pcre *request_uri_re,
unsigned short stopper)
{ {
struct rule_info *rule; struct rule_info *rule;
str prefix_str; str prefix_str;
@ -48,6 +50,7 @@ int rule_hash_table_insert(struct rule_info **hash_table,
if (rule == NULL) { if (rule == NULL) {
LM_ERR("Cannot allocate memory for rule hash table entry\n"); LM_ERR("Cannot allocate memory for rule hash table entry\n");
if (from_uri_re) shm_free(from_uri_re); if (from_uri_re) shm_free(from_uri_re);
if (request_uri_re) shm_free(request_uri_re);
return 0; return 0;
} }
memset(rule, 0, sizeof(struct rule_info)); memset(rule, 0, sizeof(struct rule_info));
@ -63,6 +66,12 @@ int rule_hash_table_insert(struct rule_info **hash_table,
(rule->from_uri)[from_uri_len] = '\0'; (rule->from_uri)[from_uri_len] = '\0';
rule->from_uri_re = from_uri_re; rule->from_uri_re = from_uri_re;
} }
rule->request_uri_len = request_uri_len;
if (request_uri_len) {
memcpy(rule->request_uri, request_uri, request_uri_len);
(rule->request_uri)[request_uri_len] = '\0';
rule->request_uri_re = request_uri_re;
}
rule->stopper = stopper; rule->stopper = stopper;
rule->targets = (struct target *)NULL; rule->targets = (struct target *)NULL;
@ -73,9 +82,9 @@ int rule_hash_table_insert(struct rule_info **hash_table,
rule->next = hash_table[hash_val]; rule->next = hash_table[hash_val];
hash_table[hash_val] = rule; hash_table[hash_val] = rule;
LM_DBG("inserted rule <%u>, prefix <%.*s>, from_uri <%.*s>, stopper <%u>, " LM_DBG("inserted rule <%u>, prefix <%.*s>, from_uri <%.*s>, request_uri <%.*s>, stopper <%u>, "
"into index <%u>\n", "into index <%u>\n",
rule_id, prefix_len, prefix, from_uri_len, from_uri, stopper, rule_id, prefix_len, prefix, from_uri_len, from_uri, request_uri_len, request_uri, stopper,
hash_val); hash_val);
return 1; return 1;
@ -177,6 +186,8 @@ void rule_hash_table_contents_free(struct rule_info **hash_table)
if (r->from_uri_re) { if (r->from_uri_re) {
shm_free(r->from_uri_re); shm_free(r->from_uri_re);
} }
if (r->request_uri_re)
shm_free(r->request_uri_re);
t = r->targets; t = r->targets;
while (t) { while (t) {
next_t = t->next; next_t = t->next;

@ -36,7 +36,9 @@ int rule_hash_table_insert(struct rule_info **hash_table,
unsigned int lcr_id, unsigned int rule_id, unsigned int lcr_id, unsigned int rule_id,
unsigned short prefix_len, char *prefix, unsigned short prefix_len, char *prefix,
unsigned short from_uri_len, char *from_uri, unsigned short from_uri_len, char *from_uri,
pcre *from_uri_re, unsigned short stopper); pcre *from_uri_re, unsigned short request_uri_len,
char *request_uri, pcre *request_uri_re,
unsigned short stopper);
int rule_hash_table_insert_target(struct rule_info **hash_table, int rule_hash_table_insert_target(struct rule_info **hash_table,
struct gw_info *gws, struct gw_info *gws,

@ -90,7 +90,7 @@ MODULE_VERSION
/* /*
* versions of database tables required by the module. * versions of database tables required by the module.
*/ */
#define LCR_RULE_TABLE_VERSION 1 #define LCR_RULE_TABLE_VERSION 2
#define LCR_RULE_TARGET_TABLE_VERSION 1 #define LCR_RULE_TARGET_TABLE_VERSION 1
#define LCR_GW_TABLE_VERSION 1 #define LCR_GW_TABLE_VERSION 1
@ -104,6 +104,7 @@ MODULE_VERSION
#define LCR_ID_COL "lcr_id" #define LCR_ID_COL "lcr_id"
#define PREFIX_COL "prefix" #define PREFIX_COL "prefix"
#define FROM_URI_COL "from_uri" #define FROM_URI_COL "from_uri"
#define REQUEST_URI_COL "request_uri"
#define STOPPER_COL "stopper" #define STOPPER_COL "stopper"
#define ENABLED_COL "enabled" #define ENABLED_COL "enabled"
#define RULE_ID_COL "rule_id" #define RULE_ID_COL "rule_id"
@ -164,6 +165,7 @@ static str id_col = str_init(ID_COL);
static str lcr_id_col = str_init(LCR_ID_COL); static str lcr_id_col = str_init(LCR_ID_COL);
static str prefix_col = str_init(PREFIX_COL); static str prefix_col = str_init(PREFIX_COL);
static str from_uri_col = str_init(FROM_URI_COL); static str from_uri_col = str_init(FROM_URI_COL);
static str request_uri_col = str_init(REQUEST_URI_COL);
static str stopper_col = str_init(STOPPER_COL); static str stopper_col = str_init(STOPPER_COL);
static str enabled_col = str_init(ENABLED_COL); static str enabled_col = str_init(ENABLED_COL);
static str rule_id_col = str_init(RULE_ID_COL); static str rule_id_col = str_init(RULE_ID_COL);
@ -294,6 +296,7 @@ static param_export_t params[] = {
{"id_column", STR_PARAM, &id_col.s}, {"id_column", STR_PARAM, &id_col.s},
{"prefix_column", STR_PARAM, &prefix_col.s}, {"prefix_column", STR_PARAM, &prefix_col.s},
{"from_uri_column", STR_PARAM, &from_uri_col.s}, {"from_uri_column", STR_PARAM, &from_uri_col.s},
{"request_uri_column", STR_PARAM, &request_uri_col.s},
{"stopper_column", STR_PARAM, &stopper_col.s}, {"stopper_column", STR_PARAM, &stopper_col.s},
{"enabled_column", STR_PARAM, &enabled_col.s}, {"enabled_column", STR_PARAM, &enabled_col.s},
{"rule_id_column", STR_PARAM, &rule_id_col.s}, {"rule_id_column", STR_PARAM, &rule_id_col.s},
@ -416,6 +419,7 @@ static int mod_init(void)
lcr_id_col.len = strlen(lcr_id_col.s); lcr_id_col.len = strlen(lcr_id_col.s);
prefix_col.len = strlen(prefix_col.s); prefix_col.len = strlen(prefix_col.s);
from_uri_col.len = strlen(from_uri_col.s); from_uri_col.len = strlen(from_uri_col.s);
request_uri_col.len = strlen(request_uri_col.s);
stopper_col.len = strlen(stopper_col.s); stopper_col.len = strlen(stopper_col.s);
enabled_col.len = strlen(enabled_col.s); enabled_col.len = strlen(enabled_col.s);
rule_id_col.len = strlen(rule_id_col.s); rule_id_col.len = strlen(rule_id_col.s);
@ -895,21 +899,21 @@ int reload_tables()
unsigned int i, n, lcr_id, rule_id, gw_id, gw_name_len, port, strip, unsigned int i, n, lcr_id, rule_id, gw_id, gw_name_len, port, strip,
tag_len, prefix_len, from_uri_len, stopper, enabled, flags, gw_cnt, tag_len, prefix_len, from_uri_len, stopper, enabled, flags, gw_cnt,
hostname_len, params_len, defunct_until, null_gw_ip_addr, priority, hostname_len, params_len, defunct_until, null_gw_ip_addr, priority,
weight, tmp; request_uri_len, weight, tmp;
struct in_addr in_addr; struct in_addr in_addr;
struct ip_addr ip_addr, *ip_p; struct ip_addr ip_addr, *ip_p;
uri_type scheme; uri_type scheme;
uri_transport transport; uri_transport transport;
char *gw_name, *hostname, *tag, *prefix, *from_uri, *params; char *gw_name, *hostname, *tag, *prefix, *from_uri, *params, *request_uri;
db1_res_t* res = NULL; db1_res_t* res = NULL;
db_row_t* row; db_row_t* row;
db_key_t key_cols[1]; db_key_t key_cols[1];
db_op_t op[1]; db_op_t op[1];
db_val_t vals[1]; db_val_t vals[1];
db_key_t gw_cols[12]; db_key_t gw_cols[12];
db_key_t rule_cols[5]; db_key_t rule_cols[6];
db_key_t target_cols[4]; db_key_t target_cols[4];
pcre *from_uri_re; pcre *from_uri_re, *request_uri_re;
struct gw_info *gws, *gw_pt_tmp; struct gw_info *gws, *gw_pt_tmp;
struct rule_info **rules, **rule_pt_tmp; struct rule_info **rules, **rule_pt_tmp;
str ip_string; str ip_string;
@ -924,6 +928,7 @@ int reload_tables()
rule_cols[2] = &from_uri_col; rule_cols[2] = &from_uri_col;
rule_cols[3] = &stopper_col; rule_cols[3] = &stopper_col;
rule_cols[4] = &enabled_col; rule_cols[4] = &enabled_col;
rule_cols[5] = &request_uri_col;
gw_cols[0] = &gw_name_col; gw_cols[0] = &gw_name_col;
gw_cols[1] = &ip_addr_col; gw_cols[1] = &ip_addr_col;
@ -943,7 +948,7 @@ int reload_tables()
target_cols[2] = &priority_col; target_cols[2] = &priority_col;
target_cols[3] = &weight_col; target_cols[3] = &weight_col;
from_uri_re = 0; request_uri_re = from_uri_re = 0;
if (lcr_db_init(&db_url) < 0) { if (lcr_db_init(&db_url) < 0) {
LM_ERR("unable to open database connection\n"); LM_ERR("unable to open database connection\n");
@ -964,7 +969,7 @@ int reload_tables()
VAL_INT(vals) = lcr_id; VAL_INT(vals) = lcr_id;
if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) { if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 5, 0, 0) if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, 0)
< 0) { < 0) {
LM_ERR("db query on lcr_rule table failed\n"); LM_ERR("db query on lcr_rule table failed\n");
goto err; goto err;
@ -974,7 +979,7 @@ int reload_tables()
goto err; goto err;
} }
} else { } else {
if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 5, 0, &res) if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, &res)
< 0) { < 0) {
LM_ERR("db query on lcr_rule table failed\n"); LM_ERR("db query on lcr_rule table failed\n");
goto err; goto err;
@ -982,13 +987,13 @@ int reload_tables()
} }
n = 0; n = 0;
from_uri_re = 0; request_uri_re = from_uri_re = 0;
do { do {
LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res)); LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res));
for (i = 0; i < RES_ROW_N(res); i++) { for (i = 0; i < RES_ROW_N(res); i++) {
from_uri_re = 0; request_uri_re = from_uri_re = 0;
row = RES_ROWS(res) + i; row = RES_ROWS(res) + i;
if ((VAL_NULL(ROW_VALUES(row)) == 1) || if ((VAL_NULL(ROW_VALUES(row)) == 1) ||
@ -1070,9 +1075,37 @@ int reload_tables()
from_uri_re = 0; from_uri_re = 0;
} }
if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {
request_uri_len = 0;
request_uri = 0;
} else {
if (VAL_TYPE(ROW_VALUES(row) + 5) != DB1_STRING) {
LM_ERR("lcr rule <%u> request_uri is not string\n",
rule_id);
goto err;
}
request_uri = (char *)VAL_STRING(ROW_VALUES(row) + 5);
request_uri_len = strlen(from_uri);
}
if (request_uri_len > MAX_URI_LEN) {
LM_ERR("lcr rule <%u> request_uri is too long\n", rule_id);
goto err;
}
if (request_uri_len > 0) {
request_uri_re = reg_ex_comp(request_uri);
if (request_uri_re == 0) {
LM_ERR("failed to compile lcr rule <%u> request_uri "
"<%s>\n", rule_id, request_uri);
goto err;
}
} else {
request_uri_re = 0;
}
if (!rule_hash_table_insert(rules, lcr_id, rule_id, prefix_len, if (!rule_hash_table_insert(rules, lcr_id, rule_id, prefix_len,
prefix, from_uri_len, from_uri, prefix, from_uri_len, from_uri,
from_uri_re, stopper) || from_uri_re, request_uri_len,
request_uri, request_uri_re, stopper) ||
!prefix_len_insert(rules, prefix_len)) { !prefix_len_insert(rules, prefix_len)) {
goto err; goto err;
} }
@ -1703,7 +1736,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id, static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id,
pv_spec_t* _from_uri) pv_spec_t* _from_uri)
{ {
str ruri_user, from_uri; str ruri_user, from_uri, *request_uri;
int i, j, lcr_id; int i, j, lcr_id;
unsigned int gw_index, now, dex; unsigned int gw_index, now, dex;
int_str val; int_str val;
@ -1749,6 +1782,7 @@ static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id,
return -1; return -1;
} }
ruri_user = _m->parsed_uri.user; ruri_user = _m->parsed_uri.user;
request_uri = GET_RURI(_m);
/* /*
* Find lcr entries that match based on prefix and from_uri and collect * Find lcr entries that match based on prefix and from_uri and collect
@ -1774,34 +1808,43 @@ static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id,
rule = rule_hash_table_lookup(rules, pl->prefix_len, ruri_user.s); rule = rule_hash_table_lookup(rules, pl->prefix_len, ruri_user.s);
while (rule) { while (rule) {
/* Match prefix */ /* Match prefix */
if ((rule->prefix_len == pl->prefix_len) && if ((rule->prefix_len != pl->prefix_len) ||
(strncmp(rule->prefix, ruri_user.s, pl->prefix_len) == 0)) { (strncmp(rule->prefix, ruri_user.s, pl->prefix_len)))
/* Match from uri */ goto next;
if ((rule->from_uri_len == 0) ||
(pcre_exec(rule->from_uri_re, NULL, from_uri.s, /* Match from uri */
from_uri.len, 0, 0, NULL, 0) >= 0)) { if ((rule->from_uri_len != 0) &&
/* Load gws associated with this rule */ (pcre_exec(rule->from_uri_re, NULL, from_uri.s,
t = rule->targets; from_uri.len, 0, 0, NULL, 0) < 0))
while (t) { goto next;
/* If this gw is defunct, skip it */
if (gws[t->gw_index].defunct_until > now) goto skip_gw; /* Match request uri */
matched_gws[gw_index].gw_index = t->gw_index; if ((rule->request_uri_len != 0) &&
matched_gws[gw_index].prefix_len = pl->prefix_len; (pcre_exec(rule->request_uri_re, NULL, request_uri->s,
matched_gws[gw_index].priority = t->priority; request_uri->len, 0, 0, NULL, 0) < 0))
matched_gws[gw_index].weight = t->weight * goto next;
(rand() >> 8);
matched_gws[gw_index].duplicate = 0; /* Load gws associated with this rule */
LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n", t = rule->targets;
gw_index, t->gw_index, pl->prefix_len, while (t) {
t->priority, matched_gws[gw_index].weight); /* If this gw is defunct, skip it */
gw_index++; if (gws[t->gw_index].defunct_until > now) goto skip_gw;
skip_gw: matched_gws[gw_index].gw_index = t->gw_index;
t = t->next; matched_gws[gw_index].prefix_len = pl->prefix_len;
} matched_gws[gw_index].priority = t->priority;
/* Do not look further if this matching rule was stopper */ matched_gws[gw_index].weight = t->weight *
if (rule->stopper == 1) goto done; (rand() >> 8);
} matched_gws[gw_index].duplicate = 0;
LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
gw_index, t->gw_index, pl->prefix_len,
t->priority, matched_gws[gw_index].weight);
gw_index++;
skip_gw:
t = t->next;
} }
/* Do not look further if this matching rule was stopper */
if (rule->stopper == 1) goto done;
next:
rule = rule->next; rule = rule->next;
} }
pl = pl->next; pl = pl->next;

@ -62,6 +62,9 @@ struct rule_info {
char from_uri[MAX_URI_LEN + 1]; char from_uri[MAX_URI_LEN + 1];
unsigned short from_uri_len; unsigned short from_uri_len;
pcre *from_uri_re; pcre *from_uri_re;
char request_uri[MAX_URI_LEN + 1];
unsigned short request_uri_len;
pcre *request_uri_re;
unsigned short stopper; unsigned short stopper;
unsigned int enabled; unsigned int enabled;
struct target *targets; struct target *targets;

Loading…
Cancel
Save