[sr-dev] recursive calls to failure_route strange behavior

Miklos Tirpak miklos at iptel.org
Fri Nov 20 09:53:03 CET 2009


On 11/20/2009 12:58 AM, Andres Moya wrote:
> 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

This is correct, the proxy must choose one of the two responses to 
forward and 401 has higher precedence than 480 (RFC3261, 16.7: "Choosing 
the best response"). The failure route always works on the selected 
response as opposed to the last response received.

Try to add t_drop_replies() to the failure route block when the 401 is 
processed. This function drops all the existing replies, 401 in your 
case, hence 401 will not be selected again when 480 is received.

Miklos

> 
> 
> 
> 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();
>   ##}
> }
> 
> _______________________________________________
> sr-dev mailing list
> sr-dev at lists.sip-router.org
> http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev



More information about the sr-dev mailing list