640 lines
17 KiB
INI
640 lines
17 KiB
INI
#!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.kamailio.org>.
|
|
#
|
|
# 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=on
|
|
# Always: Also try IPv6:
|
|
dns_try_ipv6=on
|
|
# 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=4
|
|
|
|
# ------------------ module loading ----------------------------------
|
|
mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/lib64/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"
|
|
#!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"
|
|
loadmodule "dispatcher"
|
|
#!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
|
|
|
|
loadmodule "jsonrpcs.so"
|
|
# ----- jsonrpcs params -----
|
|
modparam("jsonrpcs", "pretty_format", 1)
|
|
/* set the path to RPC fifo control file */
|
|
modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo")
|
|
/* set the path to RPC unix socket control file */
|
|
modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock")
|
|
|
|
# -- 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_icscf/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/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)
|
|
# Don't reply automatically with "100 Trying"
|
|
modparam("tm", "auto_inv_100", 0)
|
|
|
|
#!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("NOTIFY") && search("^(Event|o)([ \t]*):([ \t]*)reg")) {
|
|
if (!t_relay()) {
|
|
sl_reply_error();
|
|
}
|
|
exit;
|
|
}
|
|
|
|
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]
|
|
{
|
|
# $avp(prefix)="+";
|
|
# $ru= $(ru{s.rm,$avp(prefix)});
|
|
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
|