Initial commit

Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_sip/CMakeLists.txt b/extensions/app_sip/CMakeLists.txt
new file mode 100644
index 0000000..8bd89d1
--- /dev/null
+++ b/extensions/app_sip/CMakeLists.txt
@@ -0,0 +1,47 @@
+# The app_sip extension
+PROJECT("Diameter SIP Application (RFC4740)" C)
+
+FIND_PACKAGE(MySQL REQUIRED)
+INCLUDE_DIRECTORIES(${MySQL_INCLUDE_DIR}) 
+
+# Parser files
+BISON_FILE(app_sip.y)
+FLEX_FILE(app_sip.l)
+SET_SOURCE_FILES_PROPERTIES(lex.app_sip.c app_sip.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( DIAM_SIP_SRC
+	lex.app_sip.c
+	app_sip.tab.c
+	app_sip.tab.h
+	app_sip.c
+	app_sip.h
+	libapp_sip.c
+	md5.c
+	multimediaauth.c
+	registrationtermination.c
+	userauthorization.c
+	pushprofile.c
+	serverassignment.c
+	locationinfo.c
+	locationinfosl.c
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(app_sip ${DIAM_SIP_SRC})
+
+TARGET_LINK_LIBRARIES(app_sip ${MySQL_LIBRARIES})
+
+SUBDIRS(tools)
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_sip
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-sip-server)
+
+INSTALL(FILES README TODO
+	DESTINATION /usr/share/doc/freeDiameter-sip-server
+	CONFIGURATIONS DebianPackage 
+	COMPONENT freeDiameter-sip-server)
diff --git a/extensions/app_sip/README b/extensions/app_sip/README
new file mode 100644
index 0000000..fbc5536
--- /dev/null
+++ b/extensions/app_sip/README
@@ -0,0 +1,39 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+Diameter-SIP Application will be fully compliant with RFC4740 (server part). However, there is still some work to do so it should be considered as experimental for now.
+
diff --git a/extensions/app_sip/TODO b/extensions/app_sip/TODO
new file mode 100644
index 0000000..661face
--- /dev/null
+++ b/extensions/app_sip/TODO
@@ -0,0 +1,57 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+Diameter-SIP implementation is still under development. 
+
+TODO List
+* add in malloc the size of char
+* when getting results from mysql, check lenght
+* sort capabilities in LIR/LIA
+* make functions for database access in MAR/MAA
+* order diamsip.h because it's becoming a mess ^^
+* replace password in MAR/MAA and libdiamsip from table to malloc char!
+* display errors of mysql
+* check that all user data inserted in requests are purified
+* add accounting server uri in database and diamsip
+* add mutex on mysql writing
+* check multithreading of mysql!
+* get destination host in database for RTR and PPR
+
+
+
+
+
+
diff --git a/extensions/app_sip/app_sip.c b/extensions/app_sip/app_sip.c
new file mode 100644
index 0000000..dfabdcc
--- /dev/null
+++ b/extensions/app_sip/app_sip.c
@@ -0,0 +1,252 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+//Diameter-SIP server
+struct disp_hdl * app_sip_MAR_hdl=NULL;
+struct disp_hdl * app_sip_LIR_hdl=NULL;
+struct disp_hdl * app_sip_UAR_hdl=NULL;
+struct disp_hdl * app_sip_SAR_hdl=NULL;
+struct disp_hdl * app_sip_PPA_hdl=NULL;
+struct disp_hdl * app_sip_RTA_hdl=NULL;
+
+//Suscriber Locator
+struct disp_hdl * app_sip_SL_LIR_hdl=NULL;
+
+
+
+struct disp_hdl * app_sip_default_hdl=NULL;
+struct session_handler * ds_sess_hdl;
+
+//configuration stucture
+struct as_conf * as_conf=NULL;
+static struct as_conf app_sip_conf;
+
+//dictionary of SIP
+struct app_sip_dict sip_dict;
+
+int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p %p", msg, avp, sess, opaque, act);
+	
+	return 0;
+}
+
+void dump_config()
+{
+	TRACE_DEBUG(FULL,"***Configuration of Diameter-SIP extension***");
+	TRACE_DEBUG(FULL,"# mode: *%d*",as_conf->mode);
+	TRACE_DEBUG(FULL,"# datasource: *%d*",as_conf->datasource);
+	TRACE_DEBUG(FULL,"# mysql_login: *%s*",as_conf->mysql_login);
+	TRACE_DEBUG(FULL,"# mysql_password: *%s*",as_conf->mysql_password);
+	TRACE_DEBUG(FULL,"# mysql_database: *%s*",as_conf->mysql_database);
+	TRACE_DEBUG(FULL,"# mysql_server: *%s*",as_conf->mysql_server);
+	TRACE_DEBUG(FULL,"# mysql_port: *%d*",as_conf->mysql_port);
+	TRACE_DEBUG(FULL,"# mysql_port: *%s*",as_conf->mysql_prefix);
+	TRACE_DEBUG(FULL,"***End of Diameter-SIP configuration extension***");
+}
+
+static int as_conf_init(void)
+{
+	as_conf=&app_sip_conf;
+	//memset(app_sip_conf, 0, sizeof(struct as_conf));
+	
+
+	return 0;
+}
+
+/* entry point */
+int as_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	struct dict_object * app=NULL;
+	struct disp_when data;
+	pthread_t rtr_thread, ppr_thread;
+	
+	/* Initialize configuration */
+	CHECK_FCT( as_conf_init() );
+	
+	
+	//We parse the configuration file
+	if (conffile != NULL) {
+		CHECK_FCT( as_conf_handle(conffile) );
+	}
+	else
+	{
+		TRACE_DEBUG(INFO, "We need a configuration file for Diameter-SIP extension. See doc/ for an example.");
+	}
+	
+	//TODO: replace by configuration file!!
+	strcpy(as_conf->mysql_prefix,"as_");
+	
+	//We can dump the configuration extracted from app_sip.conf
+	//dump_config();
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) );
+	
+	
+	
+	//We set useful AVPs 
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Session-State", &sip_dict.Auth_Session_State, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &sip_dict.Auth_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &sip_dict.Destination_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &sip_dict.Destination_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sip_dict.Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host", &sip_dict.Redirect_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host-Usage", &sip_dict.Redirect_Host_Usage, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Auth-Data-Item", &sip_dict.SIP_Auth_Data_Item, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authorization", &sip_dict.SIP_Authorization, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authenticate", &sip_dict.SIP_Authenticate, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Number-Auth-Items", &sip_dict.SIP_Number_Auth_Items, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Scheme", &sip_dict.SIP_Authentication_Scheme, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Info", &sip_dict.SIP_Authentication_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-URI", &sip_dict.SIP_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-Capabilities", &sip_dict.SIP_Server_Capabilities, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Mandatory-Capability", &sip_dict.SIP_Mandatory_Capability, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Optional-Capability", &sip_dict.SIP_Optional_Capability, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Method", &sip_dict.SIP_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-AOR", &sip_dict.SIP_AOR, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Deregistration-Reason", &sip_dict.SIP_Deregistration_Reason, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Code", &sip_dict.SIP_Reason_Code, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Info", &sip_dict.SIP_Reason_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Accounting-Information", &sip_dict.SIP_Accounting_Information, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Accounting-Server-URI", &sip_dict.SIP_Accounting_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Credit-Control-Server-URI", &sip_dict.SIP_Credit_Control_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-Assignment-Type", &sip_dict.SIP_Server_Assignment_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Item-Number", &sip_dict.SIP_Item_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Authorization-Type", &sip_dict.SIP_User_Authorization_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Supported-User-Data-Type", &sip_dict.SIP_Supported_User_Data_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data", &sip_dict.SIP_User_Data, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Type", &sip_dict.SIP_User_Data_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Contents", &sip_dict.SIP_User_Data_Contents, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Already-Available", &sip_dict.SIP_User_Data_Already_Available, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Visited-Network-Id", &sip_dict.SIP_Visited_Network_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-URI", &sip_dict.Digest_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce", &sip_dict.Digest_Nonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-CNonce", &sip_dict.Digest_CNonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Method", &sip_dict.Digest_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce-Count", &sip_dict.Digest_Nonce_Count, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response", &sip_dict.Digest_Response, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response-Auth", &sip_dict.Digest_Response_Auth, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Username", &sip_dict.Digest_Username, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Algorithm", &sip_dict.Digest_Algorithm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-QoP", &sip_dict.Digest_QOP, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &sip_dict.User_Name, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-HA1", &sip_dict.Digest_HA1, ENOENT) );
+	
+	
+	//Register Application
+	memset(&data, 0, sizeof(data));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &data.app, ENOENT) );
+	
+	if(as_conf->mode==1)
+	{
+	  // **Command Codes
+	  //MAR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_MAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_MAR_hdl ) );
+	  //RTA
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Answer", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_RTA_cb, DISP_HOW_CC, &data, NULL, &app_sip_RTA_hdl ) );
+	  //PPA
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Push-Profile-Answer", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_PPA_cb, DISP_HOW_CC, &data, NULL, &app_sip_PPA_hdl ) );
+	  //LIR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_LIR_cb, DISP_HOW_CC, &data, NULL, &app_sip_LIR_hdl ) );
+	  //UAR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_UAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_UAR_hdl ) );
+	  //SAR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_SAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_SAR_hdl ) );
+	}
+	if(as_conf->mode==2)
+	{
+	  //LIR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_SL_LIR_cb, DISP_HOW_CC, &data, NULL, &app_sip_SL_LIR_hdl ) );
+	}
+	//Callback for unexpected messages
+	CHECK_FCT( fd_disp_register( app_sip_default_cb, DISP_HOW_APPID, &data, NULL, &app_sip_default_hdl ) );
+	
+	
+	//We start database connection
+	if(start_mysql_connection())
+		return EINVAL;
+	
+	CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, (void *)free, NULL, NULL));
+	
+	//Creation of thread for Registration Termination	
+	if(pthread_create(&rtr_thread, NULL,rtr_socket, NULL))
+	{
+		TRACE_DEBUG(INFO,"Creation of thread failed, abort!");
+		return EINVAL;
+	}
+	//Creation of thread for Push Profile	
+	if(pthread_create(&ppr_thread, NULL,ppr_socket, NULL))
+	{
+		TRACE_DEBUG(INFO,"Creation of thread failed, abort!");
+		return EINVAL;
+	}
+	
+	
+	return 0;
+}
+
+//Cleanup callback
+void fd_ext_fini(void)
+{
+	//TODO:unregister other callbacks
+	
+	(void) fd_disp_unregister(&app_sip_MAR_hdl, NULL);
+	CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl, NULL),return);
+	
+	
+	//We close database connection
+	close_mysql_connection();
+	
+
+	
+	TRACE_ENTRY();
+	return ;
+}
+
+EXTENSION_ENTRY("app_sip", as_entry, "dict_sip");
diff --git a/extensions/app_sip/app_sip.h b/extensions/app_sip/app_sip.h
new file mode 100644
index 0000000..a6532b7
--- /dev/null
+++ b/extensions/app_sip/app_sip.h
@@ -0,0 +1,266 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freesipserver.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include <freeDiameter/extension.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <string.h>
+#include <mysql.h>
+#include "md5.h"
+
+
+#define NONCE_SIZE 16
+#define DIGEST_LEN 16
+
+
+/* Mode for the extension */
+#define MODE_DSSERVER	0x1
+#define	MODE_SL	0x2
+
+//Redirect_Host_Usage
+#define ALL_USER	6
+
+/* The module configuration */
+struct as_conf {
+	int		mode;		/* default MODE_DSSERVER | MODE_SL */
+	enum {ASMYSQL} datasource; 
+	char * mysql_login;
+	char * mysql_password;
+	char * mysql_database;
+	char * mysql_server;
+	char mysql_prefix[10]; //default: as_
+	uint16_t  mysql_port; //if 0, default port will be used
+	uint16_t rtr_port;
+	uint16_t ppr_port;
+};
+extern struct as_conf * as_conf;
+
+/* Parse the configuration file */
+int as_conf_handle(char * conffile);
+
+
+extern MYSQL *conn;
+
+
+
+void calc_md5(char *buffer, char * data);
+void clear_digest(uint8_t * digest, char * readable_digest, int digestlength);
+struct avp_hdr * walk_digest(struct avp *avp, int avp_code);
+
+
+//MySQL part
+int start_mysql_connection();
+void request_mysql(char *query);
+void close_mysql_connection();
+int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen);
+int exist_username(const unsigned char *sip_aor, const size_t sipaorlen);
+int get_sipserver_cap(const unsigned char *sip_aor, const size_t sipaorlen, struct avp **capabilities);
+int get_password(const unsigned char *username, const size_t usernamelen, char *password);
+int check_sipaor(const unsigned char  *username, const size_t usernamelen, const char * sip_aor,const size_t sipaorlen);
+int add_user_datatype(const unsigned char  *sip_aor, const size_t sipaorlen,struct msg *message);
+int set_pending_flag(const unsigned char  *username, const size_t usernamelen);
+int clear_pending_flag(const unsigned char  *username, const size_t usernamelen);
+int set_real_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen);
+int set_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen);
+//int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen);
+int allow_roaming(const unsigned char  *username, const size_t usernamelen, const char * network,const size_t networklen);
+int get_diameter_uri(const unsigned char *sip_aor, const size_t sipaorlen, char ** diameter_uri, size_t *diameterurilen);
+//count functions
+int count_avp(struct msg * message, int code, int vendor);
+
+
+void DigestCalcHA1(char * pszAlg,char * pszUserName,char * pszRealm,char * pszPassword,char * pszNonce,char * pszCNonce,HASHHEX SessionKey);
+void DigestCalcResponse(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response);
+void DigestCalcResponseAuth(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response);
+
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp );
+
+//thread procedure
+void *rtr_socket(void *);
+void *ppr_socket(void *);
+
+struct rtrsipaor
+{
+	char username[200];
+	char sip_aor1[200];
+	char sip_aor2[200];
+	char sip_aor3[200];
+	char strreason[200];
+	char desthost[200];
+	int reason;
+};
+struct pprsipaor
+{
+	char username[200];
+	char datatype1[255];
+	char datatype2[255];
+	char datatype3[255];
+	int accounting;
+};
+
+int app_sip_RTR_cb(struct rtrsipaor *structure);
+int app_sip_PPR_cb(struct pprsipaor *structure);
+
+
+int ds_entry();
+void fd_ext_fini(void);
+int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_MAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_RTA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_PPA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_LIR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_UAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_SAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+
+//Suscriber Locator
+int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act);
+//int app_sip_SL_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act);
+
+#define SQL_GETPASSWORD "SELECT `password` FROM ds_users WHERE `username` ='%s'"
+#define SQL_GETPASSWORD_LEN sizeof(SQL_GETPASSWORD)-2
+
+//username by SIP-AOR
+#define SQL_GETUSERNAME  "SELECT `username` FROM ds_users, ds_sip_aor WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_user` = `ds_users`.`id_user`"
+#define SQL_GETUSERNAME_LEN sizeof(SQL_GETUSERNAME)-2
+
+//sip server uri by username
+#define SQL_GETSIPURI  "SELECT `sip_server_uri` FROM ds_users WHERE `username` ='%s'"
+#define SQL_GETSIPURI_LEN sizeof(SQL_GETSIPURI)-2
+
+//sip server uri by SIP-AOR
+#define SQL_GETSIPSERURI  "SELECT `ds_sip_aor`.`sip_server_uri` FROM ds_users, ds_sip_aor WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_user` = `ds_users`.`id_user`"
+#define SQL_GETSIPSERURI_LEN sizeof(SQL_GETSIPSERURI)-2
+
+//sip capabilities for a SIP-AOR
+#define SQL_GETSIPSERCAP  "SELECT `compulsory`,`id_service` FROM ds_user_services, ds_sip_aor WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_user` = `ds_user_services`.`id_user`"
+#define SQL_GETSIPSERCAP_LEN sizeof(SQL_GETSIPSERCAP)-2
+
+//user data for a user data supported
+#define SQL_GETSIPDATA  "SELECT `label_type`,`data` FROM ds_sip_aor, ds_user_data, ds_data_types WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_sip_aor` = `ds_user_data`.`id_sip_aor` AND `ds_data_types`.`id_data_type`=`ds_user_data`.`id_data_type`"
+#define SQL_GETSIPDATA_LEN sizeof(SQL_GETSIPDATA)-2
+
+#define SQL_GETDIAMURI "SELECT `sipserver_uri` FROM ds_sip_aor_map WHERE `sip_aor` ='%s'"
+#define SQL_GETDIAMURI_LEN sizeof(SQL_GETDIAMURI)-2
+
+//networks for this user
+#define SQL_GETUSERNET "SELECT `label_network` FROM ds_users, ds_user_networks, ds_networks WHERE `ds_users`.`username` ='%s' AND `ds_user_networks`.`id_user` = `ds_users`.`id_user` AND `ds_user_networks`.`id_network` = `ds_networks`.`id_network`"
+#define SQL_GETUSERNET_LEN sizeof(SQL_GETUSERNET)-2
+
+#define SQL_SETSIPURI "UPDATE ds_users SET `temp_sip_server_uri`='%s' WHERE `username` ='%s'"
+#define SQL_SETSIPURI_LEN sizeof(SQL_SETSIPURI)-4
+
+//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 
+#define SQL_RMSIPURI "UPDATE ds_users SET `temp_sip_server_uri`='', `sip_server_uri`='' WHERE `id_user` ='%s'"
+#define SQL_RMSIPURI_LEN sizeof(SQL_RMSIPURI)-2
+//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 
+
+#define SQL_SETREALSIPURI "UPDATE ds_users SET `sip_server_uri`='%s' WHERE `username` ='%s'"
+#define SQL_SETREALSIPURI_LEN sizeof(SQL_SETREALSIPURI)-4
+
+#define SQL_SETFLAG "UPDATE ds_users SET `authentication_pending`=1 WHERE `username` ='%s'"
+#define SQL_SETFLAG_LEN sizeof(SQL_SETFLAG)-2
+
+#define SQL_CLEARFLAG "UPDATE ds_users SET `authentication_pending`=0, `registrated`=1 WHERE `username` ='%s'"
+#define SQL_CLEARFLAG_LEN sizeof(SQL_CLEARFLAG)-2
+
+#define SQL_GETSIPAOR "SELECT `sip_aor` FROM `ds_sip_aor`, `ds_users` WHERE `ds_sip_aor`.`id_user` = `ds_users`.`id_user` AND `ds_users`.`username` = '%s'"
+#define SQL_GETSIPAOR_LEN sizeof(SQL_GETSIPAOR)-2
+
+//#define SQL_CLEARFLAG "UPDATE ds_users SET `authentication_pending`=0 WHERE `username` ='%s'"
+//#define SQL_CLEARFLAG_LEN 67
+
+extern struct session_handler * ds_sess_hdl;
+
+//AVP code
+#define CODE_SIP_USER_DATA_TYPE	388
+#define CODE_SIP_AOR	122
+
+//Storage for some useful AVPs
+struct app_sip_dict{
+	struct dict_object * Auth_Session_State;
+	struct dict_object * Auth_Application_Id;
+	struct dict_object * Destination_Host;
+	struct dict_object * Destination_Realm;
+	struct dict_object * User_Name;
+	struct dict_object * Session_Id;
+	struct dict_object * Redirect_Host;
+	struct dict_object * Redirect_Host_Usage;
+	struct dict_object * SIP_Auth_Data_Item;
+	struct dict_object * SIP_Accounting_Information;
+	struct dict_object * SIP_Accounting_Server_URI;
+	struct dict_object * SIP_Credit_Control_Server_URI;
+	struct dict_object * SIP_Server_Assignment_Type;
+	struct dict_object * SIP_Item_Number;
+	struct dict_object * SIP_User_Authorization_Type;
+	struct dict_object * SIP_Supported_User_Data_Type;
+	struct dict_object * SIP_User_Data;
+	struct dict_object * SIP_User_Data_Type;
+	struct dict_object * SIP_User_Data_Contents;
+	struct dict_object * SIP_User_Data_Already_Available;
+	struct dict_object * SIP_Visited_Network_Id;
+	struct dict_object * SIP_Authorization;
+	struct dict_object * SIP_Authenticate;
+	struct dict_object * SIP_Number_Auth_Items;	
+	struct dict_object * SIP_Authentication_Scheme;
+	struct dict_object * SIP_Authentication_Info;	
+	struct dict_object * SIP_Server_URI;
+	struct dict_object * SIP_Server_Capabilities;
+	struct dict_object * SIP_Mandatory_Capability;
+	struct dict_object * SIP_Optional_Capability;
+	struct dict_object * SIP_Method;
+	struct dict_object * SIP_AOR;
+	struct dict_object * SIP_Deregistration_Reason;
+	struct dict_object * SIP_Reason_Code;
+	struct dict_object * SIP_Reason_Info;
+	struct dict_object * Digest_URI;		
+	struct dict_object * Digest_Nonce;
+	struct dict_object * Digest_Nonce_Count;
+	struct dict_object * Digest_CNonce;		
+	struct dict_object * Digest_Realm;		
+	struct dict_object * Digest_Response;	
+	struct dict_object * Digest_Response_Auth;	
+	struct dict_object * Digest_Username;	
+	struct dict_object * Digest_Method;
+	struct dict_object * Digest_QOP;	
+	struct dict_object * Digest_Algorithm;
+	struct dict_object * Digest_HA1;
+};
+
+extern  struct app_sip_dict  sip_dict;
diff --git a/extensions/app_sip/app_sip.l b/extensions/app_sip/app_sip.l
new file mode 100644
index 0000000..f8e9044
--- /dev/null
+++ b/extensions/app_sip/app_sip.l
@@ -0,0 +1,162 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on ta_conf.l (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+
+%{
+#include "app_sip.h"
+/* Include yacc tokens definitions */
+#include "app_sip.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+	/* Recognize quoted strings -- we do not support escaped \" in the string currently. */
+\"[^\"]+\"		{
+				/* Match a quoted string. Let's be very permissive. */
+				yylval->string = strdup(yytext+1);
+				if (!yylval->string) {
+					fd_log_debug("Unable to copy the string '%s': %s", yytext, strerror(errno));
+					TRACE_DEBUG(INFO, "strdup failed");
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+
+
+
+	/* Recognize the tokens */	
+(?i:"mysql_login")	{
+				return ASMYSQL_LOGIN;
+			}
+
+(?i:"mysql_password")		{
+				return ASMYSQL_PASSWORD;
+			}
+
+(?i:"mysql_database")		{
+				return ASMYSQL_DATABASE;
+			}
+
+(?i:"mysql_server")		{
+				return ASMYSQL_SERVER;
+			}
+
+(?i:"mysql_port")		{
+				return ASMYSQL_PORT;
+			}
+(?i:"rtr_port")		{
+				return RTR_PORT;
+			}
+(?i:"ppr_port")		{
+				return PPR_PORT;
+			}
+(?i:"mode")		{
+				return MODE;
+			}
+
+(?i:"datasource")		{
+				return DATASOURCE;
+			}
+			
+(?i:"mysql")		{
+				yylval->integer = ASMYSQL;
+				return INTEGER;
+			}
+(?i:"dsserver")		{
+				yylval->integer = MODE_DSSERVER;
+				return INTEGER;
+			}
+
+(?i:"sl")	{
+				yylval->integer = MODE_SL;
+				return INTEGER;
+			}
+
+
+			
+	/* Valid single characters for yyparse */
+[=;]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]"*=>;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/app_sip/app_sip.y b/extensions/app_sip/app_sip.y
new file mode 100644
index 0000000..6c288a4
--- /dev/null
+++ b/extensions/app_sip/app_sip.y
@@ -0,0 +1,208 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on ta_conf.y  (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "app_sip.h"
+#include "app_sip.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int as_conf_handle(char * conffile)
+{
+	extern FILE * app_sipin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	app_sipin = fopen(conffile, "r");
+	if (app_sipin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(app_sipin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int app_siplex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;		/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Key words */
+%token 		MODE
+%token 		DATASOURCE
+%token 		ASMYSQL_LOGIN
+%token 		ASMYSQL_PASSWORD
+%token 		ASMYSQL_DATABASE
+%token 		ASMYSQL_SERVER
+%token 		ASMYSQL_PORT
+%token 		RTR_PORT
+%token 		PPR_PORT
+
+/* Tokens and types for routing table definition */
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile mode
+			| conffile datasource
+			| conffile mysql_login
+			| conffile mysql_password
+			| conffile mysql_database
+			| conffile mysql_server
+			| conffile mysql_port
+			| conffile rtr_port
+			| conffile ppr_port
+			;
+
+mode:			MODE '=' INTEGER ';'
+			{
+				as_conf->mode = $3;
+			}
+			;
+
+datasource:			DATASOURCE '=' INTEGER ';'
+			{
+				as_conf->datasource = $3;
+			}
+			;
+
+mysql_login:			ASMYSQL_LOGIN '=' QSTRING ';'
+			{
+				free(as_conf->mysql_login);
+				as_conf->mysql_login = $3;
+			}
+			;
+
+mysql_password:			ASMYSQL_PASSWORD '=' QSTRING ';'
+			{
+				free(as_conf->mysql_password);
+				as_conf->mysql_password = $3;
+			}
+			;
+
+mysql_database:			ASMYSQL_DATABASE '=' QSTRING ';'
+			{
+				free(as_conf->mysql_database);
+				as_conf->mysql_database = $3;
+			}
+			;
+
+mysql_server:		ASMYSQL_SERVER '=' QSTRING ';'
+			{
+				free(as_conf->mysql_server);
+				as_conf->mysql_server = $3;
+			}
+			;
+
+mysql_port:		ASMYSQL_PORT '=' INTEGER ';'
+			{
+				as_conf->mysql_port = (uint16_t)$3;
+			}
+			;
+rtr_port:		RTR_PORT '=' INTEGER ';'
+			{
+				as_conf->rtr_port = (uint16_t)$3;
+			}
+			;
+ppr_port:		PPR_PORT '=' INTEGER ';'
+			{
+				as_conf->ppr_port = (uint16_t)$3;
+			}
+			;
diff --git a/extensions/app_sip/libapp_sip.c b/extensions/app_sip/libapp_sip.c
new file mode 100644
index 0000000..6442ff4
--- /dev/null
+++ b/extensions/app_sip/libapp_sip.c
@@ -0,0 +1,1078 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+//#include <mysql.h>
+#include "app_sip.h"
+
+MYSQL *conn;
+
+void clear_digest(uint8_t * digest, char * readable_digest, int digestlength)
+{
+	int i=0;
+	for(i=0;i<digestlength * 2;i++)
+		sprintf(&readable_digest[2 * i], "%2.2hhx", digest[i]);
+	readable_digest[2 * digestlength]='\0';
+	
+	return;
+}
+
+// You must create a table like this "char  clearDigest[DIGEST_LEN*2+1];"
+void calc_md5(char *clearDigest, char * data)
+{
+	gcry_md_hd_t md5;
+	uint8_t * binDigest=NULL;
+	
+	CHECK_MALLOC_DO(binDigest=malloc(DIGEST_LEN),return);
+	
+	gcry_md_open(&md5,GCRY_MD_MD5, 0); 
+	gcry_md_write(md5, (char *)data, sizeof(data));
+	memcpy(binDigest, gcry_md_read(md5,  GCRY_MD_MD5),gcry_md_get_algo_dlen(GCRY_MD_MD5));
+	gcry_md_close(md5);
+	
+	clear_digest(binDigest, clearDigest, DIGEST_LEN);
+	free(binDigest);
+	return;
+}
+
+
+/* Search a given AVP model in an AVP (extracted from libfreediameter/message.c ) */
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp )
+{
+	struct avp * nextavp;
+	struct avp_hdr * nextavphdr;
+	struct dict_avp_data 	dictdata;
+	
+	
+	TRACE_ENTRY("%p %p %p", groupedavp, what, avp);
+	
+	CHECK_FCT(  fd_dict_getval(what, &dictdata)  );
+	
+	// Loop only in the group AVP 
+	CHECK_FCT(  fd_msg_browse(groupedavp, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL)  );
+	CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
+	
+	while (nextavphdr) {
+		
+		if ( (nextavphdr->avp_code   == dictdata.avp_code) && (nextavphdr->avp_vendor == dictdata.avp_vendor) ) // always 0 if no Vendor flag
+		{
+			break;
+		}
+		
+		// Otherwise move to next AVP in the grouped AVP 
+		CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );
+		
+		if(nextavp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
+		}
+		else
+			nextavphdr=NULL;
+	}
+	if (avp)
+		*avp = nextavp;
+	
+	if (avp && nextavp) {
+		struct dictionary * dict;
+		CHECK_FCT( fd_dict_getdict( what, &dict) );
+		CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ),  );
+	}
+	
+	if (avp || nextavp)
+		return 0;
+	else
+		return ENOENT;
+}
+struct avp_hdr *walk_digest(struct avp *avp, int avp_code)
+{
+	struct avp_hdr *temphdr=NULL;
+	CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL);
+	
+	while(avp!=NULL)
+	{
+		
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp,&temphdr ),return NULL);
+
+		if(temphdr->avp_code==avp_code)
+		{
+			//We found the AVP so we set avp to NULL to exit the loop
+			avp=NULL;
+			return temphdr;
+			
+		}
+		else if(temphdr->avp_code==380)//SIP-Authorization AVP
+		{
+			//We didn't found the AVP but we finished browsing the Authentication AVP
+			avp=NULL;
+			temphdr=NULL;
+			
+			return temphdr;
+		}
+		else
+		{
+			CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL);
+			temphdr=NULL;
+			
+		}
+	}
+	
+	return temphdr;
+}
+
+int start_mysql_connection()
+{
+	conn = mysql_init(NULL);
+	
+	mysql_options(conn, MYSQL_OPT_RECONNECT, "true");
+	
+	if (!mysql_real_connect(conn, as_conf->mysql_server,as_conf->mysql_login, as_conf->mysql_password, as_conf->mysql_database, as_conf->mysql_port, NULL, 0)) 
+	{//TODO: display error from mysql
+		TRACE_DEBUG(INFO,"Unable to connect to database (%s) with login:%s",as_conf->mysql_database,as_conf->mysql_login);
+		return 1;
+	}
+	return 0;
+	
+}
+
+
+void request_mysql(char *query)
+{
+	//We check if the connection is still up
+	mysql_ping(conn);
+	
+	if (mysql_query(conn, query)) 
+	{
+		TRACE_DEBUG(INFO,"Query %s failed", query);
+		
+	}
+	
+}
+
+void close_mysql_connection()
+{
+	mysql_close(conn);
+	
+}
+
+//If password is null, we just verify this user exist
+//We don't need the password length because it is a table'
+int get_password(const unsigned char *username, const size_t usernamelen, char *password)
+{
+	CHECK_PARAMS(username && usernamelen);
+	
+	int not_found=2;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We copy username in query
+			querylen=SQL_GETPASSWORD_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_GETPASSWORD, username_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				if(password!=NULL)
+					password[0]='\0';
+				free(query);
+				return 2;
+			}
+			
+			
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strlen(row[0])>0)
+				{
+					if(password!=NULL)
+						strcpy(password,row[0]);
+					
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+		break;
+	}
+	return not_found;
+}
+
+int check_sipaor(const unsigned char  *username, const size_t usernamelen, const char * sip_aor,const size_t sipaorlen)
+{
+	CHECK_PARAMS(username && usernamelen && sip_aor && sipaorlen);
+	
+	int not_found=2;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+	
+			//We get the list of AOR owned by this user
+			querylen=SQL_GETSIPAOR_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_GETSIPAOR, username_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				free(query);
+				return 2;
+			}
+			
+			
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strncmp((const char *)sip_aor,row[0],sipaorlen)==0)
+				{
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+		break;
+	}
+	return not_found;
+}
+
+int get_diameter_uri(const unsigned char *sip_aor, const size_t sipaorlen, char ** diameter_uri, size_t *diameterurilen)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen);
+
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+
+
+
+
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+
+			querylen=SQL_GETDIAMURI_LEN + sipaorlen;
+
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETDIAMURI, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				diameter_uri=NULL;
+				return 2;
+			}
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				*diameterurilen=strlen(row[0]);
+				if(*diameterurilen>0)
+				{
+					CHECK_MALLOC(*diameter_uri=malloc(*diameterurilen+1));
+					strcpy(*diameter_uri,row[0]);
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+		break;
+      
+    default:
+      
+      //We must never go here, if so, we must stop diameter_sip
+      diameter_uri=NULL;
+      return 2;
+      
+      break;
+  }
+  
+  //0 if it was found
+  return not_found;
+  
+}
+
+
+int exist_username(const unsigned char *sip_aor, const size_t sipaorlen)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen);
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=1;
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETUSERNAME_LEN + sipaorlen;
+			
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETUSERNAME, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				return 2;
+			}
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strlen(row[0])>0)
+				{
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+		default:
+			
+			//We must never go here, if so, we must stop diameter_sip
+			TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+			return 2;
+			
+			break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+}
+
+//We check if this user can go in the given network
+int allow_roaming(const unsigned char  *username, const size_t usernamelen, const char * network,const size_t networklen)
+{
+	CHECK_PARAMS(username && usernamelen && network && networklen);
+	
+	int not_found=2;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We get the list of AOR owned by this user
+			querylen=SQL_GETUSERNET_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_GETUSERNET, username_pure);
+			
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			
+			//We make the query
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				free(query);
+				return 2;
+			}
+			
+			
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strncmp((const char *)network,row[0],networklen)==0)
+				{
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			break;
+	}
+	return not_found;
+}
+
+//SIP-Server-Capabilities for the SIP-AOR
+int get_sipserver_cap(const unsigned char *sip_aor, const size_t sipaorlen, struct avp **capabilities)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen && capabilities);
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+	union avp_value value;
+	struct avp *avp;
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETSIPSERCAP_LEN + sipaorlen;
+			
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETSIPSERCAP, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				return 2;
+			}
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(atoi(row[0])==1)
+				{//mandatory
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Mandatory_Capability, 0, &avp ) );
+					value.i32=(uint32_t)atoi(row[1]);
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *capabilities, MSG_BRW_LAST_CHILD, avp) );
+					
+				}
+				else
+				{//optional
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Optional_Capability, 0, &avp ) );
+					value.i32=(uint32_t)atoi(row[1]);
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *capabilities, MSG_BRW_LAST_CHILD, avp) );
+				}
+				not_found=0;
+			}
+			
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+		default:
+			
+			//We must never go here, if so, we must stop diameter_sip
+			TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+			return 2;
+			
+			break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+}
+
+
+//We retrieve datatype
+int add_user_datatype(const unsigned char  *sip_aor, const size_t sipaorlen,struct msg *message)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen && message );
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+	union avp_value value;
+	struct avp *avp, *rootavp;
+	unsigned long *length;
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETSIPDATA_LEN + sipaorlen;
+			
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETSIPDATA, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				return 2;
+			}
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				length=mysql_fetch_lengths(res);
+				
+				if(strlen(row[0])>1)
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data, 0, &rootavp ) );
+					
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Type, 0, &avp ) );
+					CHECK_MALLOC(value.os.data=malloc(length[0]*sizeof(unsigned char)));
+					strncpy((char *)value.os.data,(char *)row[0],length[0]);
+					value.os.len=(size_t)length[0];
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+					
+					
+					
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Contents, 0, &avp ) );
+					CHECK_MALLOC(value.os.data=malloc(length[1]*sizeof(unsigned char)));
+					memcpy(value.os.data,row[1],length[1]);
+					value.os.len=(size_t)length[1];
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+					
+					//We add SIP_User_Data to message
+					CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, rootavp) );
+					not_found=0;
+				}
+				
+			}
+			
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+			default:
+				
+				//We must never go here, if so, we must stop diameter_sip
+				TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+				return 2;
+				
+				break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+	
+	
+}
+
+int set_pending_flag(const unsigned char  *username, const size_t usernamelen)
+{
+	CHECK_PARAMS(username && usernamelen);
+	
+	
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_SETFLAG_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_SETFLAG, username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+int clear_pending_flag(const unsigned char  *username, const size_t usernamelen)
+{
+	CHECK_PARAMS(username && usernamelen);
+	
+	
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_CLEARFLAG_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_CLEARFLAG, username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+		break;
+	}	
+	return 0;
+}
+
+
+
+int set_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+	CHECK_PARAMS(username && usernamelen && sipserver_uri && sipserverurilen);
+	
+	
+	size_t querylen, usernamepurelen, sipserveruripurelen;
+	char *query, *username_pure, *sipserveruri_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We allocate the double size of username because at worst it can be all quotes
+			sipserveruri_pure=malloc(sipserverurilen*2+1);
+			//We purify username not to have forbidden characters
+			sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_SETSIPURI_LEN + usernamepurelen + sipserveruripurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_SETSIPURI, sipserveruri_pure,username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+int remove_sipserver_uri(const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+	CHECK_PARAMS(sipserver_uri && sipserverurilen);
+	
+
+	size_t querylen, sipserveruripurelen;
+	char *query, *sipserveruri_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			sipserveruri_pure=malloc(sipserverurilen*2+1);
+			//We purify username not to have forbidden characters
+			sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_RMSIPURI_LEN + sipserveruripurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_RMSIPURI, sipserveruri_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+int set_real_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+	CHECK_PARAMS(username && usernamelen && sipserver_uri && sipserverurilen);
+	
+	
+	size_t querylen, usernamepurelen, sipserveruripurelen;
+	char *query, *username_pure, *sipserveruri_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We allocate the double size of username because at worst it can be all quotes
+			sipserveruri_pure=malloc(sipserverurilen*2+1);
+			//We purify username not to have forbidden characters
+			sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_SETREALSIPURI_LEN + usernamepurelen + sipserveruripurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_SETREALSIPURI, sipserveruri_pure,username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+
+int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen && sipserver_uri && sipserverurilen );
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+	
+	
+	
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETSIPSERURI_LEN + sipaorlen;
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETSIPSERURI, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				sipserver_uri=NULL;
+				return 2;
+			}
+			
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				*sipserverurilen=strlen(row[0]);
+				if(*sipserverurilen>4)
+				{
+					CHECK_MALLOC(*sipserver_uri=malloc(*sipserverurilen+1));
+					strcpy((char *)*sipserver_uri,row[0]);
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+		default:
+			
+			//We must never go here, if so, we must stop diameter_sip
+			TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+			sipserver_uri=NULL;
+			return 2;
+			
+			break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+}
+
+
+int count_avp(struct msg * message, int code, int vendor)
+{
+	CHECK_PARAMS(message);
+	
+	struct avp_hdr *temphdr;
+	struct avp *avp;
+	int counter=0;
+	
+	CHECK_FCT(fd_msg_browse (message, MSG_BRW_WALK, &avp, NULL));
+	
+	while(avp!=NULL)
+	{
+		
+		CHECK_FCT( fd_msg_avp_hdr( avp,&temphdr ));
+		
+		if(temphdr->avp_code==code && temphdr->avp_vendor==vendor)
+		{
+			counter++;
+		}
+		
+		CHECK_FCT(fd_msg_browse (avp, MSG_BRW_WALK, &avp, NULL));
+	}
+	return counter;
+}
+/* 
+void nonce_add_element(char * nonce)
+{
+	noncechain *newelt=malloc(sizeof(noncechain));
+	
+	newelt->nonce=nonce;
+	
+	newelt->timestamp=(int)time(NULL);
+	newelt->next=NULL;
+	
+	if(listnonce==NULL)
+	{
+		listnonce=newelt;
+	}
+	else
+	{
+		noncechain* temp=listnonce;
+		
+		while(temp->next != NULL)
+		{
+			if(temp->timestamp < ((int)time(NULL)-300))
+			{
+				listnonce=temp->next;
+				free(temp);
+				temp=listnonce;
+			}
+			temp = temp->next;
+		}
+		temp->next = newelt;
+	}
+	
+}
+void nonce_del_element(char * nonce)
+{
+	if(listnonce!=NULL)
+	{
+		noncechain *temp=listnonce, *tempbefore=NULL;
+		
+		if(listnonce->next==NULL && strcmp(listnonce->nonce,nonce)==0)
+		{
+			free(listnonce);
+			listnonce=NULL;
+			return;
+		}
+		while(temp->next != NULL)
+		{
+			if(strcmp(temp->nonce,nonce)==0)
+			{
+				if(tempbefore==NULL)
+				{
+					listnonce=temp->next;
+					free(temp);
+					return;
+				}
+				tempbefore->next=temp->next;
+				free(temp);
+				break;
+			}
+			tempbefore=temp;
+			temp = temp->next;
+		}
+		
+	}
+	
+}
+int nonce_check_element(char * nonce)
+{
+	if(listnonce==NULL)
+	{
+		//Not found
+		return 0;
+	}
+	else
+	{
+		noncechain* temp=listnonce;
+		
+		while(temp->next != NULL)
+		{
+			if(strcmp(temp->nonce,nonce)==0)
+				return 1;
+			else
+				temp = temp->next;
+		}
+	}
+	return 0;
+}
+
+void nonce_deletelistnonce()
+{
+	if(listnonce !=NULL)
+	{
+		noncechain* temp=listnonce;
+	
+		while(listnonce->next != NULL)
+		{
+			temp = listnonce->next;
+		
+			free(listnonce);
+		
+			listnonce=temp;
+		}
+		free(listnonce);
+	}
+}
+*/
diff --git a/extensions/app_sip/locationinfo.c b/extensions/app_sip/locationinfo.c
new file mode 100644
index 0000000..e2c372a
--- /dev/null
+++ b/extensions/app_sip/locationinfo.c
@@ -0,0 +1,208 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+
+int app_sip_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp, *groupedavp;
+	struct avp_hdr *avphdr;
+	union avp_value value;
+	int ret=0;
+	
+	//Result_Code to return in the answer
+	char result[55];
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	//Add a SIP_Server_URI
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		
+		
+		
+		
+		ret=exist_username(avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+		
+		
+		if(ret==2)
+		{//error
+			/*
+			If the Diameter server cannot process the Diameter LIR command, e.g.,
+			due to a database error, the Diameter server MUST set the Result-Code
+			AVP value to DIAMETER_UNABLE_TO_COMPLY and return it in a Diameter
+			LIA message.
+			*/
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		else if(ret==1)
+		{//not found
+			/*
+			One of the errors that the Diameter server may find is that the
+			SIP-AOR AVP value is not a valid user in the realm.  In such cases,
+			the Diameter server MUST set the Result-Code AVP value to
+			DIAMETER_ERROR_USER_UNKNOWN and return it in a Diameter LIA message.
+			
+			*/
+			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+			goto out;
+		}
+		
+		//If we arrive here, the user is known
+		size_t sipserverurilen;
+		unsigned char * sipserver_uri=NULL;
+		
+		ret=get_sipserver_uri(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
+		
+		
+		if(ret==0)
+		{//found
+			if(sipserver_uri==NULL)
+			{
+				//There is a problem because we must get a Diameter_URI here
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			else
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
+				value.os.data=(unsigned char *)sipserver_uri;
+				value.os.len=sipserverurilen;
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+				
+				strcpy(result,"DIAMETER_SUCCESS");
+			}
+		}
+		else if(ret==1)
+		{//not found
+			//We don't know this SIP_AOR in SL, that means 
+			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+			goto out;
+		}
+		else
+		{// returned 2, impossible to make request
+			//We couldn't make the request, we must stop process!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		
+		//Adding SIP-Server-Capabilities
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Capabilities, 0, &groupedavp ) );
+		//We add mandatory and optional capabilities
+		ret=get_sipserver_cap(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &groupedavp);
+		
+		
+		if(ret==0)
+		{//found
+		if(sipserver_uri==NULL)
+		{
+			//There is a problem because we must get a Diameter_URI here
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			CHECK_FCT( fd_msg_free( groupedavp ) );
+			goto out;
+		}
+		else
+		{
+			
+			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+			
+			strcpy(result,"DIAMETER_SUCCESS");
+		}
+		}
+		else if(ret==1)
+		{//not found
+			//We don't know this SIP_AOR in SL, that means 
+			strcpy(result,"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED");
+			CHECK_FCT( fd_msg_free( groupedavp ) );
+			goto out;
+		}
+		else
+		{// returned 2, impossible to make request
+			//We couldn't make the request, we must stop process!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			CHECK_FCT( fd_msg_free( groupedavp ) );
+			goto out;
+		}
+		
+		
+		
+	}
+	
+	
+	
+	
+out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/locationinfosl.c b/extensions/app_sip/locationinfosl.c
new file mode 100644
index 0000000..f28beef
--- /dev/null
+++ b/extensions/app_sip/locationinfosl.c
@@ -0,0 +1,144 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+//This callback is specific to SUSCRIBER LOCATOR. We must look for the "serving" SIP server
+int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp;
+	struct avp_hdr *avphdr;
+	union avp_value value;
+	
+	//Result_Code to return in the answer
+	char result[55];
+	int ret=0;
+	
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	// Add the Redirect Host AVP 
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		size_t diameterurilen;
+		char * diameter_uri=NULL;
+		
+		
+		
+		ret=get_diameter_uri(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &diameter_uri, &diameterurilen);
+		
+		//found
+		if(ret==0)
+		{
+		  if(diameter_uri==NULL)
+		  {
+			  //There is a problem because we must get a Diameter_URI here
+			  strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			  goto out;
+		  }
+		  else
+		  {
+		    CHECK_FCT( fd_msg_avp_new ( sip_dict.Redirect_Host, 0, &avp ) );
+		    value.os.data=(unsigned char *)diameter_uri;
+		    value.os.len=diameterurilen;
+		    CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		    CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+		    
+		    CHECK_FCT( fd_msg_avp_new ( sip_dict.Redirect_Host_Usage, 0, &avp ) );
+		    value.i32=ALL_USER; //All the request about the same user must be sent to this server
+		    CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		    CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+		    strcpy(result,"DIAMETER_SUCCESS");
+		  }
+		}
+		else if(ret==1)
+		{//not found
+			//We don't know this SIP_AOR in SL
+			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+			goto out;
+		}
+		else
+		{// returned 2, impossible to make request
+			//We couldn't make the request, we must stop process!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	
+	
+out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/md5.c b/extensions/app_sip/md5.c
new file mode 100644
index 0000000..4079bda
--- /dev/null
+++ b/extensions/app_sip/md5.c
@@ -0,0 +1,421 @@
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes directly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ *  In addition to this notice, only the #include directives have been modified.
+ */
+
+/*********************************************************************************/
+#include"app_sip.h"
+ 
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+void CvtHex(
+    IN HASH Bin,
+    OUT HASHHEX Hex
+    )
+{
+    unsigned short i;
+    unsigned char j;
+
+    for (i = 0; i < HASHLEN; i++) {
+        j = (Bin[i] >> 4) & 0xf;
+        if (j <= 9)
+            Hex[i*2] = (j + '0');
+         else
+            Hex[i*2] = (j + 'a' - 10);
+        j = Bin[i] & 0xf;
+        if (j <= 9)
+            Hex[i*2+1] = (j + '0');
+         else
+            Hex[i*2+1] = (j + 'a' - 10);
+    }
+    Hex[HASHHEXLEN] = '\0';
+}
+
+// calculate H(A1) as per spec 
+void DigestCalcHA1(char * pszAlg,char * pszUserName,char * pszRealm,char * pszPassword,char * pszNonce,char * pszCNonce,HASHHEX SessionKey)
+{
+      MD5_CTX Md5Ctx;
+      HASH HA1;
+
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszRealm, strlen(pszRealm));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword));
+      MD5Final((unsigned char *)HA1, &Md5Ctx);
+      if (strcmp(pszAlg, "md5-sess") == 0) {	
+		MD5Init(&Md5Ctx);
+		MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHLEN);
+		MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+		MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce));
+		MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+		MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+		MD5Final((unsigned char *)HA1, &Md5Ctx);
+      }
+      CvtHex(HA1, SessionKey);
+}
+
+// calculate request-digest as  SIP Digest spec RFC5090
+void DigestCalcResponse(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response)
+{
+      MD5_CTX Md5Ctx;
+      HASH HA2;
+      HASH RespHash;
+       HASHHEX HA2Hex;
+
+      // calculate H(A2)
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri));
+      if (strcmp(pszQop, "auth-int") == 0) {
+            MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+            MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
+      }
+      MD5Final((unsigned char *)HA2, &Md5Ctx);
+       CvtHex(HA2, HA2Hex);
+       
+      // calculate response
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx,(const unsigned char *) pszNonce, strlen(pszNonce));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      if (*pszQop) {
+          MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      }
+      MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
+      MD5Final((unsigned char *)RespHash, &Md5Ctx);
+      CvtHex(RespHash, Response);
+}
+// calculate Digest_response_Auth as per SIP Digest spec RFC5090
+void DigestCalcResponseAuth(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response)
+{
+      MD5_CTX Md5Ctx;
+      HASH HA2;
+      HASH RespHash;
+       HASHHEX HA2Hex;
+
+      // calculate H(A2)
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri));
+      if (strcmp(pszQop, "auth-int") == 0) {
+            MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+            MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
+      }
+      MD5Final((unsigned char *)HA2, &Md5Ctx);
+       CvtHex(HA2, HA2Hex);
+       
+      // calculate response
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      if (*pszQop) {
+          MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      }
+      MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
+      MD5Final((unsigned char *)RespHash, &Md5Ctx);
+      CvtHex(RespHash, Response);
+}
+
+
+
+
+
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+
+
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ */
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	MD5_CTX ctx;
+	size_t i;
+
+	MD5Init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		MD5Update(&ctx, addr[i], len[i]);
+	MD5Final(mac, &ctx);
+}
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len)	/* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    u32 t;
+    do {
+	t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+	    ((unsigned) buf[1] << 8 | buf[0]);
+	*(u32 *) buf = t;
+	buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    u32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+	ctx->bits[1]++;		/* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+	unsigned char *p = (unsigned char *) ctx->in + t;
+
+	t = 64 - t;
+	if (len < t) {
+	    os_memcpy(p, buf, len);
+	    return;
+	}
+	os_memcpy(p, buf, t);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += t;
+	len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+	os_memcpy(ctx->in, buf, 64);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += 64;
+	len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    os_memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+	/* Two lots of padding:  Pad the first block to 64 bytes */
+	os_memset(p, 0, count);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+	/* Now fill the next block with 56 bytes */
+	os_memset(ctx->in, 0, 56);
+    } else {
+	/* Pad block to 56 bytes */
+	os_memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((u32 *) ctx->in)[14] = ctx->bits[0];
+    ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(u32 buf[4], u32 const in[16])
+{
+    register u32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
+
diff --git a/extensions/app_sip/md5.h b/extensions/app_sip/md5.h
new file mode 100644
index 0000000..fc55872
--- /dev/null
+++ b/extensions/app_sip/md5.h
@@ -0,0 +1,59 @@
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes directly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ *  The file has not been modified, except for this notice.
+ */
+/*********************************************************************************/
+
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define MD5_MAC_LEN 16
+
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+#define HASHLEN 16
+typedef char HASH[HASHLEN];
+#define HASHHEXLEN 32
+typedef char HASHHEX[HASHHEXLEN+1];
+#define IN
+#define OUT
+
+struct MD5Context {
+	u32 buf[4];
+	u32 bits[2];
+	u8 in[64];
+};
+typedef struct MD5Context MD5_CTX;
+#define os_memcpy(d, s, n) memcpy((d), (s), (n))
+#define os_memset(s, c, n) memset(s, c, n)
+
+
+void MD5Init(struct MD5Context *ctx);
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+
+#endif /* MD5_H */
diff --git a/extensions/app_sip/multimediaauth.c b/extensions/app_sip/multimediaauth.c
new file mode 100644
index 0000000..12c1bcb
--- /dev/null
+++ b/extensions/app_sip/multimediaauth.c
@@ -0,0 +1,762 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+struct sess_state
+{
+	char *nonce;
+};
+
+
+int app_sip_MAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	//struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	char password[51];
+	int idx=0, number_of_auth_items=0,i=0, ret=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0; 
+	size_t querylen=0, usernamelen=0;
+	char *query=NULL;
+	unsigned char *username=NULL;
+	
+	//The nonce we will store and retrieve in session
+	struct sess_state *storednonce=NULL;
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	/* Create answer header */
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+
+
+	/* Add the appropriate command code & Auth-Application-Id 
+	{
+		
+		CHECK_FCT( fd_msg_hdr ( *msg, &header ) );
+		header->msg_flags = CMD_FLAG_PROXIABLE;
+		header->msg_code = 286;
+		header->msg_appl = 6;
+		
+		
+		// Add the Auth-Application-Id 
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+			ASSERT(avp);
+			val.i32 = header->msg_appl;
+			CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+		}
+	}*/
+	
+	
+	/* Add the Auth-Session-State AVP */
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+
+	
+	
+	/* Check if method is REGISTER then User-Name must be present */
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Method, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader ));
+		
+
+		char *method=NULL;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			
+			int not_found=1;
+			MYSQL_RES *res=NULL;
+			MYSQL_ROW row;
+			
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+			
+			
+			
+			if((strncmp((const char *)avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0))
+			{
+				not_found=1;
+				
+				//TODO TODO TODO TODO TODO TODO TODO: maybe doesn't work!!'
+				ret=get_password(avphdr->avp_value->os.data, avphdr->avp_value->os.len, (char *)&password);
+				
+				if(ret>1)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+				not_found=ret;
+				
+				if(not_found)
+				{
+					TRACE_DEBUG(FULL,"The user %s doesn't exist!",username);
+					result="DIAMETER_ERROR_USER_UNKNOWN";
+					free(username);	
+					goto out;
+				}
+			
+			
+				//We allocate the double size of username because at worst it can be all quotes
+				username=malloc(avphdr->avp_value->os.len*2+1);
+				//We purify username not to have forbidden characters
+				usernamelen=mysql_real_escape_string(conn, (char *)username, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+				
+				//Now that we know the user exist, we get the list of AOR owned by this user
+				querylen=SQL_GETSIPAOR_LEN + usernamelen;
+				query = malloc(querylen+2);
+				snprintf(query, querylen+1, SQL_GETSIPAOR, username);
+			
+				//We make the query
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+			
+				//We retrieve the SIP-AOR from AVP to check if the user can us it
+				CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+				CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+				not_found=1;
+				while ((row = mysql_fetch_row(res)) != NULL)
+				{
+					if(strncmp((const char *)avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
+					{
+						not_found=0;
+						break;
+					}
+				}
+				mysql_free_result(res);
+				free(query);
+      				
+				if(not_found)
+				{
+					TRACE_DEBUG(FULL,"The user %s can't use this SIP-AOR!",username);
+					result="DIAMETER_ERROR_IDENTITIES_DONT_MATCH";
+					free(username);	
+					goto out;
+				}
+				
+			}
+
+			CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			if(avphdr!=NULL)
+			{
+				unsigned char *sipuri=NULL;
+				int sipurilen=0;
+
+				//We allocate the double size of SIP-URI because at worst it can be all quotes
+				CHECK_MALLOC(sipuri=malloc(avphdr->avp_value->os.len*2+1));
+				//We purify SIP-URI not to have forbidden characters
+				sipurilen=mysql_real_escape_string(conn, (char *)sipuri, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+				
+				
+				//We get the SIP-URI assignated to the user
+				querylen=SQL_GETSIPURI_LEN + usernamelen;
+				CHECK_MALLOC(query = malloc(querylen+2));
+				snprintf(query, querylen+1, SQL_GETSIPURI, username);
+
+				//We make the query
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+				not_found=1;
+				while ((row = mysql_fetch_row(res)) != NULL)
+				{
+					if(strncmp((const char *)avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
+					{
+						not_found=0;
+						break;
+					}
+				}
+				mysql_free_result(res);
+				free(query);
+
+				if(not_found)
+				{
+					//Temporary
+					set_sipserver_uri(username, usernamelen, sipuri,sipurilen);
+					
+					
+					set_pending_flag(username, usernamelen);
+					
+					
+					authenticationpending=1;
+				}
+				free(sipuri);
+				
+			}
+			else
+				sipurinotstored=1;
+
+		}
+		else
+		{
+			result="DIAMETER_USER_NAME_REQUIRED";
+			goto out;
+		}
+
+			
+		free(method);
+
+	}
+
+	
+	//TODO: remove loop for authdataitem because RFC say only one (wait for answer from Garcia)
+	// How many Auth Data Items?
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Number_Auth_Items, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader )  );
+	
+	
+	if(avp!=NULL)
+	{
+		CHECK_FCT(fd_msg_search_avp ( qry, sip_dict.SIP_Auth_Data_Item, &avp));
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		if(avp!=NULL)
+		{
+			//First is Authentication Scheme
+			CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+			//Digest-Authentication?
+			if(avphdr->avp_value->i32==0)
+			{
+				
+				for(idx=0;idx<avpheader->avp_value->i32;idx++)
+				{
+					//We look for SIP Auth items
+					CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
+					
+					if(avp!=NULL)
+					{
+						
+						CHECK_FCT( fd_msg_avp_hdr( avp,&avphdr ));
+		
+						if(avphdr->avp_code==380) //We only create Auth-Data-Item to answer Auth-Data-Item
+						{
+							/* Add the Auth-Data-Item AVP */
+							CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Auth_Data_Item, 0, &authdataitem ) );
+					
+							/* Add the Authentication Scheme AVP */
+							{
+								CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Scheme, 0, &a2 ) );
+								val.i32=0; //We only know Digest Authentication
+								CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, a2 ) );
+							}
+							
+							//We need to know if there is a Cnonce attribute (only in the second MAR request)
+							
+							//CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
+							
+							
+							CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
+							
+							if(a2!=NULL)
+								found_cnonce=1;
+							else
+								found_cnonce=0;
+								
+							if(!found_cnonce)
+							{
+								/*
+								We are in the case of first access request so we need to challenge the user.
+								*/
+								TRACE_DEBUG(FULL,"First Authorization in progress...");
+
+								/* Create a new session */ //this create a new session Id !!!
+								//CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, "diamsip", 7), goto out );
+								
+
+								/* Create the SIP-Authenticate AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authenticate, 0, &sipAuthenticate ) );
+								}						
+
+								/* Add the Digest QOP AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_QOP, 0, &a2 ) );
+									val.os.data=(unsigned char *)"auth";
+									val.os.len=strlen((const char *)val.os.data);
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								}
+								/* Add the Digest Nonce AVP */
+								{
+									uint8_t buffer[NONCE_SIZE];
+									char nonce[NONCE_SIZE * 2 + 1];
+							
+								
+									gcry_create_nonce ((uint8_t *)buffer, sizeof(buffer));
+							
+									for(i=0;i<NONCE_SIZE;i++)
+										sprintf(&nonce[2 * i], "%2.2hhx", buffer[i]);
+								
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Nonce, 0, &a2 ) );
+									
+									
+									//We store the nonce (storednonce structure) inside the session
+									storednonce=malloc(sizeof(struct sess_state));
+									memset(storednonce,0,sizeof(struct sess_state));
+									CHECK_MALLOC(storednonce->nonce=malloc(NONCE_SIZE*2+1));
+									memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1);
+									CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce ));  
+									
+									val.os.data=(unsigned char *)nonce;
+									val.os.len=NONCE_SIZE * 2;
+									
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								}
+								/* Add the Digest Algorithm AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Algorithm, 0, &a2 ) );
+									val.os.data=(unsigned char *)"MD5";
+									val.os.len=strlen((const char *)val.os.data);
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+							
+								}
+								/* Add the Digest Realm AVP */
+								{
+									tempavp=avp;
+								
+									avpheader_auth=walk_digest(tempavp, 104);
+									if(avpheader_auth!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Realm, 0, &a2 ) );
+										CHECK_FCT( fd_msg_avp_setvalue( a2, avpheader_auth->avp_value ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								
+									}
+								}
+						
+						
+								//We add SIP Authenticate to Auth Data Item
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthenticate ) );
+								//We add Auth Data Item to Answer
+								CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
+						
+								number_of_auth_items++;
+								if(sipurinotstored)
+									result="DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED";
+								else
+									result="DIAMETER_MULTI_ROUND_AUTH";
+								found_cnonce=0;
+							}
+							else
+							{
+								/*
+								We are in the case of access request after challenge so we need to check credentials.
+								*/
+								TRACE_DEBUG(FULL,"Authentication after challenge");
+								
+								/* Search the session, retrieve its data */
+								{
+									//int new=0;
+									
+									//TRACE_DEBUG(FULL,"new: *%d*",new);
+									//ASSERT( new == 0 );
+									CHECK_FCT( fd_sess_state_retrieve( ds_sess_hdl, sess, &storednonce ));
+									if(storednonce ==NULL)
+									{
+										result="DIAMETER_UNABLE_TO_COMPLY";
+												
+										if(username!=NULL)
+											free(username);
+										goto out;
+									}
+								}
+								
+								/* Create the SIP-Authentication-Info AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Info, 0, &sipAuthentication ) );
+								}
+								
+								
+							
+								/* Add the Digest response Auth AVP */
+								{
+									//uint8_t bufferresp[DIGEST_LEN];
+									//char response[DIGEST_LEN*2+1];
+									
+									
+									//We extract all the data we need
+									tempavp=avp;
+									
+									char * digest_username=NULL, *digest_uri=NULL, *digest_response=NULL, *digest_realm=NULL, *digest_nonce=NULL, *digest_method=NULL, *digest_qop=NULL, *digest_algorithm=NULL, *digest_cnonce=NULL, *digest_noncecount=NULL;
+									
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											
+											digest_nonce = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_nonce, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_nonce[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_nonce);	
+											TRACE_DEBUG(FULL,"Stored Nonce:*%s*",storednonce->nonce);
+											
+											if(strcmp(digest_nonce,storednonce->nonce)!=0)
+											{
+												free(digest_nonce);
+												free(storednonce->nonce);
+												free(storednonce);
+												result="DIAMETER_UNABLE_TO_COMPLY";
+												
+												if(username!=NULL)
+													free(username);
+												goto out;
+											}
+											
+										}
+											
+									}
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Response, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_response = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_response, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_response[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_response);	
+										}
+										
+									}
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Realm, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_realm = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_realm, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_realm[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_realm);	
+										}
+									}
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Method, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_method = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_method, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_method[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_method);	
+										}
+									}
+									else
+										digest_method="";
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_URI, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_uri = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_uri, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_uri[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_uri);	
+										}
+									}
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_QOP, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_qop = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_qop, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_qop[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_qop);	
+										}
+									}
+									else
+										digest_qop=NULL;
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Algorithm, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_algorithm = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_algorithm, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_algorithm[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_algorithm);	
+										}
+									}
+									else
+										digest_algorithm=NULL;
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_cnonce = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_cnonce, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_cnonce[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_cnonce);	
+										}
+									}
+									else
+										digest_cnonce="";
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce_Count, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_noncecount = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_noncecount, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_noncecount[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_noncecount);	
+										}
+									}
+									else
+										digest_noncecount="";
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Username, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_username = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_username, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_username[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_username);	
+										}
+									}
+									//TODO: replace by authentication function
+									
+									HASHHEX HA1;
+									HASHHEX HA2 = "";
+									HASHHEX response, responseauth;
+
+									
+									DigestCalcHA1(digest_algorithm, digest_username, digest_realm, password, digest_nonce,digest_cnonce, HA1);
+      								DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response);
+      									
+		
+									// We check that the Digest-Response is the same (UA, Diameter)
+									if(strcmp(response,digest_response)!=0)
+									{
+										TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
+										TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
+										TRACE_DEBUG(INFO,"Digest-Response does not match!");
+										result="DIAMETER_UNABLE_TO_COMPLY";
+										free(digest_algorithm);
+										free(digest_cnonce);
+										free(digest_nonce);
+										free(digest_noncecount);
+										free(digest_method);
+										free(digest_username);
+										free(digest_uri);
+										free(digest_qop);
+										free(digest_response);
+										free(digest_realm);
+										free(storednonce->nonce);
+										free(storednonce);
+										if(username!=NULL)
+											free(username);
+										goto out;
+										
+									}
+									//We calculate Digest_Response_Auth
+									DigestCalcResponseAuth(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, responseauth);
+									
+									TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
+										TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
+									if(strcmp(digest_qop,"auth-int")==0)
+									{
+										//Digest-HA1 MUST be used instead of Digest-Response-Auth if Digest-Qop is 'auth-int'.
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_HA1, 0, &a2 ) );
+										val.os.data=(unsigned char *)HA1;
+										val.os.len=HASHHEXLEN+1;
+										CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
+									}
+									else
+									{
+										//Digest-Response-Auth MUST be used instead of Digest-HA1 if Digest-Qop is 'auth'.
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Response_Auth, 0, &a2 ) );
+										val.os.data=(unsigned char *)responseauth;
+										val.os.len=DIGEST_LEN*2;
+										CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
+									}
+									free(digest_algorithm);
+									free(digest_cnonce);
+									free(digest_nonce);
+									free(digest_noncecount);
+									free(digest_method);
+									free(digest_username);
+									free(digest_uri);
+									free(digest_qop);
+									free(digest_response);
+									free(digest_realm);
+									free(storednonce->nonce);
+									free(storednonce);
+								
+									number_of_auth_items++;
+								}	
+								
+								
+								//We add SIP Authentication-Info to Auth Data Item
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthentication ) );
+								//We add Auth Data Item to Answer
+								CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
+								
+								
+								if(username!=NULL && authenticationpending)
+								{
+									//We clear the pending flag
+									clear_pending_flag(username, usernamelen);
+								}
+								
+								if(sipurinotstored)
+									result="DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED";
+								else
+									result="DIAMETER_SUCCESS";
+								found_cnonce=0;
+							}
+						}
+					}
+					else
+						TRACE_DEBUG(INFO,"No auth data items!");
+				}
+				/*Add SIP_Number_Auth_Items  AVP */
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Number_Auth_Items, 0, &avp ) );
+					val.i32 = number_of_auth_items;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
+					CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+				}
+				
+				
+			}
+			else
+			{
+				TRACE_DEBUG(INFO,"We only support DIGEST for now, unable to comply");
+				result="DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED";
+				if(username!=NULL)
+					free(username);
+				goto out;
+			}
+		}
+	}
+	else
+	{
+		//TODO: remove this because Number_Auth_Items is not compulsory
+		TRACE_DEBUG(FULL,"Number-Auth-Items is not included.");
+		result="DIAMETER_UNABLE_TO_COMPLY";
+		if(username!=NULL)
+			free(username);
+		goto out;
+	}
+	
+	if(username!=NULL)
+		free(username);
+	
+
+out:
+	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	/* Send the answer */
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/pushprofile.c b/extensions/app_sip/pushprofile.c
new file mode 100644
index 0000000..e6233ed
--- /dev/null
+++ b/extensions/app_sip/pushprofile.c
@@ -0,0 +1,319 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+
+//Procedure which always wait for data on socket 
+void *ppr_socket(void *arg)
+{
+	
+	SOCKET sock;
+    SOCKADDR_IN sin, csin;
+    struct pprsipaor pprsip;
+    int rcvbytes=0;
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_family = AF_INET;
+	sin.sin_port = htons(as_conf->ppr_port);
+    socklen_t sinsize = sizeof(csin);
+	int accepted=0;
+
+    
+	if(!bind(sock, (SOCKADDR*)&sin, sizeof(sin)))
+	{
+		if(listen(sock,1))
+		{
+			TRACE_DEBUG(INFO,"ERROR on listen!");
+		}
+		
+		while(1)
+		{
+			accepted=accept(sock, (struct sockaddr *)&csin,&sinsize);
+			if(accepted>-1)
+			{
+				rcvbytes=recv(accepted, &pprsip, sizeof(struct pprsipaor),0);
+				
+				if(rcvbytes>-1)
+				{
+					//We received something, we can send an PPR
+					app_sip_PPR_cb(&pprsip);
+				}
+			}
+		}
+		
+		
+	}
+	else
+		TRACE_DEBUG(INFO,"Can't create socket!");
+
+	
+	pthread_exit(NULL);
+	
+}
+//Called to send a PPR
+int app_sip_PPR_cb(struct pprsipaor *structure)
+{
+	/*
+	TRACE_ENTRY("%p", structure);
+	
+	int got_username=0;
+	int got_streason=0;
+	int num_aor=0;//How many SIP-AOR?
+	struct dict_object * rtr_model=NULL;
+	struct msg * message=NULL;
+	struct avp *groupedavp=NULL, *avp=NULL;
+	struct session *sess=NULL;
+	union avp_value value;
+	
+	//We must check that we have all needed value in structure
+	if(structure.username[0]!='\0')
+		got_username=1;
+	
+	if(structure.sip_aor1[0]!='\0')
+	{	
+		num_aor++;
+		if(structure.sip_aor2[0]!='\0')
+		{
+			num_aor++;
+			if(structure.sip_aor3[0]!='\0')
+				num_aor++;
+		}
+	}
+	
+	if(structure.strreason!='\0')
+		got_streason=1;
+	
+	
+	TRACE_DEBUG(INFO,"We have %d SIP_AOR",num_aor);
+	
+	if((got_username + num_aor)==0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Can not proceed because there is no SIP_AOR or Username");
+		return EINVAL;
+	}
+	if(structure.reason<0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Incorrect Reason-Code");
+		return EINVAL;
+	}
+	
+	if(structure.desthost[0]=='\0')
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"No Destination_Host was provided!");
+		return EINVAL;
+	}
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &rtr_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (rtr_model, 0, &message));
+	
+	// Create a new session 
+	{
+		CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, "app_sip", 7 ));
+		char * sid;
+		CHECK_FCT( fd_sess_getsid ( sess, &sid ));
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp ));
+		value.os.data = (uint8_t *)sid;
+		value.os.len  = strlen(sid);
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ));
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp ));
+	}
+	
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)structure.desthost;
+		value.os.len=(size_t)strlen(structure.desthost);
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	//SIP Deregistration Reason (Grouped AVP)
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Deregistration_Reason, 0, &groupedavp ) );
+		
+		//Reason Code
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Code, 0, &avp ) );
+		value.i32=structure.reason;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		
+		if(got_streason)
+		{
+			//Reason Info
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Info, 0, &avp ) );
+			value.os.data=(unsigned char *)structure.strreason;
+			value.os.len=(size_t)strlen(structure.strreason);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		//We add the grouped AVP to the message
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, groupedavp ) );
+	}
+	
+	//Username
+	{
+		if(got_username)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
+			value.os.data=(unsigned char *)structure.username;
+			value.os.len=(size_t)strlen(structure.username);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		}
+	}
+	
+	//SIP_AOR
+	{
+		if(num_aor>0)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+			value.os.data=(unsigned char *)structure.sip_aor1;
+			value.os.len=(size_t)strlen(structure.sip_aor1);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+			if(num_aor>1)
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+				value.os.data=(unsigned char *)structure.sip_aor2;
+				value.os.len=(size_t)strlen(structure.sip_aor2);
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				if(num_aor>2)
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+					value.os.data=(unsigned char *)structure.sip_aor3;
+					value.os.len=(size_t)strlen(structure.sip_aor3);
+					CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				}
+			}
+		}
+	}
+	
+	fd_msg_dump_walk(INFO,message);
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	*/
+	return 0;
+}
+
+//Called when an PPA arrive
+int app_sip_PPA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	//TODO: PPA reception
+/*
+	//TODO:remove unused variables
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	int idx=0, idx2=0, number_of_auth_items=0,i=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
+	char *query=NULL,*username=NULL;
+	
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;	
+	
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Deregistration_Reason, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	*/
+	return 0;
+	
+}
+
diff --git a/extensions/app_sip/registrationtermination.c b/extensions/app_sip/registrationtermination.c
new file mode 100644
index 0000000..9300467
--- /dev/null
+++ b/extensions/app_sip/registrationtermination.c
@@ -0,0 +1,315 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+
+//Procedure which always wait for data on socket 
+void *rtr_socket(void *arg)
+{
+	SOCKET sock;
+	SOCKADDR_IN sin, csin;
+	struct rtrsipaor rtrsip;
+	int rcvbytes=0;
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+	sin.sin_family = AF_INET;
+	sin.sin_port = htons(as_conf->rtr_port);
+	socklen_t sinsize = sizeof(csin);
+	int accepted=0;
+
+	if(!bind(sock, (SOCKADDR*)&sin, sizeof(sin)))
+	{
+		if(listen(sock,1))
+		{
+			TRACE_DEBUG(INFO,"ERROR on listen!");
+		}
+		
+		while(1)
+		{
+			accepted=accept(sock, (struct sockaddr *)&csin,&sinsize);
+			if(accepted>-1)
+			{
+				rcvbytes=recv(accepted, &rtrsip, sizeof(struct rtrsipaor),0);
+				
+				if(rcvbytes>-1)
+				{
+					//We received something, we can send an RTR
+					app_sip_RTR_cb(&rtrsip);
+				}
+			}
+		}
+	}
+	else
+		TRACE_DEBUG(INFO,"Can't create socket!");
+
+	
+	pthread_exit(NULL);
+	
+}
+//Called to send a RTR
+int app_sip_RTR_cb(struct rtrsipaor *structure)
+{
+	TRACE_ENTRY("%p", structure);
+	
+	int got_username=0;
+	int got_streason=0;
+	int num_aor=0;//How many SIP-AOR?
+	struct dict_object * rtr_model=NULL;
+	struct msg * message=NULL;
+	struct avp *groupedavp=NULL, *avp=NULL;
+	union avp_value value;
+	
+	//We must check that we have all needed value in structure
+	if(structure->username[0]!='\0')
+		got_username=1;
+	
+	if(structure->sip_aor1[0]!='\0')
+	{	
+		num_aor++;
+		if(structure->sip_aor2[0]!='\0')
+		{
+			num_aor++;
+			if(structure->sip_aor3[0]!='\0')
+				num_aor++;
+		}
+	}
+	
+	if(structure->strreason!='\0')
+		got_streason=1;
+	
+	
+	TRACE_DEBUG(FULL,"Request for %d SIP_AOR to be deregistred.",num_aor);
+	
+	if((got_username + num_aor)==0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Can not proceed because there is no SIP_AOR or Username");
+		return EINVAL;
+	}
+	if(structure->reason<0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Incorrect Reason-Code");
+		return EINVAL;
+	}
+	
+	if(structure->desthost[0]=='\0')
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"No Destination_Host was provided!");
+		return EINVAL;
+	}
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &rtr_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (rtr_model, 0, &message));
+	
+	// Create a new session 
+	{
+		#define APP_SIP_SID_OPT  "app_sip"
+		CHECK_FCT( fd_msg_new_session( message, (os0_t)APP_SIP_SID_OPT, CONSTSTRLEN(APP_SIP_SID_OPT) ) );
+	}
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)structure->desthost;
+		value.os.len=(size_t)strlen(structure->desthost);
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	//SIP Deregistration Reason (Grouped AVP)
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Deregistration_Reason, 0, &groupedavp ) );
+		
+		//Reason Code
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Code, 0, &avp ) );
+		value.i32=structure->reason;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		
+		if(got_streason)
+		{
+			//Reason Info
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Info, 0, &avp ) );
+			value.os.data=(unsigned char *)structure->strreason;
+			value.os.len=(size_t)strlen(structure->strreason);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		//We add the grouped AVP to the message
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, groupedavp ) );
+	}
+	
+	//Username
+	{
+		if(got_username)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
+			value.os.data=(unsigned char *)structure->username;
+			value.os.len=(size_t)strlen(structure->username);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		}
+	}
+	
+	//SIP_AOR
+	{
+		if(num_aor>0)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+			value.os.data=(unsigned char *)structure->sip_aor1;
+			value.os.len=(size_t)strlen(structure->sip_aor1);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+			if(num_aor>1)
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+				value.os.data=(unsigned char *)structure->sip_aor2;
+				value.os.len=(size_t)strlen(structure->sip_aor2);
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				if(num_aor>2)
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+					value.os.data=(unsigned char *)structure->sip_aor3;
+					value.os.len=(size_t)strlen(structure->sip_aor3);
+					CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				}
+			}
+		}
+	}
+	
+	//TODO:remove for debug
+	//fd_msg_dump_walk(INFO,message);
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	
+	return 0;
+}
+
+//Called when an RTA arrive
+int app_sip_RTA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	//TODO: RTA reception
+/*
+	//TODO:remove unused variables
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	int idx=0, idx2=0, number_of_auth_items=0,i=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
+	char *query=NULL,*username=NULL;
+	
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;	
+	
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Deregistration_Reason, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	*/
+	return 0;
+	
+}
+
diff --git a/extensions/app_sip/serverassignment.c b/extensions/app_sip/serverassignment.c
new file mode 100644
index 0000000..fa31a81
--- /dev/null
+++ b/extensions/app_sip/serverassignment.c
@@ -0,0 +1,484 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+
+int app_sip_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp;
+	struct avp_hdr *avphdr, *sipaorhdr, *usernamehdr, *sipuserdataalreadyavailable;
+	union avp_value value;
+	int ret=0, assignment_type=0, got_datatype=1;
+	
+	
+	struct listdatatype
+	{
+		struct fd_list datatype;
+		char * type;
+		size_t typelen;
+	};
+	
+	//Result_Code to return in the answer
+	char result[55];
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//Retrieve SIP-AOR
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &sipaorhdr )  );
+		}
+		else
+			sipaorhdr=NULL;
+		
+	}
+	
+	//We check if we have a username AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &usernamehdr )  );
+			
+			ret=get_password(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, NULL);
+			
+			
+			if(ret==1)
+			{//not found
+				strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+				goto out;
+			}
+			else if(ret==2)
+			{//error
+				//We couldn't make the request, we must stop process!
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			else if(ret==0)
+			{//found
+				
+				if(sipaorhdr!=NULL)
+				{
+					//We must check that this user can use this SIP-AOR
+					ret=check_sipaor(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len,(const char *) sipaorhdr->avp_value->os.data,sipaorhdr->avp_value->os.len);
+					
+					if(ret==0)
+					{
+						//The SIP-AOR and Username are ok!
+						ret=clear_pending_flag(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len);
+						if(ret==2)
+						{
+							TRACE_DEBUG(INFO,"ERROR: We couldn't clear the flag of pending authentication.'");
+							strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+							goto out;
+						}
+					}
+					else if(ret==1)
+					{//not found
+						strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
+						goto out;
+					}
+					else
+					{//error
+						//We couldn't make the request, we must stop process!
+						strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+						goto out;
+					}
+				}
+				else
+				{
+					TRACE_DEBUG(INFO,"ERROR: There is no SIP-AOR AVP!'");
+					strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
+					goto out;
+				}
+			}
+		}
+		else
+		{
+			if(sipaorhdr!=NULL)
+			{//If we have a SIP-AOR, we want the user to check it.
+				strcpy(result,"DIAMETER_USER_NAME_REQUIRED");
+				goto out;
+			}
+			usernamehdr=NULL;
+		}
+			
+	}
+	
+	//We get the SIP_Server_Assignment_Type
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_Assignment_Type, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		assignment_type=avphdr->avp_value->i32;
+	}
+	
+	
+	
+	
+	
+	//We get SIP_User_Data_Already_Available AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_User_Data_Already_Available, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &sipuserdataalreadyavailable )  );
+	}
+	
+	if(assignment_type==1 || assignment_type==2)
+	{//registration & re-registration
+		if(count_avp(qry,CODE_SIP_AOR,0)==1)
+		{
+			
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+				
+				if(ret==0)
+				{
+					//We found and added datatype
+					got_datatype=1;
+				}
+				else if(ret==1)
+				{
+					//No data type was found
+					got_datatype=0;
+				}
+				else
+				{//error
+				//We couldn't make the request, we must stop process!
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+				}
+			}
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{//There is more than 1 SIP-AOR AVP
+			strcpy(result,"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES");
+			goto out;
+		}
+	}
+	else if(assignment_type==3)
+	{//Unregistered user
+		
+		//TODO:place user unknown here!
+		if(count_avp(qry,CODE_SIP_AOR,0)==1)
+		{
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				if(got_datatype==1)
+				{
+					ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+					
+					if(ret==0)
+					{
+						//We found and added datatype
+						got_datatype=1;
+					}
+					else if(ret==1)
+					{
+						//No data type was found
+						got_datatype=0;
+					}
+					else
+					{//error
+						//We couldn't make the request, we must stop process!
+						strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+						goto out;
+					}
+				}
+			}
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{//There is more than 1 SIP-AOR AVP
+			strcpy(result,"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES");
+			goto out;
+		}
+		
+		if(sipuserdataalreadyavailable->avp_value->i32==0)
+		{//Data not available, we must provide it
+			if(got_datatype==1)
+			{
+				ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+				
+				if(ret==0)
+				{
+					//We found and added datatype
+					got_datatype=1;
+				}
+				else if(ret==1)
+				{
+					//No data type was found
+					got_datatype=0;
+				}
+				else
+				{//error
+					//We couldn't make the request, we must stop process!
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			set_real_sipserver_uri(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{
+			TRACE_DEBUG(INFO,"There is no SIP_Server_URI AVP in this Unregistered User Request!");
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	else if(assignment_type==4 || assignment_type==5 || assignment_type==11 || assignment_type==8)
+	{//Unregistered user
+		
+		if(got_datatype==1)
+		{
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				
+				ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+				
+				if(ret==0)
+				{
+					//We found and added datatype
+					got_datatype=1;
+				}
+				else if(ret==1)
+				{
+					//No data type was found
+					got_datatype=0;
+				}
+				else
+				{//error
+					//We couldn't make the request, we must stop process!
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+		
+		if(sipaorhdr==NULL)
+		{
+			//We don't have any SIP-AOR to unregister, this is strange!'
+			TRACE_DEBUG(INFO, "There was no SIP-AOR in this request, we can't proceed request!'");
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		else
+		{
+			//TODO: unregister SIP-Server-URI for all SIP-AOR
+		}
+		strcpy(result,"DIAMETER_SUCCESS");
+		goto out;
+	}
+	else if(assignment_type==6 || assignment_type==7)
+	{
+		
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			//TODO: set SIP server URI for each AOR
+			
+			//TODO: unregister all SIP-AOR provided
+			
+			//set_real_sipserver_uri(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{
+			
+			
+			//TODO: unregister all SIP-AOR provided
+			
+			//TODO: clear sip server uri in database for the sip-aor
+			
+			
+			TRACE_DEBUG(INFO,"There is no SIP_Server_URI AVP in this Deregistration User Request! We just unregister SIP-AOR");
+			strcpy(result,"DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED");
+			goto out;
+		}
+	}
+	else if(assignment_type==0)
+	{
+		
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+		if(avp!=NULL)
+		{
+			unsigned char * sipserver_uri;
+			size_t sipserverurilen;
+			
+			
+			
+			
+			ret=get_sipserver_uri(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
+			
+			if(ret==0)
+			{//found
+				CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+				
+				
+				
+				
+				if(strncmp((char *)avphdr->avp_value->os.data,(char *)sipserver_uri,sipserverurilen))
+				{
+					if(got_datatype==1)
+					{
+						if(sipuserdataalreadyavailable->avp_value->i32==0)
+						{//Data not available, we must provide it
+							
+							ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+							
+							if(ret==0)
+							{
+								//We found and added datatype
+								got_datatype=1;
+							}
+							else if(ret==1)
+							{
+								//No data type was found
+								got_datatype=0;
+							}
+							else
+							{//error
+								//We couldn't make the request, we must stop process!
+								strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+								goto out;
+							}
+						}
+					}
+				}
+				else
+				{//error
+					TRACE_DEBUG(FULL,"SIP_Server_URI is different from the one in database");
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+			else
+			{
+				TRACE_DEBUG(FULL,"SIP_Server_URI is different from the one in database");
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			
+			
+			
+			
+			
+			
+			
+			//set_real_sipserver_uri(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{
+			TRACE_DEBUG(INFO, "There was no SIP_Server_URI in this request, we can't proceed request!'");
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	else if(assignment_type==9 || assignment_type==10)
+	{
+		if(count_avp(qry, CODE_SIP_AOR,0)==1)
+		{
+			//TODO: remove SIP-server URI for sip_aor
+			//TODO: unregister it
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{//There is more than 1 SIP-AOR AVP
+			strcpy(result,"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES");
+			goto out;
+		}
+	}
+	out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	//fd_msg_dump_walk(INFO,ans);
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/tools/CMakeLists.txt b/extensions/app_sip/tools/CMakeLists.txt
new file mode 100644
index 0000000..c80ccff
--- /dev/null
+++ b/extensions/app_sip/tools/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Utilities for app_sip
+PROJECT("Diameter SIP Application (RFC4740) tools" C)
+
+ADD_EXECUTABLE(freediameter-sip-rtr app_sip_rtr.c)
+ADD_EXECUTABLE(freediameter-sip-ppr app_sip_ppr.c)
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS freediameter-sip-rtr freediameter-sip-ppr
+	RUNTIME DESTINATION ${INSTALL_DAEMON_SUFFIX}
+	COMPONENT freeDiameter-sip-server)
diff --git a/extensions/app_sip/tools/app_sip_ppr.c b/extensions/app_sip/tools/app_sip_ppr.c
new file mode 100644
index 0000000..d8d8056
--- /dev/null
+++ b/extensions/app_sip/tools/app_sip_ppr.c
@@ -0,0 +1,237 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+// This file is separated from the source code because it is a separate command which will call push profile function in Diameter-SIP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+
+struct pprsipaor
+{
+	char username[200];
+	char datatype1[255];
+	char datatype2[255];
+	char datatype3[255];
+	int accounting;
+};
+
+int main (int argc, char **argv)
+{
+	SOCKET sock;
+    SOCKADDR_IN sin;
+    struct pprsipaor pprsip;
+    int numdatatype=0,i=0;
+    int port=667;
+	
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_family = AF_INET;
+    
+    
+    //We initialize the structure
+    pprsip.username[0]='\0';
+    pprsip.datatype1[0]='\0';
+    pprsip.datatype2[0]='\0';
+    pprsip.datatype3[0]='\0';
+    pprsip.accounting=0;
+    
+	//Start of arguments check
+	if(argc<3)
+	{
+		fprintf(stderr,"Missing arguments! You must at least provide a username.\n");
+		return 1;
+	}
+	
+	
+	for (i=1;i<argc;i++)
+	{
+		//We must check if it is a value or the name
+		if(strncmp(argv[i],"-",1)==0)
+		{
+			if(strcmp(argv[i],"-u")==0)
+			{
+				//Username
+				if(strlen(argv[i+1])<199)
+				{
+					strcpy(pprsip.username,argv[i+1]);
+					//We must not check the value
+					i++;
+				}
+				else
+				{
+					fprintf(stderr,"Username is too long!\n");
+				}
+			}
+			else if(strcmp(argv[i],"-t")==0)
+			{//User-data types
+				i++;
+				int j=i;
+			
+				for(j=i;j<argc;j++)
+				{
+					
+					if(strncmp(argv[i],"-",1)!=0)
+					{
+						if(strlen(argv[i])>254)
+						{
+							fprintf(stderr,"User-data type is too long!\n");
+						}
+						else
+						{
+							if(numdatatype<3)
+							{
+								switch(numdatatype)
+								{
+									case 0:
+										strcpy(pprsip.datatype1,argv[i]);
+									break;
+									case 1:
+										strcpy(pprsip.datatype2,argv[i]);
+									break;
+									case 2:
+										strcpy(pprsip.datatype3,argv[i]);
+									break;
+								}
+								numdatatype++;
+							}
+							else
+							{
+								fprintf(stderr,"You can not provide more than 3 User-data type at the same time!\n");
+								break;
+							}
+						}
+						i=j+1;
+					}
+					else
+					{
+						//We have a new argument
+						i--;
+						break;
+					}
+				}
+			}
+			else if(strcmp(argv[i],"-a")==0)
+			{
+				pprsip.accounting=1;
+				
+				
+			}
+			else if(strcmp(argv[i],"-p")==0)
+			{
+				
+				if(sscanf(argv[i+1],"%d", &port)!=1)
+				{
+					fprintf(stderr,"Incorrect port number!\n");
+					return 1;
+				}
+				
+				
+				i++;
+			}
+			
+		}
+		else
+		{
+			fprintf(stderr,"Unknown argument: %s\n",argv[i]);
+			i++;
+		}
+			
+	}
+	
+	//We set the port number
+	sin.sin_port = htons(port);
+	
+	
+	//We want a username
+	if(strlen(pprsip.username)==0)
+	{
+		fprintf(stderr,"You must provide a username!\n");
+		return 1;
+	}
+	
+    
+    fprintf(stderr,"%d!\n",port);
+   
+    /*
+    //DEBUG
+    fprintf(stderr,"*%s*\n",pprsip.username);
+	fprintf(stderr,"*%s*\n",pprsip.datatype1);
+	fprintf(stderr,"*%s*\n",pprsip.datatype2);
+	fprintf(stderr,"*%s*\n",pprsip.datatype3);
+	fprintf(stderr,"*%d*\n",pprsip.accounting);
+	
+	return 0;
+	*/
+	
+	
+	//TODO: check args
+	if(!connect(sock, (SOCKADDR*)&sin, sizeof(sin)))
+    {
+       fprintf(stderr,"Connexion succeed!\n");
+        
+ 
+        if(send(sock, &pprsip, sizeof(struct pprsipaor), 0))
+			fprintf(stderr,"sent OK!\n");
+		else
+			fprintf(stderr,"not sent\n");
+        
+    }
+    else
+    {
+        fprintf(stderr,"Unable to connect\n");
+    }
+ 
+    close(sock);
+
+	return 0;
+}
+
+
+
+
+
+
diff --git a/extensions/app_sip/tools/app_sip_rtr.c b/extensions/app_sip/tools/app_sip_rtr.c
new file mode 100644
index 0000000..21c3c60
--- /dev/null
+++ b/extensions/app_sip/tools/app_sip_rtr.c
@@ -0,0 +1,303 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+// This file is separated from the source code because it is a separate command which will call registration termination function in Diameter-SIP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct rtrsipaor
+{
+	char username[200];
+	char sip_aor1[200];
+	char sip_aor2[200];
+	char sip_aor3[200];
+	char strreason[200];
+	char desthost[200];
+	int reason;
+};
+
+int main (int argc, char **argv)
+{
+	SOCKET sock;
+    SOCKADDR_IN sin;
+    struct rtrsipaor rtrsip;
+    int numaor=0,i=0;
+	int port=666;
+	
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_family = AF_INET;
+    
+    
+    //We initialize the structure
+    rtrsip.username[0]='\0';
+    rtrsip.sip_aor1[0]='\0';
+    rtrsip.sip_aor2[0]='\0';
+    rtrsip.sip_aor3[0]='\0';
+    rtrsip.strreason[0]='\0';
+    rtrsip.desthost[0]='\0';
+    rtrsip.reason=-1;
+    
+    
+	//Start of arguments check
+	if(argc<3)
+	{
+		fprintf(stderr,"Missing arguments! You must at least provide a username.\n");
+		return 1;
+	}
+	
+	
+	for (i=1;i<argc;i++)
+	{
+		//We must check if it is a value or the name
+		if(strncmp(argv[i],"-",1)==0)
+		{
+			if(strcmp(argv[i],"-u")==0)
+			{
+				//Username
+				if(strlen(argv[i+1])<199)
+				{
+					strcpy(rtrsip.username,argv[i+1]);
+					//We must not check the value
+					i++;
+				}
+				else
+				{
+					fprintf(stderr,"Username is too long!\n");
+				}
+			}
+			else if(strcmp(argv[i],"-a")==0)
+			{
+				i++;
+				int j=i;
+			
+				for(j=i;j<argc;j++)
+				{
+					
+					if(strncmp(argv[i],"-",1)!=0)
+					{
+						if(strlen(argv[i])>199)
+						{
+							fprintf(stderr,"SIP-AOR is too long!\n");
+						}
+						else if(strncmp(argv[i],"sip",3)!=0)
+						{
+							//Bad format of SIP-AOR
+							fprintf(stderr,"A SIP-AOR must start by 'sip:' or 'sips:'. Aborting...\n");
+							return 1;
+						}
+						else
+						{
+							if(numaor<3)
+							{
+								switch(numaor)
+								{
+									case 0:
+										strcpy(rtrsip.sip_aor1,argv[i]);
+									break;
+									case 1:
+										strcpy(rtrsip.sip_aor2,argv[i]);
+									break;
+									case 2:
+										strcpy(rtrsip.sip_aor3,argv[i]);
+									break;
+								}
+								numaor++;
+							}
+							else
+							{
+								fprintf(stderr,"You can not provide more than 3 SIP-AOR at the same time!\n");
+								break;
+							}
+						}
+						i=j+1;
+					}
+					else
+					{
+						//We have a new argument
+						i--;
+						break;
+					}
+				}
+			}
+			else if(strcmp(argv[i],"-r")==0)
+			{
+				
+				if(strlen(argv[i+1])>199)
+				{
+					fprintf(stderr,"Deregistration reason is too long!\n");
+				}
+				else
+				{
+					strcpy(rtrsip.strreason,argv[i+1]);
+				}
+				i++;
+			}
+			else if(strcmp(argv[i],"-h")==0)
+			{
+				//Remote SIP Server
+				if(strlen(argv[i+1])>199)
+				{
+					fprintf(stderr,"Host is too long!\n");
+				}
+				else if(strlen(argv[i+1])<5)
+				{
+					fprintf(stderr,"Host is too short!\n");
+				}
+				else
+				{
+					strcpy(rtrsip.desthost,argv[i+1]);
+				}
+				i++;
+			}
+			else if(strcmp(argv[i],"-pt")==0)
+			{
+				//Permanent Termination
+				rtrsip.reason=0;
+			}
+			else if(strcmp(argv[i],"-nssa")==0)
+			{
+				//New SIP Server Assigned
+				rtrsip.reason=1;
+			}
+			else if(strcmp(argv[i],"-ssc")==0)
+			{
+				//SIP Server Change
+				rtrsip.reason=2;
+			}
+			else if(strcmp(argv[i],"-rss")==0)
+			{
+				//Remote SIP Server
+				rtrsip.reason=3;
+			}
+			else if(strcmp(argv[i],"-p")==0)
+			{
+				
+				if(sscanf(argv[i+1],"%d", &port)!=1)
+				{
+					fprintf(stderr,"Incorrect port number!\n");
+					return 1;
+				}
+				
+				
+				i++;
+			}
+			else
+			{
+				fprintf(stderr,"Unknown argument: %s\n",argv[i]);
+			}
+		}
+		else
+		{
+			fprintf(stderr,"Unknown argument: %s\n",argv[i]);
+			i++;
+		}
+			
+	}
+	
+	//If no SIP-AOR provided, we remove all
+	if(numaor<1)
+	{
+		fprintf(stderr,"All SIP-AOR of %s will be deregistrated.\n",rtrsip.username);
+	}
+	
+	//We want a username
+	if(strlen(rtrsip.username)==0)
+	{
+		fprintf(stderr,"You must provide a username!\n");
+		return 1;
+	}
+	
+	if(rtrsip.desthost[0]=='\0')
+	{
+		fprintf(stderr,"You must provide the hostname of SIP-Server!\n");
+		return 1;
+	}
+    
+    //We set the port number
+    sin.sin_port = htons(port);
+   
+    
+    /*
+    fprintf(stderr,"*%s*\n",rtrsip.username);
+	fprintf(stderr,"*%s*\n",rtrsip.sip_aor1);
+	fprintf(stderr,"*%s*\n",rtrsip.sip_aor2);
+	fprintf(stderr,"*%s*\n",rtrsip.sip_aor3);
+	fprintf(stderr,"*%d*\n",rtrsip.reason);
+	fprintf(stderr,"*%s*\n",rtrsip.strreason);
+	
+	//return 0;
+	*/
+	
+	
+	//TODO: check args
+	if(!connect(sock, (SOCKADDR*)&sin, sizeof(sin)))
+    {
+       fprintf(stderr,"Connexion succeed!\n");
+        
+ 
+        if(send(sock, &rtrsip, sizeof(struct rtrsipaor), 0))
+			fprintf(stderr,"sent OK!\n");
+		else
+			fprintf(stderr,"not sent\n");
+        
+    }
+    else
+    {
+        fprintf(stderr,"Unable to connect\n");
+    }
+ 
+    close(sock);
+
+	return 0;
+}
+
+
+
+
+
+
diff --git a/extensions/app_sip/userauthorization.c b/extensions/app_sip/userauthorization.c
new file mode 100644
index 0000000..f87ceb6
--- /dev/null
+++ b/extensions/app_sip/userauthorization.c
@@ -0,0 +1,337 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+
+int app_sip_UAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp, *groupedavp=NULL;
+	struct avp_hdr *avphdr, *sipaorhdr, *visitednethdr, *usernamehdr;
+	union avp_value value;
+	int ret=0, hascap=0;
+	
+	//Result_Code to return in the answer
+	char result[55];
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Retrieve SIP-AOR
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &sipaorhdr )  );
+	}
+	
+	//We check if we have a User-Name AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &usernamehdr )  );
+			
+			ret=get_password(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, NULL);
+			
+			
+			if(ret==1)
+			{//not found
+				strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+				goto out;
+			}
+			else if(ret==2)
+			{//error
+				//We couldn't make the request, we must stop process!
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			else if(ret==0)
+			{//found
+				
+				//We must check that this user can use this SIP-AOR
+				ret=check_sipaor(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, (const char *)sipaorhdr->avp_value->os.data,sipaorhdr->avp_value->os.len);
+				
+				if(ret==0)
+				{
+					//The SIP-AOR and Username are ok!
+				}
+				else if(ret==1)
+				{//not found
+					strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
+					goto out;
+				}
+				else
+				{//error
+					//We couldn't make the request, we must stop process!
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+	}
+	
+	//We check if we have a SIP-Visited-Network-Id AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Visited_Network_Id, &avp) );
+		
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &visitednethdr )  );
+		}
+		else
+			visitednethdr=NULL;
+	}
+	
+	//We check if we have a SIP_User_Authorization_Type
+	{
+		int auth_type;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_User_Authorization_Type, &avp) );
+		
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			auth_type=avphdr->avp_value->i32;
+			
+			if(auth_type==0 || auth_type==2)
+			{
+				if(visitednethdr!=NULL)
+				{
+					/*
+					If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
+					and the SIP-User-Authorization-Type AVP value received in the
+					Diameter UAR message is set to REGISTRATION or REGISTRATION&
+					CAPABILITIES, then the Diameter server SHOULD verify whether the user
+					is allowed to roam into the network specified in the
+					SIP-Visited-Network-Id AVP in the Diameter UAR message.  If the user
+					is not allowed to roam into that network, the Diameter AAA server
+					MUST set the Result-Code AVP value in the Diameter UAA message to
+					DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
+					*/
+					ret=allow_roaming(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, (const char *)visitednethdr->avp_value->os.data,visitednethdr->avp_value->os.len);
+					
+					if(ret==0)
+					{
+						//This user can come in this network
+					}
+					else if(ret==1)
+					{
+						strcpy(result,"DIAMETER_ERROR_ROAMING_NOT_ALLOWED");
+						goto out;
+					}
+					else
+					{
+						strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+						goto out;
+					}
+					
+				}
+				/*
+				If the SIP-User-Authorization-Type AVP value received in the Diameter
+				UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
+				the Diameter server SHOULD verify whether the SIP-AOR AVP value is
+				authorized to register in the Home Realm.  Where the SIP AOR is not
+				authorized to register in the Home Realm, the Diameter server MUST
+				set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
+				it in a Diameter UAA message.
+				*/
+				ret=exist_username(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len);
+				if(ret==0)
+				{
+					//The SIP_AOR exists in this realm
+				}
+				else if(ret==1)
+				{
+					strcpy(result,"DIAMETER_AUTHORIZATION_REJECTED");
+					goto out;
+				}
+				else
+				{
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+		else
+			auth_type=0; //Registration only (default value if absent)
+		
+		
+		//Let's look for the SIP_Server_URI'
+		unsigned char *sipserver_uri;
+		size_t sipserverurilen;
+		
+		ret=get_sipserver_uri(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
+		
+		if(ret==0)
+		{//We know a SIP Server so we must provide it
+			//We only add this AVP when we have registration or deregistration
+			if(auth_type==0 ||auth_type==1)
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
+				value.os.data=sipserver_uri;
+				value.os.len=sipserverurilen;
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			}
+		}
+		else if(ret==1)
+		{
+			sipserver_uri=NULL;
+			sipserverurilen=0;
+			
+		}
+		else
+		{
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		
+		//If we have a REGISTRATION or REGISTRATION & CAPABILITIES
+		if(auth_type==0 ||auth_type==2)
+		{
+			//Adding SIP-Server-Capabilities
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Capabilities, 0, &groupedavp ) );
+			
+			ret=get_sipserver_cap(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,&groupedavp);
+			
+			if(ret==0)
+			{
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+				hascap=1;
+			}
+			else if(ret==1)
+			{
+				
+				hascap=0;
+			}
+			else
+			{
+				CHECK_FCT( fd_msg_free( groupedavp ) );
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+		}
+		
+		
+		
+		if(auth_type==0)
+		{//Registration
+			
+			if(sipserver_uri==NULL)
+			{
+				strcpy(result,"DIAMETER_FIRST_REGISTRATION");
+			}
+			else
+			{
+				if(hascap==1)
+				{
+					strcpy(result,"DIAMETER_SERVER_SELECTION");
+				}
+				else
+				{
+					//We free the Capabilities AVP because we didn't found any'
+					if(groupedavp!=NULL)
+						CHECK_FCT( fd_msg_free( groupedavp ) );
+					strcpy(result,"DIAMETER_SUBSEQUENT_REGISTRATION");
+				}
+			}
+		}
+		else if(auth_type==2)
+		{//Registration & Capabilities
+			//We let the groupedavp in the message even if there is no capabilities
+			
+			if(hascap==0)
+			{
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+			}
+			strcpy(result,"DIAMETER_SUCCESS");	
+		}
+		else if(auth_type==1)
+		{//Deregistration
+			if(sipserver_uri==NULL)
+			{
+				strcpy(result,"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED");
+			}
+			else
+			{
+				strcpy(result,"DIAMETER_SUCCESS");	
+			}
+		}
+		else
+		{//We should never be here!!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	
+	
+out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	//fd_msg_dump_walk(INFO,ans);
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}