#
# $Id$
#
# iptel.org real world configuration
#

# ----------- global configuration parameters ------------------------

debug=3          # debug level (cmd line: -dddddddddd)
#fork=yes
fork=no
#log_stderror=no	# (cmd line: -E)
log_stderror=yes	# (cmd line: -E)
check_via=yes     # (cmd. line: -v)
dns=on           # (cmd. line: -r)
rev_dns=yes      # (cmd. line: -R)
#port=5060
port=8060
children=1

# advertise IP address in Via (as opposed to advertising DNS name
# which is annoying for downstream servers and some phones can
# not handle DNS at all)
listen=195.37.77.100

# ------------------ module loading ----------------------------------

loadmodule "../sip_router/modules/sl/sl.so"
loadmodule "../sip_router/modules/print/print.so"
loadmodule "../sip_router/modules/tm/tm.so"
loadmodule "../sip_router/modules/acc/acc.so"
loadmodule "../sip_router/modules/rr/rr.so"
loadmodule "../sip_router/modules/maxfwd/maxfwd.so"
loadmodule "../sip_router/modules/mysql/mysql.so"
loadmodule "../sip_router/modules/usrloc/usrloc.so"
loadmodule "../sip_router/modules/auth/auth.so"
loadmodule "../sip_router/modules/cpl/cpl.so"

# ----------------- setting module-specific parameters ---------------

# -- usrloc params --

modparam("usrloc", "use_database",   1)
modparam("usrloc", "table",          "location")
modparam("usrloc", "user_column",    "user")
modparam("usrloc", "contact_column", "contact")
modparam("usrloc", "expires_column", "expires")
modparam("usrloc", "q_column",       "q")
modparam("usrloc", "callid_column",  "callid")
modparam("usrloc", "cseq_column",    "cseq")
modparam("usrloc", "flush_interval", 60)
modparam("usrloc", "db_url",         "sql://csps:47csps11@dbhost/csps107")

# -- auth params --

modparam("auth", "db_url",        "sql://csps:47csps11@dbhost/csps107")
modparam("auth", "user_column",   "user")
# nonce generation secret; particularly useful if multiple servers
# in a proxy farm are configured to authenticate
modparam("auth", "secret",        "439tg8h349g8hq349t9384hg")
# calculate_ha1=false means password column includes ha1 strings;
# if it was false, plain-text passwords would be assumed
modparam("auth", "calculate_ha1", false)
modparam("auth", "nonce_expire",  300)
modparam("auth", "retry_count",   5)
# password_column, realm_column, group_table, group_user_column,
#   group_group_column are set to their default values
# password_column_2 allows to deal with clients who put domain name
#   in authentication credentials when calculate_ha1=false (if true,
#   it works); if set to a value and USER_DOMAIN_HACK was enabled
#   in defs.h, authentication will still work

# -- acc params --
# report ACKs too for sake of completeness -- as we account PSTN
# destinations which are RR, ACKs should show up
modparam("acc", "report_ack", 1)
# don't bother me with early media reports (I don't like 183 
# too much anyway...ever thought of timer C hitting after
# listening to music-on-hold for five minutes?)
modparam("acc", "early_media", 0)
modparam("acc", "log_level", 1)
# that is the flag for which we will account -- don't forget to
# set the same one :-)
modparam("acc", "acc_flag", 1 )
# we are interested only in succesful transactions
modparam("acc", "failed_transactions", 0 )

# -- tm params --
modparam("tm", "fr_timer", 10 )
modparam("tm", "fr_inv_timer", 30 )

# -------------------------  request routing logic -------------------

# main routing logic

route{

	# filter local stateless ACK generated by authentication of mf replies
	sl_filter_ACK();

	# filter too old messages
	log("Checking maxfwd\n");
	if (!mf_process_maxfwd_header("10")) {
		log("Too many hops\n");
		sl_send_reply("483","Too Many Hops");
		break;
	};

	# Do strict routing if route headers present
	rewriteFromRoute();

	# divert voicemail requests
    if (uri=~"mail\.iptel\.org" | uri=~":5066") {
		log("Request is for voicemail\n");
		sethost("iptel.org");
		t_relay_to("fox.iptel.org", "5066");
		break;
	};

	# if this request is not for our domain, fall over to
	# outbound request processing; include gateway's address
	# in matching too -- we RR requests to it, so that
	# its address may show up in subsequent requests
	# after rewriteFromRoute
	
	if (!(uri=~"[@:]iptel\.org([;:].*)*" 
		| uri=~"[@:]195\.37\.77\.101([;:].*)*" |
		uri=~"@195\.37\.77\.110([;:].*)*" )) {
		route(2);
	};
	# here we continue with requests for our domain...

	# various aliases (might use a database in future)
	if (uri=~"sip:9040@") {
		seturi("jiri@iptel.org");
	};
	if (uri=~"sip:17@") {
		seturi("sip:henry@siptest.wcom.com");
	};
	# check again, if it is still for our domain after aliases
	if ( !(uri=~"[@:]iptel\.org([;:].*)*" | 
		uri=~"[@:]195\.37\.77\.101([;:].*)*" |
		uri=~"@195\.37\.77\.110([;:].*)*" )) {
		route(2);
	};
	log("Request is for iptel.org\n");	

	# registers always MUST be authenticated to
	# avoid stealing incoming calls	
	if (method=="REGISTER") {
		log("Request is REGISTER\n");
		if (!www_authorize(	"iptel.org" /* realm */, 
			 				"subscriber" /* table name */ )) {
			log("REGISTER has no credentials, sending challenge\n");
			www_challenge(	"iptel.org" /* realm */, 
							"0" /* no qop -- M$ can't deal with it */);
			break;
		};
		# prohibit attempts to grab someone else's To address 
		# using  valid credentials
		if (!check_to()) {
			log("To Cheating attempt\n");
			sl_send_reply("403", "That is ugly -- use To=id next time");
			break;
		};
			
		# update Contact database
       	log("REGISTER is authorized, saving location\n");
		save_contact("location");
		break;
	};

	# now check if it's about PSTN destinations through our gateway;
	# note that 8.... is exempted for numerical destinations
	if (uri=~"sip:[0-79][0-9]*@.*") {
		route(3);
	}; 

	# ---------- demo - begin --------------
	/* added by Bogdan for cpl demo - Dorgham request*/
	if (uri=~"sip:test@.*" && method=="INVITE")
	{
		log("SER : runing CPL!! :)\n");
		if ( !cpl_run_script() )
		{
   			log("SER : Error during running CPL script!\n");
		}else{
   			if ( cpl_is_response_reject() ) {
				log("SER: reject");
       			sl_send_reply("603","I am not available!");
       			break;
   			}else if ( cpl_is_response_redirect() ) {
       			log("SER : redirect\n");
       			cpl_update_contact();
       			sl_send_reply("302","Moved temporarily");
       			break;
   			};
		};
	};
	# -------------- demo - end -------------

	# native SIP destinations are handled using our USRLOC DB
	if (!lookup_contact("location")) {
		log("Unable to lookup contact, sending 404\n");
		sl_send_reply("404", "Not Found");
		break;
	};
	# check whether some inventive user has uploaded  gateway 
	# contacts to UsrLoc to bypass our authorization logic
	if (uri=~"@195\.37\.77\.110([;:].*)*" ) {
		log("Weird! Gateway address in UsrLoc!\n");
		route(3);
	};

	# requests from gateway should be RR-ed too
	if (src_ip==195.37.77.110 && method=="INVITE")  {
		addRecordRoute();
	};

	# we now know we may, we know where, let it go out now!
	t_relay();
}

# routing logic for outbound requests targeted out of our domain
route[2] {
		# outbound requests are allowed only for our users -- we don't
		# support relaying and don't like strangers bothering us
		# with resolving DNS
		log("that's a request to outside");
		if (!(src_ip==195.37.77.110) & 
			!(proxy_authorize(	"iptel.org" /* realm */,
							"subscriber" /* table name */ ))) {
			# see comments bellow on these ACK/CANCEL exceptions
			if (method=="ACK" ) {
				log("failed outbound authentication for ACK granted");
			} else if (method=="CANCEL") {
				log("failed outbound authentication for ACK granted");
			} else proxy_challenge("iptel.org" /* realm */, "0" /* no-qop */);
			break;
		};
		# to maintain credibility of our proxy, we check From to be
		# equal of credential id -- all outbound request leaving our
		# proxy are guaranteed to be generated by persons in "From"
		if (!check_from()) {
			log("From Cheating attempt\n");
			sl_send_reply("403", "That is ugly -- use From=id next time");
			break;
		};

		t_relay();
}

# logic for calls through our PSTN gateway
route[3] {
	# free call destinations ... no authentication needed
	if (uri=~"sip:001795061546@.*" | uri=~"sip:0016097265544.*" 
		| uri=~"sip:[79][0-9][0-9][0-9]@.*") {
		log("Free PSTN\n");
	} else {
		# all other PSTN destinations only for authenticated users
		# (Cisco GW, which has no digest support, is authenticated
		# by its IP address -- that's for sure not very strong;
		# wth confirmed that we filter packets coming from outside
		# and bearing SRC IP address of our network)
		if (!(src_ip==195.37.77.110) & 
			!(proxy_authorize(	"iptel.org" /* realm */,
								"subscriber" /* table name */)))  {
			# we are forgiving and ignore improper credentials
			# for ACK/CANCEL as bis-09 is somewhat cryptic about
			# its use and many UACs have not gotten it right
			if (method=="ACK" ) {
				log("failed gw authentication for ACK granted");
			} else if (method=="CANCEL") {
				log("failed gw authentication for ACK granted");
			} else proxy_challenge(	"iptel.org" /* realm */, 
									"0" /* no qop */ );
			break;
		};
		
		# authorize only for INVITEs -- RR/Contact may result in weird
		# things showing up in d-uri that would break our logic; our
		# major concern is INVITE which causes PSTN costs anyway

		if (method=="INVITE") {

			# does the authenticated user have a permission for local
			# calls? (i.e., is he in the "local" group?)
			if (uri=~"sip:0[1-9][0-9]+@.*") {
				if (!is_in_group("local")) {
					sl_send_reply("403", "Local Toodle Noodle...");
					break;
				};
			# the same for long-distance
			} else if (uri=~"sip:00[1-9][0-9]+@.*") {
				if (uri=~"sip:001[089]" | uri=~"sip:00900.*" ) {
					sl_send_reply("403", "Added Value Destinations not permitted...");
					break;
				};
				if (!is_in_group("ld")) {
					sl_send_reply("403", "LD Toodle Noodle...");
					break;
				};
			# the same for international calls
			} else if (uri=~"sip:000[1-9][0-9]+@.*") {
				if (!is_in_group("int")) {
					sl_send_reply("403", "International Toodle Noodle...");
					break;
				};
			# everything else (e.g., interplanetary calls) is denied
			} else {
				sl_send_reply("403", "interplanetary Toodle Noodle...");
				break;
			};

		}; # INVITE to authorized PSTN

	}; # authorized PSTN

	# requests to gateway must be record-route because the GW accepts
	# only reqeusts coming from our proxy
	if (method=="INVITE")
		addRecordRoute();

	# if you have passed through all the checks, let your call go to GW!
	rewritehostport("195.37.77.110:5060");

	# tag this transaction for accounting
	setflag(1);

	t_relay();
}