|
@@ -0,0 +1,1823 @@
|
|
|
+# History: 9 Years SER-Kamailio
|
|
|
+
|
|
|
+ Date: Sep 3, 2010
|
|
|
+ Data compiled by: Daniel-Constantin Mierla
|
|
|
+
|
|
|
+## Overview
|
|
|
+
|
|
|
+**SIP Express Router** (aka **SER**) is a high-performance,
|
|
|
+configurable, free Session Initiation Protocol (SIP) server licensed
|
|
|
+under the open-source GNU license, offering a large set of features.
|
|
|
+Started before the publishing of RFC3261 (SIP v2.0), SER pioneered the
|
|
|
+development of many SIP extensions and pushed further the real-time
|
|
|
+communications over IP.
|
|
|
+
|
|
|
+Initial project web site was:
|
|
|
+
|
|
|
+- <http://iptel.org/ser>
|
|
|
+
|
|
|
+Now the web sites are:
|
|
|
+
|
|
|
+- <http://sip-router.org> (historical)
|
|
|
+- <http://www.kamailio.org>
|
|
|
+
|
|
|
+It is the oldest and most robust open source SIP server, routing
|
|
|
+**billions of VoIP minutes every month world wide**, being used from
|
|
|
+Telcos and Carriers to ITSP and SOHO environments. If you haven't heard
|
|
|
+of it so far, it is very likely because your VoIP provider routes the
|
|
|
+calls fast and reliable with SER-based SIP servers, so you don't need to
|
|
|
+build your own system.
|
|
|
+
|
|
|
+First source code commit of SER was done **9 years ago**: **Sep 3,
|
|
|
+2001**. According to GIT log, first three commits were:
|
|
|
+
|
|
|
+ git log --pretty=format:"%h%x09%an%x09%ad%x09%s" --reverse | head -3
|
|
|
+
|
|
|
+ 512dcd9 Andrei Pelinescu-Onciul Mon Sep 3 21:27:11 2001 +0000 Initial revision
|
|
|
+ 888ca09 Andrei Pelinescu-Onciul Tue Sep 4 01:41:39 2001 +0000 parser seems to work
|
|
|
+ e60a972 Andrei Pelinescu-Onciul Tue Sep 4 20:55:41 2001 +0000 First working release
|
|
|
+
|
|
|
+That is **3286 days** of continuous development, with over **70**
|
|
|
+registered developers and hundreds of contributors, estimated cost of
|
|
|
+development: **over 8 000 000 USD**.
|
|
|
+
|
|
|
+## Summary of Evolution
|
|
|
+
|
|
|
+- **September 2001** - initial commit, SER was then developed for
|
|
|
+ about one year internally at FhG FOKUS Institute, Berlin, Germany
|
|
|
+- **Autumn 2002** - SER was released as GPL, code published on
|
|
|
+ BerliOS: <http://developer.berlios.de/projects/ser/>
|
|
|
+- **June 2005** - [OpenSER](http://www.openser-project.org) forked
|
|
|
+ from SER, code hosted by Source Forge:
|
|
|
+ <http://sourceforge.net/projects/openser/>
|
|
|
+- **July 2008** - OpenSER was renamed to
|
|
|
+ [Kamailio](http://www.kamailio.org)
|
|
|
+- **November 2008** - SER and Kamailio teams decide to join
|
|
|
+ development efforts and merge the source code trees of the two
|
|
|
+ applications
|
|
|
+ - development portal for both changed to: <http://sip-router.org>
|
|
|
+- **January 2010** - version 3.0.0 is released, from a source code
|
|
|
+ tree containing both SER and Kamailio
|
|
|
+- **September 2010** - expect next major release, version 3.1.0
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/sip-router-evolution.png" class="align-center" alt="http://sip-router.org/pub/img/sip-router-evolution.png" />
|
|
|
+
|
|
|
+SER code and architecture was and still is the foundation for other
|
|
|
+projects that forked over years from it or from its forks, which still
|
|
|
+keep majority of inherited code untouched.
|
|
|
+
|
|
|
+As you can notice, **SER** and **Kamailio** are now same application
|
|
|
+(completely the same source code). The difference is made by what
|
|
|
+modules are you using for same purpose (e.g., user authentication,
|
|
|
+location, accounting) because the variants have a different database
|
|
|
+structure (you can notice later the existence of modules with same name,
|
|
|
+but located in different folders).
|
|
|
+
|
|
|
+<img src="http://www.kamailio.org/wp-images/kamailio-rock-logo.jpg" class="align-center" alt="http://www.kamailio.org/wp-images/kamailio-rock-logo.jpg" />
|
|
|
+
|
|
|
+Of course you can combine to some extent, for example use
|
|
|
+Kamailio-specific accounting module with SER-specific database user
|
|
|
+authentication module. The limitation comes to modules that have
|
|
|
+dependencies, for example registrar module depends on usrloc module --
|
|
|
+you have to use both from one side.
|
|
|
+
|
|
|
+### Public Releases
|
|
|
+
|
|
|
+There were 11 distinct numbering versions used over the years (0.9.x was
|
|
|
+overlapping, counted once), internal VCS branching representations were:
|
|
|
+
|
|
|
+#### SER Only Versions
|
|
|
+
|
|
|
+- 2002-09-25: SER 0.8.x
|
|
|
+- 2005-07-04: SER 0.9.x
|
|
|
+- 2008-08-06: SER 2.0.x
|
|
|
+- 2009-02-28: SER 2.1.x
|
|
|
+
|
|
|
+#### Kamailio (OpenSER) Only Versions
|
|
|
+
|
|
|
+- 2005-06-14: Kamailio (OpenSER) 0.9.x - release built mainly out of
|
|
|
+ SER 0.9.x
|
|
|
+- 2005-10-25: Kamailio (OpenSER) 1.0.x
|
|
|
+- 2006-07-10: Kamailio (OpenSER) 1.1.x
|
|
|
+- 2007-03-12: Kamailio (OpenSER) 1.2.x
|
|
|
+- 2007-12-13: Kamailio (OpenSER) 1.3.x - [See what was added in
|
|
|
+ 1.3.x](http://www.kamailio.org/dokuwiki/doku.php/features:new-in-1.3.x)
|
|
|
+- 2008-08-07: Kamailio (OpenSER) 1.4.x - [See what was added in
|
|
|
+ 1.4.x](http://www.kamailio.org/dokuwiki/doku.php/features:new-in-1.4.x)
|
|
|
+- 2009-03-02: Kamailio (OpenSER) 1.5.x - [See what was added in
|
|
|
+ 1.5.x](http://www.kamailio.org/dokuwiki/doku.php/features:new-in-1.5.x)
|
|
|
+
|
|
|
+#### Combined Versions
|
|
|
+
|
|
|
+- 2010-01-11: SER and Kamailio (OpenSER) 3.0.x
|
|
|
+ - [See what was added in
|
|
|
+ 3.0.x](http://www.kamailio.org/dokuwiki/doku.php/features:new-in-3.0.x)
|
|
|
+
|
|
|
+#### Next Combined Version
|
|
|
+
|
|
|
+- 3.1.x-devel - scheduled for September 2010
|
|
|
+ - see what is coming with it at:
|
|
|
+ <http://sip-router.org/wiki/features/new-in-devel>
|
|
|
+
|
|
|
+### SER Arguments
|
|
|
+
|
|
|
+The command line arguments of SER changed over the years, but you can
|
|
|
+notice that it has **IPv6** support since 2002 (well, we still wait for
|
|
|
+ISPs...).
|
|
|
+
|
|
|
+Output of **ser -h** and **ser -V** at very young age (recompiled
|
|
|
+today):
|
|
|
+
|
|
|
+ # ser -h
|
|
|
+ version: ser 0.8.7-99 (i386/linux)
|
|
|
+ Usage: ser -l address [-p port] [-l address [-p port]...] [options]
|
|
|
+ Options:
|
|
|
+ -f file Configuration file (default /usr/local/etc/ser/ser.cfg)
|
|
|
+ -p port Listen on the specified port (default: 5060)
|
|
|
+ applies to the last address in -l and to all
|
|
|
+ following that do not have a corespponding -p
|
|
|
+ -l address Listen on the specified address (multiple -l mean
|
|
|
+ listening on more addresses). The default behaviour
|
|
|
+ is to listen on the addresses returned by uname(2)
|
|
|
+
|
|
|
+ -n processes Number of child processes to fork per interface
|
|
|
+ (default: 8)
|
|
|
+
|
|
|
+ -r Use dns to check if is necessary to add a "received="
|
|
|
+ field to a via
|
|
|
+ -R Same as `-r` but use reverse dns;
|
|
|
+ (to use both use `-rR`)
|
|
|
+
|
|
|
+ -v Turn on "via:" host checking when forwarding replies
|
|
|
+ -d Debugging mode (multiple -d increase the level)
|
|
|
+ -D Do not fork into daemon mode
|
|
|
+ -E Log to stderr
|
|
|
+ -V Version number
|
|
|
+ -h This help message
|
|
|
+ -b nr Maximum receive buffer size which will not be exceeded by
|
|
|
+ auto-probing procedure even if OS allows
|
|
|
+ -m nr Size of shared memory allocated in Megabytes
|
|
|
+ -w dir change the working directory to "dir" (default "/")
|
|
|
+ -t dir chroot to "dir"
|
|
|
+ -u uid change uid
|
|
|
+ -g gid change gid
|
|
|
+ -P file create a pid file
|
|
|
+ -i fifo_path create a fifo (usefull for monitoring ser)
|
|
|
+
|
|
|
+
|
|
|
+ # ser -V
|
|
|
+ version: ser 0.8.7-99 (i386/linux)
|
|
|
+ flags: STATS:Off, USE_IPV6, DNS_IP_HACK, SHM_MEM, SHM_MMAP, PKG_MALLOC, F_MALLOC, FAST_LOCK-ADAPTIVE_WAIT
|
|
|
+ ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 3040
|
|
|
+ @(#) $Id: main.c,v 1.119 2002-09-25 19:20:26 andrei Rel $
|
|
|
+ main.c compiled on 17:11:29Sep 3 2010 with gcc 4.4
|
|
|
+
|
|
|
+Output of **ser -h** and **ser -V** nowadays:
|
|
|
+
|
|
|
+ # ser -h
|
|
|
+ version: ser 3.0.99-dev1 (i386/linux) b72876
|
|
|
+ Usage: ser [options]
|
|
|
+ Options:
|
|
|
+ -f file Configuration file (default: /usr/local/etc/ser/ser.cfg)
|
|
|
+ -L path Modules search path (default: /usr/local/lib/ser/modules:/usr/local/lib/ser/modules_s:/usr/local/lib/ser/modules_k)
|
|
|
+ -c Check configuration file for errors
|
|
|
+ -l address Listen on the specified address/interface (multiple -l
|
|
|
+ mean listening on more addresses). The address format is
|
|
|
+ [proto:]addr_lst[:port], where proto=udp|tcp|tls|sctp,
|
|
|
+ addr_lst= addr|(addr, addr_lst) and
|
|
|
+ addr= host|ip_address|interface_name.
|
|
|
+ E.g: -l locahost, -l udp:127.0.0.1:5080, -l eth0:5062,
|
|
|
+ -l "sctp:(eth0)", -l "(eth0, eth1, 127.0.0.1):5065".
|
|
|
+ The default behaviour is to listen on all the interfaces.
|
|
|
+ -n processes Number of child processes to fork per interface
|
|
|
+ (default: 8)
|
|
|
+ -r Use dns to check if is necessary to add a "received="
|
|
|
+ field to a via
|
|
|
+ -R Same as `-r` but use reverse dns;
|
|
|
+ (to use both use `-rR`)
|
|
|
+ -v Turn on "via:" host checking when forwarding replies
|
|
|
+ -d Debugging mode (multiple -d increase the level)
|
|
|
+ -D no 1..do not fork (almost) anyway, 2..do not daemonize creator
|
|
|
+ 3..daemonize (default)
|
|
|
+ -E Log to stderr
|
|
|
+ -T Disable tcp
|
|
|
+ -N Number of tcp child processes (default: equal to `-n')
|
|
|
+ -W type poll method (depending on support in OS, it can be: poll,
|
|
|
+ epoll_lt, epoll_et, sigio_rt, select, kqueue, /dev/poll)
|
|
|
+ -V Version number
|
|
|
+ -h This help message
|
|
|
+ -b nr Maximum receive buffer size which will not be exceeded by
|
|
|
+ auto-probing procedure even if OS allows
|
|
|
+ -m nr Size of shared memory allocated in Megabytes
|
|
|
+ -w dir Change the working directory to "dir" (default: "/")
|
|
|
+ -t dir Chroot to "dir"
|
|
|
+ -u uid Change uid
|
|
|
+ -g gid Change gid
|
|
|
+ -P file Create a pid file
|
|
|
+ -G file Create a pgid file
|
|
|
+ -O nr Script optimization level (debugging option)
|
|
|
+ -a mode Auto aliases mode: enable with yes or on,
|
|
|
+ disable with no or off
|
|
|
+ -A define Add config pre-processor define (e.g., -A WITH_AUTH)
|
|
|
+
|
|
|
+ # ser -V
|
|
|
+ version: ser 3.0.99-dev1 (i386/linux) b72876
|
|
|
+ flags: STATS: Off, USE_IPV6, USE_TCP, USE_TLS, TLS_HOOKS, USE_RAW_SOCKS,
|
|
|
+ DISABLE_NAGLE, USE_MCAST, DNS_IP_HACK, SHM_MEM, SHM_MMAP, PKG_MALLOC, DBG_QM_MALLOC,
|
|
|
+ USE_FUTEX, FAST_LOCK-ADAPTIVE_WAIT, USE_DNS_CACHE, USE_DNS_FAILOVER, USE_NAPTR, USE_DST_BLACKLIST, HAVE_RESOLV_RES
|
|
|
+ ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535, PKG_SIZE 4MB
|
|
|
+ poll method support: poll, epoll_lt, epoll_et, sigio_rt, select.
|
|
|
+ id: b72876
|
|
|
+ compiled on 17:16:21 Sep 3 2010 with gcc 4.4.3
|
|
|
+
|
|
|
+## Source Code Repository Statistics
|
|
|
+
|
|
|
+### Commits
|
|
|
+
|
|
|
+Nine years later since first one, the number of new development commits
|
|
|
+is **14200**:
|
|
|
+
|
|
|
+ git log --pretty=format:"%h%x09%an%x09%ad%x09%s" --reverse | wc -l
|
|
|
+
|
|
|
+ 14200
|
|
|
+
|
|
|
+This number represents **only the commits done in development branch**
|
|
|
+(GIT master branch). Over all, the number of commits is far more, since
|
|
|
+every release had its own branch. However, the number includes the
|
|
|
+commits done during 2005-2008 within Kamailio (OpenSER) project in SVN
|
|
|
+development branch (SVN trunk).
|
|
|
+
|
|
|
+### Lines in repository
|
|
|
+
|
|
|
+The total number of files and lines used in repository (code, comments,
|
|
|
+...):
|
|
|
+
|
|
|
+ Total files: 4701
|
|
|
+ Total lines: 941217
|
|
|
+
|
|
|
+Current lines of code statistics:
|
|
|
+
|
|
|
+ ansic: 392801 (73.38%)
|
|
|
+ xml: 124390 (23.24%)
|
|
|
+ sh: 8965 (1.67%)
|
|
|
+ yacc: 3393 (0.63%)
|
|
|
+ perl: 3314 (0.62%)
|
|
|
+ python: 1372 (0.26%)
|
|
|
+ php: 1047 (0.20%)
|
|
|
+ awk: 43 (0.01%)
|
|
|
+
|
|
|
+### Modules
|
|
|
+
|
|
|
+Current development branch counts over 170 modules (extensions)
|
|
|
+
|
|
|
+ ls modules | wc -w
|
|
|
+ 41
|
|
|
+
|
|
|
+ app_lua cfg_rpc debugger matrix pipelimit tm
|
|
|
+ app_python counters dialplan mediaproxy privacy topoh
|
|
|
+ auth ctl enum mi_rpc sanity utils
|
|
|
+ auth_identity db_berkeley geoip mqueue sl xhttp
|
|
|
+ avpops db_flatstore iptrtpproxy mtree sms xmlops
|
|
|
+ carrierroute db_mysql lcr pdb textopsx xmlrpc
|
|
|
+ cfg_db db_postgres malloc_test peering tls
|
|
|
+
|
|
|
+
|
|
|
+ ls modules_k | wc -w
|
|
|
+ 82
|
|
|
+
|
|
|
+ acc domainpolicy nathelper pua_usrloc sqlops
|
|
|
+ acc_radius drouting nat_traversal pua_xmpp sst
|
|
|
+ alias_db exec osp purple statistics
|
|
|
+ auth_db group path pv textops
|
|
|
+ auth_diameter h350 pdt qos tmx
|
|
|
+ auth_radius htable perl ratelimit uac
|
|
|
+ benchmark imc perlvdb regex uac_redirect
|
|
|
+ call_control jabber permissions registrar uri_db
|
|
|
+ cfgutils kex pike rls userblacklist
|
|
|
+ cpl-c ldap presence rr usrloc
|
|
|
+ db_oracle maxfwd presence_dialoginfo rtimer xcap_client
|
|
|
+ db_text memcached presence_mwi rtpproxy xcap_server
|
|
|
+ db_unixodbc mi_datagram presence_xml seas xlog
|
|
|
+ dialog mi_fifo pua siptrace xmpp
|
|
|
+ dispatcher misc_radius pua_bla siputils
|
|
|
+ diversion mi_xmlrpc pua_dialoginfo snmpstats
|
|
|
+ domain msilo pua_mi speeddial
|
|
|
+
|
|
|
+ ls modules_s | wc -w
|
|
|
+ 51
|
|
|
+
|
|
|
+ acc_db bdb domain maxfwd pike speeddial usrloc
|
|
|
+ acc_radius blst eval msilo prefix_route textops xcap
|
|
|
+ acc_syslog cpl-c exec nathelper presence_b2b timer xlog
|
|
|
+ auth_db db_ops fifo options print uac
|
|
|
+ auth_radius dbtext gflags oracle print_lib unixsock
|
|
|
+ avp dialog jabber osp ratelimit uri
|
|
|
+ avp_db dispatcher ldap pdt registrar uri_db
|
|
|
+ avp_radius diversion mangler permissions rr uri_radius
|
|
|
+
|
|
|
+Version 0.8.8 had 22, some of them no longer available:
|
|
|
+
|
|
|
+ acc cpl ext jabber msilo pike radius_acc registrar sl textops usrloc
|
|
|
+ auth cpl-c exec im maxfwd mysql print radius_auth rr sms tm
|
|
|
+
|
|
|
+### Commit Statistics
|
|
|
+
|
|
|
+Next table presents the most productive time frames in number of commits
|
|
|
+and percentage.
|
|
|
+
|
|
|
+| Description | Value | Commits | Percent |
|
|
|
+|-------------|-------------|---------|---------|
|
|
|
+| Top Hour | 17:00-18:00 | 1259 | 8.87 |
|
|
|
+| Top Day | Thursday | 2775 | 19.54 |
|
|
|
+| Top Month | March | 1727 | 12.16 |
|
|
|
+| Top Year | 2009 | 2267 | 15.96 |
|
|
|
+
|
|
|
+**Here are the screenshots with detailed representation over the time of
|
|
|
+commits:**
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-hour-of-day.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-hour-of-day.png" />
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-hour-of-day-graph.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-hour-of-day-graph.png" />
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-hour-of-week.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-hour-of-week.png" />
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-day-of-week.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-day-of-week.png" />
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-month-of-year.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-month-of-year.png" />
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-by-year.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-by-year.png" />
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-commits-by-year-table.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-commits-by-year-table.png" />
|
|
|
+
|
|
|
+### Ohloh Statistics
|
|
|
+
|
|
|
+Many other statistics can be found at:
|
|
|
+
|
|
|
+- <http://www.ohloh.net/p/sip-router>
|
|
|
+
|
|
|
+For example, estimated cost to develop the project from scratch is over
|
|
|
+**8 millions USD**:
|
|
|
+
|
|
|
+<img src="http://sip-router.org/pub/img/9-years/ser-ohloh-project-cost.png" class="align-center" alt="http://sip-router.org/pub/img/9-years/ser-ohloh-project-cost.png" />
|
|
|
+
|
|
|
+## Config Files
|
|
|
+
|
|
|
+One of most interesting evolutions inside the projects was the default
|
|
|
+configuration file. Started with a completely different format, based on
|
|
|
+regular expression matching, changed quickly in a programmable language,
|
|
|
+format that continues today.
|
|
|
+
|
|
|
+### First Ever Config
|
|
|
+
|
|
|
+If you ever wondered how was the first config file published, then here
|
|
|
+it is:
|
|
|
+
|
|
|
+``` c
|
|
|
+# $Id: sip_router.cfg,v 1.1.1.1 2001/09/03 21:27:11 andrei Exp $
|
|
|
+
|
|
|
+# format:
|
|
|
+# method_re sip_uri_re dest_host
|
|
|
+# (warning: re cannot contain space)
|
|
|
+
|
|
|
+^R.* ^sip:.*@dorian.* ekina.fokus.gmd.de
|
|
|
+^INVITE .* ape # my laptop
|
|
|
+. . 192.168.46.55
|
|
|
+.* .*andrei helios.fokus.gmd.de
|
|
|
+
|
|
|
+
|
|
|
+# end
|
|
|
+```
|
|
|
+
|
|
|
+- reference:
|
|
|
+ <http://cvs.berlios.de/viewvc/ser/sip_router/sip_router.cfg?revision=1.1&pathrev=start>
|
|
|
+
|
|
|
+Probably didn't make it in any production system with this format. The
|
|
|
+config language was completely different than what is today.
|
|
|
+
|
|
|
+### First Release Config
|
|
|
+
|
|
|
+One of first public official releases was 0.8.8 (burned on CD). The
|
|
|
+config language structure was pretty much the same like today.
|
|
|
+
|
|
|
+Here is the config:
|
|
|
+
|
|
|
+``` c
|
|
|
+#
|
|
|
+# $Id: ser.cfg,v 1.10 2002/09/26 10:54:48 janakj Rel $
|
|
|
+#
|
|
|
+# simple quick-start config script
|
|
|
+#
|
|
|
+
|
|
|
+# ----------- global configuration parameters ------------------------
|
|
|
+
|
|
|
+debug=3 # debug level (cmd line: -dddddddddd)
|
|
|
+fork=yes
|
|
|
+log_stderror=no # (cmd line: -E)
|
|
|
+check_via=no # (cmd. line: -v)
|
|
|
+dns=no # (cmd. line: -r)
|
|
|
+rev_dns=no # (cmd. line: -R)
|
|
|
+port=5060
|
|
|
+children=4
|
|
|
+fifo="/tmp/ser_fifo"
|
|
|
+
|
|
|
+# ------------------ module loading ----------------------------------
|
|
|
+
|
|
|
+# Uncomment this if you want to use SQL database
|
|
|
+#loadmodule "/usr/lib/ser/modules/mysql.so"
|
|
|
+
|
|
|
+loadmodule "/usr/lib/ser/modules/sl.so"
|
|
|
+loadmodule "/usr/lib/ser/modules/print.so"
|
|
|
+loadmodule "/usr/lib/ser/modules/tm.so"
|
|
|
+loadmodule "/usr/lib/ser/modules/rr.so"
|
|
|
+loadmodule "/usr/lib/ser/modules/maxfwd.so"
|
|
|
+loadmodule "/usr/lib/ser/modules/usrloc.so"
|
|
|
+loadmodule "/usr/lib/ser/modules/registrar.so"
|
|
|
+
|
|
|
+# Uncomment this if you want digest authentication
|
|
|
+# mysql.so must be loaded !
|
|
|
+#loadmodule "/usr/lib/ser/modules/auth.so"
|
|
|
+
|
|
|
+# ----------------- setting module-specific parameters ---------------
|
|
|
+
|
|
|
+# -- usrloc params --
|
|
|
+
|
|
|
+modparam("usrloc", "db_mode", 0)
|
|
|
+
|
|
|
+# Uncomment this if you want to use SQL database
|
|
|
+# for persistent storage and comment the previous line
|
|
|
+#modparam("usrloc", "db_mode", 2)
|
|
|
+
|
|
|
+# -- auth params --
|
|
|
+# Uncomment if you are using auth module
|
|
|
+#
|
|
|
+#modparam("auth", "secret", "alsdkhglaksdhfkloiwr")
|
|
|
+#modparam("auth", "calculate_ha1", yes)
|
|
|
+#
|
|
|
+# If you set "calculate_ha1" parameter to yes (which true in this config),
|
|
|
+# uncomment also the following parameter)
|
|
|
+#
|
|
|
+#modparam("auth", "password_column", "password")
|
|
|
+
|
|
|
+# ------------------------- request routing logic -------------------
|
|
|
+
|
|
|
+# main routing logic
|
|
|
+
|
|
|
+route{
|
|
|
+
|
|
|
+ # initial sanity checks -- discard local ACKs, messages with
|
|
|
+ # max_forwars==0, or excessively long requests
|
|
|
+ sl_filter_ACK();
|
|
|
+ if (!mf_process_maxfwd_header("10")) {
|
|
|
+ sl_send_reply("483","Too Many Hops");
|
|
|
+ break;
|
|
|
+ };
|
|
|
+ if (len_gt( max_len )) {
|
|
|
+ sl_send_reply("513", "Message too big");
|
|
|
+ break;
|
|
|
+ };
|
|
|
+
|
|
|
+ # Do strict routing if pre-loaded route headers present
|
|
|
+ rewriteFromRoute();
|
|
|
+
|
|
|
+ # if the request is for other domain use UsrLoc
|
|
|
+ # (in case, it does not work, use the following command
|
|
|
+ # with proper names and addresses in it)
|
|
|
+ if (uri==myself) {
|
|
|
+
|
|
|
+ if (method=="REGISTER") {
|
|
|
+
|
|
|
+# Uncomment this if you want to use digest authentication
|
|
|
+# if (!www_authorize("iptel.org", "subscriber")) {
|
|
|
+# www_challenge("iptel.org", "0");
|
|
|
+# break;
|
|
|
+# };
|
|
|
+
|
|
|
+ save("location");
|
|
|
+ break;
|
|
|
+ };
|
|
|
+
|
|
|
+ # native SIP destinations are handled using our USRLOC DB
|
|
|
+ if (!lookup("location")) {
|
|
|
+ sl_send_reply("404", "Not Found");
|
|
|
+ break;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ # forward to current uri now
|
|
|
+ if (!t_relay()) {
|
|
|
+ sl_reply_error();
|
|
|
+ };
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+```
|
|
|
+
|
|
|
+### Default Configs Over Years
|
|
|
+
|
|
|
+Nowadays we build two applications from same source code: **Kamailio**
|
|
|
+and **SER**.
|
|
|
+
|
|
|
+Next sections show the latest versions of default config files. If you
|
|
|
+want to see the evolution for each major version, then follow the links:
|
|
|
+
|
|
|
+- [Default config for SER
|
|
|
+ 0.8.x](http://sip-router.org/pub/configs/ser-0.8.x.cfg)
|
|
|
+- [Default config for SER
|
|
|
+ 0.9.x](http://sip-router.org/pub/configs/ser-0.9.x.cfg)
|
|
|
+- [Default config for SER
|
|
|
+ 2.0.x](http://sip-router.org/pub/configs/ser-2.0.x.cfg)
|
|
|
+- [Default config for SER
|
|
|
+ 2.1.x](http://sip-router.org/pub/configs/ser-2.1.x.cfg)
|
|
|
+- [Default config for SER
|
|
|
+ 3.0.x](http://sip-router.org/pub/configs/ser-3.0.x.cfg)
|
|
|
+- [Default config for SER
|
|
|
+ 3.1.x-devel](http://sip-router.org/pub/configs/ser-3.1.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 0.9.x](http://sip-router.org/pub/configs/kamailio-0.9.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 1.0.x](http://sip-router.org/pub/configs/kamailio-1.0.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 1.1.x](http://sip-router.org/pub/configs/kamailio-1.1.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 1.2.x](http://sip-router.org/pub/configs/kamailio-1.2.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 1.3.x](http://sip-router.org/pub/configs/kamailio-1.3.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 1.4.x](http://sip-router.org/pub/configs/kamailio-1.4.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 1.5.x](http://sip-router.org/pub/configs/kamailio-1.5.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 3.0.x](http://sip-router.org/pub/configs/kamailio-3.0.x.cfg)
|
|
|
+- [Default config for Kamailio (OpenSER)
|
|
|
+ 3.1.x-devel](http://sip-router.org/pub/configs/kamailio-3.1.x.cfg)
|
|
|
+
|
|
|
+### The Configs Today
|
|
|
+
|
|
|
+#### SER Default Config
|
|
|
+
|
|
|
+You can notice in this config the modularity with sub-routes and the
|
|
|
+usage of string names for routes (e.g., route\[REGISTRAR\]), first ever
|
|
|
+introduced by SER in 2007.
|
|
|
+
|
|
|
+``` c
|
|
|
+#
|
|
|
+# $Id$
|
|
|
+#
|
|
|
+
|
|
|
+# First start SER sample config script with:
|
|
|
+# database, accounting, authentication, multi-domain support
|
|
|
+# PSTN GW section, named flags, named routes, global-,
|
|
|
+# domain- and user-preferences with AVPs
|
|
|
+# Several of these features are only here for demonstration purpose
|
|
|
+# what can be achieved with the SER config script language.
|
|
|
+#
|
|
|
+# If you look for a simpler version with a lot less dependencies
|
|
|
+# please refer to the ser-basic.cfg file in your SER distribution.
|
|
|
+
|
|
|
+# To get this config running you need to execute the following commands
|
|
|
+# with the new serctl (the capital word are just place holders)
|
|
|
+# - ser_ctl domain add DOMAINNAME
|
|
|
+# - ser_ctl user add USERNAME@DOMAINNAME -p PASSWORD
|
|
|
+# If you want to have PID header for your user
|
|
|
+# - ser_attr add uid=UID asserted_id="PID"
|
|
|
+# If you want to have gateway support
|
|
|
+# - ser_db add attr_types name=gw_ip rich_type=string raw_type=2 description="The gateway IP for the default ser.cfg" default_flags=33
|
|
|
+# - ser_attr add global gw_ip=GATEWAY-IP
|
|
|
+
|
|
|
+# ----------- global configuration parameters ------------------------
|
|
|
+
|
|
|
+debug=2 # debug level (cmd line: -dddddddddd)
|
|
|
+#memdbg=10 # memory debug log level
|
|
|
+#memlog=10 # memory statistics log level
|
|
|
+#log_facility=LOG_LOCAL0 # sets the facility used for logging (see syslog(3))
|
|
|
+
|
|
|
+/* Uncomment these lines to enter debugging mode
|
|
|
+fork=no
|
|
|
+log_stderror=yes
|
|
|
+*/
|
|
|
+
|
|
|
+check_via=no # (cmd. line: -v)
|
|
|
+dns=no # (cmd. line: -r)
|
|
|
+rev_dns=no # (cmd. line: -R)
|
|
|
+#port=5060
|
|
|
+#children=4
|
|
|
+#user=ser
|
|
|
+#group=ser
|
|
|
+#disable_core=yes #disables core dumping
|
|
|
+#open_fd_limit=1024 # sets the open file descriptors limit
|
|
|
+#mhomed=yes # usefull for multihomed hosts, small performance penalty
|
|
|
+#disable_tcp=yes
|
|
|
+#tcp_accept_aliases=yes # accepts the tcp alias via option (see NEWS)
|
|
|
+enable_tls=yes
|
|
|
+
|
|
|
+#
|
|
|
+
|
|
|
+# ------------------ module loading ----------------------------------
|
|
|
+
|
|
|
+#loadpath "modules:modules_s"
|
|
|
+loadpath "/usr/lib/ser/modules:/usr/lib/ser/modules_s"
|
|
|
+
|
|
|
+# load a SQL database for authentication, domains, user AVPs etc.
|
|
|
+loadmodule "db_mysql"
|
|
|
+
|
|
|
+loadmodule "sl"
|
|
|
+loadmodule "tm"
|
|
|
+loadmodule "rr"
|
|
|
+loadmodule "maxfwd"
|
|
|
+loadmodule "usrloc"
|
|
|
+loadmodule "registrar"
|
|
|
+loadmodule "xlog"
|
|
|
+loadmodule "textops"
|
|
|
+loadmodule "ctl"
|
|
|
+loadmodule "cfg_rpc"
|
|
|
+loadmodule "auth"
|
|
|
+loadmodule "auth_db"
|
|
|
+loadmodule "gflags"
|
|
|
+loadmodule "domain"
|
|
|
+loadmodule "uri_db"
|
|
|
+loadmodule "avp"
|
|
|
+loadmodule "avp_db"
|
|
|
+loadmodule "acc_db"
|
|
|
+loadmodule "xmlrpc"
|
|
|
+#loadmodule "tls"
|
|
|
+
|
|
|
+# ----------------- setting script FLAGS -----------------------------
|
|
|
+flags
|
|
|
+ FLAG_ACC : 1, # include message in accounting
|
|
|
+ FLAG_FAILUREROUTE : 2; # we are operating from a failure route
|
|
|
+
|
|
|
+avpflags
|
|
|
+ dialog_cookie; # handled by rr module
|
|
|
+
|
|
|
+# ----------------- setting module-specific parameters ---------------
|
|
|
+
|
|
|
+# specify the path to you database here
|
|
|
+modparam("acc_db|auth_db|avp_db|domain|gflags|usrloc|uri_db", "db_url", "mysql://ser:[email protected]/ser")
|
|
|
+
|
|
|
+# -- usrloc params --
|
|
|
+
|
|
|
+# as we use the database anyway we will use it for usrloc as well
|
|
|
+modparam("usrloc", "db_mode", 1)
|
|
|
+
|
|
|
+# -- auth params --
|
|
|
+modparam("auth_db", "calculate_ha1", yes)
|
|
|
+modparam("auth_db", "plain_password_column", "password")
|
|
|
+
|
|
|
+# -- rr params --
|
|
|
+# add value to ;lr param to make some broken UAs happy
|
|
|
+modparam("rr", "enable_full_lr", 1)
|
|
|
+#
|
|
|
+# limit the length of the AVP cookie to only necessary ones
|
|
|
+modparam("rr", "cookie_filter", "(account)")
|
|
|
+#
|
|
|
+# you probably do not want that someone can simply read and change
|
|
|
+# the AVP cookie in your Routes, thus should really change this
|
|
|
+# secret value below
|
|
|
+modparam("rr", "cookie_secret", "MyRRAVPcookiesecret")
|
|
|
+
|
|
|
+# -- gflags params --
|
|
|
+# load the global AVPs
|
|
|
+modparam("gflags", "load_global_attrs", 1)
|
|
|
+
|
|
|
+# -- domain params --
|
|
|
+# load the domain AVPs
|
|
|
+modparam("domain", "load_domain_attrs", 1)
|
|
|
+
|
|
|
+# -- ctl params --
|
|
|
+# by default ctl listens on unixs:/tmp/ser_ctl if no other address is
|
|
|
+# specified in modparams; this is also the default for sercmd
|
|
|
+modparam("ctl", "binrpc", "unixs:/tmp/ser_ctl")
|
|
|
+# listen on the "standard" fifo for backward compatibility
|
|
|
+modparam("ctl", "fifo", "fifo:/tmp/ser_fifo")
|
|
|
+# listen on tcp, localhost
|
|
|
+#modparam("ctl", "binrpc", "tcp:localhost:2046")
|
|
|
+
|
|
|
+# -- acc_db params --
|
|
|
+# failed transactions (=negative responses) should be logged to
|
|
|
+modparam("acc_db", "failed_transactions", 1)
|
|
|
+
|
|
|
+# comment the next line if you dont want to have accounting to DB
|
|
|
+modparam("acc_db", "log_flag", "FLAG_ACC")
|
|
|
+
|
|
|
+# -- tm params --
|
|
|
+# uncomment the following line if you want to avoid that each new reply
|
|
|
+# restarts the resend timer (see INBOUND route below)
|
|
|
+#modparam("tm", "restart_fr_on_each_reply", "0")
|
|
|
+
|
|
|
+# -- xmlrpc params --
|
|
|
+# using a sub-route from the module is a lot safer then relying on the
|
|
|
+# request method to distinguish HTTP from SIP
|
|
|
+modparam("xmlrpc", "route", "RPC");
|
|
|
+
|
|
|
+# ------------------------- request routing logic -------------------
|
|
|
+
|
|
|
+# main routing logic
|
|
|
+
|
|
|
+route{
|
|
|
+ # if you have a PSTN gateway just un-comment the follwoing line and
|
|
|
+ # specify the IP address of it to route calls to it
|
|
|
+ #$gw_ip = "1.2.3.4"
|
|
|
+
|
|
|
+ # first do some initial sanity checks
|
|
|
+ route(INIT);
|
|
|
+
|
|
|
+ # bypass the rest of the script for CANCELs if possible
|
|
|
+ route(CATCH_CANCEL);
|
|
|
+
|
|
|
+ # check if the request is routed via Route header or
|
|
|
+ # needs a Record-Route header
|
|
|
+ route(RR);
|
|
|
+
|
|
|
+ # check if the request belongs to our proxy
|
|
|
+ route(DOMAIN);
|
|
|
+
|
|
|
+ # handle REGISTER requests
|
|
|
+ route(REGISTRAR);
|
|
|
+
|
|
|
+ # from here on we want to know you is calling
|
|
|
+ route(AUTHENTICATION);
|
|
|
+
|
|
|
+ # check if we should be outbound proxy for a local user
|
|
|
+ route(OUTBOUND);
|
|
|
+
|
|
|
+ # check if the request is for a local user
|
|
|
+ route(INBOUND);
|
|
|
+
|
|
|
+ # here you could for example try to do an ENUM lookup before
|
|
|
+ # the call gets routed to the PSTN
|
|
|
+ #route(ENUM);
|
|
|
+
|
|
|
+ # lets see if someone wants to call a PSTN number
|
|
|
+ route(PSTN);
|
|
|
+
|
|
|
+ # nothing matched, reject it finally
|
|
|
+ sl_reply("404", "No route matched");
|
|
|
+}
|
|
|
+
|
|
|
+route[FORWARD]
|
|
|
+{
|
|
|
+ # here you could decide wether this call needs a RTP relay or not
|
|
|
+
|
|
|
+ # if this is called from the failure route we need to open a new branch
|
|
|
+ if (isflagset(FLAG_FAILUREROUTE)) {
|
|
|
+ append_branch();
|
|
|
+ }
|
|
|
+
|
|
|
+ # if this is an initial INVITE (without a To-tag) we might try another
|
|
|
+ # (forwarding or voicemail) target after receiving an error
|
|
|
+ if (method=="INVITE" && strempty(@to.tag)) {
|
|
|
+ t_on_failure("FAILURE_ROUTE");
|
|
|
+ }
|
|
|
+
|
|
|
+ # send it out now; use stateful forwarding as it works reliably
|
|
|
+ # even for UDP2TCP
|
|
|
+ if (!t_relay()) {
|
|
|
+ sl_reply_error();
|
|
|
+ }
|
|
|
+ drop;
|
|
|
+}
|
|
|
+
|
|
|
+route[INIT]
|
|
|
+{
|
|
|
+ # initial sanity checks -- messages with
|
|
|
+ # max_forwards==0, or excessively long requests
|
|
|
+ if (!mf_process_maxfwd_header("10")) {
|
|
|
+ sl_reply("483","Too Many Hops");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msg:len >= 4096 ) {
|
|
|
+ sl_reply("513", "Message too big");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ # you could add some NAT detection here for example
|
|
|
+
|
|
|
+ # or you cuold call here some of the check from the sanity module
|
|
|
+
|
|
|
+ # lets account all initial INVITEs
|
|
|
+ # further in-dialog requests are accounted by a RR cookie (see below)
|
|
|
+ if (method=="INVITE" && strempty(@to.tag)) {
|
|
|
+ setflag(FLAG_ACC);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[RPC]
|
|
|
+{
|
|
|
+ # allow XMLRPC from localhost
|
|
|
+ if ((method=="POST" || method=="GET") &&
|
|
|
+ src_ip==127.0.0.1) {
|
|
|
+
|
|
|
+ if (msg:len >= 8192) {
|
|
|
+ sl_reply("513", "Request to big");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ # lets see if a module wants to answer this
|
|
|
+ dispatch_rpc();
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[RR]
|
|
|
+{
|
|
|
+ # subsequent messages withing a dialog should take the
|
|
|
+ # path determined by record-routing
|
|
|
+ if (loose_route()) {
|
|
|
+ # mark routing logic in request
|
|
|
+ append_hf("P-hint: rr-enforced\r\n");
|
|
|
+
|
|
|
+ # if the Route contained the accounting AVP cookie we
|
|
|
+ # set the accounting flag for the acc_db module.
|
|
|
+ # this is more for demonstration purpose as this could
|
|
|
+ # also be solved without RR cookies.
|
|
|
+ # Note: this means all in-dialog request will show up in the
|
|
|
+ # accounting tables, so prepare your accounting software for this ;-)
|
|
|
+ if ($account == "yes") {
|
|
|
+ setflag(FLAG_ACC);
|
|
|
+ }
|
|
|
+
|
|
|
+ # for broken devices which overwrite their Route's with each
|
|
|
+ # (not present) RR from within dialog requests it is better
|
|
|
+ # to repeat the RRing
|
|
|
+ # and if we call rr after loose_route the AVP cookies are restored
|
|
|
+ # automatically :)
|
|
|
+ record_route();
|
|
|
+
|
|
|
+ route(FORWARD);
|
|
|
+ } else if (!method=="REGISTER") {
|
|
|
+ # we record-route all messages -- to make sure that
|
|
|
+ # subsequent messages will go through our proxy; that's
|
|
|
+ # particularly good if upstream and downstream entities
|
|
|
+ # use different transport protocol
|
|
|
+
|
|
|
+ # if the inital INVITE got the ACC flag store this in
|
|
|
+ # an RR AVP cookie. this is more for demonstration purpose
|
|
|
+ if (isflagset(FLAG_ACC)) {
|
|
|
+ $account = "yes";
|
|
|
+ setavpflag($account, "dialog_cookie");
|
|
|
+ }
|
|
|
+
|
|
|
+ record_route();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[DOMAIN]
|
|
|
+{
|
|
|
+ # check if the caller is from a local domain
|
|
|
+ lookup_domain("$fd", "@from.uri.host");
|
|
|
+
|
|
|
+ # check if the callee is at a local domain
|
|
|
+ lookup_domain("$td", "@ruri.host");
|
|
|
+
|
|
|
+ # we dont know the domain of the caller and also not
|
|
|
+ # the domain of the callee -> somone uses our proxy as
|
|
|
+ # a relay
|
|
|
+ if (strempty($t.did) && strempty($f.did)) {
|
|
|
+ sl_reply("403", "Relaying Forbidden");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[REGISTRAR]
|
|
|
+{
|
|
|
+ # if the request is a REGISTER lets take care of it
|
|
|
+ if (method=="REGISTER") {
|
|
|
+ # check if the REGISTER if for one of our local domains
|
|
|
+ if (strempty($t.did)) {
|
|
|
+ sl_reply("403", "Register forwarding forbidden");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ # we want only authenticated users to be registered
|
|
|
+ if (!www_authenticate("$fd.digest_realm", "credentials")) {
|
|
|
+ if ($? == -2) {
|
|
|
+ sl_reply("500", "Internal Server Error");
|
|
|
+ } else if ($? == -3) {
|
|
|
+ sl_reply("400", "Bad Request");
|
|
|
+ } else {
|
|
|
+ if ($digest_challenge != "") {
|
|
|
+ append_to_reply("%$digest_challenge");
|
|
|
+ }
|
|
|
+ sl_reply("401", "Unauthorized");
|
|
|
+ }
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ # check if the authenticated user is the same as the target user
|
|
|
+ if (!lookup_user("$tu.uid", "@to.uri")) {
|
|
|
+ sl_reply("404", "Unknown user in To");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($f.uid != $t.uid) {
|
|
|
+ sl_reply("403", "Authentication and To-Header mismatch");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ # check if the authenticated user is the same as the request originator
|
|
|
+ # you may uncomment it if you care, what uri is in From header
|
|
|
+ #if (!lookup_user("$fu.uid", "@from.uri")) {
|
|
|
+ # sl_reply("404", "Unknown user in From");
|
|
|
+ # drop;
|
|
|
+ #}
|
|
|
+ #if ($fu.uid != $tu.uid) {
|
|
|
+ # sl_reply("403", "Authentication and From-Header mismatch");
|
|
|
+ # drop;
|
|
|
+ #}
|
|
|
+
|
|
|
+ # everything is fine so lets store the binding
|
|
|
+ if (!save_contacts("location")) {
|
|
|
+ sl_reply("400", "Invalid REGISTER Request");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[AUTHENTICATION]
|
|
|
+{
|
|
|
+ if (method=="CANCEL" || method=="ACK") {
|
|
|
+ # you are not allowed to challenge these methods
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ # requests from non-local to local domains should be permitted
|
|
|
+ # remove this if you want a walled garden
|
|
|
+ if (strempty($f.did)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ # as gateways are usually not able to authenticate for their
|
|
|
+ # requests you will have trust them base on some other information
|
|
|
+ # like the source IP address. WARNING: if at all this is only safe
|
|
|
+ # in a local network!!!
|
|
|
+ #if (src_ip==a.b.c.d) {
|
|
|
+ # break;
|
|
|
+ #}
|
|
|
+
|
|
|
+ if (!proxy_authenticate("$fd.digest_realm", "credentials")) {
|
|
|
+ if ($? == -2) {
|
|
|
+ sl_reply("500", "Internal Server Error");
|
|
|
+ } else if ($? == -3) {
|
|
|
+ sl_reply("400", "Bad Request");
|
|
|
+ } else {
|
|
|
+ if ($digest_challenge != "") {
|
|
|
+ append_to_reply("%$digest_challenge");
|
|
|
+ }
|
|
|
+ sl_reply("407", "Proxy Authentication Required");
|
|
|
+ }
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+
|
|
|
+ # check if the UID from the authentication meets the From header
|
|
|
+ $authuid = $uid;
|
|
|
+ if (!lookup_user("$fu.uid", "@from.uri")) {
|
|
|
+ del_attr("$uid");
|
|
|
+ }
|
|
|
+ if ($fu.uid != $fr.authuid) {
|
|
|
+ sl_reply("403", "Fake Identity");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+ # load the user AVPs (preferences) of the caller, e.g. for RPID header
|
|
|
+ load_attrs("$fu", "$f.uid");
|
|
|
+}
|
|
|
+
|
|
|
+route[OUTBOUND]
|
|
|
+{
|
|
|
+ # if a local user calls to a foreign domain we play outbound proxy for him
|
|
|
+ # comment this out if you want a walled garden
|
|
|
+ if ($f.did != "" && $t.did == "") {
|
|
|
+ append_hf("P-hint: outbound\r\n");
|
|
|
+ route(FORWARD);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[INBOUND]
|
|
|
+{
|
|
|
+ # lets see if know the callee
|
|
|
+ if (lookup_user("$tu.uid", "@ruri")) {
|
|
|
+
|
|
|
+ # load the preferences of the callee to have his timeout values loaded
|
|
|
+ load_attrs("$tu", "$t.uid");
|
|
|
+
|
|
|
+ # if you want to know if the callee username was an alias
|
|
|
+ # check it like this
|
|
|
+ #if (strempty($tu.uri_canonical)) {
|
|
|
+ # if the alias URI has different AVPs/preferences
|
|
|
+ # you can load them into the URI track like this
|
|
|
+ #load_attrs("$tr", "@ruri");
|
|
|
+ #}
|
|
|
+
|
|
|
+ # check for call forwarding of the callee
|
|
|
+ # Note: the forwarding target has to be full routable URI
|
|
|
+ # in this example
|
|
|
+ if ($tu.fwd_always_target != "") {
|
|
|
+ attr2uri("$tu.fwd_always_target");
|
|
|
+ route(FORWARD);
|
|
|
+ }
|
|
|
+
|
|
|
+ # native SIP destinations are handled using our USRLOC DB
|
|
|
+ if (lookup_contacts("location")) {
|
|
|
+ append_hf("P-hint: usrloc applied\r\n");
|
|
|
+
|
|
|
+ # we set the TM module timers according to the prefences
|
|
|
+ # of the callee (avoid too long ringing of his phones)
|
|
|
+ # Note1: timer values have to be in ms now!
|
|
|
+ # Note2: this makes even more sense if you switch to a voicemail
|
|
|
+ # from the FAILURE_ROUTE below
|
|
|
+ if ($t.fr_inv_timer != 0) {
|
|
|
+ if ($t.fr_timer != 0) {
|
|
|
+ t_set_fr("$t.fr_inv_timer", "$t.fr_timer");
|
|
|
+ } else {
|
|
|
+ t_set_fr("$t.fr_inv_timer");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ route(FORWARD);
|
|
|
+ } else {
|
|
|
+ sl_reply("480", "User temporarily not available");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[PSTN]
|
|
|
+{
|
|
|
+ # Only if the AVP 'gw_ip' is set and the request URI contains
|
|
|
+ # only a number we consider sending this to the PSTN GW.
|
|
|
+ # Only users from a local domain are permitted to make calls.
|
|
|
+ # Additionally you might want to check the acl AVP to verify
|
|
|
+ # that the user is allowed to make such expensives calls.
|
|
|
+ if ($f.did != "" && $gw_ip != "" &&
|
|
|
+ uri=~"sips?:\+?[0-9]{3,18}@.*") {
|
|
|
+ # probably you need to convert the number in the request
|
|
|
+ # URI according to the requirements of your gateway here
|
|
|
+
|
|
|
+ # if an AVP 'asserted_id' is set we insert an RPID header
|
|
|
+ if ($asserted_id != "") {
|
|
|
+ xlset_attr("$rpidheader", "<sip:%$asserted_id@%@ruri.host>;screen=yes");
|
|
|
+ replace_attr_hf("Remote-Party-ID", "$rpidheader");
|
|
|
+ }
|
|
|
+
|
|
|
+ # just replace the domain part of the RURI with the
|
|
|
+ # value from the AVP and send it out
|
|
|
+ attr2uri("$gw_ip", "domain");
|
|
|
+ route(FORWARD);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+route[CATCH_CANCEL] {
|
|
|
+ # check whether there is a corresponding INVITE to the CANCEL,
|
|
|
+ # and bypass the rest of the script if possible
|
|
|
+
|
|
|
+ if (method == CANCEL) {
|
|
|
+ if (!t_relay_cancel()) { # implicit drop if the INVITE was found
|
|
|
+
|
|
|
+ # INVITE was found but some error occurred
|
|
|
+ sl_reply("500", "Internal Server Error");
|
|
|
+ drop;
|
|
|
+ }
|
|
|
+ # bad luck, no corresponding INVITE was found,
|
|
|
+ # we have to continue with the script
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+failure_route[FAILURE_ROUTE]
|
|
|
+{
|
|
|
+ # mark for the other routes that we are operating from here on from a
|
|
|
+ # failure route
|
|
|
+ setflag(FLAG_FAILUREROUTE);
|
|
|
+
|
|
|
+ if (t_check_status("486|600")) {
|
|
|
+ # if we received a busy and a busy target is set, forward it there
|
|
|
+ # Note: again the forwarding target has to be a routeable URI
|
|
|
+ if ($tu.fwd_busy_target != "") {
|
|
|
+ attr2uri("$tu.fwd_busy_target");
|
|
|
+ route(FORWARD);
|
|
|
+ }
|
|
|
+ # alternatively you could forward the request to SEMS/voicemail here
|
|
|
+ }
|
|
|
+ else if (t_check_status("408|480")) {
|
|
|
+ # if we received no answer and the noanswer target is set,
|
|
|
+ # forward it there
|
|
|
+ # Note: again the target has to be a routeable URI
|
|
|
+ if ($tu.fwd_noanswer_target != "") {
|
|
|
+ attr2uri("$tu.fwd_noanswer_target");
|
|
|
+ route(FORWARD);
|
|
|
+ }
|
|
|
+ # alternatively you could forward the request to SEMS/voicemail here
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### Kamailio Default Config
|
|
|
+
|
|
|
+You can notice here the usage of **config defines** (#!define XYZ,
|
|
|
+#!ifdef XYZ, ...) which makes very easy to enable/disable features as
|
|
|
+well as defining values for tokens that are replaced later in config
|
|
|
+(e.g., DBURL). The config provides advanced features such as NAT
|
|
|
+traversal with RTPProxy or presence server.
|
|
|
+
|
|
|
+``` c
|
|
|
+#!KAMAILIO
|
|
|
+#
|
|
|
+# Kamailio (OpenSER) SIP Server v3.1 - default configuration script
|
|
|
+# - web: http://www.kamailio.org
|
|
|
+# - git: http://sip-router.org
|
|
|
+#
|
|
|
+# Direct your questions about this file to: <[email protected]>
|
|
|
+#
|
|
|
+# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
|
|
|
+# for an explanation of possible statements, functions and parameters.
|
|
|
+#
|
|
|
+# Several features can be enabled using '#!define WITH_FEATURE' directives:
|
|
|
+#
|
|
|
+# *** To run in debug mode:
|
|
|
+# - define WITH_DEBUG
|
|
|
+#
|
|
|
+# *** To enable mysql:
|
|
|
+# - define WITH_MYSQL
|
|
|
+#
|
|
|
+# *** To enable authentication execute:
|
|
|
+# - enable mysql
|
|
|
+# - define WITH_AUTH
|
|
|
+# - add users using 'kamctl'
|
|
|
+#
|
|
|
+# *** To enable IP authentication execute:
|
|
|
+# - enable mysql
|
|
|
+# - enable authentication
|
|
|
+# - define WITH_IPAUTH
|
|
|
+# - add IP addresses with group id '1' to 'address' table
|
|
|
+#
|
|
|
+# *** To enable persistent user location execute:
|
|
|
+# - enable mysql
|
|
|
+# - define WITH_USRLOCDB
|
|
|
+#
|
|
|
+# *** To enable presence server execute:
|
|
|
+# - enable mysql
|
|
|
+# - define WITH_PRESENCE
|
|
|
+#
|
|
|
+# *** To enable nat traversal execute:
|
|
|
+# - define WITH_NAT
|
|
|
+# - install RTPProxy: http://www.rtpproxy.org
|
|
|
+# - start RTPProxy:
|
|
|
+# rtpproxy -l _your_public_ip_ -s udp:localhost:7722
|
|
|
+#
|
|
|
+# *** To enable PSTN gateway routing execute:
|
|
|
+# - define WITH_PSTN
|
|
|
+# - set the value of pstn.gw_ip
|
|
|
+# - check route[PSTN] for regexp routing condition
|
|
|
+#
|
|
|
+# *** To enhance accounting execute:
|
|
|
+# - enable mysql
|
|
|
+# - define WITH_ACCDB
|
|
|
+# - add following columns to database
|
|
|
+#!ifdef ACCDB_COMMENT
|
|
|
+ ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
|
|
|
+ ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
|
|
|
+#!endif
|
|
|
+
|
|
|
+# *** Value defines - IDs used later in config
|
|
|
+#!ifdef WITH_MYSQL
|
|
|
+# - database URL - used to connect to database server by modules such
|
|
|
+# as: auth_db, acc, usrloc, a.s.o.
|
|
|
+#!define DBURL "mysql://openser:openserrw@localhost/openser"
|
|
|
+#!endif
|
|
|
+
|
|
|
+####### Global Parameters #########
|
|
|
+
|
|
|
+#!ifdef WITH_DEBUG
|
|
|
+debug=4
|
|
|
+log_stderror=yes
|
|
|
+#!else
|
|
|
+debug=2
|
|
|
+log_stderror=no
|
|
|
+#!endif
|
|
|
+
|
|
|
+memdbg=5
|
|
|
+memlog=5
|
|
|
+
|
|
|
+log_facility=LOG_LOCAL0
|
|
|
+
|
|
|
+fork=yes
|
|
|
+children=4
|
|
|
+
|
|
|
+/* uncomment the next line to disable TCP (default on) */
|
|
|
+#disable_tcp=yes
|
|
|
+
|
|
|
+/* uncomment the next line to disable the auto discovery of local aliases
|
|
|
+ based on reverse DNS on IPs (default on) */
|
|
|
+#auto_aliases=no
|
|
|
+
|
|
|
+/* add local domain aliases */
|
|
|
+#alias="sip.mydomain.com"
|
|
|
+
|
|
|
+port=5060
|
|
|
+
|
|
|
+/* uncomment and configure the following line if you want Kamailio to
|
|
|
+ bind on a specific interface/port/proto (default bind on all available) */
|
|
|
+#listen=udp:10.0.0.10:5060
|
|
|
+
|
|
|
+
|
|
|
+####### Custom Parameters #########
|
|
|
+
|
|
|
+# These parameters can be modified runtime via RPC interface
|
|
|
+# - see the documentation of 'cfg_rpc' module.
|
|
|
+#
|
|
|
+# Format: group.id = value 'desc' description
|
|
|
+# Access: $sel(cfg_get.group.id) or @cfg_get.group.id
|
|
|
+#
|
|
|
+
|
|
|
+#!ifdef WITH_PSTN
|
|
|
+# PSTN GW Routing
|
|
|
+#
|
|
|
+# - pstn.gw_ip: valid IP or hostname as string value, example:
|
|
|
+# pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address"
|
|
|
+#
|
|
|
+# - by default is empty to avoid misrouting
|
|
|
+pstn.gw_ip = "" desc "PSTN GW Address"
|
|
|
+#!endif
|
|
|
+
|
|
|
+
|
|
|
+####### Modules Section ########
|
|
|
+
|
|
|
+#set module path
|
|
|
+mpath="/usr/local/lib/kamailio/modules_k/:/usr/local/lib/kamailio/modules/"
|
|
|
+
|
|
|
+/* uncomment next line for MySQL DB support */
|
|
|
+#!ifdef WITH_MYSQL
|
|
|
+loadmodule "db_mysql.so"
|
|
|
+#!endif
|
|
|
+loadmodule "mi_fifo.so"
|
|
|
+loadmodule "kex.so"
|
|
|
+loadmodule "tm.so"
|
|
|
+loadmodule "tmx.so"
|
|
|
+loadmodule "sl.so"
|
|
|
+loadmodule "rr.so"
|
|
|
+loadmodule "pv.so"
|
|
|
+loadmodule "maxfwd.so"
|
|
|
+loadmodule "usrloc.so"
|
|
|
+loadmodule "registrar.so"
|
|
|
+loadmodule "textops.so"
|
|
|
+loadmodule "uri_db.so"
|
|
|
+loadmodule "siputils.so"
|
|
|
+loadmodule "xlog.so"
|
|
|
+loadmodule "sanity.so"
|
|
|
+loadmodule "ctl.so"
|
|
|
+loadmodule "mi_rpc.so"
|
|
|
+loadmodule "acc.so"
|
|
|
+#!ifdef WITH_AUTH
|
|
|
+loadmodule "auth.so"
|
|
|
+loadmodule "auth_db.so"
|
|
|
+#!ifdef WITH_IPAUTH
|
|
|
+loadmodule "permissions.so"
|
|
|
+#!endif
|
|
|
+#!endif
|
|
|
+/* uncomment next line for aliases support
|
|
|
+ NOTE: a DB (like db_mysql) module must be also loaded */
|
|
|
+#loadmodule "alias_db.so"
|
|
|
+/* uncomment next line for multi-domain support
|
|
|
+ NOTE: a DB (like db_mysql) module must be also loaded
|
|
|
+ NOTE: be sure and enable multi-domain support in all used modules
|
|
|
+ (see "multi-module params" section ) */
|
|
|
+#loadmodule "domain.so"
|
|
|
+#!ifdef WITH_PRESENCE
|
|
|
+loadmodule "presence.so"
|
|
|
+loadmodule "presence_xml.so"
|
|
|
+#!endif
|
|
|
+
|
|
|
+#!ifdef WITH_NAT
|
|
|
+loadmodule "nathelper.so"
|
|
|
+loadmodule "rtpproxy.so"
|
|
|
+#!endif
|
|
|
+
|
|
|
+# ----------------- setting module-specific parameters ---------------
|
|
|
+
|
|
|
+
|
|
|
+# ----- mi_fifo params -----
|
|
|
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
|
|
|
+
|
|
|
+
|
|
|
+# ----- tm params -----
|
|
|
+# auto-discard branches from previous serial forking leg
|
|
|
+modparam("tm", "failure_reply_mode", 3)
|
|
|
+# default retransmission timeout: 30sec
|
|
|
+modparam("tm", "fr_timer", 30000)
|
|
|
+# default invite retransmission timeout after 1xx: 120sec
|
|
|
+modparam("tm", "fr_inv_timer", 120000)
|
|
|
+
|
|
|
+# ----- rr params -----
|
|
|
+# add value to ;lr param to cope with most of the UAs
|
|
|
+modparam("rr", "enable_full_lr", 1)
|
|
|
+# do not append from tag to the RR (no need for this script)
|
|
|
+modparam("rr", "append_fromtag", 0)
|
|
|
+
|
|
|
+
|
|
|
+# ----- rr params -----
|
|
|
+modparam("registrar", "method_filtering", 1)
|
|
|
+/* uncomment the next line to disable parallel forking via location */
|
|
|
+# modparam("registrar", "append_branches", 0)
|
|
|
+/* uncomment the next line not to allow more than 10 contacts per AOR */
|
|
|
+#modparam("registrar", "max_contacts", 10)
|
|
|
+
|
|
|
+
|
|
|
+# ----- uri_db params -----
|
|
|
+/* by default we disable the DB support in the module as we do not need it
|
|
|
+ in this configuration */
|
|
|
+modparam("uri_db", "use_uri_table", 0)
|
|
|
+modparam("uri_db", "db_url", "")
|
|
|
+
|
|
|
+
|
|
|
+# ----- acc params -----
|
|
|
+/* what sepcial events should be accounted ? */
|
|
|
+modparam("acc", "early_media", 1)
|
|
|
+modparam("acc", "report_ack", 1)
|
|
|
+modparam("acc", "report_cancels", 1)
|
|
|
+/* by default ww do not adjust the direct of the sequential requests.
|
|
|
+ if you enable this parameter, be sure the enable "append_fromtag"
|
|
|
+ in "rr" module */
|
|
|
+modparam("acc", "detect_direction", 0)
|
|
|
+/* account triggers (flags) */
|
|
|
+modparam("acc", "failed_transaction_flag", 3)
|
|
|
+modparam("acc", "log_flag", 1)
|
|
|
+modparam("acc", "log_missed_flag", 2)
|
|
|
+modparam("acc", "log_extra",
|
|
|
+ "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
|
|
|
+/* enhanced DB accounting */
|
|
|
+#!ifdef WITH_ACCDB
|
|
|
+modparam("acc", "db_flag", 1)
|
|
|
+modparam("acc", "db_missed_flag", 2)
|
|
|
+modparam("acc", "db_url", DBURL)
|
|
|
+modparam("acc", "db_extra",
|
|
|
+ "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
|
|
|
+#!endif
|
|
|
+
|
|
|
+# ----- usrloc params -----
|
|
|
+/* enable DB persistency for location entries */
|
|
|
+#!ifdef WITH_USRLOCDB
|
|
|
+modparam("usrloc", "db_mode", 2)
|
|
|
+modparam("usrloc", "db_url", DBURL)
|
|
|
+#!endif
|
|
|
+
|
|
|
+# ----- auth_db params -----
|
|
|
+/* enable the DB based authentication */
|
|
|
+#!ifdef WITH_AUTH
|
|
|
+modparam("auth_db", "calculate_ha1", yes)
|
|
|
+modparam("auth_db", "password_column", "password")
|
|
|
+modparam("auth_db", "db_url", DBURL)
|
|
|
+modparam("auth_db", "load_credentials", "")
|
|
|
+
|
|
|
+#!ifdef WITH_IPAUTH
|
|
|
+modparam("permissions", "db_url", DBURL)
|
|
|
+modparam("permissions", "db_mode", 1)
|
|
|
+#!endif
|
|
|
+
|
|
|
+#!endif
|
|
|
+
|
|
|
+# ----- alias_db params -----
|
|
|
+/* uncomment the following lines if you want to enable the DB based
|
|
|
+ aliases */
|
|
|
+#modparam("alias_db", "db_url", DBURL)
|
|
|
+
|
|
|
+
|
|
|
+# ----- domain params -----
|
|
|
+/* uncomment the following lines to enable multi-domain detection
|
|
|
+ support */
|
|
|
+#modparam("domain", "db_url", DBURL)
|
|
|
+#modparam("domain", "db_mode", 1) # Use caching
|
|
|
+
|
|
|
+
|
|
|
+# ----- multi-module params -----
|
|
|
+/* uncomment the following line if you want to enable multi-domain support
|
|
|
+ in the modules (dafault off) */
|
|
|
+#modparam("alias_db|auth_db|usrloc|uri_db", "use_domain", 1)
|
|
|
+
|
|
|
+
|
|
|
+# ----- presence params -----
|
|
|
+/* enable presence server support */
|
|
|
+#!ifdef WITH_PRESENCE
|
|
|
+modparam("presence|presence_xml", "db_url", DBURL)
|
|
|
+modparam("presence_xml", "force_active", 1)
|
|
|
+modparam("presence", "server_address", "sip:10.0.0.10:5060")
|
|
|
+#!endif
|
|
|
+
|
|
|
+#!ifdef WITH_NAT
|
|
|
+# ----- rtpproxy -----
|
|
|
+modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")
|
|
|
+# ----- nathelper -----
|
|
|
+modparam("nathelper", "natping_interval", 30)
|
|
|
+modparam("nathelper", "ping_nated_only", 1)
|
|
|
+modparam("nathelper", "sipping_bflag", 7)
|
|
|
+modparam("nathelper", "sipping_from", "sip:[email protected]")
|
|
|
+modparam("registrar|nathelper", "received_avp", "$avp(i:80)")
|
|
|
+modparam("usrloc", "nat_bflag", 6)
|
|
|
+#!endif
|
|
|
+
|
|
|
+####### Routing Logic ########
|
|
|
+
|
|
|
+
|
|
|
+# main request routing logic
|
|
|
+
|
|
|
+route {
|
|
|
+
|
|
|
+ # per request initial checks
|
|
|
+ route(REQINIT);
|
|
|
+
|
|
|
+ # NAT detection
|
|
|
+ route(NAT);
|
|
|
+
|
|
|
+ # handle requests within SIP dialogs
|
|
|
+ route(WITHINDLG);
|
|
|
+
|
|
|
+ ### only initial requests (no To tag)
|
|
|
+
|
|
|
+ # CANCEL processing
|
|
|
+ if (is_method("CANCEL"))
|
|
|
+ {
|
|
|
+ if (t_check_trans())
|
|
|
+ t_relay();
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ t_check_trans();
|
|
|
+
|
|
|
+ # authentication
|
|
|
+ route(AUTH);
|
|
|
+
|
|
|
+ # record routing for dialog forming requests (in case they are routed)
|
|
|
+ # - remove preloaded route headers
|
|
|
+ remove_hf("Route");
|
|
|
+ if (is_method("INVITE|SUBSCRIBE"))
|
|
|
+ record_route();
|
|
|
+
|
|
|
+ # account only INVITEs
|
|
|
+ if (is_method("INVITE"))
|
|
|
+ {
|
|
|
+ setflag(1); # do accounting
|
|
|
+ }
|
|
|
+
|
|
|
+ # dispatch requests to foreign domains
|
|
|
+ route(SIPOUT);
|
|
|
+
|
|
|
+ ### requests for my local domains
|
|
|
+
|
|
|
+ # handle presence related requests
|
|
|
+ route(PRESENCE);
|
|
|
+
|
|
|
+ # handle registrations
|
|
|
+ route(REGISTRAR);
|
|
|
+
|
|
|
+ if ($rU==$null)
|
|
|
+ {
|
|
|
+ # request with no Username in RURI
|
|
|
+ sl_send_reply("484","Address Incomplete");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ # dispatch destinations to PSTN
|
|
|
+ route(PSTN);
|
|
|
+
|
|
|
+ # user location service
|
|
|
+ route(LOCATION);
|
|
|
+
|
|
|
+ route(RELAY);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+route[RELAY] {
|
|
|
+#!ifdef WITH_NAT
|
|
|
+ if (check_route_param("nat=yes")) {
|
|
|
+ setbflag("6");
|
|
|
+ }
|
|
|
+ if (isflagset(5) || isbflagset("6")) {
|
|
|
+ route(RTPPROXY);
|
|
|
+ }
|
|
|
+#!endif
|
|
|
+
|
|
|
+ /* example how to enable some additional event routes */
|
|
|
+ if (is_method("INVITE")) {
|
|
|
+ #t_on_branch("BRANCH_ONE");
|
|
|
+ t_on_reply("REPLY_ONE");
|
|
|
+ t_on_failure("FAIL_ONE");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!t_relay()) {
|
|
|
+ sl_reply_error();
|
|
|
+ }
|
|
|
+ exit;
|
|
|
+}
|
|
|
+
|
|
|
+# Per SIP request initial checks
|
|
|
+route[REQINIT] {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Handle requests within SIP dialogs
|
|
|
+route[WITHINDLG] {
|
|
|
+ if (has_totag()) {
|
|
|
+ # sequential request withing a dialog should
|
|
|
+ # take the path determined by record-routing
|
|
|
+ if (loose_route()) {
|
|
|
+ if (is_method("BYE")) {
|
|
|
+ setflag(1); # do accounting ...
|
|
|
+ setflag(3); # ... even if the transaction fails
|
|
|
+ }
|
|
|
+ route(RELAY);
|
|
|
+ } else {
|
|
|
+ if (is_method("SUBSCRIBE") && uri == myself) {
|
|
|
+ # in-dialog subscribe requests
|
|
|
+ route(PRESENCE);
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ if ( is_method("ACK") ) {
|
|
|
+ if ( t_check_trans() ) {
|
|
|
+ # non loose-route, but stateful ACK; must be an ACK after a 487 or e.g. 404 from upstream server
|
|
|
+ t_relay();
|
|
|
+ exit;
|
|
|
+ } else {
|
|
|
+ # ACK without matching transaction ... ignore and discard.\n");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sl_send_reply("404","Not here");
|
|
|
+ }
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Handle SIP registrations
|
|
|
+route[REGISTRAR] {
|
|
|
+ if (is_method("REGISTER"))
|
|
|
+ {
|
|
|
+ if(isflagset(5))
|
|
|
+ {
|
|
|
+ setbflag("6");
|
|
|
+ # uncomment next line to do SIP NAT pinging
|
|
|
+ ## setbflag("7");
|
|
|
+ }
|
|
|
+ if (!save("location"))
|
|
|
+ sl_reply_error();
|
|
|
+
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# USER location service
|
|
|
+route[LOCATION] {
|
|
|
+ # apply DB based aliases (uncomment to enable)
|
|
|
+ ##alias_db_lookup("dbaliases");
|
|
|
+
|
|
|
+ if (!lookup("location")) {
|
|
|
+ switch ($rc) {
|
|
|
+ case -1:
|
|
|
+ case -3:
|
|
|
+ t_newtran();
|
|
|
+ t_reply("404", "Not Found");
|
|
|
+ exit;
|
|
|
+ case -2:
|
|
|
+ sl_send_reply("405", "Method Not Allowed");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # when routing via usrloc, log the missed calls also
|
|
|
+ if (is_method("INVITE"))
|
|
|
+ {
|
|
|
+ setflag(2);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Presence server route
|
|
|
+route[PRESENCE] {
|
|
|
+ if(!is_method("PUBLISH|SUBSCRIBE"))
|
|
|
+ return;
|
|
|
+
|
|
|
+#!ifdef WITH_PRESENCE
|
|
|
+ if (!t_newtran())
|
|
|
+ {
|
|
|
+ sl_reply_error();
|
|
|
+ exit;
|
|
|
+ };
|
|
|
+
|
|
|
+ if(is_method("PUBLISH"))
|
|
|
+ {
|
|
|
+ handle_publish();
|
|
|
+ t_release();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if( is_method("SUBSCRIBE"))
|
|
|
+ {
|
|
|
+ handle_subscribe();
|
|
|
+ t_release();
|
|
|
+ }
|
|
|
+ exit;
|
|
|
+#!endif
|
|
|
+
|
|
|
+ # if presence enabled, this part will not be executed
|
|
|
+ if (is_method("PUBLISH") || $rU==$null)
|
|
|
+ {
|
|
|
+ sl_send_reply("404", "Not here");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+# Authentication route
|
|
|
+route[AUTH] {
|
|
|
+#!ifdef WITH_AUTH
|
|
|
+ if (is_method("REGISTER"))
|
|
|
+ {
|
|
|
+ # authenticate the REGISTER requests (uncomment to enable auth)
|
|
|
+ if (!www_authorize("$td", "subscriber"))
|
|
|
+ {
|
|
|
+ www_challenge("$td", "0");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($au!=$tU)
|
|
|
+ {
|
|
|
+ sl_send_reply("403","Forbidden auth ID");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+#!ifdef WITH_IPAUTH
|
|
|
+ if(allow_source_address())
|
|
|
+ {
|
|
|
+ # source IP allowed
|
|
|
+ return;
|
|
|
+ }
|
|
|
+#!endif
|
|
|
+
|
|
|
+ # authenticate if from local subscriber
|
|
|
+ if (from_uri==myself)
|
|
|
+ {
|
|
|
+ if (!proxy_authorize("$fd", "subscriber")) {
|
|
|
+ proxy_challenge("$fd", "0");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ if (is_method("PUBLISH"))
|
|
|
+ {
|
|
|
+ if ($au!=$tU) {
|
|
|
+ sl_send_reply("403","Forbidden auth ID");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if ($au!=$fU) {
|
|
|
+ sl_send_reply("403","Forbidden auth ID");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ consume_credentials();
|
|
|
+ # caller authenticated
|
|
|
+ } else {
|
|
|
+ # caller is not local subscriber, then check if it calls
|
|
|
+ # a local destination, otherwise deny, not an open relay here
|
|
|
+ if (!uri==myself)
|
|
|
+ {
|
|
|
+ sl_send_reply("403","Not relaying");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#!endif
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+# Caller NAT detection route
|
|
|
+route[NAT] {
|
|
|
+#!ifdef WITH_NAT
|
|
|
+ force_rport();
|
|
|
+ if (nat_uac_test("19")) {
|
|
|
+ if (method=="REGISTER") {
|
|
|
+ fix_nated_register();
|
|
|
+ } else {
|
|
|
+ fix_nated_contact();
|
|
|
+ }
|
|
|
+ setflag(5);
|
|
|
+ }
|
|
|
+#!endif
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+# RTPProxy control
|
|
|
+route[RTPPROXY] {
|
|
|
+#!ifdef WITH_NAT
|
|
|
+ if (is_method("BYE")) {
|
|
|
+ unforce_rtp_proxy();
|
|
|
+ } else if (is_method("INVITE")){
|
|
|
+ force_rtp_proxy();
|
|
|
+ }
|
|
|
+ if (!has_totag()) add_rr_param(";nat=yes");
|
|
|
+#!endif
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+# Routing to foreign domains
|
|
|
+route[SIPOUT] {
|
|
|
+ if (!uri==myself)
|
|
|
+ /* replace with following line if multi-domain support is used */
|
|
|
+ ##if (!is_uri_host_local())
|
|
|
+ {
|
|
|
+ append_hf("P-hint: outbound\r\n");
|
|
|
+ route(RELAY);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# PSTN GW routing
|
|
|
+route[PSTN] {
|
|
|
+#!ifdef WITH_PSTN
|
|
|
+ # check if PSTN GW IP is defined
|
|
|
+ if (strempty($sel(cfg_get.pstn.gw_ip))) {
|
|
|
+ xlog("SCRIPT: PSTN rotuing enabled but pstn.gw_ip not defined\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ # route to PSTN dialed numbers starting with '+' or '00'
|
|
|
+ # (international format)
|
|
|
+ # - update the condition to match your dialing rules for PSTN routing
|
|
|
+ if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
|
|
|
+ return;
|
|
|
+
|
|
|
+ # only local users allowed to call
|
|
|
+ if(from_uri!=myself) {
|
|
|
+ sl_send_reply("403", "Not Allowed");
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);
|
|
|
+
|
|
|
+ route(RELAY);
|
|
|
+ exit;
|
|
|
+#!endif
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+# Sample branch router
|
|
|
+branch_route[BRANCH_ONE] {
|
|
|
+ xdbg("new branch at $ru\n");
|
|
|
+}
|
|
|
+
|
|
|
+# Sample onreply route
|
|
|
+onreply_route[REPLY_ONE] {
|
|
|
+ xdbg("incoming reply\n");
|
|
|
+#!ifdef WITH_NAT
|
|
|
+ if ((isflagset(5) || isbflagset("6")) && status=~"(183)|(2[0-9][0-9])") {
|
|
|
+ force_rtp_proxy();
|
|
|
+ }
|
|
|
+ if (isbflagset("6")) {
|
|
|
+ fix_nated_contact();
|
|
|
+ }
|
|
|
+#!endif
|
|
|
+}
|
|
|
+
|
|
|
+# Sample failure route
|
|
|
+failure_route[FAIL_ONE] {
|
|
|
+#!ifdef WITH_NAT
|
|
|
+ if (is_method("INVITE")
|
|
|
+ && (isbflagset("6") || isflagset(5))) {
|
|
|
+ unforce_rtp_proxy();
|
|
|
+ }
|
|
|
+#!endif
|
|
|
+
|
|
|
+ if (t_is_canceled()) {
|
|
|
+ exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ # uncomment the following lines if you want to block client
|
|
|
+ # redirect based on 3xx replies.
|
|
|
+ ##if (t_check_status("3[0-9][0-9]")) {
|
|
|
+ ##t_reply("404","Not found");
|
|
|
+ ## exit;
|
|
|
+ ##}
|
|
|
+
|
|
|
+ # uncomment the following lines if you want to redirect the failed
|
|
|
+ # calls to a different new destination
|
|
|
+ ##if (t_check_status("486|408")) {
|
|
|
+ ## sethostport("192.168.2.100:5060");
|
|
|
+ ## append_branch();
|
|
|
+ ## # do not set the missed call flag again
|
|
|
+ ## t_relay();
|
|
|
+ ##}
|
|
|
+}
|
|
|
+
|
|
|
+```
|