Explorar el Código

Proxy-CSCF Sample Config: Add missing routes (closes Issue #785)

Carsten Bock hace 9 años
padre
commit
180e1db242

+ 231 - 0
examples/pcscf/route/mo.cfg

@@ -0,0 +1,231 @@
+######################################################################
+# Originating, Intial Requests
+######################################################################
+route[MO]
+{
+	# Strip Transport from RURI:
+	$ru = $(ru{re.subst,/;transport=[A-Za-z]*//g});
+
+	# Process route headers, if any:
+	loose_route();
+	if (!pcscf_is_registered("location")) {
+		send_reply("403","Forbidden - You must register first with a S-CSCF");
+		exit;
+	}
+
+	# We do not trust the user, let's remove the P-Asserted-Identity, if any:
+	remove_hf("P-Asserted-Identity");
+	remove_hf("P-Preferred-Identity");
+
+	# Add P-Charging-Vector
+	sip_p_charging_vector("g");
+
+	if (is_present_hf("P-Preferred-Identity") && pcscf_assert_identity("location", "$hdr(P-Preferred-Identity)")) {
+		append_hf("P-Asserted-Identity: $hdr(P-Preferred-Identity)\r\n");
+	} else if (is_present_hf("P-Asserted-Identity") && pcscf_assert_identity("location", "$hdr(P-Asserted-Identity)")) {
+		append_hf("P-Asserted-Identity: $hdr(P-Asserted-Identity)\r\n");
+	} else if (pcscf_assert_identity("location", "$(fu{tobody.uri})")) {
+		append_hf("P-Asserted-Identity: <$(fu{tobody.uri})>\r\n");
+	} else {
+		append_hf("P-Asserted-Identity: <$pcscf_asserted_identity>\r\n");
+	}
+
+	if (!pcscf_follows_service_routes("location")){
+		#Variant 1 - deny access to the network
+		#send_reply("400","Bad Request - Not following indicated service routes");
+		#break;
+
+		#Variant 2 - enforce routes and let the dialog continue
+		pcscf_force_service_routes("location");
+	}
+
+	# add IBCF/THIG route here if required
+	# Check for "sec-agree" in the Require header:
+	if (is_present_hf("Require") && $hdr(Require) =~ ".*sec-agree.*") {
+		# Remove the old Require-Header:
+		remove_hf("Require");
+		# Replace ", sec-agree" with ""
+		$var(new_hdr) = $(hdr(Require){re.subst,/[, ]*sec-agree//gi});
+		if ($(var(new_hdr){s.len}) > 0) {
+			append_hf("Require: $var(new_hdr)\r\n");
+		}
+	}
+
+	# Check for "sec-agree" in the Proxy-Require header:
+	if (is_present_hf("Proxy-Require") && $hdr(Proxy-Require) =~ ".*sec-agree.*") {
+		# Remove the old Proxy-Require-Header:		
+		remove_hf("Proxy-Require");
+		# Replace ", sec-agree" with ""
+		$var(new_hdr) = $(hdr(Proxy-Require){re.subst,/[, ]*sec-agree//gi});
+		if ($(var(new_hdr){s.len}) > 0) {
+			append_hf("Proxy-Require: $var(new_hdr)\r\n");
+		}
+        }
+	remove_hf("Security-Verify");
+
+#!ifdef TRF_FUNCTION
+	$var(trf) = TRF_FUNCTION;
+	# Check for "sec-agree" in the Proxy-Require header:
+	if (is_present_hf("Feature-Caps")) {
+		# Remove the old Proxy-Require-Header:		
+		remove_hf("Feature-Caps");
+		append_hf("Feature-Caps: $hdr(Feature-Caps);+g.3gpp.trf=\"<sip:$var(trf);lr>\"\r\n");
+        } else {
+		append_hf("Feature-Caps: *;+g.3gpp.trf=\"<sip:$var(trf);lr>\"\r\n");
+	}
+#!endif	
+	# Add a visited Network-ID-Header:
+	if (is_present_hf("P-Visited-Network-ID")) {
+		$var(new_hdr) = "NETWORKNAME, "+$hdr(P-Visited-Network-ID);
+		append_hf("P-Visited-Network-ID: $var(new_hdr)\r\n");
+	} else {
+		append_hf("P-Visited-Network-ID: NETWORKNAME\r\n");
+	}
+
+
+	t_on_reply("MO_reply");
+}
+
+######################################################################
+# Replies to Originating Initial Requests
+######################################################################
+onreply_route[MO_reply] {
+	if (is_present_hf("C-Params")) {
+		remove_hf("Contact");
+		remove_hf("C-Params");	
+		append_hf("Contact: $ct;$hdr(C-Params)\r\n");
+	}
+	# In case of 1xx and 2xx do NAT
+	if(status=~"[12][0-9][0-9]")
+		route(NATMANAGE);
+#!ifdef WITH_RX
+        if (t_check_status("183")){
+		xlog("L_DBG", "IMS: Received 183/200 inside orig_initial_reply\n");
+
+		if (t_is_retr_async_reply()) {
+	                xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
+                	drop();
+	        }
+
+		xlog("L_DBG","Diameter: Orig authorizing media via Rx\n");	
+		$avp(FTAG_CUSTOM_AVP)=$ft;
+		$avp(TTAG_CUSTOM_AVP)=$tt;
+		$avp(CALLID_CUSTOM_AVP)=$ci;
+
+		$var(aarret) = Rx_AAR("MO_aar_reply","orig");
+                xlog("L_DBG", "AAR return code is $var(aarret)\n");
+
+		switch ($var(aarret)) {
+			case 1:
+				#suspend was successful and we must break
+	                        xlog("L_DBG", "Success sending AAR for media\n");
+       		                exit;
+
+			case -1:
+				#this is retransmitted response so we just drop it
+	                        xlog("L_DBG", "AAR still processing dropping retransmitted response\n");
+       		                drop();
+                 	       	exit;
+
+			default:
+				xlog("L_ERR", "Unable to send AAR for media\n");
+	                        #comment this if you want to allow even if Rx fails
+				dlg_terminate("all", "Sorry no QoS available");
+       		                exit;
+
+		}
+	}
+
+route[MO_aar_reply]
+{
+        #this is async so to know status we have to check the reply avp
+	switch ($avp(s:aar_return_code)) {
+		case 1:
+			xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); 
+			break;
+		default:
+			xlog("L_ERR", "IMS: AAR failed Orig\n");
+               		xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)");
+	                xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)");
+	                xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)");
+			#comment this if you want to allow even if Rx fails
+	                if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){
+                        	dlg_terminate("all", "Sorry no QoS available");
+                       		exit;
+               		}
+	}
+#!endif
+}
+
+
+######################################################################
+# In-Dialog-Mo-Requests
+######################################################################
+route[MO_indialog] {
+	setflag(FLT_MOBILE_ORIG);
+	t_on_reply("MO_indialog_reply");
+}
+
+onreply_route[MO_indialog_reply] {
+	# In case of 1xx and 2xx do NAT
+	if(status=~"[12][0-9][0-9]")
+		route(NATMANAGE);
+
+#!ifdef WITH_RX
+	if(t_check_status("200") && is_method("INVITE")) {
+		if (t_is_retr_async_reply()) {
+	                xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
+       	         	drop();
+        	}
+
+      		xlog("L_DBG", "IMS: ORIG_SUBSEQUENT reply. This is a 200 OK to a re-INVITE\n");
+		xlog("L_DBG","Diameter: Orig authorizing media via Rx\n");      
+		$avp(FTAG_CUSTOM_AVP)=$ft;
+		$avp(TTAG_CUSTOM_AVP)=$tt;
+		$avp(CALLID_CUSTOM_AVP)=$ci;
+
+		$var(aarret) = Rx_AAR("MO_indialog_aar_reply","orig");
+		xlog("L_DBG", "AAR return code is $var(aarret)\n");
+
+		switch ($var(aarret)) {
+                        case 1:
+                                #suspend was successful and we must break
+                                xlog("L_DBG", "Success sending AAR for media\n");
+                                exit;
+
+                        case -1:
+                                #this is retransmitted response so we just drop it
+                                xlog("L_DBG", "AAR still processing dropping retransmitted response\n");
+                                drop();
+                                exit;
+
+                        default:
+                                xlog("L_ERR", "Unable to send AAR for media\n");
+                                #comment this if you want to allow even if Rx fails
+                                dlg_terminate("all", "Sorry no QoS available");
+                                exit;
+
+                }
+	}
+}
+
+route[MO_indialog_aar_reply]
+{
+        #this is async so to know status we have to check the reply avp
+	switch ($avp(s:aar_return_code)) {
+                case 1:
+                        xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); 
+                        break;
+                default:
+                        xlog("L_ERR", "IMS: AAR failed Orig\n");
+                        xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)");
+                        xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)");
+                        xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)");
+			#comment this if you want to allow even if Rx fails
+                        if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){
+                                dlg_terminate("all", "Sorry no QoS available");
+                                exit;
+                        }
+        }
+#!endif
+}

+ 151 - 0
examples/pcscf/route/mt.cfg

@@ -0,0 +1,151 @@
+######################################################################
+# Terminating, Initial requests
+######################################################################
+route[MT] {
+	t_on_reply("MT_reply");
+}
+
+######################################################################
+# Replies to Originating Initial Requests
+######################################################################
+onreply_route[MT_reply] {
+	if (!strempty($(ct{tobody.params}))) {
+		append_hf("C-Params: $(ct{tobody.params})\r\n");
+	}
+	# In case of 1xx and 2xx do NAT
+	if(status=~"[12][0-9][0-9]")
+		route(NATMANAGE);
+#!ifdef WITH_RX
+        if (t_check_status("183")){
+		xlog("L_DBG", "IMS: Received 183 inside term_initial_reply\n");	
+
+		xlog("L_DBG", "About to test if this is a retransmitted reply which is still currently suspended\n");
+		if (t_is_retr_async_reply()) {
+	                xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
+       		         drop();
+       		}
+
+		xlog("L_DBG","Diameter: Term authorizing media via Rx\n");	
+		$avp(FTAG_CUSTOM_AVP)=$ft;
+		$avp(TTAG_CUSTOM_AVP)=$tt;
+		$avp(CALLID_CUSTOM_AVP)=$ci;
+
+		$var(aarret) = Rx_AAR("MT_aar_reply","term");
+		xlog("L_DBG", "AAR return code is $var(aarret)\n");
+
+		 switch ($var(aarret)) {
+                        case 1:
+                                #suspend was successful and we must break
+                                xlog("L_DBG", "Success sending AAR for media\n");
+                                exit;
+
+                        case -1:
+                                #this is retransmitted response so we just drop it
+                                xlog("L_DBG", "AAR still processing dropping retransmitted response\n");
+                                drop();
+                                exit;
+
+                        default:
+                                xlog("L_ERR", "Unable to send AAR for media\n");
+                                #comment this if you want to allow even if Rx fails
+                                dlg_terminate("all", "Sorry no QoS available");
+                                exit;
+
+                }
+	}
+}
+
+route[MT_aar_reply]
+{
+        xlog("L_DBG", "IMS: TERM_SESSION_AAR_REPLY\n");
+
+        #this is async so to know status we have to check the reply avp        
+	switch ($avp(s:aar_return_code)) {
+                case 1:
+                        xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); 
+                        break;
+                default:
+                        xlog("L_ERR", "IMS: AAR failed Orig\n");
+                        xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)");
+                        xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)");
+                        xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)");
+                        #comment this if you want to allow even if Rx fails
+                        if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){
+                                dlg_terminate("all", "Sorry no QoS available");
+                                exit;
+                        }
+        }
+#!endif
+}
+
+
+######################################################################
+# In-Dialog-MT-Requests
+######################################################################
+route[MT_indialog] {
+	t_on_reply("MT_indialog_reply");
+}
+
+onreply_route[MT_indialog_reply] {
+	# In case of 1xx and 2xx do NAT
+	if(status=~"[12][0-9][0-9]")
+		route(NATMANAGE);
+
+#!ifdef WITH_RX
+	if(t_check_status("200") && is_method("INVITE")) {
+		if (t_is_retr_async_reply()) {
+			xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
+			drop();
+		}
+
+		xlog("L_DBG", "IMS: TERM_SUBSEQUENT reply. This is a 200 OK to a re-INVITE\n");
+		xlog("L_DBG","Diameter: Term authorizing media via Rx\n");      
+		$avp(FTAG_CUSTOM_AVP)=$ft;
+		$avp(TTAG_CUSTOM_AVP)=$tt;
+		$avp(CALLID_CUSTOM_AVP)=$ci;
+
+		$var(aarret) = Rx_AAR("MT_indialog_aar_reply","term");
+		xlog("L_DBG", "AAR return code is $var(aarret)\n");
+
+		switch ($var(aarret)) {
+                        case 1:
+                                #suspend was successful and we must break
+                                xlog("L_DBG", "Success sending AAR for media\n");
+                                exit;
+
+                        case -1:
+                                #this is retransmitted response so we just drop it
+                                xlog("L_DBG", "AAR still processing dropping retransmitted response\n");
+                                drop();
+                                exit;
+
+                        default:
+                                xlog("L_ERR", "Unable to send AAR for media\n");
+                                #comment this if you want to allow even if Rx fails
+                                dlg_terminate("all", "Sorry no QoS available");
+                                exit;
+
+                }
+	}
+}
+
+route[MT_indialog_aar_reply]
+{
+        #this is async so to know status we have to check the reply avp
+	switch ($avp(s:aar_return_code)) {
+                case 1:
+                        xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); 
+                        break;
+                default:
+                        xlog("L_ERR", "IMS: AAR failed Orig\n");
+                        xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)");
+                        xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)");
+                        xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)");
+                        #comment this if you want to allow even if Rx fails
+                        if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){
+                                dlg_terminate("all", "Sorry no QoS available");
+                                exit;
+                        }
+        }
+#!endif
+}

+ 186 - 0
examples/pcscf/route/register.cfg

@@ -0,0 +1,186 @@
+######################################################################
+# Route for handling Registrations:
+######################################################################
+route[REGISTER] {
+	# Provide some statistics
+        if ($sht(a=>$ci::start_time) == $null || $sht(a=>$ci::start_time) == 0) {
+            $sht(a=>$ci::start_time) = $TV(Sn);
+        } 
+
+	# Strip Transport from RURI:
+	$ru = $(ru{re.subst,/;transport=[A-Za-z]*//g});
+
+	if (is_present_hf("Contact")) {
+		pcscf_save_pending("location");
+	} else {
+		send_reply("403", "No contact header");
+		exit;
+	}
+
+
+	# Strip additional Tags from RURI:
+	if ($rU == $null)
+		$ru = "sip:"+$rd;
+	else
+		$ru = "sip:"+$rU+"@"+$rd;
+
+#!ifdef WITH_RX	
+	xlog("L_DBG","Subscribing to signalling bearer status\n");
+
+	Rx_AAR_Register("REG_AAR_REPLY", "location");
+	switch ($retcode) {
+		case -1:
+			# There was an error sending the AAR-Request:
+			xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n");
+			send_reply("403", "Can't register to QoS for signalling");
+			exit;
+			break;
+		case 0:
+			# We are waiting for an async reply, just exit here.
+			exit;
+			break;
+		case 1:
+			# We did not need to send AAR, so just continue as normal
+			route(REGISTER_CONTINUE);
+			break;
+	}
+	exit;
+}
+
+route[REG_AAR_REPLY] {
+	switch ($avp(s:aar_return_code)) {
+		case 1:
+			xlog("L_DBG", "Diameter: AAR success on subscription to signalling\n");
+			break;
+		default:
+			xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n");
+			send_reply("403", "Can't register to QoS for signalling");
+			exit;
+	}
+	# Proceed with Registering:
+	route(REGISTER_CONTINUE);
+}
+
+route[REGISTER_CONTINUE] {
+#!endif
+	append_hf("Path: <sip:term@HOSTNAME;lr>\r\n");
+
+	remove_hf("Supported");
+	append_hf("Supported: path\r\n");
+	remove_hf("Require");
+	append_hf("Require: path\r\n");
+
+	# Add a visited Network-ID-Header:
+	if (is_present_hf("P-Visited-Network-ID")) {
+		$var(new_hdr) = "NETWORKNAME, "+$hdr(P-Visited-Network-ID);
+		append_hf("P-Visited-Network-ID: $var(new_hdr)\r\n");
+	} else {
+		append_hf("P-Visited-Network-ID: NETWORKNAME\r\n");
+	}
+#!ifdef WITH_SBC
+#!ifndef WITH_SBC_CALL
+	t_on_failure("SBC_failure");
+	# Choose an SBC to send the call to:
+	if (!ds_select_dst(DISPATCHER_LIST_SBC, "4")) {
+		send_reply("503", "Service Unavailable (SBC failure)");
+		exit;
+	}
+#!else
+	t_on_failure("REGISTER_failure");
+#!endif
+#!else
+	t_on_failure("REGISTER_failure");
+#!endif
+	t_on_reply("REGISTER_reply");
+	# Forward request:
+	route(RELAY);
+	exit;
+}
+
+# Replies for REGISTER requests:
+######################################################################
+onreply_route[REGISTER_reply]
+{
+#!ifdef WITH_IMS_HDR_CACHE
+	if (is_present_hf("Service-Route")) {
+		$sht(serviceroutes=>$ci) = $hdr(Service-Route);
+	} else {
+		if ($sht(serviceroutes=>$ci) != $null) {
+			append_hf("Service-Route: $sht(serviceroutes=>$ci)\r\n");
+			msg_apply_changes();
+		}
+	}
+	if (is_present_hf("P-Associated-URI")) {
+		$sht(associateduris=>$ci) = $hdr(P-Associated-URI);
+	} else {
+		if ($sht(associateduris=>$ci) != $null) {
+			append_hf("P-Associated-URI: $sht(associateduris=>$ci)\r\n");
+			msg_apply_changes();
+		}
+	}
+#!endif
+
+	if (t_check_status("200")) {
+#!ifdef WITH_IPBLOCK
+		$sht(failedauth=>$T_req($si)) = $null;
+#!endif
+		pcscf_save("location");
+#!ifdef WITH_NATPING
+#!ifdef WITH_PING_UDP
+		if ($T_req($pr) == "udp") {
+			$var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp);
+			$sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri});
+		}
+#!endif
+#!ifdef WITH_PING_TCP
+		if ($T_req($pr) == "tcp") {
+			$var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp)+";transport=tcp";
+			$sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri});
+		}
+#!endif
+#!ifdef WITH_PING_TLS
+		if ($T_req($pr) == "tls") {
+			$var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp)+";transport=tls";
+			$sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri});
+		}
+#!endif
+#!endif
+		#update stats for register reply on success
+        	$var(start_secs) = $(sht(a=>$ci::start_time){s.select,0,.});
+        	$var(start_usecs) = $(sht(a=>$ci::start_time){s.select,1,.});
+        	$var(diff_secs) = $TV(s) - $var(start_secs);
+        	$var(diff_usecs) = $TV(u) - $var(start_usecs);
+        	$var(diff_ms) = $var(diff_secs)*1000 + ($var(diff_usecs)/1000);
+        	$sht(a=>$ci::start_time)=0;
+        	$var(stat_add) = "+" + $var(diff_ms);
+        	xlog("L_DBG", "REGISTER SUCCESS[$ci] took $var(stat_add)ms\n"); 
+        	update_stat("register_success", "+1");
+        	update_stat("register_time", "$var(stat_add)");
+   	}
+	exit;
+}
+
+# Negative replies to REGISTER requests:
+######################################################################
+failure_route[REGISTER_failure]
+{
+#!ifdef WITH_IPBLOCK
+	if (t_check_status("403|[5-6][0-9][0-9]")) {
+		if ($sht(failedauth=>$si) != $null)
+			$sht(failedauth=>$si) = $sht(failedauth=>$si) + 1;
+		else
+			$sht(failedauth=>$si) = 1;
+		if ($sht(failedauth=>$si) > 10) {
+			xlog("L_ALERT","ALERT: blocking $rm from $fu (IP:$si:$sp), more than 5 failed auth requests!\n");
+			xlog("Blocking traffic from $si\n");
+			$sht(ipban=>$si) = 1;
+		}
+                update_stat("register_failed", "+1");
+	}
+#!endif
+	if (t_check_status("408")) {
+		send_reply("504","Server Time-Out");
+                update_stat("register_failed", "+1");
+		exit;
+	}
+}

+ 188 - 0
examples/pcscf/route/rtp.cfg

@@ -0,0 +1,188 @@
+# RTPProxy control
+route[ENC_SRTP] {
+	add_rr_param(";rm=1");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=force SRTP AVP";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+}
+
+route[DEC_SRTP] {
+	add_rr_param(";rm=2");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=force SRTP AVP";
+}
+
+route[ENC_WS_RTP] {
+	add_rr_param(";rm=3");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=force RTP AVPF";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+}
+
+route[DEC_WS_RTP] {
+	add_rr_param(";rm=4");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=force RTP AVPF";
+}
+
+route[ENC_WSS_RTP] {
+	add_rr_param(";rm=5");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=force SRTP AVPF DTLS=passive";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+}
+
+route[DEC_WSS_RTP] {
+	add_rr_param(";rm=6");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=force SRTP AVPF DTLS=passive";
+}
+
+route[ENC_RTP] {
+	add_rr_param(";rm=7");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=force RTP AVP";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+}
+
+route[DEC_RTP] {
+	add_rr_param(";rm=8");
+	$avp(rtpproxy_offer_flags) = "replace-origin replace-session-connection ICE=remove RTP AVP";
+	$avp(rtpproxy_answer_flags) = "replace-origin replace-session-connection ICE=force RTP AVP";
+}
+
+# RTPProxy control
+route[NATMANAGE] {
+#!ifdef WITH_DEBUG
+	if (is_request())
+		xlog("REQUEST: $rm $ru ($si:$sp, $ci)\n");
+	else
+		xlog("REPLY: $rs $rr ($rm, $si:$sp, $ci)\n");
+
+	if (is_direction("downstream"))
+		xlog("    downstream\n");
+	else
+		xlog("    upstream\n");
+
+	xlog("    Offer: $avp(rtpproxy_offer_flags)\n");
+	xlog("    Answer: $avp(rtpproxy_answer_flags)\n");
+	if (isflagset(FLT_MOBILE_ORIG)) {
+		xlog("    mo\n");
+	} else {
+		xlog("    mt\n");
+	}
+#!endif
+	if ((is_reply() && ($T_req($tt) != $null)) || (is_request() && has_totag())) {
+		xlog("L_DBG", "Request had ToTag.");
+		#if((is_request() && !check_route_param("rm=")) || (is_reply() && !isflagset(FLT_RTP))) {
+		if(!check_route_param("rm=") && !isflagset(FLT_RTP)) {
+			xlog("L_DBG", "No RM Param\n");
+			return;
+		}
+		if (is_request()) {
+			if (isflagset(FLT_MOBILE_ORIG) && is_direction("downstream")) {
+				xlog("L_DBG", "1) add_contact_alias();");
+				add_contact_alias();
+			} else if (!isflagset(FLT_MOBILE_ORIG) && is_direction("upstream")) {
+				xlog("L_DBG", "2) add_contact_alias();");
+				add_contact_alias();
+			}
+		} else {
+			if (!isflagset(FLT_MOBILE_ORIG) && is_direction("downstream")) {
+				xlog("L_DBG", "1) ADD_contact_alias();");
+				add_contact_alias();
+			} else if (isflagset(FLT_MOBILE_ORIG) && is_direction("downstream")) {
+				xlog("L_DBG", "2) ADD_contact_alias();");
+				add_contact_alias();
+			}
+		}
+	} else {
+		if (is_reply() && !isflagset(FLT_MOBILE_ORIG)) {
+			xlog("L_DBG", "3) ADD_contact_alias();");
+			add_contact_alias();
+		}
+	}
+
+	if (isflagset(FLT_MOBILE_ORIG)) {
+		$avp(setid) = 1;
+		$avp(extra_id) = "mo";
+	} else {
+		$avp(setid) = 2;
+		$avp(extra_id) = "mt";
+	}
+
+	if(!t_is_set("onreply_route")) t_on_reply("NAT_REPLY");
+	if(!t_is_set("failure_route")) t_on_failure("NATMANAGE");
+
+	if (is_method("BYE") || t_is_failure_route()) {
+		rtpengine_manage();
+		return;
+	}
+
+	setflag(FLT_RTP);
+
+	if (!has_body("application/sdp"))
+		return;
+
+#!ifdef REMOVE_BITALIGNED_AMR
+	route(REMOVE_BITALIGNED);
+#!endif
+
+#!ifndef FORCE_RTPRELAY
+	if (!isflagset(FLT_NAT) || !check_route_param("rm="))
+		return;
+#!endif
+
+	if ((is_reply() && ($T_req($tt) != $null)) || (is_request() && has_totag())) {
+		rtpengine_manage();
+	} else {
+		if ($avp(rtpproxy_offer_flags) == $null)
+			return;
+		if ($avp(rtpproxy_answer_flags) == $null)
+			return;
+
+		if (is_request()) {
+			rtpengine_manage($avp(rtpproxy_offer_flags));		
+		} else {
+			rtpengine_manage($avp(rtpproxy_answer_flags));
+		}
+	}
+}
+
+# manage incoming replies
+onreply_route[NAT_REPLY] {
+	# In case of 1xx and 2xx do NAT
+	if(status=~"[12][0-9][0-9]")
+		route(NATMANAGE);
+}
+
+route[REMOVE_BITALIGNED] {
+	if (sdp_get_line_startswith("$avp(mline)", "m=")) {
+		# xlog("m-line: $avp(mline)\n");
+		sdp_get("$avp(sdp)");
+		# xlog("\n$avp(sdp)\n");
+		$var(x) = -1;
+		$var(remove) = "";
+		$var(codec) = $(avp(mline){s.select,$var(x), });
+		# xlog("$$var(codec) => $var(codec)\n");
+		while ($(var(codec){s.int}) > 0) {
+			# xlog("$var(x)) $$var(codec) => $var(codec)\n");
+			$var(s) = "a=fmtp:"+$var(codec);
+			# xlog("$$var(s) => $var(s)\n");
+			$var(fmtp) = $(avp(sdp){line.sw,$var(s)});
+			# xlog("$$var(fmtp) => $var(fmtp)\n");
+			if ($var(fmtp) =~ "a=fmtp:"+$var(codec)+" mode-change-capability.*") {
+				# xlog("Match: $var(codec)\n");
+				if ($var(remove) == "") {
+					$var(remove) = $var(codec);
+				} else {
+					$var(remove) = $var(remove)+","+$var(codec);
+				}
+			}
+			$var(codec) = $(avp(mline){s.select,$var(x), });
+			$var(x) = $var(x) - 1;
+		}
+		# xlog("$$var(remove) => $var(remove)\n");
+		if ($var(remove) != "") {
+			sdp_remove_codecs_by_id($var(remove), "audio");
+			msg_apply_changes();
+		}
+	}
+}
+

+ 62 - 0
examples/pcscf/route/websocket.cfg

@@ -0,0 +1,62 @@
+event_route[xhttp:request] {
+	set_reply_close();
+	set_reply_no_connect();
+	
+#!ifdef WITH_XMLRPC
+	if ($hu =~ "^/RPC") {
+		route(XMLRPC);
+		exit;
+	}
+#!endif
+
+	if ($Rp != MY_WS_PORT
+#!ifdef WITH_TLS
+	    && $Rp != MY_WSS_PORT
+#!endif
+	) {
+		xlog("L_WARN", "HTTP request received on $Rp\n");
+		xhttp_reply("403", "Forbidden - HTTP request received on $Rp", "", "");
+		exit;
+	}
+
+	if ($hdr(Upgrade)=~"websocket"
+			&&  in_list("Upgrade", $hdr(Connection), ",")
+			&& $rm=~"GET") {
+
+		# Validate Host - make sure the client is using the correct
+		# alias for WebSockets
+		if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
+			xlog("L_WARN", "Bad host $hdr(Host)\n");
+			xhttp_reply("403", "Forbidden - invalid host", "", "");
+			exit;
+		}
+
+#!ifdef WEBSOCKET_WEBSERVER
+		# Validate Origin - make sure the client is from the authorised website
+		if ($hdr(Origin) != "http://"+WEBSOCKET_WEBSERVER
+#!ifdef WITH_TLS
+		  && $hdr(Origin) != "https://"+WEBSOCKET_WEBSERVER
+#!endif
+		) {
+			xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
+			xhttp_reply("403", "Forbidden - invalid website", "", "");
+			exit;
+		}
+#!endif
+
+		# ws_handle_handshake() exits (no further configuration file
+		# processing of the request) when complete.
+		if (ws_handle_handshake()) {
+			# Optional... cache some information about the
+			# successful connection
+			exit;
+		}
+	}
+
+	# xhttp_reply("200", "OK", "text/html", "<html><body>Wrong URL $hu</body></html>");
+	xhttp_reply("404", "Not Found", "", "");
+}
+
+event_route[websocket:closed] {
+	xlog("L_DBG", "WebSocket connection from $si:$sp has closed\n");
+}

+ 27 - 0
examples/pcscf/route/xmlrpc.cfg

@@ -0,0 +1,27 @@
+# XMLRPC routing
+route[XMLRPC] {
+	# allow XMLRPC from localhost
+	if ((method=="POST" || method=="GET")
+#!ifdef XMLRPC_WHITELIST_1
+&& ((src_ip == XMLRPC_WHITELIST_1)
+#!ifdef XMLRPC_WHITELIST_2
+ || (src_ip == XMLRPC_WHITELIST_2)
+#!endif
+#!ifdef XMLRPC_WHITELIST_3
+ || (src_ip == XMLRPC_WHITELIST_3)
+#!endif
+)
+#!endif
+) {
+		# close connection only for xmlrpclib user agents (there is a bug in
+		# xmlrpclib: it waits for EOF before interpreting the response).
+		if ($hdr(User-Agent) =~ "xmlrpclib")
+			set_reply_close();
+		set_reply_no_connect();
+		dispatch_rpc();
+		exit;
+	}
+	send_reply("403", "Forbidden");
+	exit;
+}
+