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@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(); ##} }