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@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@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev