| @ -0,0 +1,469 @@ | |||||
| ## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ## | |||||
| #### Preprocessor Directives ######### | |||||
| #!define L_ALERT -5 | |||||
| #!define L_BUG -4 | |||||
| #!define L_CRIT2 -3 | |||||
| #!define L_CRIT -2 | |||||
| #!define L_ERR -1 | |||||
| #!define L_WARN 0 | |||||
| #!define L_NOTICE 1 | |||||
| #!define L_INFO 2 | |||||
| #!define L_DBG 3 | |||||
| #!define AVP_RECV_PARAM "recv_param" | |||||
| #!define AVP_LOG_LEVEL "log_level" | |||||
| #!define AVP_ROUTE_CNT "route_cnt" | |||||
| #!define AVP_ASSOCIATED_SERVER "associated_server" | |||||
| #!define AVP_ASSOCIATE_CONTACT "associate_contact" | |||||
| ####### Flags ####### | |||||
| flags | |||||
| FLAG_INTERNALLY_SOURCED: 1, | |||||
| FLAG_ASSOCIATE_SERVER: 2, | |||||
| FLAG_SKIP_NAT_CORRECTION: 3, | |||||
| FLAG_ASSOCIATE_USER: 4; | |||||
| #!define FLB_NATB 1 | |||||
| #!define FLB_NATSIPPING 2 | |||||
| #!define FLB_UAC_REDIRECT 3 | |||||
| ####### Global Parameters ######### | |||||
| fork = yes | |||||
| children = 25 | |||||
| server_signature = no | |||||
| server_header = "Server: Kazoo" | |||||
| user_agent_header = "User-Agent: Kazoo" | |||||
| shm_force_alloc = yes | |||||
| mlock_pages = yes | |||||
| phone2tel = 1 | |||||
| max_while_loops = 500 | |||||
| ####### Logging Parameters ######### | |||||
| debug = L_INFO | |||||
| memdbg = 10 | |||||
| memlog = 10 | |||||
| corelog = L_ERR | |||||
| log_stderror = no | |||||
| log_facility = LOG_LOCAL0 | |||||
| log_name="kamailio" | |||||
| ####### Alias Parameters ######### | |||||
| auto_aliases = yes | |||||
| ####### Binding Parameters ######### | |||||
| tos = IPTOS_LOWDELAY | |||||
| ####### TCP Parameters ######### | |||||
| tcp_children = 25 | |||||
| disable_tcp = no | |||||
| tcp_max_connections = 4096 | |||||
| tcp_connection_lifetime = 3605 | |||||
| tcp_accept_aliases = no | |||||
| tcp_async = yes | |||||
| tcp_connect_timeout = 10 | |||||
| tcp_conn_wq_max = 65536 | |||||
| tcp_crlf_ping = yes | |||||
| tcp_delayed_ack = yes | |||||
| tcp_fd_cache = yes | |||||
| tcp_keepalive = yes | |||||
| tcp_keepcnt = 3 | |||||
| tcp_keepidle = 30 | |||||
| tcp_keepintvl = 10 | |||||
| tcp_linger2 = 30 | |||||
| tcp_rd_buf_size = 4096 | |||||
| tcp_send_timeout = 10 | |||||
| tcp_wq_blk_size = 2100 | |||||
| tcp_wq_max = 10485760 | |||||
| ####### UDP Parameters ######### | |||||
| udp4_raw = -1 | |||||
| ####### DNS Parameters ######### | |||||
| dns = no | |||||
| rev_dns = no | |||||
| dns_try_ipv6 = no | |||||
| use_dns_cache = on | |||||
| dns_cache_del_nonexp = no | |||||
| dns_cache_flags = 1 | |||||
| dns_cache_gc_interval = 120 | |||||
| dns_cache_init = 1 | |||||
| dns_cache_mem = 1000 | |||||
| dns_cache_negative_ttl = 60 | |||||
| dns_try_naptr = no | |||||
| use_dns_failover = off | |||||
| dns_srv_lb = off | |||||
| ####### TLS Parameters ######### | |||||
| enable_tls = yes | |||||
| ####### SCTP Parameters ######### | |||||
| disable_sctp = yes | |||||
| ####### Custom Parameters ######### | |||||
| ####### Modules Section ######## | |||||
| mpath="/usr/lib64/kamailio/modules/" | |||||
| ######## Kamailio core extensions module ######## | |||||
| loadmodule "kex.so" | |||||
| ######## Transaction (stateful) module ######## | |||||
| loadmodule "tm.so" | |||||
| loadmodule "tmx.so" | |||||
| modparam("tm", "auto_inv_100", 1) | |||||
| modparam("tm", "auto_inv_100_reason", "Attempting to connect your call") | |||||
| modparam("tm", "cancel_b_method", 2) | |||||
| modparam("tm", "ruri_matching", 0) | |||||
| modparam("tm", "failure_reply_mode", 3) | |||||
| # modparam("tm", "fr_timer", 30000) | |||||
| # modparam("tm", "fr_inv_timer", 120000) | |||||
| ######## Stateless replier module ######## | |||||
| loadmodule "sl.so" | |||||
| ######## Record-Route and Route module ######## | |||||
| loadmodule "rr.so" | |||||
| modparam("rr", "enable_full_lr", 1) | |||||
| modparam("rr", "enable_double_rr", 0) | |||||
| ######## Max-Forward processor module ######## | |||||
| loadmodule "maxfwd.so" | |||||
| ######## SIP utilities [requires sl] ######## | |||||
| loadmodule "siputils.so" | |||||
| ######## SIP message formatting sanity checks [requires sl] ######## | |||||
| loadmodule "sanity.so" | |||||
| # sip_version, scheme, req_headers, cseq_method/value | |||||
| # content_length, parse_uri, digest | |||||
| modparam("sanity", "default_checks", 3303) | |||||
| modparam("sanity", "uri_checks", 3) | |||||
| modparam("sanity", "autodrop", 0) | |||||
| ######## Text operations module ######## | |||||
| loadmodule "textops.so" | |||||
| loadmodule "textopsx.so" | |||||
| ######## Generic Hash Table container in shared memory ######## | |||||
| loadmodule "htable.so" | |||||
| modparam("htable", "htable", "associations=>size=16;autoexpire=7200") | |||||
| ######## Pseudo-Variables module ######## | |||||
| loadmodule "pv.so" | |||||
| ######## Advanced logger module ######## | |||||
| loadmodule "xlog.so" | |||||
| ####### FIFO support for Management Interface ######## | |||||
| loadmodule "mi_fifo.so" | |||||
| modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") | |||||
| ######## UAC Redirection module ######## | |||||
| loadmodule "uac_redirect.so" | |||||
| ####### Role Configurations ########## | |||||
| #!ifdef DISPATCHER-ROLE | |||||
| include_file "dispatcher-role.cfg" | |||||
| #!endif | |||||
| #!ifdef REGISTRAR-ROLE | |||||
| include_file "registrar-role.cfg" | |||||
| #!endif | |||||
| #!ifdef PRESENCE-ROLE | |||||
| include_file "presence-role.cfg" | |||||
| #!endif | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| include_file "nat-traversal-role.cfg" | |||||
| #!endif | |||||
| ####### Kazoo Integration module ########## | |||||
| #!ifdef INCLUDE-DB-KAZOO | |||||
| loadmodule "db_kazoo.so" | |||||
| #!endif | |||||
| ####### Routing Logic ######## | |||||
| route | |||||
| { | |||||
| # log the basic info regarding this call | |||||
| xlog("L_INFO", "$ci|start|recieved $oP request $rm $ou"); | |||||
| xlog("L_INFO", "$ci|log|source $si:$sp"); | |||||
| xlog("L_INFO", "$ci|log|from $fu"); | |||||
| xlog("L_INFO", "$ci|log|to $tu"); | |||||
| route(SANITY_CHECK); | |||||
| #!ifdef DISPATCHER-ROLE | |||||
| route(DISPATCHER_CLASSIFY_SOURCE); | |||||
| #!endif | |||||
| route(HANDLE_OPTIONS); | |||||
| route(HANDLE_MOVE_REQUEST); | |||||
| #!ifdef PRESENCE-ROLE | |||||
| route(HANDLE_SUBSCRIBE); | |||||
| route(HANDLE_PUBLISH); | |||||
| #!endif | |||||
| #!ifdef REGISTRAR-ROLE | |||||
| route(HANDLE_REGISTER); | |||||
| #!endif | |||||
| route(HANDLE_IN_DIALOG_REQUESTS); | |||||
| route(PREPARE_INITIAL_REQUESTS); | |||||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||||
| exit(); | |||||
| } | |||||
| #!ifdef DISPATCHER-ROLE | |||||
| route(DISPATCHER_FIND_ROUTES); | |||||
| #!endif | |||||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||||
| } | |||||
| route[SANITY_CHECK] | |||||
| { | |||||
| if (!mf_process_maxfwd_header("10")) { | |||||
| xlog("L_WARN", "$ci|end|Too much hops, not enough barley"); | |||||
| sl_send_reply("483", "Too Many Hops"); | |||||
| exit; | |||||
| } | |||||
| if (!sanity_check()) { | |||||
| xlog("L_WARN", "$ci|end|message is insane"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[HANDLE_OPTIONS] | |||||
| { | |||||
| if (is_method("OPTIONS")) { | |||||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||||
| } else { | |||||
| sl_send_reply("200", "Rawr!!"); | |||||
| } | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[HANDLE_MOVE_REQUEST] | |||||
| { | |||||
| if (is_method("INVITE") && $rU == "*6683*") { | |||||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||||
| $var(from_uri) = @from.uri.user + "@" + @from.uri.host; | |||||
| if ($sht(associations=>$var(contact_uri)) != $null) { | |||||
| $sht(associations=>$var(contact_uri)) = $null; | |||||
| xlog("L_INFO", "$ci|log|removed contact association for $var(contact_uri) | |||||
| with media server $sht(associations=>$var(contact_uri))\n"); | |||||
| } | |||||
| if ($sht(associations=>$var(from_uri)) != $null) { | |||||
| $sht(associations=>$var(from_uri)) = $null; | |||||
| xlog("L_INFO", "$ci|log|removed from association for $var(from_uri) | |||||
| with media server $sht(associations=>$var(from_uri))\n"); | |||||
| } | |||||
| send_reply("503", "Removed association"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[HANDLE_IN_DIALOG_REQUESTS] | |||||
| { | |||||
| if (has_totag()) { | |||||
| if (loose_route()) { | |||||
| xlog("L_INFO", "$ci|log|loose_route in-dialog message"); | |||||
| # Called on in-dialog requests | |||||
| # If the request in an Invite for on hold from external to internal, | |||||
| # associate the contact with the media server | |||||
| # if Invite for on hold, we need to associate the contact URI with the next hop | |||||
| if (is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) { | |||||
| setflag(FLAG_ASSOCIATE_USER); | |||||
| } | |||||
| route(RELAY); | |||||
| } else if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| xlog("L_INFO", "$ci|log|relay internally sourced in-dialog message without loose_route"); | |||||
| route(RELAY); | |||||
| } else if (t_check_trans()) { | |||||
| xlog("L_INFO", "$ci|log|allow message for a known transaction"); | |||||
| route(RELAY); | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed"); | |||||
| sl_send_reply("481", "Call Leg/Transaction Does Not Exist"); | |||||
| } | |||||
| exit(); | |||||
| } | |||||
| } | |||||
| route[PREPARE_INITIAL_REQUESTS] | |||||
| { | |||||
| if (is_method("CANCEL")) { | |||||
| if (t_check_trans()) { | |||||
| route(RELAY); | |||||
| } else { | |||||
| sl_send_reply("481", "Call Leg/Transaction Does Not Exist"); | |||||
| } | |||||
| exit(); | |||||
| } else if (is_method("ACK")) { | |||||
| if (t_check_trans()) { | |||||
| route(RELAY); | |||||
| } | |||||
| exit(); | |||||
| } | |||||
| t_check_trans(); | |||||
| if (loose_route()) { | |||||
| sl_send_reply("403", "No pre-loaded routes"); | |||||
| exit(); | |||||
| } | |||||
| if (!is_method("MESSAGE")) { | |||||
| record_route(); | |||||
| } | |||||
| } | |||||
| route[RELAY] | |||||
| { | |||||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||||
| } else { | |||||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||||
| } | |||||
| exit(); | |||||
| } | |||||
| route[INTERNAL_TO_EXTERNAL_RELAY] | |||||
| { | |||||
| remove_hf("X-AUTH-IP"); | |||||
| t_on_reply("EXTERNAL_REPLY"); | |||||
| t_set_fr(0, 10000); | |||||
| t_relay(); | |||||
| } | |||||
| route[EXTERNAL_TO_INTERNAL_RELAY] | |||||
| { | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| if (!isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(NAT_TEST_AND_CORRECT); | |||||
| } | |||||
| #!endif | |||||
| remove_hf("X-AUTH-IP"); | |||||
| append_hf("X-AUTH-IP: $si\r\n"); | |||||
| t_on_reply("INTERNAL_REPLY"); | |||||
| t_on_failure("INTERNAL_FAULT"); | |||||
| t_set_fr(0, 1000); | |||||
| t_relay(); | |||||
| } | |||||
| onreply_route[EXTERNAL_REPLY] | |||||
| { | |||||
| xlog("L_INFO", "$ci|log|external reply $T_reply_code"); | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| route(NAT_TEST_AND_CORRECT); | |||||
| #!endif | |||||
| } | |||||
| onreply_route[INTERNAL_REPLY] | |||||
| { | |||||
| # this route handles replies that are comming from our media server | |||||
| xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr"); | |||||
| xlog("L_INFO", "$ci|log|source $si:$sp"); | |||||
| if ($rs < 300) { | |||||
| xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)"); | |||||
| } | |||||
| # change 6xx to 4xx | |||||
| if (t_check_status("6[0-9][0-9]")) { | |||||
| $var(new_code) = "4" + $(T_reply_code{s.substr,1,0}); | |||||
| change_reply_status("$var(new_code)", "$rr"); | |||||
| } | |||||
| } | |||||
| failure_route[INTERNAL_FAULT] | |||||
| { | |||||
| # this branch handles failures (>=300) to our media servers, | |||||
| # which we can sometimes overcome by routing to another server | |||||
| # if the failure cause was due to the transaction being | |||||
| # cancelled then we are complete | |||||
| if (t_is_canceled()) { | |||||
| xlog("L_INFO", "$ci|log|transaction was cancelled"); | |||||
| exit; | |||||
| } | |||||
| # if the failure case was something that we should recover | |||||
| # from then try to find a new media server | |||||
| if (t_check_status("302")) { | |||||
| ## TODO - test this | |||||
| ## get_redirects("*"); | |||||
| if($T_rpl($hdr(X-Redirect-Server)) != $null) { | |||||
| $var(contact_uri) = @from.uri.user + "@" + @from.uri.host; | |||||
| $sht(associations=>$var(contact_uri)) = $T_rpl($hdr(X-Redirect-Server)); | |||||
| xlog("L_INFO", "$ci|log|stored redirect mapping for $var(contact_uri) to $T_rpl($hdr(X-Redirect-Server))"); | |||||
| remove_hf("X-Redirect-Server"); | |||||
| } | |||||
| } else if (t_check_status("(401)|(407)")) { | |||||
| xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $rr"); | |||||
| exit; | |||||
| } else if (t_check_status("402")) { | |||||
| xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486"); | |||||
| xlog("L_INFO", "$ci|pass|$si:$sp"); | |||||
| send_reply("486", "Insufficient Funds"); | |||||
| exit; | |||||
| } else if (t_check_status("(4[0-9][0-9])|(5[0-9][0-9])")) { | |||||
| xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $rr"); | |||||
| #!ifdef DISPATCHER-ROLE | |||||
| route(DISPATCHER_NEXT_ROUTE); | |||||
| #!endif | |||||
| send_reply("486", "Unable to Comply"); | |||||
| exit; | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| onsend_route { | |||||
| if (isflagset(FLAG_ASSOCIATE_USER)) { | |||||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||||
| xlog("L_INFO", "$ci|log|associate user $var(contact_uri) with media server sip:$sndto(ip):$sndto(port)\n"); | |||||
| $sht(associations=>$var(contact_uri))= "sip:" + $sndto(ip) + ":" + $sndto(port); | |||||
| } | |||||
| xlog("L_INFO", "$ci|pass|$sndfrom(ip):$sndfrom(port) -> $sndto(ip):$sndto(port)"); | |||||
| } | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||
| @ -0,0 +1,142 @@ | |||||
| ######## Generic Hash Table container in shared memory ######## | |||||
| modparam("htable", "htable", "failover=>size=16;autoexpire=120") | |||||
| ####### Dispatcher module ######## | |||||
| loadmodule "dispatcher.so" | |||||
| modparam("dispatcher", "list_file", "/etc/kazoo/kamailio/dispatcher.list") | |||||
| modparam("dispatcher", "flags", 2) | |||||
| modparam("dispatcher", "use_default", 0) | |||||
| modparam("dispatcher", "force_dst", 1) | |||||
| modparam("dispatcher", "dst_avp", "$avp(ds_dst)") | |||||
| modparam("dispatcher", "attrs_avp", "$avp(ds_attrs)") | |||||
| modparam("dispatcher", "grp_avp", "$avp(ds_grp)") | |||||
| modparam("dispatcher", "cnt_avp", "$avp(ds_cnt)") | |||||
| modparam("dispatcher", "hash_pvar", "$avp(ds_grp)") | |||||
| # modparam("dispatcher", "setid_pvar", "$var(setid)") | |||||
| modparam("dispatcher", "ds_ping_method", "OPTIONS") | |||||
| modparam("dispatcher", "ds_ping_interval", 10) | |||||
| modparam("dispatcher", "ds_probing_threshhold", 3) | |||||
| modparam("dispatcher", "ds_probing_mode", 1) | |||||
| modparam("dispatcher", "ds_ping_reply_codes", "501,403,404,400,200") | |||||
| ####### Dispatcher Logic ######## | |||||
| route[DISPATCHER_CLASSIFY_SOURCE] | |||||
| { | |||||
| if (ds_is_from_list("1", "1") || ds_is_from_list("3", "1")) { | |||||
| xlog("L_INFO", "$ci|log|originated from internal sources"); | |||||
| setflag(FLAG_INTERNALLY_SOURCED); | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|originated from external sources"); | |||||
| } | |||||
| } | |||||
| # Take the routes from dispatcher - hash over callid | |||||
| # If prefered route defined, reorder the destionations | |||||
| route[DISPATCHER_FIND_ROUTES] | |||||
| { | |||||
| if ($sht(failover=>$ci::current) != $null) { | |||||
| $du = $sht(failover=>$ci::current); | |||||
| return; | |||||
| } | |||||
| if (!ds_select_dst("1", "0")) { | |||||
| xlog("L_ERR", "$ci|end|no servers avaliable"); | |||||
| sl_send_reply("480", "All servers busy"); | |||||
| exit; | |||||
| } | |||||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||||
| $var(from_uri) = @from.uri.user + "@" + @from.uri.host; | |||||
| if ($sht(associations=>$var(from_uri)) != $null) { | |||||
| $var(association) = $var(from_uri); | |||||
| route(DISPATCHER_REORDER_ROUTES); | |||||
| } else if ($sht(associations=>$var(contact_uri)) != $null) { | |||||
| $var(association) = $var(contact_uri); | |||||
| route(DISPATCHER_REORDER_ROUTES); | |||||
| } | |||||
| } | |||||
| route[DISPATCHER_REORDER_ROUTES] | |||||
| { | |||||
| $var(i) = 0; | |||||
| $var(found) = 0; | |||||
| while($(avp(ds_dst)[$var(i)]) != $null) { | |||||
| if($(avp(ds_dst)[$var(i)]) != $var(prefered_route)) { | |||||
| $avp(tmp_ds_dst) = $(avp(ds_dst)[$var(i)]); | |||||
| } else { | |||||
| $var(found) = 1; | |||||
| } | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| if ($var(found)) { | |||||
| xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); | |||||
| $(avp(ds_dst)[*]) = $null; | |||||
| $var(i) = 0; | |||||
| while($(avp(tmp_ds_dst)[$var(i)]) != $null) { | |||||
| $avp(ds_dst) = $(avp(tmp_ds_dst)[$var(i)]); | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| $avp(ds_dst) = $var(prefered_route); | |||||
| $du = $var(prefered_route); | |||||
| $(avp(tmp_ds_dst)[*]) = $null; | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); | |||||
| $sht(associations=>$var(contact_uri)) = $null; | |||||
| } | |||||
| } | |||||
| route[DISPATCHER_NEXT_ROUTE] | |||||
| { | |||||
| $var(failover_count) = $sht(failover=>$ci::counts); | |||||
| if ($sht(failover=>$ci::counts) == $null) { | |||||
| $var(i) = 0; | |||||
| while($(avp(ds_dst)[$var(i)]) != $null) { | |||||
| $sht(failover=>$ci[$var(i)]) = $(avp(ds_dst)[$var(i)]); | |||||
| $var(i) = $var(i) + 1; | |||||
| if ($var(i) >= 3) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| $sht(failover=>$ci::counts) = $var(i); | |||||
| $var(failover_count) = $var(i); | |||||
| } | |||||
| # try to find a new media server to send the call to | |||||
| if ($var(failover_count) > 1) { | |||||
| $var(failover_count) = $var(failover_count) - 1; | |||||
| $du = $sht(failover=>$ci[$var(failover_count)]); | |||||
| $sht(failover=>$ci::counts) = $var(failover_count); | |||||
| $sht(failover=>$ci::current) = $du; | |||||
| xlog("L_INFO", "$ci|log|remaining failed retry attempts: $var(failover_count)"); | |||||
| xlog("L_INFO", "$ci|log|routing call to next media server $du"); | |||||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||||
| # reset the final reply timer | |||||
| $avp(final_reply_timer) = 3; | |||||
| t_on_reply("INTERNAL_REPLY"); | |||||
| t_on_failure("INTERNAL_FAULT"); | |||||
| # relay the request to the new media server | |||||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||||
| exit(); | |||||
| } | |||||
| } | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||
| @ -1,723 +1,12 @@ | |||||
| #### Preprocessor Directives ######### | |||||
| #!define L_ALERT -5 | |||||
| #!define L_BUG -4 | |||||
| #!define L_CRIT2 -3 | |||||
| #!define L_CRIT -2 | |||||
| #!define L_ERR -1 | |||||
| #!define L_WARN 0 | |||||
| #!define L_NOTICE 1 | |||||
| #!define L_INFO 2 | |||||
| #!define L_DBG 3 | |||||
| ## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ## | |||||
| #!define AVP_RECV_PARAM "recv_param" | |||||
| #!define AVP_LOG_LEVEL "log_level" | |||||
| #!define AVP_ROUTE_CNT "route_cnt" | |||||
| #!define AVP_ASSOCIATED_SERVER "associated_server" | |||||
| #!define AVP_ASSOCIATE_CONTACT "associate_contact" | |||||
| ####### Roles Configuration ###### | |||||
| include_file "roles.cfg" | |||||
| ####### Global Parameters ######### | |||||
| fork = yes | |||||
| children = 25 | |||||
| server_signature = no | |||||
| server_header = "Server: Kazoo" | |||||
| user_agent_header = "User-Agent: Kazoo" | |||||
| shm_force_alloc = yes | |||||
| mlock_pages = yes | |||||
| phone2tel = 1 | |||||
| max_while_loops = 500 | |||||
| ####### Default Configuration ###### | |||||
| include_file "default.cfg" | |||||
| ####### Logging Parameters ######### | |||||
| debug = L_INFO | |||||
| memdbg = 10 | |||||
| memlog = 10 | |||||
| corelog = L_ERR | |||||
| log_stderror = no | |||||
| log_facility = LOG_LOCAL0 | |||||
| log_name="kamailio" | |||||
| ####### Alias Parameters ######### | |||||
| auto_aliases = yes | |||||
| # alias = "mydomain.net" | |||||
| ####### Binding Parameters ######### | |||||
| listen = tcp:127.0.0.1:5060 | |||||
| listen = udp:127.0.0.1:5060 | |||||
| listen = tcp:127.0.0.1:5080 | |||||
| listen = udp:127.0.0.1:5080 | |||||
| listen = tcp:127.0.0.1:7000 | |||||
| listen = udp:127.0.0.1:7000 | |||||
| tos = IPTOS_LOWDELAY | |||||
| ## NOTE: Uncomment on a multihomed host | |||||
| # mhomed = 1 | |||||
| ####### TCP Parameters ######### | |||||
| tcp_children = 25 | |||||
| disable_tcp = no | |||||
| tcp_max_connections = 4096 | |||||
| tcp_connection_lifetime = 3605 | |||||
| tcp_accept_aliases = no | |||||
| tcp_async = yes | |||||
| tcp_connect_timeout = 10 | |||||
| tcp_conn_wq_max = 65536 | |||||
| tcp_crlf_ping = yes | |||||
| tcp_delayed_ack = yes | |||||
| tcp_fd_cache = yes | |||||
| tcp_keepalive = yes | |||||
| tcp_keepcnt = 3 | |||||
| tcp_keepidle = 30 | |||||
| tcp_keepintvl = 10 | |||||
| tcp_linger2 = 30 | |||||
| tcp_rd_buf_size = 4096 | |||||
| tcp_send_timeout = 10 | |||||
| tcp_wq_blk_size = 2100 | |||||
| tcp_wq_max = 10485760 | |||||
| ####### UDP Parameters ######### | |||||
| udp4_raw = -1 | |||||
| ## NOTE: You must MATCH this to your network adapter!! | |||||
| ## If they do not match, all UDP packets over | |||||
| ## this limit WILL FAIL! | |||||
| ## E.g.: Add MTU=1472 to the /etc/sysconfig/network-scripts/XXX | |||||
| # udp4_raw_mtu = 1472 | |||||
| ####### DNS Parameters ######### | |||||
| dns = no | |||||
| rev_dns = no | |||||
| dns_try_ipv6 = no | |||||
| use_dns_cache = on | |||||
| dns_cache_del_nonexp = no | |||||
| dns_cache_flags = 1 | |||||
| dns_cache_gc_interval = 120 | |||||
| dns_cache_init = 1 | |||||
| dns_cache_mem = 1000 | |||||
| dns_cache_negative_ttl = 60 | |||||
| dns_try_naptr = no | |||||
| use_dns_failover = off | |||||
| dns_srv_lb = off | |||||
| ####### TLS Parameters ######### | |||||
| enable_tls = yes | |||||
| ####### SCTP Parameters ######### | |||||
| disable_sctp = yes | |||||
| ####### Custom Parameters ######### | |||||
| ####### Modules Section ######## | |||||
| mpath="/usr/lib64/kamailio/modules/" | |||||
| ####### Flags ####### | |||||
| flags | |||||
| FLAG_INTERNALLY_SOURCED: 1, | |||||
| FLAG_ASSOCIATE_SERVER: 2, | |||||
| FLAG_SKIP_NAT_CORRECTION: 3, | |||||
| FLAG_ASSOCIATE_USER: 4; | |||||
| #!define FLB_NATB 1 | |||||
| #!define FLB_NATSIPPING 2 | |||||
| #!define FLB_UAC_REDIRECT 3 | |||||
| ######## Kamailio core extensions module ######## | |||||
| loadmodule "kex.so" | |||||
| ######## Transaction (stateful) module ######## | |||||
| loadmodule "tm.so" | |||||
| loadmodule "tmx.so" | |||||
| modparam("tm", "auto_inv_100", 1) | |||||
| modparam("tm", "auto_inv_100_reason", "Attempting to connect your call") | |||||
| modparam("tm", "cancel_b_method", 2) | |||||
| modparam("tm", "ruri_matching", 0) | |||||
| modparam("tm", "failure_reply_mode", 3) | |||||
| # modparam("tm", "fr_timer", 30000) | |||||
| # modparam("tm", "fr_inv_timer", 120000) | |||||
| ######## Stateless replier module ######## | |||||
| loadmodule "sl.so" | |||||
| ######## Record-Route and Route module ######## | |||||
| loadmodule "rr.so" | |||||
| modparam("rr", "enable_full_lr", 1) | |||||
| ######## Max-Forward processor module ######## | |||||
| loadmodule "maxfwd.so" | |||||
| ######## SIP utilities [requires sl] ######## | |||||
| loadmodule "siputils.so" | |||||
| ######## SIP message formatting sanity checks [requires sl] ######## | |||||
| loadmodule "sanity.so" | |||||
| # sip_version, scheme, req_headers, cseq_method/value | |||||
| # content_length, parse_uri, digest | |||||
| modparam("sanity", "default_checks", 3303) | |||||
| modparam("sanity", "uri_checks", 3) | |||||
| modparam("sanity", "autodrop", 0) | |||||
| ######## Text operations module ######## | |||||
| loadmodule "textops.so" | |||||
| loadmodule "textopsx.so" | |||||
| ######## Generic Hash Table container in shared memory ######## | |||||
| loadmodule "htable.so" | |||||
| modparam("htable", "htable", "associations=>size=10;") | |||||
| modparam("htable", "htable", "auth_cache=>size=10;") | |||||
| modparam("htable", "htable", "dbkp=>size=4;autoexpire=7200") | |||||
| ######## Pseudo-Variables module ######## | |||||
| loadmodule "pv.so" | |||||
| ######## Advanced logger module ######## | |||||
| loadmodule "xlog.so" | |||||
| ####### FIFO support for Management Interface ######## | |||||
| loadmodule "mi_fifo.so" | |||||
| modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") | |||||
| ####### Dispatcher module ######## | |||||
| loadmodule "dispatcher.so" | |||||
| modparam("dispatcher", "list_file", "/etc/kazoo/kamailio/dispatcher.list") | |||||
| modparam("dispatcher", "flags", 2) | |||||
| modparam("dispatcher", "use_default", 0) | |||||
| modparam("dispatcher", "force_dst", 1) | |||||
| modparam("dispatcher", "dst_avp", "$avp(ds_dst)") | |||||
| modparam("dispatcher", "attrs_avp", "$avp(ds_attrs)") | |||||
| modparam("dispatcher", "grp_avp", "$avp(ds_grp)") | |||||
| modparam("dispatcher", "cnt_avp", "$avp(ds_cnt)") | |||||
| modparam("dispatcher", "hash_pvar", "$avp(ds_grp)") | |||||
| # modparam("dispatcher", "setid_pvar", "$var(setid)") | |||||
| modparam("dispatcher", "ds_ping_method", "OPTIONS") | |||||
| modparam("dispatcher", "ds_ping_from", "sip:sipcheck@127.0.0.1") | |||||
| modparam("dispatcher", "ds_ping_interval", 10) | |||||
| # modparam("dispatcher", "ds_ping_sock", "udp:{{SIP_IP}}:{{SIP_PORT}}") | |||||
| modparam("dispatcher", "ds_probing_threshhold", 3) | |||||
| modparam("dispatcher", "ds_probing_mode", 1) | |||||
| modparam("dispatcher", "ds_ping_reply_codes", "501,403,404,400,200") | |||||
| ######## UAC Redirection module ######## | |||||
| loadmodule "uac_redirect.so" | |||||
| ####### Authentication Interface module ########## | |||||
| loadmodule "auth.so" | |||||
| loadmodule "auth_db.so" | |||||
| modparam("auth_db", "use_domain", 1) | |||||
| modparam("auth_db", "version_table", 0) | |||||
| modparam("auth_db", "calculate_ha1", 1) | |||||
| modparam("auth_db", "password_column", "password") | |||||
| modparam("auth_db", "load_credentials", "$avp(password)=password") | |||||
| ####### User Location Implementation module ########## | |||||
| loadmodule "usrloc.so" | |||||
| modparam("usrloc", "db_mode", 1) | |||||
| modparam("usrloc", "db_update_as_insert", 1) | |||||
| modparam("usrloc", "use_domain", 1) | |||||
| modparam("usrloc", "nat_bflag", FLB_NATB) | |||||
| ####### SIP Registrar implementation module ########## | |||||
| loadmodule "registrar.so" | |||||
| ######## NAT Traversal module - signaling functions ######## | |||||
| loadmodule "nathelper.so" | |||||
| modparam("nathelper|registrar", "received_avp", "$avp(AVP_RECV_PARAM)") | |||||
| modparam("nathelper", "natping_interval", 30) | |||||
| modparam("nathelper", "ping_nated_only", 1) | |||||
| modparam("nathelper", "natping_processes", 5) | |||||
| modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) | |||||
| modparam("nathelper", "sipping_from", "sip:sipcheck@127.0.0.1") | |||||
| # modparam("nathelper", "natping_socket", "127.0.0.1:5060") | |||||
| ######## Presence User Agent module ######## | |||||
| loadmodule "pua_dialoginfo.so" | |||||
| modparam("pua_dialoginfo", "library_mode", 1) | |||||
| ######## Presence server module ######## | |||||
| loadmodule "presence.so" | |||||
| loadmodule "presence_dialoginfo.so" | |||||
| modparam("presence", "subs_db_mode", 1) | |||||
| modparam("presence", "expires_offset", 60) | |||||
| modparam("presence", "publ_cache", 0) | |||||
| ####### Kazoo Integration module ########## | |||||
| loadmodule "db_kazoo.so" | |||||
| # NOTE: The hostname that should be advertised to Kazoo | |||||
| modparam("db_kazoo", "node_hostname", "kamailio.2600hz.com") | |||||
| # If you want a certain fs_path to be sent Kazoo, uncomment the next line and set the right value | |||||
| # modparam("db_kazoo", "register_fs_path", "127.0.0.1:5060") | |||||
| ####### Common Module Parameters ########## | |||||
| modparam("auth_db|usrloc", "db_url", "kazoo://guest:guest@127.0.0.1:5672/callmgr") | |||||
| modparam("presence", "db_url", "kazoo://guest:guest@127.0.0.1:5672/dialoginfo") | |||||
| ####### Routing Logic ######## | |||||
| route | |||||
| { | |||||
| # log the basic info regarding this call | |||||
| xlog("L_INFO", "$ci|start|recieved $oP request $rm $ou"); | |||||
| xlog("L_INFO", "$ci|log|source $si:$sp"); | |||||
| xlog("L_INFO", "$ci|log|from $fu"); | |||||
| xlog("L_INFO", "$ci|log|to $tu"); | |||||
| route(SANITY_CHECK); | |||||
| route(CLASSIFY_SOURCE); | |||||
| route(HANDLE_OPTIONS); | |||||
| route(HANDLE_PRESENCE); | |||||
| route(HANDLE_IN_DIALOG_REQUESTS); | |||||
| route(PREPARE_INITIAL_REQUESTS); | |||||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||||
| exit(); | |||||
| } | |||||
| route(HANDLE_MOVE_REQUEST); | |||||
| route(FIND_ROUTES); | |||||
| $avp(route_attempts) = 1; | |||||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||||
| } | |||||
| route[SANITY_CHECK] | |||||
| { | |||||
| if (!mf_process_maxfwd_header("10")) { | |||||
| xlog("L_WARN", "$ci|end|max-forward limit reached"); | |||||
| sl_send_reply("483", "Too Many Hops"); | |||||
| exit; | |||||
| } | |||||
| if (!sanity_check()) { | |||||
| xlog("L_WARN", "$ci|end|message is insane"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[CLASSIFY_SOURCE] | |||||
| { | |||||
| if (ds_is_from_list("1", "1") || ds_is_from_list("3", "1")) { | |||||
| xlog("L_INFO", "$ci|log|originated from internal sources"); | |||||
| setflag(FLAG_INTERNALLY_SOURCED); | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|originated from external sources"); | |||||
| } | |||||
| } | |||||
| route[HANDLE_OPTIONS] | |||||
| { | |||||
| if (is_method("OPTIONS")) { | |||||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||||
| } else { | |||||
| sl_send_reply("200", "Rawr!!"); | |||||
| } | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[HANDLE_PRESENCE] | |||||
| { | |||||
| if (is_method("SUBSCRIBE")) { | |||||
| if (!t_newtran()) { | |||||
| sl_reply_error(); | |||||
| exit; | |||||
| } | |||||
| handle_subscribe(); | |||||
| t_release(); | |||||
| exit; | |||||
| } | |||||
| if (is_method("PUBLISH")) { | |||||
| if (!t_newtran()) { | |||||
| sl_reply_error(); | |||||
| exit; | |||||
| } | |||||
| handle_publish(); | |||||
| t_release(); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[HANDLE_IN_DIALOG_REQUESTS] | |||||
| { | |||||
| if (has_totag()) { | |||||
| if (loose_route()) { | |||||
| xlog("L_INFO", "$ci|log|loose_route in-dialog message"); | |||||
| # Called on in-dialog requests | |||||
| # If the request in an Invite for on hold from external to internal, | |||||
| # associate the contact with the media server | |||||
| # if Invite for on hold, we need to associate the contact URI with the next hop | |||||
| if (is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) { | |||||
| setflag(FLAG_ASSOCIATE_USER); | |||||
| } | |||||
| route(RELAY); | |||||
| } else if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| xlog("L_INFO", "$ci|log|relay internally sourced in-dialog message without loose_route"); | |||||
| route(RELAY); | |||||
| } else if (t_check_trans()) { | |||||
| xlog("L_INFO", "$ci|log|allow message for a known transaction"); | |||||
| route(RELAY); | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed"); | |||||
| sl_send_reply("481", "Call Leg/Transaction Does Not Exist"); | |||||
| } | |||||
| exit(); | |||||
| } | |||||
| } | |||||
| route[PREPARE_INITIAL_REQUESTS] | |||||
| { | |||||
| if (is_method("CANCEL")) { | |||||
| if (t_check_trans()) { | |||||
| route(RELAY); | |||||
| } else { | |||||
| sl_send_reply("481", "Call Leg/Transaction Does Not Exist"); | |||||
| } | |||||
| exit(); | |||||
| } else if (is_method("ACK")) { | |||||
| if (t_check_trans()) { | |||||
| route(RELAY); | |||||
| } | |||||
| exit(); | |||||
| } | |||||
| t_check_trans(); | |||||
| if (loose_route()) { | |||||
| sl_send_reply("403", "No pre-loaded routes"); | |||||
| exit(); | |||||
| } | |||||
| if (is_method("REGISTER")) { | |||||
| if (nat_uac_test("3")) { | |||||
| xlog("L_INFO", "$ci|log|Correcting NATed contact in registration\n"); | |||||
| force_rport(); | |||||
| setbflag(FLB_NATB); | |||||
| setbflag(FLB_NATSIPPING); | |||||
| fix_nated_register(); | |||||
| } | |||||
| if (is_present_hf("Authorization")) { | |||||
| if ($sht(auth_cache=>$Au) != $null && pv_auth_check("$fd", "$sht(auth_cache=>$Au)", "0", "0")) { | |||||
| xlog("L_INFO", "$ci|log|Authenticated $Au via cached SIP creds\n"); | |||||
| } else { | |||||
| ## RABBITMQ - Credentials fetch | |||||
| if (!auth_check("$fd", "subscriber", "1")) { | |||||
| auth_challenge("$fd", "0"); | |||||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to failed registration attempt\n"); | |||||
| exit; | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|Caching SIP credentials for $Au\n"); | |||||
| $sht(auth_cache=>$Au) = $avp(password); | |||||
| } | |||||
| } | |||||
| } else { | |||||
| auth_challenge("$fd", "0"); | |||||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to new registration attempt\n"); | |||||
| exit; | |||||
| } | |||||
| # user authenticated - remove auth header | |||||
| consume_credentials(); | |||||
| save("location"); | |||||
| exit; | |||||
| } else if (!is_method("MESSAGE")) { | |||||
| record_route(); | |||||
| } | |||||
| } | |||||
| # Take the routes from dispatcher - hash over callid | |||||
| # If prefered route defined, reorder the destionations | |||||
| route[FIND_ROUTES] | |||||
| { | |||||
| # alg 0 = hash(Callid) | |||||
| if (!ds_select_dst("1", "0")) { | |||||
| xlog("L_ERR", "$ci|end|no servers avaliable"); | |||||
| sl_send_reply("480", "All servers busy"); | |||||
| exit; | |||||
| } | |||||
| # Handle the case when a prefered route is set | |||||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||||
| if ($sht(associations=>$var(contact_uri)) != $null) { | |||||
| $var(prefered_route) = $sht(associations=>$var(contact_uri)); | |||||
| xlog("L_INFO", "$ci|log|should route to $var(prefered_route)"); | |||||
| route(REORDER_ROUTES); | |||||
| } | |||||
| } | |||||
| route[REORDER_ROUTES] | |||||
| { | |||||
| $var(i) = 0; | |||||
| $var(found) = 0; | |||||
| while($(avp(ds_dst)[$var(i)]) != $null) { | |||||
| if($(avp(ds_dst)[$var(i)]) != $var(prefered_route)) { | |||||
| $avp(tmp_ds_dst) = $(avp(ds_dst)[$var(i)]); | |||||
| } else { | |||||
| $var(found) = 1; | |||||
| } | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| if ($var(found)) { | |||||
| xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); | |||||
| $(avp(ds_dst)[*]) = $null; | |||||
| $var(i) = 0; | |||||
| while($(avp(tmp_ds_dst)[$var(i)]) != $null) { | |||||
| $avp(ds_dst) = $(avp(tmp_ds_dst)[$var(i)]); | |||||
| $var(i) = $var(i) + 1; | |||||
| } | |||||
| $avp(ds_dst) = $var(prefered_route); | |||||
| $du = $var(prefered_route); | |||||
| $(avp(tmp_ds_dst)[*]) = $null; | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); | |||||
| $sht(associations=>$var(contact_uri)) = $null; | |||||
| } | |||||
| } | |||||
| route[HANDLE_MOVE_REQUEST] | |||||
| { | |||||
| if (is_method("INVITE") && $rU == "*6683*") { | |||||
| $var(contact_uri) = @from.uri.user + "@" + @from.uri.host; | |||||
| if ($sht(associations=>$var(contact_uri)) != $null) { | |||||
| xlog("L_INFO", "$ci|log|remove association for user $var(contact_uri) | |||||
| with media server $sht(associations=>$var(contact_uri))\n"); | |||||
| $sht(associations=>$var(contact_uri)) = $null; | |||||
| } | |||||
| send_reply("503", "Removed association"); | |||||
| xlog("L_INFO", "$ci|log|removed association for user $var(contact_uri) | |||||
| with media server $sht(associations=>$var(contact_uri))\n"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[RELAY] | |||||
| { | |||||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||||
| } else { | |||||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||||
| } | |||||
| exit(); | |||||
| } | |||||
| route[INTERNAL_TO_EXTERNAL_RELAY] | |||||
| { | |||||
| remove_hf("X-AUTH-IP"); | |||||
| t_on_reply("EXTERNAL_REPLY"); | |||||
| t_set_fr(0, 10000); | |||||
| t_relay(); | |||||
| } | |||||
| route[EXTERNAL_TO_INTERNAL_RELAY] | |||||
| { | |||||
| if (!isflagset(FLAG_INTERNALLY_SOURCED)) { | |||||
| route(NAT_TEST_AND_CORRECT); | |||||
| } | |||||
| remove_hf("X-AUTH-IP"); | |||||
| append_hf("X-AUTH-IP: $si\r\n"); | |||||
| t_on_reply("INTERNAL_REPLY"); | |||||
| t_on_failure("INTERNAL_FAULT"); | |||||
| t_set_fr(0, 1000); | |||||
| t_relay(); | |||||
| } | |||||
| route[LOG_DESTINATION] | |||||
| { | |||||
| if (isdsturiset()) { | |||||
| $var(port) = $dp; | |||||
| $var(domain) = $dd; | |||||
| } else { | |||||
| $var(port) = $rp; | |||||
| $var(domain) = $rd; | |||||
| } | |||||
| if ($(var(port){s.len}) <= 0) { | |||||
| $var(port) = "5060"; | |||||
| } | |||||
| xlog("L_INFO", "$ci|pass|$var(domain):$var(port)"); | |||||
| } | |||||
| route[NAT_TEST_AND_CORRECT] | |||||
| { | |||||
| if (is_present_hf("Record-Route")) { | |||||
| $var(i) = $rr_count; | |||||
| while($var(i) > 0) { | |||||
| $var(i) = $var(i) - 1; | |||||
| $var(rr) = $(hdr(Record-Route)[$var(i)]); | |||||
| if (!is_myself("$(var(rr){nameaddr.uri})")) { | |||||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||||
| } | |||||
| } | |||||
| } else if ($Rp == "5080") { | |||||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||||
| } | |||||
| if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { | |||||
| return(); | |||||
| } | |||||
| if (nat_uac_test("3")) { | |||||
| force_rport(); | |||||
| fix_nated_contact(); | |||||
| } | |||||
| if (has_body("application/sdp") && nat_uac_test("8")) { | |||||
| fix_nated_sdp("10"); | |||||
| } | |||||
| } | |||||
| onreply_route[EXTERNAL_REPLY] | |||||
| { | |||||
| xlog("L_INFO", "$ci|log|external reply $T_reply_code"); | |||||
| route(NAT_TEST_AND_CORRECT); | |||||
| } | |||||
| onreply_route[INTERNAL_REPLY] | |||||
| { | |||||
| # this route handles replies that are comming from our media server | |||||
| xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr"); | |||||
| xlog("L_INFO", "$ci|log|source $si:$sp"); | |||||
| if ($rs < 300) { | |||||
| xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)"); | |||||
| } | |||||
| # change 6xx to 4xx | |||||
| if (t_check_status("6[0-9][0-9]")) { | |||||
| $var(new_code) = "4" + $(T_reply_code{s.substr,1,0}); | |||||
| change_reply_status("$var(new_code)", "$rr"); | |||||
| } | |||||
| } | |||||
| failure_route[INTERNAL_FAULT] | |||||
| { | |||||
| # this branch handles failures (>=300) to our media servers, | |||||
| # which we can sometimes overcome by routing to another server | |||||
| # if the failure cause was due to the transaction being | |||||
| # cancelled then we are complete | |||||
| if (t_is_canceled()) { | |||||
| xlog("L_INFO", "$ci|log|transaction was cancelled"); | |||||
| exit; | |||||
| } | |||||
| # if the failure case was something that we should recover | |||||
| # from then try to find a new media server | |||||
| if (t_check_status("(401)|(407)")) { | |||||
| xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $rr"); | |||||
| exit; | |||||
| } else if (t_check_status("403")) { | |||||
| xlog("L_INFO", "$ci|log|failure route overriding reply code 403 with 503"); | |||||
| xlog("L_INFO", "$ci|pass|$si:$sp"); | |||||
| send_reply("503", "Error: Services Unavailable. Try Later"); | |||||
| exit; | |||||
| } else if (t_check_status("402")) { | |||||
| xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486"); | |||||
| xlog("L_INFO", "$ci|pass|$si:$sp"); | |||||
| send_reply("486", "Insufficient Funds"); | |||||
| exit; | |||||
| } else if (t_check_status("(4[0-9][0-9])|(5[0-9][0-9])")) { | |||||
| xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $rr"); | |||||
| # try to find a new media server to send the call to | |||||
| if ($avp(route_attempts) < 3 && ds_next_domain()) { | |||||
| xlog("L_INFO", "$ci|log|attempting retry $avp(route_attempts) of failed request"); | |||||
| xlog("L_INFO", "$ci|log|routing call to next media server $rd:$rp"); | |||||
| # reset the final reply timer | |||||
| $avp(final_reply_timer) = 3; | |||||
| t_on_reply("INTERNAL_REPLY"); | |||||
| t_on_failure("INTERNAL_FAULT"); | |||||
| # relay the request to the new media server | |||||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||||
| $avp(route_attempts) = $avp(route_attempts) + 1; | |||||
| } else if (t_check_status("404")) { | |||||
| xlog("L_ERR", "$ci|log|no other media servers avaliable, sending 486"); | |||||
| send_reply("486", "Not found"); | |||||
| exit; | |||||
| } else { | |||||
| xlog("L_ERR", "$ci|log|no other media servers avaliable"); | |||||
| exit; | |||||
| } | |||||
| } else if (t_check_status("302")) { | |||||
| ## TODO - test this | |||||
| ## get_redirects("*"); | |||||
| if($T_rpl($hdr(X-Redirect-Server)) != $null) { | |||||
| $var(contact_uri) = @from.uri.user + "@" + @from.uri.host; | |||||
| $sht(associations=>$var(contact_uri)) = $T_rpl($hdr(X-Redirect-Server)); | |||||
| xlog("L_INFO", "$ci|log|stored redirect mapping for $var(contact_uri) to $T_rpl($hdr(X-Redirect-Server))"); | |||||
| remove_hf("X-Redirect-Server"); | |||||
| } | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr"); | |||||
| exit; | |||||
| } | |||||
| route(LOG_DESTINATION); | |||||
| } | |||||
| onsend_route { | |||||
| if (isflagset(FLAG_ASSOCIATE_USER)) { | |||||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||||
| xlog("L_INFO", "$ci|log|associate user $var(contact_uri) with media server sip:$sndto(ip):$sndto(port)\n"); | |||||
| $sht(associations=>$var(contact_uri))= "sip:" + $sndto(ip) + ":" + $sndto(port); | |||||
| } | |||||
| xlog("L_INFO", "$ci|pass|$sndfrom(ip):$sndfrom(port) -> $sndto(ip):$sndto(port)"); | |||||
| } | |||||
| ####### Local Configuration ######## | |||||
| include_file "local.cfg" | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | ||||
| @ -0,0 +1,50 @@ | |||||
| ####### Logging Parameters ######### | |||||
| debug = L_INFO | |||||
| ####### Alias Parameters ######### | |||||
| # alias = "mydomain.net" | |||||
| ####### UDP Parameters ######### | |||||
| ## NOTE: You must MATCH this to your network adapter!! | |||||
| ## If they do not match, all UDP packets over | |||||
| ## this limit WILL FAIL! | |||||
| ## E.g.: Add MTU=1472 to the /etc/sysconfig/network-scripts/XXX | |||||
| # udp4_raw_mtu = 1472 | |||||
| ####### Binding Parameters ######### | |||||
| # mhomed=1 | |||||
| listen = tcp:127.0.0.1:5060 | |||||
| listen = udp:127.0.0.1:5060 | |||||
| listen = tcp:127.0.0.1:7000 | |||||
| listen = udp:127.0.0.1:7000 | |||||
| ####### Dispatcher module ######## | |||||
| #!ifdef DISPATCHER-ROLE | |||||
| modparam("dispatcher", "ds_ping_from", "sip:sipcheck@127.0.0.1") | |||||
| # modparam("dispatcher", "ds_ping_sock", "udp:127.0.0.1:5060") | |||||
| #!endif | |||||
| ######## NAT Traversal module - signaling functions ######## | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| modparam("nathelper", "sipping_from", "sip:sipcheck@127.0.0.1") | |||||
| # modparam("nathelper", "natping_socket", "127.0.0.1:5060") | |||||
| #!endif | |||||
| ####### Kazoo Integration module ########## | |||||
| #!ifdef INCLUDE-DB-KAZOO | |||||
| ## NOTE: The hostname that should be advertised to Kazoo | |||||
| modparam("db_kazoo", "node_hostname", "kamailio.2600hz.com") | |||||
| ## NOTE: If you want a certain fs_path to be sent Kazoo, | |||||
| ## uncomment the next line and set the right value | |||||
| # modparam("db_kazoo", "register_fs_path", "127.0.0.1:5060") | |||||
| #!endif | |||||
| ####### Common Module Parameters ########## | |||||
| #!ifdef REGISTRAR-ROLE | |||||
| modparam("auth_db|usrloc", "db_url", "kazoo://guest:guest@127.0.0.1:5672/callmgr") | |||||
| #!endif | |||||
| #!ifdef PRESENCE-ROLE | |||||
| modparam("presence", "db_url", "kazoo://guest:guest@127.0.0.1:5672/dialoginfo") | |||||
| #!endif | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||
| @ -0,0 +1,41 @@ | |||||
| ######## NAT Traversal module - signaling functions ######## | |||||
| #!ifndef NATHELPER-LOADED | |||||
| loadmodule "nathelper.so" | |||||
| #!endif | |||||
| modparam("nathelper", "received_avp", "$avp(AVP_RECV_PARAM)") | |||||
| modparam("nathelper", "natping_interval", 30) | |||||
| modparam("nathelper", "ping_nated_only", 1) | |||||
| modparam("nathelper", "natping_processes", 5) | |||||
| modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) | |||||
| ####### NAT Traversal Logic ######## | |||||
| route[NAT_TEST_AND_CORRECT] | |||||
| { | |||||
| if (is_present_hf("Record-Route")) { | |||||
| $var(i) = $rr_count; | |||||
| while($var(i) > 0) { | |||||
| $var(i) = $var(i) - 1; | |||||
| $var(rr) = $(hdr(Record-Route)[$var(i)]); | |||||
| if (!is_myself("$(var(rr){nameaddr.uri})")) { | |||||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||||
| } | |||||
| } | |||||
| } else if ($Rp == "5080") { | |||||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||||
| } | |||||
| if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { | |||||
| return(); | |||||
| } | |||||
| if (nat_uac_test("3")) { | |||||
| force_rport(); | |||||
| fix_nated_contact(); | |||||
| } | |||||
| if (has_body("application/sdp") && nat_uac_test("8")) { | |||||
| fix_nated_sdp("10"); | |||||
| } | |||||
| } | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||
| @ -0,0 +1,48 @@ | |||||
| #!trydef INCLUDE-DB-KAZOO | |||||
| ######## Generic Hash Table container in shared memory ######## | |||||
| modparam("htable", "htable", "dbkp=>size=16;autoexpire=7200") | |||||
| ######## Presence User Agent module ######## | |||||
| loadmodule "pua_dialoginfo.so" | |||||
| modparam("pua_dialoginfo", "library_mode", 1) | |||||
| ######## Presence server module ######## | |||||
| loadmodule "presence.so" | |||||
| loadmodule "presence_dialoginfo.so" | |||||
| modparam("presence", "subs_db_mode", 1) | |||||
| modparam("presence", "expires_offset", 60) | |||||
| modparam("presence", "publ_cache", 0) | |||||
| ####### Presence Logic ######## | |||||
| route[HANDLE_SUBSCRIBE] | |||||
| { | |||||
| if (is_method("SUBSCRIBE")) { | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| route(NAT_TEST_AND_CORRECT); | |||||
| #!endif | |||||
| if (!t_newtran()) { | |||||
| sl_reply_error(); | |||||
| exit; | |||||
| } | |||||
| handle_subscribe(); | |||||
| t_release(); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| route[HANDLE_PUBLISH] | |||||
| { | |||||
| if (is_method("PUBLISH")) { | |||||
| if (!t_newtran()) { | |||||
| sl_reply_error(); | |||||
| exit; | |||||
| } | |||||
| handle_publish(); | |||||
| t_release(); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||
| @ -0,0 +1,76 @@ | |||||
| #!trydef INCLUDE-DB-KAZOO | |||||
| ######## Generic Hash Table container in shared memory ######## | |||||
| modparam("htable", "htable", "auth_cache=>size=16;autoexpire=7200") | |||||
| ####### Authentication Interface module ########## | |||||
| loadmodule "auth.so" | |||||
| loadmodule "auth_db.so" | |||||
| modparam("auth_db", "use_domain", 1) | |||||
| modparam("auth_db", "version_table", 0) | |||||
| modparam("auth_db", "calculate_ha1", 1) | |||||
| modparam("auth_db", "password_column", "password") | |||||
| modparam("auth_db", "load_credentials", "$avp(password)=password") | |||||
| ####### User Location Implementation module ########## | |||||
| loadmodule "usrloc.so" | |||||
| modparam("usrloc", "db_mode", 1) | |||||
| modparam("usrloc", "db_update_as_insert", 1) | |||||
| modparam("usrloc", "use_domain", 1) | |||||
| modparam("usrloc", "nat_bflag", FLB_NATB) | |||||
| ######## NAT Traversal module - signaling functions ######## | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| #!trydef NATHELPER-LOADED | |||||
| loadmodule "nathelper.so" | |||||
| #!endif | |||||
| ####### SIP Registrar implementation module ########## | |||||
| loadmodule "registrar.so" | |||||
| modparam("registrar", "received_avp", "$avp(AVP_RECV_PARAM)") | |||||
| ####### Registrar Logic ######## | |||||
| route[HANDLE_REGISTER] | |||||
| { | |||||
| if (is_method("REGISTER")) { | |||||
| #!ifdef NAT-TRAVERSAL-ROLE | |||||
| if (nat_uac_test("3")) { | |||||
| xlog("L_INFO", "$ci|log|Correcting NATed contact in registration\n"); | |||||
| force_rport(); | |||||
| setbflag(FLB_NATB); | |||||
| setbflag(FLB_NATSIPPING); | |||||
| fix_nated_register(); | |||||
| } | |||||
| #!endif | |||||
| if (is_present_hf("Authorization")) { | |||||
| if ($sht(auth_cache=>$Au) != $null && pv_auth_check("$fd", "$sht(auth_cache=>$Au)", "0", "0")) { | |||||
| xlog("L_INFO", "$ci|log|Authenticated $Au via cached SIP creds\n"); | |||||
| } else { | |||||
| ## RABBITMQ - Credentials fetch | |||||
| if (!auth_check("$fd", "subscriber", "1")) { | |||||
| auth_challenge("$fd", "0"); | |||||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to failed registration attempt\n"); | |||||
| exit; | |||||
| } else { | |||||
| xlog("L_INFO", "$ci|log|Caching SIP credentials for $Au\n"); | |||||
| $sht(auth_cache=>$Au) = $avp(password); | |||||
| } | |||||
| } | |||||
| } else { | |||||
| auth_challenge("$fd", "0"); | |||||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to new registration attempt\n"); | |||||
| exit; | |||||
| } | |||||
| # user authenticated - remove auth header | |||||
| consume_credentials(); | |||||
| save("location"); | |||||
| exit; | |||||
| } | |||||
| } | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||
| @ -0,0 +1,7 @@ | |||||
| ####### Roles ######## | |||||
| #!trydef DISPATCHER-ROLE | |||||
| #!trydef NAT-TRAVERSAL-ROLE | |||||
| #!trydef REGISTRAR-ROLE | |||||
| #!trydef PRESENCE-ROLE | |||||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||||