######################################################################## # Request route 'main' ######################################################################## route[0] { xlog("L_INFO", "New request - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); force_rport(); if(msg:len > max_len) { xlog("L_INFO", "Message too big - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("513", "Message Too Big"); exit; } if (!mf_process_maxfwd_header("10")) { xlog("L_INFO", "Too many hops - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("483", "Too Many Hops"); exit; } if(!is_method("REGISTER")) { if(nat_uac_test("19")) { record_route(";nat=yes"); } else { record_route(); } } if(is_method("CANCEL") || is_method("BYE")) { end_media_session(); } if(loose_route()) { if(!has_totag()) { xlog("L_INFO", "Initial loose-routing rejected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("403", "Initial Loose-Routing Rejected"); exit; } if(nat_uac_test("19") || search("^Route:.*;nat=yes")) { fix_nated_contact(); setflag(6); } route(8); } if(is_method("REGISTER")) { route(7); } if(is_method("INVITE")) { route(9); } if(is_method("CANCEL") || is_method("ACK")) { route(15); } route(16); } ######################################################################## # Request route 'clear-usr-preferences-caller' ######################################################################## route[1] { xlog("L_INFO", "Clear caller preferences - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); avp_delete("$avp(s:caller_cli)/g"); avp_delete("$avp(s:clir)/g"); } ######################################################################## # Request route 'clear-usr-preferences-callee' ######################################################################## route[2] { xlog("L_INFO", "Clear callee preferences - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); avp_delete("$avp(s:callee_fr_inv_timer)/g"); avp_delete("$avp(s:cfu)/g"); avp_delete("$avp(s:cfc)/g"); } ######################################################################## # Request route 'usr-preferences-caller' ######################################################################## route[3] { route(1); xlog("L_INFO", "Load caller preferences for uuid '$avp(s:caller_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); # load caller avps avp_db_load("$avp(s:caller_uuid)", "*"); avp_copy("$avp(s:cli)", "$avp(s:caller_cli)/d"); if(is_avp_set("$avp(s:clir)/n") && avp_check("$avp(s:clir)", "eq/i:1")) { # mark for anonymization setflag(28); } } ######################################################################## # Request route 'usr-preferences-callee' ######################################################################## route[4] { xlog("L_INFO", "Load callee preferences for uuid '$avp(s:callee_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); # load callee avps avp_db_load("$avp(s:callee_uuid)", "*"); if(is_avp_set("$avp(s:cfu)/s")) { xlog("L_INFO", "Call-forward-unconditional to '$avp(s:cfu)' found - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); avp_delete("$avp(s:caller_uuid)/g"); avp_copy("$avp(s:callee_uuid)", "$avp(s:caller_uuid)/d"); avp_pushto("$ru", "$avp(s:cfu)"); route(3); route(10); exit; } if(is_avp_set("$avp(s:ringtimeout)/n")) { xlog("L_INFO", "Setting ring timeout to $avp(s:ringtimeout) secs - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); avp_copy("$avp(s:ringtimeout)", "$avp(s:callee_fr_inv_timer)/d"); } } ######################################################################## # Request route 'clir' ######################################################################## route[5] { if(isflagset(28) && !isflagset(27)) { setflag(27); xlog("L_INFO", "Anonymize caller - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); uac_replace_from("Anonymous","sip:anonymous@anonymous.invalid"); if(is_present_hf("Privacy")) { remove_hf("Privacy"); } append_hf("Privacy: id\r\n"); } } ######################################################################## # Request route 'stop-media-proxy' ######################################################################## route[6] { if(isflagset(22)) { end_media_session(); } } ######################################################################## # Request route 'base-route-register' ######################################################################## route[7] { sl_send_reply("100", "Trying"); if(!www_authorize("", "subscriber")) { xlog("L_INFO", "Register authentication failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); www_challenge("", "0"); exit; } if(!check_to()) { xlog("L_INFO", "Spoofed To-URI detected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("403", "Spoofed To-URI Detected"); exit; } consume_credentials(); if(!search("^Contact:[ ]*\*") && nat_uac_test("19")) { fix_nated_register(); setflag(6); } if(!save("location")) { xlog("L_ERR", "Saving contact failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_reply_error(); exit; } xlog("L_INFO", "Registration successful - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); exit; } ######################################################################## # Request route 'base-outbound' ######################################################################## route[8] { if(is_present_hf("P-Asserted-Identity")) { remove_hf("P-Asserted-Identity"); } if(is_present_hf("Remote-Party-ID")) { remove_hf("Remote-Party-ID"); } if(is_avp_set("$avp(s:caller_cli)/s")) { if(!isflagset(28)) { xlog("L_INFO", "Set caller CLI '$avp(s:caller_cli)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); append_hf("P-Asserted-Identity: <$avp(s:caller_cli)>\r\n"); } } route(5); if(isflagset(6)) { if(!isflagset(22) && !search("^Content-Length:[ ]*0")) { setflag(22); use_media_proxy(); } t_on_reply("2"); } else { t_on_reply("1"); } if(!isflagset(21)) { t_on_failure("2"); } if(isflagset(29)) { append_branch(); } if(is_present_hf("Proxy-Authorization")) { consume_credentials(); } xlog("L_INFO", "Request leaving server, D-URI='$du' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); if(!t_relay()) { sl_reply_error(); if(is_method("INVITE") && isflagset(6)) { end_media_session(); } } exit; } ######################################################################## # Request route 'base-route-invite' ######################################################################## route[9] { sl_send_reply("100", "Trying"); if(from_gw()) { avp_write("s:0", "$avp(s:caller_uuid)"); xlog("L_INFO", "Call from PSTN' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); setflag(23); } else { if(allow_trusted()) { if(is_avp_set("$avp(s:peer_uuid)/s")) { # use tag-column from trusted-table as uuid for this caller avp_copy("$avp(s:peer_uuid)", "$avp(s:caller_uuid)/d"); } else { # if no uuid is set, use "0" as default uuid avp_write("s:0", "$avp(s:caller_uuid)"); } xlog("L_INFO", "Call from trusted peer with uuid '$avp(s:caller_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); if(!is_domain_local("$ruri")) { xlog("L_INFO", "Rejecting peering attempt with non-local request domain - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("403", "Relaying Denied"); exit; } #setflag(23); } else { if(!proxy_authorize("", "subscriber")) { xlog("L_INFO", "Proxy authentication failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); proxy_challenge("", "0"); exit; } if(!check_from()) { xlog("L_INFO", "Spoofed From-URI detected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("403", "Spoofed From-URI Detected"); exit; } } } route(3); if(nat_uac_test("19")) { fix_nated_contact(); setflag(6); } route(10); } ######################################################################## # Request route 'invite-find-callee' ######################################################################## route[10] { if(alias_db_lookup("dbaliases")) { xlog("L_INFO", "Callee was aliased - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); } route(2); if(!is_domain_local("$ruri")) { setflag(20); avp_write("s:0", "$avp(s:callee_uuid)"); route(12); } avp_delete("$avp(s:callee_uuid)"); avp_db_query("select uuid from subscriber where username = '$rU'", "$avp(s:callee_uuid)"); if(is_avp_set("$avp(s:callee_uuid)/s")) { xlog("L_INFO", "Callee is local, uuid='$avp(s:callee_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(11); } else { avp_write("s:0", "$avp(s:callee_uuid)"); xlog("L_INFO", "Callee is not local - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(12); } exit; } ######################################################################## # Request route 'invite-to-internal' ######################################################################## route[11] { route(4); if(!lookup("location")) { xlog("L_INFO", "Local user offline - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("404", "User Offline"); } else { xlog("L_INFO", "Local user online - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(8); } exit; } ######################################################################## # Request route 'invite-to-external' ######################################################################## route[12] { if(isflagset(20)) { xlog("L_INFO", "Call to foreign domain - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(8); exit; } route(14); if(!isflagset(23)) { # don't allow calls relaying from PSTN to PSTN, if not explicitely forwarded if(uri =~ "^sip:[0-9]+@") { # only route numeric users to PSTN if(!load_gws()) { xlog("L_ERR", "Error loading PSTN gateways - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("503", "PSTN Termination Currently Unavailable"); exit; } if(!next_gw()) { xlog("L_ERR", "No PSTN gateways available - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("503", "PSTN Termination Currently Unavailable"); exit; } setflag(21); t_on_failure("1"); route(8); } } xlog("L_INFO", "Call to unknown user - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("404", "User Not Found"); exit; } ######################################################################## # Request route 'normalize-e164' ######################################################################## route[13] { # European numbering plans look like this: # CC = country code (i.e. 43 for Austria) # NDC = national destination code (i.e. 1 for Vienna) # SN = subscriber number (i.e. 4001234) # # CC + NDC + SN, i.e. 4314001234 # # Within the same CC+NDC, it can be omitted, so if # +4314001234 wants to call +4315002345, one can dial # just 5002345. # # Within the same CC, CC can be ommitted and a "0" is prefixed # to NDC, so if +4314001234 wants to call +4326003456, # one can dial 026003456. # # For international calls, either "00" or + is prefixed, like # +49123456780 or 0049123456789. # avp_delete("$avp(s:orig_callee_user)/g"); avp_write("$rU", "$avp(s:orig_callee_user)"); if(uri =~ "^sip:(\+[1-9])?[0-9]+@") { # looks like a PSTN number if(uri =~ "^sip:0[1-9][0-9]+@") { # we have format 0+NDC+SN strip(1); prefix("+39"); } else if(uri =~ "^sip:00[1-9]+@") { # we have format 00 + CC + NDC + SN strip(2); prefix("+"); } else if(!uri =~ "^sip:\+[1-9][0-9]+@") { # unknown format, maybe NDC wasn't added before? xlog("L_INFO", "Not normalized callee '$avp(s:orig_callee_user)' to E.164 format - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); return(-1); } # else we have "+" + CC + NDC + SN xlog("L_INFO", "Normalized callee '$avp(s:orig_callee_user)' to E.164 format '$rU' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); return(1); } else { xlog("L_INFO", "Not normalized callee '$avp(s:orig_callee_user)' to E.164 format - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); return(-1); } } ######################################################################## # Request route 'lookup-enum' ######################################################################## route[14] { route(13); if(retcode == 1) { if(enum_query("e164.org.")) { # TODO: do GW fallback (load gws, set failure-route)? xlog("L_INFO", "ENUM query succeeded - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(8); exit; } else { xlog("L_INFO", "ENUM query failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); # ENUM query failed, revert $rU avp_pushto("$ru/username", "$avp(s:orig_callee_user)"); } } } ######################################################################## # Request route 'base-route-local' ######################################################################## route[15] { t_on_reply("1"); if(t_check_trans()) { xlog("L_INFO", "Request leaving server - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); if(!t_relay()) { sl_reply_error(); } } else { xlog("L_INFO", "Dropping mis-routed request - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); } exit; } ######################################################################## # Request route 'base-route-generic' ######################################################################## route[16] { xlog("L_INFO", "Method not supported - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); sl_send_reply("501", "Method Not Supported Here"); exit; } ######################################################################## # Request route 'base-filter-failover' ######################################################################## route[17] { if(!t_check_status("408|500|503")) { xlog("L_INFO", "No failover routing needed for this response code - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(6); exit; } } ######################################################################## # Reply route 'base-standard-reply' ######################################################################## onreply_route[1] { xlog("L_INFO", "Reply - S=$rs D=$rr F=$fu T=$tu IP=$si ID=$ci\n"); exit; } ######################################################################## # Reply route 'base-nat-reply' ######################################################################## onreply_route[2] { xlog("L_INFO", "NAT-Reply - S=$rs D=$rr F=$fu T=$tu IP=$si ID=$ci\n"); if(nat_uac_test("1")) { fix_nated_contact(); } if(isflagset(6) && status=~"(180)|(183)|2[0-9][0-9]") { if(!search("^Content-Length:[ ]*0")) { use_media_proxy(); } } exit; } ######################################################################## # Failure route 'pstn-failover' ######################################################################## failure_route[1] { xlog("L_INFO", "Failure route for PSTN entered - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(17); if(!next_gw()) { xlog("L_ERR", "Failed to select next PSTN gateway - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(6); exit; } t_on_failure("1"); route(8); } ######################################################################## # Failure route 'base-standard-failure' ######################################################################## failure_route[2] { if(t_check_status("422|481|487")) { xlog("L_INFO", "Final reply - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(6); exit; } t_on_branch("1"); xlog("L_INFO", "Redirect from UAC intercepted - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(10); if(avp_check("$avp(s:cfc)", "re/^.+$")) { avp_pushto("$ru", "$avp(s:cfc)"); setflag(29); append_branch(); t_on_branch("1"); xlog("L_INFO", "CFC detected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); route(10); } route(17); route(6); } ######################################################################## # Branch route 'cfc-drop-local' ######################################################################## branch_route[1] { if(!is_domain_local("$ruri")) { xlog("L_INFO", "Dropping local branch - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n"); drop(); } }