Esempio n. 1
0
/**
 * Destroys route_tree_item in shared memory by freing all its memory.
 *
 * @param route_tree_item route tree node to be destroyed
 */
static void destroy_route_tree_item(struct route_tree_item *route_tree_item) {
	int i;
	struct route_rule *rs;
	struct route_rule *rs_tmp;

	if (!route_tree_item) {
		LM_ERR("NULL pointer in parameter\n");
	}

	for (i = 0; i < 10; ++i) {
		if (route_tree_item->nodes[i] != NULL) {
			destroy_route_tree_item(route_tree_item->nodes[i]);
		}
	}
	if (route_tree_item->rules) {
		shm_free(route_tree_item->rules);
	}
	rs = route_tree_item->rule_list;
	while (rs != NULL) {
		rs_tmp = rs->next;
		destroy_route_rule(rs);
		rs = rs_tmp;
	}
	shm_free(route_tree_item);
	return;
}
Esempio n. 2
0
/**
 * Destroys route_flags in shared memory by freing all its memory.
 *
 * @param rf route_flags struct to be destroyed
 */
static void destroy_route_flags(struct route_flags *rf) {
	struct route_rule *rs;
	struct route_rule *rs_tmp;

	if (rf->rules) {
		shm_free(rf->rules);
	}
	rs = rf->rule_list;
	while (rs != NULL) {
		rs_tmp = rs->next;
		destroy_route_rule(rs);
		rs = rs_tmp;
	}
	shm_free(rf);
}
Esempio n. 3
0
/**
 * 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;
}
Esempio n. 4
0
/**
 * Adds a route rule to rf. prefix, rewrite_hostpart, rewrite_local_prefix,
 * rewrite_local_suffix, and comment must not contain NULL pointers.
 *
 * @param rf the current route_flags struct
 * @param prefix the whole scan prefix
 * @param max_targets the number of targets
 * @param prob the weight of the rule
 * @param rewrite_hostpart the rewrite_host of the rule
 * @param strip the strip value of the rule
 * @param rewrite_local_prefix the rewrite prefix
 * @param rewrite_local_suffix the rewrite suffix
 * @param status the status of the rule
 * @param hash_index the hash index of the rule
 * @param backup indicates if the route is backed up by another. only
                 useful if status==0, if set, it is the hash value
                 of another rule
 * @param backed_up an NULL-termintated array of hash indices of the route
                    for which this route is backup
 * @param comment a comment for the route rule
 *
 * @return 0 on success, -1 on failure
 *
 * @see add_route_to_tree()
 */
int add_route_rule(struct route_flags *rf, const str * prefix,
		int max_targets, double prob, const str * rewrite_hostpart, int strip,
		const str * rewrite_local_prefix, const str * rewrite_local_suffix,
		int status, int hash_index, int backup, int * backed_up,
		const str * comment) {
	struct route_rule * shm_rr, * prev = NULL, * tmp = NULL;
	struct route_rule_p_list * t_rl;
	int * t_bu;

	if (max_targets) {
		rf->max_targets = max_targets;
	} else {
		rf->max_targets++;
	}

	if ((shm_rr = shm_malloc(sizeof(struct route_rule))) == NULL) {
		LM_ERR("out of shared memory\n");
		return -1;
	}
	memset(shm_rr, 0, sizeof(struct route_rule));

	if (shm_str_dup(&shm_rr->host, rewrite_hostpart) != 0) {
		goto mem_error;
	}

	if (shm_str_dup(&shm_rr->prefix, prefix) != 0) {
		goto mem_error;
 	}

	shm_rr->strip = strip;

	if (shm_str_dup(&shm_rr->local_prefix, rewrite_local_prefix) != 0) {
		goto mem_error;
	}

	if (shm_str_dup(&shm_rr->local_suffix, rewrite_local_suffix) != 0) {
		goto mem_error;
	}

	if (shm_str_dup(&shm_rr->comment, comment) != 0) {
		goto mem_error;
	}

	shm_rr->status = status;
	shm_rr->hash_index = hash_index;
	shm_rr->orig_prob = prob;
	if (shm_rr->status || backup != -1) {
		shm_rr->prob = prob;
	}	else {
	    shm_rr->prob = 0;
	}
	if (backup >= 0) {
		if ((shm_rr->backup = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) {
			goto mem_error;
		}
		memset(shm_rr->backup, 0, sizeof(struct route_rule_p_list));
		shm_rr->backup->hash_index = backup;
	}
	shm_rr->backed_up = NULL;
	t_bu = backed_up;
	if(!backed_up){
		LM_INFO("no backed up rules\n");
	}
	while (t_bu && *t_bu != -1) {
		if ((t_rl = shm_malloc(sizeof(struct route_rule_p_list))) == NULL) {
			goto mem_error;
		}
		memset(t_rl, 0, sizeof(struct route_rule_p_list));
		t_rl->hash_index = *t_bu;
		t_rl->next = shm_rr->backed_up;
		shm_rr->backed_up = t_rl;
		t_bu++;
	}

	/* rules with a probability of zero are always at the beginning of the list */
	tmp = rf->rule_list;
	while(tmp && tmp->prob == 0){
		prev = tmp;
		tmp = tmp->next;
	}
	/* rules with prob > 0 are sorted by hash_index */
	while(tmp && (tmp->hash_index < shm_rr->hash_index)){
		prev = tmp;
		tmp = tmp->next;
	}
	if(prev){
		shm_rr->next = prev->next;
		prev->next = shm_rr;
	} else {
		shm_rr->next = rf->rule_list;
		rf->rule_list = shm_rr;
	}

	return 0;

mem_error:
	LM_ERR("out of shared memory\n");
	destroy_route_rule(shm_rr);
	return -1;
}