Exemplo n.º 1
0
/**
 * Loads the routing data from the config file given in global
 * variable config_data and stores it in routing tree rd.
 * The function mixes code parsing calls with rd structure
 * completion.
 *
 * @param rd Pointer to the route data tree where the routing data
 * shall be loaded into
 *
 * @return 0 means ok, -1 means an error occurred
 *
 */
int load_config(struct route_data_t * rd) {
	FILE * file;

	int ret_domain, ret_prefix, ret_target, ret_prefix_opts, ret_target_opts;
	int domain_id, allocated_domain_num = DEFAULT_DOMAIN_NUM;
	str domain_name, prefix_name, rewrite_host;
	char domain_buf[CR_MAX_LINE_SIZE], prefix_buf[CR_MAX_LINE_SIZE],  rewrite_buf[CR_MAX_LINE_SIZE];

	str rewrite_prefix, rewrite_suffix, comment;
	struct domain_data_t *domain_data = NULL;
	struct carrier_data_t * tmp_carrier_data;
	int hash_index, max_targets = 0, strip;
	double prob;
	int * backed_up = NULL;
	int backed_up_size = 0, backup = 0, status;
	void* p_realloc;
	int i=0, l, k;

	domain_name.s = domain_buf; domain_name.len = CR_MAX_LINE_SIZE;
	prefix_name.s = prefix_buf; prefix_name.len = CR_MAX_LINE_SIZE;
	rewrite_host.s = rewrite_buf; rewrite_host.len = CR_MAX_LINE_SIZE;

	/* open configuration file */
	if ((file = fopen(config_file, "rb"))==NULL) {
		LM_ERR("Cannot open source file.\n");
		return -1;
	}

	rd->carrier_num = 1;
	rd->first_empty_carrier = 0;
	rd->domain_num = 0;

	if ((rd->carriers = shm_malloc(sizeof(struct carrier_data_t *))) == NULL) {
		SHM_MEM_ERROR;
		goto errclose;
	}
	memset(rd->carriers, 0, sizeof(struct carrier_data_t *));

	/* Create carrier map */
	if ((rd->carrier_map = shm_malloc(sizeof(struct name_map_t))) == NULL) {
		SHM_MEM_ERROR;
		goto errclose;
	}

	memset(rd->carrier_map, 0, sizeof(struct name_map_t));
	rd->carrier_map[0].id = 1;
	rd->carrier_map[0].name.len = default_tree.len;
	rd->carrier_map[0].name.s = shm_malloc(rd->carrier_map[0].name.len);

	if (rd->carrier_map[0].name.s == NULL) {
		SHM_MEM_ERROR;
		goto errclose;
	}
	memcpy(rd->carrier_map[0].name.s, default_tree.s, rd->carrier_map[0].name.len);

	/* Create domain map */
	if ((rd->domain_map = shm_malloc(sizeof(struct name_map_t) * allocated_domain_num)) == NULL) {
		SHM_MEM_ERROR;
		goto errclose;
	}
	memset(rd->domain_map, 0, sizeof(struct name_map_t) * allocated_domain_num);

	/* Create and insert carrier data structure */
	tmp_carrier_data = create_carrier_data(1, &rd->carrier_map[0].name, allocated_domain_num);
	if (tmp_carrier_data == NULL) {
		LM_ERR("can't create new carrier\n");
		goto errclose;
	}
	tmp_carrier_data->domain_num = 0;
	tmp_carrier_data->id = 1;
	tmp_carrier_data->name = &(rd->carrier_map[0].name);

	if (add_carrier_data(rd, tmp_carrier_data) < 0) {
		LM_ERR("couldn't add carrier data\n");
		destroy_carrier_data(tmp_carrier_data);
		goto errclose;
	}

	init_prefix_opts();
	init_target_opts();

	/* add all routes by parsing the route conf file */
	/* while there are domain structures, get name and parse the structure*/
	while ((ret_domain = parse_struct_header(file, "domain", &domain_name))
			== SUCCESSFUL_PARSING) {

		domain_id = ++rd->domain_num;
		tmp_carrier_data->domain_num++;

		/* (re)allocate memory for a maximum of MAX_DOMAIN_NUM domains
		 rd is not fully allocated from the start as this would require the preparsing
		 of the entire route file */
		if ( rd->domain_num > allocated_domain_num){

			if (MAX_DOMAIN_NUM <= allocated_domain_num){
				LM_ERR("Maximum number of domains reached");
				break;
			}

			LM_INFO("crt_alloc_size=%d must be increased \n", allocated_domain_num);
			allocated_domain_num *= 2;

			if ( ( p_realloc = shm_realloc(rd->domain_map,
					sizeof(struct name_map_t) * allocated_domain_num) ) == NULL)
			{
				SHM_MEM_ERROR;
				goto errclose;
			}

			rd->domain_map = (struct name_map_t *)p_realloc;

			if (( p_realloc = shm_realloc( rd->carriers[0]->domains,
					sizeof(struct domain_data_t *) * allocated_domain_num)) == NULL) {
				SHM_MEM_ERROR;
				goto errclose;
			}
			rd->carriers[0]->domains = (struct domain_data_t **)p_realloc;

			for (i=0; i<rd->domain_num-1; i++){
				rd->carriers[0]->domains[i]->name = &(rd->domain_map[i].name);
			}
		}// end of mem (re)allocation for domains

		/*insert domain in domain map*/
		rd->domain_map[domain_id-1].id = domain_id;
		rd->domain_map[domain_id-1].name.len = domain_name.len;
		rd->domain_map[domain_id-1].name.s = shm_malloc(rd->domain_map[domain_id-1].name.len);
		if (rd->domain_map[domain_id-1].name.s == NULL) {
			SHM_MEM_ERROR;
			goto errclose;
		}
		memcpy(rd->domain_map[domain_id-1].name.s, domain_name.s, rd->domain_map[domain_id-1].name.len);

		/* create new domain data */
		if ((domain_data = create_domain_data(domain_id,&(rd->domain_map[domain_id-1].name))) == NULL) {
			LM_ERR("could not create new domain data\n");
			goto errclose;
		}

		if (add_domain_data(tmp_carrier_data, domain_data, domain_id-1) < 0) {
			LM_ERR("could not add domain data\n");
			destroy_domain_data(domain_data);
			goto errclose;
		}
		LM_DBG("added domain %d '%.*s' to carrier %d '%.*s'\n",
				domain_id, domain_name.len, domain_name.s,
				tmp_carrier_data->id, tmp_carrier_data->name->len, tmp_carrier_data->name->s);

		/* while there are prefix structures, get name and parse the structure */
		while ((ret_prefix = parse_struct_header(file, "prefix", &prefix_name))
				== SUCCESSFUL_PARSING) {

			reset_prefix_opts();
			if (str_strcasecmp(&prefix_name, &CR_EMPTY_PREFIX) == 0) {
				prefix_name.s[0] = '\0';
				prefix_name.len = 0;
			}

			/* look for max_targets = value which is described in prefix_options */
			if ((ret_prefix_opts = parse_options(file, prefix_options,
					PO_MAX_IDS, "target")) != SUCCESSFUL_PARSING) {
				LM_ERR("Error in parsing \n");
				goto errclose;
			}

			max_targets = prefix_options[PO_MAX_TARGETS].value.int_data;
			/* look for max_targets target structures */
			for ( k = 0; k < max_targets; k++) {
				/* parse the target header, get name and continue*/
				ret_target = parse_struct_header(file, "target", &rewrite_host);
				if (ret_target != SUCCESSFUL_PARSING) {
					LM_ERR("Error in parsing \n");
					goto errclose;
				}

				reset_target_opts();
				/* look for the target options: prob, hash index, status, etc*/
				ret_target_opts = parse_options(file, target_options, TO_MAX_IDS, "}");
				if ( SUCCESSFUL_PARSING == ret_target_opts ){
					/* parsing target structure closing bracket*/
					parse_struct_stop(file);
				}else{
					LM_ERR("Error in parsing in target options \n");
					goto errclose;
				}
				/* intermediary variables for more lisibility */
				if (str_strcasecmp(&rewrite_host, &CR_EMPTY_PREFIX) == 0) {
					rewrite_host.s[0] = '\0';
					rewrite_host.len = 0;
				}
				LM_DBG("loading target %.*s\n", rewrite_host.len, rewrite_host.s);
				prob = target_options[TO_ID_PROB].value.float_data;
				strip = target_options[TO_ID_STRIP].value.int_data;
				rewrite_prefix.s = target_options[TO_ID_REWR_PREFIX].value.string_data.s;
				rewrite_prefix.len = target_options[TO_ID_REWR_PREFIX].value.string_data.len;
				rewrite_suffix.s = target_options[TO_ID_REWR_SUFFIX].value.string_data.s;
				rewrite_suffix.len = target_options[TO_ID_REWR_SUFFIX].value.string_data.len;
				hash_index = target_options[TO_ID_HASH_INDEX].value.int_data;
				comment.s = target_options[TO_ID_COMMENT].value.string_data.s;
				comment.len = target_options[TO_ID_COMMENT].value.string_data.len;
				status = target_options[TO_ID_STATUS].value.int_data;

				if ( (backed_up_size = target_options[TO_ID_BACKED_UP].no_elems) > 0){
					if ((backed_up = pkg_malloc(sizeof(int) * (backed_up_size + 1))) == NULL) {
						PKG_MEM_ERROR;
						goto errclose;
					}
					for (l = 0; l < backed_up_size; l++) {
						backed_up[l] = target_options[TO_ID_BACKED_UP].value.int_list[l];
					}
					backed_up[backed_up_size] = -1;
				}
				backup = target_options[TO_ID_BACKUP].value.int_data;

				LM_DBG("\n Adding route to tree <'%.*s'>: prefix_name:%s\n,"
						" max_targets =%d\n, prob=%f\n, rewr_host=%s\n,"
						" strip=%i\n, rwr_prefix=%s\n, rwr_suff=%s\n,"
						" status=%i\n, hash_index=%i\n, comment=%s \n",
						domain_data->name->len, domain_data->name->s, prefix_name.s,
						max_targets, prob, rewrite_host.s, strip, rewrite_prefix.s,
						rewrite_suffix.s, status, hash_index, comment.s);

				if (add_route_to_tree(domain_data->tree, &prefix_name, 0, 0,
						&prefix_name, max_targets, prob, &rewrite_host,
						strip, &rewrite_prefix, &rewrite_suffix, status,
						hash_index, backup, backed_up, &comment) < 0) {
					LM_INFO("Error while adding route\n");
					if (backed_up) {
						pkg_free(backed_up);
					}
					goto errclose;
				}

				if (backed_up) {
					pkg_free(backed_up);
				}
				backed_up = NULL;
			}

			if (k != prefix_options[0].value.int_data ) {
				LM_ERR("Error in parsing: max_targets =%i, actual targets =%i \n",
						prefix_options[0].value.int_data, i);
				goto errclose;
			}
			/* parsing prefix structure closing bracket */
			if (parse_struct_stop(file) != SUCCESSFUL_PARSING) {
				LM_ERR("Error in parsing targets, expecting } \n");
				goto errclose;

			}
		} // END OF PREFIX part

		/* parsing domain structure closing bracket */
		if (parse_struct_stop(file) != SUCCESSFUL_PARSING) {
			LM_ERR("Error in parsing targets, expecting } \n");
			goto errclose;
		}
	}

	if (EOF_REACHED != ret_domain){
		LM_ERR("Error appeared while parsing domain header \n");
		goto errclose;
	}

	LM_INFO("File parsed successfully \n");
	fclose(file);
	return 0;
errclose:
	fclose(file);
	return -1;
}
Exemplo n.º 2
0
/**
 * Loads the routing data from the database given in global
 * variable db_url and stores it in routing tree rd.
 *
 * @param rd Pointer to the route data tree where the routing data
 * shall be loaded into
 *
 * @return 0 means ok, -1 means an error occured
 *
 */
int load_route_data_db(struct route_data_t * rd) {
	db1_res_t * res = NULL;
	db_row_t * row = NULL;
	int i, ret;
	struct carrier_data_t * tmp_carrier_data;
	static str query_str;
	str tmp_scan_prefix, tmp_rewrite_host, tmp_rewrite_prefix,
		tmp_rewrite_suffix, tmp_host_name, tmp_reply_code, tmp_comment;
	str *p_tmp_comment;

	if( (strlen("SELECT DISTINCT  FROM  WHERE = ")
			+ carrierroute_table.len + columns[COL_DOMAIN]->len
			+ columns[COL_CARRIER]->len + 20) >  QUERY_LEN) {
		LM_ERR("query too long\n");
		return -1;
	}

	if((rd->carrier_num = load_carrier_map(rd)) <= 0){
		LM_ERR("error while retrieving carriers\n");
		goto errout;
	}

	if((rd->domain_num = load_domain_map(rd)) <= 0){
		LM_ERR("error while retrieving domains\n");
		goto errout;
	}

	if ((rd->carriers = shm_malloc(sizeof(struct carrier_data_t *) * rd->carrier_num)) == NULL) {
		SHM_MEM_ERROR;
		goto errout;
	}
	memset(rd->carriers, 0, sizeof(struct carrier_data_t *) * rd->carrier_num);

	for (i=0; i<rd->carrier_num; i++) {
		memset(query, 0, QUERY_LEN);
		ret = snprintf(query, QUERY_LEN, "SELECT DISTINCT %.*s FROM %.*s WHERE %.*s=%i",
		columns[COL_DOMAIN]->len, columns[COL_DOMAIN]->s, carrierroute_table.len,
		carrierroute_table.s, columns[COL_CARRIER]->len, columns[COL_CARRIER]->s, rd->carrier_map[i].id);
		if (ret < 0) {
			LM_ERR("error in snprintf");
			goto errout;
		}
		query_str.s = query;
		query_str.len = ret;

		if (carrierroute_dbf.raw_query(carrierroute_dbh, &query_str, &res) < 0) {
			LM_ERR("Failed to query database.\n");
			goto errout;
		}
		LM_INFO("carrier '%.*s' (id %i) has %i domains\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s, rd->carrier_map[i].id, RES_ROW_N(res));
		tmp_carrier_data = create_carrier_data(rd->carrier_map[i].id, &rd->carrier_map[i].name, RES_ROW_N(res));
		if (tmp_carrier_data == NULL) {
			LM_ERR("can't create new carrier '%.*s'\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s);
			goto errout;
		}
		if (add_carrier_data(rd, tmp_carrier_data) < 0) {
			LM_ERR("can't add carrier '%.*s'\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s);
			destroy_carrier_data(tmp_carrier_data);
			goto errout;
		}
		carrierroute_dbf.free_result(carrierroute_dbh, res);
		res = NULL;
	}

	if (carrierroute_dbf.use_table(carrierroute_dbh, &carrierroute_table) < 0) {
		LM_ERR("Cannot set database table '%.*s'.\n", carrierroute_table.len, carrierroute_table.s);
		return -1;
	}

	if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) {
		if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *) columns, 0,
				columns_load_num, NULL, NULL) < 0) {
			LM_ERR("Failed to query database to prepare fetch row.\n");
			return -1;
		}
		if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res, cfg_get(carrierroute, carrierroute_cfg, fetch_rows)) < 0) {
			LM_ERR("Fetching rows failed\n");
			return -1;
		}
	} else {
		if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *) columns, 0,
				columns_load_num, NULL, &res) < 0) {
			LM_ERR("Failed to query database.\n");
			return -1;
		}
	}
	int n = 0;
	do {
		LM_DBG("loading, cycle %d", n++);
		for (i = 0; i < RES_ROW_N(res); ++i) {
			row = &RES_ROWS(res)[i];
			tmp_scan_prefix.s=(char *)row->values[COL_SCAN_PREFIX].val.string_val;
			tmp_rewrite_host.s=(char *)row->values[COL_REWRITE_HOST].val.string_val;
			tmp_rewrite_prefix.s=(char *)row->values[COL_REWRITE_PREFIX].val.string_val;
			tmp_rewrite_suffix.s=(char *)row->values[COL_REWRITE_SUFFIX].val.string_val;
			if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
			if (tmp_rewrite_host.s==NULL) tmp_rewrite_host.s="";
			if (tmp_rewrite_prefix.s==NULL) tmp_rewrite_prefix.s="";
			if (tmp_rewrite_suffix.s==NULL) tmp_rewrite_suffix.s="";
			tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
			tmp_rewrite_host.len=strlen(tmp_rewrite_host.s);
			tmp_rewrite_prefix.len=strlen(tmp_rewrite_prefix.s);
			tmp_rewrite_suffix.len=strlen(tmp_rewrite_suffix.s);

			p_tmp_comment = NULL;
			if (load_comments) {
				tmp_comment.s = (char *)row->values[COL_COMMENT].val.string_val;
				if (tmp_comment.s==NULL) tmp_comment.s="";
				tmp_comment.len=strlen(tmp_comment.s);
				p_tmp_comment = &tmp_comment;
			}

			if (add_route(rd,
					row->values[COL_CARRIER].val.int_val,
					row->values[COL_DOMAIN].val.int_val,
					&tmp_scan_prefix,
					row->values[COL_FLAGS].val.int_val,
					row->values[COL_MASK].val.int_val,
					0,
					row->values[COL_PROB].val.double_val,
					&tmp_rewrite_host,
					row->values[COL_STRIP].val.int_val,
					&tmp_rewrite_prefix,
					&tmp_rewrite_suffix,
					1,
					0,
					-1,
					NULL,
					p_tmp_comment) == -1) {
				goto errout;
			}
		}
		if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) {
			if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res,  cfg_get(carrierroute, carrierroute_cfg, fetch_rows)) < 0) {
				LM_ERR("fetching rows failed\n");
				carrierroute_dbf.free_result(carrierroute_dbh, res);
				return -1;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res) > 0);

	carrierroute_dbf.free_result(carrierroute_dbh, res);
	res = NULL;
	
	if (carrierroute_dbf.use_table(carrierroute_dbh, &carrierfailureroute_table) < 0) {
		LM_ERR("cannot set database table '%.*s'.\n",
				carrierfailureroute_table.len, carrierfailureroute_table.s);
		return -1;
	}
	if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *)failure_columns, 0,
			failure_columns_load_num, NULL, &res) < 0) {
		LM_ERR("failed to query database.\n");
		return -1;
	}
	for (i = 0; i < RES_ROW_N(res); ++i) {
		row = &RES_ROWS(res)[i];
		tmp_scan_prefix.s=(char *)row->values[FCOL_SCAN_PREFIX].val.string_val;
		tmp_host_name.s=(char *)row->values[FCOL_HOST_NAME].val.string_val;
		tmp_reply_code.s=(char *)row->values[FCOL_REPLY_CODE].val.string_val;
		if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
		if (tmp_host_name.s==NULL) tmp_host_name.s="";
		if (tmp_reply_code.s==NULL) tmp_reply_code.s="";
		tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
		tmp_host_name.len=strlen(tmp_host_name.s);
		tmp_reply_code.len=strlen(tmp_reply_code.s);
		p_tmp_comment = NULL;

		if (load_comments) {
			tmp_comment.s = (char *)row->values[FCOL_COMMENT].val.string_val;
			if (tmp_comment.s==NULL) tmp_comment.s="";
			tmp_comment.len=strlen(tmp_comment.s);
			p_tmp_comment = &tmp_comment;
		}

		if (add_failure_route(rd,
				row->values[FCOL_CARRIER].val.int_val,
				row->values[COL_DOMAIN].val.int_val,
				&tmp_scan_prefix,
				&tmp_host_name,
				&tmp_reply_code,
				row->values[FCOL_FLAGS].val.int_val,
				row->values[FCOL_MASK].val.int_val,
				row->values[FCOL_NEXT_DOMAIN].val.int_val,
				p_tmp_comment) == -1) {
			goto errout;
		}
	}

	carrierroute_dbf.free_result(carrierroute_dbh, res);
	return 0;

errout:
	if (res) {
		carrierroute_dbf.free_result(carrierroute_dbh, res);
	}
	return -1;
}