changeset 284:397cdcd41f53

New app_acct in progress, backup only
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 28 Apr 2010 18:54:08 +0900
parents f433bc04eb6a
children 0daf6fc2b751
files cmake/Modules/FindGnuTLS.cmake cmake/Modules/FindPostgreSQL.cmake cmake/Modules/FindSCTP.cmake doc/app_acct.conf.sample extensions/app_acct/CMakeLists.txt extensions/app_acct/acct_conf.l extensions/app_acct/acct_conf.y extensions/app_acct/acct_db.c extensions/app_acct/acct_records.c extensions/app_acct/app_acct.c extensions/app_acct/app_acct.h
diffstat 11 files changed, 1113 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/Modules/FindGnuTLS.cmake	Tue Apr 27 15:46:21 2010 +0900
+++ b/cmake/Modules/FindGnuTLS.cmake	Wed Apr 28 18:54:08 2010 +0900
@@ -5,9 +5,9 @@
 #  GNUTLS_INCLUDE_DIRS - where to find gnutls.h, etc.
 #  GNUTLS_LIBRARIES - List of libraries when using gnutls.
 
-if (GNUTLS_INCLUDE_DIRS)
+if (GNUTLS_INCLUDE_DIRS AND GNUTLS_LIBRARIES)
   set(GNUTLS_FIND_QUIETLY TRUE)
-endif (GNUTLS_INCLUDE_DIRS)
+endif (GNUTLS_INCLUDE_DIRS AND GNUTLS_LIBRARIES)
 
 # Include dir
 find_path(GNUTLS_INCLUDE_DIR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/Modules/FindPostgreSQL.cmake	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,36 @@
+# - Find PostgreSQL library
+#
+# This module defines:
+#  POSTGRESQL_FOUND - True if the package is found
+#  POSTGRESQL_INCLUDE_DIR - containing libpq-fe.h
+#  POSTGRESQL_LIBRARIES - Libraries to link to use PQ functions.
+
+if (POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES)
+  set(POSTGRESQL_FIND_QUIETLY TRUE)
+endif (POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES)
+
+# Include dir
+find_path(POSTGRESQL_INCLUDE_DIR 
+	NAMES libpq-fe.h
+	PATH_SUFFIXES postgresql
+)
+
+# Library
+find_library(POSTGRESQL_LIBRARY 
+  NAMES pq
+)
+
+# handle the QUIETLY and REQUIRED arguments and set POSTGRESQL_FOUND to TRUE if 
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(POSTGRESQL DEFAULT_MSG POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR)
+
+IF(POSTGRESQL_FOUND)
+  SET( POSTGRESQL_LIBRARIES ${POSTGRESQL_LIBRARY} )
+ELSE(POSTGRESQL_FOUND)
+  SET( POSTGRESQL_LIBRARIES )
+ENDIF(POSTGRESQL_FOUND)
+
+# Lastly make it so that the POSTGRESQL_LIBRARY and POSTGRESQL_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( POSTGRESQL_LIBRARIES POSTGRESQL_INCLUDE_DIR )
--- a/cmake/Modules/FindSCTP.cmake	Tue Apr 27 15:46:21 2010 +0900
+++ b/cmake/Modules/FindSCTP.cmake	Wed Apr 28 18:54:08 2010 +0900
@@ -5,9 +5,9 @@
 #  SCTP_INCLUDE_DIRS - the SCTP include directories
 #  SCTP_LIBRARIES - link these to use SCTP
 
-if (SCTP_INCLUDE_DIRS)
+if (SCTP_INCLUDE_DIRS AND SCTP_LIBRARIES)
   set(SCTP_FIND_QUIETLY TRUE)
-endif (SCTP_INCLUDE_DIRS)
+endif (SCTP_INCLUDE_DIRS AND SCTP_LIBRARIES)
 
 # Include dir
 find_path(SCTP_INCLUDE_DIR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/app_acct.conf.sample	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,73 @@
+#######################
+# This file contains the description of configuration and general information about the
+# "App_Acct" extension.
+
+# This extension provides a simple Diameter Accounting server.
+#  The extension does receive the Accounting-Request message, then
+# saves the contents of the AVP in a database, as configured here.
+#  The data is not processed at all. The intent is that a dedicated
+# application will then pull from this database and process the data (consolidate 
+# sessions, ...)
+
+# In order to enable this extension, the main freeDiameter configuration file
+# must contain the following declaration:
+# LoadExtension = "extensions/app_acct.fdx" : "/path/to/app_acct.conf" ;
+#######################
+
+#################
+## Part I: AVP ##
+#################
+
+# Configure here the AVPs that must be stored in the database.
+# The format is:
+#	  "AVP-dictionary-name" = {
+#		field = "db-field-name";
+#		required;
+#		multi=N;
+#	  };
+# Where:
+#  AVP-dictionary-name:
+# 	The name of the AVP, such as "Session-Id". Only this field is mandatory.
+#  field="...":
+#	The name of the field in the database where is AVP contents will be saved.
+#	The default is that the field is named as the AVP-dictionary-name.
+#  required:
+#	By default, if the AVP is not in the Diameter message, it is not passed in 
+#	the INSERT statement (will get NULL). If Required is specified for the AVP,
+#	an error is returned in the Diameter answer, and the data is discarded.
+#  multi=N:
+#	If an AVP may appear several times in a request, you may specify a number of
+#	occurrences to save in the database. The Nth first occurrences of the AVP 
+#	will be saved in fields "db-field-name1", "db-field-name2", ... "db-field-nameN"
+#
+# In case the default behavior for an AVP is fine, you can use the short syntax:
+#  "AVP-dictionary-name";
+#
+# Note that at the moment, GROUPED AVP are not supported. Also, only the top-level AVPs are
+# search. This behavior can be changed quite easily if needed.
+
+
+#######################
+## Part II: Database ##
+#######################
+
+# You must specify the connection information to the database here.
+# Please note that if the connection is terminated, it will trig the shutdown of the freeDiameter daemon
+# For this reason, you should as much as possible use a local database.
+
+# ConnInfo:
+# The connection string to the database. See http://www.postgresql.org/docs/8.4/static/libpq-connect.html
+# Example: ConnInfo = "host=localhost port=5432 dbname=acct user=acct password=freediameter";
+
+# Table:
+# The name of the table to use. The fields and types in this table must be created accordingly to the Part I configuration in this file.
+# Example: Table = "incoming";
+
+# Timestamp_field:
+# Optionaly, you can specify a name of a field that will receive the value 'now' when a new record is inserted.
+# Default: no timestamp is inserted.
+# Example: Timestamp_field = "inc_ts";
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/CMakeLists.txt	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,28 @@
+# The dict_nasreq extension
+PROJECT("Simple Accounting server" C)
+
+########################
+# Search for libpg (postgresql package)
+FIND_PACKAGE(PostgreSQL REQUIRED)
+INCLUDE_DIRECTORIES(${POSTGRESQL_INCLUDE_DIR})
+
+########################
+# Parser files
+BISON_FILE(acct_conf.y)
+FLEX_FILE(acct_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.acct_conf.c acct_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( APP_ACCT_SRC
+	app_acct.h
+	app_acct.c
+	lex.acct_conf.c
+	acct_conf.tab.c
+	acct_conf.tab.h
+	acct_db.c
+	acct_records.c
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(app_acct ${APP_ACCT_SRC})
+TARGET_LINK_LIBRARIES(app_acct ${POSTGRESQL_LIBRARIES})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/acct_conf.l	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,139 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2010, WIDE Project and NICT								 *
+* 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 WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* 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.								 *
+*********************************************************************************************************/
+
+/* Lex extension's configuration parser.
+ *
+ */
+
+%{
+#include "app_acct.h"
+#include "acct_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+/* Quoted string. Multilines do not match. */
+qstring		\"[^\"\n]*\"
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s\n", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+	/* Recognize quoted strings -- we do not support escaped \" in the string currently. */
+{qstring}		{
+				/* Match a quoted string. Let's be very permissive. */
+				yylval->string = strdup(yytext+1);
+				if (!yylval->string) {
+					fd_log_debug("Unable to copy the string '%s': %s\n", yytext, strerror(errno));
+					TRACE_DEBUG(INFO, "strdup failed");
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+			
+	/* Recognize the tokens */	
+(?i:"ConnInfo")		{
+				return CONNINFO;
+			}
+
+(?i:"Table")		{
+				return TABLE;
+			}
+
+(?i:"Timestamp_field")	{
+				return TSFIELD;
+			}
+
+(?i:"field")		{
+				return FIELD;
+			}
+
+(?i:"required")		{
+				return REQUIRED;
+			}
+
+(?i:"multi")		{
+				return MULTI;
+			}
+
+
+			
+	/* Valid single characters for yyparse */
+[=;{}]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]"*=>;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.\n", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/acct_conf.y	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,317 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2010, WIDE Project and NICT								 *
+* 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 WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* 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.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/app_acct.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "app_acct.h"
+#include "acct_conf.tab.h"
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* the global configuration */
+struct acct_conf * acct_config = NULL;
+
+/* Initialize the blank configuration structure */
+int acct_conf_init(void)
+{
+	TRACE_ENTRY();
+	
+	CHECK_MALLOC( acct_config = malloc(sizeof(struct acct_conf)) );
+	memset(acct_config, 0, sizeof(struct acct_conf) );
+	fd_list_init(&acct_config->avps, NULL);
+	
+	return 0;
+}
+
+/* Validate and eventually display the content of the configuration file for debug */
+int acct_conf_check(char * conffile)
+{
+	CHECK_PARAMS(acct_config);
+	
+	if ( ! acct_config->conninfo) {
+		fd_log_debug("[app_acct] ERROR: 'ConnInfo' is missing in file '%s'.\n"
+			" You can specify 'ConnInfo=\"\";' to use default parameters.\n", conffile);
+		return EINVAL;
+	}
+	if ( ! acct_config->tablename) {
+		fd_log_debug("[app_acct] ERROR: 'Table' value is missing in file '%s'.\n", conffile);
+		return EINVAL;
+	}
+
+	struct fd_list * li;
+	if (!TRACE_BOOL(FULL))
+		return;
+		
+	fd_log_debug("[app_acct] Configuration dump:\n");
+	fd_log_debug(" Database:\n");
+	fd_log_debug("   ConnInfo ...... : '%s'\n", acct_config->conninfo ?: "<null>");
+	fd_log_debug("   Table name .... : '%s'\n", acct_config->tablename ?: "<null>");
+	fd_log_debug("   Timestamp field : '%s'\n", acct_config->tsfield ?: "<null>");
+	fd_log_debug(" AVPs that will be saved to the database:\n");
+	for (li = acct_config->avps.next; li != &acct_config->avps; li = li->next) {
+		struct acct_conf_avp * a = (struct acct_conf_avp *)li;
+		fd_log_debug("   %-*s AVP%s saved in ", 30, a->avpname, a->required ? " [required]":"" );
+		if (a->multi) {
+			fd_log_debug("fields '%s[1..%d]' ", a->field?:a->avpname, a->multi);
+		} else {
+			fd_log_debug("field '%s' ", a->field?:a->avpname);
+		}
+		fd_log_debug("as ::%s\n", diam2db_types_mapping[a->avptype]);
+	}
+	fd_log_debug("[app_acct] Complete.\n");
+}
+
+void acct_conf_free(void)
+{
+	TRACE_ENTRY();
+	
+	if (!acct_config)
+		return;
+		
+	/* Destroy the list */
+	while (!FD_IS_LIST_EMPTY(&acct_config->avps)) {
+		struct acct_conf_avp * a = (struct acct_conf_avp *)(acct_config->avps.next);
+		fd_list_unlink(&a->chain);
+		free(a->avpname);
+		free(a->field);
+		free(a);
+	}
+	
+	/* destroy other data */
+	free(acct_config->conninfo);
+	free(acct_config->tablename);
+	free(acct_config->tsfield);
+	
+	/* Done */
+	free(acct_config);
+	acct_config = NULL;
+}
+
+/* Parse the configuration file */
+int acct_conf_parse(char * conffile)
+{
+	extern FILE * acct_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	acct_confin = fopen(conffile, "r");
+	if (acct_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s\n", conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(acct_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s\n", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s\n", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s\n", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+static struct acct_conf_avp avpdata;
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;	/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Keywords */
+%token 		FIELD
+%token 		REQUIRED
+%token 		MULTI
+%token 		CONNINFO
+%token 		TABLE
+%token 		TSFIELD
+
+/* Tokens and types */
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK for the parser (will be validated afterwards) */
+			| conffile avpline
+			| conffile conninfoline
+			| conffile tableline
+			| conffile tsfieldline
+			| conffile errors
+			{
+				yyerror(&yylloc, conffile, "An error occurred while parsing the configuration file.");
+				return EINVAL;
+			}
+			;
+
+			/* Catch lexical and syntax errors */
+errors:			LEX_ERROR
+			| error
+			;
+
+	/* The tokens */
+avpline:		{
+				memset(&avpdata, 0, sizeof(struct acct_conf_avp));
+			}
+			QSTRING avpcontents ';'
+			{
+				struct acct_conf_avp *new;
+				struct dict_object * dict;
+				struct dict_avp_data dictdata;
+				
+				/* Validate the avp name first */
+				CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, $2, &dict, ENOENT),
+					{ yyerror (&yylloc, conffile, "AVP definition not found in the dictionary. Was the appropriate dict_*.fdx extension loaded?"); YYERROR; } );
+				CHECK_FCT( fd_dict_getval( dict, &dictdata ));
+				
+				/* Create a new entry */
+				CHECK_MALLOC_DO( new = malloc(sizeof(struct acct_conf_avp)),
+					{ yyerror (&yylloc, conffile, "Out of memory"); YYERROR; } );
+				
+				/* Retrieve all the data from avpcontents parsing (field, required, multi) */	
+				memcpy(new, &avpdata, sizeof(struct acct_conf_avp));
+				
+				/* Initialize the other data */
+				fd_list_init(&new->chain, NULL);
+				new->avpname = $2;
+				new->avpobj = dict;
+				new->avptype = dictdata.avp_basetype;
+			
+				/* Add this new entry at the end of the list */
+				fd_list_insert_before( &acct_config->avps, &new->chain );
+			}
+			;
+			
+avpcontents:		/* Empty content is fine */
+			| '=' '{' avpflagline '}'
+			;
+			
+avpflagline:		/* Empty flags is also fine */
+			| avpflagline FIELD '=' QSTRING ';'
+			{
+				if (avpdata.field) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				avpdata.field = $4;
+			}
+			| avpflagline REQUIRED ';'
+			{
+				avpdata.required = 1;
+			}
+			| avpflagline MULTI '=' INTEGER ';'
+			{
+				avpdata.multi = (unsigned) $4;
+			}
+			;
+	
+conninfoline:		CONNINFO '=' QSTRING ';'
+			{
+				if (acct_config->conninfo) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->conninfo = $3
+			}
+			;
+
+tableline:		TABLE '=' QSTRING ';'
+			{
+				if (acct_config->tablename) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->tablename = $3
+			}
+			;
+
+tsfieldline:		TSFIELD '=' QSTRING ';'
+			{
+				if (acct_config->tsfield) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->tsfield = $3
+			}
+			;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/acct_db.c	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,193 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2010, WIDE Project and NICT								 *
+* 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 WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* 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.								 *
+*********************************************************************************************************/
+
+/* Database interface module */
+
+#include "app_acct.h"
+#include <libpq-fe.h>
+
+const char * diam2db_types_mapping[AVP_TYPE_MAX + 1] = {
+	"" 		/* AVP_TYPE_GROUPED */,
+	"bytea" 	/* AVP_TYPE_OCTETSTRING */,
+	"integer" 	/* AVP_TYPE_INTEGER32 */,
+	"bigint" 	/* AVP_TYPE_INTEGER64 */,
+	"integer" 	/* AVP_TYPE_UNSIGNED32 + cast */,
+	"bigint" 	/* AVP_TYPE_UNSIGNED64 + cast */,
+	"real" 		/* AVP_TYPE_FLOAT32 */,
+	"double precision" /* AVP_TYPE_FLOAT64 */
+};
+
+static const char * stmt = "acct_db_stmt";
+static PGconn *conn = NULL;
+
+int acct_db_init(void)
+{
+	struct acct_record_list emptyrecords;
+	struct fd_list * li;
+	char * sql=NULL;   /* The buffer that will contain the SQL query */
+	size_t sql_allocd = 0; /* The malloc'd size of the buffer */
+	size_t sql_offset = 0; /* The actual data already written in this buffer */
+	size_t p;
+	int idx = 0;
+	PGresult * res;
+	#define REALLOC_SIZE	1024
+	
+	TRACE_ENTRY();
+	CHECK_PARAMS( acct_config && acct_config->conninfo && acct_config->tablename ); 
+	
+	/* Use the information from acct_config to create the connection and prepare the query */
+	conn = PQconnectdb(acct_config->conninfo);
+	
+	/* Check to see that the backend connection was successfully made */
+	if (PQstatus(conn) != CONNECTION_OK) {
+		fd_log_debug("Connection to database failed: %s\n", PQerrorMessage(conn));
+		acct_db_free();
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(INFO, "Connection to database successfull: user:%s, db:%s, host:%s.", PQuser(conn), PQdb(conn), PQhost(conn));
+	}
+	
+	/* Now, prepare the request object */
+	
+	/* First, we build the list of AVP we will insert in the database */
+	CHECK_FCT( acct_rec_prepare(&emptyrecords) );
+	
+	/* Now, prepare the text of the request */
+	CHECK_MALLOC(sql = malloc(REALLOC_SIZE));
+	sql_allocd = REALLOC_SIZE;
+	
+	/* This macro hides the details of extending the buffer on each sprintf... */
+	#define ADD_EXTEND(args...) {									\
+		size_t p;										\
+		int loop = 0;										\
+		do {											\
+			p = snprintf(sql + sql_offset, sql_allocd - sql_offset, ##args);		\
+			if (p >= sql_allocd - sql_offset) {						\
+				/* Too short, extend the buffer and start again */			\
+				CHECK_MALLOC( sql = realloc(sql, sql_allocd + REALLOC_SIZE) );		\
+				sql_allocd += REALLOC_SIZE;						\
+				loop++;									\
+				ASSERT(loop < 100); /* detect infinite loops */				\
+				continue;								\
+			}										\
+			sql_offset += p;								\
+			break;										\
+		} while (1);										\
+	}
+	
+	/* This macro allows to add a value in the SQL buffer while escaping in properly */
+	#define ADD_ESCAPE(str) {									\
+		char * __s = (char *)str;								\
+		/* Check we have at least twice the size available +1 */				\
+		size_t p = strlen(__s);									\
+													\
+		while (sql_allocd - sql_offset < 2 * p + 1) {						\
+			/* Too short, extend the buffer */						\
+			CHECK_MALLOC( sql = realloc(sql, sql_allocd + REALLOC_SIZE) );			\
+			sql_allocd += REALLOC_SIZE;							\
+		}											\
+													\
+		/* Now add the escaped string */							\
+		p = PQescapeStringConn(conn, sql+sql_offset, __s, p, NULL);				\
+		sql_offset += p;									\
+	}
+	
+	/* INSERT INTO table (tsfield, field1, field2, ...) VALUES (now, $1::bytea, $2::integer, ...) */
+	ADD_EXTEND("INSERT INTO %s (", acct_config->tablename);
+	
+	if (acct_config->tsfield) {
+		ADD_EXTEND("\"");
+		ADD_ESCAPE(acct_config->tsfield);
+		ADD_EXTEND("\", ");
+	}
+	
+	for (li = emptyrecords.all.next; li != &emptyrecords.all; li = li->next) {
+		struct acct_record_item * i = (struct acct_record_item *)(li->o);
+		ADD_EXTEND("\"");
+		ADD_ESCAPE(i->param->field?:i->param->avpname);
+		if (i->index) {
+			ADD_EXTEND("%d", i->index);
+		}
+		if (li->next != &emptyrecords.all) {
+			ADD_EXTEND("\", ");
+		}
+	}
+	
+	ADD_EXTEND("\") VALUES (");
+	
+	if (acct_config->tsfield) {
+		ADD_EXTEND("'now', ");
+	}
+	
+	for (li = emptyrecords.all.next; li != &emptyrecords.all; li = li->next) {
+		struct acct_record_item * i = (struct acct_record_item *)(li->o);
+		idx += 1;
+		ADD_EXTEND("$%d::%s", idx, diam2db_types_mapping[i->param->avptype]);
+		
+		if (li->next != &emptyrecords.all) {
+			ADD_EXTEND(", ");
+		}
+	}
+	
+	ADD_EXTEND(");");
+	
+	TRACE_DEBUG(FULL, "Preparing the following SQL statement:\n%s\n", sql);
+	res = PQprepare(conn, stmt, sql, emptyrecords.nball, NULL);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+		TRACE_DEBUG(INFO, "Preparing statement '%s' failed: %s",
+			sql, PQerrorMessage(conn));
+		PQclear(res);
+		return EINVAL;
+        }
+	PQclear(res);
+	
+	
+
+	return 0;
+}
+
+void acct_db_free(void)
+{
+	if (conn)
+		PQfinish(conn);
+	conn = NULL;
+}
+
+int acct_db_insert(struct acct_record_list * records)
+{
+	return ENOTSUP;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/acct_records.c	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,83 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2010, WIDE Project and NICT								 *
+* 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 WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* 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.								 *
+*********************************************************************************************************/
+
+/* Functions to create a list of AVPs according to the configuration file */
+
+#include "app_acct.h"
+
+/* Prepare a list of acct_record entries from the configuration, without mapping any value at this time */
+int acct_rec_prepare(struct acct_record_list * records)
+{
+	struct fd_list * li;
+	TRACE_ENTRY("%p", records);
+	CHECK_PARAMS( records && acct_config );
+	
+	/* Prepare the records structure */
+	memset(records, 0, sizeof(struct acct_record_list));
+	fd_list_init(&records->all, records);
+	fd_list_init(&records->unmaped, records);
+	
+	/* for each entry in the configuration */
+	for (li = acct_config->avps.next; li != &acct_config->avps; li = li->next) {
+		struct acct_conf_avp * a = (struct acct_conf_avp *)li;
+		struct acct_record_item * new;
+		int i = a->multi ? 1 : 0;
+		/* Create as many records as the 'multi' parameter requires */
+		do {
+			CHECK_MALLOC( new = malloc(sizeof(struct acct_record_item)) );
+			memset(new, 0, sizeof(struct acct_record_item));
+			fd_list_init(&new->chain, new);
+			fd_list_init(&new->unmapd, new);
+			new->param = a;
+			new->index = i;
+			fd_list_insert_before(&records->all, &new->chain);
+			fd_list_insert_before(&records->unmaped, &new->unmapd);
+			records->nball++;
+			records->nbunmap++;
+			i++;
+		} while (i <= a->multi);
+	}
+	
+	return 0;
+}
+
+int acct_rec_map(struct acct_record_list * records, struct msg * msg)
+{
+	TRACE_ENTRY("%p %p", records, msg);
+	
+	/* For each AVP in the message, search if we have a corresponding unmap'd record */
+	
+	return ENOTSUP;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/app_acct.c	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,127 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2010, WIDE Project and NICT								 *
+* 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 WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* 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.								 *
+*********************************************************************************************************/
+
+/* The simple Accounting server for freeDiameter */
+
+#include "app_acct.h"
+
+/* Default callback for the Accounting application. */
+static int acct_fallback( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
+{
+	/* This CB should never be called */
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	fd_log_debug("Unexpected message received!\n");
+	
+	return ENOTSUP;
+}
+
+
+/* Callback for incoming Base Accounting Accounting-Request messages */
+static int acct_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
+{
+	struct msg_hdr *hdr = NULL;
+	struct msg *ans, *qry;
+	struct avp * a = NULL;
+	struct avp_hdr * h = NULL;
+	char * s;
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	if (msg == NULL)
+		return EINVAL;
+	
+	qry = *msg;
+	/* Create the answer message, including the Session-Id AVP */
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+
+	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+	CHECK_FCT( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+
+	fd_log_debug("--------------Received the following Accounting message:--------------\n");
+
+	CHECK_FCT( fd_sess_getsid ( sess, &s ) );
+	fd_log_debug("Session: %s\n", s);
+
+	/* We may also dump other data from the message, such as Accounting session Id, number of packets, ...  */
+
+	fd_log_debug("----------------------------------------------------------------------\n");
+
+	/* Send the answer */
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+		
+	return 0;
+}
+	
+
+/* entry point */
+static int acct_entry(char * conffile)
+{
+	struct disp_when data;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Initialize the configuration and parse the file */
+	CHECK_FCT( acct_conf_init() );
+	CHECK_FCT( acct_conf_parse(conffile) );
+	CHECK_FCT( acct_conf_check(conffile) );
+	
+	/* Now initialize the database module */
+	CHECK_FCT( acct_db_init() );
+	
+	/* Register the dispatch callbacks */
+	memset(&data, 0, sizeof(data));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &data.app, ENOENT) );
+	CHECK_FCT( fd_disp_register( acct_fallback, DISP_HOW_APPID, &data, NULL ) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( acct_cb, DISP_HOW_CC, &data, NULL ) );
+	
+	/* Advertise the support for the Diameter Base Accounting application in the peer */
+	CHECK_FCT( fd_disp_app_support ( data.app, NULL, 0, 1 ) );
+	
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Close the db connection */
+	acct_db_free();
+	
+	/* Destroy the configuration */
+	acct_conf_free();
+}
+
+EXTENSION_ENTRY("app_acct", acct_entry);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/app_acct/app_acct.h	Wed Apr 28 18:54:08 2010 +0900
@@ -0,0 +1,113 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2010, WIDE Project and NICT								 *
+* 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 WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* 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.								 *
+*********************************************************************************************************/
+
+/* Header file for the app_acct extension. 
+ *
+ *  This extension is a simple Diameter Accounting server.
+ *
+ * It receives the Diameter Accounting-Request message, and sends its content in a 
+ * "buffer" postgreSQL database (see configuration sample file app_acct.conf.sample).
+ *
+ * The intent is that another application will then pick the records from this "buffer" database
+ * and process it accordingly to the requirements of the end application.
+ */
+ 
+#include <freeDiameter/extension.h>
+
+/* The structure corresponding to an AVP entry in the configuration file */
+struct acct_conf_avp {
+	/* Chain */
+	struct fd_list	 	 chain;		/* link in the global list */
+	
+	/* Raw information from the configuration file */
+	char 			*avpname;	/* the name of the AVP, as appear in the configuration file */
+	char			*field;		/* the field name in the database, or NULL if it is the same as avpname */
+	int			 required;	/* set to true if this AVP has to be in the message */
+	unsigned 		 multi;		/* the number of occurrences of this AVP we convert, or 0 if it was not specified */
+	
+	/* Parsed information */
+	struct dict_object 	*avpobj;	/* the dictionary object corresponding to this AVP */
+	enum dict_avp_basetype	 avptype;	/* this info is extracted from avpobj. GROUPED avps are not allowed yet */
+};
+
+/* This is described only inside acct_db.c */
+struct acct_db;
+
+/* The complete configuration */
+struct acct_conf {
+	/* AVPs */
+	struct fd_list	 avps;		/* the list of acct_conf_avp entries */
+	
+	/* Raw information */
+	char		*conninfo;	/* the connection string to the database, that is passed as is to the database library */
+	char 		*tablename;	/* the name of the table we are working with */
+	char 		*tsfield;	/* the name of the timestamp field, or NULL if not required */
+};
+
+/* A successfully parsed Accounting-Request produces a list of these: */
+struct acct_record_item {
+	struct fd_list		 chain;	/* link with all others */
+	struct fd_list		 unmapd;/* link with only unmap'd records */
+	struct acct_conf_avp 	*param;	/* the AVP entry this refers to. */
+	unsigned		 index;	/* in case of multi */
+	union avp_value		*value; /* If the AVP was found in the message, this points to its value. Otherwise, NULL */
+};
+
+/* The sentinel for a list of acct_record_items */
+struct acct_record_list {
+	struct fd_list	all;	/* The list of records */
+	int		nball;	/* The number of records in all */
+	struct fd_list	unmaped;/* Only the records without a value */
+	int		nbunmap;/* The number of unmap'd records */
+};
+
+/* Mapping of the data types between Diameter AVP and PQ types: */
+extern const char * diam2db_types_mapping[];
+
+/* In acct_conf.y */
+extern struct acct_conf * acct_config;	/* the global configuration */
+int acct_conf_init(void);
+int acct_conf_parse(char * conffile);
+int acct_conf_check(char * conffile);
+void acct_conf_free(void);
+
+/* In acct_db.c */
+int acct_db_init(void);
+int acct_db_insert(struct acct_record_list * records);
+void acct_db_free(void);
+
+/* In acct_records.c */
+int acct_rec_prepare(struct acct_record_list * records);
+int acct_rec_map(struct acct_record_list * records, struct msg * msg);
"Welcome to our mercurial repository"