Kamailio-kamailio.cfg: Difference between revisions
(Created page with "== Overview == kamailio.cfg 파일 내용 정리 == Basic == kamailio.cfg 파일은 크게 세가지 영역으로 구분된다. * global parameters * modules settings * rout...") |
|||
(22 intermediate revisions by the same user not shown) | |||
Line 9: | Line 9: | ||
* routing blocks | * routing blocks | ||
== Global Parameters Section == | === Global Parameters Section === | ||
Configuration 파일의 첫번째 부분으로, Kamailio 의 core 와 custom global parameter 설정을 한다. | Configuration 파일의 첫번째 부분으로, Kamailio 의 core 와 custom global parameter 설정을 한다. | ||
Line 30: | Line 30: | ||
listen=udp:10.0.0.10:5060 | listen=udp:10.0.0.10:5060 | ||
</pre> | </pre> | ||
대부분의 parameter의 설정은 라인의 끝부분까지이지만, 세미콜론(;)을 사용할 수도 있다. | |||
이는 parameter 설정이 한번에 여러개의 값을 설정할 수 있도록 허용한 경우에 사용할 수 있다. | |||
<pre> | |||
alias="sip.mydomain.com"; | |||
</pre> | |||
만약 reserved config keyword 를 parameter로 사용하고 싶다면, ""로 감싸야 한다. 아래의 예에서 reserved config keyword 는 "dns"이다. | |||
<pre> | |||
listen=tcp:127.0.0.1:5060 advertise "sip.dns.example.com":5060 | |||
</pre> | |||
=== Modules Settings Section === | |||
Configuration file 의 두번째 부분으로써, module 들을 로드하는 지시어와 설정값들로 이루어져 있다. | |||
설정의 첫부분에는 mpath 지시어로 모듈 디렉토리를 지정한다. | |||
<pre> | |||
/* set paths to location of modules */ | |||
# mpath="/usr/local/lib64/kamailio/modules/" | |||
</pre> | |||
loadmoudle 과 modparam 지시어가 사용된다. | |||
<pre> | |||
loadmodule "debugger.so" | |||
... | |||
modparam("debugger", "cfgtrace", 1) | |||
</pre> | |||
=== Routing Blocks Section === | |||
Configuration 파일의 마지막 부분으로서 SIP 트래픽의 routing logic 을 설정한다. | |||
가장 중요한 routing block 은 request_route 이다. 이 request_route 에서 SIP 트래픽의 경로를 결정한다. | |||
<pre> | |||
request_route { | |||
# per request initial checks | |||
route(REQINIT); | |||
... | |||
} | |||
branch_route[MANAGE_BRANCH] { | |||
xdbg("new branch [$T_branch_idx] to $ru\n"); | |||
route(NATMANAGE); | |||
} | |||
</pre> | |||
== Generic Elements == | |||
=== Comments === | |||
# 혹은 // 로 시작하는 라인은 해당 라인이 코멘트로 인식된다. | |||
/* 과 */ 에 포함되는 모든 부분도 코멘트로 인식된다. | |||
<pre> | |||
# this is a line comment | |||
// this is another line comment | |||
/* this | |||
is | |||
a | |||
block | |||
comment */ | |||
</pre> | |||
단, #! 로 시작되는 preprocessor 지시어는 코멘트 처리되지 않는다. | |||
=== Values === | |||
세가지 타입의 value 가 있다. | |||
* integer: Numbers of 32-bit size. | |||
* boolean: aliases to 1(true, on, yes) or 0(false, off, no). | |||
* string: tokens enclosed in between double or single quotes. | |||
<pre> | |||
// next two are strings | |||
"this is a string value" | |||
'this is another string value" | |||
// next is a boolean | |||
yes | |||
// next is an integer | |||
64 | |||
</pre> | |||
=== Identifiers === | |||
Identifiers are tokens which are not enclosed in single or double quotes and to match the rules for integer or boolean values. | |||
<pre> | |||
return | |||
</pre> | |||
=== Variables === | |||
Variable 은 $로 시작한다. | |||
<pre> | |||
$var(x) = $rU + "@" + $fd; | |||
</pre> | |||
=== Actions === | |||
An action is an element used inside routing blocks ended by ;(semicolon). It can be an execution of a function from core or module, a conditional or loop statement, an assignment expression. | |||
<pre> | |||
sl_send_reply("404", "Not found"); | |||
exit; | |||
</pre> | |||
=== Expressions === | |||
An expression is an association group of statements, variables, functions and operatiors. | |||
<pre> | |||
if(!t_relay()) | |||
if($var(x)>10) | |||
"sip:" + $var(prefix) + $rU + "@" + $rd | |||
</pre> | |||
== Config Pre-Processor Directives == | |||
=== include_file === | |||
<pre> | |||
include_file "path_to_file" | |||
</pre> | |||
Include the content of the file in config before parsing. | |||
path_to_file 은 반드시 static string 이어야 한다. Including file operation is done at startup. If you change the content of included file, you have to restart the SIP server to become effective. | |||
The path_to_file can be relative or absolute. If it is not absolute path, first attempt is to locate it relative to current directory, and if fails, relative to directory of the file that includes int. There is no restriction where include can be used or what can contain - any part of config file is ok. There is a limit of maximum 10 includes in depth, otherwise you can use as many includes as you want. Reporting of the cfg file syntax errors prints now the file name for easier troubleshooting. | |||
If the included file is not found, the config file parser throws error. You can find this error message at the logging destination, usually in the system logging file. | |||
You can use also the syntax '''#!include_file''' or '''!!include_file'''. | |||
<pre> | |||
route { | |||
... | |||
include_file "/sr/checks.cfg" | |||
... | |||
} | |||
--- /sr/checks.cfg --- | |||
if (!mf_process_maxfwd_header("10")) { | |||
sl_send_reply("483","Too Many Hops"); | |||
exit; | |||
} | |||
--- | |||
</pre> | |||
=== import_file === | |||
<pre> | |||
import_file "path_to_file" | |||
</pre> | |||
Similar to include_file, but does not throw error if the include file is not found. | |||
=== define === | |||
Control in C-style what parts of the config file are executed. The parts in non-defined-zones are not loaded, ensuring lower memory usage and faster execution. | |||
Available directives: | |||
* #!define NAME: define a keyword | |||
* #!define NAME VALUE: define a keyword with value. | |||
* #!ifdef NAME: check if a keyword is defined | |||
* #!ifndef: check if a keyword is not defined. | |||
* #!else: switch to false branch of ifdef/ifndef region. | |||
* #!endif: end ifdef/ifndef region. | |||
* #!trydef: add a define if not already define. | |||
* #!redefine: forse readefinition even if already defined. | |||
Among benefits: | |||
* easy way to enable/disable features(e.g., see default cfg - controlling support of nat traversal, presence, etc...). | |||
* switch control for parts where conditional statements were not possible(e.g., global parameters, module settings). | |||
* faster by not using conditional statements inside routing blocks when switching between running environments. | |||
<pre> | |||
... | |||
#!define TESTBED_MODE | |||
#!ifdef TESTBED_MODE | |||
debug=5 | |||
log_stderror=yes | |||
listen=192.168.1.1 | |||
#!else | |||
debug=2 | |||
log_stderror=no | |||
listen=10.0.0.1 | |||
#!endif | |||
... | |||
#!ifdef TESTBED_MODE | |||
modparam("acc|auth_db|usrloc", "db_url", | |||
"mysql://kamailio:kamailiorw@localhost/kamailio_testbed") | |||
#!else | |||
modparam("acc|auth_db|usrloc", "db_url", | |||
"mysql://kamailio:kamailiorw@10.0.0.2/kamailio_production") | |||
#!endif | |||
... | |||
#!ifdef TESTBED_MODE | |||
route[DEBUG] { | |||
xlog("SCRIPT: SIP $rm from: $fu to: $ru - srcip: $si"\n); | |||
} | |||
#!endif | |||
... | |||
route { | |||
#!ifdef TESTBED_MODE | |||
route(DEBUG); | |||
#!endif | |||
... | |||
} | |||
... | |||
</pre> | |||
You can define values for IDs. | |||
<pre> | |||
#!define MYINT 123 | |||
#!define MYSTR "xyz" | |||
</pre> | |||
Defined IDs are replaced at startup, during config parsing, e.g., | |||
<pre> | |||
$var(x) = 100 + MYINT; | |||
</pre> | |||
is interpreted as | |||
<pre> | |||
$var(x) = 100 + 123; | |||
</pre> | |||
You can have multi-line defined IDs. | |||
<pre> | |||
#!define IDLOOP $var(i) = 0; \ | |||
while($var(i)<5) { \ | |||
xlog("++++ $var(i)\n"); \ | |||
$var(i) = $var(i) + 1; \ | |||
} | |||
</pre> | |||
Then in routing block | |||
<pre> | |||
route { | |||
... | |||
IDLOOP | |||
... | |||
} | |||
</pre> | |||
Number of allowed defines is not set to 256. | |||
Note: | |||
* Multilines defines are reduced to single line, so line counter should be fine. | |||
* Column counter goes inside the define value, but you have to omit the '\' and CR for the accurate inside-define position. | |||
* Text on the same line as the directive will cause problem. Keep the directive lines clean and only comment on a line before or after. | |||
=== subst === | |||
* Perform substitutions inside the strings of config (note that define is replacing only IDs - alphanumeric tokens not enclosed in quotes). | |||
* #!subst offers an easy way to search and replace inside strings before cfg parsing. | |||
<pre> | |||
#!subst "/regexp/subst/flags" | |||
</pre> | |||
* flag is optinal and can be below. | |||
** 'i': ignore case. | |||
** 'g': global replacement. | |||
<pre> | |||
#!subst "/DBPASSWD/xyz/" | |||
modparam("acc", "db_url", "mysql://user:DBPASSWD@localhost/db") | |||
</pre> | |||
db_url 파라미터 값으로 설정된 DBPASSWORD 는 xyz 로 대체된다. | |||
=== substdef === | |||
<pre> | |||
#!substdef "/ID/subst/" | |||
</pre> | |||
Similar to subst, but in addtion it adds a #!define ID subst. | |||
== Core Keywords == | |||
Keywords specific to SIP messages which can be used mainly in '''if''' expressions. | |||
=== af === | |||
The address family of the received SIP message. It is INET if the message was received over IPv4 or INET6 if the message was received over IPv6. | |||
Address Family. 주소 타입을 참조함다. IPv4 타입이면 INET, IPv6 타입이면 INET6 가 된다. | |||
<pre> | |||
if (af==INET6) { | |||
log("Message received over IPv6 link\n"); | |||
} | |||
</pre> | |||
=== dst_ip === | |||
The IP of the local interface where the SIP message was received. When the proxy listens on many network interfaces, makes possible to detect which was the one that received the packet. | |||
SIP message 를 수신한 IP 주소를 참조한다. Interface 가 많이 있어 Listen 하고 있는 주소가 많은 경우, 여러개의 IP 주소로 메시지가 수신될 수 있는데, 이를 구분할 때 사용할 수 있다. | |||
<pre> | |||
if(dst_ip==127.0.0.1) { | |||
log("message received on loopback interface\n"); | |||
}; | |||
</pre> | |||
=== dst_port === | |||
The local port where the SIP packet was received. When Kamailio is listening on many ports, it is useful to learn which was the one that received the SIP packet. | |||
SIP message 를 수신한 port 를 참조한다. | |||
<pre> | |||
if(dst_port==5061) | |||
{ | |||
log("message was received on port 5061\n"); | |||
}; | |||
</pre> | |||
=== from_uri === | |||
This script variable is a reference to the URI of 'From' header. It can be used to test 'From'- header URI value. | |||
수신한 SIP 메시지의 From header 의 URI 를 참조한다. | |||
<pre> | |||
if(is_method("INVITE") && from_uri=~".*@kamailio.org") | |||
{ | |||
log("the caller is from kamailio.org\n"); | |||
}; | |||
</pre> | |||
=== method === | |||
The variable is a reference to the SIP method of the message. | |||
수신한 SIP message 의 method 를 참조한다. | |||
<pre> | |||
if(method=="REGISTER") | |||
{ | |||
log("this SIP request is a REGISTER message\n"); | |||
}; | |||
</pre> | |||
=== msg:len === | |||
The variable is a reference to the size of the message. It can be used in '''if''' constructs to test message's size. | |||
수신한 message 의 len 를 참조한다. | |||
<pre> | |||
if(msg:len>2048) | |||
{ | |||
sl_send_reply("413", "message too large"); | |||
exit; | |||
}; | |||
</pre> | |||
=== ptoro === | |||
This variable can be used to test the transport protocol of the SIP message. | |||
수신한 SIP 메시지의 protocol 을 참조한다. | |||
<pre> | |||
if(proto==UDP) | |||
{ | |||
log("SIP message received over UDP\n"); | |||
}; | |||
</pre> | |||
=== status === | |||
If used in onreply_route, this variable is a reference to the status code of the reply. If it used in a standard route block, the variable is a reference to the status of the last reply sent out for the current request. | |||
onreply_route 에서는 reply 의 status code 를 참조한다. 일반 route block 에서는 현재 request 의 마지막 reply 의 status 를 참조한다. | |||
<pre> | |||
if(status=="200") | |||
{ | |||
log("this is a 200 OK reply\n"); | |||
}; | |||
</pre> | |||
=== snd_af, snd_ip, snd_port, snd_proto, === | |||
Kamailio 에서 메시지를 보낼 때 사용된 AF, IP, PORT, PROTO 를 참조한다. | |||
=== src_ip === | |||
Reference to source IP address of the SIP message. | |||
수신한 SIP message 의 Source IP 를 참조한다. | |||
<pre> | |||
if(src_ip==127.0.0.1) | |||
{ | |||
log("the message was sent from localhost!\n"); | |||
}; | |||
</pre> | |||
=== src_port === | |||
Reference to the source port of the SIP message (from which port the message was sent by the previous hop). | |||
수신한 SIP 메시지의 Source Port 를 참조한다. | |||
<pre> | |||
if(src_port==5061) | |||
{ | |||
log("message sent from port 5061\n"); | |||
} | |||
</pre> | |||
=== to_ip === | |||
=== to_port === | |||
=== to_uri === | |||
This variable can be used to test the value of URI from To header. | |||
수신한 SIP 메시지의 To header URI 를 참조한다. | |||
<pre> | |||
if(to_uri=~"sip:.+@kamailio.org") | |||
{ | |||
log("this is a request for kamailio.org users\n"); | |||
}; | |||
</pre> | |||
=== uri === | |||
This variable can be used to test the value of the request URI. | |||
수신한 SIP 메시지의 Request URI 를 참조한다. | |||
<pre> | |||
if(uri=~"sip:.+@kamailio.org") | |||
{ | |||
log("this is a request for kamailio.org users\n"); | |||
}; | |||
</pre> | |||
== Core Values == | |||
Values that can be used in '''if''' expressions to check against Core Keywords. | |||
=== INET === | |||
This keyword can be used to test whether the SIP packet was received over an IPv4 connection. | |||
<pre> | |||
if (af==INET) { | |||
log("the SIP message was received over IPv4\n"); | |||
} | |||
</pre> | |||
=== INET6 === | |||
This keyword can be used to test whether the SIP packet was received over an IPv6 connection. | |||
<pre> | |||
if(af==INET6) | |||
{ | |||
log("the SIP message was received over IPv6\n"); | |||
}; | |||
</pre> | |||
=== SCTP === | |||
This keyword can be used to test the value of '''proto''' and check whether the SIP packet was received over SCTP or not. | |||
<pre> | |||
if(proto==SCTP) | |||
{ | |||
log("the SIP message was received over SCTP\n"); | |||
}; | |||
</pre> | |||
=== TCP === | |||
This keyword can be used to test the value of '''proto''' and check whether the SIP packet was received over TCP or not. | |||
<pre> | |||
if(proto==TCP) | |||
{ | |||
log("the SIP message was received over TCP\n"); | |||
}; | |||
</pre> | |||
=== TLS === | |||
This keyword can be used to test the value of '''proto''' and check whether the SIP packet was received over TLS or not. | |||
<pre> | |||
if(proto==TLS) | |||
{ | |||
log("the SIP message was received over TLS\n"); | |||
}; | |||
</pre> | |||
=== UDP === | |||
This keyword can be used to test the value of '''proto''' and check whether the SIP packet was received over UDP or not. | |||
<pre> | |||
if(proto==UDP) | |||
{ | |||
log("the SIP message was received over UDP\n"); | |||
}; | |||
</pre> | |||
=== WS === | |||
This keyword can be used to test the value of '''proto''' and check whether the SIP packet was received over WS or not. | |||
<pre> | |||
if(proto==WS) | |||
{ | |||
log("the SIP message was received over WS\n"); | |||
}; | |||
</pre> | |||
=== WSS === | |||
This keyword can be used to test the value of '''proto''' and check whether the SIP packet was received over WSS or not. | |||
<pre> | |||
if(proto==WSS) | |||
{ | |||
log("the SIP message was received over WSS\n"); | |||
}; | |||
</pre> | |||
=== max_len === | |||
This command was removed. | |||
지금은 사용되지 않음. | |||
=== myself === | |||
This is a reference to the list of local IP address, hostnames, and aliases that has been set in the Kamailio configuration file. This lists contain the domains served by Kamailio. | |||
The variable can be used to test if the host part of an URI is in the list. The usefulness of this test is to select the messages that has to be processed locally or has to be forwared to another server. | |||
You can also use the is_mysqlf() function. | |||
<pre> | |||
if(uri==myself) { | |||
log("the request is for local processing\n"); | |||
}; | |||
</pre> | |||
== Core parameters == | |||
=== advertised_address === | |||
It can be an IP address or string and represents the address advertised in Via header. If empty or not set (default value) the socket address from where the request will be sent is used. | |||
Note: This option may be '''deprecated''' and removed in the near future, it is recoomended to set advertise option for listen parameter. | |||
<pre> | |||
advertised_address="1.2.3.4" | |||
advertised_address="kamailio.org" | |||
</pre> | |||
=== advertised_port === | |||
The port advertised in Via header. If empty or not set(default value) the prot from where the message will be sent is used. Same warning as for 'advertised_address'. | |||
Note: This option may be deprecated and removed in the near future, it is recommended to set advertise option for listen parameter. | |||
<pre> | |||
advertised_port=5080 | |||
</pre> | |||
=== alias === | |||
Parameter to set alias hostnames for the server. It can be set many times, each value being added in a list to match the hostname when 'myself' is checked. | |||
It is necessary to include the port(the port value used in the "port=" or "listen=" definitions) in the alias definition otherwise the loose_route() function will not work as expected for local forwards. Even if you do not use 'myself' explicitly (for example if you use the domain module), it is often necessary to set the alias as these aliases are used by the loose_routing function and might be needed to handle requests with pre-loaded route set correctly. | |||
Note: The hostname has to be enclosed in between quotes if it has reserved tokens such as forward, drop ... or operators such -(minus)... | |||
<pre> | |||
alias=other.domain.com:5060 | |||
alias=another.domain.com:5060 | |||
</pre> | |||
== Core Functions == | |||
=== force_rport === | |||
The force_rport() adds the rport parameter to the first Via header of the received message. Thus, Kamailio will add the received port to the top most Via header in the SIP message, even if the client does not indicate support for rport. This enables subsequent SIP message to return to the proper port later on in a SIP transaction. | |||
This is useful for NAT traversal, to enforce symmetric response signaling. | |||
The rport parameter is defined in RFC 3581. There is alose force_rport parameter which changes the global behavior of the SIP proxy. | |||
<pre> | |||
force_rport(); | |||
</pre> | |||
== Routing Blocks == | |||
The routing blocks are the parts of the configuration file executed by kamailio at runtime. They can be seen as blocks of actions similar to functions (or procedures) from common programming languages. | |||
A routing block is identified by a specific token, followed by a name in between square brackets and actions in between curly braces. | |||
<pre> | |||
route_block_id[NAME] { | |||
ACTIONS | |||
} | |||
</pre> | |||
The name can be any alphanumeric string, with specific routing blocks enforcing a particular format. | |||
: route(number) is equivalent to route("number"). | |||
Route blocks can be executed on network events (e.g., receiving a SIP message), timer events(e.g., retransmission timeout) or particular events specific to modules. | |||
There can be so called sub-route blocks, which can be invoked from another route blocks, like a function. Invocation is done with 'route' followed by the name of sub-route to execute, enclosed in between parentheses. | |||
<pre> | |||
request_route{ | |||
... | |||
route("test"); | |||
... | |||
} | |||
route["test"]{ | |||
... | |||
} | |||
</pre> | |||
=== request_route === | |||
Reqeust routing block - is executed for each SIP request. | |||
It contains a set of actions to be executed for SIP requests received from the network. It is the equivalent of '''main()''' function for handling the SIP requests. | |||
For backward compatibility reasons, the main request 'route' block can be identified by 'route{...}' or 'route[0]{...}'. | |||
The implicit action after execution of the main route block is to drop the SIP request. To send a reply or forward the request, explicit actions (e.g., sl_send_reply(), forward(), t_relay()) must be called inside the route block. | |||
<pre> | |||
request_route { | |||
if(is_method("OPTIONS")) { | |||
# send reply for each options request | |||
sl_send_reply("200", "ok"); | |||
exit(); | |||
} | |||
route(FWD); | |||
} | |||
route[FWD] { | |||
# forward according to uri | |||
forward(); | |||
} | |||
</pre> | |||
=== reply_route === | |||
Main SIP response (reply) handling block - it contains a set of actions to be executed for SIP replies. It is executed for all replies received from the network. | |||
It does not have a name and it is executed by the core, before any other module handling the SIP reply. It is triggered only by SIP replies on the network. | |||
There is no network route that can be enforced for a SIP reply - it is sent based based on Via header, according to SIP RFC3261 - therefore no dedicated actions for forwarding the reply must be used in this block. | |||
This routing block is optional, if missing, the SIP reply is sent to the address in 2nd Via header. | |||
<pre> | |||
reply_route { | |||
if(status=="128"") { | |||
drop; | |||
} | |||
} | |||
</pre> | |||
Note: for backward compatibility reasons, the main 'reply' routing block can b e also identified by 'onreply_route{...}' or 'onreply_route[0]{...}'. | |||
=== onreply_route === | |||
SIP reply routing block executed by tm module. It contains a set of actions to be taken for SIP replies in the contect of an active transaction. | |||
The 'onreply_route' must be armed for the SIP requests whose replies should be processed within it, via t_on_reply("onreply_route_index"). | |||
Main 'onreply_route' block is executed before a possible tm 'onreply_route' blcok. | |||
<pre> | |||
request_route { | |||
lookup("location"); | |||
t_on_reply("LOGRPL"); | |||
if(!t_relay()) { | |||
sl_send_reply("500", "relaying failed"); | |||
} | |||
} | |||
reply_route { | |||
if(!t_check_trans()) { | |||
drop; | |||
} | |||
} | |||
onreply_route[LOGRPL] { | |||
if(status=~"1[0-9][0-9]") { | |||
log("provisional response\n"); | |||
} | |||
} | |||
</pre> | |||
== See also == | |||
* https://www.kamailio.org/wiki/cookbooks/5.2.x/core | |||
[[category:kamailio]] | [[category:kamailio]] |
Latest revision as of 12:04, 10 March 2020
Overview
kamailio.cfg 파일 내용 정리
Basic
kamailio.cfg 파일은 크게 세가지 영역으로 구분된다.
- global parameters
- modules settings
- routing blocks
Global Parameters Section
Configuration 파일의 첫번째 부분으로, Kamailio 의 core 와 custom global parameter 설정을 한다.
일반적으로 다음과 같이 설정된다.
name=value
name 부분은 core parameter 에 나와있는 항목이어야 한다. 만약 항목에 없는 name 을 설정했다면, kamailio 는 에러를 발생시키고 시작하지 앟는다.
value 부분은 integer, boolean, string 으로 설정한다. 하지만 몇몇 parameter 들은 복합된 형식의 value 로도 설정이 가능하다.
log_facility=LOG_LOCAL0 children=4 disable_tcp=yes alias="sip.mydomain.com" listen=udp:10.0.0.10:5060
대부분의 parameter의 설정은 라인의 끝부분까지이지만, 세미콜론(;)을 사용할 수도 있다. 이는 parameter 설정이 한번에 여러개의 값을 설정할 수 있도록 허용한 경우에 사용할 수 있다.
alias="sip.mydomain.com";
만약 reserved config keyword 를 parameter로 사용하고 싶다면, ""로 감싸야 한다. 아래의 예에서 reserved config keyword 는 "dns"이다.
listen=tcp:127.0.0.1:5060 advertise "sip.dns.example.com":5060
Modules Settings Section
Configuration file 의 두번째 부분으로써, module 들을 로드하는 지시어와 설정값들로 이루어져 있다.
설정의 첫부분에는 mpath 지시어로 모듈 디렉토리를 지정한다.
/* set paths to location of modules */ # mpath="/usr/local/lib64/kamailio/modules/"
loadmoudle 과 modparam 지시어가 사용된다.
loadmodule "debugger.so" ... modparam("debugger", "cfgtrace", 1)
Routing Blocks Section
Configuration 파일의 마지막 부분으로서 SIP 트래픽의 routing logic 을 설정한다.
가장 중요한 routing block 은 request_route 이다. 이 request_route 에서 SIP 트래픽의 경로를 결정한다.
request_route { # per request initial checks route(REQINIT); ... } branch_route[MANAGE_BRANCH] { xdbg("new branch [$T_branch_idx] to $ru\n"); route(NATMANAGE); }
Generic Elements
Comments
- 혹은 // 로 시작하는 라인은 해당 라인이 코멘트로 인식된다.
/* 과 */ 에 포함되는 모든 부분도 코멘트로 인식된다.
# this is a line comment // this is another line comment /* this is a block comment */
단, #! 로 시작되는 preprocessor 지시어는 코멘트 처리되지 않는다.
Values
세가지 타입의 value 가 있다.
- integer: Numbers of 32-bit size.
- boolean: aliases to 1(true, on, yes) or 0(false, off, no).
- string: tokens enclosed in between double or single quotes.
// next two are strings "this is a string value" 'this is another string value" // next is a boolean yes // next is an integer 64
Identifiers
Identifiers are tokens which are not enclosed in single or double quotes and to match the rules for integer or boolean values.
return
Variables
Variable 은 $로 시작한다.
$var(x) = $rU + "@" + $fd;
Actions
An action is an element used inside routing blocks ended by ;(semicolon). It can be an execution of a function from core or module, a conditional or loop statement, an assignment expression.
sl_send_reply("404", "Not found"); exit;
Expressions
An expression is an association group of statements, variables, functions and operatiors.
if(!t_relay()) if($var(x)>10) "sip:" + $var(prefix) + $rU + "@" + $rd
Config Pre-Processor Directives
include_file
include_file "path_to_file"
Include the content of the file in config before parsing.
path_to_file 은 반드시 static string 이어야 한다. Including file operation is done at startup. If you change the content of included file, you have to restart the SIP server to become effective.
The path_to_file can be relative or absolute. If it is not absolute path, first attempt is to locate it relative to current directory, and if fails, relative to directory of the file that includes int. There is no restriction where include can be used or what can contain - any part of config file is ok. There is a limit of maximum 10 includes in depth, otherwise you can use as many includes as you want. Reporting of the cfg file syntax errors prints now the file name for easier troubleshooting.
If the included file is not found, the config file parser throws error. You can find this error message at the logging destination, usually in the system logging file.
You can use also the syntax #!include_file or !!include_file.
route { ... include_file "/sr/checks.cfg" ... } --- /sr/checks.cfg --- if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } ---
import_file
import_file "path_to_file"
Similar to include_file, but does not throw error if the include file is not found.
define
Control in C-style what parts of the config file are executed. The parts in non-defined-zones are not loaded, ensuring lower memory usage and faster execution.
Available directives:
- #!define NAME: define a keyword
- #!define NAME VALUE: define a keyword with value.
- #!ifdef NAME: check if a keyword is defined
- #!ifndef: check if a keyword is not defined.
- #!else: switch to false branch of ifdef/ifndef region.
- #!endif: end ifdef/ifndef region.
- #!trydef: add a define if not already define.
- #!redefine: forse readefinition even if already defined.
Among benefits:
- easy way to enable/disable features(e.g., see default cfg - controlling support of nat traversal, presence, etc...).
- switch control for parts where conditional statements were not possible(e.g., global parameters, module settings).
- faster by not using conditional statements inside routing blocks when switching between running environments.
... #!define TESTBED_MODE #!ifdef TESTBED_MODE debug=5 log_stderror=yes listen=192.168.1.1 #!else debug=2 log_stderror=no listen=10.0.0.1 #!endif ... #!ifdef TESTBED_MODE modparam("acc|auth_db|usrloc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio_testbed") #!else modparam("acc|auth_db|usrloc", "db_url", "mysql://kamailio:kamailiorw@10.0.0.2/kamailio_production") #!endif ... #!ifdef TESTBED_MODE route[DEBUG] { xlog("SCRIPT: SIP $rm from: $fu to: $ru - srcip: $si"\n); } #!endif ... route { #!ifdef TESTBED_MODE route(DEBUG); #!endif ... } ...
You can define values for IDs.
#!define MYINT 123 #!define MYSTR "xyz"
Defined IDs are replaced at startup, during config parsing, e.g.,
$var(x) = 100 + MYINT;
is interpreted as
$var(x) = 100 + 123;
You can have multi-line defined IDs.
#!define IDLOOP $var(i) = 0; \ while($var(i)<5) { \ xlog("++++ $var(i)\n"); \ $var(i) = $var(i) + 1; \ }
Then in routing block
route { ... IDLOOP ... }
Number of allowed defines is not set to 256.
Note:
- Multilines defines are reduced to single line, so line counter should be fine.
- Column counter goes inside the define value, but you have to omit the '\' and CR for the accurate inside-define position.
- Text on the same line as the directive will cause problem. Keep the directive lines clean and only comment on a line before or after.
subst
- Perform substitutions inside the strings of config (note that define is replacing only IDs - alphanumeric tokens not enclosed in quotes).
- #!subst offers an easy way to search and replace inside strings before cfg parsing.
#!subst "/regexp/subst/flags"
- flag is optinal and can be below.
- 'i': ignore case.
- 'g': global replacement.
#!subst "/DBPASSWD/xyz/" modparam("acc", "db_url", "mysql://user:DBPASSWD@localhost/db")
db_url 파라미터 값으로 설정된 DBPASSWORD 는 xyz 로 대체된다.
substdef
#!substdef "/ID/subst/"
Similar to subst, but in addtion it adds a #!define ID subst.
Core Keywords
Keywords specific to SIP messages which can be used mainly in if expressions.
af
The address family of the received SIP message. It is INET if the message was received over IPv4 or INET6 if the message was received over IPv6.
Address Family. 주소 타입을 참조함다. IPv4 타입이면 INET, IPv6 타입이면 INET6 가 된다.
if (af==INET6) { log("Message received over IPv6 link\n"); }
dst_ip
The IP of the local interface where the SIP message was received. When the proxy listens on many network interfaces, makes possible to detect which was the one that received the packet.
SIP message 를 수신한 IP 주소를 참조한다. Interface 가 많이 있어 Listen 하고 있는 주소가 많은 경우, 여러개의 IP 주소로 메시지가 수신될 수 있는데, 이를 구분할 때 사용할 수 있다.
if(dst_ip==127.0.0.1) { log("message received on loopback interface\n"); };
dst_port
The local port where the SIP packet was received. When Kamailio is listening on many ports, it is useful to learn which was the one that received the SIP packet.
SIP message 를 수신한 port 를 참조한다.
if(dst_port==5061) { log("message was received on port 5061\n"); };
from_uri
This script variable is a reference to the URI of 'From' header. It can be used to test 'From'- header URI value.
수신한 SIP 메시지의 From header 의 URI 를 참조한다.
if(is_method("INVITE") && from_uri=~".*@kamailio.org") { log("the caller is from kamailio.org\n"); };
method
The variable is a reference to the SIP method of the message.
수신한 SIP message 의 method 를 참조한다.
if(method=="REGISTER") { log("this SIP request is a REGISTER message\n"); };
msg:len
The variable is a reference to the size of the message. It can be used in if constructs to test message's size.
수신한 message 의 len 를 참조한다.
if(msg:len>2048) { sl_send_reply("413", "message too large"); exit; };
ptoro
This variable can be used to test the transport protocol of the SIP message.
수신한 SIP 메시지의 protocol 을 참조한다.
if(proto==UDP) { log("SIP message received over UDP\n"); };
status
If used in onreply_route, this variable is a reference to the status code of the reply. If it used in a standard route block, the variable is a reference to the status of the last reply sent out for the current request.
onreply_route 에서는 reply 의 status code 를 참조한다. 일반 route block 에서는 현재 request 의 마지막 reply 의 status 를 참조한다.
if(status=="200") { log("this is a 200 OK reply\n"); };
snd_af, snd_ip, snd_port, snd_proto,
Kamailio 에서 메시지를 보낼 때 사용된 AF, IP, PORT, PROTO 를 참조한다.
src_ip
Reference to source IP address of the SIP message.
수신한 SIP message 의 Source IP 를 참조한다.
if(src_ip==127.0.0.1) { log("the message was sent from localhost!\n"); };
src_port
Reference to the source port of the SIP message (from which port the message was sent by the previous hop).
수신한 SIP 메시지의 Source Port 를 참조한다.
if(src_port==5061) { log("message sent from port 5061\n"); }
to_ip
to_port
to_uri
This variable can be used to test the value of URI from To header.
수신한 SIP 메시지의 To header URI 를 참조한다.
if(to_uri=~"sip:.+@kamailio.org") { log("this is a request for kamailio.org users\n"); };
uri
This variable can be used to test the value of the request URI.
수신한 SIP 메시지의 Request URI 를 참조한다.
if(uri=~"sip:.+@kamailio.org") { log("this is a request for kamailio.org users\n"); };
Core Values
Values that can be used in if expressions to check against Core Keywords.
INET
This keyword can be used to test whether the SIP packet was received over an IPv4 connection.
if (af==INET) { log("the SIP message was received over IPv4\n"); }
INET6
This keyword can be used to test whether the SIP packet was received over an IPv6 connection.
if(af==INET6) { log("the SIP message was received over IPv6\n"); };
SCTP
This keyword can be used to test the value of proto and check whether the SIP packet was received over SCTP or not.
if(proto==SCTP) { log("the SIP message was received over SCTP\n"); };
TCP
This keyword can be used to test the value of proto and check whether the SIP packet was received over TCP or not.
if(proto==TCP) { log("the SIP message was received over TCP\n"); };
TLS
This keyword can be used to test the value of proto and check whether the SIP packet was received over TLS or not.
if(proto==TLS) { log("the SIP message was received over TLS\n"); };
UDP
This keyword can be used to test the value of proto and check whether the SIP packet was received over UDP or not.
if(proto==UDP) { log("the SIP message was received over UDP\n"); };
WS
This keyword can be used to test the value of proto and check whether the SIP packet was received over WS or not.
if(proto==WS) { log("the SIP message was received over WS\n"); };
WSS
This keyword can be used to test the value of proto and check whether the SIP packet was received over WSS or not.
if(proto==WSS) { log("the SIP message was received over WSS\n"); };
max_len
This command was removed.
지금은 사용되지 않음.
myself
This is a reference to the list of local IP address, hostnames, and aliases that has been set in the Kamailio configuration file. This lists contain the domains served by Kamailio.
The variable can be used to test if the host part of an URI is in the list. The usefulness of this test is to select the messages that has to be processed locally or has to be forwared to another server.
You can also use the is_mysqlf() function.
if(uri==myself) { log("the request is for local processing\n"); };
Core parameters
advertised_address
It can be an IP address or string and represents the address advertised in Via header. If empty or not set (default value) the socket address from where the request will be sent is used.
Note: This option may be deprecated and removed in the near future, it is recoomended to set advertise option for listen parameter.
advertised_address="1.2.3.4" advertised_address="kamailio.org"
advertised_port
The port advertised in Via header. If empty or not set(default value) the prot from where the message will be sent is used. Same warning as for 'advertised_address'.
Note: This option may be deprecated and removed in the near future, it is recommended to set advertise option for listen parameter.
advertised_port=5080
alias
Parameter to set alias hostnames for the server. It can be set many times, each value being added in a list to match the hostname when 'myself' is checked.
It is necessary to include the port(the port value used in the "port=" or "listen=" definitions) in the alias definition otherwise the loose_route() function will not work as expected for local forwards. Even if you do not use 'myself' explicitly (for example if you use the domain module), it is often necessary to set the alias as these aliases are used by the loose_routing function and might be needed to handle requests with pre-loaded route set correctly.
Note: The hostname has to be enclosed in between quotes if it has reserved tokens such as forward, drop ... or operators such -(minus)...
alias=other.domain.com:5060 alias=another.domain.com:5060
Core Functions
force_rport
The force_rport() adds the rport parameter to the first Via header of the received message. Thus, Kamailio will add the received port to the top most Via header in the SIP message, even if the client does not indicate support for rport. This enables subsequent SIP message to return to the proper port later on in a SIP transaction.
This is useful for NAT traversal, to enforce symmetric response signaling.
The rport parameter is defined in RFC 3581. There is alose force_rport parameter which changes the global behavior of the SIP proxy.
force_rport();
Routing Blocks
The routing blocks are the parts of the configuration file executed by kamailio at runtime. They can be seen as blocks of actions similar to functions (or procedures) from common programming languages.
A routing block is identified by a specific token, followed by a name in between square brackets and actions in between curly braces.
route_block_id[NAME] { ACTIONS }
The name can be any alphanumeric string, with specific routing blocks enforcing a particular format.
- route(number) is equivalent to route("number").
Route blocks can be executed on network events (e.g., receiving a SIP message), timer events(e.g., retransmission timeout) or particular events specific to modules.
There can be so called sub-route blocks, which can be invoked from another route blocks, like a function. Invocation is done with 'route' followed by the name of sub-route to execute, enclosed in between parentheses.
request_route{ ... route("test"); ... } route["test"]{ ... }
request_route
Reqeust routing block - is executed for each SIP request.
It contains a set of actions to be executed for SIP requests received from the network. It is the equivalent of main() function for handling the SIP requests.
For backward compatibility reasons, the main request 'route' block can be identified by 'route{...}' or 'route[0]{...}'.
The implicit action after execution of the main route block is to drop the SIP request. To send a reply or forward the request, explicit actions (e.g., sl_send_reply(), forward(), t_relay()) must be called inside the route block.
request_route { if(is_method("OPTIONS")) { # send reply for each options request sl_send_reply("200", "ok"); exit(); } route(FWD); } route[FWD] { # forward according to uri forward(); }
reply_route
Main SIP response (reply) handling block - it contains a set of actions to be executed for SIP replies. It is executed for all replies received from the network.
It does not have a name and it is executed by the core, before any other module handling the SIP reply. It is triggered only by SIP replies on the network.
There is no network route that can be enforced for a SIP reply - it is sent based based on Via header, according to SIP RFC3261 - therefore no dedicated actions for forwarding the reply must be used in this block.
This routing block is optional, if missing, the SIP reply is sent to the address in 2nd Via header.
reply_route { if(status=="128"") { drop; } }
Note: for backward compatibility reasons, the main 'reply' routing block can b e also identified by 'onreply_route{...}' or 'onreply_route[0]{...}'.
onreply_route
SIP reply routing block executed by tm module. It contains a set of actions to be taken for SIP replies in the contect of an active transaction.
The 'onreply_route' must be armed for the SIP requests whose replies should be processed within it, via t_on_reply("onreply_route_index").
Main 'onreply_route' block is executed before a possible tm 'onreply_route' blcok.
request_route { lookup("location"); t_on_reply("LOGRPL"); if(!t_relay()) { sl_send_reply("500", "relaying failed"); } } reply_route { if(!t_check_trans()) { drop; } } onreply_route[LOGRPL] { if(status=~"1[0-9][0-9]") { log("provisional response\n"); } }