request_route { ## Per request initial checks route(REQINIT); ## NAT detection route(NATDETECT); ## Handle requests within SIP dialogs route(WITHINDLG); ## CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) { t_relay(); } exit; } t_check_trans(); ## Authentication route(AUTH); remove_hf("Route"); if (is_method("INVITE")) record_route(); # account only INVITEs if (is_method("INVITE")) { setflag(FLT_ACC); # do accounting } ## Outgoing calls route(SIPOUT); ## Handle registrations route(REGISTRAR); if ($rU==$null) { # request with no Username in RURI sl_send_reply("484","Address Incomplete"); exit; } # user location service route(LOCATION); route(RELAY); } route[RELAY] { # enable additional event routes for forwarded requests # - serial forking, RTP relaying handling, a.s.o. if (is_method("INVITE")) { t_on_branch("MANAGE_BRANCH"); t_on_reply("MANAGE_REPLY"); } if (is_method("INVITE")) { t_on_failure("MANAGE_FAILURE"); } if (!t_relay()) { sl_reply_error(); } } route[REQINIT] { ## No more than 10 hops away if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } ## No more than 2K message if (msg:len >= 2048 ) { sl_send_reply("513", "Message too big"); } } route[NATDETECT] { force_rport(); if (!search("^Contact:[ ]*\*") && nat_uac_test("19")) { if (is_method("REGISTER")) { fix_nated_register(); } else { fix_nated_contact(); } setflag(FLT_NATS); } return; } route[NATMANAGE] { if (is_request()) { if(has_totag()) { if(check_route_param("nat=yes")) { setbflag(FLB_NATB); } } } if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; rtpproxy_manage(); if (is_request()) { if (!has_totag()) { add_rr_param(";nat=yes"); } } if (is_reply()) { if(isbflagset(FLB_NATB)) { fix_nated_contact(); } } return; } route[WITHINDLG] { if (has_totag()) { # sequential request withing a dialog should # take the path determined by record-routing if (loose_route()) { if (is_method("BYE")) { setflag(FLT_ACC); # do accounting ... setflag(FLT_ACCFAILED); # ... even if the transaction fails } if ( is_method("ACK") ) { # ACK is forwarded statelessy route(NATMANAGE); } route(RELAY); } else { if ( is_method("ACK") ) { if ( t_check_trans() ) { # no loose-route, but stateful ACK; # must be an ACK after a 487 # or e.g. 404 from upstream server t_relay(); exit; } else { # ACK without matching transaction ... ignore and discard exit; } } sl_send_reply("404","Not here"); } exit; } } route[AUTH] { if (is_method("REGISTER")) { ## Authenticate the REGISTER requests (uncomment to enable auth) if (!www_authorize("$td", "subscriber")) { www_challenge("$td", "0"); exit; } if ($au!=$tU) { sl_send_reply("403","Forbidden auth ID"); exit; } } else { ## Authenticate if from local subscriber if (from_uri==myself) { if (!proxy_authorize("$fd", "subscriber")) { proxy_challenge("$fd", "0"); exit; } consume_credentials(); # caller authenticated } else { # caller is not local subscriber, then check if it calls # a local destination, otherwise deny, not an open relay here if (!uri==myself) { sl_send_reply("403","Not relaying"); exit; } } } return; } route[SIPOUT] { if (!uri==myself) { append_hf("P-hint: outgoing call\r\n"); route(RELAY); } } route[REGISTRAR] { if (is_method("REGISTER")) { if(isflagset(FLT_NATS)) { setbflag(FLB_NATB); } if (!save("location")) sl_reply_error(); exit; } } route[LOCATION] { if (!lookup("location")) { t_newtran(); switch ($var(rc)) { case -1: case -3: send_reply("404", "Not Found"); exit; case -2: send_reply("405", "Method Not Allowed"); exit; } } if (is_method("INVITE")) { setflag(FLT_ACCMISSED); } } # manage outgoing branches branch_route[MANAGE_BRANCH] { xdbg("new branch [$T_branch_idx] to $ru\n"); route(NATMANAGE); } # manage incoming replies onreply_route[MANAGE_REPLY] { xdbg("incoming reply\n"); if(status=~"[12][0-9][0-9]") route(NATMANAGE); } # manage failure routing cases failure_route[MANAGE_FAILURE] { route(NATMANAGE); if (t_is_canceled()) { exit; } }