|
@@ -0,0 +1,1060 @@
|
|
|
|
+#
|
|
|
|
+# $Id$
|
|
|
|
+#
|
|
|
|
+#
|
|
|
|
+# Applicability of this Configuration File
|
|
|
|
+# ----------------------------------------
|
|
|
|
+#
|
|
|
|
+# This is default SER script as used for example at the iptel.org
|
|
|
|
+# SIP service; it can deal with NATs, terminate calls to a PSTN
|
|
|
|
+# gateway, and it implements a couple of basic signaling features
|
|
|
|
+# (few types of call forwarding). In this scenario you may have
|
|
|
|
+# multiple SIP proxies sharing one database for accessing provisioned
|
|
|
|
+# data, which are maintained for example using serweb. The proxy
|
|
|
|
+# servers also share write-access to user location database (and
|
|
|
|
+# keeps a full cache of all usrloc entries synchronized using
|
|
|
|
+# multicast).
|
|
|
|
+#
|
|
|
|
+# If you look for a simpler version with a lot less dependencies
|
|
|
|
+# please refer to the ser-basic.cfg file in your SER distribution.
|
|
|
|
+#
|
|
|
|
+# Requirements:
|
|
|
|
+# ---------------
|
|
|
|
+# running DB, running RTP proxy, one public IP address
|
|
|
|
+# for SIP service, one private IP address for administrative purposes;
|
|
|
|
+# optional: IP address of a PSTN gateway
|
|
|
|
+#
|
|
|
|
+# HOWTOs:
|
|
|
|
+# ---------
|
|
|
|
+# 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
|
|
|
|
+# Alternatively you can use serweb to set all the values above.
|
|
|
|
+#
|
|
|
|
+# Users with permission to call PSTN using this script must have
|
|
|
|
+# the $gw_acl attribute set properly, and shall have $asserted_id
|
|
|
|
+# set to indicate their caller-id for calls to PSTN. For inbound
|
|
|
|
+# calls from PSTN, additional aliases may be also set.
|
|
|
|
+#
|
|
|
|
+# Warning:
|
|
|
|
+# -----------
|
|
|
|
+# Note: if this file is installed on Debian from package 'ser-oob' then some options
|
|
|
|
+# in this configuration file may be set by post-installation script, according to values
|
|
|
|
+# entered by user at installation time in debconf configuration.
|
|
|
|
+# These values are then applied automatically to this file each time the 'ser-oob' package
|
|
|
|
+# is upgraded or reconfigured by calling 'dpkg-reconfigure ser-oob'.
|
|
|
|
+# The parts of this configuration file that may be altered by debconf are enclosed
|
|
|
|
+# between '#DEBCONF-something-START' and '#DEBCONF-something-END' comment marks. Please
|
|
|
|
+# don't remove them.
|
|
|
|
+#
|
|
|
|
+#
|
|
|
|
+# TODO (Future possible improvements):
|
|
|
|
+# ---------------------------------------
|
|
|
|
+# * protocol tuning
|
|
|
|
+# - session-timer (port existing textops-based scripts)
|
|
|
|
+# - AVP-based diversion for call-forwarding (as opposed to specialized module)
|
|
|
|
+# - add Date header in 200s to REGISTERs (to be packaged with NTP!)
|
|
|
|
+# * more security:
|
|
|
|
+# - pike/rate-limit
|
|
|
|
+# - identity
|
|
|
|
+# - TLS
|
|
|
|
+# - permissions
|
|
|
|
+# * refined DB use (e.g., flatstore for acc)
|
|
|
|
+# * miscellanous:
|
|
|
|
+# - dialog module for monitoring purposes
|
|
|
|
+# - more extensive logging using xlog (controlled by gflags/gAVPs)
|
|
|
|
+# * leveraging 2.1 features:
|
|
|
|
+# - removal of private IP address (it takes a multicast-specific
|
|
|
|
+# command which will allow OS to determine source IP address)
|
|
|
|
+# - timer route:
|
|
|
|
+# * don't use exec (it takes domain.reload as script command)
|
|
|
|
+# * compare last-stored timestamp with current timestamp (it takes
|
|
|
|
+# assignment of gAVPs)
|
|
|
|
+# * check multicast REGISTERs for their TTL (this is a simple and
|
|
|
|
+# effective security check to prevent remote multicast messages
|
|
|
|
+# to damage our traffic)
|
|
|
|
+# - numerous fine-tuning parameters which are only available in 2.1
|
|
|
|
+# (mlock_pages, dns_try_naptr, etc.)
|
|
|
|
+# - better support for preloaded routes with domain name
|
|
|
|
+#
|
|
|
|
+# Security considerations:
|
|
|
|
+# ------------------------
|
|
|
|
+# the script has been tested against security leaks, but it comes
|
|
|
|
+# under terms of GPL "as is" without any warranties; better check
|
|
|
|
+# yourself that:
|
|
|
|
+# - IP based authentication of PSTN gateway and multicast REGISTERs
|
|
|
|
+# is compliant to your network setup and security policy
|
|
|
|
+# - mutliple gateway IPs can't be provisioned as security checks
|
|
|
|
+# are applied only to one
|
|
|
|
+#
|
|
|
|
+# Licensing
|
|
|
|
+# ----------
|
|
|
|
+# Copyright (C) 2005-2007 iptelorg GmbH
|
|
|
|
+# This file is part of SER, a free SIP server. It is available under the
|
|
|
|
+# terms of the GNU General Public License.
|
|
|
|
+# Numerous folks have contributed to this file, including but not limited
|
|
|
|
+# to Andrei, Jan, Jiri, Michal, Miklos, Nils
|
|
|
|
+#
|
|
|
|
+#
|
|
|
|
+# .... that's it, enough of yadiyada, here the real config begin!
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# ----------- global configuration parameters ------------------------
|
|
|
|
+
|
|
|
|
+#debug=3 # debug level (cmd line: -ddd)
|
|
|
|
+#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_files_limit=20480 # sets the open file descriptors limit
|
|
|
|
+#mhomed=yes # usefull for multihomed hosts, small performance penalty
|
|
|
|
+# be conservative about enabling TCP -- it can degrade performance a lot
|
|
|
|
+disable_tcp=no
|
|
|
|
+#tcp_accept_aliases=yes # accepts the tcp alias via option (see NEWS)
|
|
|
|
+# ignore user=phone in request-URIs -- otherwise these URIs would be
|
|
|
|
+# interpreted as equivalent to TEL URIs, and their lookup would fail
|
|
|
|
+# in URI database
|
|
|
|
+phone2tel=no
|
|
|
|
+
|
|
|
|
+reply_to_via=no
|
|
|
|
+# public IP address
|
|
|
|
+#DEBCONF-LISTEN-START
|
|
|
|
+listen=1.2.3.4
|
|
|
|
+#DEBCONF-LISTEN-END
|
|
|
|
+# sip.mcast.net for REGISTER replication
|
|
|
|
+listen=224.0.1.75
|
|
|
|
+# administrative interface -- needed for example for multicast source
|
|
|
|
+# or XML-RPC
|
|
|
|
+#DEBCONF-LISTEN_ADMIN-START
|
|
|
|
+listen=udp:192.168.1.1
|
|
|
|
+#DEBCONF-LISTEN_ADMIN-END
|
|
|
|
+
|
|
|
|
+# ------------------- misc params -------------------------------------
|
|
|
|
+# ser 2.1 only
|
|
|
|
+# mlock_pages=yes
|
|
|
|
+# shm_force_alloc=yes
|
|
|
|
+# real_time=7
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# ------------------- DNS params -------------------------------------
|
|
|
|
+# (see doc/dns.txt for more details)
|
|
|
|
+# minimum timeouts
|
|
|
|
+dns_retr_time=1
|
|
|
|
+dns_retr_no=1
|
|
|
|
+dns_servers_no=1
|
|
|
|
+dns_use_search_list=no
|
|
|
|
+dns_try_ipv6=no
|
|
|
|
+# dns cache & failover
|
|
|
|
+use_dns_cache=on
|
|
|
|
+use_dns_failover=on
|
|
|
|
+# dns_cache_flags=0
|
|
|
|
+dns_cache_negative_ttl=300
|
|
|
|
+dns_cache_min_ttl=60
|
|
|
|
+dns_cache_max_ttl=86400 # 1 day
|
|
|
|
+dns_cache_mem=2048 # 2 MB
|
|
|
|
+dns_cache_gc_interval=60 # garbage collection every minute
|
|
|
|
+# ser 2.1 specific options
|
|
|
|
+# dns_try_naptr=yes
|
|
|
|
+# dns_srv_lb=yes # srv based load balancing
|
|
|
|
+# dns_udp_pref=3 # prefer udp (when resolving naptr record)
|
|
|
|
+# dns_tcp_pref=2 # if no udp availbale accept tcp (for naptr)
|
|
|
|
+# dns_tls_pref=-1 # ignore / don't accept tls (for naptr)
|
|
|
|
+# dns_cache_delete_nonexpired=no
|
|
|
|
+
|
|
|
|
+# ------------------- blacklist params -------------------------------------
|
|
|
|
+# (see doc/dst_blacklist.txt for more details)
|
|
|
|
+
|
|
|
|
+use_dst_blacklist=on
|
|
|
|
+dst_blacklist_mem=1024 # 1 MB
|
|
|
|
+dst_blacklist_expire=300 # blacklist default time
|
|
|
|
+dst_blacklist_gc_interval=150 # 2.5 min
|
|
|
|
+# for ser 2.1 to the above add tm blst_503* parameters and/or use the
|
|
|
|
+# blst module (see NEWS)
|
|
|
|
+
|
|
|
|
+# ------------------- tcp params -------------------------------------
|
|
|
|
+# (see NEWS for more details)
|
|
|
|
+tcp_connection_lifetime=3600
|
|
|
|
+#tcp_max_connections=10240 # default is 2048
|
|
|
|
+tcp_connect_timeout=1
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# ------------------ module loading ----------------------------------
|
|
|
|
+
|
|
|
|
+# load a SQL database for authentication, domains, user AVPs etc.
|
|
|
|
+loadmodule "/usr/lib/ser/modules/mysql.so"
|
|
|
|
+
|
|
|
|
+loadmodule "/usr/lib/ser/modules/sl.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"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/xlog.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/textops.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/ctl.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/auth.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/auth_db.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/gflags.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/domain.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/uri_db.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/avp.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/avp_db.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/acc_db.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/xmlrpc.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/options.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/sanity.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/nathelper.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/uri.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/speeddial.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/timer.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/db_ops.so"
|
|
|
|
+loadmodule "/usr/lib/ser/modules/exec.so"
|
|
|
|
+
|
|
|
|
+# ----------------- setting script FLAGS -----------------------------
|
|
|
|
+flags
|
|
|
|
+ FLAG_ACC : 1, # this request will be recorded by ACC
|
|
|
|
+ FLAG_FAILUREROUTE : 2, # we are operating from the failure route
|
|
|
|
+ FLAG_NAT : 3, # the UAC is behind a NAT
|
|
|
|
+ FLAG_PEER_REPLICATE : 4, # the request came from a replication peer node
|
|
|
|
+ FLAG_TOTAG : 5,
|
|
|
|
+ FLAG_PSTN_ALLOWED : 6, # the user is allowed to use the PSTN
|
|
|
|
+ FLAG_DONT_RM_CRED : 7, # do not remove the credentials
|
|
|
|
+ FLAG_AUTH_OK : 8, # authentication suceeded
|
|
|
|
+ FLAG_SERWEB_RSVD1 : 9, # bit reserved for use with serweb
|
|
|
|
+ FLAG_SERWEB_RSVD2 :10; # bit reserved for use with serweb
|
|
|
|
+
|
|
|
|
+avpflags
|
|
|
|
+ dialog_cookie; # handled by rr module
|
|
|
|
+
|
|
|
|
+# ----------------- setting module-specific parameters ---------------
|
|
|
|
+
|
|
|
|
+# specify the path to you database here
|
|
|
|
+#DEBCONF-DBURL-START
|
|
|
|
+modparam("speeddial|auth_db|usrloc|acc_db|domain|uri_db|gflags|avp_db|db_ops", "db_url", "mysql://ser:[email protected]/ser")
|
|
|
|
+#DEBCONF-DBURL-END
|
|
|
|
+
|
|
|
|
+# -- usrloc params --
|
|
|
|
+
|
|
|
|
+# db_mode 0 -- memory cached, 1 -- write thru, 2 -- delayed write
|
|
|
|
+modparam("usrloc", "db_mode", 2)
|
|
|
|
+# don't delete expired records from database on a per-contact basis -- that
|
|
|
|
+# results in bulky DB operations and can lead to synchronization issues
|
|
|
|
+# in server farm when for a time a server doesn't obtain re-reregistrations
|
|
|
|
+modparam("usrloc","db_skip_delete",1)
|
|
|
|
+
|
|
|
|
+# -- registrar params
|
|
|
|
+# maximum expires time, forces users to re-register every 10 min.
|
|
|
|
+modparam("registrar", "max_expires", 600)
|
|
|
|
+# minimum expires time, even if tried, clients cannot get registered
|
|
|
|
+# for a shorter time than this
|
|
|
|
+modparam("registrar", "min_expires", 240)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# identify natted contacts using a flag
|
|
|
|
+modparam("registrar", "load_nat_flag", "FLAG_NAT")
|
|
|
|
+modparam("registrar", "save_nat_flag", "FLAG_NAT")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# -- auth params --
|
|
|
|
+#modparam("auth_db", "calculate_ha1", yes)
|
|
|
|
+#modparam("auth_db", "plain_password_column", "password")
|
|
|
|
+# minimize replay-attack window
|
|
|
|
+modparam("auth", "nonce_expire", 10)
|
|
|
|
+# deal with client's who can't do qop properly
|
|
|
|
+modparam("auth", "qop", "")
|
|
|
|
+#DEBCONF-AUTHSECRET-START
|
|
|
|
+modparam("auth", "secret", "aqwedrftredswqwddcft")
|
|
|
|
+#DEBCONF-AUTHSECRET-END
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# -- 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|uac_nat)")
|
|
|
|
+#
|
|
|
|
+# 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", "sgsatewgdbsnmpoiewh")
|
|
|
|
+
|
|
|
|
+# ftag may be used to easily determine if a BYE is coming from
|
|
|
|
+# caller or callee, but here we prefer shorter messages
|
|
|
|
+modparam("rr", "append_fromtag", 0)
|
|
|
|
+
|
|
|
|
+# -- gflags params --
|
|
|
|
+# load the global AVPs
|
|
|
|
+# here we load global AVPs such as PSTN GW IP address; this can
|
|
|
|
+# be manipulated using ser_attr
|
|
|
|
+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 accouting to DB
|
|
|
|
+modparam("acc_db", "log_flag", "FLAG_ACC")
|
|
|
|
+
|
|
|
|
+# if you would like to customize your CDRs, do it here....
|
|
|
|
+#modparam("acc_db", "attrs", "$f.sop_billing_category,$f.isPrepaidCustomer,$f.sop_cf_orig_uid")
|
|
|
|
+
|
|
|
|
+# -- 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");
|
|
|
|
+
|
|
|
|
+# -- nathelper params --
|
|
|
|
+# RTP-Proxy
|
|
|
|
+#DEBCONF-RTTPPROXY-START
|
|
|
|
+modparam("nathelper", "rtpproxy_sock", "udp:192.168.1.1:22222")
|
|
|
|
+#DEBCONF-RTTPPROXY-END
|
|
|
|
+# TCP keepalives as simple as CRLF
|
|
|
|
+# modparam("nathelper", "tcpping_crlf", 0)
|
|
|
|
+#DEBCONF-NATPING_INTERVAL-START
|
|
|
|
+modparam("nathelper", "natping_interval", 15)
|
|
|
|
+#DEBCONF-NATPING_INTERVAL-END
|
|
|
|
+modparam("nathelper", "ping_nated_only", 1 )
|
|
|
|
+# if this option is not set, simple 4-bytes ping is sent
|
|
|
|
+modparam("nathelper", "natping_method", "OPTIONS" )
|
|
|
|
+#temporary statefull natping test (only in future versions)
|
|
|
|
+#modparam("nathelper", "natping_stateful", 1)
|
|
|
|
+
|
|
|
|
+# -- exec module
|
|
|
|
+modparam("exec", "time_to_kill", 200);
|
|
|
|
+modparam("exec", "setvars", 0);
|
|
|
|
+
|
|
|
|
+# -- timer module
|
|
|
|
+modparam("timer", "declare_timer", "ON_1MIN_TIMER,60000,slow,enable");
|
|
|
|
+
|
|
|
|
+# ------------------------- 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"
|
|
|
|
+ # alternatively (even better, set it as global persistent parameter
|
|
|
|
+ # using serweb or ser_attrs); also if using a PSTN GW per-subscriber
|
|
|
|
+ # options must ($gw_acl) or may (asserted_id) be set to enable calls
|
|
|
|
+ # to PSTN; if email-like addresses are used, having a URI alias for
|
|
|
|
+ # processing incoming pstn-2-ip requests may be useful too
|
|
|
|
+ # important: the script is assuming one global pstn-gw for all domains!
|
|
|
|
+ # failure to allow gw_ip to be a domain-specic attribute would result
|
|
|
|
+ # in security gaps (onsend_route checks only for one gateway)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # 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);
|
|
|
|
+
|
|
|
|
+ # answer OPTIONS to our system
|
|
|
|
+ route(OPTIONS_REPLY);
|
|
|
|
+
|
|
|
|
+ # handle REGISTER requests
|
|
|
|
+ route(REGISTRAR);
|
|
|
|
+
|
|
|
|
+ # from here on we want to know who is calling
|
|
|
|
+ route(AUTHENTICATION);
|
|
|
|
+
|
|
|
|
+ # we are finished with all the precaution work -- let's
|
|
|
|
+ # try to locate the callee; the first route that matches
|
|
|
|
+ # "wins", if none matches, SER will send a 404
|
|
|
|
+
|
|
|
|
+ # check if we should be outbound proxy for a local user
|
|
|
|
+ route(OUTBOUND);
|
|
|
|
+
|
|
|
|
+ # redirect in case user dialed a speed dial entry
|
|
|
|
+ route(SPEEDDIAL);
|
|
|
|
+
|
|
|
|
+ # place various site-specific routes here
|
|
|
|
+ route(SITE_SPECIFIC);
|
|
|
|
+
|
|
|
|
+ # 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);
|
|
|
|
+
|
|
|
|
+ # last resort: if none of the previous route has found
|
|
|
|
+ # the recepient, try PSTN
|
|
|
|
+ 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" && [email protected]) {
|
|
|
|
+ t_on_failure("FAILURE_ROUTE");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ t_on_reply("REPLY_ROUTE");
|
|
|
|
+
|
|
|
|
+ route(RTPPROXY);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # remove credentials to keep requests shorter
|
|
|
|
+ if (isflagset(FLAG_AUTH_OK) && !isflagset(FLAG_DONT_RM_CRED) ) {
|
|
|
|
+ consume_credentials();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # 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 >= max_len ) {
|
|
|
|
+ if (msg:len >= 4096 ) {
|
|
|
|
+ sl_reply("513", "Message too big");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # this flag is need for the onsend route
|
|
|
|
+ if (@to.tag) {
|
|
|
|
+ setflag(FLAG_TOTAG);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # check if the UAC is natted and fix the message appropiatly
|
|
|
|
+ route(NAT_DETECTION);
|
|
|
|
+
|
|
|
|
+ # lets account all initial INVITEs
|
|
|
|
+ # further in-dialog requests are accounted by a RR cookie (see below)
|
|
|
|
+ if (method=="INVITE" && [email protected]) {
|
|
|
|
+ setflag(FLAG_ACC);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ($replicate==1) { # if global flag enabled, carry on replication
|
|
|
|
+ setflag(FLAG_PEER_REPLICATE);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+route[OPTIONS_REPLY]
|
|
|
|
+{
|
|
|
|
+ # if it an OPTIONS without a username in the RURI but one
|
|
|
|
+ # our IPs answer directly statelessly
|
|
|
|
+ if (method=="OPTIONS" && @ruri.user=="" && (uri==myself||$t.did)) {
|
|
|
|
+ options_reply();
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+route[NAT_DETECTION]
|
|
|
|
+{
|
|
|
|
+ # lots of UAs do not send rport in there Via header
|
|
|
|
+ # so we put it there to remember where to send the reply to
|
|
|
|
+ force_rport();
|
|
|
|
+ force_tcp_alias();
|
|
|
|
+
|
|
|
|
+ # check if the request contains hints for a NATed UAC
|
|
|
|
+ # also try to rewrite contacts using maddr; using maddr is a real
|
|
|
|
+ # dubious technique and we better replace such with transport address;
|
|
|
|
+ # downside: it fails for clients fronted by another server, in which
|
|
|
|
+ # case a valid contact we dislike because of maddr will be substituted
|
|
|
|
+ # inapproprietely; (e.g., WM from other domains will fail); if worried
|
|
|
|
+ # about that, remove tests for maddr and recompile SER using HONOR_MADDR
|
|
|
|
+ # also note that possibly rewriting contacts may lead to client
|
|
|
|
+ # renying subseqent requests to them because they don't recognized
|
|
|
|
+ # fixed contacts as their own; we haven't encountered such case
|
|
|
|
+ # yet; a possible solution a la usrloc would be to store the original
|
|
|
|
+ # information as a contact parameter and restore it on its way back
|
|
|
|
+ if (nat_uac_test("19") || (@hf_value["contact"] && @contact.uri.params.maddr) ) {
|
|
|
|
+ setflag(FLAG_NAT);
|
|
|
|
+ $uac_nat=1;
|
|
|
|
+ if (method=="REGISTER") {
|
|
|
|
+ # prepare the Contact so that the registrar module saves the
|
|
|
|
+ # source as well
|
|
|
|
+ fix_nated_register();
|
|
|
|
+ } else {
|
|
|
|
+ # overwrite the Contact to allow proper in-dialog routing
|
|
|
|
+ fix_nated_contact();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+route[RTPPROXY]
|
|
|
|
+{
|
|
|
|
+ # if no NAT is involved we dont have to do here anything
|
|
|
|
+ if (!isflagset(FLAG_NAT)) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # if the message terminates a dialog turn RTP proxy off
|
|
|
|
+ if ((method=="BYE" || method=="CANCEL") ||
|
|
|
|
+ isflagset(FLAG_FAILUREROUTE)) {
|
|
|
|
+ unforce_rtp_proxy();
|
|
|
|
+ append_hf("P-RTP-Proxy: UNFORCED\r\n");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # turn the RTP proxy on for INVITEs
|
|
|
|
+ if (method=="INVITE") {
|
|
|
|
+ force_rtp_proxy('r');
|
|
|
|
+ append_hf("P-RTP-Proxy: YES\r\n");
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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
|
|
|
|
+ # accouting tables, so prepare your accounting software for this ;-)
|
|
|
|
+ if ($account == "yes") {
|
|
|
|
+ setflag(FLAG_ACC);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # restore the NAT flag is is present
|
|
|
|
+ if ($uac_nat == 1) {
|
|
|
|
+ setflag(FLAG_NAT);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # 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 :)
|
|
|
|
+ # note that here we forward before authentication check is executed;
|
|
|
|
+ # generally we only authenticate dialog-initiating requests; some
|
|
|
|
+ # in-dialog requests can't be authenticated at all, see the
|
|
|
|
+ # call-forwarding example in route[DOMAIN]
|
|
|
|
+ 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; however we apply this check only to dialog
|
|
|
|
+ # initiating requests (no totag) -- in some cases such
|
|
|
|
+ # as call-forwarding, subsequent requests may not include
|
|
|
|
+ # served domain neither as origination nor destination
|
|
|
|
+ # (a@A calls b@B that forwards to c@C; BYE is formed as
|
|
|
|
+ # BYE a's IP\n f: b@B \n t: a@A; C server doesnt't spot
|
|
|
|
+ # C domain anywhere despite BYE is legitimate)
|
|
|
|
+ if (!isflagset(FLAG_TOTAG) && !$t.did && !$f.did) {
|
|
|
|
+ sl_reply("403", "Relaying Forbidden");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+route[REGISTRAR]
|
|
|
|
+{
|
|
|
|
+ # process only REGISTERs here
|
|
|
|
+ if (!method=="REGISTER") {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # if this is a replica (sent to multicast address), trust it to be
|
|
|
|
+ # secure and store it in usrloc
|
|
|
|
+ if (dst_ip==224.0.1.75) {
|
|
|
|
+ if (!isflagset(FLAG_PEER_REPLICATE)) {
|
|
|
|
+ # multicast replication adminsitratively disabled -- ignore
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+ if (search("^Repl-Marker: nated")) { #: read marker from master
|
|
|
|
+ setflag(FLAG_NAT);
|
|
|
|
+ $uac_nat=1;
|
|
|
|
+ }
|
|
|
|
+ # assumes URI in form of UID@mydomain; store contacts under
|
|
|
|
+ # this UID; note it only works if local policy causes UIDs to
|
|
|
|
+ # have form compliant to RFC3261 URI usernames
|
|
|
|
+ [email protected];
|
|
|
|
+ if (!save_mem_nr("location")) {
|
|
|
|
+ log(1, "SER: Error while processing replicated REGISTER");
|
|
|
|
+ }
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # check if the REGISTER if for one of our local domains
|
|
|
|
+ if (!$t.did) {
|
|
|
|
+ sl_reply("403", "Register forwarding forbidden");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # the REGISTER target is in the To header, so reload the domain
|
|
|
|
+ if (!lookup_domain("$td", "@to.uri.host")) {
|
|
|
|
+ sl_reply("404", "Unknown Domain");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ append_to_reply("Expires: 600\r\n");
|
|
|
|
+ # useful for clients that ignore expires in 200 -- this is a try
|
|
|
|
+ # to keep them sticking to our value of 600
|
|
|
|
+ append_to_reply("Min-Expires: 240\r\n");
|
|
|
|
+
|
|
|
|
+ # 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # the authentication ID does not match the ID in the To header
|
|
|
|
+ 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;
|
|
|
|
+ #}
|
|
|
|
+
|
|
|
|
+ # everyhting is fine so lets store the binding
|
|
|
|
+ if (!save_contacts("location")) {
|
|
|
|
+ sl_reply("400", "Invalid REGISTER Request");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+ if (isflagset(FLAG_PEER_REPLICATE)) {
|
|
|
|
+ if (isflagset(FLAG_NAT)) {
|
|
|
|
+ append_hf("Repl-Marker: nated\r\n");
|
|
|
|
+ }
|
|
|
|
+ # note: we are multicasting a successful REGISTER
|
|
|
|
+ # to all proxies on the multicast network for
|
|
|
|
+ # sake of replication; in case they share the
|
|
|
|
+ # same IP address (VIP) it is important to set
|
|
|
|
+ # the sending IP address to an unshared one
|
|
|
|
+ # (in the future a special mcast module may
|
|
|
|
+ # use unbound sockets for sending and leave
|
|
|
|
+ # the srouce IP address decision up to kernel
|
|
|
|
+ # routing tables)
|
|
|
|
+ #DEBCONF-REPL_SEND_ADDR-START
|
|
|
|
+ force_send_socket(udp:192.168.1.1);
|
|
|
|
+ #DEBCONF-REPL_SEND_ADDR-END
|
|
|
|
+ # put UID in request URI so that it doesn't
|
|
|
|
+ # have to be looked up by all multicast receivers
|
|
|
|
+ # in database
|
|
|
|
+ attr2uri("$tu.uid","user");
|
|
|
|
+ forward_udp(224.0.1.75,5060);
|
|
|
|
+ }
|
|
|
|
+ drop;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# authentication of request originators claiming to belong to our
|
|
|
|
+# domain
|
|
|
|
+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 (! $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 == $gw_ip) {
|
|
|
|
+ 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 matches 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;
|
|
|
|
+ }
|
|
|
|
+ setflag(FLAG_AUTH_OK);
|
|
|
|
+ # 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[SPEEDDIAL]
|
|
|
|
+{
|
|
|
|
+ # if the caller is local and used only two digits
|
|
|
|
+ # we redirect the UA to the real target
|
|
|
|
+ if ($fd.did && uri=~"sip:[0-9][0-9]@") {
|
|
|
|
+ if (sd_lookup("speed_dial")) {
|
|
|
|
+ sl_reply("302", "Speed Dial Redirect");
|
|
|
|
+ } else {
|
|
|
|
+ sl_reply("404", "Speed Dial Not Found");
|
|
|
|
+ }
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+ ;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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 (! $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");
|
|
|
|
+
|
|
|
|
+ # if we are forwarding to ourselves, don't
|
|
|
|
+ # remove credentials ; otherwise we would be
|
|
|
|
+ # challenged again
|
|
|
|
+ # Note: this doesn't apply to failure_route which
|
|
|
|
+ # may be still problematic -- credentials are already
|
|
|
|
+ # removed when we forward; consider 3xx!!!
|
|
|
|
+ lookup_domain("$td", "@ruri.host");
|
|
|
|
+ if ($t.did) {
|
|
|
|
+ setflag(FLAG_DONT_RM_CRED);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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) {
|
|
|
|
+ if ($t.fr_timer) {
|
|
|
|
+ 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) break;
|
|
|
|
+ if (!$gw_ip) break;
|
|
|
|
+ if (!uri=~"sips?:\+?[0-9]{3,18}@.*") break;
|
|
|
|
+
|
|
|
|
+ # probably you need to convert the number in the request
|
|
|
|
+ # URI according to the requirements of your gateway here
|
|
|
|
+
|
|
|
|
+ # ....
|
|
|
|
+
|
|
|
|
+ # check permissions of the caller here for dialog-initiating requests
|
|
|
|
+ if (method=="INVITE" && [email protected]) {
|
|
|
|
+ if (!$f.gw_acl=="1") {
|
|
|
|
+ sl_reply("403", "pstn not permitted");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # if an optional 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");
|
|
|
|
+ # set the PSTN_ALLOWED flag, checked from onsend_route
|
|
|
|
+ setflag(FLAG_PSTN_ALLOWED);
|
|
|
|
+ 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) {
|
|
|
|
+ # ser 2.1 only
|
|
|
|
+ #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
|
|
|
|
+ ;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+route[SITE_SPECIFIC] {
|
|
|
|
+ # only if a request is coming for one of our domains...
|
|
|
|
+ if (!$t.did) break;
|
|
|
|
+ # check if we do have some site-specific routing policy
|
|
|
|
+ # such as peering
|
|
|
|
+ # example:
|
|
|
|
+ if (uri=~"^sip:000777") {
|
|
|
|
+ rewritehostport("sems01.iptel.org:5074");
|
|
|
|
+ route(FORWARD);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+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
|
|
|
|
+ # We redirect using 3xx to avoid possible issues with credentials
|
|
|
|
+ # (if we consumed them, they may be missing in a loop, if we don't
|
|
|
|
+ # consume them, messages are bigger and more vulnerable)
|
|
|
|
+ if ($tu.fwd_busy_target) {
|
|
|
|
+ #attr2uri("$tu.fwd_busy_target");
|
|
|
|
+ #route(FORWARD);
|
|
|
|
+ attr_destination("$tu.fwd_busy_target");
|
|
|
|
+ t_reply("302", "Redirect On Busy");
|
|
|
|
+ }
|
|
|
|
+ # 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);
|
|
|
|
+ attr_destination("$tu.fwd_noanswer_target");
|
|
|
|
+ t_reply("302", "Redirect On Busy");
|
|
|
|
+ }
|
|
|
|
+ # alternatively you could forward the request to SEMS/voicemail here
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+onreply_route[REPLY_ROUTE]
|
|
|
|
+{
|
|
|
|
+ # fix Contact in reply if it contains a private IP to allow
|
|
|
|
+ # proper routing of in-dialog messages
|
|
|
|
+ # do the same if the contact is maddred -- see [NAT_DETECTION]
|
|
|
|
+ # for additional notes about it
|
|
|
|
+ if (nat_uac_test("1") || (@hf_value["contact"] && @contact.uri.params.maddr) ) {
|
|
|
|
+ fix_nated_contact();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # if a NAT is involved and this is the final positive reply
|
|
|
|
+ # which contains a body, start to use the RTP proxy
|
|
|
|
+ if (isflagset(FLAG_NAT) &&
|
|
|
|
+ status=~"(18[03])|(2[0-9][0-9])" &&
|
|
|
|
+ !search("^Content-Length: 0")) {
|
|
|
|
+ force_rtp_proxy('r');
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+onsend_route{
|
|
|
|
+ # bypass check -- eliminate requests to PSTN GW if they have not
|
|
|
|
+ # passed ACL checks (not marked with FLAG_PSTN_ALLOWED) and are
|
|
|
|
+ # dialog-initiating requests (no to-tag, no CANCEL, no ACK); this
|
|
|
|
+ # helps to stop policy bypasses (GW IP uploaded as a forked contact,
|
|
|
|
+ # or a call-forwarding destination, or a DNS name, or a preloaded
|
|
|
|
+ # route, or something else possibly)
|
|
|
|
+
|
|
|
|
+ if (to_ip==$g.gw_ip && !isflagset(FLAG_PSTN_ALLOWED) &&
|
|
|
|
+ !isflagset(FLAG_TOTAG) && method!="ACK" && method!="CANCEL"){
|
|
|
|
+ log(1, "ALERT: non authorized packet for PSTN, dropping...\n%mb\n");
|
|
|
|
+ # can't use advanced features from onsend_route
|
|
|
|
+ #xlog("L_ALERT", "non authorized packet for PSTN, dropping...\n%mb\n");
|
|
|
|
+ drop;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+route[ON_1MIN_TIMER] {
|
|
|
|
+ # cleanup expired location records
|
|
|
|
+ db_query("delete from location where expires<utc_timestamp()");
|
|
|
|
+
|
|
|
|
+ # reload domains if domain table has been changed recently
|
|
|
|
+ # note: because global attributes are read-only and we can't
|
|
|
|
+ # easily remember the "last" status, we check for changed
|
|
|
|
+ # timestamp in 2 minute time-interval
|
|
|
|
+
|
|
|
|
+ db_query("select value from global_attrs where name='domain_data_version' and type=0 and cast(value as unsigned int) between unix_timestamp(now())-120 and unix_timestamp(now())", 0);
|
|
|
|
+
|
|
|
|
+ if (@db.fetch[0].count=="1") {
|
|
|
|
+ # domain reload only available as fifo command
|
|
|
|
+ exec_msg("sercmd domain.reload");
|
|
|
|
+ }
|
|
|
|
+ db_close(0);
|
|
|
|
+}
|
|
|
|
+
|