00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #include <confuse.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <unistd.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <stdarg.h>
00037 #include "../../mem/shm_mem.h"
00038 #include "../../mem/mem.h"
00039 #include "../../ut.h"
00040 #include "cr_config.h"
00041 #include "carrierroute.h"
00042 #include "cr_rule.h"
00043 #include "cr_domain.h"
00044 #include "cr_carrier.h"
00045
00046
00054 static void conf_error(cfg_t *cfg, const char * fmt, va_list ap) {
00055 int ret;
00056 static char buf[1024];
00057
00058 ret = vsnprintf(buf, sizeof(buf), fmt, ap);
00059 if (ret < 0 || ret >= sizeof(buf)) {
00060 LM_ERR("could not print error message\n");
00061 } else {
00062
00063
00064 LM_GEN1(L_ERR, "%s", buf);
00065 }
00066 }
00067
00068
00074 static cfg_t * parse_config(void) {
00075 cfg_t * cfg = NULL;
00076
00077 cfg_opt_t target_opts[] = {
00078 CFG_STR("comment", 0, CFGF_NONE),
00079 CFG_INT("strip", 0, CFGF_NONE),
00080 CFG_STR("rewrite_prefix", 0, CFGF_NONE),
00081 CFG_FLOAT("prob", 0, CFGF_NONE),
00082 CFG_INT("hash_index", 0, CFGF_NONE),
00083 CFG_STR("rewrite_suffix", 0, CFGF_NONE),
00084 CFG_INT("status", 1, CFGF_NONE),
00085 CFG_INT_LIST("backed_up", NULL, CFGF_NONE),
00086 CFG_INT("backup", -1, CFGF_NONE),
00087 CFG_END()
00088 };
00089
00090 cfg_opt_t prefix_opts[] = {
00091 CFG_SEC("target", target_opts, CFGF_MULTI | CFGF_TITLE),
00092 CFG_INT("max_targets", -1, CFGF_NONE),
00093 CFG_END()
00094 };
00095
00096 cfg_opt_t domain_opts[] = {
00097 CFG_SEC("prefix", prefix_opts, CFGF_MULTI | CFGF_TITLE),
00098 CFG_END()
00099 };
00100
00101 cfg_opt_t opts[] = {
00102 CFG_SEC("domain", domain_opts, CFGF_MULTI | CFGF_TITLE),
00103 CFG_END()
00104 };
00105
00106 cfg = cfg_init(opts, CFGF_NONE);
00107 if (cfg == NULL) {
00108 LM_ERR("could not initialize configuration\n");
00109 return NULL;
00110 }
00111
00112 cfg_set_error_function(cfg, conf_error);
00113
00114 switch (cfg_parse(cfg, config_file)) {
00115 case CFG_FILE_ERROR: LM_ERR("file not found: %s\n", config_file);
00116 return NULL;
00117 case CFG_PARSE_ERROR: LM_ERR("error while parsing %s in line %i, section %s\n",
00118 cfg->filename, cfg->line, cfg->name);
00119 return NULL;
00120 case CFG_SUCCESS: break;
00121 }
00122 return cfg;
00123 }
00124
00125
00126 static int backup_config(void) {
00127 FILE * from, * to;
00128 char * backup_file, ch;
00129 LM_INFO("start configuration backup\n");
00130 if((backup_file = pkg_malloc(strlen(config_file) + strlen (".bak") + 1)) == NULL){
00131 PKG_MEM_ERROR;
00132 return -1;
00133 }
00134 if(!strcpy(backup_file, config_file)){
00135 LM_ERR("can't copy filename\n");
00136 goto errout;
00137 }
00138 if(!strcat(backup_file, ".bak")){
00139 LM_ERR("can't attach suffix\n");
00140 goto errout;
00141 }
00142
00143 if ((from = fopen(config_file, "rb"))==NULL) {
00144 LM_ERR("Cannot open source file.\n");
00145 goto errout;
00146 }
00147
00148
00149 if ((to = fopen(backup_file, "wb"))==NULL) {
00150 LM_ERR("Cannot open destination file.\n");
00151 fclose(from);
00152 goto errout;
00153 }
00154
00155
00156 while (!feof(from)) {
00157 ch = fgetc(from);
00158 if (ferror(from)) {
00159 LM_ERR("Error reading source file.\n");
00160 goto errclose;
00161 }
00162 if (!feof(from)) fputc(ch, to);
00163 if (ferror(to)) {
00164 LM_ERR("Error writing destination file.\n");
00165 goto errclose;
00166 }
00167 }
00168
00169 if (fclose(from)==EOF) {
00170 LM_ERR("Error closing source file.\n");
00171 fclose(to);
00172 goto errout;
00173 }
00174
00175 if (fclose(to)==EOF) {
00176 LM_ERR("Error closing destination file.\n");
00177 goto errout;
00178 }
00179 LM_NOTICE("backup written to %s\n", backup_file);
00180 pkg_free(backup_file);
00181 return 0;
00182 errclose:
00183
00184 fclose(from);
00185 fclose(to);
00186 errout:
00187 pkg_free(backup_file);
00188 return -1;
00189 }
00190
00191
00202 int load_config(struct route_data_t * rd) {
00203 cfg_t * cfg = NULL;
00204 int m, o, i, j, k,l, status, hash_index, max_targets, strip;
00205 cfg_t * d, * p, * t;
00206 struct carrier_data_t * tmp_carrier_data;
00207 int domain_id;
00208 str domain, prefix, rewrite_prefix, rewrite_suffix, rewrite_host, comment;
00209 double prob;
00210 int * backed_up = NULL;
00211 int backed_up_size, backup;
00212 backed_up_size = backup = 0;
00213
00214 if ((cfg = parse_config()) == NULL) {
00215 return -1;
00216 }
00217
00218 rd->carrier_num = 1;
00219 rd->first_empty_carrier = 0;
00220 rd->domain_num = cfg_size(cfg, "domain");
00221
00222 if ((rd->carriers = shm_malloc(sizeof(struct carrier_data_t *))) == NULL) {
00223 SHM_MEM_ERROR;
00224 return -1;
00225 }
00226 memset(rd->carriers, 0, sizeof(struct carrier_data_t *));
00227
00228
00229 if ((rd->carrier_map = shm_malloc(sizeof(struct name_map_t))) == NULL) {
00230 SHM_MEM_ERROR;
00231 return -1;
00232 }
00233 memset(rd->carrier_map, 0, sizeof(struct name_map_t));
00234 rd->carrier_map[0].id = 1;
00235 rd->carrier_map[0].name.len = default_tree.len;
00236 rd->carrier_map[0].name.s = shm_malloc(rd->carrier_map[0].name.len);
00237 if (rd->carrier_map[0].name.s == NULL) {
00238 SHM_MEM_ERROR;
00239 return -1;
00240 }
00241 memcpy(rd->carrier_map[0].name.s, default_tree.s, rd->carrier_map[0].name.len);
00242
00243
00244 if ((rd->domain_map = shm_malloc(sizeof(struct name_map_t) * rd->domain_num)) == NULL) {
00245 SHM_MEM_ERROR;
00246 return -1;
00247 }
00248 memset(rd->domain_map, 0, sizeof(struct name_map_t) * rd->domain_num);
00249 for (i=0; i<rd->domain_num; i++) {
00250 d = cfg_getnsec(cfg, "domain", i);
00251 domain.s = (char *)cfg_title(d);
00252 if (domain.s==NULL) domain.s="";
00253 domain.len = strlen(domain.s);
00254 rd->domain_map[i].id = i+1;
00255 rd->domain_map[i].name.len = domain.len;
00256 rd->domain_map[i].name.s = shm_malloc(rd->domain_map[i].name.len);
00257 if (rd->domain_map[i].name.s == NULL) {
00258 SHM_MEM_ERROR;
00259 return -1;
00260 }
00261 memcpy(rd->domain_map[i].name.s, domain.s, rd->domain_map[i].name.len);
00262 }
00263
00264 qsort(rd->domain_map, rd->domain_num, sizeof(rd->domain_map[0]), compare_name_map);
00265
00266
00267 tmp_carrier_data = create_carrier_data(1, &rd->carrier_map[0].name, rd->domain_num);
00268 if (tmp_carrier_data == NULL) {
00269 LM_ERR("can't create new carrier\n");
00270 return -1;
00271 }
00272 if (add_carrier_data(rd, tmp_carrier_data) < 0) {
00273 LM_ERR("couldn't add carrier data\n");
00274 destroy_carrier_data(tmp_carrier_data);
00275 return -1;
00276 }
00277
00278
00279 for (i = 0; i < rd->domain_num; i++) {
00280 d = cfg_getnsec(cfg, "domain", i);
00281 domain.s = (char *)cfg_title(d);
00282 if (domain.s==NULL) domain.s="";
00283 domain.len = strlen(domain.s);
00284 m = cfg_size(d, "prefix");
00285
00286 LM_INFO("loading domain %.*s\n", domain.len, domain.s);
00287 for (j = 0; j < m; j++) {
00288 p = cfg_getnsec(d, "prefix", j);
00289 prefix.s = (char *)cfg_title(p);
00290 if (prefix.s==NULL) prefix.s="";
00291 prefix.len = strlen(prefix.s);
00292 if (str_strcasecmp(&prefix, &CR_EMPTY_PREFIX) == 0) {
00293 prefix.s = "";
00294 prefix.len = 0;
00295 }
00296
00297 LM_INFO("loading prefix %.*s\n", prefix.len, prefix.s);
00298 max_targets = cfg_getint(p, "max_targets");
00299 o = cfg_size(p, "target");
00300 for (k = 0; k < o; k++) {
00301 t = cfg_getnsec(p, "target", k);
00302 rewrite_host.s = (char *)cfg_title(t);
00303 if (rewrite_host.s==NULL) rewrite_host.s="";
00304 rewrite_host.len = strlen(rewrite_host.s);
00305 if (str_strcasecmp(&rewrite_host, &CR_EMPTY_PREFIX) == 0) {
00306 rewrite_host.s = "";
00307 rewrite_host.len = 0;
00308 }
00309
00310 LM_INFO("loading target %.*s\n", rewrite_host.len, rewrite_host.s);
00311 prob = cfg_getfloat(t, "prob");
00312 strip = cfg_getint(t, "strip");
00313 rewrite_prefix.s = (char *)cfg_getstr(t, "rewrite_prefix");
00314 if (rewrite_prefix.s==NULL) rewrite_prefix.s="";
00315 rewrite_prefix.len = strlen(rewrite_prefix.s);
00316 rewrite_suffix.s = (char *)cfg_getstr(t, "rewrite_suffix");
00317 if (rewrite_suffix.s==NULL) rewrite_suffix.s="";
00318 rewrite_suffix.len = strlen(rewrite_suffix.s);
00319 hash_index = cfg_getint(t, "hash_index");
00320 comment.s = (char *)cfg_getstr(t, "comment");
00321 if (comment.s==NULL) comment.s="";
00322 comment.len = strlen(comment.s);
00323 status = cfg_getint(t, "status");
00324
00325 if ((backed_up_size = cfg_size(t, "backed_up")) > 0) {
00326 if ((backed_up = pkg_malloc(sizeof(int) * (backed_up_size + 1))) == NULL) {
00327 PKG_MEM_ERROR;
00328 return -1;
00329 }
00330 for (l = 0; l < backed_up_size; l++) {
00331 backed_up[l] = cfg_getnint(t, "backed_up", l);
00332 }
00333 backed_up[backed_up_size] = -1;
00334 }
00335 backup = cfg_getint(t, "backup");
00336
00337 domain_id = map_name2id(rd->domain_map, rd->domain_num, &domain);
00338 if (domain_id < 0) {
00339 LM_ERR("cannot find id for domain '%.*s'", domain.len, domain.s);
00340 if (backed_up) {
00341 pkg_free(backed_up);
00342 }
00343 return -1;
00344 }
00345
00346 LM_INFO("adding route for prefix %.*s, to host %.*s, prob %f, backed up: %i, backup: %i\n",
00347 prefix.len, prefix.s, rewrite_host.len, rewrite_host.s, prob, backed_up_size, backup);
00348 if (add_route(rd, 1, domain_id, &prefix, 0, 0, max_targets, prob, &rewrite_host,
00349 strip, &rewrite_prefix, &rewrite_suffix, status,
00350 hash_index, backup, backed_up, &comment) < 0) {
00351 LM_INFO("Error while adding route\n");
00352 if (backed_up) {
00353 pkg_free(backed_up);
00354 }
00355 return -1;
00356 }
00357 if (backed_up) {
00358 pkg_free(backed_up);
00359 }
00360 backed_up = NULL;
00361 }
00362 }
00363
00364 }
00365 cfg_free(cfg);
00366 return 0;
00367 }
00368
00369
00379 static int save_route_data_recursor(struct dtrie_node_t * node, FILE * outfile) {
00380 int i;
00381 struct route_flags *rf;
00382 struct route_rule * rr;
00383 struct route_rule_p_list * rl;
00384 str *tmp_str;
00385 str null_str = str_init("NULL");
00386
00387
00388 rf = (struct route_flags *)(node->data);
00389 if (rf && rf->rule_list) {
00390 rr = rf->rule_list;
00391 tmp_str = (rr->prefix.len ? &rr->prefix : &null_str);
00392 fprintf(outfile, "\tprefix %.*s {\n", tmp_str->len, tmp_str->s);
00393 fprintf(outfile, "\t\tmax_targets = %i\n\n", rf->max_targets);
00394 while (rr) {
00395 tmp_str = (rr->host.len ? &rr->host : &null_str);
00396 fprintf(outfile, "\t\ttarget %.*s {\n", tmp_str->len, tmp_str->s);
00397 fprintf(outfile, "\t\t\tprob = %f\n", rr->orig_prob);
00398 fprintf(outfile, "\t\t\thash_index = %i\n", rr->hash_index);
00399 fprintf(outfile, "\t\t\tstatus = %i\n", rr->status);
00400 if (rr->strip > 0) {
00401 fprintf(outfile, "\t\t\tstrip = \"%i\"\n", rr->strip);
00402 }
00403 if (rr->local_prefix.len) {
00404 fprintf(outfile, "\t\t\trewrite_prefix = \"%.*s\"\n", rr->local_prefix.len, rr->local_prefix.s);
00405 }
00406 if (rr->local_suffix.len) {
00407 fprintf(outfile, "\t\t\trewrite_suffix: \"%.*s\"\n", rr->local_suffix.len, rr->local_suffix.s);
00408 }
00409 if (rr->backup) {
00410 fprintf(outfile, "\t\t\tbackup = %i\n", rr->backup->hash_index);
00411 }
00412 if (rr->backed_up) {
00413 rl = rr->backed_up;
00414 fprintf(outfile, "\t\t\tbacked_up = {");
00415 i=0;
00416 while (rl) {
00417 if (i>0) {
00418 fprintf(outfile, ", ");
00419 }
00420 fprintf(outfile, "%i", rl->hash_index);
00421 rl = rl->next;
00422 i++;
00423 }
00424 fprintf(outfile, "}\n");
00425 }
00426 if (rr->comment.len) {
00427 fprintf(outfile, "\t\t\tcomment = \"%.*s\"\n", rr->comment.len, rr->comment.s);
00428 }
00429 fprintf(outfile, "\t\t}\n");
00430 rr = rr->next;
00431 }
00432 fprintf(outfile, "\t}\n");
00433 }
00434 for (i = 0; i < cr_match_mode; i++) {
00435 if (node->child[i]) {
00436 if (save_route_data_recursor(node->child[i], outfile) < 0) {
00437 return -1;
00438 }
00439 }
00440 }
00441 return 0;
00442 }
00443
00444
00452 int save_config(struct route_data_t * rd) {
00453 FILE * outfile;
00454 int i,j;
00455
00456 if(backup_config() < 0){
00457 return -1;
00458 }
00459
00460 if ((outfile = fopen(config_file, "w")) == NULL) {
00461 LM_ERR("Could not open config file %s\n", config_file);
00462 return -1;
00463 }
00464
00465 i = 0;
00466 if (rd->carrier_num>=1) {
00467 for (j=0; j< rd->carriers[i]->domain_num; j++) {
00468 fprintf(outfile, "domain %.*s {\n", rd->carriers[i]->domains[j]->name->len, rd->carriers[i]->domains[j]->name->s);
00469 if (save_route_data_recursor(rd->carriers[i]->domains[j]->tree, outfile) < 0) {
00470 goto errout;
00471 }
00472 fprintf(outfile, "}\n\n");
00473 }
00474 }
00475 fclose(outfile);
00476 return 0;
00477 errout:
00478 fclose(outfile);
00479 LM_ERR("Cannot save config file %s\n", config_file);
00480 return -1;
00481 }