00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #include "../../ut.h"
00031 #include "cr_rule.h"
00032
00033
00059 int add_route_rule(struct route_flags *rf, const str * prefix,
00060 int max_targets, double prob, const str * rewrite_hostpart, int strip,
00061 const str * rewrite_local_prefix, const str * rewrite_local_suffix,
00062 int status, int hash_index, int backup, int * backed_up,
00063 const str * comment) {
00064 struct route_rule * shm_rr, * prev = NULL, * tmp = NULL;
00065 struct route_rule_p_list * t_rl;
00066 int * t_bu;
00067
00068 if (max_targets) {
00069 rf->max_targets = max_targets;
00070 } else {
00071 rf->max_targets++;
00072 }
00073
00074 if ((shm_rr = shm_malloc(sizeof(struct route_rule))) == NULL) {
00075 SHM_MEM_ERROR;
00076 return -1;
00077 }
00078 memset(shm_rr, 0, sizeof(struct route_rule));
00079
00080 if (shm_str_dup(&shm_rr->host, rewrite_hostpart) != 0) {
00081 goto mem_error;
00082 }
00083
00084 if (shm_str_dup(&shm_rr->prefix, prefix) != 0) {
00085 goto mem_error;
00086 }
00087
00088 shm_rr->strip = strip;
00089
00090 if (shm_str_dup(&shm_rr->local_prefix, rewrite_local_prefix) != 0) {
00091 goto mem_error;
00092 }
00093
00094 if (shm_str_dup(&shm_rr->local_suffix, rewrite_local_suffix) != 0) {
00095 goto mem_error;
00096 }
00097
00098 if (shm_str_dup(&shm_rr->comment, comment) != 0) {
00099 goto mem_error;
00100 }
00101
00102 shm_rr->status = status;
00103 shm_rr->hash_index = hash_index;
00104 shm_rr->orig_prob = prob;
00105 if (shm_rr->status || backup != -1) {
00106 shm_rr->prob = prob;
00107 } else {
00108 shm_rr->prob = 0;
00109 }
00110 if (backup >= 0) {
00111 if ((shm_rr->backup = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) {
00112 goto mem_error;
00113 }
00114 memset(shm_rr->backup, 0, sizeof(struct route_rule_p_list));
00115 shm_rr->backup->hash_index = backup;
00116 }
00117 shm_rr->backed_up = NULL;
00118 t_bu = backed_up;
00119 if(!backed_up){
00120 LM_INFO("no backed up rules\n");
00121 }
00122 while (t_bu && *t_bu != -1) {
00123 if ((t_rl = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) {
00124 goto mem_error;
00125 }
00126 memset(t_rl, 0, sizeof(struct route_rule_p_list));
00127 t_rl->hash_index = *t_bu;
00128 t_rl->next = shm_rr->backed_up;
00129 shm_rr->backed_up = t_rl;
00130 t_bu++;
00131 }
00132
00133
00134 tmp = rf->rule_list;
00135 while(tmp && tmp->prob == 0){
00136 prev = tmp;
00137 tmp = tmp->next;
00138 }
00139
00140 while(tmp && (tmp->hash_index < shm_rr->hash_index)){
00141 prev = tmp;
00142 tmp = tmp->next;
00143 }
00144 if(prev){
00145 shm_rr->next = prev->next;
00146 prev->next = shm_rr;
00147 } else {
00148 shm_rr->next = rf->rule_list;
00149 rf->rule_list = shm_rr;
00150 }
00151
00152 return 0;
00153
00154 mem_error:
00155 SHM_MEM_ERROR;
00156 destroy_route_rule(shm_rr);
00157 return -1;
00158 }
00159
00160
00166 void destroy_route_rule(struct route_rule * rr) {
00167 struct route_rule_p_list * t_rl;
00168 if (rr->host.s) {
00169 shm_free(rr->host.s);
00170 }
00171 if (rr->local_prefix.s) {
00172 shm_free(rr->local_prefix.s);
00173 }
00174 if (rr->local_suffix.s) {
00175 shm_free(rr->local_suffix.s);
00176 }
00177 if (rr->comment.s) {
00178 shm_free(rr->comment.s);
00179 }
00180 if (rr->prefix.s) {
00181 shm_free(rr->prefix.s);
00182 }
00183 if(rr->backup){
00184 shm_free(rr->backup);
00185 }
00186 while(rr->backed_up){
00187 t_rl = rr->backed_up->next;
00188 shm_free(rr->backed_up);
00189 rr->backed_up = t_rl;
00190 }
00191 shm_free(rr);
00192 return;
00193 }
00194
00195
00206 struct route_flags * add_route_flags(struct route_flags **rf_head, const flag_t flags, const flag_t mask)
00207 {
00208 struct route_flags *shm_rf;
00209 struct route_flags *prev_rf, *tmp_rf;
00210 prev_rf = tmp_rf = NULL;
00211
00212 if (rf_head) {
00213
00214 for (tmp_rf=*rf_head; tmp_rf!=NULL; tmp_rf=tmp_rf->next) {
00215 if ((tmp_rf->flags == flags) && (tmp_rf->mask == mask)) return tmp_rf;
00216 }
00217
00218
00219 for (tmp_rf=*rf_head; tmp_rf!=NULL; tmp_rf=tmp_rf->next) {
00220 if (tmp_rf->mask < mask) break;
00221 prev_rf=tmp_rf;
00222 }
00223 }
00224
00225 if ((shm_rf = shm_malloc(sizeof(struct route_flags))) == NULL) {
00226 SHM_MEM_ERROR;
00227 return NULL;
00228 }
00229 memset(shm_rf, 0, sizeof(struct route_flags));
00230
00231 shm_rf->flags=flags;
00232 shm_rf->mask=mask;
00233 shm_rf->next=tmp_rf;
00234
00235 if (prev_rf) {
00236 prev_rf->next = shm_rf;
00237 }
00238 else {
00239 if (rf_head) *rf_head=shm_rf;
00240 }
00241
00242 return shm_rf;
00243 }
00244
00245
00251 void destroy_route_flags(struct route_flags *rf) {
00252 struct route_rule *rs, *rs_tmp;
00253
00254 if (rf->rules) {
00255 shm_free(rf->rules);
00256 }
00257 rs = rf->rule_list;
00258 while (rs != NULL) {
00259 rs_tmp = rs->next;
00260 destroy_route_rule(rs);
00261 rs = rs_tmp;
00262 }
00263 shm_free(rf);
00264 }
00265
00266
00277 static int failure_rule_prio_cmp(struct failure_route_rule *frr1, struct failure_route_rule *frr2) {
00278 int n1, n2, i;
00279
00280
00281 if ((frr1->host.len == 0) && (frr2->host.len > 0)) {
00282
00283 return 1;
00284 }
00285 else if ((frr1->host.len > 0) && (frr2->host.len == 0)) {
00286
00287 return -1;
00288 }
00289 else {
00290
00291 n1=0;
00292 n2=0;
00293 for (i=0; i < frr1->reply_code.len; i++) {
00294 if (frr1->reply_code.s[i]=='.') n1++;
00295 }
00296 for (i=0; i < frr2->reply_code.len; i++) {
00297 if (frr2->reply_code.s[i]=='.') n2++;
00298 }
00299 if (n1 < n2) {
00300
00301 return -1;
00302 }
00303 else if (n1 > n2) {
00304
00305 return 1;
00306 }
00307 else {
00308
00309 if (frr1->mask > frr2->mask) {
00310 return -1;
00311 }
00312 else if (frr1->mask < frr2->mask) {
00313 return 1;
00314 }
00315 }
00316 }
00317
00318 return 0;
00319 }
00320
00321
00339 struct failure_route_rule *add_failure_route_rule(struct failure_route_rule **frr_head,
00340 const str * prefix, const str * host, const str * reply_code,
00341 flag_t flags, flag_t mask, const int next_domain, const str * comment) {
00342 struct failure_route_rule *shm_frr, *frr, *prev;
00343 frr = prev = NULL;
00344
00345 if ((shm_frr = shm_malloc(sizeof(struct failure_route_rule))) == NULL) {
00346 SHM_MEM_ERROR;
00347 return NULL;
00348 }
00349 memset(shm_frr, 0, sizeof(struct failure_route_rule));
00350
00351 if (shm_str_dup(&shm_frr->host, host) != 0) {
00352 goto mem_error;
00353 }
00354
00355 if (shm_str_dup(&shm_frr->reply_code, reply_code) != 0) {
00356 goto mem_error;
00357 }
00358
00359 shm_frr->flags = flags;
00360 shm_frr->mask = mask;
00361 shm_frr->next_domain = next_domain;
00362
00363 if (shm_str_dup(&shm_frr->comment, comment) != 0) {
00364 goto mem_error;
00365 }
00366
00367
00368 if (frr_head) {
00369 frr=*frr_head;
00370 prev=NULL;
00371 while ((frr != NULL) && (failure_rule_prio_cmp(shm_frr, frr) > 0)) {
00372 prev=frr;
00373 frr=frr->next;
00374 }
00375 }
00376
00377 shm_frr->next = frr;
00378
00379 if(prev){
00380 prev->next = shm_frr;
00381 }
00382 else {
00383 if (frr_head) *frr_head=shm_frr;
00384 }
00385
00386 return shm_frr;
00387
00388 mem_error:
00389 SHM_MEM_ERROR;
00390 destroy_failure_route_rule(shm_frr);
00391 return NULL;
00392 }
00393
00394
00400 void destroy_failure_route_rule(struct failure_route_rule * frr) {
00401 if (frr->host.s) {
00402 shm_free(frr->host.s);
00403 }
00404 if (frr->comment.s) {
00405 shm_free(frr->comment.s);
00406 }
00407 if (frr->prefix.s) {
00408 shm_free(frr->prefix.s);
00409 }
00410 if (frr->reply_code.s) {
00411 shm_free(frr->reply_code.s);
00412 }
00413 shm_free(frr);
00414 return;
00415 }
00416
00417
00418 struct route_rule * find_rule_by_hash(struct route_flags * rf, int hash){
00419 struct route_rule * rr;
00420 rr = rf->rule_list;
00421 while(rr){
00422 if(rr->hash_index == hash){
00423 return rr;
00424 }
00425 rr = rr->next;
00426 }
00427 return NULL;
00428 }
00429
00430
00431 struct route_rule * find_rule_by_host(struct route_flags * rf, str * host){
00432 struct route_rule * rr;
00433 rr = rf->rule_list;
00434 while(rr){
00435 if(str_strcmp(&(rr->host), host) == 0){
00436 return rr;
00437 }
00438 rr = rr->next;
00439 }
00440 return NULL;
00441 }
00442
00443
00444 int add_backup_rule(struct route_rule * rule, struct route_rule * backup){
00445 struct route_rule_p_list * tmp = NULL;
00446 if(!backup->status){
00447 LM_ERR("desired backup route is inactive\n");
00448 return -1;
00449 }
00450 if((tmp = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) {
00451 SHM_MEM_ERROR;
00452 return -1;
00453 }
00454 memset(tmp, 0, sizeof(struct route_rule_p_list));
00455 tmp->hash_index = rule->hash_index;
00456 tmp->rr = rule;
00457 tmp->next = backup->backed_up;
00458 backup->backed_up = tmp;
00459
00460 tmp = NULL;
00461 if((tmp = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) {
00462 SHM_MEM_ERROR;
00463 return -1;
00464 }
00465 memset(tmp, 0, sizeof(struct route_rule_p_list));
00466 tmp->hash_index = backup->hash_index;
00467 tmp->rr = backup;
00468 rule->backup = tmp;
00469
00470 if(rule->backed_up){
00471 tmp = rule->backed_up;
00472 while(tmp->next) {
00473 tmp = tmp->next;
00474 }
00475 tmp->next = backup->backed_up;
00476 backup->backed_up = rule->backed_up;
00477 rule->backed_up = NULL;
00478 }
00479 tmp = rule->backup->rr->backed_up;
00480 while(tmp) {
00481 tmp->rr->backup->hash_index = rule->backup->hash_index;
00482 tmp->rr->backup->rr = rule->backup->rr;
00483 tmp = tmp->next;
00484 }
00485 return 0;
00486 }
00487
00488
00489 int remove_backed_up(struct route_rule * rule){
00490 struct route_rule_p_list * rl, * prev = NULL;
00491 if(rule->backup) {
00492 if(rule->backup->rr) {
00493 rl = rule->backup->rr->backed_up;
00494 while(rl) {
00495 if(rl->hash_index == rule->hash_index) {
00496 if(prev) {
00497 prev->next = rl->next;
00498 } else {
00499 rule->backup->rr->backed_up = rl->next;
00500 }
00501 shm_free(rl);
00502 shm_free(rule->backup);
00503 rule->backup = NULL;
00504 return 0;
00505 }
00506 prev = rl;
00507 rl = rl->next;
00508 }
00509 }
00510 return -1;
00511 }
00512 return 0;
00513 }
00514
00515
00516 struct route_rule * find_auto_backup(struct route_flags * rf, struct route_rule * rule){
00517 struct route_rule * rr;
00518 rr = rf->rule_list;
00519 while(rr){
00520 if(!rr->backed_up && (rr->hash_index != rule->hash_index) && rr->status){
00521 return rr;
00522 }
00523 rr = rr->next;
00524 }
00525 return NULL;
00526 }