00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
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 goto error2;
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 if (dump_tree_recursor (&rpl_tree->node, rd->carriers[i]->domains[j]->tree, "") < 0)
00159 goto error;
00160 }
00161 }
00162 }
00163 }
00164 release_data (rd);
00165 return rpl_tree;
00166
00167 error:
00168 free_mi_tree(rpl_tree);
00169 error2:
00170 release_data (rd);
00171 return 0;
00172 }
00173
00174
00185 struct mi_root* replace_host (struct mi_root* cmd_tree, void *param) {
00186 struct mi_node *node = NULL;
00187
00188 int ret;
00189 fifo_opt_t options;
00190
00191 if(mode != CARRIERROUTE_MODE_FILE) {
00192 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00193 }
00194
00195 node = cmd_tree->node.kids;
00196 if (node==NULL || node->next!=NULL)
00197 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00198
00199
00200
00201 if (node->value.s==NULL)
00202 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00203
00204 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_REPLACE])) < 0) {
00205 return print_fifo_err();
00206 }
00207
00208 options.status = 1;
00209 options.cmd = OPT_REPLACE;
00210
00211 if(update_route_data(&options) < 0) {
00212 return init_mi_tree(500, "failed to update route data, see log", 37);
00213 }
00214
00215 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00216 }
00217
00218
00229 struct mi_root* deactivate_host (struct mi_root* cmd_tree, void *param) {
00230 struct mi_node *node = NULL;
00231
00232 int ret;
00233 fifo_opt_t options;
00234
00235 if(mode != CARRIERROUTE_MODE_FILE) {
00236 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00237 }
00238
00239 node = cmd_tree->node.kids;
00240 if (node==NULL || node->next!=NULL)
00241 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00242
00243
00244
00245 if (node->value.s==NULL)
00246 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00247
00248 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_DEACTIVATE])) < 0) {
00249 return print_fifo_err();
00250 }
00251
00252 options.status = 0;
00253 options.cmd = OPT_DEACTIVATE;
00254
00255 if(update_route_data(&options) < 0) {
00256 return init_mi_tree(500, "failed to update route data, see log", 37);
00257 }
00258
00259 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00260 }
00261
00262
00273 struct mi_root* activate_host (struct mi_root* cmd_tree, void *param) {
00274 struct mi_node *node = NULL;
00275
00276 int ret;
00277 fifo_opt_t options;
00278
00279 if(mode != CARRIERROUTE_MODE_FILE) {
00280 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00281 }
00282
00283 node = cmd_tree->node.kids;
00284 if (node==NULL || node->next!=NULL)
00285 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00286
00287
00288
00289 if (node->value.s==NULL)
00290 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00291
00292 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_ACTIVATE])) < 0) {
00293 return print_fifo_err();
00294 }
00295
00296 options.status = 1;
00297 options.cmd = OPT_ACTIVATE;
00298
00299 if(update_route_data(&options) < 0) {
00300 return init_mi_tree(500, "failed to update route data, see log", 37);
00301 }
00302
00303 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00304 }
00305
00306
00317 struct mi_root* add_host (struct mi_root* cmd_tree, void *param) {
00318 struct mi_node *node = NULL;
00319
00320 int ret;
00321 fifo_opt_t options;
00322
00323 if(mode != CARRIERROUTE_MODE_FILE) {
00324 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00325 }
00326
00327 node = cmd_tree->node.kids;
00328 if (node==NULL || node->next!=NULL || node->value.s==NULL) {
00329 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00330 }
00331
00332 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_ADD])) < 0) {
00333 return print_fifo_err();
00334 }
00335
00336 options.status = 1;
00337 options.cmd = OPT_ADD;
00338
00339 if(update_route_data(&options) < 0) {
00340 return init_mi_tree(500, "failed to update route data, see log", 37);
00341 }
00342
00343 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00344 }
00345
00346
00357 struct mi_root* delete_host (struct mi_root* cmd_tree, void * param) {
00358 struct mi_node *node = NULL;
00359
00360 int ret;
00361 fifo_opt_t options;
00362
00363 if(mode != CARRIERROUTE_MODE_FILE) {
00364 return init_mi_tree(400, "Not running in config file mode, cannot modify route from command line", 70);
00365 }
00366
00367 node = cmd_tree->node.kids;
00368 if (node==NULL || node->next!=NULL)
00369 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00370
00371
00372
00373 if (node->value.s==NULL)
00374 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00375
00376 if((ret = get_fifo_opts(&node->value, &options, opt_settings[OPT_REMOVE])) < 0) {
00377 return print_fifo_err();
00378 }
00379
00380 options.cmd = OPT_REMOVE;
00381
00382 if(update_route_data(&options) < 0) {
00383 return init_mi_tree(500, "failed to update route data, see log", 37);
00384 }
00385
00386 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00387 }
00388
00389
00400 static int dump_tree_recursor (struct mi_node* msg, struct dtrie_node_t *node, char *prefix) {
00401 char s[256];
00402 char *p;
00403 int i;
00404 struct route_flags *rf;
00405 struct route_rule *rr;
00406 struct route_rule_p_list * rl;
00407 double prob;
00408 struct mi_node* tmp_node = NULL;
00409
00410 strcpy (s, prefix);
00411 p = s + strlen (s);
00412 p[1] = '\0';
00413 for (i = 0; i < cr_match_mode; ++i) {
00414 if (node->child[i] != NULL) {
00415 *p = i + '0';
00416
00417 if(dump_tree_recursor (msg->next, node->child[i], s) < 0)
00418 return -1;
00419 }
00420 }
00421 *p = '\0';
00422 for (rf = (struct route_flags *)(node->data); rf != NULL; rf = rf->next) {
00423 for (rr = rf->rule_list; rr != NULL; rr = rr->next) {
00424 if(rf->dice_max){
00425 prob = (double)(rr->prob * DICE_MAX)/(double)rf->dice_max;
00426 } else {
00427 prob = rr->prob;
00428 }
00429 tmp_node = addf_mi_node_child(msg->next, 0, 0, 0, "%10s: %0.3f %%, '%.*s': %s, '%i', '%.*s', '%.*s', '%.*s'\n",
00430 strlen(prefix) > 0 ? prefix : "NULL", prob * 100, rr->host.len, rr->host.s,
00431 (rr->status ? "ON" : "OFF"), rr->strip,
00432 rr->local_prefix.len, rr->local_prefix.s,
00433 rr->local_suffix.len, rr->local_suffix.s,
00434 rr->comment.len, rr->comment.s);
00435 if(!tmp_node) return -1;
00436 if(!rr->status && rr->backup && rr->backup->rr){
00437 tmp_node = 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);
00438 if(!tmp_node) return -1;
00439 }
00440 if(rr->backed_up){
00441 rl = rr->backed_up;
00442 i=0;
00443 while(rl){
00444 if(rl->rr){
00445 tmp_node = addf_mi_node_child(msg->next, 0, 0, 0, " Rule is backup for: %.*s", rl->rr->host.len, rl->rr->host.s);
00446 if(!tmp_node) return -1;
00447 }
00448 rl = rl->next;
00449 i++;
00450 }
00451 }
00452 }
00453 }
00454 return 0;
00455 }
00456
00457
00469 static int get_fifo_opts(str * buf, fifo_opt_t * opts, unsigned int opt_set[]) {
00470 int opt_argc = 0;
00471 str opt_argv[20];
00472 int i, op = -1;
00473 unsigned int used_opts = 0;
00474 int toklen;
00475
00476 memset(opt_argv, 0, sizeof(opt_argv));
00477 memset(opts, 0, sizeof(fifo_opt_t));
00478 opts->prob = -1;
00479
00480 while((toklen = str_toklen(buf, " \t\r\n")) >=0 && opt_argc < 20) {
00481 buf->s[toklen] = '\0';
00482 opt_argv[opt_argc].len = toklen;
00483 opt_argv[opt_argc].s = buf->s;
00484 buf->s += toklen + 1;
00485 buf->len -= toklen + 1;
00486 LM_DBG("found arg[%i]: %.*s\n", opt_argc, opt_argv[opt_argc].len, opt_argv[opt_argc].s);
00487 opt_argc++;
00488 }
00489 for (i=0; i<opt_argc; i++) {
00490 LM_DBG("token %.*s", opt_argv[i].len, opt_argv[i].s);
00491 if (opt_argv[i].len >= 1) {
00492 switch(*opt_argv[i].s) {
00493 case '-': switch(opt_argv[i].s[1]) {
00494 case OPT_DOMAIN_CHR:
00495 op = OPT_DOMAIN;
00496 used_opts |= O_DOMAIN;
00497 break;
00498 case OPT_PREFIX_CHR:
00499 op = OPT_PREFIX;
00500 used_opts |= O_PREFIX;
00501 break;
00502 case OPT_HOST_CHR:
00503 op = OPT_HOST;
00504 used_opts |= O_HOST;
00505 break;
00506 case OPT_NEW_TARGET_CHR:
00507 op = OPT_NEW_TARGET;
00508 used_opts |= O_NEW_TARGET;
00509 break;
00510 case OPT_PROB_CHR:
00511 op = OPT_PROB;
00512 used_opts |= O_PROB;
00513 break;
00514 case OPT_R_PREFIX_CHR:
00515 op = OPT_R_PREFIX;
00516 used_opts |= O_R_PREFIX;
00517 break;
00518 case OPT_R_SUFFIX_CHR:
00519 op = OPT_R_SUFFIX;
00520 used_opts |= O_R_SUFFIX;
00521 break;
00522 case OPT_HASH_INDEX_CHR:
00523 op = OPT_HASH_INDEX;
00524 used_opts |= O_H_INDEX;
00525 break;
00526 case OPT_HELP_CHR:
00527 FIFO_ERR(E_HELP);
00528 return -1;
00529 default: {
00530 FIFO_ERR(E_WRONGOPT);
00531 LM_DBG("Unknown option: %.*s\n", opt_argv[i].len, opt_argv[i].s);
00532 return -1;
00533 }
00534 }
00535 break;
00536 default: switch(op) {
00537 case OPT_DOMAIN:
00538 opts->domain = opt_argv[i];
00539 op = -1;
00540 break;
00541 case OPT_PREFIX:
00542 if (str_strcasecmp(&opt_argv[i], &CR_EMPTY_PREFIX) == 0) {
00543 opts->prefix.s = NULL;
00544 opts->prefix.len = 0;
00545 } else {
00546 opts->prefix = opt_argv[i];
00547 }
00548 op = -1;
00549 break;
00550 case OPT_HOST:
00551 opts->host = opt_argv[i];
00552 op = -1;
00553 break;
00554 case OPT_NEW_TARGET:
00555 opts->new_host = opt_argv[i];
00556 op = -1;
00557 break;
00558 case OPT_PROB:
00559 opts->prob = strtod(opt_argv[i].s, NULL);
00560 op = -1;
00561 break;
00562 case OPT_R_PREFIX:
00563 opts->rewrite_prefix = opt_argv[i];
00564 op = -1;
00565 break;
00566 case OPT_STRIP:
00567 str2sint(&opt_argv[i], &opts->strip);
00568 op = -1;
00569 break;
00570 case OPT_R_SUFFIX:
00571 opts->rewrite_suffix = opt_argv[i];
00572 op = -1;
00573 break;
00574 case OPT_HASH_INDEX:
00575 str2sint(&opt_argv[i], &opts->hash_index);
00576 op = -1;
00577 break;
00578 default: {
00579 LM_DBG("No option given\n");
00580 FIFO_ERR(E_NOOPT);
00581 return -1;
00582 }
00583 }
00584 break;
00585 }
00586 }
00587 }
00588 if((used_opts & opt_set[OPT_INVALID]) != 0) {
00589 LM_DBG("invalid option\n");
00590 FIFO_ERR(E_INVALIDOPT);
00591 return -1;
00592 }
00593 if((used_opts & opt_set[OPT_MANDATORY]) != opt_set[OPT_MANDATORY]) {
00594 LM_DBG("option missing\n");
00595 FIFO_ERR(E_MISSOPT);
00596 return -1;
00597 }
00598 return 0;
00599 }
00600
00601
00612 static int update_route_data(fifo_opt_t * opts) {
00613 struct route_data_t * rd;
00614 int i,j;
00615 int domain_id;
00616 str tmp_domain;
00617 str tmp_prefix;
00618 str tmp_host;
00619 str tmp_rewrite_prefix;
00620 str tmp_rewrite_suffix;
00621 str tmp_comment = str_init("");
00622
00623 if ((rd = shm_malloc(sizeof(struct route_data_t))) == NULL) {
00624 SHM_MEM_ERROR;
00625 return -1;
00626 }
00627 memset(rd, 0, sizeof(struct route_data_t));
00628 if (load_config(rd) < 0) {
00629 LM_ERR("could not load config");
00630 FIFO_ERR(E_LOADCONF);
00631 return -1;
00632 }
00633
00634 if (rule_fixup(rd) < 0) {
00635 LM_ERR("could not fixup rules");
00636 FIFO_ERR(E_RULEFIXUP);
00637 return -1;
00638 }
00639 updated = 0;
00640
00641 if (opts->cmd == OPT_ADD) {
00642 tmp_domain=opts->domain;
00643 tmp_prefix=opts->prefix;
00644 tmp_host=opts->host;
00645 tmp_rewrite_prefix=opts->rewrite_prefix;
00646 tmp_rewrite_suffix=opts->rewrite_suffix;
00647 if (tmp_domain.s==NULL) {
00648 tmp_domain.s="";
00649 tmp_domain.len=0;
00650 }
00651 if (tmp_prefix.s==NULL) {
00652 tmp_prefix.s="";
00653 tmp_prefix.len=0;
00654 }
00655 if (tmp_host.s==NULL) {
00656 tmp_host.s="";
00657 tmp_host.len=0;
00658 }
00659 if (tmp_rewrite_prefix.s==NULL) {
00660 tmp_rewrite_prefix.s="";
00661 tmp_rewrite_prefix.len=0;
00662 }
00663 if (tmp_rewrite_suffix.s==NULL) {
00664 tmp_rewrite_suffix.s="";
00665 tmp_rewrite_suffix.len=0;
00666 }
00667
00668 domain_id = map_name2id(rd->domain_map, rd->domain_num, &tmp_domain);
00669 if (domain_id < 0) {
00670 LM_ERR("cannot find id for domain '%.*s'", tmp_domain.len, tmp_domain.s);
00671 goto errout;
00672 }
00673
00674 if (add_route(rd, 1, domain_id, &tmp_prefix, 0, 0, 0, opts->prob,
00675 &tmp_host, opts->strip, &tmp_rewrite_prefix, &tmp_rewrite_suffix,
00676 opts->status, opts->hash_index, -1, NULL, &tmp_comment) < 0) {
00677 goto errout;
00678 }
00679 updated = 1;
00680 if (rule_fixup(rd) < 0) {
00681 LM_ERR("could not fixup rules after route appending");
00682 FIFO_ERR(E_RULEFIXUP);
00683 goto errout;
00684 }
00685 } else {
00686 for (i=0; i<rd->carrier_num; i++) {
00687 if(rd->carriers[i]){
00688 for (j=0; j<rd->carriers[i]->domain_num; j++) {
00689 if (rd->carriers[i]->domains[j] && rd->carriers[i]->domains[j]->tree) {
00690 if (update_route_data_recursor(rd->carriers[i]->domains[j]->tree, rd->carriers[i]->domains[j]->name, opts) < 0) {
00691 goto errout;
00692 }
00693 }
00694 }
00695 }
00696 }
00697 }
00698
00699 if(!updated){
00700 LM_ERR("no match for update found");
00701 FIFO_ERR(E_NOUPDATE);
00702 goto errout;
00703 }
00704
00705 if (save_config(rd) < 0) {
00706 LM_ERR("could not save config");
00707 FIFO_ERR(E_SAVECONF);
00708 goto errout;
00709 }
00710
00711 if (reload_route_data() == -1) {
00712 LM_ERR("could not reload route data");
00713 FIFO_ERR(E_LOADCONF);
00714 goto errout;
00715 }
00716
00717 clear_route_data(rd);
00718 return 0;
00719 errout:
00720 clear_route_data(rd);
00721 return -1;
00722 }
00723
00724
00738 static int update_route_data_recursor(struct dtrie_node_t *node, str * act_domain, fifo_opt_t * opts) {
00739 int i, hash = 0;
00740 struct route_rule * rr, * prev = NULL, * tmp, * backup;
00741 struct route_flags *rf;
00742
00743 rf = (struct route_flags *)(node->data);
00744 if (rf && rf->rule_list) {
00745 rr = rf->rule_list;
00746 while (rr) {
00747 if ((!opts->domain.len || (strncmp(opts->domain.s, OPT_STAR, strlen(OPT_STAR)) == 0)
00748 || ((opts->domain.len == act_domain->len) && (strncmp(opts->domain.s, act_domain->s, opts->domain.len) == 0)))
00749 && ((!opts->prefix.len && !rr->prefix.len) || (strncmp(opts->prefix.s, OPT_STAR, strlen(OPT_STAR)) == 0)
00750 || (rr->prefix.len == opts->prefix.len && (strncmp(opts->prefix.s, rr->prefix.s, opts->prefix.len) == 0)))
00751 && ((!opts->host.len && !rr->host.s) || (strncmp(opts->host.s, OPT_STAR, strlen(OPT_STAR)) == 0)
00752 || ((strncmp(rr->host.s, opts->host.s, opts->host.len) == 0) && (rr->host.len == opts->host.len)))
00753 && ((opts->prob < 0) || (opts->prob == rr->prob))) {
00754 switch (opts->cmd) {
00755 case OPT_REPLACE:
00756 LM_INFO("replace host %.*s with %.*s\n", rr->host.len, rr->host.s, opts->new_host.len, opts->new_host.s);
00757 if (rr->host.s) {
00758 shm_free(rr->host.s);
00759 }
00760 if (opts->new_host.len) {
00761 if ((rr->host.s = shm_malloc(opts->new_host.len + 1)) == NULL) {
00762 SHM_MEM_ERROR;
00763 FIFO_ERR(E_NOMEM);
00764 return -1;
00765 }
00766 memmove(rr->host.s, opts->new_host.s, opts->new_host.len + 1);
00767 rr->host.len = opts->new_host.len;
00768 rr->host.s[rr->host.len] = '\0';
00769 } else {
00770 rr->host.len = 0;
00771 }
00772 rr->status = opts->status;
00773 prev = rr;
00774 rr = rr->next;
00775 updated = 1;
00776 break;
00777 case OPT_DEACTIVATE:
00778 if (remove_backed_up(rr) < 0) {
00779 LM_ERR("could not reset backup hosts\n");
00780 FIFO_ERR(E_RESET);
00781 return -1;
00782 }
00783 if (opts->new_host.len > 0) {
00784 LM_INFO("deactivating host %.*s\n", rr->host.len, rr->host.s);
00785 if ( opts->new_host.s && (strcmp(opts->new_host.s, rr->host.s) == 0)){
00786 LM_ERR("Backup host the same as initial host %.*s",rr->host.len, rr->host.s);
00787 FIFO_ERR(E_WRONGOPT);
00788 return -1;
00789 }
00790 if (opts->new_host.len == 1 && opts->new_host.s[0] == 'a') {
00791 if ((backup = find_auto_backup(rf, rr)) == NULL) {
00792 LM_ERR("didn't find auto backup route\n");
00793 FIFO_ERR(E_NOAUTOBACKUP);
00794 return -1;
00795 }
00796 } else {
00797 errno = 0;
00798 hash = strtol(opts->new_host.s, NULL, 10);
00799 if (errno == EINVAL || errno == ERANGE) {
00800 if ((backup = find_rule_by_hash(rf, hash)) == NULL) {
00801 LM_ERR("didn't find given backup route (hash %i)\n", hash);
00802 FIFO_ERR(E_NOHASHBACKUP);
00803 return -1;
00804 }
00805 } else {
00806 if ((backup = find_rule_by_host(rf, &opts->new_host)) == NULL) {
00807 LM_ERR("didn't find given backup route (host %.*s)\n", opts->new_host.len, opts->new_host.s);
00808 FIFO_ERR(E_NOHOSTBACKUP);
00809 return -1;
00810 }
00811 }
00812 }
00813 if (add_backup_rule(rr, backup) < 0) {
00814 LM_ERR("couldn't set backup route\n");
00815 FIFO_ERR(E_ADDBACKUP);
00816 return -1;
00817 }
00818 } else {
00819 if(rr->backed_up){
00820 LM_ERR("can't deactivate route without backup route because it is backup route for others\n");
00821 FIFO_ERR(E_DELBACKUP);
00822 return -1;
00823 }
00824 }
00825 rr->status = opts->status;
00826 prev = rr;
00827 rr = rr->next;
00828 updated = 1;
00829 break;
00830 case OPT_ACTIVATE:
00831 LM_INFO("activating host %.*s\n", rr->host.len, rr->host.s);
00832 if (remove_backed_up(rr) < 0) {
00833 LM_ERR("could not reset backup hosts\n");
00834 FIFO_ERR(E_RESET);
00835 return -1;
00836 }
00837 rr->status = opts->status;
00838 prev = rr;
00839 rr = rr->next;
00840 updated = 1;
00841 break;
00842 case OPT_REMOVE:
00843 LM_INFO("removing host %.*s\n", rr->host.len, rr->host.s);
00844 if (rr->backed_up){
00845 LM_ERR("cannot remove host %.*s which is backup for other hosts\n", rr->host.len, rr->host.s);
00846 FIFO_ERR(E_DELBACKUP);
00847 return -1;
00848 }
00849 if (remove_backed_up(rr) < 0) {
00850 LM_ERR("could not reset backup hosts\n");
00851 FIFO_ERR(E_RESET);
00852 return -1;
00853 }
00854 if (prev) {
00855 prev->next = rr->next;
00856 tmp = rr;
00857 rr = prev;
00858 destroy_route_rule(tmp);
00859 prev = rr;
00860 rr = rr->next;
00861 } else {
00862 rf->rule_list = rr->next;
00863 tmp = rr;
00864 rr = rf->rule_list;
00865 destroy_route_rule(tmp);
00866 }
00867 rf->rule_num--;
00868 rf->max_targets--;
00869 updated = 1;
00870 break;
00871 default:
00872 rr = rr->next;
00873 break;
00874 }
00875 } else {
00876 prev = rr;
00877 rr = rr->next;
00878 }
00879 }
00880 }
00881 for (i=0; i<cr_match_mode; i++) {
00882 if (node->child[i]) {
00883 if (update_route_data_recursor(node->child[i], act_domain, opts) < 0) {
00884 return -1;
00885 }
00886 }
00887 }
00888 return 0;
00889 }
00890
00891
00895 static struct mi_root* print_replace_help(void) {
00896 struct mi_root* rpl_tree;
00897 struct mi_node* node;
00898
00899 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00900 if(rpl_tree == NULL)
00901 return 0;
00902
00903 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "carrierroute options usage:");
00904 if(node == NULL)
00905 goto error;
00906 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c searched/new remote host\n", OPT_HOST_CHR);
00907 if(node == NULL)
00908 goto error;
00909 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c replacement/backup host", OPT_NEW_TARGET_CHR);
00910 if(node == NULL)
00911 goto error;
00912 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: searched/new domain", OPT_DOMAIN_CHR);
00913 if(node == NULL)
00914 goto error;
00915 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: searched/new prefix", OPT_PREFIX_CHR);
00916 if(node == NULL)
00917 goto error;
00918 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: searched/new weight (0..1)", OPT_PROB_CHR);
00919 if(node == NULL)
00920 goto error;
00921 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: new rewrite prefix", OPT_R_PREFIX_CHR);
00922 if(node == NULL)
00923 goto error;
00924 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: new rewrite suffix", OPT_R_SUFFIX_CHR);
00925 if(node == NULL)
00926 goto error;
00927 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: new hash index", OPT_HASH_INDEX_CHR);
00928 if(node == NULL)
00929 goto error;
00930 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "\t-%c: prints this help", OPT_HELP_CHR);
00931 if(node == NULL)
00932 goto error;
00933
00934 return rpl_tree;
00935
00936 error:
00937 free_mi_tree(rpl_tree);
00938 return 0;
00939 }
00940
00941
00946 struct mi_root* print_fifo_err(void) {
00947 struct mi_root* rpl_tree;
00948
00949 switch (fifo_err) {
00950 case E_MISC:
00951 rpl_tree = init_mi_tree( 400, "An error occured", 17);
00952 if(rpl_tree == NULL)
00953 return 0;
00954 break;
00955 case E_NOOPT:
00956 rpl_tree = init_mi_tree( 400, "No option given", 16);
00957 if(rpl_tree == NULL)
00958 return 0;
00959 break;
00960 case E_WRONGOPT:
00961 rpl_tree = init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00962 if(rpl_tree == NULL)
00963 return 0;
00964 break;
00965 case E_NOMEM:
00966 rpl_tree = init_mi_tree( 500, "Out of memory", 14);
00967 if(rpl_tree == NULL)
00968 return 0;
00969 break;
00970 case E_RESET:
00971 rpl_tree = init_mi_tree( 500, "Could not reset backup routes", 30);
00972 if(rpl_tree == NULL)
00973 return 0;
00974 break;
00975 case E_NOAUTOBACKUP:
00976 rpl_tree = init_mi_tree( 400, "No auto backup route found", 27);
00977 if(rpl_tree == NULL)
00978 return 0;
00979 break;
00980 case E_NOHASHBACKUP:
00981 rpl_tree = init_mi_tree( 400, "No backup route for given hash found", 37);
00982 if(rpl_tree == NULL)
00983 return 0;
00984 break;
00985 case E_NOHOSTBACKUP:
00986 rpl_tree = init_mi_tree( 400, "No backup route for given host found", 37);
00987 if(rpl_tree == NULL)
00988 return 0;
00989 break;
00990 case E_ADDBACKUP:
00991 rpl_tree = init_mi_tree( 500, "Could not set backup route", 27);
00992 if(rpl_tree == NULL)
00993 return 0;
00994 break;
00995 case E_DELBACKUP:
00996 rpl_tree = init_mi_tree( 400, "Could not delete or deactivate route, it is backup for other routes", 68);
00997 if(rpl_tree == NULL)
00998 return 0;
00999 break;
01000 case E_LOADCONF:
01001 rpl_tree = init_mi_tree( 500, "Could not load config from file", 32);
01002 if(rpl_tree == NULL)
01003 return 0;
01004 break;
01005 case E_SAVECONF:
01006 rpl_tree = init_mi_tree( 500, "Could not save config", 22);
01007 if(rpl_tree == NULL)
01008 return 0;
01009 break;
01010 case E_INVALIDOPT:
01011 rpl_tree = init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
01012 if(rpl_tree == NULL)
01013 return 0;
01014 break;
01015 case E_MISSOPT:
01016 rpl_tree = init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
01017 if(rpl_tree == NULL)
01018 return 0;
01019 break;
01020 case E_RULEFIXUP:
01021 rpl_tree = init_mi_tree( 500, "Could not fixup rules", 22);
01022 if(rpl_tree == NULL)
01023 return 0;
01024 break;
01025 case E_NOUPDATE:
01026 rpl_tree = init_mi_tree( 500, "No match for update found", 26);
01027 if(rpl_tree == NULL)
01028 return 0;
01029 break;
01030 case E_HELP:
01031 return print_replace_help();
01032 break;
01033 default:
01034 rpl_tree = init_mi_tree( 500, "An error occured", 17);
01035 if(rpl_tree == NULL)
01036 return 0;
01037 break;
01038 }
01039 return rpl_tree;
01040 }