/** * rewrites the request URI of msg after determining the * new destination URI * * @param carrier the requested carrier * @param domain the requested routing domain * @param uri the URI to be rewritten * @param msg the current SIP message * @param user the localpart of the URI to be rewritten * @param hash_source the SIP header used for hashing * @param alg the algorithm used for hashing * * @return 1 on success, -1 on failure */ static int carrier_rewrite_msg(int carrier, int domain, str * uri, struct sip_msg * msg, str * user, enum hash_source hash_source, enum hash_algorithm alg) { struct rewrite_data *rd; struct route_tree * rt; struct action act; str dest; int ret; do { rd = get_data(); } while (rd == NULL); if (carrier >= rd->tree_num) { LM_ERR("desired carrier doesn't exist. (We only have %ld carriers, " "you wanted %d.)\n", (long)(rd->tree_num) - 1, carrier); ret = -1; goto unlock_and_out; } if ((rt = get_route_tree_by_id(rd->carriers[carrier], domain)) == NULL) { LM_ERR("desired routing domain doesn't exist, uri %.*s, carrier %d, domain %d\n", user->len, user->s, carrier, domain); ret = -1; goto unlock_and_out; } if (rewrite_uri_recursor(rt->tree, uri, &dest, msg, user, hash_source, alg) != 0) { LM_ERR("during rewrite_uri_recursor, uri %.*s, carrier %d, domain %d\n", user->len, user->s, carrier, domain); ret = -1; goto unlock_and_out; } LM_INFO("uri %.*s was rewritten to %.*s\n", user->len, user->s, dest.len, dest.s); act.type = SET_URI_T; act.elem[0].type= STRING_ST; act.elem[0].u.string = dest.s; act.next = NULL; ret = do_action(&act, msg); if (ret < 0) { LM_ERR("Error in do_action()\n"); } pkg_free(dest.s); unlock_and_out: release_data(rd); return ret; }
/** * traverses the routing tree until a matching rule is found * The longest match is taken, so it is possible to define * route rules for a single number * * @param route_tree the current routing tree node * @param pm the user to be used for prefix matching * @param flags user defined flags * @param dest the returned new destination URI * @param msg the sip message * @param user the localpart of the uri to be rewritten * @param hash_source the SIP header used for hashing * @param alg the algorithm used for hashing * @param dstavp the name of the destination AVP where the used host name is stored * * @return 0 on success, -1 on failure, 1 on no more matching child node and no rule list */ static int rewrite_uri_recursor(const struct route_tree_item * route_tree, const str * pm, flag_t flags, str * dest, struct sip_msg * msg, const str * user, const enum hash_source hash_source, const enum hash_algorithm alg, struct multiparam_t *dstavp) { struct route_tree_item *re_tree; str re_pm; re_pm=*pm; /* Skip over non-digits. */ while (re_pm.len > 0 && !isdigit(*re_pm.s)) { ++re_pm.s; --re_pm.len; } if (re_pm.len == 0 || route_tree->nodes[*re_pm.s - '0'] == NULL) { if (route_tree->flag_list == NULL) { LM_INFO("URI or route tree nodes empty, empty flag list\n"); return 1; } else { return rewrite_on_rule(route_tree, flags, dest, msg, user, hash_source, alg, dstavp); } } else { /* match, goto the next digit of the uri and try again */ re_tree = route_tree->nodes[*re_pm.s - '0']; re_pm.s = re_pm.s + 1; re_pm.len = re_pm.len - 1; switch (rewrite_uri_recursor(re_tree, &re_pm, flags, dest, msg, user, hash_source, alg, dstavp)) { case 0: return 0; case 1: if (route_tree->flag_list != NULL) { return rewrite_on_rule(route_tree, flags, dest, msg, user, hash_source, alg, dstavp); } else { LM_INFO("empty flag list for prefix [%.*s]%.*s\n", user->len - re_pm.len, user->s, re_pm.len, re_pm.s); return 1; } default: return -1; } } }
/** * traverses the routing tree until a matching rule is found * The longest match is taken, so it is possible to define * route rules for a single number * * @param route_tree the current routing tree node * @param uri the uri to be rewritten at the current position * @param dest the returned new destination URI * @param msg the sip message * @param user the localpart of the uri to be rewritten * @param hash_source the SIP header used for hashing * @param alg the algorithm used for hashing * * @return 0 on success, -1 on failure, 1 on no more matching child node and no rule list */ static int rewrite_uri_recursor(struct route_tree_item * route_tree, str * uri, str * dest, struct sip_msg * msg, str * user, enum hash_source hash_source, enum hash_algorithm alg) { struct route_tree_item *re_tree; str re_uri; /* Skip over non-digits. */ while (uri->len > 0 && !isdigit(*uri->s)) { ++uri->s; --uri->len; } if (uri->len == 0 || route_tree->nodes[*uri->s - '0'] == NULL) { if (route_tree->rule_list == NULL) { LM_INFO("URI or route tree nodes empty, empty rule list\n"); return 1; } else { return rewrite_on_rule(route_tree, dest, msg, user, hash_source, alg); } } else { /* match, goto the next number of the uri and try again */ re_tree = route_tree->nodes[*uri->s - '0']; re_uri.s = uri->s + 1; re_uri.len = uri->len - 1; switch (rewrite_uri_recursor(re_tree, &re_uri, dest, msg, user, hash_source, alg)) { case 0: return 0; case 1: if (route_tree->rule_list != NULL) { return rewrite_on_rule(route_tree, dest, msg, user, hash_source, alg); } else { LM_INFO("empty rule list for prefix [%.*s]%.*s\n", user->len - re_uri.len, user->s, re_uri.len, re_uri.s); return 1; } default: return -1; } } }
/** * rewrites the request URI of msg after determining the * new destination URI * * @param _msg the current SIP message * @param _carrier the requested carrier * @param _domain the requested routing domain * @param _prefix_matching the user to be used for prefix matching * @param _rewrite_user the localpart of the URI to be rewritten * @param _hsrc the SIP header used for hashing * @param _halg the hash algorithm used for hashing * @param _dstavp the name of the destination AVP where the used host name is stored * * @return 1 on success, -1 on failure */ int cr_do_route(struct sip_msg * _msg, gparam_t *_carrier, gparam_t *_domain, gparam_t *_prefix_matching, gparam_t *_rewrite_user, enum hash_source _hsrc, enum hash_algorithm _halg, gparam_t *_dstavp) { int carrier_id, domain_id, ret = -1; str rewrite_user, prefix_matching, dest; flag_t flags; struct route_data_t * rd; struct carrier_data_t * carrier_data; struct domain_data_t * domain_data; struct action act; struct run_act_ctx ra_ctx; if (fixup_get_svalue(_msg, _rewrite_user, &rewrite_user)<0) { LM_ERR("cannot print the rewrite_user\n"); return -1; } if (fixup_get_svalue(_msg, _prefix_matching, &prefix_matching)<0) { LM_ERR("cannot print the prefix_matching\n"); return -1; } flags = _msg->flags; do { rd = get_data(); } while (rd == NULL); carrier_id = cr_gp2id(_msg, _carrier, rd->carrier_map, rd->carrier_num); if (carrier_id < 0) { LM_ERR("invalid carrier id %d\n", carrier_id); release_data(rd); return -1; } domain_id = cr_gp2id(_msg, _domain, rd->domain_map, rd->domain_num); if (domain_id < 0) { LM_ERR("invalid domain id %d\n", domain_id); release_data(rd); return -1; } carrier_data=NULL; if (carrier_id < 0) { if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) { LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id); carrier_data = get_carrier_data(rd, rd->default_carrier_id); } } else if (carrier_id == 0) { carrier_data = get_carrier_data(rd, rd->default_carrier_id); } else { carrier_data = get_carrier_data(rd, carrier_id); if (carrier_data == NULL) { if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) { LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id); carrier_data = get_carrier_data(rd, rd->default_carrier_id); } } } if (carrier_data == NULL) { LM_ERR("cannot get carrier data\n"); goto unlock_and_out; } domain_data = get_domain_data(carrier_data, domain_id); if (domain_data == NULL) { LM_ERR("desired routing domain doesn't exist, prefix %.*s, carrier %d, domain %d\n", prefix_matching.len, prefix_matching.s, carrier_id, domain_id); goto unlock_and_out; } if (rewrite_uri_recursor(domain_data->tree, &prefix_matching, flags, &dest, _msg, &rewrite_user, _hsrc, _halg, _dstavp) != 0) { /* this is not necessarily an error, rewrite_recursor does already some error logging */ LM_INFO("rewrite_uri_recursor doesn't complete, uri %.*s, carrier %d, domain %d\n", prefix_matching.len, prefix_matching.s, carrier_id, domain_id); goto unlock_and_out; } LM_INFO("uri %.*s was rewritten to %.*s, carrier %d, domain %d\n", rewrite_user.len, rewrite_user.s, dest.len, dest.s, carrier_id, domain_id); memset(&act, 0, sizeof(act)); act.type = SET_URI_T; act.val[0].type = STRING_ST; act.val[0].u.string = dest.s; init_run_actions_ctx(&ra_ctx); ret = do_action(&ra_ctx, &act, _msg); if (ret < 0) { LM_ERR("Error in do_action()\n"); } unlock_and_out: release_data(rd); return ret; }
/** * rewrites the request URI of msg after determining the * new destination URI * * @param _msg the current SIP message * @param _carrier the requested carrier * @param _domain the requested routing domain * @param _prefix_matching the user to be used for prefix matching * @param _rewrite_user the localpart of the URI to be rewritten * @param _hsrc the SIP header used for hashing * @param _halg the hash algorithm used for hashing * @param _dstavp the name of the destination AVP where the used host name is stored * * @return 1 on success, -1 on failure */ int cr_do_route(struct sip_msg * _msg, struct multiparam_t *_carrier, struct multiparam_t *_domain, pv_elem_t *_prefix_matching, pv_elem_t *_rewrite_user, enum hash_source _hsrc, enum hash_algorithm _halg, struct multiparam_t *_dstavp) { int carrier_id; int domain_id; str rewrite_user; str prefix_matching; flag_t flags; struct rewrite_data * rd; struct carrier_tree * ct; struct route_tree * rt; struct action act; str dest; int ret; ret = -1; carrier_id = mp2carrier_id(_msg, _carrier); domain_id = mp2domain_id(_msg, _domain); if (domain_id < 0) { LM_ERR("invalid domain id %d\n", domain_id); return -1; } if (pv_printf_s(_msg, _rewrite_user, &rewrite_user)<0) { LM_ERR("cannot print the rewrite_user\n"); return -1; } if (pv_printf_s(_msg, _prefix_matching, &prefix_matching)<0) { LM_ERR("cannot print the prefix_matching\n"); return -1; } flags = _msg->flags; do { rd = get_data(); } while (rd == NULL); ct=NULL; if (carrier_id < 0) { if (fallback_default) { LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id); ct = rd->carriers[rd->default_carrier_index]; } } else if (carrier_id == 0) { ct = rd->carriers[rd->default_carrier_index]; } else { ct = get_carrier_tree(carrier_id, rd); if (ct == NULL) { if (fallback_default) { LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id); ct = rd->carriers[rd->default_carrier_index]; } } } if (ct == NULL) { LM_ERR("cannot get carrier tree\n"); goto unlock_and_out; } rt = get_route_tree_by_id(ct, domain_id); if (rt == NULL) { LM_ERR("desired routing domain doesn't exist, prefix %.*s, carrier %d, domain %d\n", prefix_matching.len, prefix_matching.s, carrier_id, domain_id); goto unlock_and_out; } if (rewrite_uri_recursor(rt->tree, &prefix_matching, flags, &dest, _msg, &rewrite_user, _hsrc, _halg, _dstavp) != 0) { /* this is not necessarily an error, rewrite_recursor does already some error logging */ LM_INFO("rewrite_uri_recursor doesn't complete, uri %.*s, carrier %d, domain %d\n", prefix_matching.len, prefix_matching.s, carrier_id, domain_id); goto unlock_and_out; } LM_INFO("uri %.*s was rewritten to %.*s\n", rewrite_user.len, rewrite_user.s, dest.len, dest.s); act.type = SET_URI_T; act.elem[0].type= STR_ST; act.elem[0].u.s = dest; act.next = NULL; ret = do_action(&act, _msg); if (ret < 0) { LM_ERR("Error in do_action()\n"); } pkg_free(dest.s); unlock_and_out: release_data(rd); return ret; }