/** * loads the config data into shared memory (but doesn't really * share it), updates the routing data and writes it to the config * file. Afterwards, the global routing data is reloaded. * * @param opts pointer to the option structure which contains * data to be modified or to be added * * @return 0 on success, -1 on failure */ static int update_route_data(fifo_opt_t * opts) { struct rewrite_data * rd; int i,j; str tmp_domain; str tmp_prefix; str tmp_host; str tmp_rewrite_prefix; str tmp_rewrite_suffix; str tmp_comment = str_init(""); if ((rd = shm_malloc(sizeof(struct rewrite_data))) == NULL) { LM_ERR("out of shared memory\n"); return -1; } memset(rd, 0, sizeof(struct rewrite_data)); if (load_config(rd) < 0) { LM_ERR("could not load config\n"); FIFO_ERR(E_LOADCONF); return -1; } if (rule_fixup(rd) < 0) { LM_ERR("could not fixup rules\n"); FIFO_ERR(E_RULEFIXUP); return -1; } updated = 0; if (opts->cmd == OPT_ADD) { tmp_domain=opts->domain; tmp_prefix=opts->prefix; tmp_host=opts->host; tmp_rewrite_prefix=opts->rewrite_prefix; tmp_rewrite_suffix=opts->rewrite_suffix; if (tmp_domain.s==NULL) { tmp_domain.s=""; tmp_domain.len=0; } if (tmp_prefix.s==NULL) { tmp_prefix.s=""; tmp_prefix.len=0; } if (tmp_host.s==NULL) { tmp_host.s=""; tmp_host.len=0; } if (tmp_rewrite_prefix.s==NULL) { tmp_rewrite_prefix.s=""; tmp_rewrite_prefix.len=0; } if (tmp_rewrite_suffix.s==NULL) { tmp_rewrite_suffix.s=""; tmp_rewrite_suffix.len=0; } if (add_route(rd, 1, &tmp_domain, &tmp_prefix, 0, 0, 0, opts->prob, &tmp_host, opts->strip, &tmp_rewrite_prefix, &tmp_rewrite_suffix, opts->status, opts->hash_index, -1, NULL, &tmp_comment) < 0) { goto errout; } updated = 1; if (rule_fixup(rd) < 0) { LM_ERR("could not fixup rules after route appending\n"); FIFO_ERR(E_RULEFIXUP); return -1; } } else { for (i=0; i<rd->tree_num; i++) { if(rd->carriers[i]){ for (j=0; j<rd->carriers[i]->tree_num; j++) { if (rd->carriers[i]->trees[j] && rd->carriers[i]->trees[j]->tree) { if (update_route_data_recursor(rd->carriers[i]->trees[j]->tree, &rd->carriers[i]->trees[j]->name, opts) < 0) { goto errout; } } } } } } if(!updated){ LM_ERR("no match for update found\n"); FIFO_ERR(E_NOUPDATE); goto errout; } if (save_config(rd) < 0) { LM_ERR("could not save config\n"); FIFO_ERR(E_SAVECONF); goto errout; } if (prepare_route_tree() == -1) { LM_ERR("could not prepare the route tree\n"); FIFO_ERR(E_LOADCONF); goto errout; } destroy_rewrite_data(rd); return 0; errout: destroy_rewrite_data(rd); return -1; }
/** * loads the config data into shared memory (but doesn't really * share it), updates the routing data and writes it to the config * file. Afterwards, the global routing data is reloaded. * * @param opts pointer to the option structure which contains * data to be modified or to be added * * @return 0 on success, -1 on failure */ static int update_route_data(fifo_opt_t * opts) { struct route_data_t * rd; int i,j; int domain_id; str tmp_domain; str tmp_prefix; str tmp_host; str tmp_rewrite_prefix; str tmp_rewrite_suffix; str tmp_comment = str_init(""); if ((rd = shm_malloc(sizeof(struct route_data_t))) == NULL) { SHM_MEM_ERROR; return -1; } memset(rd, 0, sizeof(struct route_data_t)); if (load_config(rd) < 0) { LM_ERR("could not load config"); FIFO_ERR(E_LOADCONF); return -1; } if (rule_fixup(rd) < 0) { LM_ERR("could not fixup rules"); FIFO_ERR(E_RULEFIXUP); return -1; } updated = 0; if (opts->cmd == OPT_ADD) { tmp_domain=opts->domain; tmp_prefix=opts->prefix; tmp_host=opts->host; tmp_rewrite_prefix=opts->rewrite_prefix; tmp_rewrite_suffix=opts->rewrite_suffix; if (tmp_domain.s==NULL) { tmp_domain.s=""; tmp_domain.len=0; } if (tmp_prefix.s==NULL) { tmp_prefix.s=""; tmp_prefix.len=0; } if (tmp_host.s==NULL) { tmp_host.s=""; tmp_host.len=0; } if (tmp_rewrite_prefix.s==NULL) { tmp_rewrite_prefix.s=""; tmp_rewrite_prefix.len=0; } if (tmp_rewrite_suffix.s==NULL) { tmp_rewrite_suffix.s=""; tmp_rewrite_suffix.len=0; } domain_id = map_name2id(rd->domain_map, rd->domain_num, &tmp_domain); if (domain_id < 0) { LM_ERR("cannot find id for domain '%.*s'", tmp_domain.len, tmp_domain.s); goto errout; } if (add_route(rd, 1, domain_id, &tmp_prefix, 0, 0, 0, opts->prob, &tmp_host, opts->strip, &tmp_rewrite_prefix, &tmp_rewrite_suffix, opts->status, opts->hash_index, -1, NULL, &tmp_comment) < 0) { goto errout; } updated = 1; if (rule_fixup(rd) < 0) { LM_ERR("could not fixup rules after route appending"); FIFO_ERR(E_RULEFIXUP); goto errout; } } else { for (i=0; i<rd->carrier_num; i++) { if(rd->carriers[i]){ for (j=0; j<rd->carriers[i]->domain_num; j++) { if (rd->carriers[i]->domains[j] && rd->carriers[i]->domains[j]->tree) { if (update_route_data_recursor(rd->carriers[i]->domains[j]->tree, rd->carriers[i]->domains[j]->name, opts) < 0) { goto errout; } } } } } } if(!updated){ LM_ERR("no match for update found"); FIFO_ERR(E_NOUPDATE); goto errout; } if (save_config(rd) < 0) { LM_ERR("could not save config"); FIFO_ERR(E_SAVECONF); goto errout; } if (reload_route_data() == -1) { LM_ERR("could not reload route data"); FIFO_ERR(E_LOADCONF); goto errout; } clear_route_data(rd); return 0; errout: clear_route_data(rd); return -1; }
/** * Loads the routing data into the routing trees and sets the * global_data pointer to the new data. The old_data is removed * when it is not locked anymore. * * @return 0 on success, -1 on failure */ int reload_route_data(void) { struct route_data_t * old_data; struct route_data_t * new_data = NULL; int i; if ((new_data = shm_malloc(sizeof(struct route_data_t))) == NULL) { SHM_MEM_ERROR; return -1; } memset(new_data, 0, sizeof(struct route_data_t)); switch (mode) { case CARRIERROUTE_MODE_DB: if (load_route_data_db(new_data) < 0) { LM_ERR("could not load routing data\n"); goto errout; } break; case CARRIERROUTE_MODE_FILE: if (load_config(new_data) < 0) { LM_ERR("could not load routing data\n"); goto errout; } break; default: LM_ERR("invalid mode"); goto errout; } if (new_data == NULL) { LM_ERR("loading routing data failed (NULL pointer)"); goto errout; } /* sort carriers by id for faster access */ qsort(new_data->carriers, new_data->carrier_num, sizeof(new_data->carriers[0]), compare_carrier_data); /* sort domains by id for faster access */ for (i=0; i<new_data->carrier_num; i++) { qsort(new_data->carriers[i]->domains, new_data->carriers[i]->domain_num, sizeof(new_data->carriers[i]->domains[0]), compare_domain_data); } if (rule_fixup(new_data) < 0) { LM_ERR("could not fixup rules\n"); goto errout; } if (carrier_data_fixup(new_data) < 0){ LM_ERR("could not fixup trees\n"); goto errout; } new_data->proc_cnt = 0; if (*global_data == NULL) { *global_data = new_data; } else { old_data = *global_data; *global_data = new_data; i = 0; while (old_data->proc_cnt > 0) { LM_ERR("data is still locked after %i seconds\n", i); sleep_us(i*1000000); i++; } clear_route_data(old_data); } return 0; errout: clear_route_data(new_data); return -1; }