00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdio.h>
00040 #include <unistd.h>
00041 #include <stdlib.h>
00042
00043 #include "../../db/db_op.h"
00044 #include "../../sr_module.h"
00045 #include "../../db/db.h"
00046 #include "../../mem/shm_mem.h"
00047 #include "../../mem/mem.h"
00048 #include "../../dprint.h"
00049 #include "../../parser/parse_uri.h"
00050 #include "../../timer.h"
00051 #include "../../ut.h"
00052 #include "../../locking.h"
00053 #include "../../action.h"
00054 #include "../../mod_fix.h"
00055 #include "../../parser/parse_from.h"
00056
00057 #include "pdtree.h"
00058
00059 MODULE_VERSION
00060
00061
00062 #define NR_KEYS 3
00063
00064 int pdt_fetch_rows = 1000;
00065
00066
00067 pdt_tree_t **_ptree = NULL;
00068
00069
00070 static db_con_t *db_con = NULL;
00071 static db_func_t pdt_dbf;
00072
00073
00074
00075 static str db_url = str_init(DEFAULT_DB_URL);
00076 static str db_table = str_init("pdt");
00077 static str sdomain_column = str_init("sdomain");
00078 static str prefix_column = str_init("prefix");
00079 static str domain_column = str_init("domain");
00080 static int pdt_check_domain = 1;
00081
00082
00083 str prefix = {"", 0};
00084
00085 str pdt_char_list = {"0123456789", 10};
00086
00087
00088 static gen_lock_t *pdt_lock = 0;
00089 static volatile int pdt_tree_refcnt = 0;
00090 static volatile int pdt_reload_flag = 0;
00091
00092 static int w_prefix2domain(struct sip_msg* msg, char* str1, char* str2);
00093 static int w_prefix2domain_1(struct sip_msg* msg, char* mode, char* str2);
00094 static int w_prefix2domain_2(struct sip_msg* msg, char* mode, char* sd_en);
00095 static int mod_init(void);
00096 static void mod_destroy(void);
00097 static int child_init(void);
00098 static int mod_child_init(int r);
00099 static int prefix2domain(struct sip_msg*, int mode, int sd_en);
00100
00101 static struct mi_root* pdt_mi_reload(struct mi_root*, void* param);
00102 static struct mi_root* pdt_mi_add(struct mi_root*, void* param);
00103 static struct mi_root* pdt_mi_delete(struct mi_root*, void* param);
00104 static struct mi_root* pdt_mi_list(struct mi_root*, void* param);
00105
00106 static int update_new_uri(struct sip_msg *msg, int plen, str *d, int mode);
00107 static int pdt_load_db();
00108
00109 static cmd_export_t cmds[]={
00110 {"prefix2domain", (cmd_function)w_prefix2domain, 0, 0,
00111 0, REQUEST_ROUTE|FAILURE_ROUTE},
00112 {"prefix2domain", (cmd_function)w_prefix2domain_1, 1, fixup_igp_null,
00113 0, REQUEST_ROUTE|FAILURE_ROUTE},
00114 {"prefix2domain", (cmd_function)w_prefix2domain_2, 2, fixup_igp_igp,
00115 0, REQUEST_ROUTE|FAILURE_ROUTE},
00116 {0, 0, 0, 0, 0, 0}
00117 };
00118
00119 static param_export_t params[]={
00120 {"db_url", STR_PARAM, &db_url.s},
00121 {"db_table", STR_PARAM, &db_table.s},
00122 {"sdomain_column", STR_PARAM, &sdomain_column.s},
00123 {"prefix_column", STR_PARAM, &prefix_column.s},
00124 {"domain_column", STR_PARAM, &domain_column.s},
00125 {"prefix", STR_PARAM, &prefix.s},
00126 {"char_list", STR_PARAM, &pdt_char_list.s},
00127 {"fetch_rows", INT_PARAM, &pdt_fetch_rows},
00128 {"check_domain", INT_PARAM, &pdt_check_domain},
00129 {0, 0, 0}
00130 };
00131
00132 static mi_export_t mi_cmds[] = {
00133 { "pdt_add", pdt_mi_add, 0, 0, child_init },
00134 { "pdt_reload", pdt_mi_reload, 0, 0, 0 },
00135 { "pdt_delete", pdt_mi_delete, 0, 0, 0 },
00136 { "pdt_list", pdt_mi_list, 0, 0, 0 },
00137 { 0, 0, 0, 0, 0}
00138 };
00139
00140
00141 struct module_exports exports = {
00142 "pdt",
00143 DEFAULT_DLFLAGS,
00144 cmds,
00145 params,
00146 0,
00147 mi_cmds,
00148 0,
00149 0,
00150 mod_init,
00151 0,
00152 mod_destroy,
00153 mod_child_init
00154 };
00155
00156
00157
00158
00159
00160
00161 static int mod_init(void)
00162 {
00163 db_url.len = strlen(db_url.s);
00164 db_table.len = strlen(db_table.s);
00165 sdomain_column.len = strlen(sdomain_column.s);
00166 prefix_column.len = strlen(prefix_column.s);
00167 domain_column.len = strlen(domain_column.s);
00168 prefix.len = strlen(prefix.s);
00169
00170 if(pdt_fetch_rows<=0)
00171 pdt_fetch_rows = 1000;
00172
00173 pdt_char_list.len = strlen(pdt_char_list.s);
00174 if(pdt_char_list.len<=0)
00175 {
00176 LM_ERR("invalid pdt char list\n");
00177 return -1;
00178 }
00179 LM_INFO("pdt_char_list=%s \n",pdt_char_list.s);
00180
00181
00182 if(db_bind_mod(&db_url, &pdt_dbf))
00183 {
00184 LM_ERR("database module not found\n");
00185 return -1;
00186 }
00187
00188 if (!DB_CAPABILITY(pdt_dbf, DB_CAP_ALL))
00189 {
00190 LM_ERR("database module does not "
00191 "implement all functions needed by the module\n");
00192 return -1;
00193 }
00194
00195
00196 db_con = pdt_dbf.init(&db_url);
00197 if(db_con==NULL)
00198 {
00199 LM_ERR("failed to connect to the database\n");
00200 return -1;
00201 }
00202
00203 if (pdt_dbf.use_table(db_con, &db_table) < 0)
00204 {
00205 LM_ERR("failed to use_table\n");
00206 goto error1;
00207 }
00208 LM_DBG("database connection opened successfully\n");
00209
00210 if ( (pdt_lock=lock_alloc())==0) {
00211 LM_CRIT("failed to alloc lock\n");
00212 goto error1;
00213 }
00214 if (lock_init(pdt_lock)==0 ) {
00215 LM_CRIT("failed to init lock\n");
00216 goto error1;
00217 }
00218
00219
00220 _ptree = (pdt_tree_t**)shm_malloc( sizeof(pdt_tree_t*) );
00221 if (_ptree==0) {
00222 LM_ERR("out of shm mem for pdtree\n");
00223 goto error1;
00224 }
00225 *_ptree=0;
00226
00227
00228 if(pdt_load_db()!=0)
00229 {
00230 LM_ERR("cannot load info from database\n");
00231 goto error1;
00232 }
00233
00234 pdt_dbf.close(db_con);
00235 db_con = 0;
00236
00237 #if 0
00238 pdt_print_tree(*_ptree);
00239 #endif
00240
00241
00242 return 0;
00243
00244 error1:
00245 if (pdt_lock)
00246 {
00247 lock_destroy( pdt_lock );
00248 lock_dealloc( pdt_lock );
00249 pdt_lock = 0;
00250 }
00251 if(_ptree!=0)
00252 shm_free(_ptree);
00253
00254 if(db_con!=NULL)
00255 {
00256 pdt_dbf.close(db_con);
00257 db_con = 0;
00258 }
00259 return -1;
00260 }
00261
00262
00263 static int child_init(void)
00264 {
00265 db_con = pdt_dbf.init(&db_url);
00266 if(db_con==NULL)
00267 {
00268 LM_ERR("failed to connect to database\n");
00269 return -1;
00270 }
00271
00272 if (pdt_dbf.use_table(db_con, &db_table) < 0)
00273 {
00274 LM_ERR("use_table failed\n");
00275 return -1;
00276 }
00277 return 0;
00278 }
00279
00280
00281
00282 static int mod_child_init(int r)
00283 {
00284 if ( child_init()!=0 )
00285 return -1;
00286
00287 LM_DBG("#%d: database connection opened successfully\n",r);
00288
00289 return 0;
00290 }
00291
00292
00293 static void mod_destroy(void)
00294 {
00295 LM_DBG("cleaning up\n");
00296 if (_ptree!=NULL)
00297 {
00298 if (*_ptree!=NULL)
00299 pdt_free_tree(*_ptree);
00300 shm_free(_ptree);
00301 }
00302 if (db_con!=NULL && pdt_dbf.close!=NULL)
00303 pdt_dbf.close(db_con);
00304
00305 if (pdt_lock)
00306 {
00307 lock_destroy( pdt_lock );
00308 lock_dealloc( pdt_lock );
00309 pdt_lock = 0;
00310 }
00311
00312 }
00313
00314
00315 static int w_prefix2domain(struct sip_msg* msg, char* str1, char* str2)
00316 {
00317 return prefix2domain(msg, 0, 0);
00318 }
00319
00320 static int w_prefix2domain_1(struct sip_msg* msg, char* mode, char* str2)
00321 {
00322 int m;
00323
00324 if(fixup_get_ivalue(msg, (gparam_p)mode, &m)!=0)
00325 {
00326 LM_ERR("no mode value\n");
00327 return -1;
00328 }
00329
00330 if(m!=1 && m!=2)
00331 m = 0;
00332
00333 return prefix2domain(msg, m, 0);
00334 }
00335
00336 static int w_prefix2domain_2(struct sip_msg* msg, char* mode, char* sdm)
00337 {
00338 int m, s;
00339
00340 if(fixup_get_ivalue(msg, (gparam_p)mode, &m)!=0)
00341 {
00342 LM_ERR("no mode value\n");
00343 return -1;
00344 }
00345
00346 if(m!=1 && m!=2)
00347 m = 0;
00348
00349 if(fixup_get_ivalue(msg, (gparam_p)sdm, &s)!=0)
00350 {
00351 LM_ERR("no multi-domain mode value\n");
00352 return -1;
00353 }
00354
00355 if(s!=1 && s!=2)
00356 s = 0;
00357
00358 return prefix2domain(msg, m, s);
00359 }
00360
00361
00362 static int prefix2domain(struct sip_msg* msg, int mode, int sd_en)
00363 {
00364 str *d, p, all={"*",1};
00365 int plen;
00366 struct sip_uri uri;
00367
00368 if(msg==NULL)
00369 {
00370 LM_ERR("received null msg\n");
00371 return -1;
00372 }
00373
00374
00375 if(msg->parsed_uri_ok==0)
00376 if(parse_sip_msg_uri(msg)<0)
00377 {
00378 LM_ERR("failed to parse the R-URI\n");
00379 return -1;
00380 }
00381
00382
00383 if (msg->parsed_uri.user.len<=0)
00384 {
00385 LM_DBG("user part of the message is empty\n");
00386 return -1;
00387 }
00388
00389 if(prefix.len>0)
00390 {
00391 if (msg->parsed_uri.user.len<=prefix.len)
00392 {
00393 LM_DBG("user part is less than prefix\n");
00394 return -1;
00395 }
00396 if(strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0)
00397 {
00398 LM_DBG("PSTN prefix did not matched\n");
00399 return -1;
00400 }
00401 }
00402
00403 if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len
00404 && strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0)
00405 {
00406 LM_DBG("PSTN prefix did not matched\n");
00407 return -1;
00408
00409 }
00410
00411 p.s = msg->parsed_uri.user.s + prefix.len;
00412 p.len = msg->parsed_uri.user.len - prefix.len;
00413
00414 again:
00415 lock_get( pdt_lock );
00416 if (pdt_reload_flag) {
00417 lock_release( pdt_lock );
00418 sleep_us(5);
00419 goto again;
00420 }
00421 pdt_tree_refcnt++;
00422 lock_release( pdt_lock );
00423
00424 if(sd_en==2)
00425 {
00426
00427 if(parse_from_header(msg)<0 || msg->from == NULL
00428 || get_from(msg)==NULL)
00429 {
00430 LM_ERR("cannot parse FROM header\n");
00431 goto error;
00432 }
00433
00434 memset(&uri, 0, sizeof(struct sip_uri));
00435 if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0)
00436 {
00437 LM_ERR("failed to parse From uri\n");
00438 goto error;
00439 }
00440
00441
00442 plen = 0;
00443 if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL)
00444 {
00445 plen = 0;
00446 if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL)
00447 {
00448 LM_INFO("no prefix found in [%.*s]\n", p.len, p.s);
00449 goto error;
00450 }
00451 }
00452 } else if(sd_en==1) {
00453
00454 if(parse_from_header(msg)<0 || msg->from == NULL
00455 || get_from(msg)==NULL)
00456 {
00457 LM_ERR("ERROR cannot parse FROM header\n");
00458 goto error;
00459 }
00460
00461 memset(&uri, 0, sizeof(struct sip_uri));
00462 if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0)
00463 {
00464 LM_ERR("failed to parse From uri\n");
00465 goto error;
00466 }
00467
00468
00469 plen = 0;
00470 if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL)
00471 {
00472 LM_INFO("no prefix found in [%.*s]\n", p.len, p.s);
00473 goto error;
00474 }
00475 } else {
00476
00477 plen = 0;
00478 if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL)
00479 {
00480 LM_INFO("no prefix found in [%.*s]\n", p.len, p.s);
00481 goto error;
00482 }
00483 }
00484
00485
00486 if(update_new_uri(msg, plen, d, mode)<0)
00487 {
00488 LM_ERR("new_uri cannot be updated\n");
00489 goto error;
00490 }
00491
00492 lock_get( pdt_lock );
00493 pdt_tree_refcnt--;
00494 lock_release( pdt_lock );
00495 return 1;
00496
00497 error:
00498 lock_get( pdt_lock );
00499 pdt_tree_refcnt--;
00500 lock_release( pdt_lock );
00501 return -1;
00502 }
00503
00504
00505 static int update_new_uri(struct sip_msg *msg, int plen, str *d, int mode)
00506 {
00507 struct action act;
00508 if(msg==NULL || d==NULL)
00509 {
00510 LM_ERR("bad parameters\n");
00511 return -1;
00512 }
00513
00514 if(mode==0 || (mode==1 && prefix.len>0))
00515 {
00516 act.type = STRIP_T;
00517 act.elem[0].type = NUMBER_ST;
00518 if(mode==0)
00519 act.elem[0].u.number = plen + prefix.len;
00520 else
00521 act.elem[0].u.number = prefix.len;
00522 act.next = 0;
00523
00524 if (do_action(&act, msg) < 0)
00525 {
00526 LM_ERR("failed to remove prefix\n");
00527 return -1;
00528 }
00529 }
00530
00531 act.type = SET_HOSTPORT_T;
00532 act.elem[0].type = STRING_ST;
00533 act.elem[0].u.string = d->s;
00534 act.next = 0;
00535
00536 if (do_action(&act, msg) < 0)
00537 {
00538 LM_ERR("failed to change domain\n");
00539 return -1;
00540 }
00541
00542 LM_DBG("len=%d uri=%.*s\n", msg->new_uri.len,
00543 msg->new_uri.len, msg->new_uri.s);
00544
00545 return 0;
00546 }
00547
00548 static int pdt_load_db(void)
00549 {
00550 db_key_t db_cols[3] = {&sdomain_column, &prefix_column, &domain_column};
00551 str p, d, sdomain;
00552 db_res_t* db_res = NULL;
00553 int i, ret;
00554 pdt_tree_t *_ptree_new = NULL;
00555 pdt_tree_t *old_tree = NULL;
00556
00557 if(db_con==NULL)
00558 {
00559 LM_ERR("no db connection\n");
00560 return -1;
00561 }
00562
00563 if (pdt_dbf.use_table(db_con, &db_table) < 0)
00564 {
00565 LM_ERR("failed to use_table\n");
00566 return -1;
00567 }
00568
00569 if (DB_CAPABILITY(pdt_dbf, DB_CAP_FETCH)) {
00570 if(pdt_dbf.query(db_con,0,0,0,db_cols,0,3,&sdomain_column,0) < 0)
00571 {
00572 LM_ERR("Error while querying db\n");
00573 return -1;
00574 }
00575 if(pdt_dbf.fetch_result(db_con, &db_res, pdt_fetch_rows)<0)
00576 {
00577 LM_ERR("Error while fetching result\n");
00578 if (db_res)
00579 pdt_dbf.free_result(db_con, db_res);
00580 goto error;
00581 } else {
00582 if(RES_ROW_N(db_res)==0)
00583 {
00584 return 0;
00585 }
00586 }
00587 } else {
00588 if((ret=pdt_dbf.query(db_con, NULL, NULL, NULL, db_cols,
00589 0, 3, &sdomain_column, &db_res))!=0
00590 || RES_ROW_N(db_res)<=0 )
00591 {
00592 pdt_dbf.free_result(db_con, db_res);
00593 if( ret==0)
00594 {
00595 return 0;
00596 } else {
00597 goto error;
00598 }
00599 }
00600 }
00601
00602 do {
00603 for(i=0; i<RES_ROW_N(db_res); i++)
00604 {
00605
00606 sdomain.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);
00607 sdomain.len = strlen(sdomain.s);
00608
00609 p.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);
00610 p.len = strlen(p.s);
00611
00612 d.s = (char*)(RES_ROWS(db_res)[i].values[2].val.string_val);
00613 d.len = strlen(d.s);
00614
00615 if(p.s==NULL || d.s==NULL || sdomain.s==NULL ||
00616 p.len<=0 || d.len<=0 || sdomain.len<=0)
00617 {
00618 LM_ERR("Error - bad values in db\n");
00619 continue;
00620 }
00621
00622 if(pdt_check_domain!=0 && _ptree_new!=NULL
00623 && pdt_check_pd(_ptree_new, &sdomain, &p, &d)==1)
00624 {
00625 LM_ERR("sdomain [%.*s]: prefix [%.*s] or domain <%.*s> "
00626 "duplicated\n", sdomain.len, sdomain.s, p.len, p.s,
00627 d.len, d.s);
00628 continue;
00629 }
00630
00631 if(pdt_add_to_tree(&_ptree_new, &sdomain, &p, &d)<0)
00632 {
00633 LM_ERR("Error adding info to tree\n");
00634 goto error;
00635 }
00636 }
00637 if (DB_CAPABILITY(pdt_dbf, DB_CAP_FETCH)) {
00638 if(pdt_dbf.fetch_result(db_con, &db_res, pdt_fetch_rows)<0) {
00639 LM_ERR("Error while fetching!\n");
00640 if (db_res)
00641 pdt_dbf.free_result(db_con, db_res);
00642 goto error;
00643 }
00644 } else {
00645 break;
00646 }
00647 } while(RES_ROW_N(db_res)>0);
00648 pdt_dbf.free_result(db_con, db_res);
00649
00650
00651
00652 lock_get( pdt_lock );
00653 pdt_reload_flag = 1;
00654 lock_release( pdt_lock );
00655
00656 while (pdt_tree_refcnt) {
00657 sleep_us(10);
00658 }
00659
00660 old_tree = *_ptree;
00661 *_ptree = _ptree_new;
00662
00663 pdt_reload_flag = 0;
00664
00665
00666 if (old_tree!=NULL)
00667 pdt_free_tree(old_tree);
00668
00669 return 0;
00670
00671 error:
00672 pdt_dbf.free_result(db_con, db_res);
00673 if (_ptree_new!=NULL)
00674 pdt_free_tree(_ptree_new);
00675 return -1;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 static struct mi_root* pdt_mi_reload(struct mi_root *cmd_tree, void *param)
00685 {
00686
00687 if(pdt_load_db()!=0)
00688 {
00689 LM_ERR("cannot re-load info from database\n");
00690 goto error;
00691 }
00692
00693 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00694
00695 error:
00696 return init_mi_tree( 500, "Failed to reload",16);
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 struct mi_root* pdt_mi_add(struct mi_root* cmd_tree, void* param)
00708 {
00709 db_key_t db_keys[NR_KEYS] = {&sdomain_column, &prefix_column, &domain_column};
00710 db_val_t db_vals[NR_KEYS];
00711 db_op_t db_ops[NR_KEYS] = {OP_EQ, OP_EQ};
00712 int i= 0;
00713 str sd, sp, sdomain;
00714 struct mi_node* node= NULL;
00715
00716 if(_ptree==NULL)
00717 {
00718 LM_ERR("strange situation\n");
00719 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00720 }
00721
00722
00723 node = cmd_tree->node.kids;
00724 if(node == NULL)
00725 goto error1;
00726
00727 sdomain = node->value;
00728 if(sdomain.s == NULL || sdomain.len== 0)
00729 return init_mi_tree( 404, "domain not found", 16);
00730
00731 if(*sdomain.s=='.' )
00732 return init_mi_tree( 400, "empty param",11);
00733
00734
00735 node = node->next;
00736 if(node == NULL)
00737 goto error1;
00738
00739 sp= node->value;
00740 if(sp.s== NULL || sp.len==0)
00741 {
00742 LM_ERR("could not read prefix\n");
00743 return init_mi_tree( 404, "prefix not found", 16);
00744 }
00745
00746 if(*sp.s=='.')
00747 return init_mi_tree(400, "empty param", 11);
00748
00749 while(i< sp.len)
00750 {
00751 if(strpos(pdt_char_list.s,sp.s[i]) < 0)
00752 return init_mi_tree(400, "bad prefix", 10);
00753 i++;
00754 }
00755
00756
00757 node= node->next;
00758 if(node == NULL || node->next!=NULL)
00759 goto error1;
00760
00761 sd= node->value;
00762 if(sd.s== NULL || sd.len==0)
00763 {
00764 LM_ERR("could not read domain\n");
00765 return init_mi_tree( 400, "domain not found", 16);
00766 }
00767
00768 if(*sd.s=='.')
00769 return init_mi_tree(400, "empty param", 11);
00770
00771
00772 if(pdt_check_domain!=0 && *_ptree!=NULL
00773 && pdt_check_pd(*_ptree, &sdomain, &sp, &sd)==1)
00774 {
00775 LM_ERR("(sdomain,prefix,domain) exists\n");
00776 return init_mi_tree(400,
00777 "(sdomain,prefix,domain) exists already", 38);
00778 }
00779 db_vals[0].type = DB_STR;
00780 db_vals[0].nul = 0;
00781 db_vals[0].val.str_val.s = sdomain.s;
00782 db_vals[0].val.str_val.len = sdomain.len;
00783
00784 db_vals[1].type = DB_STR;
00785 db_vals[1].nul = 0;
00786 db_vals[1].val.str_val.s = sp.s;
00787 db_vals[1].val.str_val.len = sp.len;
00788
00789 db_vals[2].type = DB_STR;
00790 db_vals[2].nul = 0;
00791 db_vals[2].val.str_val.s = sd.s;
00792 db_vals[2].val.str_val.len = sd.len;
00793
00794
00795 if(pdt_dbf.insert(db_con, db_keys, db_vals, NR_KEYS)<0)
00796 {
00797 LM_ERR("failed to store new prefix/domain\n");
00798 return init_mi_tree( 500,"Cannot store prefix/domain", 26);
00799 }
00800
00801
00802 if(pdt_load_db()!=0)
00803 {
00804 LM_ERR("cannot re-load info from database\n");
00805 goto error;
00806 }
00807
00808 LM_DBG("new prefix added %.*s-%.*s => %.*s\n",
00809 sdomain.len, sdomain.s, sp.len, sp.s, sd.len, sd.s);
00810 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00811
00812
00813 error:
00814 if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, NR_KEYS)<0)
00815 LM_ERR("database/cache are inconsistent\n");
00816 return init_mi_tree( 500, "could not add to cache", 23 );
00817
00818 error1:
00819 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00820
00821 }
00822
00823
00824
00825
00826
00827
00828 struct mi_root* pdt_mi_delete(struct mi_root* cmd_tree, void* param)
00829 {
00830 str sd, sdomain;
00831 struct mi_node* node= NULL;
00832 db_key_t db_keys[2] = {&sdomain_column, &domain_column};
00833 db_val_t db_vals[2];
00834 db_op_t db_ops[2] = {OP_EQ, OP_EQ};
00835
00836
00837 node = cmd_tree->node.kids;
00838 if(node == NULL)
00839 goto error;
00840
00841 sdomain = node->value;
00842 if(sdomain.s == NULL || sdomain.len== 0)
00843 return init_mi_tree( 404, "domain not found", 16);
00844
00845 if( *sdomain.s=='.' )
00846 return init_mi_tree( 400, "400 empty param",11);
00847
00848
00849 node= node->next;
00850 if(node == NULL || node->next!=NULL)
00851 goto error;
00852
00853 sd= node->value;
00854 if(sd.s== NULL || sd.len==0)
00855 {
00856 LM_ERR("could not read domain\n");
00857 return init_mi_tree(404, "domain not found", 16);
00858 }
00859
00860 if(*sd.s=='.')
00861 return init_mi_tree( 400, "empty param", 11);
00862
00863
00864 db_vals[0].type = DB_STR;
00865 db_vals[0].nul = 0;
00866 db_vals[0].val.str_val.s = sdomain.s;
00867 db_vals[0].val.str_val.len = sdomain.len;
00868
00869 db_vals[1].type = DB_STR;
00870 db_vals[1].nul = 0;
00871 db_vals[1].val.str_val.s = sd.s;
00872 db_vals[1].val.str_val.len = sd.len;
00873
00874 if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, 2)<0)
00875 {
00876 LM_ERR("database/cache are inconsistent\n");
00877 return init_mi_tree( 500, "database/cache are inconsistent", 31 );
00878 }
00879
00880 if(pdt_load_db()!=0)
00881 {
00882 LM_ERR("cannot re-load info from database\n");
00883 return init_mi_tree( 500, "cannot reload", 13 );
00884 }
00885
00886 LM_DBG("prefix for sdomain [%.*s] domain [%.*s] "
00887 "removed\n", sdomain.len, sdomain.s, sd.len, sd.s);
00888 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00889 error:
00890 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00891 }
00892
00893
00894 int pdt_print_mi_node(pdt_node_t *pt, struct mi_node* rpl, char *code,
00895 int len, str *sdomain, str *sd, str *sp)
00896 {
00897 int i;
00898 struct mi_node* node = NULL;
00899 struct mi_attr* attr= NULL;
00900
00901 if(pt==NULL || len>=PDT_MAX_DEPTH)
00902 return 0;
00903
00904 for(i=0; i<PDT_NODE_SIZE; i++)
00905 {
00906 code[len]=pdt_char_list.s[i];
00907 if(pt[i].domain.s!=NULL)
00908 {
00909 if((sp->s==NULL && sd->s==NULL)
00910 || (sp->s==NULL && (sd->s!=NULL && pt[i].domain.len==sd->len
00911 && strncasecmp(pt[i].domain.s, sd->s, sd->len)==0))
00912 || (sd->s==NULL && (len+1>=sp->len
00913 && strncmp(code, sp->s, sp->len)==0))
00914 || ((sp->s!=NULL && len+1>=sp->len
00915 && strncmp(code, sp->s, sp->len)==0)
00916 && (sd->s!=NULL && pt[i].domain.len>=sd->len
00917 && strncasecmp(pt[i].domain.s, sd->s, sd->len)==0)))
00918 {
00919 node = add_mi_node_child(rpl, 0, "PDT", 3, 0, 0);
00920 if(node == NULL)
00921 goto error;
00922
00923 attr = add_mi_attr(node, MI_DUP_VALUE, "SDOMAIN", 7,
00924 sdomain->s, sdomain->len);
00925 if(attr == NULL)
00926 goto error;
00927 attr = add_mi_attr(node, MI_DUP_VALUE, "PREFIX", 6,
00928 code, len+1);
00929 if(attr == NULL)
00930 goto error;
00931
00932 attr = add_mi_attr(node, MI_DUP_VALUE,"DOMAIN", 6,
00933 pt[i].domain.s, pt[i].domain.len);
00934 if(attr == NULL)
00935 goto error;
00936 }
00937 }
00938 if(pdt_print_mi_node(pt[i].child, rpl, code, len+1, sdomain, sd, sp)<0)
00939 goto error;
00940 }
00941 return 0;
00942 error:
00943 return -1;
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 struct mi_root* pdt_mi_list(struct mi_root* cmd_tree, void* param)
00965 {
00966 str sd, sp, sdomain;
00967 pdt_tree_t *pt;
00968 struct mi_node* node = NULL;
00969 unsigned int i= 0;
00970 struct mi_root* rpl_tree = NULL;
00971 struct mi_node* rpl = NULL;
00972 static char code_buf[PDT_MAX_DEPTH+1];
00973 int len;
00974
00975 if(_ptree==NULL)
00976 {
00977 LM_ERR("empty domain list\n");
00978 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00979 }
00980
00981
00982 sdomain.s = 0;
00983 sdomain.len = 0;
00984 sp.s = 0;
00985 sp.len = 0;
00986 sd.s = 0;
00987 sd.len = 0;
00988 node = cmd_tree->node.kids;
00989 if(node != NULL)
00990 {
00991 sdomain = node->value;
00992 if(sdomain.s == NULL || sdomain.len== 0)
00993 return init_mi_tree( 404, "domain not found", 16);
00994
00995 if(*sdomain.s=='.')
00996 sdomain.s = 0;
00997
00998
00999 node = node->next;
01000 if(node != NULL)
01001 {
01002 sp= node->value;
01003 if(sp.s== NULL || sp.len==0 || *sp.s=='.')
01004 sp.s = NULL;
01005 else {
01006 while(sp.s!=NULL && i!=sp.len)
01007 {
01008 if(strpos(pdt_char_list.s,sp.s[i]) < 0)
01009 {
01010 LM_ERR("bad prefix [%.*s]\n", sp.len, sp.s);
01011 return init_mi_tree( 400, "bad prefix", 10);
01012 }
01013 i++;
01014 }
01015 }
01016
01017
01018 node= node->next;
01019 if(node != NULL)
01020 {
01021 sd= node->value;
01022 if(sd.s== NULL || sd.len==0 || *sd.s=='.')
01023 sd.s = NULL;
01024 }
01025 }
01026 }
01027
01028 rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
01029 if(rpl_tree == NULL)
01030 return 0;
01031 rpl = &rpl_tree->node;
01032
01033 if(*_ptree==0)
01034 return rpl_tree;
01035
01036 pt = *_ptree;
01037
01038 while(pt!=NULL)
01039 {
01040 if(sdomain.s==NULL ||
01041 (sdomain.s!=NULL && pt->sdomain.len>=sdomain.len &&
01042 strncmp(pt->sdomain.s, sdomain.s, sdomain.len)==0))
01043 {
01044 len = 0;
01045 if(pdt_print_mi_node(pt->head, rpl, code_buf, len, &pt->sdomain,
01046 &sd, &sp)<0)
01047 goto error;
01048 }
01049 pt = pt->next;
01050 }
01051
01052 return rpl_tree;
01053
01054 error:
01055 free_mi_tree(rpl_tree);
01056 return 0;
01057 }
01058