Index: extensions/app_sip/CMakeLists.txt
===================================================================
--- extensions/app_sip/CMakeLists.txt	(revision 420)
+++ extensions/app_sip/CMakeLists.txt	(revision 427)
@@ -21,5 +21,7 @@
 	multimediaauth.c
 	registrationtermination.c
+	userauthorization.c
 	pushprofile.c
+	serverassignment.c
 	locationinfo.c
 	locationinfosl.c
Index: extensions/app_sip/TODO
===================================================================
--- extensions/app_sip/TODO	(revision 420)
+++ extensions/app_sip/TODO	(revision 427)
@@ -38,2 +38,19 @@
 TODO List
 * add in malloc the size of char
+* when getting results from mysql, check lenght
+* sort capabilities in LIR/LIA
+* remove warnings in SIP plugin for gateway
+* 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!
+
+
+
+
+
+
Index: extensions/app_sip/diamsip.c
===================================================================
--- extensions/app_sip/diamsip.c	(revision 420)
+++ extensions/app_sip/diamsip.c	(revision 427)
@@ -126,4 +126,5 @@
 	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) );
@@ -136,4 +137,7 @@
 	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) );
@@ -141,4 +145,16 @@
 	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) );
@@ -176,4 +192,10 @@
 	  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( diamsip_LIR_cb, DISP_HOW_CC, &data, &diamsip_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( diamsip_UAR_cb, DISP_HOW_CC, &data, &diamsip_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( diamsip_SAR_cb, DISP_HOW_CC, &data, &diamsip_SAR_hdl ) );
 	}
 	if(as_conf->mode==2)
@@ -205,8 +227,4 @@
 		return EINVAL;
 	}
-		
-
-	
-	
 	
 	
Index: extensions/app_sip/diamsip.h
===================================================================
--- extensions/app_sip/diamsip.h	(revision 420)
+++ extensions/app_sip/diamsip.h	(revision 427)
@@ -88,4 +88,17 @@
 void close_mysql_connection();
 int get_diameter_uri(const unsigned char *sip_aor, const size_t sipaorlen, char ** diameter_uri, size_t *diameterurilen);
+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 get_user_datatype(const unsigned char  *username, const size_t usernamelen,char **table_supported, const int num_elements, struct avp **groupedavp);
+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);
+
+//count functions
+int count_supporteddatatype(const struct msg * message);
+int count_sipaor(const struct msg * message);
 
 
@@ -130,4 +143,6 @@
 int diamsip_PPA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
 int diamsip_LIR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
+int diamsip_UAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
+int diamsip_SAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
 
 //Suscriber Locator
@@ -138,18 +153,53 @@
 #define SQL_GETPASSWORD_LEN 52
 
+//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 113
+
+//sip server uri by username
 #define SQL_GETSIPURI  "SELECT `sip_server_uri` FROM ds_users WHERE `username` ='%s'"
 #define SQL_GETSIPURI_LEN 60
 
+//sip server uri by SIP-AOR
+#define SQL_GETSIPSERURI  "SELECT `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 119
+
+//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 144
+
+//user data for a user data supported
+#define SQL_GETUSEDATA  "SELECT `data_type`,`data` FROM ds_users, ds_user_data, ds_data_types WHERE `username` ='%s' AND `ds_users`.`id_user` = `ds_user_data`.`id_user` AND `ds_data_types`.`id_data_type`=`ds_user_data`.`id_data_type`"
+#define SQL_GETUSEDATA_LEN 206
+
 #define SQL_GETDIAMURI "SELECT `diameter_uri` FROM sl_sip_aor_map WHERE `sip_aor` ='%s'"
 #define SQL_GETDIAMURI_LEN 61
 
-#define SQL_SETSIPURI "UPDATE ds_users SET `sip_server_uri`='%s', `flag`=1 WHERE `username` ='%s'"
-#define SQL_SETSIPURI_LEN 74
+//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 220
+
+#define SQL_SETSIPURI "UPDATE ds_users SET `temp_sip_server_uri`='%s' WHERE `username` ='%s'"
+#define SQL_SETSIPURI_LEN 65
+
+//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 65
+//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 65
+
+#define SQL_SETFLAG "UPDATE ds_users SET `authentication_pending`=1 WHERE `username` ='%s'"
+#define SQL_SETFLAG_LEN 67
+
+#define SQL_CLEARFLAG "UPDATE ds_users SET `authentication_pending`=0, `registrated`=1 WHERE `username` ='%s'"
+#define SQL_CLEARFLAG_LEN 84
 
 #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 131
 
-#define SQL_CLEARFLAG "UPDATE ds_users SET `flag`=0 WHERE `username` ='%s'"
-#define SQL_CLEARFLAG_LEN 74
+//#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;
@@ -167,4 +217,5 @@
 	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;
@@ -172,4 +223,16 @@
 	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;
@@ -178,4 +241,7 @@
 	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;
Index: extensions/app_sip/libdiamsip.c
===================================================================
--- extensions/app_sip/libdiamsip.c	(revision 420)
+++ extensions/app_sip/libdiamsip.c	(revision 427)
@@ -166,5 +166,5 @@
 }
 
-//You must free ""result"" after using this function
+
 void request_mysql(char *query)
 {
@@ -186,67 +186,175 @@
 }
 
+//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=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_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;
+	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;
-      }
-      TRACE_DEBUG(INFO,"***********%d|%d****************\n%s\n*********************************",sipaorlen,sipaorpurelen,query);
-      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;
+
+	//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:
@@ -265,4 +373,631 @@
 
 
+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 get_user_datatype(const unsigned char  *username, const size_t usernamelen, char **table_supported, const int num_elements, struct avp **groupedavp)
+{
+	CHECK_PARAMS(table_supported && num_elements && username && usernamelen && groupedavp);
+	
+	
+	int counter=0, not_found=1;
+	union avp_value value;
+	struct avp *avp, *rootavp;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	if(num_elements<1)
+		return 1;
+	
+	//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_GETUSEDATA_LEN + usernamelen;
+			
+			
+			//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);
+			
+			
+			query = malloc(querylen+usernamelen+ 2);
+			snprintf(query, querylen+1, SQL_GETUSEDATA, username_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;
+			
+			counter=0;
+			unsigned long *length=0;
+			
+			//int index=0;//current field number
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				length=mysql_fetch_lengths(res);
+				
+				for(counter=0;counter<num_elements; counter++)
+				{
+					//TODO: check length
+					if(strcmp(table_supported[counter],row[0]))
+					{
+						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 ) );
+						value.os.data=(unsigned char *)table_supported[counter];
+						value.os.len=strlen(table_supported[counter]);
+						CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+						CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+						//This was used
+						table_supported[counter]=NULL;
+						
+						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]*sizeof(unsigned char));
+						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_add ( *groupedavp, MSG_BRW_LAST_CHILD, rootavp) );
+						not_found=0;
+					}
+				}
+				//index++;
+			}
+			
+			mysql_free_result(res);
+			free(query);
+			free(username_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);
+	
+	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 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);
+	
+	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 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);
+	
+	int not_found=2;
+	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);
+	
+	int not_found=2;
+	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);
+	
+	int not_found=2;
+	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, 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(*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_sipaor(const struct msg * message)
+{
+	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==122 && temphdr->avp_vendor==0)
+		{
+			counter++;
+		}
+		
+		CHECK_FCT(fd_msg_browse ( &message, MSG_BRW_WALK, &avp, NULL));
+	}
+	return counter;
+}
+int count_supporteddatatype(const struct msg * message)
+{
+	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==388 && temphdr->avp_vendor==0)
+		{
+			counter++;
+		}
+		
+		CHECK_FCT(fd_msg_browse ( &message, MSG_BRW_WALK, &avp, NULL));
+	}
+	return counter;
+}
 /*
 void nonce_add_element(char * nonce)
Index: extensions/app_sip/locationinfo.c
===================================================================
--- extensions/app_sip/locationinfo.c	(revision 420)
+++ extensions/app_sip/locationinfo.c	(revision 427)
@@ -45,4 +45,5 @@
 	struct avp_hdr *avphdr;
 	union avp_value value;
+	int ret=0;
 	
 	//Result_Code to return in the answer
@@ -58,4 +59,11 @@
 	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 
 	{
@@ -69,5 +77,5 @@
 	}
 	
-	//TODO: wait for answer from authors to clear how to find SIP server!
+	
 	//Add a SIP_Server_URI
 	{
@@ -75,24 +83,114 @@
 		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
 		
-		//We extract Realm from SIP_AOR
-		char *realm=NULL;
-		
-		
-		realm = strtok( (char *)(avphdr->avp_value->os.data), "@" );
-		realm = strtok( NULL, "@" );
-		
-		if(realm!=NULL)
+		
+		
+		
+		
+		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
+		int sipserverurilen;
+		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)
 		{
-			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
-			value.os.data=(unsigned char *)realm;
-			value.os.len=strlen(realm);
-			CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
-			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+			//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
 		{
-			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
-			goto out;
-		}
+			
+			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;
+		}
+		
+		
+		
 	}
 	
Index: extensions/app_sip/locationinfosl.c
===================================================================
--- extensions/app_sip/locationinfosl.c	(revision 420)
+++ extensions/app_sip/locationinfosl.c	(revision 427)
@@ -61,6 +61,4 @@
 	ans = *msg;
 	
-	//DEBUG
-	fd_msg_dump_walk(INFO,qry);
 	
 	//Add the Auth-Application-Id 
@@ -91,5 +89,5 @@
 		char * diameter_uri=NULL;
 		
-		TRACE_DEBUG(INFO,"***********%d*********************************************",avphdr->avp_value->os.len);
+		
 		
 		ret=get_diameter_uri(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &diameter_uri, &diameterurilen);
@@ -108,5 +106,5 @@
 		    CHECK_FCT( fd_msg_avp_new ( sip_dict.Redirect_Host, 0, &avp ) );
 		    value.os.data=diameter_uri;
-		    value.os.len=strlen(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 ) );
@@ -121,5 +119,5 @@
 		else if(ret==1)
 		{//not found
-			//We don't know this SIP_AOR in SL, that means 
+			//We don't know this SIP_AOR in SL
 			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
 			goto out;
@@ -132,35 +130,4 @@
 		}
 	}
-	
-	/*
-	//TODO: wait for answer from authors to clear how to find SIP server!
-	//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 )  );
-		
-		//We extract Realm from SIP_AOR
-		char *realm=NULL;
-		
-		
-		realm = strtok( (char *)(avphdr->avp_value->os.data), "@" );
-		realm = strtok( NULL, "@" );
-		
-		if(realm!=NULL)
-		{
-			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
-			value.os.data=(unsigned char *)realm;
-			value.os.len=strlen(realm);
-			CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
-			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
-		}
-		else
-		{
-			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
-			goto out;
-		}
-	}
-	
-	*/
 	
 	
Index: extensions/app_sip/multimediaauth.c
===================================================================
--- extensions/app_sip/multimediaauth.c	(revision 420)
+++ extensions/app_sip/multimediaauth.c	(revision 427)
@@ -48,5 +48,5 @@
 	char * result;
 	char password[51];
-	int idx=0, number_of_auth_items=0,i=0;
+	int idx=0, number_of_auth_items=0,i=0, ret=0;
 	//Flags and variables for Database
 	int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
@@ -122,8 +122,5 @@
 			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
 			
-			//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, username, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+			
 			
 			
@@ -132,15 +129,8 @@
 				not_found=1;
 				
-				//We copy username in query
-				querylen=SQL_GETPASSWORD_LEN + usernamelen;
-				query = malloc(querylen+2);
-				snprintf(query, querylen+1, SQL_GETPASSWORD, username);
-				
-				
-				
-				//We make the query	
-				request_mysql(query);
-				res=mysql_use_result(conn);
-				if(res==NULL)
+				//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
@@ -148,20 +138,7 @@
 					goto out;
 				}
-			
-			
-			
-				while ((row = mysql_fetch_row(res)) != NULL)
-      				{
-      					if(strlen(row[0])>0)
-      					{
-      						strcpy(password,row[0]);
-      						not_found=0;
-      						break;
-      					}
-      				}
-      				mysql_free_result(res);
-      				free(query);
-      				
-      				if(not_found)
+				not_found=ret;
+				
+				if(not_found)
 				{
 					TRACE_DEBUG(FULL,"The user %s doesn't exist!",username);
@@ -172,5 +149,9 @@
 			
 			
-			
+				//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, 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;
@@ -194,15 +175,15 @@
 				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(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)
+				if(not_found)
 				{
 					TRACE_DEBUG(FULL,"The user %s can't use this SIP-AOR!",username);
@@ -244,28 +225,26 @@
 				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)
-				{
-					//We update the SIP_URI for the user and we flag "authentication in progress"
-					querylen=SQL_SETSIPURI_LEN + usernamelen + sipurilen;
-					query = malloc(querylen+2);
-					snprintf(query, querylen+1, SQL_SETSIPURI, sipuri, username);
-			
-					//We make the query
-					request_mysql(query);
+				{
+					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);
 					
-	      				free(query);
-	      				authenticationpending=1;
-				}
-      				free(sipuri);
+					
+					set_pending_flag(username, usernamelen);
+					
+					
+					authenticationpending=1;
+				}
+				free(sipuri);
 				
 			}
@@ -715,13 +694,6 @@
 								if(username!=NULL && authenticationpending)
 								{
-									//We clear the flag "authentication pending"
-									querylen=SQL_CLEARFLAG_LEN + usernamelen;
-									query = malloc(querylen+2);
-									snprintf(query, querylen+1, SQL_CLEARFLAG, username);
-		
-									//We make the query
-									request_mysql(query);
-				
-					      				free(query);
+									//We clear the pending flag
+									clear_pending_flag(username, usernamelen);
 								}
 								
Index: extensions/app_sip/serverassignment.c
===================================================================
--- extensions/app_sip/serverassignment.c	(revision 427)
+++ extensions/app_sip/serverassignment.c	(revision 427)
@@ -0,0 +1,461 @@
+/*********************************************************************************************************
+* 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 "diamsip.h"
+
+
+int diamsip_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, 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, *usernamehdr, *sipuserdataalreadyavailable;
+	union avp_value value;
+	int ret=0, assignment_type=0, supported_datatype=0, got_datatype=0;
+	
+	
+	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, 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;
+	}
+	
+	//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO : check which assignment need data type
+	//We check if we have SIP_Supported_User_Data_Type and we make a table with all of them
+	{
+		supported_datatype=count_supporteddatatype(qry);
+		
+		if(supported_datatype>0)
+		{
+			char ** table_supporteddatatype=NULL;
+			
+			//TODO: maybe table doesn't work'
+			//We make a table of char * to store all supported datatypes
+			CHECK_MALLOC(table_supporteddatatype=(char**)realloc(table_supporteddatatype,supported_datatype*sizeof(char *)));
+			
+			
+			CHECK_FCT(fd_msg_browse ( qry, MSG_BRW_WALK, &avp, NULL));
+			int counter=0;
+			
+			while(avp!=NULL)
+			{
+				
+				CHECK_FCT( fd_msg_avp_hdr( avp,&avphdr ));
+				
+				//TODO: check if counter is good!
+				if(avphdr->avp_code==388 && avphdr->avp_vendor==0 && counter<supported_datatype)
+				{
+					
+					CHECK_MALLOC(table_supporteddatatype[counter]=malloc(avphdr->avp_value->os.len+1));
+					strncpy(table_supporteddatatype[counter],avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+					table_supporteddatatype[counter][avphdr->avp_value->os.len+1]='\0';
+					
+					counter++;
+				}
+				
+				CHECK_FCT(fd_msg_browse ( qry, MSG_BRW_WALK, &avp, NULL));
+			}
+			
+			if(usernamehdr!=NULL)
+			{
+				ret=get_user_datatype(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len,(char **)table_supporteddatatype, counter, &groupedavp);
+				
+				//We free all unused datatypes
+				int i=0;
+				for(i=0;i<counter;i++)
+				{
+					if(table_supporteddatatype[counter]!=NULL)
+						free(table_supporteddatatype[counter]);
+				}
+				
+				if(ret==0)
+				{
+					got_datatype=1;
+					
+				}
+				else if(ret==1)
+				{
+					TRACE_DEBUG(INFO,"There was no link between supported and transmisted SIP-User-Data AVPs");
+				}
+				else
+				{
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+				
+			}
+			else
+			{
+				strcpy(result,"DIAMETER_USER_NAME_REQUIRED");
+				int i=0;
+				for(i=0;i<counter;i++)
+				{
+					if(table_supporteddatatype[counter]!=NULL)
+						free(table_supporteddatatype[counter]);
+				}
+				goto out;
+			}
+			
+		}
+	}
+	
+	//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_sipaor(qry)==1)
+		{
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				if(got_datatype==1)
+				{
+					//We provide User Data
+					CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+				}
+			}
+			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_sipaor(qry)==1)
+		{
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				if(got_datatype==1)
+				{
+					//We provide User Data
+					CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+				}
+			}
+			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)
+			{
+				//We provide User Data
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+			}
+		}
+		
+		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
+				
+				//We provide User Data
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+			}
+			else
+			{
+				CHECK_FCT( fd_msg_free( groupedavp ) );
+			}
+		}
+		
+		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)
+		{
+			//TODO: check that SIP-server_URI provided is the same as associated and answer unable to comply if so
+			//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO here
+			
+			
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			if(got_datatype==1)
+			{
+				if(sipuserdataalreadyavailable->avp_value->i32==0)
+				{//Data not available, we must provide it
+					
+					//We provide User Data
+					CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+				}
+				else
+				{
+					CHECK_FCT( fd_msg_free( groupedavp ) );
+				}
+			}
+			
+			
+			
+			
+			//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-AOR 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_sipaor(qry)==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;
+}
Index: extensions/app_sip/userauthorization.c
===================================================================
--- extensions/app_sip/userauthorization.c	(revision 427)
+++ extensions/app_sip/userauthorization.c	(revision 427)
@@ -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 "diamsip.h"
+
+
+int diamsip_UAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, 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, 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, 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'
+		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;
+}
