123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- ####### Routing Logic ########
- # Main SIP request routing logic
- # - processing of any incoming SIP request starts with this route
- # - note: this is the same as route { ... }
- request_route {
- # per request initial checks
- route(REQINIT);
- # NAT detection
- route(NATDETECT);
- # CANCEL processing
- if (is_method("CANCEL")) {
- if (t_check_trans()) {
- route(RELAY);
- }
- exit;
- }
- # handle requests within SIP dialogs
- route(WITHINDLG);
- ### only initial requests (no To tag)
- # handle retransmissions
- if(t_precheck_trans()) {
- t_check_trans();
- exit;
- }
- t_check_trans();
- # authentication
- route(AUTH);
- # record routing for dialog forming requests (in case they are routed)
- # - remove preloaded route headers
- remove_hf("Route");
- if (is_method("INVITE|SUBSCRIBE"))
- record_route();
- # account only INVITEs
- if (is_method("INVITE")) {
- setflag(FLT_ACC); # do accounting
- }
- # dispatch requests to foreign domains
- route(SIPOUT);
- ### requests for my local domains
- # 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] {
- # enable additional event routes for forwarded requests
- # - serial forking, RTP relaying handling, a.s.o.
- if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
- if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
- }
- if (is_method("INVITE|SUBSCRIBE|UPDATE")) {
- if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");
- }
- if (is_method("INVITE")) {
- if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
- }
- if (!t_relay()) {
- sl_reply_error();
- }
- exit;
- }
- # Per SIP request initial checks
- route[REQINIT] {
- #!ifdef WITH_ANTIFLOOD
- # flood dection from same IP and traffic ban for a while
- # be sure you exclude checking trusted peers, such as pstn gateways
- # - local host excluded (e.g., loop to self)
- if(src_ip!=myself) {
- if($sht(ipban=>$si)!=$null) {
- # ip is already blocked
- xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
- exit;
- }
- if (!pike_check_req()) {
- xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
- $sht(ipban=>$si) = 1;
- exit;
- }
- }
- if($ua =~ "friendly-scanner") {
- sl_send_reply("200", "OK");
- exit;
- }
- #!endif
- if (!mf_process_maxfwd_header("10")) {
- sl_send_reply("483","Too Many Hops");
- exit;
- }
- if(is_method("OPTIONS") && uri==myself && $rU==$null) {
- sl_send_reply("200","Keepalive");
- exit;
- }
- if(!sanity_check("1511", "7")) {
- xlog("Malformed SIP message from $si:$sp\n");
- exit;
- }
- }
- # Handle requests within SIP dialogs
- route[WITHINDLG] {
- if (!has_totag()) return;
- # sequential request withing a dialog should
- # take the path determined by record-routing
- if (loose_route()) {
- route(DLGURI);
- if (is_method("BYE")) {
- setflag(FLT_ACC); # do accounting ...
- setflag(FLT_ACCFAILED); # ... even if the transaction fails
- }
- else if ( is_method("ACK") ) {
- # ACK is forwarded statelessy
- route(NATMANAGE);
- }
- else if ( is_method("NOTIFY") ) {
- # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
- record_route();
- }
- route(RELAY);
- exit;
- }
- 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
- route(RELAY);
- exit;
- } else {
- # ACK without matching transaction ... ignore and discard
- exit;
- }
- }
- sl_send_reply("404", "Not here");
- exit;
- }
- # Handle SIP registrations
- route[REGISTRAR] {
- if (!is_method("REGISTER")) return;
- if(isflagset(FLT_NATS)) {
- setbflag(FLB_NATB);
- #!ifdef WITH_NATSIPPING
- # do SIP NAT pinging
- setbflag(FLB_NATSIPPING);
- #!endif
- }
- if (!save("location"))
- sl_reply_error();
- exit;
- }
- # User location service
- route[LOCATION] {
- if (!lookup("location")) {
- $var(rc) = $rc;
- t_newtran();
- switch ($var(rc)) {
- case -1:
- case -3:
- send_reply("404", "Not Found");
- exit;
- case -2:
- send_reply("405", "Method Not Allowed");
- exit;
- }
- }
- # when routing via usrloc, log the missed calls also
- if (is_method("INVITE")) {
- setflag(FLT_ACCMISSED);
- }
- route(RELAY);
- exit;
- }
- # IP authorization and user uthentication
- route[AUTH] {
- #!ifdef WITH_AUTH
- #!ifdef WITH_IPAUTH
- if((!is_method("REGISTER")) && allow_source_address()) {
- # source IP allowed
- return;
- }
- #!endif
- if (is_method("REGISTER") || from_uri==myself) {
- # authenticate requests
- if (!auth_check("$fd", "subscriber", "1")) {
- auth_challenge("$fd", "0");
- exit;
- }
- # user authenticated - remove auth header
- if(!is_method("REGISTER|PUBLISH"))
- consume_credentials();
- }
- # if caller is not local subscriber, then check if it calls
- # a local destination, otherwise deny, not an open relay here
- if (from_uri!=myself && uri!=myself) {
- sl_send_reply("403","Not relaying");
- exit;
- }
- #!endif
- return;
- }
- # Caller NAT detection
- route[NATDETECT] {
- #!ifdef WITH_NAT
- force_rport();
- if (nat_uac_test("19")) {
- if (is_method("REGISTER")) {
- fix_nated_register();
- } else {
- if(is_first_hop())
- set_contact_alias();
- }
- setflag(FLT_NATS);
- }
- #!endif
- return;
- }
- # RTPProxy control
- route[NATMANAGE] {
- #!ifdef WITH_NAT
- 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("co");
- if (is_request()) {
- if (!has_totag()) {
- if(t_is_branch_route()) {
- add_rr_param(";nat=yes");
- }
- }
- }
- if (is_reply()) {
- if(isbflagset(FLB_NATB)) {
- set_contact_alias();
- }
- }
- #!endif
- return;
- }
- # URI update for dialog requests
- route[DLGURI] {
- #!ifdef WITH_NAT
- if(!isdsturiset()) {
- handle_ruri_alias();
- }
- #!endif
- return;
- }
- # Routing to foreign domains
- route[SIPOUT] {
- if (uri==myself) return;
- append_hf("P-hint: outbound\r\n");
- route(RELAY);
- exit;
- }
- # 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;
- }
- }
|