示例#1
0
文件: cr_fifo.c 项目: 2pac/kamailio
/**
 * 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;
}
示例#2
0
文件: cr_fifo.c 项目: 2pac/kamailio
/**
 * Does the work for update_route_data by recursively
 * traversing the routing tree
 *
 * @param node points to the current routing tree node
 * @param act_domain routing domain which is currently
 * searched
 * @param opts points to the fifo command option structure
 *
 * @see update_route_data()
 *
 * @return 0 on success, -1 on failure
 */
static int update_route_data_recursor(struct dtrie_node_t *node, str * act_domain, fifo_opt_t * opts) {
	int i, hash = 0;
	struct route_rule * rr, * prev = NULL, * tmp, * backup;
	struct route_flags *rf;

	rf = (struct route_flags *)(node->data);
	if (rf && rf->rule_list) {
		rr = rf->rule_list;
		while (rr) {
			if ((!opts->domain.len || (strncmp(opts->domain.s, OPT_STAR, strlen(OPT_STAR)) == 0)
			        || ((opts->domain.len == act_domain->len) && (strncmp(opts->domain.s, act_domain->s, opts->domain.len) == 0)))
			        && ((!opts->prefix.len && !rr->prefix.len) || (strncmp(opts->prefix.s, OPT_STAR, strlen(OPT_STAR)) == 0)
			            || (rr->prefix.len == opts->prefix.len && (strncmp(opts->prefix.s, rr->prefix.s, opts->prefix.len) == 0)))
			        && ((!opts->host.len && !rr->host.s) || (strncmp(opts->host.s, OPT_STAR, strlen(OPT_STAR)) == 0)
			            || ((strncmp(rr->host.s, opts->host.s, opts->host.len) == 0) && (rr->host.len == opts->host.len)))
			        && ((opts->prob < 0) || (opts->prob == rr->prob))) {
				switch (opts->cmd) {
					case OPT_REPLACE:
						LM_INFO("replace host %.*s with %.*s\n", rr->host.len, rr->host.s, opts->new_host.len, opts->new_host.s);
						if (rr->host.s) {
							shm_free(rr->host.s);
						}
						if (opts->new_host.len) {
							if ((rr->host.s = shm_malloc(opts->new_host.len + 1)) == NULL) {
								SHM_MEM_ERROR;
								FIFO_ERR(E_NOMEM);
								return -1;
							}
							memmove(rr->host.s, opts->new_host.s, opts->new_host.len + 1);
							rr->host.len = opts->new_host.len;
							rr->host.s[rr->host.len] = '\0';
						} else {
							rr->host.len = 0;
						}
						rr->status = opts->status;
						prev = rr;
						rr = rr->next;
						updated = 1;
						break;
					case OPT_DEACTIVATE:
						if (remove_backed_up(rr) < 0) {
							LM_ERR("could not reset backup hosts\n");
							FIFO_ERR(E_RESET);
							return -1;
						}
						if (opts->new_host.len > 0) {
							LM_INFO("deactivating host %.*s\n", rr->host.len, rr->host.s);
							if ( opts->new_host.s && (strcmp(opts->new_host.s, rr->host.s) == 0)){
								LM_ERR("Backup host the same as initial host %.*s",rr->host.len, rr->host.s);
								FIFO_ERR(E_WRONGOPT);
								return -1;
							}
							if (opts->new_host.len == 1 && opts->new_host.s[0] == 'a') {
								if ((backup = find_auto_backup(rf, rr)) == NULL) {
									LM_ERR("didn't find auto backup route\n");
									FIFO_ERR(E_NOAUTOBACKUP);
									return -1;
								}
							} else {
								errno = 0;
								hash = strtol(opts->new_host.s, NULL, 10);
								if (errno == EINVAL || errno == ERANGE) {
									if ((backup = find_rule_by_hash(rf, hash)) == NULL) {
										LM_ERR("didn't find given backup route (hash %i)\n", hash);
										FIFO_ERR(E_NOHASHBACKUP);
										return -1;
									}
								} else {
									if ((backup = find_rule_by_host(rf, &opts->new_host)) == NULL) {
										LM_ERR("didn't find given backup route (host %.*s)\n", opts->new_host.len, opts->new_host.s);
										FIFO_ERR(E_NOHOSTBACKUP);
										return -1;
									}
								}
							}
							if (add_backup_rule(rr, backup) < 0) {
								LM_ERR("couldn't set backup route\n");
								FIFO_ERR(E_ADDBACKUP);
								return -1;
							}
						} else {
							if(rr->backed_up){
								LM_ERR("can't deactivate route without backup route because it is backup route for others\n");
								FIFO_ERR(E_DELBACKUP);
								return -1;
							}
						}
						rr->status = opts->status;
						prev = rr;
						rr = rr->next;
						updated = 1;
						break;
					case OPT_ACTIVATE:
						LM_INFO("activating host %.*s\n", rr->host.len, rr->host.s);
						if (remove_backed_up(rr) < 0) {
							LM_ERR("could not reset backup hosts\n");
							FIFO_ERR(E_RESET);
							return -1;
						}
						rr->status = opts->status;
						prev = rr;
						rr = rr->next;
						updated = 1;
						break;
					case OPT_REMOVE:
						LM_INFO("removing host %.*s\n", rr->host.len, rr->host.s);
						if (rr->backed_up){
							LM_ERR("cannot remove host %.*s which is backup for other hosts\n", rr->host.len, rr->host.s);
							FIFO_ERR(E_DELBACKUP);
							return -1;
						}
						if (remove_backed_up(rr) < 0) {
							LM_ERR("could not reset backup hosts\n");
							FIFO_ERR(E_RESET);
							return -1;
						}
						if (prev) {
							prev->next = rr->next;
							tmp = rr;
							rr = prev;
							destroy_route_rule(tmp);
							prev = rr;
							rr = rr->next;
						} else {
							rf->rule_list = rr->next;
							tmp = rr;
							rr = rf->rule_list;
							destroy_route_rule(tmp);
						}
						rf->rule_num--;
						rf->max_targets--;
						updated = 1;
						break;
					default:
						rr = rr->next;
						break;
				}
			} else {
				prev = rr;
				rr = rr->next;
			}
		}
	}
	for (i=0; i<cr_match_mode; i++) {
		if (node->child[i]) {
			if (update_route_data_recursor(node->child[i], act_domain, opts) < 0) {
				return -1;
			}
		}
	}
	return 0;
}
示例#3
0
/**
 * 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;
}