view extensions/app_sip/libapp_sip.c @ 1424:c8057892e56b

adapt extensions to fd_msg_search_avp(struct avp) Remove now-unnecessary fd_avp_search_avp() implementations now that fd_msg_search_avp() can be used. TODO: rt_rewrite.fdx still uses own version because that does extra validation and logging (that may or may not be necessary).
author Luke Mewburn <luke@mewburn.net>
date Wed, 19 Feb 2020 10:24:13 +1100
parents 0d08a9ab2212
children
line wrap: on
line source

/*********************************************************************************************************
* 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;
}

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);
	}
}
*/
"Welcome to our mercurial repository"