[sr-dev] recursive calls to failure_route strange behavior

Andres Moya andres.moya.i at gmail.com
Fri Nov 20 00:58:31 CET 2009


Dear all!

Please help. I have problem dealing with recursive call in failure route.

this route happen first time for authentication to external SIP provider 
(react on code 401), then it have response 480 i want to direct traffic 
to another operator via cr_route.

First i relay INVITE and getting 401, then sending authentication, but 
provider gives 480. I can see it in a dump of SIP session. But my 
failure_route still thinking that reply code is 401 on second reply. 
Maybe because i dont understand well how branches concept work here? Or 
using kamailio 3.0? ;) Looks like it give me status code of first reply 
and ignoring actual code in reply. :( I don't know if it something with 
development version or my own misunderstanding. sorry



route[PSTN_RELAY] {
    # open trans or it will complain on uac_replace_from
    if (!t_check_trans()) t_newtran();

#!ifdef WITH_NAT
    if (check_route_param("nat=yes")) {
        setbflag("6");
    }
    if (isflagset(5) || isbflagset("6")) {
        route(RTPPROXY);
    }
#!endif

    cr_user_carrier("$fU", "$fd", "$avp(s:carrier)");

    xlog ("L_INFO","carrier $avp(s:carrier) selected for $fU at $fd\n");
    $avp(s:domain)="route_domain1";
    if( !cr_route("$avp(s:carrier)", "$avp(s:domain)", "$rU", "$rU", 
"call_id") ){
        sl_send_reply("403", "Not allowed");
        xlog ("cr_route failed for $rU from $fU@$fd\n");
        t_release();
        exit;
    }

    #loading auth information for $rd (ruri domain) and replace "From" 
header
    route (LOAD_AUTH);

    xlog ("L_INFO","relaying to $rd\n");

    #reducing size to fit MTU
    remove_hf("User-Agent");
    remove_hf("P-Preferred-Identity");
    remove_hf("Record-route");
    remove_hf("a=nortpproxy");

    # setflag(11); # so failroute can procees carrierroute backup
    # we do all in one failure block;
    t_on_failure("FAIL_ONE");


    if (!t_relay()) {
        sl_reply_error();
    }
   
    exit;

}



#####  LOAD_AUTH ##########
# loading authentication information from carrierauth table
# set From field according to carrierauth information
# arguments:
# $rd - request uri doamin, sip provider carrier
# returns:
# avp(i:20) - rewrited host = $rd
# avp(i:21) - auth user
# avp(i:22) - auth pass
# avp(i:23) - auth realm
# avp(i:24) - auth domain

route[LOAD_AUTH]{
   xlog ("L_INFO","searching authentication for $rd host");
   $avp(i:20)=$rd;

   if ( avp_db_query(
      "SELECT username, password, realm, domain FROM carrierauth WHERE 
hostname='$rd'",
      "$avp(i:21);$avp(i:22);$avp(i:23);$avp(i:24)") > 0 ) {
      xlog ("L_INFO"," for $rd got user: $avp(i:21) pass: $avp(i:22) 
realm: $avp(i:23) domain: $avp(i:24)");

      # replace from_user at from_domain
      xlog("L_INFO","changing from -> sip:$avp(i:21)@$avp(i:24)");
      uac_replace_from("sip:$avp(i:21)@$avp(i:24)");
   }

   # we are not relaying authentications :)
   remove_hf("Authorization"); # remove client authentication

   # reset flag to mark no authentication yet performed
   resetflag(10); # let's use 10 to know uac authentication was sent

   return(1);

}

failure_route[FAIL_ONE] {
xlog("L_INFO","failure reply: $T_rpl($rr) $T_rpl($rs) $T_reply_code 
$branch(count) $rb\n");
#######
####### Here is a problem. Error code $T_reply_code is always 401 even 
for second time... I have 480 on ngrep
#######


   if ( t_check_status("401|407") ) # Unathorised reply
   { xlog("Authentication required \n");
      # have we already tried to authenticate? do we have auth 
information loaded?
      if (isflagset(10) || $avp(i:21)==$null ) # auth was already sent 
or we don't have auth info
      {
         xlog("Authentication to $avp(i:20) provider as 
$avp(i:21)@$avp(i:24) failed\n");
         t_reply("503","Authentication failed");
         avp_delete("$avp(i:20)");
         avp_delete("$avp(i:21)");
         avp_delete("$avp(i:22)");
         avp_delete("$avp(i:23)");
         avp_delete("$avp(i:24)");
         exit(); # :(

      }

      # if call from here LOAD_AUTH will look for original uri, not 
rewriten before
      if( !is_avp_set("$avp(i:20)") || $avp(i:20)=='') # if LAOD_AUTH 
was not done yet
         route (LOAD_AUTH); # loads auth avps and rewrite 'from' field

      # this avps loaded before by LOAD_AUTH
      # avp(i:20) - rewrited host
      # avp(i:21) - auth user
      # avp(i:22) - auth pass
      # avp(i:23) - auth realm
      # avp(i:24) - auth domain

      remove_hf("Authorization"); # remove client authentication
      if (uac_auth()) # adding auth header
      {
         xlog("L_INFO","Authorization header set, sending...");
         # mark that auth was performed
         setflag(10);
         # trigger again the failure route
         t_on_failure("FAIL_ONE");
         # repeat the request with auth response this time
         append_branch(); # ?
         t_relay();
         exit;
      }
   }

   # In case of failure on PSTN provider, send it to an alternative route:
   if ( t_check_status("408|5[0-9][0-9]")) {
#   if ( isflagset(11) && t_check_status("408|5[0-9][0-9]")) {

      revert_uri();
      if (!cr_next_domain("$avp(s:carrier)", "$avp(s:domain)", "$rU",
            "$rd", "$T_reply_code", "$avp(s:domain)")) {
         xlog("L_ERR", "cr_next_domain failed\n");
         exit;
      }
      if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", "$rU", "$rU",
            "call_id")) {
         xlog("L_ERR", "cr_route failed\n");
         exit;
      }

      route(LOAD_AUTH);
   
      t_on_failure("FAIL_ONE");
      append_branch();
      if (!t_relay()) {
         xlog("L_ERR", "t_relay to $rd failed\n");
         exit;
      }


   }

#!ifdef WITH_NAT
   if (is_method("INVITE")
         && (isbflagset("6") || isflagset(5))) {
      unforce_rtp_proxy();
   }
#!endif

   if (t_is_canceled()) {
      exit;
   }

   # uncomment the following lines if you want to block client
   # redirect based on 3xx replies.
   ##if (t_check_status("3[0-9][0-9]")) {
   ##t_reply("404","Not found");
   ##   exit;
   ##}

   # uncomment the following lines if you want to redirect the failed
   # calls to a different new destination
   ##if (t_check_status("486|408")) {
   ##   sethostport("192.168.2.100:5060");
   ##   append_branch();
   ##   # do not set the missed call flag again
   ##   t_relay();
   ##}
}



More information about the sr-dev mailing list