/* Adds a new separate partition and loads all rules from database in shm */ dp_connection_list_p dp_add_connection(dp_head_p head) { dp_connection_list_t *el; if ((el = dp_get_connection(&head->partition)) != NULL){ return el; } el = shm_malloc(sizeof(dp_connection_list_t)); if (!el) { LM_ERR("No more shm mem\n"); return NULL; } memset(el, 0, sizeof(dp_connection_list_t)); /* create & init lock */ if((el->ref_lock = lock_init_rw()) == NULL) { LM_ERR("Failed to init lock\n"); shm_free(el); return NULL; } /*Set table name*/ el->table_name = head->dp_table_name; /*Set partition*/ el->partition = head->partition; /*Set db_url*/ el->db_url = head->dp_db_url; el->dp_db_handle = pkg_malloc(sizeof(db_con_t*)); if (!el->dp_db_handle) { LM_ERR("No more shm mem\n"); return NULL; } *el->dp_db_handle = 0; /* *el->dp_db_handle is set to null at the end of test_db; * no need to do it again here */ if (test_db(el) != 0) { LM_ERR("Unable to test db\n"); shm_free(el); return NULL; } el->next = dp_conns; dp_conns = el; LM_DBG("Added dialplan partition [%.*s] table [%.*s].\n", head->partition.len, head->partition.s, head->dp_table_name.len, head->dp_table_name.s); return el; }
static struct mi_root * mi_show_partition(struct mi_root *cmd_tree, void *param) { struct mi_node *node = NULL; struct mi_root *rpl_tree = NULL; struct mi_node* root= NULL; struct mi_attr* attr; dp_connection_list_t *el; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==NULL) return NULL; if (cmd_tree) node = cmd_tree->node.kids; if (node == NULL) { el = dp_get_connections(); root = &rpl_tree->node; while (el) { node = add_mi_node_child(root, 0, "Partition", 9, el->partition.s, el->partition.len); if( node == NULL) goto error; attr = add_mi_attr(node, 0, "table", 5, el->table_name.s, el->table_name.len); if(attr == NULL) goto error; db_get_url(&el->db_url); if(database_url.len == 0) goto error; attr = add_mi_attr(node, MI_DUP_VALUE, "db_url", 6, database_url.s, database_url.len); if(attr == NULL) goto error; el = el->next; } } else { el = dp_get_connection(&node->value); if (!el) goto error; root = &rpl_tree->node; node = add_mi_node_child(root, 0, "Partition", 9, el->partition.s, el->partition.len); if( node == NULL) goto error; attr = add_mi_attr(node, 0, "table", 5, el->table_name.s, el->table_name.len); if(attr == NULL) goto error; db_get_url(&el->db_url); if(database_url.len == 0) goto error; attr = add_mi_attr(node, MI_DUP_VALUE, "db_url", 6, database_url.s, database_url.len); if(attr == NULL) goto error; } return rpl_tree; error: if(rpl_tree) free_mi_tree(rpl_tree); return NULL; }
static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree, void *param) { struct mi_node *node = NULL; struct mi_root *rpl_tree = NULL; dp_connection_list_t *el; if (cmd_tree) node = cmd_tree->node.kids; if (node == NULL) { /* Reload rules from all partitions */ if(dp_load_all_db() != 0){ LM_ERR("failed to reload database\n"); return 0; } } else if (node->value.s == NULL || node->value.len == 0) { return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); } else { el = dp_get_connection(&node->value); if (!el) return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); /* Reload rules from specified partition */ LM_DBG("Reloading rules from table %.*s\n", node->value.len, node->value.s); if(dp_load_db(el) != 0){ LM_ERR("failed to reload database data\n"); return 0; } } rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) return 0; return rpl_tree; }
/* first param: DPID: type: INT, AVP, SVAR * second param: SRC/DST type: RURI, RURI_USERNAME, AVP, SVAR * default value for the second param: $ru.user/$ru.user */ static int dp_trans_fixup(void ** param, int param_no){ int dpid; dp_param_p dp_par= NULL; char *p, *s = NULL; str lstr, partition_name; dp_connection_list_t *list = NULL; if (param_no < 1 || param_no > 3) return 0; p = (char*)*param; if(!p || (*p == '\0')){ LM_DBG("null param %i\n", param_no); return E_CFG; } dp_par = (dp_param_p)pkg_malloc(sizeof(dp_param_t)); if(dp_par == NULL){ LM_ERR("no more pkg memory\n"); return E_OUT_OF_MEM; } memset(dp_par, 0, sizeof(dp_param_t)); switch (param_no) { case 1: p = parse_dp_command(p, -1, &partition_name); if (p == NULL) { LM_ERR("Invalid dp command\n"); return E_CFG; } if (!partition_name.s && !partition_name.len) { partition_name.s = DEFAULT_PARTITION; partition_name.len = sizeof(DEFAULT_PARTITION) - 1; } if (*partition_name.s != PV_MARKER) { list = dp_get_connection(&partition_name); if(!list){ LM_ERR("Partition with name [%.*s] is not defined\n", partition_name.len, partition_name.s ); return -1; } dp_par->type = DP_VAL_STR; } else { dp_par->type = DP_VAL_SPEC; } if (*p != PV_MARKER) { lstr.s = p; lstr.len = strlen(p); if(str2sint(&lstr, &dpid) != 0) { LM_ERR("bad number <%s>\n",(char *)(*param)); pkg_free(dp_par); return E_CFG; } if(dp_par->type == DP_VAL_SPEC){ /*int dpid and pv partition_name*/ dp_par->type = DP_VAL_INT; dp_par->v.pv_id.id = dpid; if( !pv_parse_spec( &partition_name, &dp_par->v.pv_id.partition)) goto error; } else { /*DP_VAL_STR remains DP_VAL_STR ( int dpid and str partition_name)*/ dp_par->v.id = dpid; } } else { if (dp_par->type == DP_VAL_STR) { /*pv dpid and str partition_name*/ dp_par->type = DP_VAL_STR_SPEC; } else { /*DP_VAL_SPEC remains DP_VAL_SPEC ( pv dpid and pv partition_name) */ if( !pv_parse_spec( &partition_name, &dp_par->v.sp[1])) goto error; } lstr.s = p; lstr.len = strlen(p); if (pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL) goto error; verify_par_type(dp_par->v.sp[0]); } dp_par->hash = list; break; case 2: if( ((s = strchr(p, '/')) == 0) ||( *(s+1)=='\0')) goto error; *s = '\0'; s++; lstr.s = p; lstr.len = strlen(p); if(pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL) goto error; verify_par_type(dp_par->v.sp[0]); lstr.s = s; lstr.len = strlen(s); if (pv_parse_spec( &lstr, &dp_par->v.sp[1] )==NULL) goto error; verify_par_type(dp_par->v.sp[1]); if (dp_par->v.sp[1].setf==NULL) { LM_ERR("the output PV is read-only!!\n"); return E_CFG; } dp_par->type = DP_VAL_SPEC; break; case 3: return fixup_pvar(param); } *param = (void *)dp_par; return 0; error: LM_ERR("failed to parse param %i\n", param_no); return E_INVALID_PARAMS; }
static int dp_translate_f(struct sip_msg *msg, char *str1, char *str2, char *attr_spec) { int dpid; str input, output; dpl_id_p idp; dp_param_p id_par, repl_par; str attrs, *attrs_par; dp_connection_list_p connection; pv_value_t pval; str partition_name; if (!msg) return -1; /* verify first param's value */ id_par = (dp_param_p) str1; if (dp_get_ivalue(msg, id_par, &dpid) != 0){ LM_ERR("no dpid value\n"); return -1; } switch( id_par->type ) { case DP_VAL_INT : if (dp_get_svalue(msg, id_par->v.pv_id.partition, &partition_name)) { LM_ERR("invalid partition\n"); return -1; } goto GET_CONN; case DP_VAL_SPEC : if (dp_get_svalue(msg, id_par->v.sp[1], &partition_name)) { LM_ERR("invalid partition\n"); return -1; } GET_CONN: if (!(id_par->hash = dp_get_connection(&partition_name))) { LM_ERR("invalid partition\n"); return -1; } break; default : break; } LM_DBG("dpid is %i partition is %.*s\n", dpid, id_par->hash->partition.len, id_par->hash->partition.s); repl_par = (str2!=NULL) ? ((dp_param_p)str2) : default_par2; if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){ LM_ERR("invalid param 2\n"); return -1; } LM_DBG("input is %.*s\n", input.len, input.s); connection = id_par->hash; /* ref the data for reading */ lock_start_read( connection->ref_lock ); if ((idp = select_dpid(connection, dpid, connection->crt_index)) == 0) { LM_DBG("no information available for dpid %i\n", dpid); goto error; } LM_DBG("Checking with dpid %i\n", idp->dp_id); attrs_par = attr_spec ? &attrs : NULL; if (translate(msg, input, &output, idp, attrs_par) != 0) { LM_DBG("could not translate %.*s " "with dpid %i\n", input.len, input.s, idp->dp_id); goto error; } LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s, idp->dp_id, output.len, output.s); /* set the output */ if (dp_update(msg, &repl_par->v.sp[0], &repl_par->v.sp[1], &output) != 0) { LM_ERR("cannot set the output\n"); goto error; } /* we are done reading -> unref the data */ lock_stop_read( connection->ref_lock ); if (attr_spec) { pval.flags = PV_VAL_STR; pval.rs = attrs; if (pv_set_value(msg, (pv_spec_p)attr_spec, 0, &pval) != 0) { LM_ERR("failed to set value '%.*s' for the attr pvar!\n", attrs.len, attrs.s); goto error; } } return 1; error: /* we are done reading -> unref the data */ lock_stop_read( connection->ref_lock ); return -1; }
static struct mi_root * mi_translate(struct mi_root *cmd, void *param) { struct mi_root* rpl= NULL; struct mi_node* root, *node; char *p; dpl_id_p idp; str dpid_str, partition_str; str input; int dpid; str attrs; str output= {0, 0}; dp_connection_list_p connection = NULL; node = cmd->node.kids; if(node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); /* Get the id parameter */ dpid_str = node->value; if(dpid_str.s == NULL || dpid_str.len== 0) { LM_ERR( "empty idp parameter\n"); return init_mi_tree(404, "Empty id parameter", 18); } p = parse_dp_command(dpid_str.s, dpid_str.len, &partition_str); if (p == NULL) { LM_ERR("Invalid dp command\n"); return init_mi_tree(404, "Invalid dp command", 18); } if (partition_str.s == NULL || partition_str.len == 0) { partition_str.s = DEFAULT_PARTITION; partition_str.len = sizeof(DEFAULT_PARTITION) - 1; } connection = dp_get_connection(&partition_str); dpid_str.len -= (p - dpid_str.s); dpid_str.s = p; if (!connection) { LM_ERR("Unable to get connection\n"); return init_mi_tree(400, "Wrong db connection parameter", 24); } if(str2sint(&dpid_str, &dpid) != 0) { LM_ERR("Wrong id parameter - should be an integer\n"); return init_mi_tree(404, "Wrong id parameter", 18); } node = node->next; if(node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if(node->next!= NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); input = node->value; if(input.s == NULL || input.len== 0) { LM_ERR( "empty input parameter\n"); return init_mi_tree(404, "Empty input parameter", 21); } /* ref the data for reading */ lock_start_read( connection->ref_lock ); if ((idp = select_dpid(connection, dpid, connection->crt_index)) ==0 ){ LM_ERR("no information available for dpid %i\n", dpid); lock_stop_read( connection->ref_lock ); return init_mi_tree(404, "No information available for dpid", 33); } if (translate(NULL, input, &output, idp, &attrs)!=0){ LM_DBG("could not translate %.*s with dpid %i\n", input.len, input.s, idp->dp_id); lock_stop_read( connection->ref_lock ); return init_mi_tree(404, "No translation", 14); } /* we are done reading -> unref the data */ lock_stop_read( connection->ref_lock ); LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s, idp->dp_id, output.len, output.s); rpl = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl==0) goto error; root= &rpl->node; node = add_mi_node_child(root, 0, "Output", 6, output.s, output.len ); if( node == NULL) goto error; node = add_mi_node_child(root, 0, "ATTRIBUTES", 10, attrs.s, attrs.len); if( node == NULL) goto error; return rpl; error: if(rpl) free_mi_tree(rpl); return 0; }
/* Adds a new separate partition and loads all rules from database in shm */ dp_connection_list_p dp_add_connection(dp_head_p head) { dp_connection_list_t *el; if ((el = dp_get_connection(&head->partition)) != NULL){ return el; } int all_size = sizeof(dp_connection_list_t) +head->dp_table_name.len + head->partition.len + head->dp_db_url.len; el = shm_malloc(all_size); if(!el) LM_ERR("No more shm\n"); if (!el) { LM_ERR("No more shm mem\n"); return NULL; } /* create & init lock */ if((el->ref_lock = lock_init_rw()) == NULL) { LM_ERR("Failed to init lock\n"); shm_free(el); return NULL; } /*Set table name*/ el->table_name.s = (char*)el + sizeof(*el); el->table_name.len = head->dp_table_name.len; memcpy(el->table_name.s, head->dp_table_name.s, head->dp_table_name.len); /*Set partition*/ el->partition.s = el->table_name.s + el->table_name.len; el->partition.len = head->partition.len; memcpy(el->partition.s, head->partition.s, head->partition.len); /*Set db_url*/ el->db_url.s = el->partition.s + el->partition.len; el->db_url.len = head->dp_db_url.len; memcpy(el->db_url.s, head->dp_db_url.s, head->dp_db_url.len); el->dp_db_handle = pkg_malloc(sizeof(db_con_t*)); if (!el->dp_db_handle) { LM_ERR("No more shm mem\n"); return NULL; } *el->dp_db_handle = 0; if (test_db(el) != 0) { LM_ERR("Unable to test db\n"); shm_free(el); return NULL; } *el->dp_db_handle = 0; el->next = dp_conns; dp_conns = el; LM_DBG("Added dialplan partition [%.*s] table [%.*s].\n", head->partition.len, head->partition.s, head->dp_table_name.len, head->dp_table_name.s); return el; }