verify the return value of append_branch()
[sip-router] / etc / ser-oob.cfg
1 #
2 # $Id$
3 #
4 #
5 # Applicability of this Configuration File
6 # ----------------------------------------
7 #
8 # This is default SER script as used for example at the iptel.org
9 # SIP service; it can deal with NATs, terminate calls to a PSTN
10 # gateway, and it implements a couple of basic signaling features
11 # (few types of call forwarding). In this scenario you may have
12 # multiple SIP proxies sharing one database for accessing provisioned
13 # data, which are maintained for example using serweb. The proxy
14 # servers also share write-access to user location database (and
15 # keeps a full cache of all usrloc entries synchronized using
16 # multicast).
17
18 # If you look for a simpler version with a lot less dependencies
19 # please refer to the ser-basic.cfg file in your SER distribution.
20 #
21 # Requirements: 
22 # ---------------
23 # running DB, running RTP proxy, one public IP address
24 # for SIP service, one private IP address for administrative purposes;
25 # optional: IP address of a PSTN gateway
26 #
27 # HOWTOs:
28 # ---------
29 # To get this config running you need to execute the following commands
30 # with the new serctl (the capital word are just place holders)
31 # - ser_ctl domain add DOMAINNAME
32 # - ser_ctl user add USERNAME@DOMAINNAME -p PASSWORD
33 # If you want to have PID header for your user
34 # - ser_attr add uid=UID asserted_id="PID"
35 # If you want to have gateway support
36 # - 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
37 # - ser_attr add global gw_ip=GATEWAY-IP
38 #  Alternatively you can use serweb to set all the values above.
39 #
40 # Users with permission to call PSTN using this script must have
41 # the $gw_acl attribute set properly, and shall have $asserted_id
42 # set to indicate their caller-id for calls to PSTN. For inbound
43 # calls from PSTN, additional aliases may be also set.
44 #
45 # Warning:
46 # -----------
47 # Note: if this file is installed on Debian from package 'ser-oob' then some options
48 # in this configuration file may be set by post-installation script, according to values
49 # entered by user at installation time in debconf configuration.
50 # These values are then applied automatically to this file each time the 'ser-oob' package
51 # is upgraded or reconfigured by calling 'dpkg-reconfigure ser-oob'.
52 # The parts of this configuration file that may be altered by debconf are enclosed
53 # between '#DEBCONF-something-START' and '#DEBCONF-something-END' comment marks. Please
54 # don't remove them.
55 #
56 #
57 # TODO (Future possible improvements):
58 # ---------------------------------------
59 # * protocol tuning
60 #   - AVP-based diversion for call-forwarding (as opposed to specialized module)
61 #   - add Date header in 200s to REGISTERs (to be packaged with NTP!)
62 # * more security: 
63 #   - pike/rate-limit
64 #   - identity
65 #   - TLS
66 #   - permissions
67 # * refined DB use (e.g., flatstore for acc)
68 # * miscellanous:
69 #  - dialog module for monitoring purposes
70 #  - more extensive logging using xlog (controlled by gflags/gAVPs)
71 # * leveraging 2.1 features:
72 #  - removal of private IP address (it takes a multicast-specific 
73 #    command which will allow OS to determine source IP address)
74 #  - timer route: 
75 #     * don't use exec (it takes domain.reload as script command)
76 #     * compare last-stored timestamp with current timestamp (it takes 
77 #       assignment of gAVPs)
78 #     * check multicast REGISTERs for their TTL (this is a simple and
79 #       effective security check to prevent remote multicast messages
80 #       to damage our traffic)
81 #  - numerous fine-tuning parameters which are only available in 2.1 
82 #   (mlock_pages, dns_try_naptr, etc.)
83 #  - better support for preloaded routes with domain name
84 #
85 # Security considerations:
86 # ------------------------
87 # the script has been tested against security leaks, but it comes
88 # under terms of GPL "as is" without any warranties; better check
89 # yourself that:
90 # - IP based authentication of PSTN gateway and multicast REGISTERs 
91 #   is compliant to your network setup and security policy
92 # - mutliple gateway IPs can't be provisioned as security checks
93 #   are applied only to one
94 #
95 # Licensing
96 # ----------
97 # Copyright (C) 2005-2008 iptelorg GmbH
98 # This file is part of SER, a free SIP server. It is available under the
99 # terms of the  GNU General Public License.
100 # Numerous folks have contributed to this file, including but not limited
101 # to Andrei, Jan, Jiri, Michal, Miklos, Nils
102 #
103 #
104 # .... that's it, enough of yadiyada, here the real file config begins!
105
106
107 # ----------- global configuration parameters ------------------------
108
109 #debug=3         # debug level (cmd line: -ddd)
110 #memdbg=10 # memory debug log level
111 #memlog=10 # memory statistics log level
112 #log_facility=LOG_LOCAL0 # sets the facility used for logging (see syslog(3))
113
114 /* Uncomment these lines to enter debugging mode 
115 fork=no
116 log_stderror=yes
117 */
118
119 check_via=no    # (cmd. line: -v)
120 dns=no          # (cmd. line: -r)
121 rev_dns=no      # (cmd. line: -R)
122 #port=5060
123 #children=4
124 #user=ser
125 #group=ser
126 #disable_core=yes #disables core dumping
127 open_files_limit=20480 # sets the open file descriptors limit
128 #mhomed=yes  # usefull for multihomed hosts, small performance penalty
129 # be conservative about enabling TCP -- it can degrade performance a lot
130 disable_tcp=no
131 #tcp_accept_aliases=yes # accepts the tcp alias via option (see NEWS)
132 # ignore user=phone in request-URIs -- otherwise these URIs would be
133 # interpreted as equivalent to TEL URIs, and their lookup would fail
134 # in URI database
135 phone2tel=no
136
137 reply_to_via=no
138 # public IP address
139 #DEBCONF-LISTEN-START
140 listen=1.2.3.4
141 #DEBCONF-LISTEN-END
142 # sip.mcast.net for REGISTER replication
143 listen=224.0.1.75
144 # administrative interface -- needed for example for multicast source
145 # or XML-RPC
146 #DEBCONF-LISTEN_ADMIN-START
147 listen=udp:192.168.1.1
148 #DEBCONF-LISTEN_ADMIN-END
149
150 # ------------------- misc params -------------------------------------
151 # ser 2.1 only
152 mlock_pages=yes
153 shm_force_alloc=yes
154 real_time=7
155
156
157 # ------------------- DNS params -------------------------------------
158 # (see doc/dns.txt for more details)
159 # minimum timeouts 
160 dns_retr_time=1
161 dns_retr_no=1
162 dns_servers_no=1
163 dns_use_search_list=no
164 dns_try_ipv6=no
165 # dns cache & failover
166 use_dns_cache=on
167 use_dns_failover=on
168 # dns_cache_flags=0
169 dns_cache_negative_ttl=300
170 dns_cache_min_ttl=60
171 dns_cache_max_ttl=86400 # 1 day
172 dns_cache_mem=2048 # 2 MB
173 dns_cache_gc_interval=60  # garbage collection every minute
174 # ser 2.1 specific options
175 # dns_try_naptr=yes
176 # dns_srv_lb=yes  # srv based load balancing
177 # dns_udp_pref=3  # prefer udp (when resolving naptr record)
178 # dns_tcp_pref=2  # if no udp availbale accept tcp (for naptr)
179 # dns_tls_pref=-1 # ignore / don't accept tls (for naptr)
180 # dns_cache_delete_nonexpired=no
181
182 # ------------------- blacklist params -------------------------------------
183 # (see doc/dst_blacklist.txt for more details)
184
185 use_dst_blacklist=on
186 dst_blacklist_mem=1024 # 1 MB
187 dst_blacklist_expire=300  # blacklist default time
188 dst_blacklist_gc_interval=150 # 2.5 min
189 # for ser 2.1 to the above add tm blst_503* parameters and/or use the 
190 # blst module (see NEWS)
191
192 # ------------------- tcp params -------------------------------------
193 # (see NEWS for more details)
194 tcp_connection_lifetime=3600
195 #tcp_max_connections=10240  # default is 2048
196 tcp_connect_timeout=1
197
198 # -------------------- custom parameters ----------------------------
199 # These parameters can be modified runtime via RPC interface,
200 # read the documentation of cfg_rpc module!
201 #
202 # Session Timer parameters, RFC 4028
203 #
204 # default session interval value used by the proxy if the UAC does not support
205 # session timer. Set it to "0" to disable session timer proxy support
206 session_timer.default = "1800" desc "default session interval (in s)"
207 #
208 # minimum session interval value accepted by the proxy,
209 # it must not be less than 90 seconds
210 session_timer.min_se = "90" desc "minimum session interval (in s)"
211
212  
213 # ------------------ module loading ----------------------------------
214
215 # load a SQL database for authentication, domains, user AVPs etc.
216 loadmodule "/usr/lib/ser/modules/mysql.so"
217
218 loadmodule "/usr/lib/ser/modules/sl.so"
219 loadmodule "/usr/lib/ser/modules/tm.so"
220 loadmodule "/usr/lib/ser/modules/rr.so"
221 loadmodule "/usr/lib/ser/modules/maxfwd.so"
222 loadmodule "/usr/lib/ser/modules/usrloc.so"
223 loadmodule "/usr/lib/ser/modules/registrar.so"
224 loadmodule "/usr/lib/ser/modules/xlog.so"
225 loadmodule "/usr/lib/ser/modules/textops.so"
226 loadmodule "/usr/lib/ser/modules/ctl.so"
227 loadmodule "/usr/lib/ser/modules/auth.so"
228 loadmodule "/usr/lib/ser/modules/auth_db.so"
229 loadmodule "/usr/lib/ser/modules/gflags.so"
230 loadmodule "/usr/lib/ser/modules/domain.so"
231 loadmodule "/usr/lib/ser/modules/uri_db.so"
232 loadmodule "/usr/lib/ser/modules/avp.so"
233 loadmodule "/usr/lib/ser/modules/avp_db.so"
234 loadmodule "/usr/lib/ser/modules/acc_db.so"
235 #loadmodule "/usr/lib/ser/modules/xmlrpc.so"
236 loadmodule "/usr/lib/ser/modules/options.so"
237 loadmodule "/usr/lib/ser/modules/sanity.so"
238 loadmodule "/usr/lib/ser/modules/nathelper.so"
239 loadmodule "/usr/lib/ser/modules/uri.so"
240 loadmodule "/usr/lib/ser/modules/speeddial.so"
241 loadmodule "/usr/lib/ser/modules/timer.so"
242 loadmodule "/usr/lib/ser/modules/db_ops.so"
243 loadmodule "/usr/lib/ser/modules/exec.so"
244 loadmodule "/usr/lib/ser/modules/cfg_rpc.so"
245 loadmodule "/usr/lib/ser/modules/eval.so"
246
247 # ----------------- setting script FLAGS -----------------------------
248 flags
249   FLAG_ACC            : 1, # this request will be recorded by ACC
250   FLAG_FAILUREROUTE   : 2, # we are operating from the failure route
251   FLAG_NAT            : 3, # the UAC is behind a NAT
252   FLAG_PEER_REPLICATE : 4, # the request came from a replication peer node
253   FLAG_TOTAG          : 5,
254   FLAG_PSTN_ALLOWED   : 6, # the user is allowed to use the PSTN
255   FLAG_DONT_RM_CRED   : 7, # do not remove the credentials
256   FLAG_AUTH_OK        : 8, # authentication succeeded
257   FLAG_SERWEB_RSVD1   : 9, # bit reserved for use with serweb
258   FLAG_SERWEB_RSVD2   : 10, # bit reserved for use with serweb
259   FLAG_SESSIONTIMER   : 11, # indicates that the UAC supports Session Timer
260   FLAG_RR_DONE        : 12; # the request got already one RR header
261
262 avpflags
263   dialog_cookie;        # handled by rr module
264
265 # ----------------- setting module-specific parameters ---------------
266
267 # specify the path to you database here
268 #DEBCONF-DBURL-START
269 modparam("speeddial|auth_db|usrloc|domain|uri_db|gflags|avp_db|db_ops", "db_url", "mysql://ser:heslo@192.168.1.1/ser")
270 #DEBCONF-DBURL-END
271
272 # specify the path to your database for accounting
273 #DEBCONF-DBURLACC-START
274 modparam("acc_db", "db_url", "mysql://ser:heslo@192.168.1.1/ser")
275 #DEBCONF-DBURLACC-END
276
277 # -- usrloc params --
278
279 # db_mode 0 -- memory cached, 1 -- write thru, 2 -- delayed write
280 # 1 is generally safer than 2 ... 2 can help to survive peaks in load
281 # however it creates delayed peaks that can impair request-processing
282 # latency later (it would have to be re-redesigned more lock-free to
283 # avoid it)
284 #DEBCONF-DBMODE-START
285 modparam("usrloc", "db_mode", 1)
286 #DEBCONF-DBMODE-END
287 # don't delete expired records from database on a per-contact basis -- that
288 # results in bulky DB operations and can lead to synchronization issues
289 # in server farm when for a time a server doesn't obtain re-reregistrations
290 modparam("usrloc","db_skip_delete",1)
291
292 # -- registrar params
293 # maximum expires time, forces users to re-register every 10 min.
294 modparam("registrar", "max_expires", 600)
295 # minimum expires time, even if tried, clients cannot get registered
296 # for a shorter time than this
297 modparam("registrar", "min_expires", 240)
298
299 # identify natted contacts using a flag
300 modparam("registrar", "load_nat_flag", "FLAG_NAT")
301 modparam("registrar", "save_nat_flag", "FLAG_NAT")
302
303 # maximum number of contacts
304 modparam("registrar", "max_contacts", 10)
305
306 # -- auth params --
307 #modparam("auth_db", "calculate_ha1", yes)
308 #modparam("auth_db", "password_column", "password")
309 # minimize replay-attack window
310 modparam("auth", "nonce_expire", 10)
311
312 # Enable/disable extra authentication checks using the following modparams.
313 # The values are: 1:Request-URI, 2:Call-ID, 4: From tag, 8:source IP
314 # The options are disabled by default.
315
316 # For REGISTER requests we hash the Request-URI, Call-ID, and source IP of the
317 # request into the nonce string. This ensures that the generated credentials
318 # cannot be used with another registrar, user agent with another source IP
319 # address or Call-ID. Note that user agents that change Call-ID with every
320 # REGISTER message will not be able to register if you enable this.
321 #modparam("auth", "auth_checks_register", 11)
322
323 # For dialog-establishing requests (such as the original INVITE, OPTIONS, etc)
324 # we hash the Request-URI and source IP. Hashing Call-ID and From tags takes
325 # some extra precaution, because these checks could render some UA unusable.
326 #modparam("auth", "auth_checks_no_dlg", 9)
327
328 # For mid-dialog requests, such as re-INVITE, we can hash source IP and
329 # Request-URI just like in the previous case. In addition to that we can hash
330 # Call-ID and From tag because these are fixed within a dialog and are
331 # guaranteed not to change. This settings effectively restrict the usage of
332 # generated credentials to a single user agent within a single dialog.
333 #modparam("auth", "auth_checks_in_dlg", 15)
334
335 # deal with client's who can't do qop properly
336 modparam("auth", "qop", "")
337 #DEBCONF-AUTHSECRET-START
338 modparam("auth", "secret", "aqwedrftredswqwddcft")
339 #DEBCONF-AUTHSECRET-END
340
341
342 # -- rr params --
343 # add value to ;lr param to make some broken UAs happy
344 modparam("rr", "enable_full_lr", 1)
345 #
346 # limit the length of the AVP cookie to only necessary ones
347 modparam("rr", "cookie_filter", "(account|uac_nat|stimer)")
348 #
349 # you probably do not want that someone can simply read and change
350 # the AVP cookie in your Routes, thus should really change this
351 # secret value below
352 modparam("rr", "cookie_secret", "sgsatewgdbsnmpoiewh")
353
354 # ftag may be used to easily determine if a BYE is coming from
355 # caller or callee, but here we prefer shorter messages
356 modparam("rr", "append_fromtag", 0)
357
358 # -- gflags params --
359 # load the global AVPs
360 # here we load global AVPs such as PSTN GW IP address; this can
361 # be manipulated using ser_attr
362 modparam("gflags", "load_global_attrs", 1)
363
364 # -- domain params --
365 # load the domain AVPs
366 modparam("domain", "load_domain_attrs", 1)
367
368 # -- ctl params --
369 # by default ctl listens on unixs:/tmp/ser_ctl if no other address is
370 # specified in modparams; this is also the default for sercmd
371 modparam("ctl", "binrpc", "unixs:/tmp/ser_ctl")
372 # listen on the "standard" fifo for backward compatibility
373 modparam("ctl", "fifo", "fifo:/tmp/ser_fifo")
374 # listen on tcp, localhost
375 #modparam("ctl", "binrpc", "tcp:localhost:2046")
376
377 # -- acc_db params --
378 # failed transactions (=negative responses) should be logged to
379 modparam("acc_db", "failed_transactions", 1)
380
381 # comment the next line if you dont want to have accouting to DB
382 modparam("acc_db", "log_flag", "FLAG_ACC")
383
384 # if you would like to customize your CDRs, do it here....
385 #modparam("acc_db", "attrs", "$f.sop_billing_category,$f.isPrepaidCustomer,$f.sop_cf_orig_uid")
386
387 # -- tm params --
388 # uncomment the following line if you want to avoid that each new reply
389 # restarts the resend timer (see INBOUND route below)
390 modparam("tm", "restart_fr_on_each_reply", 0)
391
392 # -- xmlrpc params --
393 # using a sub-route from the module is a lot safer then relying on the
394 # request method to distinguish HTTP from SIP
395 #modparam("xmlrpc", "route", "RPC");
396
397 # -- nathelper params --
398 # RTP-Proxy
399 #DEBCONF-RTTPPROXY-START
400 modparam("nathelper", "rtpproxy_sock", "udp:192.168.1.1:22222")
401 #DEBCONF-RTTPPROXY-END
402 # TCP keepalives as simple as CRLF
403 modparam("nathelper", "natping_crlf", 0)
404 #DEBCONF-NATPING_INTERVAL-START
405 modparam("nathelper", "natping_interval", 15)
406 #DEBCONF-NATPING_INTERVAL-END
407 modparam("nathelper", "ping_nated_only", 1)
408 # if this option is not set, simple 4-bytes ping is sent
409 modparam("nathelper", "natping_method", "OPTIONS")
410 #temporary statefull natping test (only in future versions)
411 #modparam("nathelper", "natping_stateful", 1)
412
413 # -- exec module
414 modparam("exec", "time_to_kill", 200);
415 modparam("exec", "setvars", 0);
416
417 # -- timer module
418 modparam("timer", "declare_timer", "ON_1MIN_TIMER=ON_1MIN_TIMER,60000,slow,enable");
419
420 # -- db_ops module
421 modparam("db_ops", "declare_handle", "reload")
422
423 # -------------------------  request routing logic -------------------
424
425 # main routing logic
426
427 route{
428
429
430
431         # if you have a PSTN gateway just un-comment the follwoing line and 
432         # specify the IP address of it to route calls to it
433         #$gw_ip = "1.2.3.4"
434         # alternatively (even better, set it as global persistent parameter
435         # using serweb or ser_attrs); also if using a PSTN GW per-subscriber
436         # options must ($gw_acl) or may (asserted_id) be set to enable calls
437         # to PSTN; if email-like addresses are used, having a URI alias for
438         # processing incoming pstn-2-ip requests may be useful too
439         # important: the script is assuming one global pstn-gw for all domains!
440         # failure to allow gw_ip to be a domain-specific attribute would result
441         # in security gaps (onsend_route checks only for one gateway)
442
443
444         # first do some initial sanity checks
445         route(INIT);
446
447         # bypass the rest of the script for CANCELs if possible
448         route(CATCH_CANCEL);
449
450         # check if the request is routed via Route header
451         route(LOOSE_ROUTE);
452
453         # look up domain IDs
454         route(DOMAIN);
455
456         # answer OPTIONS to our system
457         route(OPTIONS_REPLY);
458
459         # enforce domain policy
460         route(DOMAIN_POLICY);
461
462         # handle REGISTER requests
463         route(REGISTRAR);
464
465         # from here on we want to know who is calling
466         route(AUTHENTICATION);
467
468         # we are finished with all the precaution work -- let's
469         # try to locate the callee; the first route that matches
470         # "wins", if none matches, SER will send a 404
471
472         # check if we should be outbound proxy for a local user
473         route(OUTBOUND);
474
475         # redirect in case user dialed a speed dial entry
476         route(SPEEDDIAL);
477
478         # place various site-specific routes here
479         route(SITE_SPECIFIC);
480
481         # check if the request is for a local user
482         route(INBOUND);
483
484         # here you could for example try to do an ENUM lookup before
485         # the call gets routed to the PSTN
486         #route(ENUM);
487
488         # last resort: if none of the previous route has found
489         # the recepient, try PSTN
490         route(PSTN);
491
492         # nothing matched, reject it finally
493         sl_reply("404", "No route matched");
494 }
495
496 route[FORWARD]
497 {
498         # if this is called from the failure route we need to open a new branch
499         if (isflagset(FLAG_FAILUREROUTE)) {
500                 if (!append_branch()) {
501                         t_reply("500", "Too many branches");
502                         drop;
503                 }
504         }
505
506         # if this is an initial INVITE (without a To-tag) we might try another
507         # (forwarding or voicemail) target after receiving an error
508         if (method=="INVITE" && !@to.tag) {
509                 t_on_failure("FAILURE_ROUTE");
510         }
511
512         # always use the reply route to check for NATed UAS
513         t_on_reply("REPLY_ROUTE");
514
515         # insert a Record-Route header into all requests
516         # this has to be done as one of the last steps to include all the RR
517         # cookies which might have been created during the script run
518         route(RR);
519
520         # turn on or off the RTP proxy as the last step because it modifies the SDP
521         route(RTPPROXY);
522
523
524         # remove credentials to keep requests shorter
525         if (isflagset(FLAG_AUTH_OK) && !isflagset(FLAG_DONT_RM_CRED) ) {
526                 consume_credentials();
527         }
528
529         # send it out now; use stateful forwarding as it works reliably
530         # even for UDP2TCP
531         if (!t_relay()) {
532                 sl_reply_error();
533         }
534         drop;
535 }
536
537 route[INIT]
538 {
539         # initial sanity checks -- messages with
540         # max_forwards==0, or excessively long requests
541         if (!mf_process_maxfwd_header("10")) {
542                 sl_reply("483","Too Many Hops");
543                 drop;
544         }
545
546         #if (msg:len >=  max_len ) {
547         # if (msg:len >=  4096 ) {
548         #       sl_reply("513", "Message too big");
549         #               drop;
550         #}
551
552
553         # this flag is need for the onsend route
554         if (@to.tag) {
555                 setflag(FLAG_TOTAG);
556         }
557         
558         # check if the UAC is natted and fix the message appropiatly
559         route(NAT_DETECTION);
560
561         # lets account all initial INVITEs
562         # further in-dialog requests are accounted by a RR cookie (see below)
563         if (method=="INVITE" && !@to.tag) {
564                 setflag(FLAG_ACC);
565         }
566
567         if ($replicate==1) { # if global flag enabled, carry on replication
568                 setflag(FLAG_PEER_REPLICATE);
569         }
570 }
571
572 route[OPTIONS_REPLY]
573 {
574         # if it is an OPTIONS without a username in the RURI but one
575         # of our IPs answer directly statelessly
576         if (method=="OPTIONS" && @ruri.user=="" && (uri==myself||$t.did)) {
577                 options_reply();
578                 drop;
579         }
580 }
581
582 route[NAT_DETECTION]
583 {
584         # lots of UAs do not send rport in there Via header
585         # so we put it there to remember where to send the reply to
586         force_rport();
587         force_tcp_alias();
588
589         # check if the request contains hints for a NATed UAC
590         # also try to rewrite contacts using maddr; using maddr is a real
591         # dubious technique and we better replace such with transport address;
592         # downside: it fails for clients fronted by another server, in which
593         # case a valid contact we dislike because of maddr will be substituted
594         # inapproprietely; (e.g., WM from other domains will fail); if worried
595         # about that, remove tests for maddr and recompile SER using HONOR_MADDR
596         # also note that possibly rewriting contacts may lead to client
597         # denying subseqent requests to them because they don't recognized
598         # fixed contacts as their own; we haven't encountered such case
599         # yet; a possible solution a la usrloc would be to store the original
600         # information as a contact parameter and restore it on its way back
601         if (nat_uac_test("19") || (@hf_value["contact"] && @contact.uri.params.maddr) ) {
602                 setflag(FLAG_NAT);
603                 $uac_nat=1;
604                 setavpflag($uac_nat, "dialog_cookie");
605                 if (method=="REGISTER") {
606                         # prepare the Contact so that the registrar module saves the
607                         # source as well
608                         fix_nated_register();
609                 } else {
610                         # overwrite the Contact to allow proper in-dialog routing
611                         fix_nated_contact();
612                 }
613         }
614
615 }
616
617 route[RTPPROXY]
618 {
619         # if no NAT is involved we dont have to do here anything
620         if (!isflagset(FLAG_NAT)) {
621                 break;
622         }
623
624         # if the message terminates a dialog turn RTP proxy off
625         if ((method=="BYE" || method=="CANCEL") ||
626                 isflagset(FLAG_FAILUREROUTE)) {
627                 unforce_rtp_proxy();
628                 append_hf("P-RTP-Proxy: UNFORCED\r\n");
629                 break;
630         }
631
632         # turn the RTP proxy on for INVITEs and UPDATEs
633         if ((method=="INVITE" || method == "UPDATE") && @msg.body != "") {
634                 force_rtp_proxy('r');
635                 append_hf("P-RTP-Proxy: YES\r\n");
636         }
637 }
638
639 route[LOOSE_ROUTE]
640 {
641         # subsequent messages withing a dialog should take the
642         # path determined by the Route header
643         if (loose_route()) {
644                 # mark routing logic in request
645                 append_hf("P-hint: rr-enforced\r\n"); 
646
647                 # if the Route contained the accounting AVP cookie we
648                 # set the accounting flag for the acc_db module.
649                 # this is more for demonstration purpose as this could
650                 # also be solved without RR cookies.
651                 # Note: this means all in-dialog request will show up in the
652                 # accouting tables, so prepare your accounting software for this ;-)
653                 if ($account == "yes") {
654                         setflag(FLAG_ACC);
655                 }
656
657                 # restore the NAT flag if present
658                 if ($uac_nat == 1) {
659                         setflag(FLAG_NAT);
660                 }
661
662                 # restore Session Timer flag and headers
663                 if ($stimer && ($stimer != "0")) {
664                         route(SESSION_TIMER);
665                 }
666
667                 # for broken devices which overwrite their Route's with each
668                 # (not present) RR from within dialog requests it is better
669                 # to repeat the RRing
670                 # and if we call rr after loose_route the AVP cookies are restored
671                 # automatically :)
672                 # There is also one scenario where subsequent indialog RR is
673                 # required if the initial SUBSCRIBE forked.
674                 # note that here we forward before authentication check is executed;
675                 # generally we only authenticate dialog-initiating requests; some
676                 # in-dialog requests can't be authenticated at all, see the
677                 # call-forwarding example in route[DOMAIN]
678                 route(RR);
679
680                 route(FORWARD);
681         }
682 }
683
684 route[RR]
685 {
686         if (!isflagset(FLAG_RR_DONE) && !method=="REGISTER") {
687                 # we record-route all messages -- to make sure that
688                 # subsequent messages will go through our proxy; that's
689                 # particularly good if upstream and downstream entities
690                 # use different transport protocol
691
692                 # if the inital INVITE got the ACC flag store this in
693                 # an RR AVP cookie. this is more for demonstration purpose
694                 if (isflagset(FLAG_ACC)) {
695                         $account = "yes";
696                         setavpflag($account, "dialog_cookie");
697                 }
698
699                 # let's insert the RR header now
700                 record_route();
701
702                 # this flag simply allows to call this route several times
703                 # without inserting several RR headers
704                 setflag(FLAG_RR_DONE);
705         }
706 }
707
708 route[DOMAIN]
709 {
710         # check if the caller is from a local domain
711         lookup_domain("$fd", "@from.uri.host");
712
713         # check if the callee is at a local domain
714         lookup_domain("$td", "@ruri.host");
715 }
716
717 route[DOMAIN_POLICY]
718 {
719
720         # we dont know the domain of the caller and also not
721         # the domain of the callee -> somone uses our proxy as
722         # a relay; however we apply this check only to dialog
723         # initiating requests (no totag) -- in some cases such
724         # as call-forwarding, subsequent requests may not include
725         # served domain neither as origination nor destination
726         # (a@A calls b@B that forwards to c@C; BYE is formed as
727         # BYE a's IP\n f: b@B \n t: a@A; C server doesn't spot
728         # C domain anywhere despite BYE is legitimate)
729         if (!isflagset(FLAG_TOTAG) && !$t.did && !$f.did) {
730                 sl_reply("403", "Relaying Forbidden");
731                 drop;
732         }
733 }
734
735
736
737 route[REGISTRAR]
738 {
739         # process only REGISTERs here
740         if (!method=="REGISTER") {
741                 break;
742         }
743
744         # if this is a replica (sent to multicast address), trust it to be
745         # secure and store it in usrloc
746         if (dst_ip==224.0.1.75) {
747                 if (!isflagset(FLAG_PEER_REPLICATE)) {
748                         # multicast replication adminsitratively disabled -- ignore
749                         drop;
750                 }
751                 if (search("^Repl-Marker: nated")) { #: read marker from master
752                         setflag(FLAG_NAT);
753                         $uac_nat=1;
754                 }
755                 # assumes URI in form of UID@mydomain; store contacts under
756                 # this UID; note it only works if local policy causes UIDs to
757                 # have form compliant to RFC3261 URI usernames
758                 $tu.uid=@ruri.user;
759                 if (!save_mem_nr("location")) {
760                         log(1, "SER: Error while processing replicated REGISTER");
761                 }
762                 drop;
763         }
764
765         # check if the REGISTER if for one of our local domains
766         if (!$t.did) {
767                 sl_reply("403", "Register forwarding forbidden");
768                 drop;
769         }
770
771         # the REGISTER target is in the To header, so reload the domain
772         if (!lookup_domain("$td", "@to.uri.host")) {
773                 sl_reply("404", "Unknown Domain");
774                 drop;
775         }
776
777         append_to_reply("Expires: 600\r\n");
778         # useful for clients that ignore expires in 200 -- this is a try
779         # to keep them sticking to our value of 600
780         append_to_reply("Min-Expires: 240\r\n");
781
782         # we want only authenticated users to be registered
783         if (!www_authenticate("$fd.digest_realm", "credentials")) {
784                 if ($? == -2) {
785                         sl_reply("500", "Internal Server Error");
786                 } else if ($? == -3) {
787                         sl_reply("400", "Bad Request");
788                 } else {
789                         if ($digest_challenge) {
790                                 append_to_reply("%$digest_challenge");
791                         }
792                         sl_reply("401", "Unauthorized");
793                 }
794                 drop;
795         }
796
797         # check if the authenticated user is the same as the target user
798         if (!lookup_user("$tu.uid", "@to.uri")) {
799                 sl_reply("404", "Unknown user in To");
800                 drop;
801         }
802
803         # the authentication ID does not match the ID in the To header
804         if ($f.uid != $t.uid) {
805                 sl_reply("403", "Authentication and To-Header mismatch");
806                 drop;
807         }
808
809         # check if the authenticated user is the same as the request originator
810         # you may uncomment it if you care, what uri is in From header
811         #if (!lookup_user("$fu.uid", "@from.uri")) {
812         #       sl_reply("404", "Unknown user in From");
813         #       drop;
814         #}
815         #if ($fu.uid != $tu.uid) {
816         #       sl_reply("403", "Authentication and From-Header mismatch");
817         #       drop;
818         #}
819
820         # everyhting is fine so lets store the binding
821         if (!save_contacts("location")) {
822                 sl_reply("400", "Invalid REGISTER Request");
823                 drop;
824         }
825         if (isflagset(FLAG_PEER_REPLICATE)) {
826                 if (isflagset(FLAG_NAT)) {
827                         append_hf("Repl-Marker: nated\r\n");
828                 }
829                 # note: we are multicasting a successful REGISTER
830                 # to all proxies on the multicast network for
831                 # sake of replication; in case they share the
832                 # same IP address (VIP) it is important to set
833                 # the sending IP address to an unshared one
834                 # (in the future a special mcast module may 
835                 # use unbound sockets for sending and leave
836                 # the source IP address decision up to kernel
837                 # routing tables)
838                 #DEBCONF-REPL_SEND_ADDR-START
839                 force_send_socket(udp:192.168.1.1);
840                 #DEBCONF-REPL_SEND_ADDR-END
841                 # put UID in request URI so that it doesn't
842                 # have to be looked up by all multicast receivers
843                 # in database
844                 attr2uri("$tu.uid","user");
845                 forward_udp(224.0.1.75,5060);
846         }
847         drop;
848 }
849
850
851
852 # authentication of request originators claiming to belong to our
853 # domain
854 route[AUTHENTICATION]
855 {
856         if (method=="CANCEL" || method=="ACK") {
857                 # you are not allowed to challenge these methods
858                 break;
859         }
860
861
862         # requests from non-local to local domains should be permitted
863         # remove this if you want a walled garden
864         if (! $f.did) {
865                 break;
866         }
867
868         # as gateways are usually not able to authenticate for their
869         # requests you will have trust them base on some other information
870         # like the source IP address. WARNING: if at all this is only safe
871         # in a local network!!!
872         if (@src.ip == $gw_ip) {
873                 break;
874         }
875
876         if (!proxy_authenticate("$fd.digest_realm", "credentials")) {
877                 if ($? == -2) {
878                         sl_reply("500", "Internal Server Error");
879                 } else if ($? == -3) {
880                         sl_reply("400", "Bad Request");
881                 } else {
882                         if ($digest_challenge) {
883                                 append_to_reply("%$digest_challenge");
884                         }
885                         sl_reply("407", "Proxy Authentication Required");
886                 }
887                 drop;
888         }
889
890         # check if the UID from the authentication matches the From header
891         if (!lookup_user("$fr.uid", "@from.uri")) {
892                 del_attr("$uid");
893         }
894         if ($fu.uid != $fr.uid) {
895                 sl_reply("403", "Fake Identity");
896                 drop;
897         }
898         setflag(FLAG_AUTH_OK);
899         # load the user AVPs (preferences) of the caller, e.g. for RPID header
900         load_attrs("$fu", "$f.uid");
901 }
902
903 route[OUTBOUND]
904 {
905         # if a local user calls to a foreign domain we play outbound proxy for him
906         # comment this out if you want a walled garden
907         if ($f.did && ! $t.did) {
908                 append_hf("P-hint: outbound\r\n");
909                 route(FORWARD);
910         }
911 }
912
913 route[SPEEDDIAL]
914 {
915         # if the caller is local and used only two digits
916         # we redirect the UA to the real target
917         if ($fd.did && uri=~"sip:[0-9][0-9]@") {
918                 if (sd_lookup("speed_dial")) {
919                         sl_reply("302", "Speed Dial Redirect");
920                 } else {
921                         sl_reply("404", "Speed Dial Not Found");
922                 }
923                 drop;
924         }
925         ;
926 }
927
928 route[INBOUND]
929 {
930         # lets see if know the callee
931         if (!lookup_user("$tu.uid", "@ruri")) 
932                 break;
933         
934         # load the preferences of the callee to have his timeout values loaded
935         load_attrs("$tu", "$t.uid");
936
937         # if you want to know if the callee username was an alias
938         # check it like this
939         #if (! $tu.uri_canonical) {
940                 # if the alias URI has different AVPs/preferences
941                 # you can load them into the URI track like this
942                 #load_attrs("$tr", "@ruri");
943         #}
944
945         # check for call forwarding of the callee
946         # Note: the forwarding target has to be full routable URI
947         #       in this example
948         if ($tu.fwd_always_target) {
949                 attr2uri("$tu.fwd_always_target");
950
951                 # if we are forwarding to ourselves, don't
952                 # remove credentials ; otherwise we would be
953                 # challenged again
954                 # Note: this doesn't apply to failure_route which
955                 # may be still problematic -- credentials are already
956                 # removed when we forward; consider 3xx!!!
957                 lookup_domain("$td", "@ruri.host");
958                 if ($t.did) {
959                         setflag(FLAG_DONT_RM_CRED);
960                 }
961
962                 route(FORWARD);
963         }
964
965         # native SIP destinations are handled using our USRLOC DB
966         if (lookup_contacts("location")) {
967                 append_hf("P-hint: usrloc applied\r\n");
968
969
970                 # we set the TM module timers according to the prefences
971                 # of the callee (avoid too long ringing of his phones)
972                 # Note1: timer values have to be in ms now!
973                 # Note2: this makes even more sense if you switch to a voicemail
974                 #        from the FAILURE_ROUTE below
975                 if ($t.fr_inv_timer) {
976                         if ($t.fr_timer) {
977                                 t_set_fr("$t.fr_inv_timer", "$t.fr_timer");
978                         } else {
979                                 t_set_fr("$t.fr_inv_timer");
980                         }
981                 }
982
983                 # this enables session timer support as long as one side supports it.
984                 # if you want to have session timmer support only for calls from your
985                 # PSTN gateway but between pure VoIP calls you can remove the comment
986                 # marks from the if clause in the next line and closing bracket below
987                 # WARNING: if at all you should trust IP addresses only in your local network!!!
988                 #if (@src.ip == $gw_ip) {
989                         route(SESSION_TIMER);
990                 #}
991
992                 route(FORWARD);
993         } else {
994                 sl_reply("480", "User temporarily not available");
995                 drop;
996         }
997 }
998
999 route[PSTN]
1000 {
1001         # Only if the AVP 'gw_ip' is set and the request URI contains
1002         # only a number we consider sending this to the PSTN GW.
1003         # Only users from a local domain are permitted to make calls.
1004         # Additionally you might want to check the acl AVP to verify
1005         # that the user is allowed to make such expensives calls.
1006         if (!$f.did) break;
1007         if (!$gw_ip) break;
1008         if (!uri=~"sips?:\+?[0-9]{3,18}@.*") break;
1009         
1010         # probably you need to convert the number in the request
1011         # URI according to the requirements of your gateway here
1012
1013         # ....
1014
1015         # check permissions of the caller here for dialog-initiating requests
1016         if (method=="INVITE" && !@to.tag) {
1017                 if (!$f.gw_acl=="1") {
1018                         sl_reply("403", "pstn not permitted");
1019                         drop;
1020                 }
1021         }
1022
1023         # if an optional AVP 'asserted_id' is set we insert an RPID header
1024         if ($asserted_id) {
1025                 xlset_attr("$rpidheader", "<sip:%$asserted_id@%@ruri.host>;screen=yes");
1026                 replace_attr_hf("Remote-Party-ID", "$rpidheader");
1027         }
1028
1029         # enable Session Timer support with the GW
1030         route(SESSION_TIMER);
1031
1032         # just replace the domain part of the RURI with the
1033         # value from the AVP and send it out
1034         attr2uri("$gw_ip", "domain");
1035         # set the PSTN_ALLOWED flag, checked from onsend_route
1036         setflag(FLAG_PSTN_ALLOWED);
1037         route(FORWARD);
1038 }
1039
1040 route[CATCH_CANCEL] {
1041         # check whether there is a corresponding INVITE to the CANCEL,
1042         # and bypass the rest of the script if possible
1043
1044         if (method == CANCEL) {
1045                 # ser 2.1 only
1046                 if (!t_relay_cancel()) { # implicit drop if the INVITE was found
1047
1048                         # INVITE was found but some error occurred
1049                         sl_reply("500", "Internal Server Error");
1050                         drop;
1051                 }
1052                 # bad luck, no corresponding INVITE was found,
1053                 # we have to continue with the script
1054                 ;
1055         }
1056 }
1057
1058 route[SITE_SPECIFIC] {
1059         # only if a request is coming for one of our domains...
1060         if (!$t.did) break;
1061         # check if we do have some site-specific routing policy
1062         # such as peering
1063         # example:
1064         if (uri=~"^sip:000777") {
1065                 rewritehostport("sems01.iptel.org:5074");
1066                 route(FORWARD);
1067         }
1068 }
1069
1070 route[SESSION_TIMER]
1071 {
1072         # we are only interested in session establishment or
1073         # session refresher
1074         if (!(method == "INVITE" || method == "UPDATE")) {
1075                 break;
1076         }
1077
1078         # lets check if the Session-Expires header is already present
1079         if (@hf_value.session_expires) {
1080                 # compare the Session-Expires header value with the
1081                 # configured Min-SE
1082                 eval_push("x:%@hf_value.session_expires.uri");
1083                 eval_oper("(int)", -1);
1084                 eval_push("x:%@cfg_get.session_timer.min_se");
1085                 eval_oper("(int)", -1);
1086                 eval_oper(">", -2);
1087
1088                 # lets check for the Suported header
1089                 if (hf_value_exists("Supported", "timer")) {
1090                         # the UAC supports Session Timer, so we
1091                         # only need to take a look at the values
1092
1093                         if (@eval.pop[-1] == "0") {
1094                                 # session interval is lower than the configured Min-SE
1095                                 append_to_reply("Min-SE: %@cfg_get.session_timer.min_se\r\n");
1096                                 sl_reply("422", "Session Interval Too Small");
1097                                 drop;
1098                         }
1099
1100                         # we store the session expires value for the reply route
1101                         $stimer = @hf_value.session_expires.uri;
1102                         # and mark the AVP to be inserted as RR cookie
1103                         setavpflag($stimer, "dialog_cookie");
1104
1105                         # set the session timer flag that indicates the
1106                         # UAC supports the extension.
1107                         setflag(FLAG_SESSIONTIMER);
1108                 } else {
1109                         #session epxires was already inserted by some other proxy
1110                         if (@eval.pop[-1] == "0") {
1111                                 # session interval is lower than the configured Min-SE.
1112                                 # There is no point in sending 422 response, because the UAC
1113                                 # does not support the extension, the values can be corrected instead.
1114                                 assign_hf_value("Session-Expires", "%@cfg_get.session_timer.min_se");
1115                                 remove_hf_value("Min-SE");
1116                                 append_hf_value("Min-SE", "%@cfg_get.session_timer.min_se");
1117                         }
1118                 }
1119         } else {
1120                 # no Session Timer is requested yet, neither by UAC nor by proxy
1121
1122                 if (@cfg_get.session_timer.default != "0") {
1123                         # Add a Session Expires header
1124                         # to see if the UAS supports Session Timer.
1125                         # We do not insert a Required header because then the
1126                         # call might fail.
1127                         append_hf_value("Session-Expires", "%@cfg_get.session_timer.default");
1128                         if (@cfg_get.session_timer.min_se != "90") { # not the default value
1129                                 append_hf_value("Min-SE", "%@cfg_get.session_timer.min_se");
1130                         }
1131
1132                         # mark the AVP to be inserted as RR cookie
1133                         $stimer = @cfg_get.session_timer.default;
1134                         setavpflag($stimer, "dialog_cookie");
1135                 }
1136         }
1137 }
1138
1139 failure_route[FAILURE_ROUTE]
1140 {
1141         # mark for the other routes that we are operating from here on from a
1142         # failure route
1143         setflag(FLAG_FAILUREROUTE);
1144
1145         if (t_check_status("486|600")) {
1146                 # if we received a busy and a busy target is set, forward it there
1147                 # Note: again the forwarding target has to be a routeable URI
1148                 # We redirect using 3xx to avoid possible issues with credentials
1149                 # (if we consumed them, they may be missing in a loop, if we don't
1150                 # consume them, messages are bigger and more vulnerable)
1151                 if ($tu.fwd_busy_target) {
1152                         #attr2uri("$tu.fwd_busy_target");
1153                         #route(FORWARD);
1154                         attr_destination("$tu.fwd_busy_target");
1155                         t_reply("302", "Redirect On Busy");
1156                 }
1157                 # alternatively you could forward the request to SEMS/voicemail here
1158         }
1159         else if (t_check_status("408|480")) {
1160                 # if we received no answer and the noanswer target is set,
1161                 # forward it there
1162                 # Note: again the target has to be a routeable URI
1163                 if ($tu.fwd_noanswer_target) {
1164                         #attr2uri("$tu.fwd_noanswer_target");
1165                         #route(FORWARD);
1166                         attr_destination("$tu.fwd_noanswer_target");
1167                         t_reply("302", "Redirect On No Answer");
1168                 }
1169                 # alternatively you could forward the request to SEMS/voicemail here
1170         }
1171 }
1172
1173 onreply_route[REPLY_ROUTE]
1174 {
1175         # fix Contact in reply if it contains a private IP to allow
1176         # proper routing of in-dialog messages
1177         # do the same if the contact is maddred -- see [NAT_DETECTION]
1178         # for additional notes about it
1179         if (nat_uac_test("1") || (@hf_value["contact"] && @contact.uri.params.maddr) ) {
1180                 fix_nated_contact();
1181         }
1182
1183         # if a NAT is involved and this is the final positive reply
1184         # which contains a body, start to use the RTP proxy
1185         if (isflagset(FLAG_NAT) &&
1186                 status=~"(18[03])|(2[0-9][0-9])" &&
1187                 @msg.body != "") {
1188                 force_rtp_proxy('r');
1189         }
1190
1191         # lets check for session timer support
1192         if (isflagset(FLAG_SESSIONTIMER) && status =~ "2[0-9][0-9]") {
1193                 # the UAC wanted to have a session timer
1194
1195                 if (!@hf_value.session_expires) {
1196                         # but the UAS does not support it
1197                         # so we will try to convince the UAC to do it
1198                         append_hf_value("Session-Expires", "%$stimer;refresher=uac");
1199
1200                         if (!hf_value_exists("Require", "timer")) {
1201                                 include_hf_value("Require", "timer");
1202                         }
1203                 }
1204         }
1205 }
1206
1207
1208 onsend_route{
1209         # bypass check -- eliminate requests to PSTN GW if they have not
1210         # passed ACL checks (not marked with FLAG_PSTN_ALLOWED) and are
1211         # dialog-initiating requests (no to-tag, no CANCEL, no ACK); this
1212         # helps to stop policy bypasses (GW IP uploaded as a forked contact,
1213         # or a call-forwarding destination, or a DNS name, or a preloaded
1214         # route, or something else possibly)
1215
1216         if (to_ip==$g.gw_ip && !isflagset(FLAG_PSTN_ALLOWED) &&
1217             !isflagset(FLAG_TOTAG) && method!="ACK" && method!="CANCEL"){
1218                 log(1, "ALERT: non authorized packet for PSTN, dropping...\n%mb\n");
1219                 # can't use advanced features from onsend_route
1220                 #xlog("L_ALERT", "non authorized packet for PSTN, dropping...\n%mb\n");
1221                 drop;
1222         }
1223         # RFC1918 relay protection -- useful if SER is attached to an administrative
1224         # network using private IP address space and you wish to prevent UACs from
1225         # relaying their packets there
1226         if (to_ip==10.0.0.0/8 || to_ip==172.16.0.0/12 || to_ip==192.168.0.0/16) {
1227                 log(1, "ALERT: Packet targeted to an RFC1918 address dropped\n");
1228                 drop;
1229         }
1230
1231 }
1232
1233 route[ON_1MIN_TIMER] {
1234         # cleanup expired location records
1235         db_query("delete from location where expires<utc_timestamp()");  
1236
1237         # reload domains if domain table has been changed recently
1238         # note: because global attributes are read-only and we can't
1239         # easily remember the "last" status, we check for changed
1240         # timestamp in 2 minute time-interval
1241
1242         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())", "reload");
1243
1244         if (@db.fetch.reload.count=="1") {
1245                 # domain reload only available as fifo command
1246                 exec_msg("sercmd domain.reload"); 
1247         }
1248         db_close("reload");
1249 }
1250