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 #include <ctype.h>
00031 #include <stdlib.h>
00032
00033 #include "../../mem/mem.h"
00034 #include "../../mem/shm_mem.h"
00035 #include "../../str.h"
00036 #include "../../ut.h"
00037
00038 #include "cr_fifo.h"
00039 #include "carrierroute.h"
00040 #include "cr_config.h"
00041 #include "cr_carrier.h"
00042 #include "cr_domain.h"
00043 #include "cr_rule.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052 static unsigned int opt_settings[5][3] = {{O_PREFIX|O_DOMAIN|O_HOST|O_PROB, O_R_PREFIX|O_R_SUFFIX|O_H_INDEX, O_NEW_TARGET},
00053 {O_HOST|O_DOMAIN|O_PREFIX, O_PROB, O_R_PREFIX|O_R_SUFFIX|O_NEW_TARGET|O_H_INDEX},
00054 {O_HOST|O_NEW_TARGET, O_PREFIX|O_DOMAIN|O_PROB, O_R_PREFIX|O_R_SUFFIX|O_H_INDEX},
00055 {O_HOST|O_DOMAIN|O_PREFIX, O_PROB|O_NEW_TARGET, O_R_PREFIX|O_R_SUFFIX|O_H_INDEX},
00056 {O_HOST|O_DOMAIN|O_PREFIX, O_PROB, O_R_PREFIX|O_R_SUFFIX|O_NEW_TARGET|O_H_INDEX}};
00057
00058 int fifo_err;
00059
00060 static int updated;
00061
00062 static int dump_tree_recursor (struct mi_node* msg, struct dtrie_node_t *node, char *prefix);
00063
00064 static struct mi_root* print_replace_help(void);
00065
00066 static int get_fifo_opts(str * buf, fifo_opt_t * opts, unsigned int opt_set[]);
00067
00068 static int update_route_data(fifo_opt_t * opts);
00069
00070 static int update_route_data_recursor(struct dtrie_node_t *node, str * act_domain, fifo_opt_t * opts);
00071
00072 static struct mi_root* print_fifo_err(void);
00073
00074
00075 static int str_toklen(str * str, const char * delims)
00076 {
00077 int len;
00078
00079 if ((str==NULL) || (str->s==NULL)) {
00080
00081 return -1;
00082 }
00083
00084 len=0;
00085 while (len<str->len) {
00086 if (strchr(delims,str->s[len])!=NULL) {
00087 return len;
00088 }
00089 len++;
00090 }
00091
00092 return len;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 struct mi_root* reload_fifo (struct mi_root* cmd_tree, void *param) {
00105 struct mi_root * tmp = NULL;
00106
00107 if (reload_route_data () == -1) {
00108 tmp = init_mi_tree(500, "failed to re-built tree, see log", 33);
00109 }
00110 else {
00111 tmp = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00112 }
00113 return tmp;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 struct mi_root* dump_fifo (struct mi_root* cmd_tree, void *param) {
00126 struct route_data_t * rd;
00127 str *tmp_str;
00128 str empty_str = str_init("<empty>");
00129
00130 if((rd = get_data ()) == NULL) {
00131 LM_ERR("error during retrieve data\n");
00132 return init_mi_tree(500, "error during command processing", 31);
00133 }
00134
00135 struct mi_root* rpl_tree;
00136 struct mi_node* node = NULL;
00137 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00138 if(rpl_tree == NULL)
00139 return 0;
00140 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "Printing routing information:");
00141 if(node == NULL)
00142 goto error;
00143
00144 LM_DBG("start processing of data\n");
00145 int i, j;
00146 for (i = 0; i < rd->carrier_num; i++) {
00147 if (rd->carriers[i]) {
00148 tmp_str = (rd->carriers[i] ? rd->carriers[i]->name : &empty_str);
00149 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "Printing tree for carrier '%.*s' (%i)\n", tmp_str->len, tmp_str->s, rd->carriers[i] ? rd->carriers[i]->id : 0);
00150 if(node == NULL)
00151 goto error;
00152 for (j=0; j<rd->carriers[i]->domain_num; j++) {
00153 if (rd->carriers[i]->domains[j] && rd->carriers[i]->domains[j]->tree) {
00154 tmp_str = (rd->carriers[i]->domains[j] ? rd->carriers[i]->domains[j]->name : &empty_str);
00155 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "Printing tree for domain '%.*s' (%i)\n", tmp_str->len, tmp_str->s, rd->carriers[i]->domains[j]->id);
00156 if(node == NULL)
00157 goto error;
00158 dump_tree_recursor (&rpl_tree->node, rd->carriers[i]->domains[j]->tree, "");
00159 }
00160 }
00161 }
00162 }
00163 release_data (rd);
00164 return rpl_tree;
00165 return 0;
00166
00167 error:
00168 release_data (rd);
00169 free_mi_tree(rpl_tree);
00170 return 0;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 struct mi_root* replace_host (struct mi_root* cmd_tree, void *param) {
00185 struct mi_node *node = NULL;
00186
00187 int ret;
00188 fifo_opt_t options;
00189
00190 if(mode != CARRIERROUTE_MODE_FILE) {
00191 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00192 }
00193
00194 node = cmd_tree->node.kids;
00195 if (node==NULL || node->next!=NULL)
00196 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00197
00198
00199
00200 if (node->value.s==NULL)
00201 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00202
00203 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_REPLACE])) < 0) {
00204 return print_fifo_err();
00205 }
00206
00207 options.status = 1;
00208 options.cmd = OPT_REPLACE;
00209
00210 if(update_route_data(&options) < 0) {
00211 return init_mi_tree(500, "failed to update route data, see log", 37);
00212 }
00213
00214 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 struct mi_root* deactivate_host (struct mi_root* cmd_tree, void *param) {
00229 struct mi_node *node = NULL;
00230
00231 int ret;
00232 fifo_opt_t options;
00233
00234 if(mode != CARRIERROUTE_MODE_FILE) {
00235 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00236 }
00237
00238 node = cmd_tree->node.kids;
00239 if (node==NULL || node->next!=NULL)
00240 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00241
00242
00243
00244 if (node->value.s==NULL)
00245 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00246
00247 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_DEACTIVATE])) < 0) {
00248 return print_fifo_err();
00249 }
00250
00251 options.status = 0;
00252 options.cmd = OPT_DEACTIVATE;
00253
00254 if(update_route_data(&options) < 0) {
00255 return init_mi_tree(500, "failed to update route data, see log", 37);
00256 }
00257
00258 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 struct mi_root* activate_host (struct mi_root* cmd_tree, void *param) {
00273 struct mi_node *node = NULL;
00274
00275 int ret;
00276 fifo_opt_t options;
00277
00278 if(mode != CARRIERROUTE_MODE_FILE) {
00279 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00280 }
00281
00282 node = cmd_tree->node.kids;
00283 if (node==NULL || node->next!=NULL)
00284 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00285
00286
00287
00288 if (node->value.s==NULL)
00289 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00290
00291 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_ACTIVATE])) < 0) {
00292 return print_fifo_err();
00293 }
00294
00295 options.status = 1;
00296 options.cmd = OPT_ACTIVATE;
00297
00298 if(update_route_data(&options) < 0) {
00299 return init_mi_tree(500, "failed to update route data, see log", 37);
00300 }
00301
00302 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 struct mi_root* add_host (struct mi_root* cmd_tree, void *param) {
00317 struct mi_node *node = NULL;
00318
00319 int ret;
00320 fifo_opt_t options;
00321
00322 if(mode != CARRIERROUTE_MODE_FILE) {
00323 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00324 }
00325
00326 node = cmd_tree->node.kids;
00327 if (node==NULL || node->next!=NULL || node->value.s==NULL) {
00328 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00329 }
00330
00331 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_ADD])) < 0) {
00332 return print_fifo_err();
00333 }
00334
00335 options.status = 1;
00336 options.cmd = OPT_ADD;
00337
00338 if(update_route_data(&options) < 0) {
00339 return init_mi_tree(500, "failed to update route data, see log", 37);
00340 }
00341
00342 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 struct mi_root* delete_host (struct mi_root* cmd_tree, void * param) {
00357 struct mi_node *node = NULL;
00358
00359 int ret;
00360 fifo_opt_t options;
00361
00362 if(mode != CARRIERROUTE_MODE_FILE) {
00363 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00364 }
00365
00366 node = cmd_tree->node.kids;
00367 if (node==NULL || node->next!=NULL)
00368 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00369
00370
00371
00372 if (node->value.s==NULL)
00373 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00374
00375 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_REMOVE])) < 0) {
00376 return print_fifo_err();
00377 }
00378
00379 options.cmd = OPT_REMOVE;
00380
00381 if(update_route_data(&options) < 0) {
00382 return init_mi_tree(500, "failed to update route data, see log", 37);
00383 }
00384
00385 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 static int dump_tree_recursor (struct mi_node* msg, struct dtrie_node_t *node, char *prefix) {
00400 char s[256];
00401 char *p;
00402 int i;
00403 struct route_flags *rf;
00404 struct route_rule *rr;
00405 struct route_rule_p_list * rl;
00406 double prob;
00407
00408 strcpy (s, prefix);
00409 p = s + strlen (s);
00410 p[1] = '\0';
00411 for (i = 0; i < cr_match_mode; ++i) {
00412 if (node->child[i] != NULL) {
00413 *p = i + '0';
00414 dump_tree_recursor (msg->next, node->child[i], s);
00415 }
00416 }
00417 *p = '\0';
00418 for (rf = (struct route_flags *)(node->data); rf != NULL; rf = rf->next) {
00419 for (rr = rf->rule_list; rr != NULL; rr = rr->next) {
00420 if(rf->dice_max){
00421 prob = (double)(rr->prob * DICE_MAX)/(double)rf->dice_max;
00422 } else {
00423 prob = rr->prob;
00424 }
00425 addf_mi_node_child(msg->next, 0, 0, 0, "%10s: %0.3f %%, '%.*s': %s, '%i', '%.*s', '%.*s', '%.*s'\n",
00426 strlen(prefix) > 0 ? prefix : "NULL", prob * 100, rr->host.len, rr->host.s,
00427 (rr->status ? "ON" : "OFF"), rr->strip,
00428 rr->local_prefix.len, rr->local_prefix.s,
00429 rr->local_suffix.len, rr->local_suffix.s,
00430 rr->comment.len, rr->comment.s);
00431 if(!rr->status && rr->backup && rr->backup->rr){
00432 addf_mi_node_child(msg->next, 0, 0, 0, " Rule is backed up by: %.*s\n", rr->backup->rr->host.len, rr->backup->rr->host.s);
00433 }
00434 if(rr->backed_up){
00435 rl = rr->backed_up;
00436 i=0;
00437 while(rl){
00438 if(rl->rr){
00439 addf_mi_node_child(msg->next, 0, 0, 0, " Rule is backup for: %.*s", rl->rr->host.len, rl->rr->host.s);
00440 }
00441 rl = rl->next;
00442 i++;
00443 }
00444 }
00445 }
00446 }
00447 return 0;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 static int get_fifo_opts(str * buf, fifo_opt_t * opts, unsigned int opt_set[]) {
00463 int opt_argc = 0;
00464 str opt_argv[20];
00465 int i, op = -1;
00466 unsigned int used_opts = 0;
00467 int toklen;
00468
00469 memset(opt_argv, 0, sizeof(opt_argv));
00470 memset(opts, 0, sizeof(fifo_opt_t));
00471 opts->prob = -1;
00472
00473 while((toklen = str_toklen(buf, " \t\r\n")) >=0 && opt_argc < 20) {
00474 buf->s[toklen] = '\0';
00475 opt_argv[opt_argc].len = toklen;
00476 opt_argv[opt_argc].s = buf->s;
00477 buf->s += toklen + 1;
00478 buf->len -= toklen + 1;
00479 LM_DBG("found arg[%i]: %.*s\n", opt_argc, opt_argv[opt_argc].len, opt_argv[opt_argc].s);
00480 opt_argc++;
00481 }
00482 for (i=0; i<opt_argc; i++) {
00483 LM_DBG("token %.*s", opt_argv[i].len, opt_argv[i].s);
00484 if (opt_argv[i].len >= 1) {
00485 switch(*opt_argv[i].s) {
00486 case '-': switch(opt_argv[i].s[1]) {
00487 case OPT_DOMAIN_CHR:
00488 op = OPT_DOMAIN;
00489 used_opts |= O_DOMAIN;
00490 break;
00491 case OPT_PREFIX_CHR:
00492 op = OPT_PREFIX;
00493 used_opts |= O_PREFIX;
00494 break;
00495 case OPT_HOST_CHR:
00496 op = OPT_HOST;
00497 used_opts |= O_HOST;
00498 break;
00499 case OPT_NEW_TARGET_CHR:
00500 op = OPT_NEW_TARGET;
00501 used_opts |= O_NEW_TARGET;
00502 break;
00503 case OPT_PROB_CHR:
00504 op = OPT_PROB;
00505 used_opts |= O_PROB;
00506 break;
00507 case OPT_R_PREFIX_CHR:
00508 op = OPT_R_PREFIX;
00509 used_opts |= O_R_PREFIX;
00510 break;
00511 case OPT_R_SUFFIX_CHR:
00512 op = OPT_R_SUFFIX;
00513 used_opts |= O_R_SUFFIX;
00514 break;
00515 case OPT_HASH_INDEX_CHR:
00516 op = OPT_HASH_INDEX;
00517 used_opts |= O_H_INDEX;
00518 break;
00519 case OPT_HELP_CHR:
00520 FIFO_ERR(E_HELP);
00521 return -1;
00522 default: {
00523 FIFO_ERR(E_WRONGOPT);
00524 LM_DBG("Unknown option: %.*s\n", opt_argv[i].len, opt_argv[i].s);
00525 return -1;
00526 }
00527 }
00528 break;
00529 default: switch(op) {
00530 case OPT_DOMAIN:
00531 opts->domain = opt_argv[i];
00532 op = -1;
00533 break;
00534 case OPT_PREFIX:
00535 if (str_strcasecmp(&opt_argv[i], &CR_EMPTY_PREFIX) == 0) {
00536 opts->prefix.s = NULL;
00537 opts->prefix.len = 0;
00538 } else {
00539 opts->prefix = opt_argv[i];
00540 }
00541 op = -1;
00542 break;
00543 case OPT_HOST:
00544 opts->host = opt_argv[i];
00545 op = -1;
00546 break;
00547 case OPT_NEW_TARGET:
00548 opts->new_host = opt_argv[i];
00549 op = -1;
00550 break;
00551 case OPT_PROB:
00552 opts->prob = strtod(opt_argv[i].s, NULL);
00553 op = -1;
00554 break;
00555 case OPT_R_PREFIX:
00556 opts->rewrite_prefix = opt_argv[i];
00557 op = -1;
00558 break;
00559 case OPT_STRIP:
00560 str2sint(&opt_argv[i], &opts->strip);
00561 op = -1;
00562 break;
00563 case OPT_R_SUFFIX:
00564 opts->rewrite_suffix = opt_argv[i];
00565 op = -1;
00566 break;
00567 case OPT_HASH_INDEX:
00568 str2sint(&opt_argv[i], &opts->hash_index);
00569 op = -1;
00570 break;
00571 default: {
00572 LM_DBG("No option given\n");
00573 FIFO_ERR(E_NOOPT);
00574 return -1;
00575 }
00576 }
00577 break;
00578 }
00579 }
00580 }
00581 if((used_opts & opt_set[OPT_INVALID]) != 0) {
00582 LM_DBG("invalid option\n");
00583 FIFO_ERR(E_INVALIDOPT);
00584 return -1;
00585 }
00586 if((used_opts & opt_set[OPT_MANDATORY]) != opt_set[OPT_MANDATORY]) {
00587 LM_DBG("option missing\n");
00588 FIFO_ERR(E_MISSOPT);
00589 return -1;
00590 }
00591 return 0;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 static int update_route_data(fifo_opt_t * opts) {
00606 struct route_data_t * rd;
00607 int i,j;
00608 int domain_id;
00609 str tmp_domain;
00610 str tmp_prefix;
00611 str tmp_host;
00612 str tmp_rewrite_prefix;
00613 str tmp_rewrite_suffix;
00614 str tmp_comment = str_init("");
00615
00616 if ((rd = shm_malloc(sizeof(struct route_data_t))) == NULL) {
00617 SHM_MEM_ERROR;
00618 return -1;
00619 }
00620 memset(rd, 0, sizeof(struct route_data_t));
00621 if (load_config(rd) < 0) {
00622 LM_ERR("could not load config");
00623 FIFO_ERR(E_LOADCONF);
00624 return -1;
00625 }
00626
00627 if (rule_fixup(rd) < 0) {
00628 LM_ERR("could not fixup rules");
00629 FIFO_ERR(E_RULEFIXUP);
00630 return -1;
00631 }
00632 updated = 0;
00633
00634 if (opts->cmd == OPT_ADD) {
00635 tmp_domain=opts->domain;
00636 tmp_prefix=opts->prefix;
00637 tmp_host=opts->host;
00638 tmp_rewrite_prefix=opts->rewrite_prefix;
00639 tmp_rewrite_suffix=opts->rewrite_suffix;
00640 if (tmp_domain.s==NULL) {
00641 tmp_domain.s="";
00642 tmp_domain.len=0;
00643 }
00644 if (tmp_prefix.s==NULL) {
00645 tmp_prefix.s="";
00646 tmp_prefix.len=0;
00647 }
00648 if (tmp_host.s==NULL) {
00649 tmp_host.s="";
00650 tmp_host.len=0;
00651 }
00652 if (tmp_rewrite_prefix.s==NULL) {
00653 tmp_rewrite_prefix.s="";
00654 tmp_rewrite_prefix.len=0;
00655 }
00656 if (tmp_rewrite_suffix.s==NULL) {
00657 tmp_rewrite_suffix.s="";
00658 tmp_rewrite_suffix.len=0;
00659 }
00660
00661 domain_id = map_name2id(rd->domain_map, rd->domain_num, &tmp_domain);
00662 if (domain_id < 0) {
00663 LM_ERR("cannot find id for domain '%.*s'", tmp_domain.len, tmp_domain.s);
00664 goto errout;
00665 }
00666
00667 if (add_route(rd, 1, domain_id, &tmp_prefix, 0, 0, 0, opts->prob,
00668 &tmp_host, opts->strip, &tmp_rewrite_prefix, &tmp_rewrite_suffix,
00669 opts->status, opts->hash_index, -1, NULL, &tmp_comment) < 0) {
00670 goto errout;
00671 }
00672 updated = 1;
00673 if (rule_fixup(rd) < 0) {
00674 LM_ERR("could not fixup rules after route appending");
00675 FIFO_ERR(E_RULEFIXUP);
00676 goto errout;
00677 }
00678 } else {
00679 for (i=0; i<rd->carrier_num; i++) {
00680 if(rd->carriers[i]){
00681 for (j=0; j<rd->carriers[i]->domain_num; j++) {
00682 if (rd->carriers[i]->domains[j] && rd->carriers[i]->domains[j]->tree) {
00683 if (update_route_data_recursor(rd->carriers[i]->domains[j]->tree, rd->carriers[i]->domains[j]->name, opts) < 0) {
00684 goto errout;
00685 }
00686 }
00687 }
00688 }
00689 }
00690 }
00691
00692 if(!updated){
00693 LM_ERR("no match for update found");
00694 FIFO_ERR(E_NOUPDATE);
00695 goto errout;
00696 }
00697
00698 if (save_config(rd) < 0) {
00699 LM_ERR("could not save config");
00700 FIFO_ERR(E_SAVECONF);
00701 goto errout;
00702 }
00703
00704 if (reload_route_data() == -1) {
00705 LM_ERR("could not reload route data");
00706 FIFO_ERR(E_LOADCONF);
00707 goto errout;
00708 }
00709
00710 clear_route_data(rd);
00711 return 0;
00712 errout:
00713 clear_route_data(rd);
00714 return -1;
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 static int update_route_data_recursor(struct dtrie_node_t *node, str * act_domain, fifo_opt_t * opts) {
00732 int i, hash = 0;
00733 struct route_rule * rr, * prev = NULL, * tmp, * backup;
00734 struct route_flags *rf;
00735
00736 rf = (struct route_flags *)(node->data);
00737 if (rf && rf->rule_list) {
00738 rr = rf->rule_list;
00739 while (rr) {
00740 if ((!opts->domain.len || (strncmp(opts->domain.s, OPT_STAR, strlen(OPT_STAR)) == 0)
00741 || ((opts->domain.len == act_domain->len) && (strncmp(opts->domain.s, act_domain->s, opts->domain.len) == 0)))
00742 && ((!opts->prefix.len && !rr->prefix.len) || (strncmp(opts->prefix.s, OPT_STAR, strlen(OPT_STAR)) == 0)
00743 || (rr->prefix.len == opts->prefix.len && (strncmp(opts->prefix.s, rr->prefix.s, opts->prefix.len) == 0)))
00744 && ((!opts->host.len && !rr->host.s) || (strncmp(opts->host.s, OPT_STAR, strlen(OPT_STAR)) == 0)
00745 || ((strncmp(rr->host.s, opts->host.s, opts->host.len) == 0) && (rr->host.len == opts->host.len)))
00746 && ((opts->prob < 0) || (opts->prob == rr->prob))) {
00747 switch (opts->cmd) {
00748 case OPT_REPLACE:
00749 LM_INFO("replace host %.*s with %.*s\n", rr->host.len, rr->host.s, opts->new_host.len, opts->new_host.s);
00750 if (rr->host.s) {
00751 shm_free(rr->host.s);
00752 }
00753 if (opts->new_host.len) {
00754 if ((rr->host.s = shm_malloc(opts->new_host.len + 1)) == NULL) {
00755 SHM_MEM_ERROR;
00756 FIFO_ERR(E_NOMEM);
00757 return -1;
00758 }
00759 memmove(rr->host.s, opts->new_host.s, opts->new_host.len + 1);
00760 rr->host.len = opts->new_host.len;
00761 rr->host.s[rr->host.len] = '\0';
00762 } else {
00763 rr->host.len = 0;
00764 }
00765 rr->status = opts->status;
00766 prev = rr;
00767 rr = rr->next;
00768 updated = 1;
00769 break;
00770 case OPT_DEACTIVATE:
00771 if (remove_backed_up(rr) < 0) {
00772 LM_ERR("could not reset backup hosts\n");
00773 FIFO_ERR(E_RESET);
00774 return -1;
00775 }
00776 if (opts->new_host.len > 0) {
00777 LM_INFO("deactivating host %.*s\n", rr->host.len, rr->host.s);
00778 if (opts->new_host.len == 1 && opts->new_host.s[0] == 'a') {
00779 if ((backup = find_auto_backup(rf, rr)) == NULL) {
00780 LM_ERR("didn't find auto backup route\n");
00781 FIFO_ERR(E_NOAUTOBACKUP);
00782 return -1;
00783 }
00784 } else {
00785 errno = 0;
00786 hash = strtol(opts->new_host.s, NULL, 10);
00787 if (errno == EINVAL || errno == ERANGE) {
00788 if ((backup = find_rule_by_hash(rf, hash)) == NULL) {
00789 LM_ERR("didn't find given backup route (hash %i)\n", hash);
00790 FIFO_ERR(E_NOHASHBACKUP);
00791 return -1;
00792 }
00793 } else {
00794 if ((backup = find_rule_by_host(rf, &opts->new_host)) == NULL) {
00795 LM_ERR("didn't find given backup route (host %.*s)\n", opts->new_host.len, opts->new_host.s);
00796 FIFO_ERR(E_NOHOSTBACKUP);
00797 return -1;
00798 }
00799 }
00800 }
00801 if (add_backup_rule(rr, backup) < 0) {
00802 LM_ERR("couldn't set backup route\n");
00803 FIFO_ERR(E_ADDBACKUP);
00804 return -1;
00805 }
00806 } else {
00807 if(rr->backed_up){
00808 LM_ERR("can't deactivate route without backup route because it is backup route for others\n");
00809 FIFO_ERR(E_DELBACKUP);
00810 return -1;
00811 }
00812 }
00813 rr->status = opts->status;
00814 prev = rr;
00815 rr = rr->next;
00816 updated = 1;
00817 break;
00818 case OPT_ACTIVATE:
00819 LM_INFO("activating host %.*s\n", rr->host.len, rr->host.s);
00820 if (remove_backed_up(rr) < 0) {
00821 LM_ERR("could not reset backup hosts\n");
00822 FIFO_ERR(E_RESET);
00823 return -1;
00824 }
00825 rr->status = opts->status;
00826 prev = rr;
00827 rr = rr->next;
00828 updated = 1;
00829 break;
00830 case OPT_REMOVE:
00831 LM_INFO("removing host %.*s\n", rr->host.len, rr->host.s);
00832 if (rr->backed_up){
00833 LM_ERR("cannot remove host %.*s which is backup for other hosts\n", rr->host.len, rr->host.s);
00834 FIFO_ERR(E_DELBACKUP);
00835 return -1;
00836 }
00837 if (remove_backed_up(rr) < 0) {
00838 LM_ERR("could not reset backup hosts\n");
00839 FIFO_ERR(E_RESET);
00840 return -1;
00841 }
00842 if (prev) {
00843 prev->next = rr->next;
00844 tmp = rr;
00845 rr = prev;
00846 destroy_route_rule(tmp);
00847 prev = rr;
00848 rr = rr->next;
00849 } else {
00850 rf->rule_list = rr->next;
00851 tmp = rr;
00852 rr = rf->rule_list;
00853 destroy_route_rule(tmp);
00854 }
00855 rf->rule_num--;
00856 rf->max_targets--;
00857 updated = 1;
00858 break;
00859 default:
00860 rr = rr->next;
00861 break;
00862 }
00863 } else {
00864 prev = rr;
00865 rr = rr->next;
00866 }
00867 }
00868 }
00869 for (i=0; i<cr_match_mode; i++) {
00870 if (node->child[i]) {
00871 if (update_route_data_recursor(node->child[i], act_domain, opts) < 0) {
00872 return -1;
00873 }
00874 }
00875 }
00876 return 0;
00877 }
00878
00879
00880
00881
00882
00883 static struct mi_root* print_replace_help(void) {
00884 struct mi_root* rpl_tree;
00885 struct mi_node* node;
00886
00887 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00888 if(rpl_tree == NULL)
00889 return 0;
00890
00891 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "carrierroute options usage:");
00892 if(node == NULL)
00893 goto error;
00894 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c searched/new remote host\n", OPT_HOST_CHR);
00895 if(node == NULL)
00896 goto error;
00897 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c replacement/backup host", OPT_NEW_TARGET_CHR);
00898 if(node == NULL)
00899 goto error;
00900 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: searched/new domain", OPT_DOMAIN_CHR);
00901 if(node == NULL)
00902 goto error;
00903 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: searched/new prefix", OPT_PREFIX_CHR);
00904 if(node == NULL)
00905 goto error;
00906 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: searched/new weight (0..1)", OPT_PROB_CHR);
00907 if(node == NULL)
00908 goto error;
00909 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: new rewrite prefix", OPT_R_PREFIX_CHR);
00910 if(node == NULL)
00911 goto error;
00912 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: new rewrite suffix", OPT_R_SUFFIX_CHR);
00913 if(node == NULL)
00914 goto error;
00915 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: new hash index", OPT_HASH_INDEX_CHR);
00916 if(node == NULL)
00917 goto error;
00918 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: prints this help", OPT_HELP_CHR);
00919 if(node == NULL)
00920 goto error;
00921
00922 return rpl_tree;
00923
00924 error:
00925 free_mi_tree(rpl_tree);
00926 return 0;
00927 }
00928
00929
00930
00931
00932
00933
00934 struct mi_root* print_fifo_err(void) {
00935 struct mi_root* rpl_tree;
00936
00937 switch (fifo_err) {
00938 case E_MISC:
00939 rpl_tree = init_mi_tree( 400, "An error occured", 17);
00940 if(rpl_tree == NULL)
00941 return 0;
00942 break;
00943 case E_NOOPT:
00944 rpl_tree = init_mi_tree( 400, "No option given", 16);
00945 if(rpl_tree == NULL)
00946 return 0;
00947 break;
00948 case E_WRONGOPT:
00949 rpl_tree = init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00950 if(rpl_tree == NULL)
00951 return 0;
00952 break;
00953 case E_NOMEM:
00954 rpl_tree = init_mi_tree( 500, "Out of memory", 14);
00955 if(rpl_tree == NULL)
00956 return 0;
00957 break;
00958 case E_RESET:
00959 rpl_tree = init_mi_tree( 500, "Could not reset backup routes", 30);
00960 if(rpl_tree == NULL)
00961 return 0;
00962 break;
00963 case E_NOAUTOBACKUP:
00964 rpl_tree = init_mi_tree( 400, "No auto backup route found", 27);
00965 if(rpl_tree == NULL)
00966 return 0;
00967 break;
00968 case E_NOHASHBACKUP:
00969 rpl_tree = init_mi_tree( 400, "No backup route for given hash found", 37);
00970 if(rpl_tree == NULL)
00971 return 0;
00972 break;
00973 case E_NOHOSTBACKUP:
00974 rpl_tree = init_mi_tree( 400, "No backup route for given host found", 37);
00975 if(rpl_tree == NULL)
00976 return 0;
00977 break;
00978 case E_ADDBACKUP:
00979 rpl_tree = init_mi_tree( 500, "Could not set backup route", 27);
00980 if(rpl_tree == NULL)
00981 return 0;
00982 break;
00983 case E_DELBACKUP:
00984 rpl_tree = init_mi_tree( 400, "Could not delete or deactivate route, it is backup for other routes", 68);
00985 if(rpl_tree == NULL)
00986 return 0;
00987 break;
00988 case E_LOADCONF:
00989 rpl_tree = init_mi_tree( 500, "Could not load config from file", 32);
00990 if(rpl_tree == NULL)
00991 return 0;
00992 break;
00993 case E_SAVECONF:
00994 rpl_tree = init_mi_tree( 500, "Could not save config", 22);
00995 if(rpl_tree == NULL)
00996 return 0;
00997 break;
00998 case E_INVALIDOPT:
00999 rpl_tree = init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
01000 if(rpl_tree == NULL)
01001 return 0;
01002 break;
01003 case E_MISSOPT:
01004 rpl_tree = init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
01005 if(rpl_tree == NULL)
01006 return 0;
01007 break;
01008 case E_RULEFIXUP:
01009 rpl_tree = init_mi_tree( 500, "Could not fixup rules", 22);
01010 if(rpl_tree == NULL)
01011 return 0;
01012 break;
01013 case E_NOUPDATE:
01014 rpl_tree = init_mi_tree( 500, "No match for update found", 26);
01015 if(rpl_tree == NULL)
01016 return 0;
01017 break;
01018 case E_HELP:
01019 return print_replace_help();
01020 break;
01021 default:
01022 rpl_tree = init_mi_tree( 500, "An error occured", 17);
01023 if(rpl_tree == NULL)
01024 return 0;
01025 break;
01026 }
01027 return rpl_tree;
01028 }