examples/icscf/kamailio.cfg
85ee1079
 #!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: <sr-users@lists.sip-router.org>.
 #
 # For more information about the various parameters, functions and statements
 # try http://sip-router.org/wiki/ .
 #
17fa8ffe
 
 system.shutdownmode = 0 desc "System shutdown mode"
 
85ee1079
 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
 
 ####### 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
94d5ace9
 # Query NAPTR-Records as well:
17fa8ffe
 dns_try_naptr=no
85ee1079
 
86d706bd
 #!ifdef WITH_XMLRPC
 #!ifndef WITH_TCP
85ee1079
 #!define WITH_TCP
86d706bd
 #!endif
 #!ifndef TCP_PROCESSES
 # Number of TCP Processes
 #!define TCP_PROCESSES 3
 #!endif
85ee1079
 #!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
86d706bd
 #!ifdef TCP_PROCESSES
 tcp_children=TCP_PROCESSES
 #!endif
85ee1079
 #!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 "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:
17fa8ffe
 loadmodule "db_mysql"
 #!ifdef DB_URL2
 loadmodule "db_cluster"
 #!endif
85ee1079
 
 loadmodule "cdp.so"
 loadmodule "cdp_avp.so"
 loadmodule "xlog.so"
 
d3dee2b4
 loadmodule "ims_icscf.so"
85ee1079
 
 #!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 ---------------
17fa8ffe
 #!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
 
85ee1079
 # ----- 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.xml")
 
 # ----- icscf params -----
 # Comment the following line to enable realm routing
 #!ifdef CXDX_FORCED_PEER
d3dee2b4
 modparam("ims_icscf", "cxdx_forced_peer", CXDX_FORCED_PEER)
85ee1079
 #!endif
d3dee2b4
 modparam("ims_icscf","cxdx_dest_realm", NETWORKNAME)
17fa8ffe
 
85ee1079
 # DB-URL, where information about S-CSCF-Server can be found:
17fa8ffe
 #!ifdef DB_URL2
 modparam("ims_icscf", "db_url", "cluster://cluster1")
 #!else
 modparam("ims_icscf", "db_url", DB_URL)
 #!endif
 
d3dee2b4
 modparam("ims_icscf","cxdx_dest_realm", NETWORKNAME)
85ee1079
 #!ifdef PEERING
 # Route which is executed, in case HSS returned "User-Unknown" on LIR request
d3dee2b4
 modparam("ims_icscf","route_lir_user_unknown", "lir_term_user_unknown")
85ee1079
 #!endif
 #!ifdef FALLBACK_AUTH
 # Route which is executed, in case HSS returned "User-Unknown" on UAR request
d3dee2b4
 modparam("ims_icscf","route_uar_user_unknown", "uar_term_user_unknown")
85ee1079
 #!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
 
 #!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
 
17fa8ffe
 # ----- 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)
 
85ee1079
 # -------------------------  request routing logic -------------------
 # main routing logic
 
 route{
17fa8ffe
 #!ifdef WITH_DEBUG
 	xlog("$rm ($fu ($si:$sp) to $tu, $ci)\n");
 #!endif
85ee1079
 
 	# per request initial checks
 	route(REQINIT);
 
 	if (is_method("REGISTER")) {
 		route(register);
 		break;
 	}
 
 	if (is_method("INVITE|SUBSCRIBE|MESSAGE|INFO|PUBLISH|CANCEL")) {
 		route(initial_request);
 		break;
 	} 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");
 		t_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] {
 	# 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;
 	}
17fa8ffe
 
 	if (is_method("INVITE|REGISTER")) {
 		send_reply("100", "Trying");
 	}
85ee1079
 }
 
 ######################################################################
 # XMLRPC routing
 ######################################################################
 #!ifdef WITH_XMLRPC
 route[XMLRPC] {
86d706bd
 	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
 ) {
85ee1079
 		# 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]
 {
 	#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()) {
 			t_reply("500","Error forwarding towards S-CSCF");
 			break;
 		}
 		break;
        } 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:
bf08aa1a
                 I_perform_user_authorization_request("REG_UAR_REPLY","0"); #0=REG/DEREG; 1=REG+Capabilities
                 exit;    
85ee1079
 	}
 	break;
 }
 
bf08aa1a
 route[REG_UAR_REPLY]
 {
     #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;
     }
 }
 
 
85ee1079
 ######################################################################
 # 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]
 {
17fa8ffe
 	if (t_check_status("(403)|(408)|(480)|([5-6][0-9][0-9])")){
85ee1079
 		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]
 {
d07e4f70
 	I_perform_location_information_request("LIR_REPLY", "0");
 }
 
 route[LIR_REPLY] {
85ee1079
 	if ($avp(lia_return_code) == 1) {
 		if (I_scscf_select("0")) {
6729c79d
 			xlog("L_DBG", "ru = $ru, du = $du\n");
85ee1079
 			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