#!KAMAILIO # # This config file implements the basic I-CSCF functionality # - web: http://www.kamailio.org # - git: http://sip-router.org # # Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php # for an explanation of possible statements, functions and parameters. # # Direct your questions about this file to: . # # For more information about the various parameters, functions and statements # try http://sip-router.org/wiki/ . # system.shutdownmode = 0 desc "System shutdown mode" system.service = "Interrogating-CSCF" desc "Function of this server" include_file "icscf.cfg" ####### Defined Values ######### # *** Value defines - IDs used later in config # - flags # FLT_ - per transaction (message) flags # FLB_ - per branch flags #!define FLT_CAPTURE 1 #!ifdef WITH_XMLRPC listen=tcp:127.0.0.1:4060 #!endif ####### Global Parameters ######### #!ifdef WITH_DEBUG debug=5 log_stderror=yes sip_warning=yes #!else debug=2 log_stderror=no sip_warning=no #!endif user_agent_header="User-Agent: Kamailio I-CSCF" server_header="Server: Kamailio I-CSCF" /* comment the next line to enable the auto discovery of local aliases based on reverse DNS on IPs (default on) */ auto_aliases=no # Do SRV-Loadbalancing: dns_srv_lb=yes # Always: Also try IPv6: dns_try_ipv6=yes # Query NAPTR-Records as well: dns_try_naptr=no #!ifdef WITH_XMLRPC #!ifndef WITH_TCP #!define WITH_TCP #!endif #!ifndef TCP_PROCESSES # Number of TCP Processes #!define TCP_PROCESSES 3 #!endif #!endif #!ifdef WITH_TCP # life time of TCP connection when there is no traffic # - a bit higher than registration expires to cope with UA behind NAT tcp_connection_lifetime=3615 #!ifdef TCP_PROCESSES tcp_children=TCP_PROCESSES #!endif #!else disable_tcp=yes #!endif check_via=no # (cmd. line: -v) dns=no # (cmd. line: -r) rev_dns=no # (cmd. line: -R) children=64 # ------------------ module loading ---------------------------------- mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/" # (we try both the lib64 and the lib directory) loadmodule "tm" loadmodule "sl" loadmodule "rr" loadmodule "pv" loadmodule "textops" loadmodule "maxfwd" loadmodule "sanity" loadmodule "siputils" loadmodule "kex" loadmodule "tmx" loadmodule "pike" loadmodule "corex" # Control interfaces: loadmodule "ctl" loadmodule "cfg_rpc" loadmodule "mi_rpc" loadmodule "mi_fifo" #!ifdef WITH_XMLRPC loadmodule "xmlrpc" #!endif # Load the according DB-Module: loadmodule "db_mysql" #!ifdef DB_URL2 loadmodule "db_cluster" #!endif loadmodule "cdp.so" loadmodule "cdp_avp.so" loadmodule "xlog.so" loadmodule "ims_icscf.so" #!ifdef CAPTURE_NODE loadmodule "siptrace.so" #!endif #!ifdef WITH_DEBUG loadmodule "debugger.so" #!endif #!ifdef WITH_TLS loadmodule "tls.so" #!endif #!ifdef PEERING loadmodule "enum" #!endif # ----------------- setting module-specific parameters --------------- #!ifdef DB_URL2 # ----- db_cluster params ----- modparam("db_cluster", "connection", DB_URL) modparam("db_cluster", "connection", DB_URL2) modparam("db_cluster", "cluster", "cluster1=>con1=2s2s;con2=1s1s") #!endif # ----- mi_fifo params ----- modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") modparam("mi_fifo", "fifo_mode", 0666) modparam("mi_fifo", "fifo_user", "kamailio") modparam("mi_fifo", "fifo_group", "kamailio") # -- rr params -- # add value to ;lr param to make some broken UAs happy modparam("rr", "enable_full_lr", 1) # -- cdp params -- modparam("cdp","config_file","/etc/kamailio_icscf/icscf.xml") # ----- icscf params ----- # Comment the following line to enable realm routing #!ifdef CXDX_FORCED_PEER modparam("ims_icscf", "cxdx_forced_peer", CXDX_FORCED_PEER) #!endif modparam("ims_icscf","cxdx_dest_realm", NETWORKNAME) # DB-URL, where information about S-CSCF-Server can be found: #!ifdef DB_URL2 modparam("ims_icscf", "db_url", "cluster://cluster1") #!else modparam("ims_icscf", "db_url", DB_URL) #!endif #!ifdef PEERING # Route which is executed, in case HSS returned "User-Unknown" on LIR request modparam("ims_icscf","route_lir_user_unknown", "lir_term_user_unknown") #!endif #!ifdef FALLBACK_AUTH # Route which is executed, in case HSS returned "User-Unknown" on UAR request modparam("ims_icscf","route_uar_user_unknown", "uar_term_user_unknown") #!endif #!ifdef WITH_TLS # ----- tls params ----- modparam("tls", "config", "/etc/kamailio/tls.cfg") #!endif #!ifdef WITH_XMLRPC # ----- xmlrpc params ----- modparam("xmlrpc", "route", "XMLRPC"); modparam("xmlrpc", "url_match", "^/RPC") #!endif # ----- ctl params ----- modparam("ctl", "binrpc", "unix:/var/run/kamailio_icscf/kamailio_ctl") #!ifdef WITH_DEBUG # ----- debugger params ----- modparam("debugger", "cfgtrace", 1) #!endif #!ifdef CAPTURE_NODE # Destination, where to send the traffic modparam("siptrace", "duplicate_uri", CAPTURE_NODE) # Trace all traffic modparam("siptrace", "trace_on", 1) modparam("siptrace", "trace_to_database", 0) modparam("siptrace", "trace_flag", FLT_CAPTURE) modparam("siptrace", "hep_mode_on", 1) #!endif #!ifdef PEERING # ----- enum params ----- modparam("enum", "domain_suffix", ENUM_SUFFIX) #!endif # ----- tm params ----- # auto-discard branches from previous serial forking leg modparam("tm", "failure_reply_mode", 3) # default retransmission timeout: 10sec modparam("tm", "fr_timer", 10000) # default invite retransmission timeout after 1xx: 120sec modparam("tm", "fr_inv_timer", 120000) #!ifdef WITH_DEBUG loadmodule "debugger.so" modparam("debugger", "mod_hash_size", 5) modparam("debugger", "mod_level_mode", 1) modparam("debugger", "mod_level", "cdp=3") modparam("debugger", "mod_level", "ims_icscf=3") #!endif # ------------------------- request routing logic ------------------- # main routing logic route{ #!ifdef WITH_DEBUG xlog("I-CSCF >>>>>>>>>>>>>>>>>>>> $rm $ru ($fu => $tu ($si:$sp) to $tu, $ci)\n"); #!endif if !($rU =~ "\+.*") { prefix("+"); } # per request initial checks route(REQINIT); if (is_method("REGISTER")) { route(register); } if (is_method("INVITE|SUBSCRIBE|MESSAGE|INFO|PUBLISH|CANCEL")) { route(initial_request); } else { # Shouldn't get here unless missconfigured (add more methods as initial) or # somebody is routing unknown messages append_to_reply("Allow: INVITE,SUBSCRIBE,MESSAGE,INFO,PUBLISH,CANCEL\r\n"); send_reply("406","Initial Request Method not allowed at the I-CSCF"); break; } } ###################################################################### # Helper routes (Basic-Checks, NAT-Handling/RTP-Control, XML-RPC) ###################################################################### # Per SIP request initial checks route[REQINIT] { $var(used) = 1 - ($stat(free_size) / $stat(total_size)); xlog("L_DBG", "Mem: Total $stat(total_size), Free $stat(free_size) [$var(used)% used]\n"); if ($var(used) > 95) { send_reply("503", "Server overloaded"); exit; } # Trace this message #!ifdef CAPTURE_NODE sip_trace(); setflag(FLT_CAPTURE); #!endif if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } # Check for shutdown mode: if (!has_totag() && ($sel(cfg_get.system.shutdownmode) > 0)) { send_reply("503", "Server shutting down"); exit; } # Reply to OPTIONS: if (is_method("OPTIONS") && (uri==myself)) { options_reply(); exit; } # Ignore Re-Transmits: if (t_lookup_request()) { exit; } if (is_method("INVITE|REGISTER")) { send_reply("100", "Trying"); } } ###################################################################### # XMLRPC routing ###################################################################### #!ifdef WITH_XMLRPC route[XMLRPC] { if ((method=="POST" || method=="GET") #!ifdef XMLRPC_WHITELIST_1 && ((src_ip == XMLRPC_WHITELIST_1) #!ifdef XMLRPC_WHITELIST_2 || (src_ip == XMLRPC_WHITELIST_2) #!endif #!ifdef XMLRPC_WHITELIST_3 || (src_ip == XMLRPC_WHITELIST_3) #!endif ) #!endif ) { # close connection only for xmlrpclib user agents (there is a bug in # xmlrpclib: it waits for EOF before interpreting the response). if ($hdr(User-Agent) =~ "xmlrpclib") set_reply_close(); set_reply_no_connect(); dispatch_rpc(); exit; } send_reply("403", "Forbidden"); exit; } #!endif ###################################################################### # Handling of REGISTER requests ###################################################################### route[register] { t_set_fr(5000, 5000); #first check if we have an S-CSCF list if (I_scscf_select("0")) { #there is an S-CSCF list - no need to do a UAR t_on_reply("register_reply"); t_on_failure("register_failure"); if (!t_relay()) { send_reply("500","Error forwarding towards S-CSCF"); } } else { #no S-CSCF list therefore must do UAR #free this from the failed I_scscf_select call I_scscf_drop(); # Do an asynchronous UAR: #0=REG/DEREG; 1=REG+Capabilities if (!I_perform_user_authorization_request("REG_UAR_REPLY","0")) { send_reply("500", "Error in Request"); } } exit; } route[REG_UAR_REPLY] { #xlog("$$avp(s:uaa_return_code) = $avp(s:uaa_return_code)\n"); #this is async so to know status we have to check the reply avp switch ($avp(s:uaa_return_code)){ case 1: #success if (I_scscf_select("0")){ t_on_failure("register_failure"); t_on_reply("register_reply"); #now relay to appropriate SCSCF if (!t_relay()) { t_reply("500", "Error forwarding to SCSCF"); } } else {#select failed I_scscf_drop(); t_reply("500", "Server error on SCSCF Select (UAR)"); } break; case -1: #failure xlog("L_ERR", "UAR failure - error response sent from module\n"); break; case -2: #error xlog("L_ERR", "UAR error - sending error response now\n"); t_reply("500", "UAR failed"); break; default: xlog("L_ERR", "Unknown return code from UAR, value is [$avp(s:uaa_return_code)]\n"); t_reply("500", "Unknown response code from UAR"); break; } } ###################################################################### # Replies to REGISTER requests, ###################################################################### onreply_route[register_reply] { xlog("L_DBG", "Enter register reply block"); if (!t_check_status("(408)|(480)")){ if (!t_check_status("(401)")){ xlog("L_DBG", "dropping scscf list on register failure"); I_scscf_drop(); } else { xlog("L_DBG", "This is a 401 - keep scscf list to do optimisation"); } } break; } ###################################################################### # Failed REGISTERs ###################################################################### failure_route[register_failure] { if (t_branch_timeout() || t_check_status("([5-6][0-9][0-9])")){ if (I_scscf_select("1")) { t_on_reply("register_reply"); t_on_failure("register_failure"); if (!t_relay()) { t_reply("500","Error forwarding towards next S-CSCF"); break; } break; } else { t_reply("500", "Server error on UAR select next S-CSCF"); break; } } else { if (!t_check_status("(401)")){ xlog("L_DBG", "dropping scscf list on register failure"); I_scscf_drop(); } else { xlog("L_DBG", "This is a 401 - keep scscf list to do optimisation"); } break; } } ###################################################################### # Initial requests ###################################################################### route[initial_request] { xlog("$$ru => $ru\n"); I_perform_location_information_request("LIR_REPLY", "0"); } route[LIR_REPLY] { if ($avp(lia_return_code) == 1) { if (I_scscf_select("0")) { xlog("L_DBG", "ru = $ru, du = $du\n"); t_on_reply("initial_request_reply"); t_on_failure("initial_request_failure"); if (!t_relay()) { t_reply("500","Error forwarding towards S-CSCF"); break; } break; } else { xlog("L_DBG", "dropping scscf list on initial request"); I_scscf_drop(); t_reply("500", "Server error on LIR select S-CSCF"); break; } } else { t_reply("500", "Server error on LIR"); break; } break; } ###################################################################### # Replies to initial requests ###################################################################### onreply_route[initial_request_reply] { xlog("L_DBG", "Enter initial request request block"); if (!t_check_status("(408)")){ xlog("L_DBG", "dropping scscf list on initial request reply"); I_scscf_drop(); } break; } ###################################################################### # Failed initial requests ###################################################################### failure_route[initial_request_failure] { xlog("L_DBG", "Enter initial request failure block"); if (t_check_status("(408)")){ xlog("L_DBG", "Got a failure for initial request"); if (I_scscf_select("1")) { t_on_reply("initial_request_reply"); t_on_failure("initial_request_failure"); if (!t_relay()) { t_reply("500","Error forwarding towards next S-CSCF"); break; } break; } else { t_reply("500", "Server error on LIR select next S-CSCF"); break; } } else { xlog("L_DBG", "dropping scscf list on initial request failure"); I_scscf_drop(); } break; } #!ifdef PEERING ###################################################################### # HSS returned "User-Unknown" on LIR request ###################################################################### route[lir_term_user_unknown] { if (uri =~ "tel:.*") { # Let's check, if the number can be found in ENUM: if(!enum_query()) { # ENUM failed, send it to the PSTN-Gateway: route(PSTN); break; } # ENUM resolved to another domain if ($rd != NETWORKNAME) { t_on_reply("initial_request_reply"); t_on_failure("initial_request_failure"); if (!t_relay()) { t_reply("500","Error forwarding to external domain"); exit; }; exit; } else { t_reply("604","Does not exist anywhere - HSS User Unknown"); exit; }; } else { # we received a request for our domain (non-tel), but HSS said "User Unknown" if ($rd != NETWORKNAME) { t_reply("604","Does not exist anywhere - HSS User Unknown"); exit; } else { # try to forward non-tel request to other domain t_on_reply("Initial_Request_reply"); t_on_failure("Initial_Request_failure"); if (!t_relay()) { t_reply("500","Error forwarding to external domain"); exit; }; exit; }; }; } } ###################################################################### # Send calls to the PSTN-Gateways: ###################################################################### route[PSTN] { t_on_failure("PSTN_failure"); # Relay the request towards the PSTN-Gateway: if (!ds_select_dst("1", "4")) { send_reply("503", "Service not available"); exit; } # Relay the request: if (!t_relay()) { send_reply("503", "Service not available"); exit; }; exit; } ###################################################################### # manage failure routing cases, perform failover ###################################################################### failure_route[PSTN_failure] { # Choose another gateway, in case we # - get a local generated "408" # - receive a 5xx or 6xx reply from the proxy. if (t_branch_timeout() || t_check_status("[5-6]..")) { if (ds_next_dst()) { # Do Failover in case problems: t_on_failure("PSTN_failure"); # Relay the request: if (!t_relay()) { send_reply("503", "Service not available"); exit; }; } else { # Add a header, to indicate the phone should try again in 30 seconds. append_hf("Retry-After: 30\r\n"); send_reply("503", "Service not available"); } exit; } } #!endif #!ifdef FALLBACK_AUTH ###################################################################### # HSS returned "User-Unknown" on UAR request, # try to send it to any S-CSCF for authentication ###################################################################### route[uar_term_user_unknown] { $rd = "scscf."+NETWORKNAME; t_on_reply("register_reply"); t_on_failure("register_failure"); if (!t_relay()) { t_reply("500","Error forwarding towards S-CSCF"); break; } break; } #!endif