####### Global Parameters ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 check_via=yes dns=no rev_dns=no disable_tcp=yes disable_dns_blacklist=yes auto_aliases=no listen=udp:79.12.254.153:5060 alias="zcall.com" ####### Modules Section ######## #set module path mpath="/usr/local/kamailio-1.4-pp/lib64/kamailio/modules/" /* loading module */ loadmodule "mi_fifo.so" loadmodule "db_mysql.so" loadmodule "sl.so" loadmodule "tm.so" loadmodule "rr.so" loadmodule "maxfwd.so" loadmodule "usrloc.so" loadmodule "registrar.so" loadmodule "textops.so" loadmodule "uri_db.so" loadmodule "uri.so" loadmodule "xlog.so" loadmodule "acc.so" loadmodule "auth.so" loadmodule "domain.so" loadmodule "avpops.so" loadmodule "nathelper.so" loadmodule "pike.so" loadmodule "lcr.so" loadmodule "rtimer.so" # ----------------- setting module-specific parameters --------------- # ----- mi_fifo params ----- modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") # ----- rr params ----- modparam("rr", "enable_full_lr", 1) modparam("rr", "append_fromtag", 1) # ----- rr params ----- modparam("registrar", "method_filtering", 1) # modparam("registrar", "append_branches", 0) modparam("registrar", "max_contacts", 4) modparam("registrar", "aor_avp", "$avp(i:200)") modparam("registrar", "received_avp", "$avp(i:201)") modparam("registrar", "max_expires", 600) # ----- uri_db params ----- modparam("uri_db", "use_uri_table", 0) modparam("uri_db", "db_url", "") # ----- acc params ----- /* what sepcial events should be accounted ? */ modparam("acc", "db_url", "mysql://openser:XXXXXXXX@192.168.1.11/openser") modparam("acc", "acc_time_column", "start_time") modparam("acc", "early_media", 0) modparam("acc", "report_ack", 0) modparam("acc", "report_cancels", 0) modparam("acc", "detect_direction", 0) modparam("acc", "failed_transaction_flag", 3) modparam("acc", "log_flag", 1) modparam("acc", "log_missed_flag", 2) modparam("acc", "db_flag", 1) modparam("acc", "db_missed_flag", 2) modparam("acc", "log_extra", "su_id=$avp(i:321);du_id=$avp(i:361);src_orig=$avp(i:381);dst_orig=$avp(i:382);dst_addr=$avp(i:383);src_ip=$si") modparam("acc", "db_extra", "su_id=$avp(i:321);du_id=$avp(i:361);src_orig=$avp(i:381);dst_orig=$avp(i:382);dst_addr=$avp(i:383);src_ip=$si") # ----- usrloc params ----- modparam("usrloc", "db_url", "mysql://openser:XXXXXXX@192.168.1.11/openser") modparam("usrloc", "db_mode", 2) modparam("usrloc", "timer_interval", 10) modparam("usrloc", "nat_bflag", 6) modparam("usrloc", "desc_time_order", 1) # ----- avpops params ----- modparam("avpops", "db_url", "mysql://openser:XXXXXXX@192.168.1.11/openser") modparam("avpops", "avp_table", "usr_preferences") # ----- domain params ----- modparam("domain", "db_url", "mysql://openser:XXXXXXX@192.168.1.11/openser") modparam("domain", "db_mode", 1) # Use caching # ----- auth params ----- modparam("auth", "nonce_expire", 300) modparam("auth", "rpid_avp", "$avp(i:202)") modparam("auth", "username_spec", "$var(username)") modparam("auth", "password_spec", "$var(password)") modparam("auth", "calculate_ha1", 1) # ----- tm params ----- modparam("tm", "fr_timer", 20) modparam("tm", "fr_inv_timer", 40) modparam("tm", "wt_timer", 5) modparam("tm", "fr_inv_timer_avp", "$avp(i:203)") # ----- maxfwd params ----- modparam("maxfwd", "max_limit", 15) # ----- nathelper ----- modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:7811") modparam("nathelper", "natping_interval", 30) modparam("nathelper", "ping_nated_only", 1) modparam("nathelper", "sipping_from", "sip:pinger@zcall.com") modparam("nathelper", "received_avp", "$avp(i:201)") modparam("nathelper", "sipping_bflag", 8) # ----- pike params ----- modparam("pike", "sampling_time_unit", 5) modparam("pike", "reqs_density_per_unit", 50) modparam("pike", "remove_latency", 4) # ----- lcr params ----- modparam("lcr", "db_url", "mysql://openser:XXXXXXX@192.168.1.11/openser") modparam("lcr", "fr_inv_timer",40) modparam("lcr", "fr_inv_timer_next",30) modparam("lcr", "fr_inv_timer_avp", "$avp(i:203)") modparam("lcr", "gw_uri_avp", "$avp(i:440)") modparam("lcr", "ruri_user_avp", "$avp(i:441)") modparam("lcr", "contact_avp", "$avp(i:442)") modparam("lcr", "flags_avp", "$avp(i:443)") modparam("lcr", "rpid_avp", "$avp(i:202)") # ----- rtimer params ----- modparam("rtimer", "timer", "name=ta;interval=60;mode=1;") modparam("rtimer", "exec", "timer=ta;route=24") ####### Routing Logic ######## # main request routing logic route[0]{ ##### ----- INITIAL CHECKS ----------------------------------------- if(from_uri=~"sip:.*@.+@.+") { xlog("+++++ bad from uri from IP: $si\n"); exit; } if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } if ( msg:len >= 8192 ) { sl_send_reply("513", "Message too big"); exit; } if (from_uri =~ "sip:[a-zA-Z0-9]+ .*@" ) { sl_send_reply("400", "Insane message with spaces in uri"); exit; } if ( is_method("NOTIFY") && is_domain_local("$rd") && $hdr(Event) =~ "keep-alive" ) { sl_send_reply("200", "OK - keepalive"); exit; } if (!has_totag() && $rd=="79.12.254.153") rewritehost("zcall.com"); ##### ----- NAT DETECTION ------------------------------------------ route(3); ##### ----- WITHIN DIALOG ------------------------------------------ if (has_totag()) { if (loose_route()) { if (is_method(“BYE”)) { setflag(1); # do accouting ... setflag(3); # ... even if the transaction fails route(21); } route(1); } else { if ( is_method(“ACK”) ) { if ( t_check_trans() ) { t_relay(); exit; } else { exit; } } sl_send_reply(“404”,”Not here”); } exit; } ##### ----- INITIAL REQUESTS ------------------------------------------ # CANCEL processing if (is_method(“CANCEL”)) { if (t_check_trans()) t_relay(); exit; } t_check_trans(); ##### ----- REGISTER FILTERING ---------------------------------------- if (is_method(“REGISTER”)) route(7); ##### ----- AUTHENTICATE ---------------------------------------------- if(!is_domain_local(“$fd”)) { if(!is_domain_local(“$rd”)) { xlog(“+++++ bad from fd from IP: $fd\n”); xlog(“+++++ bad from $rd from IP: $rd \n”); sl_send_reply(“403”, “Proxy forbidden”); exit; } } else { $var(u) = $fU; $var(d) = $fd; $var(p) = 0; if(!route(9)) { sl_send_reply(“404”, “Non-local user”); exit; } if(!route(8)) { sl_send_reply(“404”, “No user profile”); exit; } if($avp(i:323)==1 || $avp(i:323)==2) { sl_send_reply(“403”, “Not allowed”); exit; } route(6); setflag(4); } ##### ----- RECORD ROUTING -------------------------------------------- If (!is_method(“REGISTER|MESSAGE”)) record_route(); ##### ----- ACCOUNTING ------------------------------------------------ if (is_method("INVITE")) { setflag(1); # do accouting $avp(i:381) = $fu; $avp(i:382) = $ru; } ##### ----- LOCAL/FOREIGN DOMAIN FILTERING ------------------------------ if ( is_domain_local("$rd") || $rU=~"^000111" ) { Route(4); } else { route(5); } exit; } ###----------------------- RELAY --------------------------------------- route[1] { if (!issflagset(9)) { if (subst_uri('/(sip:.*);nty=yes/\1/')) setbflag(6); if (isflagset(5)) { route(2); search_append('Contact:.*sip:[^>[:cntrl:]]*', ';nty=yes'); } setsflag(9); } else { append_branch(); } t_on_branch("1"); if (!t_relay()) sl_reply_error(); exit; } ###----------------------- LOCAL dst ------------------------------------ route[4] { if ($rU==NULL) { # request with no Username in RURI sl_send_reply("484","Address Incomplete"); exit; } route(10); switch($var(dst_type)) { case 1: route(5); exit; case 2: $avp(i:200) = "sip:" + $avp(i:361) + "@zcall.com"; if (!lookup("location")) { switch ($retcode) { case -1: case -3: route(12); exit; case -2: if (issflagset(9)) { t_reply("405", "Method Not Allowed"); } else { sl_send_reply("405", "Method Not Allowed"); } exit; } } # when routing via usrloc, log the missed calls also setflag(2); t_on_failure("1"); route(1); exit; case 3: route(16); exit; default: route(19); exit; } route(1); exit; } ###----------------------- FOREIGN dst ---------------------------------- route[5] { $avp(i:383) := $ru; route(1); } ###----------------------- PSTN dst ---------------------------------- route[19] { if($rU =~ "^3[1-9]") { prefix("0000039"); } if($rU =~ "^0[1-9]") { prefix("0000039"); } if(!isflagset(4)) { if (issflagset(9)) { t_reply("403", "PSTN not allowed"); } else { sl_send_reply("403", "PSTN not allowed"); } } if (!load_gws()) { sl_send_reply("503", "Unable to load gateways"); exit; } if(!next_gw()){ sl_send_reply("503", "Unable to find a gateway"); exit; } route(20); exit; } ###----------------------- SET LOCAL dst -------------------------------- route[10] { $var(dst_type) = 0; # check emergency service numbers # check media server numbers if($rU =~ "^000111[0-9]+" || $rU =~ "^2[0-9]+$" || $rU=~ "^0698960860") { $var(dst_type) = 3; $avp(i:383) := $ru; return(1); } if ($rU=~"^[0-9][0-9]$") { if(!avp_db_query("select address from speed_dial where \ subsid='$avp(i:321)' and short_dial='$rU'", "$avp(i:100)") || !is_avp_set("$avp(i:100)")) { if (issflagset(9)) { t_reply("404", "Not Found - Invalid Speed dial"); } else { sl_send_reply("404", "Not Found - Invalid Speed dial"); } exit; } $ru = $avp(i:100); $avp(i:100) = null; $avp(i:383) := $ru; if ( !is_domain_local("$rd") ) { $var(dst_type) = 1; return(-1); } } $var(u) = $rU; $var(d) = $rd; $var(p) = 1; $avp(i:383) := $ru; if($rU=~"^[09][0-9]+$" && route(9)) { if(!route(8)) { sl_send_reply("404", "No user profile"); exit; } if($avp(i:363)==1) { sl_send_reply("404", "User suspended"); exit; } $var(dst_type) = 2; return(1); } if($rU =~ "^00[1-9]") { prefix("000"); } $avp(i:383) := $ru; return(1); } route[11] { rewritehostport("79.12.254.153"); setdsturi("sip:79.12.254.153:5068"); route(1); } route[22] { avp_db_query("insert into hanitest (hclient,hs) values ('from hani','route22') "); rewritehostport("79.12.254.153"); setdsturi("sip:79.12.254.153:5068"); if(isflagset(9)) { t_on_failure("2"); t_on_reply("2"); t_on_branch("2"); } if (issflagset(9)) append_branch(); if(!t_relay()) sl_reply_error(); exit; } ###----------------------- NAT detection -------------------------------- route[3] { force_rport(); if (nat_uac_test("19")) { if ( is_method("REGISTER") || ! is_present_hf("Record-Route")) { if (is_method("REGISTER")) { fix_nated_register(); } else { fix_nated_contact(); } setflag(5); # Mark as NATed source } } } ###----------------------- NAT processing ------------------------------- route[2] { if (is_method("BYE|CANCEL")) { unforce_rtp_proxy(); } else if (is_method("INVITE")) { if (nat_uac_test("8")) { force_rtp_proxy("co"); } else { force_rtp_proxy("cor"); } setbflag(7); t_on_failure("1"); t_on_reply("1"); } } ###----------------------- AUTHENTICATE --------------------------------- route[6] { if($var(p) == 0) { $var(password) = $avp(i:322); } else { $var(password) = $avp(i:362); } if(is_method("REGISTER")) { if(is_present_hf("Authorization")) { $var(username) = $au; if(!pv_www_authorize("")) { www_challenge(""/*realm*/,"0"/*qop*/); exit; } return(1); } else { www_challenge("","0"); exit; } # TODO add check-to } else { if(is_present_hf("Proxy-Authorization")) { $var(username) = $au; if(!pv_proxy_authorize("")) { proxy_challenge(""/*realm*/,"0"/*qop*/); exit; } consume_credentials(); return(1); } else { proxy_challenge("","0"); exit; } # TODO add check-fromm } } ###----------------------- REGISTRAR ------------------------------------ route[7] { # do AUTH if(!is_domain_local("$fd")) { sl_send_reply("403", "Registration forbidden"); exit; } $var(u) = $tU; $var(d) = $td; $var(p) = 1; if(!route(9)) { sl_send_reply("404", "Non-local user"); exit; } if(!route(8)) { sl_send_reply("404", "No user profile"); exit; } if($avp(i:363)==1) { sl_send_reply("403", "Registration not allowed"); exit; } route(6); # save source NAT flag if (isflagset(5)) { setbflag(6); # do SIP ping for everybody setbflag(8); } $avp(i:200) = "sip:" + $avp(i:361) + "@zcall.com"; if (!save("location")) { sl_send_reply("500", "Registrar error"); exit; } exit; } ###----------------------- LOAD PROFILE --------------------------------- route[8] { if($var(p) == 0) { if(!avp_db_query("select password, user_type from subscriber where \ subsid='$avp(i:321)'", "$avp(i:322),$avp(i:323)")) return(-1); } else { if(!avp_db_query("select password, user_type from subscriber where \ subsid='$avp(i:361)'", "$avp(i:362),$avp(i:363)")) return(-1); } return(1); } ###----------------------- DETECT SUBS ID ------------------------------- route[9] { if(!avp_db_query("select subsid from sipaliases where \ sip_username='$var(u)' and sip_domain='$var(d)'", "$avp(i:300)")) return(-1); if(!is_avp_set("$avp(i:300)")) return(-1); if($var(p) == 0) $avp(i:321) = $avp(i:300); else $avp(i:361) = $avp(i:300); $avp(i:300) := null; return(1); } route[12] { if ( !is_method("INVITE") ) { sl_send_reply("404", "Not Found"); exit; } # maybe send to VM ... if (issflagset(9)) { t_reply("404","user off-line"); } else { sl_send_reply("404", "user off-line"); } exit; } route[16] { if( !is_method("INVITE") ) return; if($rU=~"^000111") { strip(6); if($rU=~"^4") { strip(1); route(20); exit; } } switch($rU) { case "200": case "202": route(23); exit; case "234": $rU = "APP_WELCOME_IPS"; route(11); exit; case "235": $rU = "APP_ECHO"; route(11); exit; default: route(11); } if (issflagset(9)) { t_reply("404","No such app"); } else { sl_send_reply("404", "No such app"); } exit; } route[20] { if(!is_avp_set("$avp(i:321)")) { if (issflagset(9)) t_reply("403","Not allowed"); else sl_send_reply("403", "Not allowed"); exit; } $var(ppaccount) = $avp(i:321); avp_db_query("select count(*) from prp_acalls where account='$var(ppaccount)'", "$avp(i:1)"); if($avp(i:1)>0) { if (issflagset(9)) t_reply("403","Not allowed - active calls"); else sl_send_reply("403", "Not allowed - active calls"); exit; } $avp(i:1) = null; avp_db_query("select client_name from subscriber where subsid='$var(ppaccount)'","$avp(i:420)"); $var(ppclient) = $avp(i:420); avp_db_query("select agent,profile,plan,atype,credit from prp_accounts where client='$var(ppclient)'","$avp(i:433),$avp(i:434),$avp(i:421),$avp(i:422),$avp(i:423)"); $var(ppagent) = $avp(i:433); if(!is_avp_set("$avp(i:421)")) { if (issflagset(9)) t_reply("403","Not allowed - no account"); else sl_send_reply("403", "Not allowed - no account"); exit; } # chech agent credit and allow if has enough credit avp_db_query("select ag_credit, ag_profile from prp_agent where agent='$var(ppagent)'","$avp(i:424),$avp(i:425)"); # check agent credit if($avp(i:424)<=0 and $avp(i:425)==400) { if (issflagset(9)) t_reply("403","Not allowed - agent no credit"); else sl_send_reply("403", "Not allowed - agent no credit"); exit; } #check if client is enabled and has credit if($avp(i:422)!=0 || $avp(i:423)<=0) { if (issflagset(9)) t_reply("403","Not allowed - no credit"); else sl_send_reply("403", "Not allowed - no credit"); exit; } $var(pplan) = $avp(i:421); avp_db_query("select time_unit, rate from prp_rates where plan='$var(pplan)' and '$var(ppru)' like prefix order by prefix desc","$avp(i:426),$avp(i:427)"); avp_db_query("insert into hanitest (hclient,hs)values('$rU','$var(ppru)')"); if(!is_avp_set("$avp(i:427)")) { if (issflagset(9)) t_reply("403","Not allowed - no rate"); else sl_send_reply("403", "Not allowed - no rate"); } if($avp(i:423)<$avp(i:427)) { if (issflagset(9)) t_reply("403","Not allowed - no much credit"); else sl_send_reply("403", "Not allowed - no much credit"); exit; } # check agent sufficent credit if($avp(i:424)<$avp(i:427)) { if (issflagset(9)) t_reply("403","Not allowed -agent no much credit"); else sl_send_reply("403", "Not allowed -agent no much credit"); exit; } $var(tu) = $avp(i:423) / $avp(i:427); $var(tu) = $var(tu) * $avp(i:426); if($var(tu)>7200) $var(tu) = 7200; pv_printf($var(dst), "$rU@$rd"); if(!avp_db_query("insert into prp_acalls (callid,agent,ag_profile,client,account,profile,dest_addr,start_time,plan,time_unit,rate) values ('$ci',$var(ppagent),$avp(i:425),'$var(ppclient)','$var(ppaccount)',$avp(i:434),'$var(dst)',$Ts,'$avp(i:421)',$avp(i:426),$avp(i:427))")) { avp_db_query("insert into hanitest (hclient,hs)values('$var(ppclient)','haniroute 20erro3')"); if (issflagset(9)){ t_reply("403","Not allowed - no storage"); } } $avp(i:431) = $var(tu); setflag(9); if(isflagset(5)){ fix_nated_sdp("1"); } if($rU!="5566"){ $rU = "APP_PREPAID"; } avp_db_query("insert into hanitest (hclient,hs)values('$var(ppclient)','haniroute 20 ready for 22')"); route(22); } route[21] { avp_db_query("select agent,ag_profile,client,account,profile,dest_addr,start_time,plan,time_unit,rate from prp_acalls where callid='$ci'", "$avp(i:433),$avp(i:425),$avp(i:432),$avp(i:428),$avp(i:434),$avp(i:430),$avp(i:429),$avp(i:421),$avp(i:426),$avp(i:427)"); if(!is_avp_set("$avp(i:428)")) return(1); $var(dur) = $Ts - $avp(i:429); # cost 0 for calls below 10 secs if($var(dur) < 10 ){ $var(dur) =0; } $var(tu) = $var(dur)/$avp(i:426); $var(bd) = $var(tu)*$avp(i:426); if($var(bd)!=$var(dur)) $var(tu) = $var(tu) + 1; $var(cost) = $var(tu) * $avp(i:427); avp_db_query("insert into prp_cdrs (client,account,dest_addr,start_time,end_time,plan,cost,callid) values ('$avp(i:432)','$avp(i:428)','$avp(i:430)',$avp(i:429),$Ts,'$avp(i:421)',$var(cost),'$ci')"); # check if account is PostPaid if($avp(i:434)>1){ avp_db_query("update prp_accounts set credit=credit-$var(cost) where client='$avp(i:432)'"); } # add consumed credit avp_db_query("update prp_accounts set consumed_credit=consumed_credit+$var(cost) where client='$avp(i:432)'"); # check agent profile if($avp(i:425)<401){ avp_db_query("update prp_agent set ag_credit=ag_credit-$var(cost),ag_consumed_credit=ag_consumed_credit+$var(cost) where agent='$avp(i:433)'"); } avp_db_query("delete from prp_acalls where callid='$ci'"); } route[23] { if(!is_avp_set("$avp(i:321)")) { if (issflagset(9)) t_reply("403","Not allowed"); else sl_send_reply("403", "Not allowed"); exit; } $var(ppaccount) = $avp(i:321); avp_db_query("select count(*) from prp_acalls where account='$var(ppaccount)'","$avp(i:1)"); # Select client group for each susid avp_db_query("select client_name from subscriber where subsid='$var(ppaccount)'","$avp(i:420)"); $var(ppclient) = $avp(i:420); if($rU=="202") { append_hf("P-UID: $var(ppclient)\r\n"); if(isflagset(5)) fix_nated_sdp("1"); $rU = "APP_VOUCHERS"; route(22); exit; } if($avp(i:1)>0) { if (issflagset(9)) t_reply("403","Not allowed - active calls"); else sl_send_reply("403", "Not allowed - active calls"); exit; } $avp(i:1) = null; # modified to read credit of the client group avp_db_query("select credit from prp_accounts where client='$var(ppclient)'","$avp(i:423)"); if(!is_avp_set("$avp(i:423)")) { if (issflagset(9)) t_reply("403","Not allowed - no account"); else sl_send_reply("403", "Not allowed - no account"); exit; } $var(euro) = $avp(i:423)/1000000; $var(cent) = ($avp(i:423)%1000000)/10000; append_hf("P-Credit: $var(euro).$var(cent)\r\n"); if(isflagset(5)) fix_nated_sdp("1"); $rU = "APP_SAYCREDIT"; route(22); exit; } route[24] { avp_db_query("delete from prp_acalls where start_time<$Ts-7210"); } branch_route[1] { if (isflagset(5)) { setbflag(7); } else { if (isbflagset(6)) { route(2); } } } failure_route[1] { # only INVITEs here if ( isbflagset(6) && !isflagset(5) ) { unforce_rtp_proxy(); resetbflag(7); } if (t_was_cancelled()) { t_reply("487","Request cancelled"); exit; } if($avp(i:361)==null) exit; resetbflag(6); setsflag(9); # Redirect to voicemail ... ?!?! } failure_route[2] { if (t_was_cancelled()) { avp_db_query("delete from prp_acalls where callid='$ci'"); t_reply("487","Request cancelled"); exit; } setsflag(9); if(next_gw()) { pv_printf($var(dst), "$rU@$rd"); $rU = "APP_PREPAID"; route(22); exit; } avp_db_query("delete from prp_acalls where callid='$ci'"); } onreply_route[1] { if ( isbflagset(7) && status=~"(18[03])|(2[0-9][0-9])" && $hdr(Content-Type) =~ "application/sdp" ) { if (nat_uac_test("8")) { force_rtp_proxy("co"); } else { force_rtp_proxy("cor"); } } if (isbflagset(6)) { search_append('Contact:.*sip:[^>[:cntrl:]]*', ';nty=yes'); fix_nated_contact(); } exit; } onreply_route[2] { if ( status=~"2[0-9][0-9]" ) { avp_db_query("update prp_acalls set start_time=$Ts where callid='$ci'"); } } branch_route[2] { append_hf("P-PInfo: $avp(i:321),$avp(i:431),$var(dst)\r\n"); }