cr_func.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2007-2008 1&1 Internet AG
00005  *
00006  * This file is part of SIP-router, a free SIP server.
00007  *
00008  * SIP-router is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * SIP-router is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00030 #include <ctype.h>
00031 #include <assert.h>
00032 #include <stdlib.h>
00033 #include "cr_func.h"
00034 #include "cr_db.h"
00035 #include "../../sr_module.h"
00036 #include "../../action.h"
00037 #include "../../parser/parse_uri.h"
00038 #include "../../parser/parse_from.h"
00039 #include "../../ut.h"
00040 #include "../../parser/digest/digest.h"
00041 #include "../../parser/hf.h"
00042 #include "../../mem/mem.h"
00043 #include "../../qvalue.h"
00044 #include "../../dset.h"
00045 #include "cr_map.h"
00046 #include "cr_rule.h"
00047 #include "cr_domain.h"
00048 #include "cr_carrier.h"
00049 #include "carrierroute.h"
00050 #include "config.h"
00051 
00052 enum hash_algorithm {
00053         alg_crc32 = 1, 
00054         alg_crc32_nofallback, 
00056         alg_error
00057 };
00058 
00059 
00060 static const str SIP_URI  = { .s="sip:",  .len=4 };
00061 static const str SIPS_URI = { .s="sips:", .len=5 };
00062 static const str AT_SIGN  = { .s="@",     .len=1 };
00063 static char g_rewrite_uri[MAX_URI_SIZE+1];
00064 
00076 static inline int cr_gp2id(struct sip_msg *_msg, gparam_t *gp, struct name_map_t *map, int size) {
00077         int id;
00078         struct usr_avp *avp;
00079         int_str avp_val;
00080         str tmp;
00081 
00082         switch (gp->type) {
00083         case GPARAM_TYPE_INT:
00084                 return gp->v.i;
00085                 break;
00086         case GPARAM_TYPE_PVE:
00087                 /* does this PV hold an AVP? */
00088                 if (gp->v.pve->spec.type==PVT_AVP) {
00089                         avp = search_first_avp(gp->v.pve->spec.pvp.pvn.u.isname.type,
00090                                                 gp->v.pve->spec.pvp.pvn.u.isname.name, &avp_val, 0);
00091                         if (!avp) {
00092                                 if(gp->v.pve->spec.pvp.pvn.u.isname.type & AVP_NAME_STR)
00093                                         LM_ERR("cannot find AVP '%.*s'\n", gp->v.pve->spec.pvp.pvn.u.isname.name.s.len,
00094                                                 gp->v.pve->spec.pvp.pvn.u.isname.name.s.s);
00095                                 else if(gp->v.pve->spec.pvp.pvn.u.isname.type & AVP_NAME_RE)
00096                                         LM_ERR("cannot find AVP regex\n");
00097                                 else    LM_ERR("cannot find AVP '%d'\n", gp->v.pve->spec.pvp.pvn.u.isname.name.n);
00098                                 return -1;
00099                         }
00100                         if ((avp->flags&AVP_VAL_STR)==0) {
00101                                 return avp_val.n;
00102                         } else {
00103                                 id = map_name2id(map, size, &avp_val.s);
00104                                 if (id < 0) {
00105                                         if(gp->v.pve->spec.pvp.pvn.u.isname.type & AVP_NAME_STR)
00106                                                 LM_ERR("cannot map carrier with id %.*s from  AVP '%.*s'\n", avp_val.s.len, avp_val.s.s, gp->v.pve->spec.pvp.pvn.u.isname.name.s.len,
00107                                                         gp->v.pve->spec.pvp.pvn.u.isname.name.s.s);
00108                                         else if(gp->v.pve->spec.pvp.pvn.u.isname.type & AVP_NAME_RE)
00109                                                 LM_ERR("cannot map carrier with id %.*s from  AVP regex\n", avp_val.s.len, avp_val.s.s);
00110                                         else    LM_ERR("cannot map carrier with id %.*s from  AVP '%d'\n", avp_val.s.len, avp_val.s.s, gp->v.pve->spec.pvp.pvn.u.isname.name.n);
00111                                         return -1;
00112                                 }
00113                                 return id;
00114                         }
00115                 } else {
00116                         /* retrieve name from parameter */
00117                         if (fixup_get_svalue(_msg, gp, &tmp)<0) {
00118                                 LM_ERR("cannot print the name from PV\n");
00119                                 return -1;
00120                         }
00121                         id = map_name2id(map, size, &tmp);
00122                         if (id < 0) {
00123                                 LM_ERR("could not find id '%.*s' from PV\n", tmp.len, tmp.s);
00124                                 return -1;
00125                         }
00126                         return id;
00127                 }
00128         default:
00129                 LM_ERR("invalid parameter type\n");
00130                 return -1;
00131         }
00132 }
00133 
00134 
00143 static inline int reply_code_matcher(const str *rcw, const str *rc) {
00144         int i;
00145         
00146         if (rcw->len==0) return 0;
00147         
00148         if (rcw->len != rc->len) return -1;
00149         
00150         for (i=0; i<rc->len; i++) {
00151                 if (rcw->s[i]!='.' && rcw->s[i]!=rc->s[i]) return -1;
00152         }
00153         
00154         return 0;
00155 }
00156 
00157 
00169 static int set_next_domain_on_rule(struct failure_route_rule *frr_head,
00170                 const str *host, const str *reply_code, const flag_t flags,
00171                 const gparam_t *dstavp) {
00172         struct failure_route_rule * rr;
00173         int_str avp_val;
00174         
00175         assert(frr_head != NULL);
00176         
00177         LM_DBG("searching for matching routing rules");
00178         for (rr = frr_head; rr != NULL; rr = rr->next) {
00179                 /*
00180                 LM_DBG("rr.flags=%d rr.mask=%d flags=%d\n", rr->flags, rr->mask, flags);
00181                 LM_DBG("rr.host.len=%d host.len=%d\n", rr->host.len, host->len);
00182                 LM_DBG("rr.host.s='%.*s' host.s='%.*s'\n", rr->host.len, rr->host.s, host->len, host->s);
00183                 LM_DBG("rr.reply_code.len=%d reply_code.len=%d\n", rr->reply_code.len, reply_code->len);
00184                 LM_DBG("rr.reply_code.s='%.*s' reply_code.s='%.*s'\n", rr->reply_code.len, rr->reply_code.s, reply_code->len, reply_code->s);
00185                 */
00186                 if (((rr->mask & flags) == rr->flags) &&
00187                                 ((rr->host.len == 0) || (str_strcmp(host, &rr->host)==0)) &&
00188                                 (reply_code_matcher(&(rr->reply_code), reply_code)==0)) {
00189                         avp_val.n = rr->next_domain;
00190                         if (add_avp(dstavp->v.pve->spec.pvp.pvn.u.isname.type,
00191                                         dstavp->v.pve->spec.pvp.pvn.u.isname.name, avp_val)<0) {
00192                                 LM_ERR("set AVP failed\n");
00193                                 return -1;
00194                         }
00195                         
00196                         LM_INFO("next_domain is %d\n", rr->next_domain);
00197                         return 0;
00198                 }
00199         }
00200         
00201         LM_INFO("no matching rule for (flags=%d, host='%.*s', reply_code='%.*s') found\n", flags, host->len, host->s, reply_code->len, reply_code->s);
00202         return -1;
00203 }
00204 
00205 
00220 static int set_next_domain_recursor(struct dtrie_node_t *failure_node,
00221                 const str *uri, const str *host, const str *reply_code, const flag_t flags,
00222                 const gparam_t *dstavp) {
00223         str re_uri = *uri;
00224         void **ret;
00225         
00226         /* Skip over non-digits.  */
00227         while (re_uri.len > 0 && (!isdigit(*re_uri.s) && cr_match_mode == 10)) {
00228                 ++re_uri.s;
00229                 --re_uri.len;
00230         }
00231         ret = dtrie_longest_match(failure_node, re_uri.s, re_uri.len, NULL, cr_match_mode);
00232 
00233         if (ret == NULL) {
00234                 LM_INFO("URI or prefix tree nodes empty, empty rule list\n");
00235                 return 1;
00236         }
00237         else return set_next_domain_on_rule(*ret, host, reply_code, flags, dstavp);
00238 }
00239 
00240 
00251 static struct route_rule * get_rule_by_hash(const struct route_flags * rf,
00252                 const int prob) {
00253         struct route_rule * act_hash = NULL;
00254 
00255         if (prob > rf->rule_num) {
00256                 LM_WARN("too large desired hash, taking highest\n");
00257                 act_hash = rf->rules[rf->rule_num - 1];
00258         }
00259         else act_hash = rf->rules[prob - 1];
00260 
00261         if (!act_hash->status) {
00262                 if (act_hash->backup && act_hash->backup->rr) {
00263                         act_hash = act_hash->backup->rr;
00264                 } else {
00265                         act_hash = NULL;
00266                 }
00267         }
00268         LM_INFO("desired hash was %i, return %i\n", prob, act_hash ? act_hash->hash_index : -1);
00269         return act_hash;
00270 }
00271 
00272 
00285 static int actually_rewrite(const struct route_rule *rs, str *dest,
00286                 const struct sip_msg *msg, const str * user, gparam_t *descavp) {
00287         size_t len;
00288         char *p;
00289         int_str avp_val;
00290         int strip = 0;
00291 
00292         str l_user;
00293         
00294         if( !rs || !dest || !msg || !user) {
00295                 LM_ERR("NULL parameter\n");
00296                 return -1;
00297         }
00298         
00299         l_user = *user;
00300 
00301         strip = (rs->strip > user->len ? user->len : rs->strip);
00302         strip = (strip < 0 ? 0 : strip);
00303 
00304         if ( strcmp(user->s, "<null>") == 0 || user->len == 0)
00305         {
00306                 l_user.s = NULL;
00307                 l_user.len = 0;
00308                 len = rs->host.len;
00309                 strip = 0;
00310         }
00311         else{
00312                 len = rs->local_prefix.len + l_user.len + rs->local_suffix.len +
00313                        AT_SIGN.len + rs->host.len - strip;
00314         }
00315         
00316         if (msg->parsed_uri.type == SIPS_URI_T) {
00317                 len += SIPS_URI.len;
00318         } else {
00319                 len += SIP_URI.len;
00320         }
00321         if ( len > MAX_URI_SIZE ) {
00322                 LM_ERR("Calculated uri size too large: %lu\n", (unsigned long)len);
00323                 return -1;
00324         }
00325 
00326         dest->s = g_rewrite_uri;
00327         dest->len = len;
00328         p = dest->s;
00329         if (msg->parsed_uri.type == SIPS_URI_T) {
00330                 memcpy(p, SIPS_URI.s, SIPS_URI.len);
00331                 p += SIPS_URI.len;
00332         } else {
00333                 memcpy(p, SIP_URI.s, SIP_URI.len);
00334                 p += SIP_URI.len;
00335         }
00336         if (l_user.len) {
00337                 memcpy(p, rs->local_prefix.s, rs->local_prefix.len);
00338                 p += rs->local_prefix.len;
00339                 memcpy(p, l_user.s + strip, l_user.len - strip);
00340                 p += l_user.len - strip;
00341                 memcpy(p, rs->local_suffix.s, rs->local_suffix.len);
00342                 p += rs->local_suffix.len;
00343                 memcpy(p, AT_SIGN.s, AT_SIGN.len);
00344                 p += AT_SIGN.len;
00345         }
00346         /* this could be an error, or a blacklisted destination */
00347         if (rs->host.len == 0) {
00348                 *p = '\0';
00349                 return -1;
00350         }
00351         memcpy(p, rs->host.s, rs->host.len);
00352         p += rs->host.len;
00353         *p = '\0';
00354 
00355         if (descavp) {
00356                 avp_val.s = rs->comment;
00357                 if (add_avp(AVP_VAL_STR | descavp->v.pve->spec.pvp.pvn.u.isname.type,
00358                                         descavp->v.pve->spec.pvp.pvn.u.isname.name, avp_val)<0) {
00359                         LM_ERR("set AVP failed\n");
00360                         return -1;
00361                 }
00362         }
00363 
00364         return 0;
00365 }
00366 
00367 
00382 static int rewrite_on_rule(struct route_flags *rf_head, flag_t flags, str * dest,
00383                 struct sip_msg * msg, const str * user, const enum hash_source hash_source,
00384                 const enum hash_algorithm alg, gparam_t *descavp) {
00385         struct route_flags * rf;
00386         struct route_rule * rr;
00387         int prob;
00388 
00389         assert(rf_head != NULL);
00390 
00391         LM_DBG("searching for matching routing rules");
00392         for (rf = rf_head; rf != NULL; rf = rf->next) {
00393                 /* LM_DBG("actual flags %i, searched flags %i, mask %i and match %i", rf->flags, flags, rf->mask, flags&rf->mask); */
00394                 if ((flags&rf->mask) == rf->flags) break;
00395         }
00396 
00397         if (rf==NULL) {
00398                 LM_INFO("did not find a match for flags %d\n", flags);
00399                 return -1;
00400         }
00401 
00402         if (rf->rule_list == NULL) {
00403                 LM_INFO("empty rule list\n");
00404                 return 1;
00405         }
00406 
00407         switch (alg) {
00408                 case alg_crc32:
00409                         if(rf->dice_max == 0) {
00410                                 LM_ERR("invalid dice_max value\n");
00411                                 return -1;
00412                         }
00413                         if ((prob = hash_func(msg, hash_source, rf->dice_max)) < 0) {
00414                                 LM_ERR("could not hash message with CRC32");
00415                                 return -1;
00416                         }
00417                         /* This auto-magically takes the last rule if anything is broken.
00418                          * Sometimes the hash result is zero. If the first rule is off
00419                          * (has a probablility of zero) then it has also a dice_to of
00420                          * zero and the message could not be routed at all if we use
00421                          * '<' here. Thus the '<=' is necessary.
00422                          */
00423                         for (rr = rf->rule_list;
00424                                 rr->next != NULL && rr->dice_to <= prob;
00425                         rr = rr->next) {}
00426                         if (!rr->status) {
00427                                 if (!rr->backup) {
00428                                         LM_ERR("all routes are off\n");
00429                                         return -1;
00430                                 } else {
00431                                         if (!rr->backup->rr) {
00432                                                 LM_ERR("all routes are off\n");
00433                                                 return -1;
00434                                         }
00435                                         rr = rr->backup->rr;
00436                                 }
00437                         }
00438                         break;
00439                 case alg_crc32_nofallback:
00440                         if ((prob = (hash_func(msg, hash_source, rf->max_targets))) < 0) {
00441                                 LM_ERR("could not hash message with CRC32");
00442                                 return -1;
00443                         }
00444                         /* Instead of search the whole rule_list if there is something broken
00445                          * this function just tries only a backup rule and otherwise
00446                          * returns -1. This way we get an error
00447                          */
00448                         if ((rr = get_rule_by_hash(rf, prob + 1)) == NULL) {
00449                                 LM_CRIT("no route found\n");
00450                                 return -1;
00451                         }
00452                         break;
00453                 default:
00454                         LM_ERR("invalid hash algorithm\n");
00455                         return -1;
00456         }
00457         return actually_rewrite(rr, dest, msg, user, descavp);
00458 }
00459 
00460 
00478 static int rewrite_uri_recursor(struct dtrie_node_t * node,
00479                 const str * pm, flag_t flags, str * dest, struct sip_msg * msg, const str * user,
00480                 const enum hash_source hash_source, const enum hash_algorithm alg,
00481                 gparam_t *descavp) {
00482         str re_pm = *pm;
00483         void **ret;
00484         
00485         /* Skip over non-digits.  */
00486         while (re_pm.len > 0 && (!isdigit(*re_pm.s) && cr_match_mode == 10)) {
00487                 ++re_pm.s;
00488                 --re_pm.len;
00489         }
00490         ret = dtrie_longest_match(node, re_pm.s, re_pm.len, NULL, cr_match_mode);
00491 
00492         if (ret == NULL) {
00493                 LM_INFO("URI or prefix tree nodes empty, empty rule list\n");
00494                 return 1;
00495         }
00496         else return rewrite_on_rule(*ret, flags, dest, msg, user, hash_source, alg, descavp);
00497 }
00498 
00499 
00515 int cr_do_route(struct sip_msg * _msg, gparam_t *_carrier,
00516                 gparam_t *_domain, gparam_t *_prefix_matching,
00517                 gparam_t *_rewrite_user, enum hash_source _hsrc,
00518                 enum hash_algorithm _halg, gparam_t *_dstavp) {
00519 
00520         int carrier_id, domain_id, ret = -1;
00521         str rewrite_user, prefix_matching, dest;
00522         flag_t flags;
00523         struct route_data_t * rd;
00524         struct carrier_data_t * carrier_data;
00525         struct domain_data_t * domain_data;
00526         struct action act;
00527         struct run_act_ctx ra_ctx;
00528 
00529         if (fixup_get_svalue(_msg, _rewrite_user, &rewrite_user)<0) {
00530                 LM_ERR("cannot print the rewrite_user\n");
00531                 return -1;
00532         }
00533 
00534         if (fixup_get_svalue(_msg, _prefix_matching, &prefix_matching)<0) {
00535                 LM_ERR("cannot print the prefix_matching\n");
00536                 return -1;
00537         }
00538 
00539         flags = _msg->flags;
00540 
00541         do {
00542                 rd = get_data();
00543         } while (rd == NULL);
00544 
00545         carrier_id = cr_gp2id(_msg, _carrier, rd->carrier_map, rd->carrier_num);
00546         if (carrier_id < 0) {
00547                 LM_ERR("invalid carrier id %d\n", carrier_id);
00548                 release_data(rd);
00549                 return -1;
00550         }
00551 
00552         domain_id = cr_gp2id(_msg, _domain, rd->domain_map, rd->domain_num);
00553         if (domain_id < 0) {
00554                 LM_ERR("invalid domain id %d\n", domain_id);
00555                 release_data(rd);
00556                 return -1;
00557         }
00558         
00559         carrier_data=NULL;
00560         if (carrier_id < 0) {
00561                 if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) {
00562                         LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
00563                         carrier_data = get_carrier_data(rd, rd->default_carrier_id);
00564                 }
00565         } else if (carrier_id == 0) {
00566                 carrier_data = get_carrier_data(rd, rd->default_carrier_id);
00567         } else {
00568                 carrier_data = get_carrier_data(rd, carrier_id);
00569                 if (carrier_data == NULL) {
00570                         if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) {
00571                                 LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
00572                                 carrier_data = get_carrier_data(rd, rd->default_carrier_id);
00573                         }
00574                 }
00575         }
00576         if (carrier_data == NULL) {
00577                 LM_ERR("cannot get carrier data\n");
00578                 goto unlock_and_out;
00579         }
00580 
00581         domain_data = get_domain_data(carrier_data, domain_id);
00582         if (domain_data == NULL) {
00583                 LM_ERR("desired routing domain doesn't exist, prefix %.*s, carrier %d, domain %d\n",
00584                         prefix_matching.len, prefix_matching.s, carrier_id, domain_id);
00585                 goto unlock_and_out;
00586         }
00587 
00588         if (rewrite_uri_recursor(domain_data->tree, &prefix_matching, flags, &dest, _msg, &rewrite_user, _hsrc, _halg, _dstavp) != 0) {
00589                 /* this is not necessarily an error, rewrite_recursor does already some error logging */
00590                 LM_INFO("rewrite_uri_recursor doesn't complete, uri %.*s, carrier %d, domain %d\n", prefix_matching.len,
00591                         prefix_matching.s, carrier_id, domain_id);
00592                 goto unlock_and_out;
00593         }
00594 
00595         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);
00596 
00597         memset(&act, 0, sizeof(act));
00598         act.type = SET_URI_T;
00599         act.val[0].type = STRING_ST;
00600         act.val[0].u.string = dest.s;
00601         init_run_actions_ctx(&ra_ctx);
00602         ret = do_action(&ra_ctx, &act, _msg);
00603         if (ret < 0) {
00604                 LM_ERR("Error in do_action()\n");
00605         }
00606 
00607 unlock_and_out:
00608         release_data(rd);
00609         return ret;
00610 }
00611 
00612 
00623 int cr_load_user_carrier(struct sip_msg * _msg, gparam_t *_user, gparam_t *_domain, gparam_t *_dstavp) {
00624         str user, domain;
00625         int_str avp_val;
00626         
00627         if (fixup_get_svalue(_msg, _user, &user)<0) {
00628                 LM_ERR("cannot print the user\n");
00629                 return -1;
00630         }
00631 
00632         if (fixup_get_svalue(_msg, _domain, &domain)<0) {
00633                 LM_ERR("cannot print the domain\n");
00634                 return -1;
00635         }
00636         /* get carrier id */
00637         if ((avp_val.n = load_user_carrier(&user, &domain)) < 0) {
00638                 LM_ERR("error in load user carrier");
00639                 return -1;
00640         } else {
00641                 /* set avp */
00642                 if (add_avp(_dstavp->v.pve->spec.pvp.pvn.u.isname.type,
00643                                         _dstavp->v.pve->spec.pvp.pvn.u.isname.name, avp_val)<0) {
00644                         LM_ERR("add AVP failed\n");
00645                         return -1;
00646                 }
00647         }
00648         return 1;
00649 }
00650 
00651 
00666 int cr_route(struct sip_msg * _msg, gparam_t *_carrier,
00667                 gparam_t *_domain, gparam_t *_prefix_matching,
00668                 gparam_t *_rewrite_user, enum hash_source _hsrc,
00669                 gparam_t *_descavp)
00670 {
00671         return cr_do_route(_msg, _carrier, _domain, _prefix_matching,
00672                 _rewrite_user, _hsrc, alg_crc32, _descavp);
00673 }
00674 
00675 int cr_route5(struct sip_msg * _msg, gparam_t *_carrier,
00676                 gparam_t *_domain, gparam_t *_prefix_matching,
00677                 gparam_t *_rewrite_user, enum hash_source _hsrc)
00678 {
00679         return cr_do_route(_msg, _carrier, _domain, _prefix_matching,
00680                 _rewrite_user, _hsrc, alg_crc32, NULL);
00681 }
00682 
00683 
00700 int cr_nofallback_route(struct sip_msg * _msg, gparam_t *_carrier,
00701                 gparam_t *_domain, gparam_t *_prefix_matching,
00702                 gparam_t *_rewrite_user, enum hash_source _hsrc,
00703                 gparam_t *_dstavp)
00704 {
00705         return cr_do_route(_msg, _carrier, _domain, _prefix_matching,
00706                 _rewrite_user, _hsrc, alg_crc32_nofallback, _dstavp);
00707 }
00708 
00709 int cr_nofallback_route5(struct sip_msg * _msg, gparam_t *_carrier,
00710                 gparam_t *_domain, gparam_t *_prefix_matching,
00711                 gparam_t *_rewrite_user, enum hash_source _hsrc)
00712 {
00713         return cr_do_route(_msg, _carrier, _domain, _prefix_matching,
00714                 _rewrite_user, _hsrc, alg_crc32_nofallback, NULL);
00715 }
00716 
00717 
00731 int cr_load_next_domain(struct sip_msg * _msg, gparam_t *_carrier,
00732                 gparam_t *_domain, gparam_t *_prefix_matching,
00733                 gparam_t *_host, gparam_t *_reply_code, gparam_t *_dstavp) {
00734 
00735         int carrier_id, domain_id, ret = -1;
00736         str prefix_matching, host, reply_code;
00737         flag_t flags;
00738         struct route_data_t * rd;
00739         struct carrier_data_t * carrier_data;
00740         struct domain_data_t * domain_data;
00741 
00742         if (fixup_get_svalue(_msg, _prefix_matching, &prefix_matching)<0) {
00743                 LM_ERR("cannot print the prefix_matching\n");
00744                 return -1;
00745         }
00746         if (fixup_get_svalue(_msg, _host, &host)<0) {
00747                 LM_ERR("cannot print the host\n");
00748                 return -1;
00749         }
00750         if (fixup_get_svalue(_msg, _reply_code, &reply_code)<0) {
00751                 LM_ERR("cannot print the reply_code\n");
00752                 return -1;
00753         }
00754 
00755         flags = _msg->flags;
00756 
00757         do {
00758                 rd = get_data();
00759         } while (rd == NULL);
00760         
00761         carrier_id = cr_gp2id(_msg, _carrier, rd->carrier_map, rd->carrier_num);
00762         if (carrier_id < 0) {
00763                 LM_ERR("invalid carrier id %d\n", carrier_id);
00764                 release_data(rd);
00765                 return -1;
00766         }
00767 
00768         domain_id = cr_gp2id(_msg, _domain, rd->domain_map, rd->domain_num);
00769         if (domain_id < 0) {
00770                 LM_ERR("invalid domain id %d\n", domain_id);
00771                 release_data(rd);
00772                 return -1;
00773         }
00774 
00775         carrier_data=NULL;
00776         if (carrier_id < 0) {
00777                 if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) {
00778                         LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
00779                         carrier_data = get_carrier_data(rd, rd->default_carrier_id);
00780                 }
00781         } else if (carrier_id == 0) {
00782                 carrier_data = get_carrier_data(rd, rd->default_carrier_id);
00783         } else {
00784                 carrier_data = get_carrier_data(rd, carrier_id);
00785                 if (carrier_data == NULL) {
00786                         if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) {
00787                                 LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
00788                                 carrier_data = get_carrier_data(rd, rd->default_carrier_id);
00789                         }
00790                 }
00791         }
00792         if (carrier_data == NULL) {
00793                 LM_ERR("cannot get carrier data\n");
00794                 goto unlock_and_out;
00795         }
00796 
00797         domain_data = get_domain_data(carrier_data, domain_id);
00798         if (domain_data == NULL) {
00799                 LM_ERR("desired routing domain doesn't exist, prefix %.*s, carrier %d, domain %d\n",
00800                         prefix_matching.len, prefix_matching.s, carrier_id, domain_id);
00801                 goto unlock_and_out;
00802         }
00803 
00804         if (set_next_domain_recursor(domain_data->failure_tree, &prefix_matching, &host, &reply_code, flags, _dstavp) != 0) {
00805                 LM_INFO("set_next_domain_recursor doesn't complete, prefix '%.*s', carrier %d, domain %d\n", prefix_matching.len,
00806                         prefix_matching.s, carrier_id, domain_id);
00807                 goto unlock_and_out;
00808         }
00809         
00810         ret = 1;
00811         
00812 unlock_and_out:
00813         release_data(rd);
00814         return ret;
00815 }