|
@@ -0,0 +1,563 @@
|
|
|
|
+#!/bin/sh
|
|
|
|
+#
|
|
|
|
+# $Id$
|
|
|
|
+#
|
|
|
|
+# SER configuration script
|
|
|
|
+#
|
|
|
|
+# disclaimer: extremely simplistic and experimental
|
|
|
|
+# useful only for people who know what they are doing
|
|
|
|
+# and want to save some typing
|
|
|
|
+#
|
|
|
|
+# call it to generate a basic script -- you have to
|
|
|
|
+# carry out any subsequent changes manually
|
|
|
|
+#
|
|
|
|
+
|
|
|
|
+# ------------------- Variables ------------------------
|
|
|
|
+
|
|
|
|
+# prompted variables
|
|
|
|
+# SER_DOMAIN -- name of served domain, e.g., foo.bar.com
|
|
|
|
+# SER_GWIP -- IP address of PSTN gateway, e.g. 10.0.0.1
|
|
|
|
+
|
|
|
|
+# parameters that are typically not changed
|
|
|
|
+SER_SQL_URI="sql://ser:heslo@localhost/ser"
|
|
|
|
+# set LIB_PATH if all modules are installed in a single
|
|
|
|
+# directory; otherwise, modules are sought in 'modules'
|
|
|
|
+# subdirectories
|
|
|
|
+#SER_LIB_PATH="/usr/local/lib/ser/modules"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# --------------------- functions ---------------------------
|
|
|
|
+function go_to_pstn()
|
|
|
|
+{
|
|
|
|
+ if [ -n "$SER_GWIP" ] ; then
|
|
|
|
+ cat << EOGOTOPSTN
|
|
|
|
+ # now check if it's about PSTN destinations through our gateway;
|
|
|
|
+ # note that 8.... is exempted for numerical non-gw destinations
|
|
|
|
+ if (uri=~"sip:\+?[0-79][0-9]*@.*") {
|
|
|
|
+ route(3);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+EOGOTOPSTN
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function addr2re()
|
|
|
|
+{
|
|
|
|
+ echo $1 | sed -ne "s/\./\\\./gp"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function gw_check()
|
|
|
|
+{
|
|
|
|
+ if [ -n "$SER_GWIP" ] ; then
|
|
|
|
+ cat << EOGWTEST
|
|
|
|
+ if (uri=~"sip:[+0-9]+@$SER_GWIP_RE") {
|
|
|
|
+ # it is gateway -- proceed to ACLs
|
|
|
|
+ route(3);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+EOGWTEST
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function mine_check()
|
|
|
|
+{
|
|
|
|
+ printf "uri=~\"[@:](sip[\.)?$SER_DOMAIN_TEST_RE([;:].*)*\" $SER_GW_TEST_RE"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function gw_m_check()
|
|
|
|
+{
|
|
|
|
+ if [ -n "$SER_GWIP" ] ; then
|
|
|
|
+ cat << EOMCHECK
|
|
|
|
+ if (search("^(Contact|m): .*$SER_GWIP_RE")) {
|
|
|
|
+ log(1, "LOG: alert: protected contacts\n");
|
|
|
|
+ sl_send_reply("476", "No Server Address in Contacts Allowed" );
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+EOMCHECK
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function help()
|
|
|
|
+{
|
|
|
|
+ cat << EOHELP
|
|
|
|
+Numbering plan is as follows:
|
|
|
|
+- numbers beginning with 8 are considered aliases
|
|
|
|
+- numbers beginning with + are considered ENUM destinations
|
|
|
|
+EOHELP
|
|
|
|
+ if [ -n "$SER_GWIP" ] ; then
|
|
|
|
+ cat << EOHELP2
|
|
|
|
+- all other numbers are considered PSTN destinations
|
|
|
|
+ ... to dial PSTN, a user must have 'int' privilege
|
|
|
|
+EOHELP2
|
|
|
|
+ else
|
|
|
|
+ echo "- all other numbers are considered usernames"
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function usage()
|
|
|
|
+{
|
|
|
|
+ echo "Usage: $0 <domain_name> [<ip_address_of_gateway>]" \
|
|
|
|
+ '> <config_file>' > /dev/stderr
|
|
|
|
+ exit 1
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function load_mod()
|
|
|
|
+{
|
|
|
|
+ if [ -n "$SER_LIB_PATH" ] ; then
|
|
|
|
+ echo "loadmodule \"$SER_LIB_PATH/$1.so\""
|
|
|
|
+ else
|
|
|
|
+ echo "loadmodule \"modules/$1/$1.so\""
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# ----------------------- user-parameter check ---------------
|
|
|
|
+# SER_DOMAIN -- name of served domain, e.g., foo.bar.com
|
|
|
|
+# SER_GWIP -- IP address of PSTN gateway, e.g. 10.0.0.1
|
|
|
|
+
|
|
|
|
+if [ $# -gt 0 ] ; then
|
|
|
|
+ SER_DOMAIN="$1"
|
|
|
|
+ shift
|
|
|
|
+ if [ $# -gt 0 ] ; then
|
|
|
|
+ SER_GWIP="$1"
|
|
|
|
+ shift
|
|
|
|
+ fi
|
|
|
|
+ if [ $# -gt 0 ] ; then
|
|
|
|
+ usage
|
|
|
|
+ fi
|
|
|
|
+else
|
|
|
|
+ usage
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# ---------------------- initialization -------------------------
|
|
|
|
+
|
|
|
|
+# autodetection parameters
|
|
|
|
+SER_IP=`/sbin/ifconfig eth0 |
|
|
|
|
+ sed -ne 's/\( \)*\(inet addr:\)\([0-9\.]*\).*/\3/gp'`
|
|
|
|
+
|
|
|
|
+# construction of regular expressions
|
|
|
|
+SER_IP_RE=`addr2re $SER_IP`
|
|
|
|
+SER_DOMAIN_RE=`addr2re $SER_DOMAIN`
|
|
|
|
+
|
|
|
|
+# tests
|
|
|
|
+# - is this for my domain
|
|
|
|
+SER_DOMAIN_TEST_RE=`printf "($SER_DOMAIN_RE|$SER_IP_RE)"`
|
|
|
|
+# - is this for my gateway ?
|
|
|
|
+if [ -n "$SER_GWIP" ] ; then
|
|
|
|
+ SER_GWIP_RE=`addr2re $SER_GWIP`
|
|
|
|
+ SER_GW_TEST_RE=`printf "| uri=~\"@$SER_GWIP_RE([;:].*)*\""`
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+SER_REGISTRAR="registrar@$SER_DOMAIN"
|
|
|
|
+
|
|
|
|
+# ---------------------- verficiation --------------------------
|
|
|
|
+set | grep ^SER_ > /dev/stderr
|
|
|
|
+echo > /dev/stderr
|
|
|
|
+echo "IS EVERYTHING OK ???? (press ^C to interrupt)" > /dev/stderr
|
|
|
|
+read
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# --------------------- dump it here -------------------------
|
|
|
|
+
|
|
|
|
+cat << EOF
|
|
|
|
+
|
|
|
|
+#
|
|
|
|
+# \$Id$
|
|
|
|
+#
|
|
|
|
+# autogenerated SER configuration
|
|
|
|
+#
|
|
|
|
+# user: `id`
|
|
|
|
+# system: `uname -a`
|
|
|
|
+# date: `date`
|
|
|
|
+#
|
|
|
|
+
|
|
|
|
+# ----------- global configuration parameters ------------------------
|
|
|
|
+
|
|
|
|
+debug=3
|
|
|
|
+fork=yes
|
|
|
|
+port=5060
|
|
|
|
+log_stderror=no
|
|
|
|
+memlog=5
|
|
|
|
+
|
|
|
|
+mhomed=yes
|
|
|
|
+
|
|
|
|
+fifo="/tmp/ser_fifo"
|
|
|
|
+
|
|
|
|
+alias=$SER_DOMAIN
|
|
|
|
+
|
|
|
|
+# uncomment to override config values for test
|
|
|
|
+/*
|
|
|
|
+debug=3 # debug level (cmd line: -ddd)
|
|
|
|
+fork=no
|
|
|
|
+port=5068
|
|
|
|
+log_stderror=yes # (cmd line: -E)
|
|
|
|
+fifo="/tmp/ser_fifox"
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+check_via=no # (cmd. line: -v)
|
|
|
|
+dns=no # (cmd. line: -r)
|
|
|
|
+rev_dns=no # (cmd. line: -R)
|
|
|
|
+children=16
|
|
|
|
+# if changing fifo mode to a more restrictive value, put
|
|
|
|
+# decimal value in there, e.g. dec(rw|rw|rw)=dec(666)=438
|
|
|
|
+#fifo_mode=438
|
|
|
|
+
|
|
|
|
+# ------------------ module loading ----------------------------------
|
|
|
|
+
|
|
|
|
+`load_mod tm`
|
|
|
|
+`load_mod sl`
|
|
|
|
+`load_mod acc`
|
|
|
|
+`load_mod rr`
|
|
|
|
+`load_mod maxfwd`
|
|
|
|
+`load_mod mysql`
|
|
|
|
+`load_mod usrloc`
|
|
|
|
+`load_mod registrar`
|
|
|
|
+`load_mod auth`
|
|
|
|
+`load_mod auth_db`
|
|
|
|
+`load_mod textops`
|
|
|
|
+`load_mod uri`
|
|
|
|
+`load_mod group`
|
|
|
|
+`load_mod msilo`
|
|
|
|
+`load_mod enum`
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# ----------------- setting module-specific parameters ---------------
|
|
|
|
+
|
|
|
|
+# all DB urls here
|
|
|
|
+modparam("usrloc|acc|auth_db|group|msilo|uri", "db_url",
|
|
|
|
+ "$SER_SQL_URI")
|
|
|
|
+
|
|
|
|
+# -- usrloc params --
|
|
|
|
+/* 0 -- dont use mysql, 1 -- write_through, 2--write_back */
|
|
|
|
+modparam("usrloc", "db_mode", 2)
|
|
|
|
+modparam("usrloc", "timer_interval", 10)
|
|
|
|
+
|
|
|
|
+# -- auth params --
|
|
|
|
+
|
|
|
|
+modparam("auth_db", "calculate_ha1", yes)
|
|
|
|
+#modparam("auth_db", "user_column", "user_id")
|
|
|
|
+modparam("auth_db", "password_column", "password")
|
|
|
|
+modparam("auth", "nonce_expire", 300)
|
|
|
|
+
|
|
|
|
+# -- rr params --
|
|
|
|
+# add value to ;lr param to make some broken UAs happy
|
|
|
|
+modparam("rr", "enable_full_lr", 1)
|
|
|
|
+
|
|
|
|
+# -- acc params --
|
|
|
|
+# that is the flag for which we will account -- don't forget to
|
|
|
|
+modparam("acc", "db_flag", 1 )
|
|
|
|
+modparam("acc", "db_missed_flag", 3 )
|
|
|
|
+
|
|
|
|
+# -- tm params --
|
|
|
|
+modparam("tm", "fr_timer", 20 )
|
|
|
|
+modparam("tm", "fr_inv_timer", 90 )
|
|
|
|
+modparam("tm", "wt_timer", 20 )
|
|
|
|
+
|
|
|
|
+# -- msilo params
|
|
|
|
+modparam("msilo", "registrar", "sip:$SER_REGISTRAR")
|
|
|
|
+
|
|
|
|
+# -- enum params --
|
|
|
|
+#
|
|
|
|
+modparam("enum", "domain_suffix", "e164.arpa.")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# ------------------------- request routing logic -------------------
|
|
|
|
+
|
|
|
|
+# main routing logic
|
|
|
|
+
|
|
|
|
+route{
|
|
|
|
+
|
|
|
|
+ /* ********* ROUTINE CHECKS ********************************** */
|
|
|
|
+
|
|
|
|
+ # filter too old messages
|
|
|
|
+ if (!mf_process_maxfwd_header("10")) {
|
|
|
|
+ log("LOG: Too many hops\n");
|
|
|
|
+ sl_send_reply("483","Alas Too Many Hops");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ if (len_gt( max_len )) {
|
|
|
|
+ sl_send_reply("513", "Message too large sorry");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # Make sure that requests dont advertise addresses
|
|
|
|
+ # from private IP space (RFC1918) in Contact HF
|
|
|
|
+ # (note: does not match with folded lines)
|
|
|
|
+ if (search("^(Contact|m): .*@(192\.168\.|10\.|172\.16)")) {
|
|
|
|
+ # allow RR-ed requests, as these may indicate that
|
|
|
|
+ # a NAT-enabled proxy takes care of it; unless it is
|
|
|
|
+ # a REGISTER
|
|
|
|
+ if ((method=="REGISTER" || ! search("^Record-Route:"))
|
|
|
|
+ && !( src_ip==192.168.0.0/16 ||
|
|
|
|
+ src_ip==10.0.0.0/8 || src_ip==172.16.0.0/12 )) {
|
|
|
|
+ log("LOG: Someone trying to register from private IP again\n");
|
|
|
|
+ sl_send_reply("479", "We dont accept private IP contacts" );
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ # anti-spam -- if somene claims to belong to our domain in From,
|
|
|
|
+ # challenge him (skip REGISTERs -- we will chalenge them later)
|
|
|
|
+ if (search("(From|F):.*$SER_DOMAIN_TEST_RE")) {
|
|
|
|
+ # invites forwarded to other domains, like FWD may cause subsequent
|
|
|
|
+ # request to come from there but have iptel in From -> verify
|
|
|
|
+ # only INVITEs (ignore FIFO/UAC's requests, i.e. src_ip==myself)
|
|
|
|
+ if (method=="INVITE" & !(src_ip==$SER_IP)) {
|
|
|
|
+ if (!(proxy_authorize( "$SER_DOMAIN" /* realm */,
|
|
|
|
+ "subscriber" /* table name */ ))) {
|
|
|
|
+ proxy_challenge("$SER_DOMAIN" /* realm */, "0" /* no-qop */);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ # to maintain outside credibility of our proxy, we enforce
|
|
|
|
+ # username in From to equal digest username; user with
|
|
|
|
+ # "john.doe" id could advertise "bill.gates" in From otherwise;
|
|
|
|
+ if (!check_from()) {
|
|
|
|
+ log("LOG: From Cheating attempt in INVITE\n");
|
|
|
|
+ sl_send_reply("403", "That is ugly -- use From=id next time (OB)");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ # we better don't consume credentials -- some requests may be
|
|
|
|
+ # spiraled through our server (sfo@iptel->7141@iptel) and the
|
|
|
|
+ # subsequent iteration may challenge too, for example because of
|
|
|
|
+ # iptel claim in From; UACs then give up because they
|
|
|
|
+ # already submitted credentials for the given realm
|
|
|
|
+ #consume_credentials();
|
|
|
|
+ }; # INVITEs claiming to come from our domain
|
|
|
|
+ } else if (method=="INVITE" && !(uri=~"[@:\.]$SER_DOMAIN_TEST_RE([;:].*)*"
|
|
|
|
+ # ... and we serve our gateway too if present
|
|
|
|
+ $SER_GW_TEST_RE )) {
|
|
|
|
+ #the INVITE neither claims to come from our domain nor is it targeted to it
|
|
|
|
+ # -> junk it
|
|
|
|
+ sl_send_reply("403", "No relaying");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* ********* RR ********************************** */
|
|
|
|
+ # to be safe, record route everything; UAs may use different
|
|
|
|
+ # transport protocols and need to have SER in path
|
|
|
|
+ record_route();
|
|
|
|
+ # if route forces us to forward to some explicit destination,
|
|
|
|
+ # do so; check however first that a cheater didn't preload
|
|
|
|
+ # a gateway destination to bypass PSTN ACLs
|
|
|
|
+
|
|
|
|
+ if (loose_route()) {
|
|
|
|
+ `gw_check`
|
|
|
|
+ # route HF determined next hop; forward there
|
|
|
|
+ append_hf("P-hint: rr-enforced\r\n");
|
|
|
|
+ t_relay();
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* ********* check for requests targeted out of our domain... ******* */
|
|
|
|
+ # sign of our domain: there is '@' (username) or : (nothing) in
|
|
|
|
+ # front of our domain name ; ('.' is not there -- we handle all
|
|
|
|
+ # xxx.iptel.org as outbound hosts);if none of these cases matches,
|
|
|
|
+ # proceed with processing of outbound requests in route[2]
|
|
|
|
+ if (!(`mine_check`)) {
|
|
|
|
+ route(2);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* ************ requests for our domain ********** */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* now, the request is for sure for our domain */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # registers always MUST be authenticated to
|
|
|
|
+ # avoid stealing incoming calls
|
|
|
|
+ if (method=="REGISTER") {
|
|
|
|
+
|
|
|
|
+ # Make sure that user's dont register infinite loops
|
|
|
|
+ # (note: does not match with folded lines)
|
|
|
|
+ if (search("^(Contact|m): .*@$SER_DOMAIN_TEST_RE")) {
|
|
|
|
+ log(1, "LOG: alert: someone trying to set aor==contact\n");
|
|
|
|
+ sl_send_reply("476", "No Server Address in Contacts Allowed" );
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ `gw_m_check`
|
|
|
|
+
|
|
|
|
+ if (!www_authorize( "$SER_DOMAIN" /* realm */,
|
|
|
|
+ "subscriber" /* table name */ )) {
|
|
|
|
+ # challenge if none or invalid credentials
|
|
|
|
+ www_challenge( "$SER_DOMAIN" /* realm */,
|
|
|
|
+ "0" /* no qop -- some phones can't deal with it */);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ # prohibit attempts to grab someone else's To address
|
|
|
|
+ # using valid credentials;
|
|
|
|
+
|
|
|
|
+ if (!check_to()) {
|
|
|
|
+ log("LOG: To Cheating attempt\n");
|
|
|
|
+ sl_send_reply("403", "That is ugly -- use To=id in REGISTERs");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ # it is an authenticated request, update Contact database now
|
|
|
|
+ if (!save("location")) {
|
|
|
|
+ sl_reply_error();
|
|
|
|
+ };
|
|
|
|
+ m_dump();
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ # some UACs might be fooled by Contacts our UACs generate to make MSN
|
|
|
|
+ # happy (web-im, e.g.) -- tell its urneachable
|
|
|
|
+ if (uri=~"sip:daemon@" ) {
|
|
|
|
+ sl_send_reply("410", "daemon is gone");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ # is this an ENUM destination (leading +?)? give it a try, if the lookup
|
|
|
|
+ # doesn't change URI, just continue
|
|
|
|
+ if (uri=~"sip:\+[0-9]+@") {
|
|
|
|
+ if (!enum_query("voice")) { # if parameter empty, it defaults to "e2u+sip"
|
|
|
|
+ enum_query(""); # E2U+sip
|
|
|
|
+ };
|
|
|
|
+ } else {
|
|
|
|
+ # aliases (take precedences over PSTN number; provisioning interface
|
|
|
|
+ # is set up to assinge aliases beginning with 8)
|
|
|
|
+ lookup("aliases");
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # check again, if it is still for our domain after aliases are resolved
|
|
|
|
+ if (!(`mine_check`)) {
|
|
|
|
+ route(5);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ `go_to_pstn`
|
|
|
|
+
|
|
|
|
+ # native SIP destinations are handled using our USRLOC DB
|
|
|
|
+ if (!lookup("location")) {
|
|
|
|
+ # handle user which was not found ...
|
|
|
|
+ route(4);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ # check whether some inventive user has uploaded gateway
|
|
|
|
+ # contacts to UsrLoc to bypass our authorization logic
|
|
|
|
+ `gw_check`
|
|
|
|
+
|
|
|
|
+ /* ... and also report on missed calls ... */
|
|
|
|
+ setflag(3);
|
|
|
|
+
|
|
|
|
+ # we now know we may, we know where, let it go out now!
|
|
|
|
+ append_hf("P-hint: USRLOC\r\n");
|
|
|
|
+ if (!t_relay()) {
|
|
|
|
+ sl_reply_error();
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+}
|
|
|
|
+#------------------- OUTBOUND ----------------------------------------
|
|
|
|
+
|
|
|
|
+# routing logic for outbound requests targeted out of our domain
|
|
|
|
+# (keep in mind messages to our users can end up here too: for example,
|
|
|
|
+# an INVITE may be UsrLoc-ed, then the other party uses outbound
|
|
|
|
+# proxy with r-uri=the usr_loced addredd (typically IP))
|
|
|
|
+route[2] {
|
|
|
|
+ append_hf("P-hint: OUTBOUND\r\n");
|
|
|
|
+ t_relay();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#------- ALIASED OUTBOUND --------------------------------------------
|
|
|
|
+
|
|
|
|
+# routing logic for inbound requests aliased outbound; unlike
|
|
|
|
+# with real outbound requests we do not force authentication
|
|
|
|
+# as these calls are server by our server and we do not want
|
|
|
|
+# to disqualify unathenticated request originatiors from other
|
|
|
|
+# domains
|
|
|
|
+route[5] {
|
|
|
|
+ append_hf("P-hint: ALIASED-OUTBOUND\r\n");
|
|
|
|
+ t_relay();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#----------------- PSTN ----------------------------------------------
|
|
|
|
+
|
|
|
|
+# logic for calls to the PSTN
|
|
|
|
+route[3] {
|
|
|
|
+ # turn accounting on
|
|
|
|
+ setflag(1);
|
|
|
|
+
|
|
|
|
+ /* require all who call PSTN to be members of the "int" group;
|
|
|
|
+ apply ACLs only to INVITEs -- we don't need to protect other requests, as they
|
|
|
|
+ don't imply charges; also it could cause troubles when a call comes in via PSTN
|
|
|
|
+ and goes to a party that can't authenticate (voicemail, other domain) -- BYEs would
|
|
|
|
+ fail then; exempt Cisco gateway from authentication by IP address -- it does not
|
|
|
|
+ support digest
|
|
|
|
+ */
|
|
|
|
+ if (method=="INVITE" && (!src_ip==$SER_GWIP)) {
|
|
|
|
+ if (!proxy_authorize( "$SER_DOMAIN" /* realm */,
|
|
|
|
+ "subscriber" /* table name */)) {
|
|
|
|
+ proxy_challenge( "$SER_DOMAIN" /* realm */, "0" /* no qop */ );
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ # let's check from=id ... avoids accounting confusion
|
|
|
|
+ if (method=="INVITE" & !check_from()) {
|
|
|
|
+ log("LOG: From Cheating attempt\n");
|
|
|
|
+ sl_send_reply("403", "That is ugly -- use From=id next time (gw)");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if(!is_user_in("credentials", "int")) {
|
|
|
|
+ sl_send_reply("403", "NO PSTN Privileges...");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ consume_credentials();
|
|
|
|
+
|
|
|
|
+ }; # INVITE to authorized PSTN
|
|
|
|
+
|
|
|
|
+ # if you have passed through all the checks, let your call go to GW!
|
|
|
|
+ rewritehostport("$SER_GWIP:5060");
|
|
|
|
+
|
|
|
|
+ # snom conditioner
|
|
|
|
+ if (method=="INVITE" && search("User-Agent: snom")) {
|
|
|
|
+ replace("100rel, ", "");
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ append_hf("P-hint: GATEWAY\r\n");
|
|
|
|
+ # use UDP to guarantee well-known sender port (TCP ephemeral)
|
|
|
|
+ t_relay_to_udp("$SER_GWIP","5060");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/* *********** handling of unavailable user ******************* */
|
|
|
|
+
|
|
|
|
+route[4] {
|
|
|
|
+/**/
|
|
|
|
+ # message store
|
|
|
|
+ if (method=="MESSAGE") {
|
|
|
|
+ t_newtran();
|
|
|
|
+ if (m_store("0")) {
|
|
|
|
+ t_reply("202", "Accepted for Later Delivery");
|
|
|
|
+ } else {
|
|
|
|
+ t_reply("503", "Service Unavailable");
|
|
|
|
+ };
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+/**/
|
|
|
|
+ # non-Voip -- just send "off-line"
|
|
|
|
+ if (!(method=="INVITE" || method=="ACK" || method=="CANCEL")) {
|
|
|
|
+ sl_send_reply("404", "Not Found");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ # voicemail subscribers ...
|
|
|
|
+ t_newtran();
|
|
|
|
+ t_reply("404", "Not Found");
|
|
|
|
+ # we account missed incoming calls; previous statteful processing
|
|
|
|
+ # guarantees that retransmissions are not accounted
|
|
|
|
+ if (method=="INVITE") {
|
|
|
|
+ acc_db_request("404 missed call", "missed_calls");
|
|
|
|
+ };
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+EOF
|
|
|
|
+
|
|
|
|
+help > /dev/stderr
|