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