changeset 10:c5c99c73c2bf

Added some extensions and functions in the daemon
author Sebastien Decugis <sdecugis@nict.go.jp>
date Fri, 25 Sep 2009 16:12:08 +0900
parents fc7c18867cf7
children 6576ef5e01eb
files doc/freediameter.conf.sample extensions/CMakeLists.txt extensions/_sample/CMakeLists.txt extensions/_sample/fini.c extensions/_sample/sample.c extensions/dbg_monitor/CMakeLists.txt extensions/dbg_monitor/monitor.c extensions/dict_eap/CMakeLists.txt extensions/dict_eap/dict_eap.c extensions/dict_nasreq/CMakeLists.txt extensions/dict_nasreq/dict_nasreq.c freeDiameter/CMakeLists.txt freeDiameter/config.c freeDiameter/dispatch.c freeDiameter/extensions.c freeDiameter/fD.h freeDiameter/fdd.y freeDiameter/main.c freeDiameter/messages.c freeDiameter/queues.c freeDiameter/routing.c freeDiameter/tests/CMakeLists.txt freeDiameter/tests/testdict.c freeDiameter/tests/testdisp.c freeDiameter/tests/testfifo.c freeDiameter/tests/testmesg.c freeDiameter/tests/testqueues.c freeDiameter/tests/tests.h include/freeDiameter/freeDiameter.h include/freeDiameter/libfreeDiameter.h libfreeDiameter/CMakeLists.txt libfreeDiameter/fifo.c libfreeDiameter/queues.c
diffstat 33 files changed, 6247 insertions(+), 1163 deletions(-) [+]
line wrap: on
line diff
--- a/doc/freediameter.conf.sample	Thu Sep 24 14:01:48 2009 +0900
+++ b/doc/freediameter.conf.sample	Fri Sep 25 16:12:08 2009 +0900
@@ -128,5 +128,6 @@
 TcTimer = 60;
 TwTimer = 6;
 NoRelay;
-#LoadExtension = "extensions/sample.fdx";
-LoadExtension = "extensions/sample.fdx":"conf/sample.conf";
+LoadExtension = "extensions/dbg_monitor.fdx";
+LoadExtension = "extensions/dict_nasreq.fdx";
+LoadExtension = "extensions/dict_eap.fdx";
--- a/extensions/CMakeLists.txt	Thu Sep 24 14:01:48 2009 +0900
+++ b/extensions/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -17,15 +17,15 @@
 
 ####
 # Diameter applications dictionary
-# OPTION(BUILD_DICT_NASREQ "Build NASREQ (RFC4005) Dictionary definitions?" ON)
-# 	IF (BUILD_DICT_NASREQ)
-# 	   SUBDIRS(dict_nasreq)
-# 	ENDIF (BUILD_DICT_NASREQ)
+OPTION(BUILD_DICT_NASREQ "Build NASREQ (RFC4005) Dictionary definitions?" ON)
+	IF (BUILD_DICT_NASREQ)
+	   SUBDIRS(dict_nasreq)
+	ENDIF (BUILD_DICT_NASREQ)
 
-# OPTION(BUILD_DICT_EAP "Build Diameter EAP (RFC4072) Dictionary definitions?" ON)
-# 	IF (BUILD_DICT_EAP)
-# 	   SUBDIRS(dict_eap)
-# 	ENDIF (BUILD_DICT_EAP)
+OPTION(BUILD_DICT_EAP "Build Diameter EAP (RFC4072) Dictionary definitions?" ON)
+	IF (BUILD_DICT_EAP)
+	   SUBDIRS(dict_eap)
+	ENDIF (BUILD_DICT_EAP)
 
 
 
@@ -58,11 +58,16 @@
 ####
 # Debug / development extensions
 
-OPTION(BUILD_SAMPLE "Build sample? (Simple extension to demonstrate extension mechanism, for developpers only)" OFF)
+OPTION(BUILD_SAMPLE "Build sample.fdx? (Simple extension to demonstrate extension mechanism, for developpers only)" OFF)
 	IF (BUILD_SAMPLE)
 	   SUBDIRS(_sample)
 	ENDIF (BUILD_SAMPLE)
 
+OPTION(BUILD_MONITOR "Build monitor.fdx? (display periodical debug information on the console)" OFF)
+	IF (BUILD_MONITOR)
+	   SUBDIRS(dbg_monitor)
+	ENDIF (BUILD_MONITOR)
+
 # OPTION(BUILD_RT_ANY "Build rt_any? (Routing extension sending message to any peer available, for testing purpose only)" OFF)
 # 	IF (BUILD_RT_ANY)
 # 	   SUBDIRS(rt_any)
--- a/extensions/_sample/CMakeLists.txt	Thu Sep 24 14:01:48 2009 +0900
+++ b/extensions/_sample/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -2,4 +2,4 @@
 PROJECT("Sample extension" C)
 
 # Compile as a module
-FD_ADD_EXTENSION(sample sample.c fini.c)
+FD_ADD_EXTENSION(dbg_sample sample.c fini.c)
--- a/extensions/_sample/fini.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/extensions/_sample/fini.c	Fri Sep 25 16:12:08 2009 +0900
@@ -33,13 +33,13 @@
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
 *********************************************************************************************************/
 
-/* Sample extension exit point */
-
 #include <freeDiameter/extension.h>
 
+/* The function MUST be called this */
 void fd_ext_fini(void)
 {
-	fd_log_debug("Extension is terminated... Bye!\n");
+	/* This code is executed when the daemon is exiting; cleanup management should be placed here */
+	TRACE_DEBUG(INFO, "Extension is terminated... Bye!");
 	return ;
 }
 
--- a/extensions/_sample/sample.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/extensions/_sample/sample.c	Fri Sep 25 16:12:08 2009 +0900
@@ -44,18 +44,21 @@
 /* The extension-specific initialization code */
 static int sample_main(char * conffile)
 {
+	/* The debug macro from main tree can be used the same way */
 	TRACE_ENTRY("%p", conffile);
 	
-	fprintf(stdout, "I am extension " __FILE__ " running on host %s\n", fd_g_config->diam_id);
+	/* This is how we access daemon's global vars */
+	fprintf(stdout, "I am extension " __FILE__ " running on host %s.", fd_g_config->cnf_diamid);
 	
+	/* The configuration file name is received in the conffile var. It's up to extension to parse it */
 	if (conffile) {
 		fprintf(stdout, "I should parse my configuration file there: %s\n", conffile);
 	} else {
 		fprintf(stdout, "I received no configuration file to parse\n");
 	}
 	
-	/* Use the dictionary for test */
-	fd_log_debug("Let's create that 'Example-AVP'...\n");
+	/* Functions from the libfreediameter can also be used as demonstrated here: */
+	TRACE_DEBUG(INFO, "Let's create that 'Example-AVP'...");
 	{
 		struct dict_object * origin_host_avp = NULL;
 		struct dict_object * session_id_avp = NULL;
@@ -63,22 +66,27 @@
 		struct dict_rule_data rule_data = { NULL, RULE_REQUIRED, 0, -1, 1 };
 		struct dict_avp_data example_avp_data = { 999999, 0, "Example-AVP", AVP_FLAG_VENDOR , 0, AVP_TYPE_GROUPED };
 
-		CHECK_FCT( fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT));
-		CHECK_FCT( fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT));
+		CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT));
+		CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT));
 		
-		CHECK_FCT( fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ));
+		CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ));
 		
 		rule_data.rule_avp = origin_host_avp;
 		rule_data.rule_min = 1;
 		rule_data.rule_max = 1;
-		CHECK_FCT( fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+		CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
 		
 		rule_data.rule_avp = session_id_avp;
 		rule_data.rule_min = 1;
 		rule_data.rule_max = -1;
-		CHECK_FCT( fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+		CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+		
+		fd_dict_dump_object(example_avp_avp);
 	}
-	fd_log_debug("'Example-AVP' created without error\n");
+	TRACE_DEBUG(INFO, "'Example-AVP' created without error\n");
 	
+	/* The initialization function returns an error code with the standard POSIX meaning (ENOMEM, and so on) */
 	return 0;
 }
+
+/* See file fini.c for an example of destructor */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/dbg_monitor/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,3 @@
+# Monitoring extension
+PROJECT("Monitor extension" C)
+FD_ADD_EXTENSION(dbg_monitor monitor.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/dbg_monitor/monitor.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,96 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+/* Monitoring extension:
+ - periodically display queues and peers information
+ - upon SIGUSR1, display additional debug information
+ */
+
+#include <freeDiameter/extension.h>
+#include <signal.h>
+
+static int 	 monitor_main(char * conffile);
+
+EXTENSION_ENTRY("monitor", monitor_main);
+
+/* Function called on receipt of SIGUSR1 */
+static void got_sig(int signal)
+{
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_DICT, NULL), /* continue */);
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_CONFIG, NULL), /* continue */);
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_EXT, NULL), /* continue */);
+}
+/* Thread to display periodical debug information */
+static pthread_t thr;
+static void * mn_thr(void * arg)
+{
+	sigset_t sig;
+	struct sigaction act;
+	fd_log_threadname("Monitor thread");
+	
+	/* Catch signal SIGUSR1 */
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = got_sig;
+	CHECK_SYS_DO( sigaction(SIGUSR1, &act, NULL), /* conitnue */ );
+	sigemptyset(&sig);
+	sigaddset(&sig, SIGUSR1);
+	CHECK_POSIX_DO(  pthread_sigmask(SIG_UNBLOCK, &sig, NULL), /* conitnue */  );
+	
+	/* Loop */
+	while (1) {
+		sleep(60);
+		TRACE_DEBUG(NONE, "Monitor information");
+		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_QUEUES, NULL), /* continue */);
+		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_PEERS, NULL), /* continue */);
+		pthread_testcancel();
+	}
+	
+	return NULL;
+}
+
+static int monitor_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	CHECK_POSIX( pthread_create( &thr, NULL, mn_thr, NULL ) );
+	return 0;
+}
+
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT_DO( fd_thr_term(&thr), /* continue */ );
+	return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/dict_eap/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,5 @@
+# The dict_nasreq extension
+PROJECT("Diameter EAP (RFC4072) dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_eap dict_eap.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/dict_eap/dict_eap.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,530 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+/* 
+ * Dictionary definitions of objects specified in Diameter EAP application (RFC4072).
+ */
+#include <freeDiameter/extension.h>
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int deap_entry(char * conffile)
+{
+	struct dict_object * eap;
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Since we need many AVP from the NASREQ application, check that it is already defined in the dictionary */
+	{
+		application_id_t nasreqid = 1;
+		CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_ID, &nasreqid, NULL, ENOENT),
+		   {
+			fprintf(stderr, "The dict_eap extension needs definitions from NASREQ application (RFC4005).\n"
+				  "Please load the 'dict_nasreq' extension prior to this one.\n");
+			return ENOTSUP;
+		   }  );
+	}
+	
+	/* Applications section */
+	{
+		/* EAP (RFC 4072) */
+		{
+			struct dict_application_data data  = { 	5, "Diameter Extensible Authentication Protocol (EAP) Application"	};
+			CHECK_dict_new( DICT_APPLICATION, &data , NULL, &eap);
+		}
+	}
+	
+	/* AVP section */
+	{
+		/* EAP-Payload */
+		{
+			/*
+				The EAP-Payload AVP (AVP Code 462) is of type OctetString and is used
+				to encapsulate the actual EAP packet that is being exchanged between
+				the EAP client and the home Diameter server.
+			*/
+			struct dict_avp_data data = { 
+					462, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Payload", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* EAP-Reissued-Payload */
+		{
+			/*
+				The EAP-Reissued-Payload AVP (AVP Code 463) is of type OctetString.
+			*/
+			struct dict_avp_data data = { 
+					463, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Reissued-Payload", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* EAP-Master-Session-Key */
+		{
+			/*
+				The EAP-Master-Session-Key AVP (AVP Code 464) is of type OctetString.
+				It contains keying material for protecting the communications between
+				the user and the NAS.  Exactly how this keying material is used
+				depends on the link layer in question, and is beyond the scope of
+				this document.
+			*/
+			struct dict_avp_data data = { 
+					464, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Master-Session-Key", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* EAP-Key-Name */
+		{
+			/*
+				The EAP-Key-Name AVP (Radius Attribute Type 102) is of type
+				OctetString.  It contains an opaque key identifier (name) generated
+				by the EAP method.  Exactly how this name is used depends on the link
+				layer in question, and is beyond the scope of this document (see
+				[EAPKey] for more discussion).
+
+				Note that not all link layers use this name, and currently most EAP
+				methods do not generate it.  Since the NAS operates in pass-through
+				mode, it cannot know the Key-Name before receiving it from the AAA
+				server.  As a result, a Key-Name AVP sent in a Diameter-EAP-Request
+				MUST NOT contain any data.  A home Diameter server receiving a
+				Diameter-EAP-Request with a Key-Name AVP with non-empty data MUST
+				silently discard the AVP.  In addition, the home Diameter server
+				SHOULD include this AVP in Diameter-EAP-Response only if an empty
+				EAP-Key-Name AVP was present in Diameter-EAP-Request.
+			*/
+			struct dict_avp_data data = { 
+					102, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Key-Name", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-EAP-Auth-Method */
+		{
+			/*
+				The Accounting-EAP-Auth-Method AVP (AVP Code 465) is of type
+				Unsigned64.  In case of expanded types [EAP, Section 5.7], this AVP
+				contains the value ((Vendor-Id * 2^32) + Vendor-Type).
+			*/
+			struct dict_avp_data data = { 
+					465, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-EAP-Auth-Method", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+	}
+
+/********************/		
+/* Commands section */
+/********************/		
+	{
+		/* To avoid defining global variables for all the AVP that we use here, we do search the dictionary in each sub-block.
+		 * This is far from optimal, but the code is clearer like this, and the time it requires at execution is not noticeable.
+		 */
+		/* Diameter-EAP-Request (DER) Command */
+		{
+			/*
+				The Diameter-EAP-Request (DER) command, indicated by the Command-Code
+				field set to 268 and the 'R' bit set in the Command Flags field, is
+				sent by a Diameter client to a Diameter server, and conveys an
+				EAP-Response from the EAP client.  The Diameter-EAP-Request MUST
+				contain one EAP-Payload AVP containing the actual EAP payload.  An
+				EAP-Payload AVP with no data MAY be sent to the Diameter server to
+				initiate an EAP authentication session.
+
+				The DER message MAY be the result of a multi-round authentication
+				exchange that occurs when the DEA is received with the Result-Code
+				AVP set to DIAMETER_MULTI_ROUND_AUTH [BASE].  A subsequent DER
+				message MUST include any State AVPs [NASREQ] that were present in the
+				DEA.  For re-authentication, it is recommended that the Identity
+				request be skipped in order to reduce the number of authentication
+				round trips.  This is only possible when the user's identity is
+				already known by the home Diameter server.
+
+				Message format
+
+				<Diameter-EAP-Request> ::= < Diameter Header: 268, REQ, PXY >
+                        				 < Session-Id >
+                        				 { Auth-Application-Id }
+                        				 { Origin-Host }
+                        				 { Origin-Realm }
+                        				 { Destination-Realm }
+                        				 { Auth-Request-Type }
+                        				 [ Destination-Host ]
+                        				 [ NAS-Identifier ]
+                        				 [ NAS-IP-Address ]
+                        				 [ NAS-IPv6-Address ]
+                        				 [ NAS-Port ]
+                        				 [ NAS-Port-Id ]
+                        				 [ NAS-Port-Type ]
+                        				 [ Origin-State-Id ]
+                        				 [ Port-Limit ]
+                        				 [ User-Name ]
+                        				 { EAP-Payload }
+                        				 [ EAP-Key-Name ]
+                        				 [ Service-Type ]
+                        				 [ State ]
+                        				 [ Authorization-Lifetime ]
+                        				 [ Auth-Grace-Period ]
+                        				 [ Auth-Session-State ]
+                        				 [ Callback-Number ]
+                        				 [ Called-Station-Id ]
+                        				 [ Calling-Station-Id ]
+                        				 [ Originating-Line-Info ]
+                        				 [ Connect-Info ]
+                				       * [ Framed-Compression ]
+                        				 [ Framed-Interface-Id ]
+                        				 [ Framed-IP-Address ]
+                				       * [ Framed-IPv6-Prefix ]
+                        				 [ Framed-IP-Netmask ]
+                        				 [ Framed-MTU ]
+                        				 [ Framed-Protocol ]
+                				       * [ Tunneling ]
+                				       * [ Proxy-Info ]
+                				       * [ Route-Record ]
+                				       * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					268, 					/* Code */
+					"Diameter-EAP-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Payload",			RULE_REQUIRED,   -1, 1 }
+							,{  "EAP-Key-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Connect-Info",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , eap, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Diameter-EAP-Answer (DEA) Command */
+		{
+			/*
+				The Diameter-EAP-Answer (DEA) message, indicated by the Command-Code
+				field set to 268 and the 'R' bit cleared in the Command Flags field,
+				is sent by the Diameter server to the client for one of the following
+				reasons:
+
+				1.  The message is part of a multi-round authentication exchange, and
+				the server is expecting a subsequent Diameter-EAP-Request.  This
+				is indicated by setting the Result-Code to
+				DIAMETER_MULTI_ROUND_AUTH, and MAY include zero or more State
+				AVPs.
+
+				2.  The EAP client has been successfully authenticated and
+				authorized, in which case the message MUST include the
+				Result-Code AVP indicating success, and SHOULD include an
+				EAP-Payload of type EAP-Success.  This event MUST cause the
+				access device to provide service to the EAP client.
+
+				3.  The EAP client has not been successfully authenticated and/or
+				authorized, and the Result-Code AVP is set to indicate failure.
+				This message SHOULD include an EAP-Payload, but this AVP is not
+				used to determine whether service is to be provided.
+
+				If the message from the Diameter client included a request for
+				authorization, a successful response MUST include the authorization
+				AVPs that are relevant to the service being provided.
+
+				Message format
+
+				<Diameter-EAP-Answer> ::= < Diameter Header: 268, PXY >
+                        				< Session-Id >
+                        				{ Auth-Application-Id }
+                        				{ Auth-Request-Type }
+                        				{ Result-Code }
+                        				{ Origin-Host }
+                        				{ Origin-Realm }
+                        				[ User-Name ]
+                        				[ EAP-Payload ]
+                        				[ EAP-Reissued-Payload ]
+                        				[ EAP-Master-Session-Key ]
+                        				[ EAP-Key-Name ]
+                        				[ Multi-Round-Time-Out ]
+                        				[ Accounting-EAP-Auth-Method ]
+                        				[ Service-Type ]
+                				      * [ Class ]
+                				      * [ Configuration-Token ]
+                        				[ Acct-Interim-Interval ]
+                        				[ Error-Message ]
+                        				[ Error-Reporting-Host ]
+                				      * [ Failed-AVP ]
+                        				[ Idle-Timeout ]
+                        				[ Authorization-Lifetime ]
+                        				[ Auth-Grace-Period ]
+                        				[ Auth-Session-State ]
+                        				[ Re-Auth-Request-Type ]
+                        				[ Session-Timeout ]
+                        				[ State ]
+                				      * [ Reply-Message ]
+                        				[ Origin-State-Id ]
+                				      * [ Filter-Id ]
+                        				[ Port-Limit ]
+                        				[ Callback-Id ]
+                        				[ Callback-Number ]
+                        				[ Framed-Appletalk-Link ]
+                				      * [ Framed-Appletalk-Network ]
+                        				[ Framed-Appletalk-Zone ]
+                				      * [ Framed-Compression ]
+                        				[ Framed-Interface-Id ]
+                        				[ Framed-IP-Address ]
+                				      * [ Framed-IPv6-Prefix ]
+                        				[ Framed-IPv6-Pool ]
+                				      * [ Framed-IPv6-Route ]
+                        				[ Framed-IP-Netmask ]
+                				      * [ Framed-Route ]
+                        				[ Framed-Pool ]
+                        				[ Framed-IPX-Network ]
+                        				[ Framed-MTU ]
+                        				[ Framed-Protocol ]
+                        				[ Framed-Routing ]
+                				      * [ NAS-Filter-Rule ]
+                				      * [ QoS-Filter-Rule ]
+                				      * [ Tunneling ]
+                				      * [ Redirect-Host ]
+                        				[ Redirect-Host-Usage ]
+                        				[ Redirect-Max-Cache-Time ]
+                				      * [ Proxy-Info ]
+                				      * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					268, 					/* Code */
+					"Diameter-EAP-Answer", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Payload",			RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Reissued-Payload",		RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Master-Session-Key",		RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Key-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Multi-Round-Time-Out",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-EAP-Auth-Method",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Configuration-Token",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Acct-Interim-Interval",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Session-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Filter-Id",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Link",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Network",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-AppleTalk-Zone",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IPv6-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Route",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Route",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPX-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Routing",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "QoS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , eap, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				Attribute Name                         | ACR | ACA |
+				---------------------------------------|-----+-----+
+				Accounting-EAP-Auth-Method             |  0+ |  0  |
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Accounting-EAP-Auth-Method",	RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+	}
+	
+	TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for EAP' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_eap", deap_entry);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/dict_nasreq/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,5 @@
+# The dict_nasreq extension
+PROJECT("Diameter NASREQ (RFC4005) dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_nasreq dict_nasreq.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/dict_nasreq/dict_nasreq.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,3735 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+/* 
+ * Dictionary definitions of objects specified in Diameter NASREQ (RFC4005).
+ */
+#include <freeDiameter/extension.h>
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dnr_entry(char * conffile)
+{
+	struct dict_object * nasreq;
+	TRACE_ENTRY("%p", conffile);
+	
+	/* No Vendors definitions */
+	
+	/* Applications section */
+	{
+		/* NASREQ (RFC 4005) */
+		{
+			struct dict_application_data data = {        1, "Diameter Network Access Server Application" 			};
+			CHECK_dict_new( DICT_APPLICATION, &data, NULL, &nasreq);
+		}
+	}
+	
+	/* Derived AVP types section */
+	{
+		/* QoSFilterRule */
+		{
+			/*
+				The QosFilterRule format is derived from the OctetString AVP Base
+				Format.  It uses the ASCII charset.  Packets may be marked or
+				metered based on the following information:
+
+				 Direction                          (in or out)
+				 Source and destination IP address  (possibly masked)
+				 Protocol
+				 Source and destination port        (lists or ranges)
+				 DSCP values                        (no mask or range)
+
+				Rules for the appropriate direction are evaluated in order; the
+				first matched rule terminates the evaluation.  Each packet is
+				evaluated once.  If no rule matches, the packet is treated as best
+				effort.  An access device unable to interpret or apply a QoS rule
+				SHOULD NOT terminate the session.
+
+				QoSFilterRule filters MUST follow the following format:
+
+				action dir proto from src to dst [options]
+
+        				tag    - Mark packet with a specific DSCP
+                				 [DIFFSERV].  The DSCP option MUST be
+                				 included.
+        				meter  - Meter traffic.  The metering options
+                				 MUST be included.
+
+				dir           The format is as described under IPFilterRule.
+
+				proto         The format is as described under IPFilterRule.
+
+				src and dst   The format is as described under IPFilterRule.
+
+				 options:
+
+				 DSCP <color>
+				       Color values as defined in [DIFFSERV].  Exact
+				       matching of DSCP values is required (no masks or
+				       ranges).
+
+				 metering <rate> <color_under> <color_over>
+				       The metering option provides Assured Forwarding,
+				       as defined in [DIFFSERVAF], and MUST be present
+				       if the action is set to meter.  The rate option is
+				       the throughput, in bits per second, used
+				       by the access device to mark packets.  Traffic
+				       over the rate is marked with the color_over
+				       codepoint, and traffic under the rate is marked
+				       with the color_under codepoint.  The color_under
+				       and color_over options contain the drop
+				       preferences and MUST conform to the recommended
+				       codepoint keywords described in [DIFFSERVAF]
+				       (e.g., AF13).
+
+				       The metering option also supports the strict
+				       limit on traffic required by Expedited
+				       Forwarding, as defined in [DIFFSERVEF].  The
+				       color_over option may contain the keyword "drop"
+				       to prevent forwarding of traffic that exceeds the
+				       rate parameter.
+
+				 The rule syntax is a modified subset of ipfw(8) from FreeBSD,
+				 and the ipfw.c code may provide a useful base for
+				 implementations.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"QoSFilterRule"		, NULL			, NULL			};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+	}
+	
+	/* AVP section */
+	{
+		struct dict_object * UTF8String_type;
+		struct dict_object * IPFilterRule_type;
+		struct dict_object * QoSFilterRule_type;
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "QoSFilterRule", &QoSFilterRule_type);
+
+/********************************
+ *  NAS Session AVPs            *
+ ********************************/		
+		/* NAS-Port */
+		{
+			/*
+				The NAS-Port AVP (AVP Code 5) is of type Unsigned32 and contains the
+				physical or virtual port number of the NAS which is authenticating
+				the user.  Note that "port" is meant in its sense as a service
+				connection on the NAS, not as an IP protocol identifier.
+
+				Either NAS-Port or NAS-Port-Id (AVP Code 87) SHOULD be present in
+				AA-Request (AAR) commands if the NAS differentiates among its ports.
+			*/
+			struct dict_avp_data data = { 
+					5, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* NAS-Port-Id */
+		{
+			/*
+				The NAS-Port-Id AVP (AVP Code 87) is of type UTF8String and consists
+				of ASCII text identifying the port of the NAS authenticating the
+				user.  Note that "port" is meant in its sense as a service connection
+				on the NAS, not as an IP protocol identifier.
+
+				Either NAS-Port or NAS-Port-Id SHOULD be present in AA-Request (AAR)
+				commands if the NAS differentiates among its ports.  NAS-Port-Id is
+				intended for use by NASes that cannot conveniently number their
+				ports.
+			*/
+			struct dict_avp_data data = { 
+					87, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* NAS-Port-Type */
+		{
+			/*
+				The NAS-Port-Type AVP (AVP Code 61) is of type Enumerated and
+				contains the type of the port on which the NAS is authenticating the
+				user.  This AVP SHOULD be present if the NAS uses the same NAS-Port
+				number ranges for different service types concurrently.
+
+				The supported values are defined in [RADIUSTypes].  The following
+				list is informational and subject to change by the IANA.
+				
+				http://www.iana.org/assignments/radius-types
+				Sub-registry: Values for RADIUS Attribute 61, NAS-Port-Type
+				Reference: [RFC2865]
+				
+				Extract on 2009.06.01:
+				0      Async                                                               [RFC2865]
+				1      Sync                                                                [RFC2865]
+				2      ISDN Sync                                                           [RFC2865]
+				3      ISDN Async V.120                                                    [RFC2865]
+				4      ISDN Async V.110                                                    [RFC2865]
+				5      Virtual                                                             [RFC2865]
+				6      PIAFS                                                               [RFC2865]
+				7      HDLC Clear Channel                                                  [RFC2865]
+				8      X.25                                                                [RFC2865]
+				9      X.75                                                                [RFC2865]
+				10     G.3 Fax                                                             [RFC2865]
+				11     SDSL - Symmetric DSL                                                [RFC2865]
+				12     ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation   [RFC2865]
+				13     ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone                      [RFC2865]
+				14     IDSL - ISDN Digital Subscriber Line                                 [RFC2865]
+				15     Ethernet                                                            [RFC2865]
+				16     xDSL - Digital Subscriber Line of unknown type                      [RFC2865]
+				17     Cable                                                               [RFC2865]
+				18     Wireless - Other                                                    [RFC2865]
+				19     Wireless - IEEE 802.11                                              [RFC2865]
+				20     Token-Ring                                                          [RFC3580] 
+				21     FDDI                                                                [RFC3580]
+				22     Wireless - CDMA2000                                                 [McCann] 
+				23     Wireless - UMTS                                                     [McCann]
+				24     Wireless - 1X-EV                                                    [McCann]
+				25     IAPP                                                                [IEEE 802.11F][Kerry]   
+				26     FTTP - Fiber to the Premises                                        [Nyce]
+				27     Wireless - IEEE 802.16                                              [IEEE 802.16]          12 December 2006
+				28     Wireless - IEEE 802.20                                              [IEEE 802.20]          12 December 2006
+				29     Wireless - IEEE 802.22                                              [IEEE 802.22]          12 December 2006		
+				30     PPPoA - PPP over ATM                                                [RFC4603]
+				31     PPPoEoA - PPP over Ethernet over ATM                                [RFC4603]
+				32     PPPoEoE - PPP over Ethernet over Ethernet                           [RFC4603]
+				33     PPPoEoVLAN - PPP over Ethernet over VLAN                            [RFC4603]
+				34     PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ                  [RFC4603]
+				35     xPON - Passive Optical Network                                      [Hublet][Yan]           19 June 2007
+			*/
+			
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(NAS-Port-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "Async [RFC2865]"),
+				enumval_def_u32( 1, "Sync [RFC2865]"),
+				enumval_def_u32( 2, "ISDN Sync [RFC2865]"),
+				enumval_def_u32( 3, "ISDN Async V.120 [RFC2865]"),
+				enumval_def_u32( 4, "ISDN Async V.110 [RFC2865]"),
+				enumval_def_u32( 5, "Virtual [RFC2865]"),
+				enumval_def_u32( 6, "PIAFS [RFC2865]"),
+				enumval_def_u32( 7, "HDLC Clear Channel [RFC2865]"),
+				enumval_def_u32( 8, "X.25 [RFC2865]"),
+				enumval_def_u32( 9, "X.75 [RFC2865]"),
+				enumval_def_u32(10, "G.3 Fax [RFC2865]"),
+				enumval_def_u32(11, "SDSL - Symmetric DSL [RFC2865]"),
+				enumval_def_u32(12, "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation [RFC2865]"),
+				enumval_def_u32(13, "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone [RFC2865]"),
+				enumval_def_u32(14, "IDSL - ISDN Digital Subscriber Line [RFC2865]"),
+				enumval_def_u32(15, "Ethernet [RFC2865]"),
+				enumval_def_u32(16, "xDSL - Digital Subscriber Line of unknown type [RFC2865]"),
+				enumval_def_u32(17, "Cable [RFC2865]"),
+				enumval_def_u32(18, "Wireless - Other [RFC2865]"),
+				enumval_def_u32(19, "Wireless - IEEE 802.11 [RFC2865]"),
+				enumval_def_u32(20, "Token-Ring [RFC3580]"),
+				enumval_def_u32(21, "FDDI [RFC3580]"),
+				enumval_def_u32(22, "Wireless - CDMA2000 [McCann]"),
+				enumval_def_u32(23, "Wireless - UMTS [McCann]"),
+				enumval_def_u32(24, "Wireless - 1X-EV [McCann]"),
+				enumval_def_u32(25, "IAPP [IEEE 802.11F][Kerry]"),
+				enumval_def_u32(26, "FTTP - Fiber to the Premises [Nyce]"),
+				enumval_def_u32(27, "Wireless - IEEE 802.16 [IEEE 802.16]"),
+				enumval_def_u32(28, "Wireless - IEEE 802.20 [IEEE 802.20]"),
+				enumval_def_u32(29, "Wireless - IEEE 802.22 [IEEE 802.22]"),
+				enumval_def_u32(30, "PPPoA - PPP over ATM [RFC4603]"),
+				enumval_def_u32(31, "PPPoEoA - PPP over Ethernet over ATM [RFC4603]"),
+				enumval_def_u32(32, "PPPoEoE - PPP over Ethernet over Ethernet [RFC4603]"),
+				enumval_def_u32(33, "PPPoEoVLAN - PPP over Ethernet over VLAN [RFC4603]"),
+				enumval_def_u32(34, "PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ [RFC4603]"),
+				enumval_def_u32(35, "xPON - Passive Optical Network [Hublet][Yan]")
+			};
+			struct dict_avp_data 	data = { 
+					61, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Called-Station-Id */
+		{
+			/*
+				The Called-Station-Id AVP (AVP Code 30) is of type UTF8String and
+				allows the NAS to send the ASCII string describing the layer 2
+				address the user contacted in the request.  For dialup access, this
+				can be a phone number obtained by using Dialed Number Identification
+				(DNIS) or a similar technology.  Note that this may be different from
+				the phone number the call comes in on.  For use with IEEE 802 access,
+				the Called-Station-Id MAY contain a MAC address formatted as
+				described in [RAD802.1X].  It SHOULD only be present in
+				authentication and/or authorization requests.
+
+				If the Auth-Request-Type AVP is set to authorization-only and the
+				User-Name AVP is absent, the Diameter Server MAY perform
+				authorization based on this field.  This can be used by a NAS to
+				request whether a call should be answered based on the DNIS.
+			*/
+			struct dict_avp_data data = { 
+					30, 					/* Code */
+					0, 					/* Vendor */
+					"Called-Station-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Calling-Station-Id */
+		{
+			/*
+				The Calling-Station-Id AVP (AVP Code 31) is of type UTF8String and
+				allows the NAS to send the ASCII string describing the layer 2
+				address from which the user connected in the request.  For dialup
+				access, this is the phone number the call came from, using Automatic
+				Number Identification (ANI) or a similar technology.  For use with
+				IEEE 802 access, the Calling-Station-Id AVP MAY contain a MAC
+				address, formated as described in [RAD802.1X].  It SHOULD only be
+				present in authentication and/or authorization requests.
+
+				If the Auth-Request-Type AVP is set to authorization-only and the
+				User-Name AVP is absent, the Diameter Server MAY perform
+				authorization based on this field.  This can be used by a NAS to
+				request whether a call should be answered based on the layer 2
+				address (ANI, MAC Address, etc.)
+			*/
+			struct dict_avp_data data = { 
+					31, 					/* Code */
+					0, 					/* Vendor */
+					"Calling-Station-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Connect-Info */
+		{
+			/*
+				The Connect-Info AVP (AVP Code 77) is of type UTF8String and is sent
+				in the AA-Request message or ACR STOP message.  When sent in the
+				Access-Request, it indicates the nature of the user's connection.
+				The connection speed SHOULD be included at the beginning of the first
+				Connect-Info AVP in the message.  If the transmit and receive
+				connection speeds differ, both may be included in the first AVP with
+				the transmit speed listed first (the speed the NAS modem transmits
+				at), then a slash (/), then the receive speed, and then other
+				optional information.
+
+				For example: "28800 V42BIS/LAPM" or "52000/31200 V90"
+
+				More than one Connect-Info attribute may be present in an
+				Accounting-Request packet to accommodate expected efforts by the ITU
+				to have modems report more connection information in a standard
+				format that might exceed 252 octets.
+
+				If sent in the ACR STOP, this attribute may summarize statistics
+				relating to session quality.  For example, in IEEE 802.11, the
+				Connect-Info attribute may contain information on the number of link
+				layer retransmissions.  The exact format of this attribute is
+				implementation specific.
+			*/
+			struct dict_avp_data data = { 
+					77, 					/* Code */
+					0, 					/* Vendor */
+					"Connect-Info", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Originating-Line-Info */
+		{
+			/*
+				The Originating-Line-Info AVP (AVP Code 94) is of type OctetString
+				and is sent by the NAS system to convey information about the origin
+				of the call from an SS7 system.
+
+				The originating line information (OLI) element indicates the nature
+				and/or characteristics of the line from which a call originated
+				(e.g., pay phone, hotel, cellular).  Telephone companies are starting
+				to offer OLI to their customers as an option over Primary Rate
+				Interface (PRI).  Internet Service Providers (ISPs) can use OLI in
+				addition to Called-Station-Id and Calling-Station-Id attributes to
+				differentiate customer calls and to define different services.
+
+				The Value field contains two octets (00 - 99).  ANSI T1.113 and
+				BELLCORE 394 can be used for additional information about these
+				values and their use.  For more information on current assignment
+				values, see [http://www.nanpa.com/number_resource_info/ani_ii_assignments.html].
+
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_OCTETSTRING,	"Enumerated*(Originating-Line-Info)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_os( 2, "00", "Plain Old Telephone Service (POTS)"),
+				enumval_def_os( 2, "01", "Multiparty Line (more than 2)"),
+				enumval_def_os( 2, "02", "ANI Failure"),
+				enumval_def_os( 2, "06", "Station Level Rating"),
+				enumval_def_os( 2, "07", "Special Operator Handling Required"),
+				enumval_def_os( 2, "20", "Automatic Identified Outward Dialing (AIOD)"),
+				enumval_def_os( 2, "23", "Coin or Non-Coin"),
+				enumval_def_os( 2, "24", "Toll Free Service (Non-Pay Origination)"),
+				enumval_def_os( 2, "25", "Toll Free Service (Pay Origination)"),
+				enumval_def_os( 2, "27", "Toll Free Service (Coin Control Origination)"),
+				enumval_def_os( 2, "29", "Prison/Inmate Service"),
+				enumval_def_os( 2, "30", "Intercept (Blank)"),
+				enumval_def_os( 2, "31", "Intercept (Trouble)"),
+				enumval_def_os( 2, "32", "Intercept (Regular)"),
+				enumval_def_os( 2, "34", "Telco Operator Handled Call"),
+				enumval_def_os( 2, "52", "Outward Wide Area Telecommunications Service (OUTWATS)"),
+				enumval_def_os( 2, "60", "Telecommunications Relay Service (TRS)(Unrestricted)"),
+				enumval_def_os( 2, "61", "Cellular/Wireless PCS (Type 1)"),
+				enumval_def_os( 2, "62", "Cellular/Wireless PCS (Type 2)"),
+				enumval_def_os( 2, "63", "Cellular/Wireless PCS (Roaming)"),
+				enumval_def_os( 2, "66", "TRS (Hotel)"),
+				enumval_def_os( 2, "67", "TRS (Restricted)"),
+				enumval_def_os( 2, "70", "Pay Station, No Coin Control"),
+				enumval_def_os( 2, "93", "Access for Private Virtual Network Service")
+			};
+			struct dict_avp_data data = { 
+					94, 					/* Code */
+					0, 					/* Vendor */
+					"Originating-Line-Info", 		/* Name */
+					AVP_FLAG_VENDOR, 			/* Fixed flags */
+					0,		 			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Reply-Message */
+		{
+			/*
+				The Reply-Message AVP (AVP Code 18) is of type UTF8String and
+				contains text that MAY be displayed to the user.  When used in an
+				AA-Answer message with a successful Result-Code AVP, it indicates
+				success.  When found in an AAA message with a Result-Code other than
+				DIAMETER_SUCCESS, the AVP contains a failure message.
+
+				The Reply-Message AVP MAY indicate dialog text to prompt the user
+				before another AA-Request attempt.  When used in an AA-Answer with a
+				Result-Code of DIAMETER_MULTI_ROUND_AUTH or in an Re-Auth-Request
+				message, it MAY contain a dialog text to prompt the user for a
+				response.
+
+				Multiple Reply-Messages MAY be included, and if any are displayed,
+				they MUST be displayed in the same order as they appear in the
+				Diameter message.
+			*/
+			struct dict_avp_data data = { 
+					18, 					/* Code */
+					0, 					/* Vendor */
+					"Reply-Message", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+/********************************
+ *  NAS Authentication AVPs     *
+ ********************************/		
+		/* User-Password */
+		{
+			/*
+				The User-Password AVP (AVP Code 2) is of type OctetString and
+				contains the password of the user to be authenticated, or the user's
+				input in a multi-round authentication exchange.
+
+				The User-Password AVP contains a user password or one-time password
+				and therefore represents sensitive information.  As required in
+				[BASE], Diameter messages are encrypted by using IPsec or TLS.
+				Unless this AVP is used for one-time passwords, the User-Password AVP
+				SHOULD NOT be used in untrusted proxy environments without encrypting
+				it by using end-to-end security techniques, such as the proposed CMS
+				Security [DiamCMS].
+
+				The clear-text password (prior to encryption) MUST NOT be longer than
+				128 bytes in length.
+			*/
+			struct dict_avp_data data = { 
+					2, 					/* Code */
+					0, 					/* Vendor */
+					"User-Password", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Password-Retry */
+		{
+			/*
+				The Password-Retry AVP (AVP Code 75) is of type Unsigned32 and MAY be
+				included in the AA-Answer if the Result-Code indicates an
+				authentication failure.  The value of this AVP indicates how many
+				authentication attempts a user is permitted before being
+				disconnected.  This AVP is primarily intended for use when the
+				Framed-Protocol AVP (see section 6.10.1) is set to ARAP.
+			*/
+			struct dict_avp_data data = { 
+					75, 					/* Code */
+					0, 					/* Vendor */
+					"Password-Retry", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Prompt */
+		{
+			/*
+				The Prompt AVP (AVP Code 76) is of type Enumerated and MAY be present
+				in the AA-Answer message.  When present, it is used by the NAS to
+				determine whether the user's response, when entered, should be
+				echoed.
+
+				The supported values are listed in http://www.iana.org/assignments/radius-types
+				Sub-registry: Values for RADIUS Attribute 76, Prompt
+				Reference: [RFC2869]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Prompt)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "No Echo [RFC2869]"),
+				enumval_def_u32( 1, "Echo [RFC2869]")
+			};
+			struct dict_avp_data data = { 
+					76, 					/* Code */
+					0, 					/* Vendor */
+					"Prompt", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* CHAP-Algorithm */
+		{
+			/*
+				The CHAP-Algorithm AVP (AVP Code 403) is of type Enumerated and
+				contains the algorithm identifier used in the computation of the CHAP
+				response [PPPCHAP].  The following values are currently supported:
+
+				CHAP with MD5       5
+				 The CHAP response is computed by using the procedure described
+				 in [PPPCHAP].  This algorithm requires that the CHAP-Response
+				 AVP MUST be present in the CHAP-Auth AVP.
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(CHAP-Algorithm)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 5, "CHAP with MD5")
+			};
+			struct dict_avp_data adata = { 
+					403, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Algorithm", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &adata , type, NULL);
+		}
+		
+		/* CHAP-Ident */
+		{
+			/*
+				The CHAP-Ident AVP (AVP Code 404) is of type OctetString and contains
+				the 1 octet CHAP Identifier used in the computation of the CHAP
+				response [PPPCHAP].
+			*/
+			struct dict_avp_data adata = { 
+					404, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Ident", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+			
+		/* CHAP-Response */
+		{
+			/*
+				The CHAP-Response AVP (AVP Code 405) is of type OctetString and
+				contains the 16 octet authentication data provided by the user in
+				response to the CHAP challenge [PPPCHAP].
+			*/
+			struct dict_avp_data adata = { 
+					405, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Response", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+			
+		/* CHAP-Auth */
+		{
+			/*
+				The CHAP-Auth AVP (AVP Code 402) is of type Grouped and contains the
+				information necessary to authenticate a user using the PPP
+				Challenge-Handshake Authentication Protocol (CHAP) [PPPCHAP].  If the
+				CHAP-Auth AVP is found in a message, the CHAP-Challenge AVP MUST be
+				present as well.  The optional AVPs containing the CHAP response
+				depend upon the value of the CHAP-Algorithm AVP.  The grouped AVP has
+				the following ABNF grammar:
+
+				CHAP-Auth  ::= < AVP Header: 402 >
+        				     { CHAP-Algorithm }
+        				     { CHAP-Ident }
+        				     [ CHAP-Response ]
+        				   * [ AVP ]
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					402, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Auth", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "CHAP-Algorithm", 			RULE_REQUIRED, -1, 1 }
+							,{  "CHAP-Ident",			RULE_REQUIRED, -1, 1 }
+							,{  "CHAP-Response",			RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		
+		/* CHAP-Challenge */
+		{
+			/*
+				The CHAP-Challenge AVP (AVP Code 60) is of type OctetString and
+				contains the CHAP Challenge sent by the NAS to the CHAP peer
+				[PPPCHAP].
+			*/
+			struct dict_avp_data data = { 
+					60, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Challenge", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Password */
+		{
+			/*
+				The ARAP-Password AVP (AVP Code 70) is of type OctetString and is
+				only present when the Framed-Protocol AVP (see section 6.10.1) is
+				included in the message and is set to ARAP.  This AVP MUST NOT be
+				present if either the User-Password or the CHAP-Auth AVP is present.
+				See [RADIUSExt] for more information on the contents of this AVP.
+			*/
+			struct dict_avp_data data = { 
+					70, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Password", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Challenge-Response */
+		{
+			/*
+				The ARAP-Challenge-Response AVP (AVP Code 84) is of type OctetString
+				and is only present when the Framed-Protocol AVP (see section 6.10.1)
+				is included in the message and is set to ARAP.  This AVP contains an
+				8 octet response to the dial-in client's challenge.  The RADIUS
+				server calculates this value by taking the dial-in client's challenge
+				from the high-order 8 octets of the ARAP-Password AVP and performing
+				DES encryption on this value with the authenticating user's password
+				as the key.  If the user's password is fewer than 8 octets in length,
+				the password is padded at the end with NULL octets to a length of 8
+				before it is used as a key.
+			*/
+			struct dict_avp_data data = { 
+					84, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Challenge-Response", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Security */
+		{
+			/*
+				The ARAP-Security AVP (AVP Code 73) is of type Unsigned32 and MAY be
+				present in the AA-Answer message if the Framed-Protocol AVP (see
+				section 6.10.1) is set to the value of ARAP, and the Result-Code AVP
+				is set to DIAMETER_MULTI_ROUND_AUTH.  See [RADIUSExt] for more
+				information on the format of this AVP.
+			*/
+			struct dict_avp_data data = { 
+					73, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Security", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Security-Data */
+		{
+			/*
+				The ARAP-Security-Data AVP (AVP Code 74) is of type OctetString and MAY be
+				present in the AA-Request or AA-Answer message if the Framed-Protocol
+				AVP is set to the value of ARAP, and the Result-Code AVP is set to
+				DIAMETER_MULTI_ROUND_AUTH.  This AVP contains the security module
+				challenge or response associated with the ARAP Security Module
+				specified in ARAP-Security.
+			*/
+			struct dict_avp_data data = { 
+					74, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Security-Data", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/********************************
+ *  NAS Authorization AVPs      *
+ ********************************/		
+		/* Service-Type */
+		{
+			/*
+				The Service-Type AVP (AVP Code 6) is of type Enumerated and contains
+				the type of service the user has requested or the type of service to
+				be provided.  One such AVP MAY be present in an authentication and/or
+				authorization request or response.  A NAS is not required to
+				implement all of these service types.  It MUST treat unknown or
+				unsupported Service-Types received in a response as a failure and end
+				the session with a DIAMETER_INVALID_AVP_VALUE Result-Code.
+
+				When used in a request, the Service-Type AVP SHOULD be considered a
+				hint to the server that the NAS believes the user would prefer the
+				kind of service indicated.  The server is not required to honor the
+				hint.  Furthermore, if the service specified by the server is
+				supported, but not compatible with the current mode of access, the
+				NAS MUST fail to start the session.  The NAS MUST also generate the
+				appropriate error message(s).
+
+				The following values have been defined for the Service-Type AVP.  The
+				complete list of defined values can be found in [RADIUS] and
+				[RADIUSTypes].
+
+				Registry Name: Radius Attribute Values
+				Reference: [RFC2865][RFC3575]
+
+				Sub-registry: Values for RADIUS Attribute 6, Service-Type
+				Reference: [RFC2865][RFC3575]
+
+				1  Login
+				2  Framed
+				3  Callback Login
+				4  Callback Framed
+				5  Outbound
+				6  Administrative
+				7  NAS Prompt
+				8  Authenticate Only
+				9  Callback NAS Prompt
+				10  Call Check
+				11  Callback Administrative
+				12  Voice           [Chiba]
+				13  Fax             [Chiba]
+				14  Modem Relay	    [Chiba]
+				15  IAPP-Register   [IEEE 802.11f][Kerry]
+				16  IAPP-AP-Check   [IEEE 802.11f][Kerry]
+				17  Authorize Only  [RFC3576]
+
+				The following values are further qualified:
+
+				Login               1
+				 The user should be connected to a host.  The message MAY
+				 include additional AVPs defined in sections 6.16 or 6.17.
+
+				Framed              2
+				 A Framed Protocol, such as PPP or SLIP, should be started for
+				 the User.  The message MAY include additional AVPs defined in
+				 section 6.10, or section 7 for tunneling services.
+
+				Callback Login      3
+				 The user should be disconnected and called back, then connected
+				 to a host.  The message MAY include additional AVPs defined in
+				 this section.
+
+				Callback Framed     4
+				 The user should be disconnected and called back, and then a
+				 Framed Protocol, such as PPP or SLIP, should be started for the
+				 User.  The message MAY include additional AVPs defined in
+				 section 6.10, or in section 7 for tunneling services.
+
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Service-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "Login"),
+				enumval_def_u32( 2, "Framed"),
+				enumval_def_u32( 3, "Callback Login"),
+				enumval_def_u32( 4, "Callback Framed"),
+				enumval_def_u32( 5, "Outbound"),
+				enumval_def_u32( 6, "Administrative"),
+				enumval_def_u32( 7, "NAS Prompt"),
+				enumval_def_u32( 8, "Authenticate Only"),
+				enumval_def_u32( 9, "Callback NAS Prompt"),
+				enumval_def_u32(10, "Call Check"),
+				enumval_def_u32(11, "Callback Administrative"),
+				enumval_def_u32(12, "Voice [Chiba]"),
+				enumval_def_u32(13, "Fax [Chiba]"),
+				enumval_def_u32(14, "Modem Relay [Chiba]"),
+				enumval_def_u32(15, "IAPP-Register [IEEE 802.11f][Kerry]"),
+				enumval_def_u32(16, "IAPP-AP-Check [IEEE 802.11f][Kerry]"),
+				enumval_def_u32(17, "Authorize Only [RFC3576]")
+			};
+			struct dict_avp_data data = { 
+					6, 					/* Code */
+					0, 					/* Vendor */
+					"Service-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Callback-Number */
+		{
+			/*
+				The Callback-Number AVP (AVP Code 19) is of type UTF8String and
+				contains a dialing string to be used for callback.  It MAY be used in
+				an authentication and/or authorization request as a hint to the
+				server that a Callback service is desired, but the server is not
+				required to honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					19, 					/* Code */
+					0, 					/* Vendor */
+					"Callback-Number", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Callback-Id */
+		{
+			/*
+				The Callback-Id AVP (AVP Code 20) is of type UTF8String and contains
+				the name of a place to be called, to be interpreted by the NAS.  This
+				AVP MAY be present in an authentication and/or authorization
+				response.
+
+				This AVP is not roaming-friendly as it assumes that the Callback-Id
+				is configured on the NAS.  Using the Callback-Number AVP therefore
+				preferable.
+			*/
+			struct dict_avp_data data = { 
+					20, 					/* Code */
+					0, 					/* Vendor */
+					"Callback-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Idle-Timeout */
+		{
+			/*
+				The Idle-Timeout AVP (AVP Code 28) is of type Unsigned32 and sets the
+				maximum number of consecutive seconds of idle connection allowable to
+				the user before termination of the session or before a prompt is
+				issued.  The default is none, or system specific.
+			*/
+			struct dict_avp_data data = { 
+					28, 					/* Code */
+					0, 					/* Vendor */
+					"Idle-Timeout", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Port-Limit */
+		{
+			/*
+				The Port-Limit AVP (AVP Code 62) is of type Unsigned32 and sets the
+				maximum number of ports the NAS provides to the user.  It MAY be used
+				in an authentication and/or authorization request as a hint to the
+				server that multilink PPP [PPPMP] service is desired, but the server
+				is not required to honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					62, 					/* Code */
+					0, 					/* Vendor */
+					"Port-Limit", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* NAS-Filter-Rule */
+		{
+			/*
+				The NAS-Filter-Rule AVP (AVP Code 400) is of type IPFilterRule and
+				provides filter rules that need to be configured on the NAS for the
+				user.  One or more of these AVPs MAY be present in an authorization
+				response.
+			*/
+			struct dict_avp_data data = { 
+					400, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Filter-Rule", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , IPFilterRule_type, NULL);
+		}
+		
+		/* Filter-Id */
+		{
+			/*
+				The Filter-Id AVP (AVP Code 11) is of type UTF8String and contains
+				the name of the filter list for this user.  Zero or more Filter-Id
+				AVPs MAY be sent in an authorization answer.
+
+				Identifying a filter list by name allows the filter to be used on
+				different NASes without regard to filter-list implementation details.
+				However, this AVP is not roaming friendly, as filter naming differs
+				from one service provider to another.
+
+				In non-RADIUS environments, it is RECOMMENDED that the NAS-Filter-
+				Rule AVP be used instead.
+			*/
+			struct dict_avp_data data = { 
+					11, 					/* Code */
+					0, 					/* Vendor */
+					"Filter-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Configuration-Token */
+		{
+			/*
+				The Configuration-Token AVP (AVP Code 78) is of type OctetString and
+				is sent by a Diameter Server to a Diameter Proxy Agent or Translation
+				Agent in an AA-Answer command to indicate a type of user profile to
+				be used.  It should not be sent to a Diameter Client (NAS).
+
+				The format of the Data field of this AVP is site specific.
+			*/
+			struct dict_avp_data data = { 
+					78, 					/* Code */
+					0, 					/* Vendor */
+					"Configuration-Token", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* QoS-Filter-Rule */
+		{
+			/*
+				The QoS-Filter-Rule AVP (AVP Code 407) is of type QoSFilterRule and
+				provides QoS filter rules that need to be configured on the NAS for
+				the user.  One or more such AVPs MAY be present in an authorization
+				response.
+			*/
+			struct dict_avp_data data = { 
+					407, 					/* Code */
+					0, 					/* Vendor */
+					"QoS-Filter-Rule", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , QoSFilterRule_type, NULL);
+		}
+		
+/***  Framed Access Authorization AVPs  ***/
+		
+		/* Framed-Protocol */
+		{
+			/*
+				The Framed-Protocol AVP (AVP Code 7) is of type Enumerated and
+				contains the framing to be used for framed access.  This AVP MAY be
+				present in both requests and responses.  The supported values are
+				listed in [RADIUSTypes].
+
+				Sub-registry: Values for RADIUS Attribute 7, Framed-Protocol
+				Reference: [RFC2865]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Framed-Protocol)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "PPP"),
+				enumval_def_u32( 2, "SLIP"),
+				enumval_def_u32( 3, "AppleTalk Remote Access Protocol (ARAP)"),
+				enumval_def_u32( 4, "Gandalf proprietary SingleLink/MultiLink protocol"),
+				enumval_def_u32( 5, "Xylogics proprietary IPX/SLIP"),
+				enumval_def_u32( 6, "X.75 Synchronous"),
+				enumval_def_u32( 7, "GPRS PDP Context [Moore]")
+			};
+			struct dict_avp_data data = { 
+					7, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Protocol", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Framed-Routing */
+		{
+			/*
+				The Framed-Routing AVP (AVP Code 10) is of type Enumerated and
+				contains the routing method for the user when the user is a router to
+				a network.  This AVP SHOULD only be present in authorization
+				responses.  The supported values are listed in [RADIUSTypes].
+
+				Sub-registry: Values for RADIUS Attribute 10, Framed-Routing
+				Reference: [RFC2865]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Framed-Routing)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "None"),
+				enumval_def_u32( 1, "Send routing packets"),
+				enumval_def_u32( 2, "Listen for routing packets"),
+				enumval_def_u32( 3, "Send and Listen")
+			};
+			struct dict_avp_data data = { 
+					10, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Routing", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Framed-MTU */
+		{
+			/*
+				The Framed-MTU AVP (AVP Code 12) is of type Unsigned32 and contains
+				the Maximum Transmission Unit to be configured for the user, when it
+				is not negotiated by some other means (such as PPP).  This AVP SHOULD
+				only be present in authorization responses.  The MTU value MUST be in
+				the range from 64 to 65535.
+			*/
+			struct dict_avp_data data = { 
+					12, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-MTU", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-Compression */
+		{
+			/*
+				The Framed-Compression AVP (AVP Code 13) is of type Enumerated and
+				contains the compression protocol to be used for the link.  It MAY be
+				used in an authorization request as a hint to the server that a
+				specific compression type is desired, but the server is not required
+				to honor the hint in the corresponding response.
+
+				More than one compression protocol AVP MAY be sent.  The NAS is
+				responsible for applying the proper compression protocol to the
+				appropriate link traffic.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 13, Framed-Compression
+				Reference: [RFC2865]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Framed-Compression)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "None"),
+				enumval_def_u32( 1, "VJ TCP/IP header compression"),
+				enumval_def_u32( 2, "IPX header compression"),
+				enumval_def_u32( 3, "Stac-LZS compression")
+			};
+			struct dict_avp_data data = { 
+					13, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Compression", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+/***  IP Access Authorization AVPs  ***/
+		
+		/* Framed-IP-Address */
+		{
+			/*
+				The Framed-IP-Address AVP (AVP Code 8) [RADIUS] is of type
+				OctetString and contains an IPv4 address of the type specified in the
+				attribute value to be configured for the user.  It MAY be used in an
+				authorization request as a hint to the server that a specific address
+				is desired, but the server is not required to honor the hint in the
+				corresponding response.
+
+				Two values have special significance: 0xFFFFFFFF and 0xFFFFFFFE.  The
+				value 0xFFFFFFFF indicates that the NAS should allow the user to
+				select an address (i.e., negotiated).  The value 0xFFFFFFFE indicates
+				that the NAS should select an address for the user (e.g., assigned
+				from a pool of addresses kept by the NAS).
+			*/
+			struct dict_avp_data data = { 
+					8, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IP-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-IP-Netmask */
+		{
+			/*
+				The Framed-IP-Netmask AVP (AVP Code 9) is of type OctetString and
+				contains the four octets of the IPv4 netmask to be configured for the
+				user when the user is a router to a network.  It MAY be used in an
+				authorization request as a hint to the server that a specific netmask
+				is desired, but the server is not required to honor the hint in the
+				corresponding response.  This AVP MUST be present in a response if
+				the request included this AVP with a value of 0xFFFFFFFF.
+			*/
+			struct dict_avp_data data = { 
+					9, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IP-Netmask", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-Route */
+		{
+			/*
+				The Framed-Route AVP (AVP Code 22) is of type UTF8String and contains
+				the ASCII routing information to be configured for the user on the
+				NAS.  Zero or more of these AVPs MAY be present in an authorization
+				response.
+
+				The string MUST contain a destination prefix in dotted quad form
+				optionally followed by a slash and a decimal length specifier stating
+				how many high-order bits of the prefix should be used.  This is
+				followed by a space, a gateway address in dotted quad form, a space,
+				and one or more metrics separated by spaces; for example,
+
+				"192.168.1.0/24 192.168.1.1 1".
+
+				The length specifier may be omitted, in which case it should default
+				to 8 bits for class A prefixes, to 16 bits for class B prefixes, and
+				to 24 bits for class C prefixes; for example,
+
+				"192.168.1.0 192.168.1.1 1".
+
+				Whenever the gateway address is specified as "0.0.0.0" the IP address
+				of the user SHOULD be used as the gateway address.
+			*/
+			struct dict_avp_data data = { 
+					22, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Route", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Framed-Pool */
+		{
+			/*
+				The Framed-Pool AVP (AVP Code 88) is of type OctetString and contains
+				the name of an assigned address pool that SHOULD be used to assign an
+				address for the user.  If a NAS does not support multiple address
+				pools, the NAS SHOULD ignore this AVP.  Address pools are usually
+				used for IP addresses but can be used for other protocols if the NAS
+				supports pools for those protocols.
+
+				Although specified as type OctetString for compatibility with RADIUS
+				[RADIUSExt], the encoding of the Data field SHOULD also conform to
+				the rules for the UTF8String Data Format.
+			*/
+			struct dict_avp_data data = { 
+					88, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Pool", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-Interface-Id */
+		{
+			/*
+				The Framed-Interface-Id AVP (AVP Code 96) is of type Unsigned64 and
+				contains the IPv6 interface identifier to be configured for the user.
+				It MAY be used in authorization requests as a hint to the server that
+				a specific interface id is desired, but the server is not required to
+				honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					96, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Interface-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-IPv6-Prefix */
+		{
+			/*
+				The Framed-IPv6-Prefix AVP (AVP Code 97) is of type OctetString and
+				contains the IPv6 prefix to be configured for the user.  One or more
+				AVPs MAY be used in authorization requests as a hint to the server
+				that specific IPv6 prefixes are desired, but the server is not
+				required to honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					97, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPv6-Prefix", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-IPv6-Route */
+		{
+			/*
+				The Framed-IPv6-Route AVP (AVP Code 99) is of type UTF8String and
+				contains the ASCII routing information to be configured for the user
+				on the NAS.  Zero or more of these AVPs MAY be present in an
+				authorization response.
+
+				The string MUST contain an IPv6 address prefix followed by a slash
+				and a decimal length specifier stating how many high order bits of
+				the prefix should be used.  This is followed by a space, a gateway
+				address in hexadecimal notation, a space, and one or more metrics
+				separated by spaces; for example,
+
+				"2000:0:0:106::/64 2000::106:a00:20ff:fe99:a998 1".
+
+				Whenever the gateway address is the IPv6 unspecified address, the IP
+				address of the user SHOULD be used as the gateway address, such as
+				in:
+
+				"2000:0:0:106::/64 :: 1".
+			*/
+			struct dict_avp_data data = { 
+					99, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPv6-Route", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Framed-IPv6-Pool */
+		{
+			/*
+				The Framed-IPv6-Pool AVP (AVP Code 100) is of type OctetString and
+				contains the name of an assigned pool that SHOULD be used to assign
+				an IPv6 prefix for the user.  If the access device does not support
+				multiple prefix pools, it MUST ignore this AVP.
+
+				Although specified as type OctetString for compatibility with RADIUS
+				[RADIUSIPv6], the encoding of the Data field SHOULD also conform to
+				the rules for the UTF8String Data Format.
+			*/
+			struct dict_avp_data data = { 
+					100, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPv6-Pool", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  IPX Access  ***/
+		
+		/* Framed-IPX-Network */
+		{
+			/*
+				The Framed-IPX-Network AVP (AVP Code 23) is of type Unsigned32 and
+				contains the IPX Network number to be configured for the user.  It
+				MAY be used in an authorization request as a hint to the server that
+				a specific address is desired, but the server is not required to
+				honor the hint in the corresponding response.
+
+				Two addresses have special significance: 0xFFFFFFFF and 0xFFFFFFFE.
+				The value 0xFFFFFFFF indicates that the NAS should allow the user to
+				select an address (i.e., Negotiated).  The value 0xFFFFFFFE indicates
+				that the NAS should select an address for the user (e.g., assign it
+				from a pool of one or more IPX networks kept by the NAS).
+			*/
+			struct dict_avp_data data = { 
+					23, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPX-Network", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  AppleTalk Network Access  ***/
+		
+		/* Framed-AppleTalk-Link */
+		{
+			/*
+				The Framed-AppleTalk-Link AVP (AVP Code 37) is of type Unsigned32 and
+				contains the AppleTalk network number that should be used for the
+				serial link to the user, which is another AppleTalk router.  This AVP
+				MUST only be present in an authorization response and is never used
+				when the user is not another router.
+
+				Despite the size of the field, values range from 0 to 65,535.  The
+				special value of 0 indicates an unnumbered serial link.  A value of 1
+				to 65,535 means that the serial line between the NAS and the user
+				should be assigned that value as an AppleTalk network number.
+			*/
+			struct dict_avp_data data = { 
+					37, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-AppleTalk-Link", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-AppleTalk-Network */
+		{
+			/*
+				The Framed-AppleTalk-Network AVP (AVP Code 38) is of type Unsigned32
+				and contains the AppleTalk Network number that the NAS should probe
+				to allocate an AppleTalk node for the user.  This AVP MUST only be
+				present in an authorization response and is never used when the user
+				is not another router.  Multiple instances of this AVP indicate that
+				the NAS may probe, using any of the network numbers specified.
+
+				Despite the size of the field, values range from 0 to 65,535.  The
+				special value 0 indicates that the NAS should assign a network for
+				the user, using its default cable range.  A value between 1 and
+				65,535 (inclusive) indicates to the AppleTalk Network that the NAS
+				should probe to find an address for the user.
+			*/
+			struct dict_avp_data data = { 
+					38, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-AppleTalk-Network", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-AppleTalk-Zone */
+		{
+			/*
+				The Framed-AppleTalk-Zone AVP (AVP Code 39) is of type OctetString
+				and contains the AppleTalk Default Zone to be used for this user.
+				This AVP MUST only be present in an authorization response.  Multiple
+				instances of this AVP in the same message are not allowed.
+
+				The codification of this field's allowed range is outside the scope
+				of this specification.
+			*/
+			struct dict_avp_data data = { 
+					39, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-AppleTalk-Zone", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  AppleTalk Remote Access [RFC2869] ***/
+		
+		/* ARAP-Features */
+		{
+			/*
+				The ARAP-Features AVP (AVP Code 71) is of type OctetString and MAY be
+				present in the AA-Accept message if the Framed-Protocol AVP is set to
+				the value of ARAP.  See [RADIUSExt] for more information about the
+				format of this AVP.
+			*/
+			struct dict_avp_data data = { 
+					71, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Features", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Zone-Access */
+		{
+			/*
+				The ARAP-Zone-Access AVP (AVP Code 72) is of type Enumerated and MAY
+				be present in the AA-Accept message if the Framed-Protocol AVP is set
+				to the value of ARAP.
+
+				The supported values are listed in [RADIUSTypes] and defined in
+				[RADIUSExt].
+				Sub-registry: Values for RADIUS Attribute 72, ARAP-Zone-Access 
+				Reference: [RFC2869]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(ARAP-Zone-Access)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "Only allow access to default zone [RFC2869]"),
+				enumval_def_u32( 2, "Use zone filter inclusively [RFC2869]"),
+				enumval_def_u32( 3, "Not used [RFC2869]"),
+				enumval_def_u32( 4, "Use zone filter exclusively [RFC2869]")
+			};
+			struct dict_avp_data data = { 
+					72, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Zone-Access", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+/***  Non-Framed Access Authorization AVPs ***/
+		
+		/* Login-IP-Host */
+		{
+			/*
+				The Login-IP-Host AVP (AVP Code 14) [RADIUS] is of type OctetString
+				and contains the IPv4 address of a host with which to connect the
+				user when the Login-Service AVP is included.  It MAY be used in an
+				AA-Request command as a hint to the Diameter Server that a specific
+				host is desired, but the Diameter Server is not required to honor the
+				hint in the AA-Answer.
+
+				Two addresses have special significance: all ones and 0.  The value
+				of all ones indicates that the NAS SHOULD allow the user to select an
+				address.  The value 0 indicates that the NAS SHOULD select a host to
+				connect the user to.
+			*/
+			struct dict_object 	*type;
+			uint32_t		 allzeros = 0;
+			uint32_t		 allones  = (uint32_t) -1;
+			struct dict_type_data 	 tdata = { AVP_TYPE_OCTETSTRING,	"Enumerated(Login-IP-Host)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_os( 4, &allzeros, "(0) NAS selects the host"),
+				enumval_def_os( 4, &allones , "(1) User selects the address")
+			};
+			struct dict_avp_data data = { 
+					14, 					/* Code */
+					0, 					/* Vendor */
+					"Login-IP-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Login-IPv6-Host */
+		{
+			/*
+				The Login-IPv6-Host AVP (AVP Code 98) [RADIUSIPv6] is of type
+				OctetString and contains the IPv6 address of a host with which to
+				connect the user when the Login-Service AVP is included.  It MAY be
+				used in an AA-Request command as a hint to the Diameter Server that a
+				specific host is desired, but the Diameter Server is not required to
+				honor the hint in the AA-Answer.
+
+				Two addresses have special significance:
+
+				0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF and 0.  The value
+				0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF indicates that the NAS SHOULD
+				allow the user to select an address.  The value 0 indicates that the
+				NAS SHOULD select a host to connect the user to.
+
+			*/
+			struct dict_object 	*type;
+			unsigned char 		 allzeros[16];
+			unsigned char		 allones[16];
+			struct dict_type_data 	 tdata = { AVP_TYPE_OCTETSTRING,	"Enumerated(Login-IPv6-Host)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_os( 16, &allzeros, "(0) NAS selects the host"),
+				enumval_def_os( 16, &allones , "(1) User selects the address")
+			};
+			struct dict_avp_data data = { 
+					98, 					/* Code */
+					0, 					/* Vendor */
+					"Login-IPv6-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			int i;
+			memset(allzeros, 0,   sizeof(allzeros));
+			memset(allones, 0xff, sizeof(allones));
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Login-Service */
+		{
+			/*
+				The Login-Service AVP (AVP Code 15) is of type Enumerated and
+				contains the service that should be used to connect the user to the
+				login host.  This AVP SHOULD only be present in authorization
+				responses.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 15, Login-Service
+				Reference: [RFC2865]
+   			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Login-Service)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "Telnet"),
+				enumval_def_u32( 1, "Rlogin"),
+				enumval_def_u32( 2, "TCP Clear"),
+				enumval_def_u32( 3, "PortMaster (proprietary)"),
+				enumval_def_u32( 4, "LAT"),
+				enumval_def_u32( 5, "X25-PAD"),
+				enumval_def_u32( 6, "X25-T3POS"),
+				enumval_def_u32( 8, "TCP Clear Quiet (suppresses any NAS-generated connect string)")
+			};
+			struct dict_avp_data data = { 
+					15, 					/* Code */
+					0, 					/* Vendor */
+					"Login-Service", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+/***  TCP Services  ***/
+		
+		/* Login-TCP-Port */
+		{
+			/*
+				The Login-TCP-Port AVP (AVP Code 16) is of type Unsigned32 and
+				contains the TCP port with which the user is to be connected when the
+				Login-Service AVP is also present.  This AVP SHOULD only be present
+				in authorization responses.  The value MUST NOT be greater than
+				65,535.
+			*/
+			struct dict_avp_data data = { 
+					16, 					/* Code */
+					0, 					/* Vendor */
+					"Login-TCP-Port", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  LAT Services  ***/
+		
+		/* Login-LAT-Service */
+		{
+			/*
+				The Login-LAT-Service AVP (AVP Code 34) is of type OctetString and
+				contains the system with which the user is to be connected by LAT.
+				It MAY be used in an authorization request as a hint to the server
+				that a specific service is desired, but the server is not required to
+				honor the hint in the corresponding response.  This AVP MUST only be
+				present in the response if the Login-Service AVP states that LAT is
+				desired.
+
+				Administrators use this service attribute when dealing with clustered
+				systems, such as a VAX or Alpha cluster.  In these environments,
+				several different time-sharing hosts share the same resources (disks,
+				printers, etc.), and administrators often configure each host to
+				offer access (service) to each of the shared resources.  In this
+				case, each host in the cluster advertises its services through LAT
+				broadcasts.
+
+				Sophisticated users often know which service providers (machines) are
+				faster and tend to use a node name when initiating a LAT connection.
+				Some administrators want particular users to use certain machines as
+				a primitive form of load balancing (although LAT knows how to do load
+				balancing itself).
+
+				The String field contains the identity of the LAT service to use.
+				The LAT Architecture allows this string to contain $ (dollar), -
+				(hyphen), . (period), _ (underscore), numerics, upper- and lowercase
+				alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+				All LAT string comparisons are case insensitive.
+			*/
+			struct dict_avp_data data = { 
+					34, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Service", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Login-LAT-Node */
+		{
+			/*
+				The Login-LAT-Node AVP (AVP Code 35) is of type OctetString and
+				contains the Node with which the user is to be automatically
+				connected by LAT.  It MAY be used in an authorization request as a
+				hint to the server that a specific LAT node is desired, but the
+				server is not required to honor the hint in the corresponding
+				response.  This AVP MUST only be present in a response if the Login-
+				Service-Type AVP is set to LAT.
+
+				The String field contains the identity of the LAT service to use.
+				The LAT Architecture allows this string to contain $ (dollar), -
+				(hyphen), . (period), _ (underscore), numerics, upper- and lowercase
+				alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+				All LAT string comparisons are case insensitive.
+			*/
+			struct dict_avp_data data = { 
+					35, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Node", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Login-LAT-Group */
+		{
+			/*
+				The Login-LAT-Group AVP (AVP Code 36) is of type OctetString and
+				contains a string identifying the LAT group codes this user is
+				authorized to use.  It MAY be used in an authorization request as a
+				hint to the server that a specific group is desired, but the server
+				is not required to honor the hint in the corresponding response.
+				This AVP MUST only be present in a response if the Login-Service-Type
+				AVP is set to LAT.
+
+				LAT supports 256 different group codes, which LAT uses as a form of
+				access rights.  LAT encodes the group codes as a 256-bit bitmap.
+
+				Administrators can assign one or more of the group code bits at the
+				LAT service provider; it will only accept LAT connections that have
+				these group codes set in the bitmap.  The administrators assign a
+				bitmap of authorized group codes to each user.  LAT gets these from
+				the operating system and uses them in its requests to the service
+				providers.
+
+				The codification of the range of allowed usage of this field is
+				outside the scope of this specification.
+			*/
+			struct dict_avp_data data = { 
+					36, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Group", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Login-LAT-Port */
+		{
+			/*
+				The Login-LAT-Port AVP (AVP Code 63) is of type OctetString and
+				contains the Port with which the user is to be connected by LAT.  It
+				MAY be used in an authorization request as a hint to the server that
+				a specific port is desired, but the server is not required to honor
+				the hint in the corresponding response.  This AVP MUST only be
+				present in a response if the Login-Service-Type AVP is set to LAT.
+
+				The String field contains the identity of the LAT service to use.
+				The LAT Architecture allows this string to contain $ (dollar), -
+				(hyphen), . (period), _ (underscore), numerics, upper- and lower-case
+				alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+				All LAT string comparisons are case insensitive.
+			*/
+			struct dict_avp_data data = { 
+					63, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Port", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/********************************
+ *  NAS Tunneling AVPs          *
+ ********************************/		
+		/* Tunnel-Type */
+		{
+			/*
+				The Tunnel-Type AVP (AVP Code 64) is of type Enumerated and contains
+				the tunneling protocol(s) to be used (in the case of a tunnel
+				initiator) or in use (in the case of a tunnel terminator).  It MAY be
+				used in an authorization request as a hint to the server that a
+				specific tunnel type is desired, but the server is not required to
+				honor the hint in the corresponding response.
+
+				The Tunnel-Type AVP SHOULD also be included in Accounting-Request
+				messages.
+
+				A tunnel initiator is not required to implement any of these tunnel
+				types.  If a tunnel initiator receives a response that contains only
+				unknown or unsupported Tunnel-Types, the tunnel initiator MUST behave
+				as though a response were received with the Result-Code indicating a
+				failure.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 64, Tunnel-Type 
+				Reference: [RFC2868]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Tunnel-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "Point-to-Point Tunneling Protocol (PPTP) [RFC2868]"),
+				enumval_def_u32( 2, "Layer Two Forwarding (L2F) [RFC2868]"),
+				enumval_def_u32( 3, "Layer Two Tunneling Protocol (L2TP) [RFC2868]"),
+				enumval_def_u32( 4, "Ascend Tunnel Management Protocol (ATMP) [RFC2868]"),
+				enumval_def_u32( 5, "Virtual Tunneling Protocol (VTP) [RFC2868]"),
+				enumval_def_u32( 6, "IP Authentication Header in the Tunnel-mode (AH) [RFC2868]"),
+				enumval_def_u32( 7, "IP-in-IP Encapsulation (IP-IP) [RFC2868]"),
+				enumval_def_u32( 8, "Minimal IP-in-IP Encapsulation (MIN-IP-IP) [RFC2868]"),
+				enumval_def_u32( 9, "IP Encapsulating Security Payload in the Tunnel-mode (ESP) [RFC2868]"),
+				enumval_def_u32(10, "Generic Route Encapsulation (GRE) [RFC2868]"),
+				enumval_def_u32(11, "Bay Dial Virtual Services (DVS) [RFC2868]"),
+				enumval_def_u32(12, "IP-in-IP Tunneling [RFC2868]"),
+				enumval_def_u32(13, "Virtual LANs (VLAN) [RFC3580]")
+			};
+			struct dict_avp_data adata = { 
+					64, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Type", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &adata , type, NULL);
+		}
+		
+		/* Tunnel-Medium-Type */
+		{
+			/*
+				The Tunnel-Medium-Type AVP (AVP Code 65) is of type Enumerated and
+				contains the transport medium to use when creating a tunnel for
+				protocols (such as L2TP) that can operate over multiple transports.
+				It MAY be used in an authorization request as a hint to the server
+				that a specific medium is desired, but the server is not required to
+				honor the hint in the corresponding response.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 65, Tunnel-Medium-Type
+				Reference: [RFC2868]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Tunnel-Medium-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "IPv4 (IP version 4) [RFC2868]"),
+				enumval_def_u32( 2, "IPv6 (IP version 6) [RFC2868]"),
+				enumval_def_u32( 3, "NSAP [RFC2868]"),
+				enumval_def_u32( 4, "HDLC (8-bit multidrop) [RFC2868]"),
+				enumval_def_u32( 5, "BBN 1822 [RFC2868]"),
+				enumval_def_u32( 6, "802 (includes all 802 media plus Ethernet \"canonical format\") [RFC2868]"),
+				enumval_def_u32( 7, "E.163 (POTS) [RFC2868]"),
+				enumval_def_u32( 8, "E.164 (SMDS, Frame Relay, ATM) [RFC2868]"),
+				enumval_def_u32( 9, "F.69 (Telex) [RFC2868]"),
+				enumval_def_u32(10, "X.121 (X.25, Frame Relay) [RFC2868]"),
+				enumval_def_u32(11, "IPX [RFC2868]"),
+				enumval_def_u32(12, "Appletalk [RFC2868]"),
+				enumval_def_u32(13, "Decnet IV [RFC2868]"),
+				enumval_def_u32(14, "Banyan Vines [RFC2868]"),
+				enumval_def_u32(15, "E.164 with NSAP format subaddress [RFC2868]")
+			};
+			struct dict_avp_data adata = { 
+					65, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Medium-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &adata , type, NULL);
+		}
+		
+		/* Tunnel-Client-Endpoint */
+		{
+			/*
+				The Tunnel-Client-Endpoint AVP (AVP Code 66) is of type UTF8String
+				and contains the address of the initiator end of the tunnel.  It MAY
+				be used in an authorization request as a hint to the server that a
+				specific endpoint is desired, but the server is not required to honor
+				the hint in the corresponding response.
+
+				This AVP SHOULD be included in the corresponding Accounting-Request
+				messages, in which case it indicates the address from which the
+				tunnel was initiated.  This AVP, along with the Tunnel-Server-
+				Endpoint and Session-Id AVP [BASE], MAY be used to provide a globally
+				unique means to identify a tunnel for accounting and auditing
+				purposes.
+
+				If Tunnel-Medium-Type is IPv4 (1), then this string is either the
+				fully qualified domain name (FQDN) of the tunnel client machine, or a
+				"dotted-decimal" IP address.  Implementations MUST support the
+				dotted-decimal format and SHOULD support the FQDN format for IP
+				addresses.
+
+				If Tunnel-Medium-Type is IPv6 (2), then this string is either the
+				FQDN of the tunnel client machine, or a text representation of the
+				address in either the preferred or alternate form [IPv6Addr].
+				Conforming implementations MUST support the preferred form and SHOULD
+				support both the alternate text form and the FQDN format for IPv6
+				addresses.
+
+				If Tunnel-Medium-Type is neither IPv4 nor IPv6, then this string is a
+				tag referring to configuration data local to the Diameter client that
+				describes the interface or medium-specific client address to use.
+   			*/
+			struct dict_avp_data adata = { 
+					66, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Client-Endpoint", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunnel-Server-Endpoint */
+		{
+			/*
+				The Tunnel-Server-Endpoint AVP (AVP Code 67) is of type UTF8String
+				and contains the address of the server end of the tunnel.  It MAY be
+				used in an authorization request as a hint to the server that a
+				specific endpoint is desired, but the server is not required to honor
+				the hint in the corresponding response.
+
+				This AVP SHOULD be included in the corresponding Accounting-Request
+				messages, in which case it indicates the address from which the
+				tunnel was initiated.  This AVP, along with the Tunnel-Client-
+				Endpoint and Session-Id AVP [BASE], MAY be used to provide a globally
+				unique means to identify a tunnel for accounting and auditing
+				purposes.
+
+				If Tunnel-Medium-Type is IPv4 (1), then this string is either the
+				fully qualified domain name (FQDN) of the tunnel server machine, or a
+				"dotted-decimal" IP address.  Implementations MUST support the
+				dotted-decimal format and SHOULD support the FQDN format for IP
+				addresses.
+
+				If Tunnel-Medium-Type is IPv6 (2), then this string is either the
+				FQDN of the tunnel server machine, or a text representation of the
+				address in either the preferred or alternate form [IPv6Addr].
+				Implementations MUST support the preferred form and SHOULD support
+				both the alternate text form and the FQDN format for IPv6 addresses.
+
+				If Tunnel-Medium-Type is not IPv4 or IPv6, this string is a tag
+				referring to configuration data local to the Diameter client that
+				describes the interface or medium-specific server address to use.
+   			*/
+			struct dict_avp_data adata = { 
+					67, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Server-Endpoint", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunnel-Password */
+		{
+			/*
+				The Tunnel-Password AVP (AVP Code 69) is of type OctetString and may
+				contain a password to be used to authenticate to a remote server.
+				The Tunnel-Password AVP contains sensitive information.  This value
+				is not protected in the same manner as RADIUS [RADTunnels].
+
+				As required in [BASE], Diameter messages are encrypted by using IPsec
+				or TLS.  The Tunnel-Password AVP SHOULD NOT be used in untrusted
+				proxy environments without encrypting it by using end-to-end security
+				techniques, such as CMS Security [DiamCMS].
+   			*/
+			struct dict_avp_data adata = { 
+					69, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Password", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Private-Group-Id */
+		{
+			/*
+				The Tunnel-Private-Group-Id AVP (AVP Code 81) is of type OctetString
+				and contains the group Id for a particular tunneled session.  The
+				Tunnel-Private-Group-Id AVP MAY be included in an authorization
+				request if the tunnel initiator can predetermine the group resulting
+				from a particular connection.  It SHOULD be included in the
+				authorization response if this tunnel session is to be treated as
+				belonging to a particular private group.  Private groups may be used
+				to associate a tunneled session with a particular group of users.
+				For example, it MAY be used to facilitate routing of unregistered IP
+				addresses through a particular interface.  This AVP SHOULD be
+				included in the Accounting-Request messages that pertain to the
+				tunneled session.
+   			*/
+			struct dict_avp_data adata = { 
+					81, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Private-Group-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Assignment-Id */
+		{
+			/*
+				The Tunnel-Assignment-Id AVP (AVP Code 82) is of type OctetString and
+				is used to indicate to the tunnel initiator the particular tunnel to
+				which a session is to be assigned.  Some tunneling protocols, such as
+				[PPTP] and [L2TP], allow for sessions between the same two tunnel
+				endpoints to be multiplexed over the same tunnel and also for a given
+				session to use its own dedicated tunnel.  This attribute provides a
+				mechanism for Diameter to inform the tunnel initiator (e.g., PAC,
+				LAC) whether to assign the session to a multiplexed tunnel or to a
+				separate tunnel.  Furthermore, it allows for sessions sharing
+				multiplexed tunnels to be assigned to different multiplexed tunnels.
+
+				A particular tunneling implementation may assign differing
+				characteristics to particular tunnels.  For example, different
+				tunnels may be assigned different QoS parameters.  Such tunnels may
+				be used to carry either individual or multiple sessions.  The
+				Tunnel-Assignment-Id attribute thus allows the Diameter server to
+				indicate that a particular session is to be assigned to a tunnel
+				providing an appropriate level of service.  It is expected that any
+				QoS-related Diameter tunneling attributes defined in the future
+				accompanying this one will be associated by the tunnel initiator with
+				the Id given by this attribute.  In the meantime, any semantic given
+				to a particular Id string is a matter left to local configuration in
+				the tunnel initiator.
+
+				The Tunnel-Assignment-Id AVP is of significance only to Diameter and
+				the tunnel initiator.  The Id it specifies is only intended to be of
+				local use to Diameter and the tunnel initiator.  The Id assigned by
+				the tunnel initiator is not conveyed to the tunnel peer.
+
+				This attribute MAY be included in authorization responses.  The
+				tunnel initiator receiving this attribute MAY choose to ignore it and
+				to assign the session to an arbitrary multiplexed or non-multiplexed
+				tunnel between the desired endpoints.  This AVP SHOULD also be
+				included in the Accounting-Request messages pertaining to the
+				tunneled session.
+
+				If a tunnel initiator supports the Tunnel-Assignment-Id AVP, then it
+				should assign a session to a tunnel in the following manner:
+
+				-  If this AVP is present and a tunnel exists between the
+				 specified endpoints with the specified Id, then the session
+				 should be assigned to that tunnel.
+
+				-  If this AVP is present and no tunnel exists between the
+				 specified endpoints with the specified Id, then a new tunnel
+				 should be established for the session and the specified Id
+				 should be associated with the new tunnel.
+
+				-  If this AVP is not present, then the session is assigned to an
+				 unnamed tunnel.  If an unnamed tunnel does not yet exist
+				 between the specified endpoints, then it is established and
+				 used for this session and for subsequent ones established
+				 without the Tunnel-Assignment-Id attribute.  A tunnel initiator
+				 MUST NOT assign a session for which a Tunnel-Assignment-Id AVP
+				 was not specified to a named tunnel (i.e., one that was
+				 initiated by a session specifying this AVP).
+
+				Note that the same Id may be used to name different tunnels if these
+				tunnels are between different endpoints.
+
+   			*/
+			struct dict_avp_data adata = { 
+					82, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Assignment-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Preference */
+		{
+			/*
+				The Tunnel-Preference AVP (AVP Code 83) is of type Unsigned32 and is
+				used to identify the relative preference assigned to each tunnel when
+				more than one set of tunneling AVPs is returned within separate
+				Grouped-AVP AVPs.  It MAY be used in an authorization request as a
+				hint to the server that a specific preference is desired, but the
+				server is not required to honor the hint in the corresponding
+				response.
+
+				For example, suppose that AVPs describing two tunnels are returned by
+				the server, one with a Tunnel-Type of PPTP and the other with a
+				Tunnel-Type of L2TP.  If the tunnel initiator supports only one of
+				the Tunnel-Types returned, it will initiate a tunnel of that type.
+				If, however, it supports both tunnel protocols, it SHOULD use the
+				value of the Tunnel-Preference AVP to decide which tunnel should be
+				started.  The tunnel with the lowest numerical value in the Value
+				field of this AVP SHOULD be given the highest preference.  The values
+				assigned to two or more instances of the Tunnel-Preference AVP within
+				a given authorization response MAY be identical.  In this case, the
+				tunnel initiator SHOULD use locally configured metrics to decide
+				which set of AVPs to use.
+   			*/
+			struct dict_avp_data adata = { 
+					83, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Preference", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Client-Auth-Id */
+		{
+			/*
+				The Tunnel-Client-Auth-Id AVP (AVP Code 90) is of type UTF8String and
+				specifies the name used by the tunnel initiator during the
+				authentication phase of tunnel establishment.  It MAY be used in an
+				authorization request as a hint to the server that a specific
+				preference is desired, but the server is not required to honor the
+				hint in the corresponding response.  This AVP MUST be present in the
+				authorization response if an authentication name other than the
+				default is desired.  This AVP SHOULD be included in the Accounting-
+				Request messages pertaining to the tunneled session.
+   			*/
+			struct dict_avp_data adata = { 
+					90, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Client-Auth-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunnel-Server-Auth-Id */
+		{
+			/*
+				The Tunnel-Server-Auth-Id AVP (AVP Code 91) is of type UTF8String and
+				specifies the name used by the tunnel terminator during the
+				authentication phase of tunnel establishment.  It MAY be used in an
+				authorization request as a hint to the server that a specific
+				preference is desired, but the server is not required to honor the
+				hint in the corresponding response.  This AVP MUST be present in the
+				authorization response if an authentication name other than the
+				default is desired.  This AVP SHOULD be included in the Accounting-
+				Request messages pertaining to the tunneled session.
+   			*/
+			struct dict_avp_data adata = { 
+					91, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Server-Auth-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunneling */
+		{
+			/*
+				The Tunneling AVP (AVP Code 401) is of type Grouped and contains the
+				following AVPs, used to describe a compulsory tunnel service:
+				[RADTunnels], [RADTunlAcct].  Its data field has the following ABNF
+				grammar:
+
+				Tunneling     ::= < AVP Header: 401 >
+                				{ Tunnel-Type }
+                				{ Tunnel-Medium-Type }
+                				{ Tunnel-Client-Endpoint }
+                				{ Tunnel-Server-Endpoint }
+                				[ Tunnel-Preference ]
+                				[ Tunnel-Client-Auth-Id ]
+                				[ Tunnel-Server-Auth-Id ]
+                				[ Tunnel-Assignment-Id ]
+                				[ Tunnel-Password ]
+                				[ Tunnel-Private-Group-Id ]
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					401, 					/* Code */
+					0, 					/* Vendor */
+					"Tunneling", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Tunnel-Type", 			RULE_REQUIRED, -1, 1 }
+							,{  "Tunnel-Medium-Type",		RULE_REQUIRED, -1, 1 }
+							,{  "Tunnel-Client-Endpoint",		RULE_REQUIRED, -1, 1 }
+							,{  "Tunnel-Server-Endpoint",		RULE_REQUIRED, -1, 1 }
+							,{  "Tunnel-Preference",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Client-Auth-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Server-Auth-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Assignment-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Password",			RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Private-Group-Id",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		
+/********************************
+ *  NAS Accounting AVPs         *
+ ********************************/		
+		/* Accounting-Input-Octets */
+		{
+			/*
+				The Accounting-Input-Octets AVP (AVP Code 363) is of type Unsigned64
+				and contains the number of octets received from the user.
+				
+				For NAS usage, this AVP indicates how many octets have been received
+				from the port in the course of this session.  It can only be present
+				in ACR messages with an Accounting-Record-Type of INTERIM_RECORD or
+				STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					363, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Octets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Output-Octets */
+		{
+			/*
+				The Accounting-Output-Octets AVP (AVP Code 364) is of type Unsigned64
+				and contains the number of octets sent to the user.
+
+				For NAS usage, this AVP indicates how many octets have been sent to
+				the port in the course of this session.  It can only be present in
+				ACR messages with an Accounting-Record-Type of INTERIM_RECORD or
+				STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					364, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Octets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Input-Packets */
+		{
+			/*
+				The Accounting-Input-Packets (AVP Code 365) is of type Unsigned64 and
+				contains the number of packets received from the user.
+
+				For NAS usage, this AVP indicates how many packets have been received
+				from the port over the course of a session being provided to a Framed
+				User.  It can only be present in ACR messages with an Accounting-
+				Record-Type of INTERIM_RECORD or STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					365, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Packets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Output-Packets */
+		{
+			/*
+				The Accounting-Output-Packets (AVP Code 366) is of type Unsigned64
+				and contains the number of IP packets sent to the user.
+
+				For NAS usage, this AVP indicates how many packets have been sent to
+				the port over the course of a session being provided to a Framed
+				User.  It can only be present in ACR messages with an Accounting-
+				Record-Type of INTERIM_RECORD or STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					366, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Packets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Session-Time */
+		{
+			/*
+				The Acct-Session-Time AVP (AVP Code 46) is of type Unsigned32 and
+				indicates the length of the current session in seconds.  It can only
+				be present in ACR messages with an Accounting-Record-Type of
+				INTERIM_RECORD or STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					46, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Session-Time", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Authentic */
+		{
+			/*
+				The Acct-Authentic AVP (AVP Code 45) is of type Enumerated and
+				specifies how the user was authenticated.  The supported values are
+				listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 45, Acct-Authentic
+				Reference: [RFC2866]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Acct-Authentic)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "RADIUS"),
+				enumval_def_u32( 2, "Local"),
+				enumval_def_u32( 3, "Remote"),
+				enumval_def_u32( 4, "Diameter")
+			};
+			struct dict_avp_data data = { 
+					45, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Authentic", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Accounting-Auth-Method */
+		{
+			/*
+				The Accounting-Auth-Method AVP (AVP Code 406) is of type Enumerated.
+				A NAS MAY include this AVP in an Accounting-Request message to
+				indicate the method used to authenticate the user.  (Note that this
+				is equivalent to the RADIUS MS-Acct-Auth-Type VSA attribute).
+
+				The following values are defined:
+
+				1  PAP
+				2  CHAP
+				3  MS-CHAP-1
+				4  MS-CHAP-2
+				5  EAP
+				7  None
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Accounting-Auth-Method)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "PAP"),
+				enumval_def_u32( 2, "CHAP"),
+				enumval_def_u32( 3, "MS-CHAP-1"),
+				enumval_def_u32( 4, "MS-CHAP-2"),
+				enumval_def_u32( 5, "EAP"),
+				enumval_def_u32( 7, "None")
+			};
+			struct dict_avp_data data = { 
+					406, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Auth-Method", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Acct-Delay-Time */
+		{
+			/*
+				The Acct-Delay-Time AVP (AVP Code 41) is of type Unsigned32 and
+				indicates the number of seconds the Diameter client has been trying
+				to send the Accounting-Request (ACR).  The accounting server may
+				subtract this value from the time when the ACR arrives at the server
+				to calculate the approximate time of the event that caused the ACR to
+				be generated.
+
+				This AVP is not used for retransmissions at the transport level (TCP
+				or SCTP).  Rather, it may be used when an ACR command cannot be
+				transmitted because there is no appropriate peer to transmit it to or
+				was rejected because it could not be delivered.  In these cases, the
+				command MAY be buffered and transmitted later, when an appropriate
+				peer-connection is available or after sufficient time has passed that
+				the destination-host may be reachable and operational.  If the ACR is
+				resent in this way, the Acct-Delay-Time AVP SHOULD be included.  The
+				value of this AVP indicates the number of seconds that elapsed
+				between the time of the first attempt at transmission and the current
+				attempt.
+			*/
+			struct dict_avp_data data = { 
+					41, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Delay-Time", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Link-Count */
+		{
+			/*
+				The Acct-Link-Count AVP (AVP Code 51) is of type Unsigned32 and
+				indicates the total number of links that have been active (current or
+				closed) in a given multilink session at the time the accounting
+				record is generated.  This AVP MAY be included in Accounting-Requests
+				for any session that may be part of a multilink service.
+
+				The Acct-Link-Count AVP may be used to make it easier for an
+				accounting server to know when it has all the records for a given
+				multilink service.  When the number of Accounting-Requests received
+				with Accounting-Record-Type = STOP_RECORD and with the same Acct-
+				Multi-Session-Id and unique Session-Ids equals the largest value of
+				Acct-Link-Count seen in those Accounting-Requests, all STOP_RECORD
+				Accounting-Requests for that multilink service have been received.
+
+				The following example, showing eight Accounting-Requests, illustrates
+				how the Acct-Link-Count AVP is used.  In the table below, only the
+				relevant AVPs are shown, although additional AVPs containing
+				accounting information will be present in the Accounting-Requests.
+
+				Acct-Multi-                   Accounting-     Acct-
+				Session-Id     Session-Id     Record-Type     Link-Count
+				--------------------------------------------------------
+				"...10"        "...10"      START_RECORD        1
+				"...10"        "...11"      START_RECORD        2
+				"...10"        "...11"      STOP_RECORD         2
+				"...10"        "...12"      START_RECORD        3
+				"...10"        "...13"      START_RECORD        4
+				"...10"        "...12"      STOP_RECORD         4
+				"...10"        "...13"      STOP_RECORD         4
+				"...10"        "...10"      STOP_RECORD         4
+
+			*/
+			struct dict_avp_data data = { 
+					51, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Link-Count", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Tunnel-Connection */
+		{
+			/*
+				The Acct-Tunnel-Connection AVP (AVP Code 68) is of type OctetString
+				and contains the identifier assigned to the tunnel session.  This
+				AVP, along with the Tunnel-Client-Endpoint and Tunnel-Server-Endpoint
+				AVPs, may be used to provide a means to uniquely identify a tunnel
+				session for auditing purposes.
+
+				The format of the identifier in this AVP depends upon the value of
+				the Tunnel-Type AVP.  For example, to identify an L2TP tunnel
+				connection fully, the L2TP Tunnel Id and Call Id might be encoded in
+				this field.  The exact encoding of this field is implementation
+				dependent.
+			*/
+			struct dict_avp_data data = { 
+					68, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Tunnel-Connection", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Tunnel-Packets-Lost */
+		{
+			/*
+				The Acct-Tunnel-Packets-Lost AVP (AVP Code 86) is of type Unsigned32
+				and contains the number of packets lost on a given link.
+			*/
+			struct dict_avp_data data = { 
+					86, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Tunnel-Packets-Lost", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***********************************
+ *  Compatibility with RADIUS AVPs *
+ ***********************************/
+		/* NAS-Identifier */
+		{
+			/*
+				The NAS-Identifier AVP (AVP Code 32) [RADIUS] is of type UTF8String
+				and contains the identity of the NAS providing service to the user.
+				This AVP SHOULD only be added by a RADIUS/Diameter Translation Agent.
+				When this AVP is present, the Origin-Host AVP identifies the NAS
+				providing service to the user.
+
+				In RADIUS it would be possible for a rogue NAS to forge the NAS-
+				Identifier attribute.  Diameter/RADIUS translation agents SHOULD
+				attempt to check a received NAS-Identifier attribute against the
+				source address of the RADIUS packet, by doing an A/AAAA RR query.  If
+				the NAS-Identifier attribute contains an FQDN, then such a query
+				would resolve to an IP address matching the source address.  However,
+				the NAS-Identifier attribute is not required to contain an FQDN, so
+				such a query could fail.  If it fails, an error should be logged, but
+				no action should be taken, other than a reverse lookup on the source
+				address and insert the resulting FQDN into the Route-Record AVP.
+
+				Diameter agents and servers SHOULD check whether a NAS-Identifier AVP
+				corresponds to an entry in the Route-Record AVP.  If no match is
+				found, then an error is logged, but no other action is taken.
+			*/
+			struct dict_avp_data data = { 
+					32, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Identifier", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* NAS-IP-Address */
+		{
+			/*
+				The NAS-IP-Address AVP (AVP Code 4) [RADIUS] is of type OctetString
+				and contains the IP Address of the NAS providing service to the user.
+				This AVP SHOULD only be added by a RADIUS/Diameter Translation Agent.
+				When this AVP is present, the Origin-Host AVP identifies the NAS
+				providing service to the user.
+
+				In RADIUS it would be possible for a rogue NAS to forge the NAS-IP-
+				Address attribute value.  Diameter/RADIUS translation agents MUST
+				check a received NAS-IP-Address or NAS-IPv6-Address attribute against
+				the source address of the RADIUS packet.  If they do not match and
+				the Diameter/RADIUS translation agent does not know whether the
+				packet was sent by a RADIUS proxy or NAS (e.g., no Proxy-State
+				attribute), then by default it is assumed that the source address
+				corresponds to a RADIUS proxy, and that the NAS Address is behind
+				that proxy, potentially with some additional RADIUS proxies in
+				between.  The Diameter/RADIUS translation agent MUST insert entries
+				in the Route-Record AVP corresponding to the apparent route.  This
+				implies doing a reverse lookup on the source address and NAS-IP-
+				Address or NAS-IPv6-Address attributes to determine the corresponding
+				FQDNs.
+
+				If the source address and the NAS-IP-Address or NAS-IPv6-Address do
+				not match, and the Diameter/RADIUS translation agent knows that it is
+				talking directly to the NAS (e.g., there are no RADIUS proxies
+				between it and the NAS), then the error should be logged, and the
+				packet MUST be discarded.
+
+				Diameter agents and servers MUST check whether the NAS-IP-Address AVP
+				corresponds to an entry in the Route-Record AVP.  This is done by
+				doing a reverse lookup (PTR RR) for the NAS-IP-Address to retrieve
+				the corresponding FQDN, and by checking for a match with the Route-
+				Record AVP.  If no match is found, then an error is logged, but no
+				other action is taken.
+			*/
+			struct dict_avp_data data = { 
+					4, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IP-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* NAS-IPv6-Address */
+		{
+			/*
+				The NAS-IPv6-Address AVP (AVP Code 95) [RADIUSIPv6] is of type
+				OctetString and contains the IPv6 Address of the NAS providing
+				service to the user.  This AVP SHOULD only be added by a
+				RADIUS/Diameter Translation Agent.  When this AVP is present, the
+				Origin-Host AVP identifies the NAS providing service to the user.
+
+				In RADIUS it would be possible for a rogue NAS to forge the NAS-
+				IPv6-Address attribute.  Diameter/RADIUS translation agents MUST
+				check a received NAS-IPv6-Address attribute against the source
+				address of the RADIUS packet.  If they do not match and the
+				Diameter/RADIUS translation agent does not know whether the packet
+				was sent by a RADIUS proxy or NAS (e.g., no Proxy-State attribute),
+				then by default it is assumed that the source address corresponds to
+				a RADIUS proxy, and that the NAS-IPv6-Address is behind that proxy,
+				potentially with some additional RADIUS proxies in between.  The
+				Diameter/RADIUS translation agent MUST insert entries in the Route-
+				Record AVP corresponding to the apparent route.  This implies doing a
+				reverse lookup on the source address and NAS-IPv6-Address attributes
+				to determine the corresponding FQDNs.
+
+				If the source address and the NAS-IPv6-Address do not match, and the
+				Diameter/RADIUS translation agent knows that it is talking directly
+				to the NAS (e.g., there are no RADIUS proxies between it and the
+				NAS), then the error should be logged, and the packet MUST be
+				discarded.
+
+				Diameter agents and servers MUST check whether the NAS-IPv6-Address
+				AVP corresponds to an entry in the Route-Record AVP.  This is done by
+				doing a reverse lookup (PTR RR) for the NAS-IPv6-Address to retrieve
+				the corresponding FQDN, and by checking for a match with the Record-
+				Route AVP.  If no match is found, then an error is logged, but no
+				other action is taken.
+			*/
+			struct dict_avp_data data = { 
+					95, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IPv6-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* State */
+		{
+			/*
+				The State AVP (AVP Code 24) [RADIUS] is of type OctetString and has
+				two uses in the Diameter NAS application.
+
+				The State AVP MAY be sent by a Diameter Server to a NAS in an AA-
+				Response command that contains a Result-Code of
+				DIAMETER_MULTI_ROUND_AUTH.  If so, the NAS MUST return it unmodified
+				in the subsequent AA-Request command.
+
+				The State AVP MAY also be sent by a Diameter Server to a NAS in an
+				AA-Response command that also includes a Termination-Action AVP with
+				the value of AA-REQUEST.  If the NAS performs the Termination-Action
+				by sending a new AA-Request command upon termination of the current
+				service, it MUST return the State AVP unmodified in the new request
+				command.
+
+				In either usage, the NAS MUST NOT interpret the AVP locally.  Usage
+				of the State AVP is implementation dependent.
+			*/
+			struct dict_avp_data data = { 
+					24, 					/* Code */
+					0, 					/* Vendor */
+					"State", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Termination-Cause mapping */
+		{
+			
+			struct dict_object 	*type;
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32(11, "[RADIUS] User Request"),
+				enumval_def_u32(12, "[RADIUS] Lost Carrier"),
+				enumval_def_u32(13, "[RADIUS] Lost Service"),
+				enumval_def_u32(14, "[RADIUS] Idle Timeout"),
+				enumval_def_u32(15, "[RADIUS] Session Timeout"),
+				enumval_def_u32(16, "[RADIUS] Admin Reset"),
+				enumval_def_u32(17, "[RADIUS] Admin Reboot"),
+				enumval_def_u32(18, "[RADIUS] Port Error"),
+				enumval_def_u32(19, "[RADIUS] NAS Error"),
+				enumval_def_u32(20, "[RADIUS] NAS Request"),
+				enumval_def_u32(21, "[RADIUS] NAS Reboot"),
+				enumval_def_u32(22, "[RADIUS] Port Unneeded"),
+				enumval_def_u32(23, "[RADIUS] Port Preempted"),
+				enumval_def_u32(24, "[RADIUS] Port Suspended"),
+				enumval_def_u32(25, "[RADIUS] Service Unavailable"),
+				enumval_def_u32(26, "[RADIUS] Callback"),
+				enumval_def_u32(27, "[RADIUS] User Error"),
+				enumval_def_u32(28, "[RADIUS] Host Request"),
+				enumval_def_u32(29, "[RADIUS] Supplicant Restart"),
+				enumval_def_u32(30, "[RADIUS] Reauthentication Failure"),
+				enumval_def_u32(31, "[RADIUS] Port Reinit"),
+				enumval_def_u32(32, "[RADIUS] Port Disabled")
+				};
+			int i;
+
+			CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Enumerated(Termination-Cause)", &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			
+		}
+		
+		/* Origin-AAA-Protocol */
+		{
+			/*
+				The Origin-AAA-Protocol AVP (AVP Code 408) is of the type Enumerated
+				and should be inserted in a Diameter message translated by a gateway
+				system from another AAA protocol, such as RADIUS.  It identifies the
+				source protocol of the message to the Diameter system receiving the
+				message.
+
+				The supported values are:
+
+				 1       RADIUS
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Origin-AAA-Protocol)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "RADIUS")
+			};
+			struct dict_avp_data data = { 
+					408, 					/* Code */
+					0, 					/* Vendor */
+					"Origin-AAA-Protocol", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+	}
+
+/********************/		
+/* Commands section */
+/********************/		
+	{
+		/* To avoid defining global variables for all the AVP that we use here, we do search the dictionary in each sub-block.
+		 * This is far from optimal, but the code is clearer like this, and the time it requires at execution is not noticeable.
+		 */
+		
+		/* AA-Request (AAR) Command */
+		{
+			/*
+				The AA-Request (AAR), which is indicated by setting the Command-Code
+				field to 265 and the 'R' bit in the Command Flags field, is used to
+				request authentication and/or authorization for a given NAS user.
+				The type of request is identified through the Auth-Request-Type AVP
+				[BASE].  The recommended value for most RADIUS interoperabily
+				situations is AUTHORIZE_AUTHENTICATE.
+
+				If Authentication is requested, the User-Name attribute SHOULD be
+				present, as well as any additional authentication AVPs that would
+				carry the password information.  A request for authorization SHOULD
+				only include the information from which the authorization will be
+				performed, such as the User-Name, Called-Station-Id, or Calling-
+				Station-Id AVPs.  All requests SHOULD contain AVPs uniquely
+				identifying the source of the call, such as Origin-Host and NAS-Port.
+				Certain networks MAY use different AVPs for authorization purposes.
+				A request for authorization will include some AVPs defined in section
+				6.
+
+				It is possible for a single session to be authorized first and then
+				for an authentication request to follow.
+
+				This AA-Request message MAY be the result of a multi-round
+				authentication exchange, which occurs when the AA-Answer message is
+				received with the Result-Code AVP set to DIAMETER_MULTI_ROUND_AUTH.
+				A subsequent AAR message SHOULD be sent, with the User-Password AVP
+				that includes the user's response to the prompt, and MUST include any
+				State AVPs that were present in the AAA message.
+
+				Message Format
+				<AA-Request> ::= < Diameter Header: 265, REQ, PXY >
+        				       < Session-Id >
+        				       { Auth-Application-Id }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       { Destination-Realm }
+        				       { Auth-Request-Type }
+        				       [ Destination-Host ]
+        				       [ NAS-Identifier ]
+        				       [ NAS-IP-Address ]
+        				       [ NAS-IPv6-Address ]
+        				       [ NAS-Port ]
+        				       [ NAS-Port-Id ]
+        				       [ NAS-Port-Type ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				       [ Port-Limit ]
+        				       [ User-Name ]
+        				       [ User-Password ]
+        				       [ Service-Type ]
+        				       [ State ]
+        				       [ Authorization-Lifetime ]
+        				       [ Auth-Grace-Period ]
+        				       [ Auth-Session-State ]
+        				       [ Callback-Number ]
+        				       [ Called-Station-Id ]
+        				       [ Calling-Station-Id ]
+        				       [ Originating-Line-Info ]
+        				       [ Connect-Info ]
+        				       [ CHAP-Auth ]
+        				       [ CHAP-Challenge ]
+        				     * [ Framed-Compression ]
+        				       [ Framed-Interface-Id ]
+        				       [ Framed-IP-Address ]
+        				     * [ Framed-IPv6-Prefix ]
+        				       [ Framed-IP-Netmask ]
+        				       [ Framed-MTU ]
+        				       [ Framed-Protocol ]
+        				       [ ARAP-Password ]
+        				       [ ARAP-Security ]
+        				     * [ ARAP-Security-Data ]
+        				     * [ Login-IP-Host ]
+        				     * [ Login-IPv6-Host ]
+        				       [ Login-LAT-Group ]
+        				       [ Login-LAT-Node ]
+        				       [ Login-LAT-Port ]
+        				       [ Login-LAT-Service ]
+        				     * [ Tunneling ]
+        				     * [ Proxy-Info ]
+        				     * [ Route-Record ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					265, 					/* Code */
+					"AA-Request", 				/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Password",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Connect-Info",			RULE_OPTIONAL,   -1, 1 }
+							,{  "CHAP-Auth",			RULE_OPTIONAL,   -1, 1 }
+							,{  "CHAP-Challenge",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Password",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security-Data",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IP-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IPv6-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-LAT-Group",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Node",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Service",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , nasreq, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* AA-Answer (AAA) Command */
+		{
+			/*
+				The AA-Answer (AAA) message is indicated by setting the Command-Code
+				field to 265 and clearing the 'R' bit in the Command Flags field.  It
+				is sent in response to the AA-Request (AAR) message.  If
+				authorization was requested, a successful response will include the
+				authorization AVPs appropriate for the service being provided, as
+				defined in section 6.
+
+				For authentication exchanges requiring more than a single round trip,
+				the server MUST set the Result-Code AVP to DIAMETER_MULTI_ROUND_AUTH.
+				An AAA message with this result code MAY include one Reply-Message or
+				more and MAY include zero or one State AVPs.
+
+				If the Reply-Message AVP was present, the network access server
+				SHOULD send the text to the user's client to display to the user,
+				instructing the client to prompt the user for a response.  For
+				example, this capability can be achieved in PPP via PAP.  If the
+				access client is unable to prompt the user for a new response, it
+				MUST treat the AA-Answer (AAA) with the Reply-Message AVP as an error
+				and deny access.
+
+				Message Format
+
+				<AA-Answer> ::= < Diameter Header: 265, PXY >
+        				      < Session-Id >
+        				      { Auth-Application-Id }
+        				      { Auth-Request-Type }
+        				      { Result-Code }
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      [ User-Name ]
+        				      [ Service-Type ]
+        				    * [ Class ]
+        				    * [ Configuration-Token ]
+        				      [ Acct-Interim-Interval ]
+        				      [ Error-Message ]
+        				      [ Error-Reporting-Host ]
+        				    * [ Failed-AVP ]
+        				      [ Idle-Timeout ]
+        				      [ Authorization-Lifetime ]
+        				      [ Auth-Grace-Period ]
+        				      [ Auth-Session-State ]
+        				      [ Re-Auth-Request-Type ]
+        				      [ Multi-Round-Time-Out ]
+        				      [ Session-Timeout ]
+        				      [ State ]
+        				    * [ Reply-Message ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				    * [ Filter-Id ]
+        				      [ Password-Retry ]
+        				      [ Port-Limit ]
+        				      [ Prompt ]
+        				      [ ARAP-Challenge-Response ]
+        				      [ ARAP-Features ]
+        				      [ ARAP-Security ]
+        				    * [ ARAP-Security-Data ]
+        				      [ ARAP-Zone-Access ]
+        				      [ Callback-Id ]
+        				      [ Callback-Number ]
+        				      [ Framed-Appletalk-Link ]
+        				    * [ Framed-Appletalk-Network ]
+        				      [ Framed-Appletalk-Zone ]
+        				    * [ Framed-Compression ]
+        				      [ Framed-Interface-Id ]
+        				      [ Framed-IP-Address ]
+        				    * [ Framed-IPv6-Prefix ]
+        				      [ Framed-IPv6-Pool ]
+        				    * [ Framed-IPv6-Route ]
+        				      [ Framed-IP-Netmask ]
+        				    * [ Framed-Route ]
+        				      [ Framed-Pool ]
+        				      [ Framed-IPX-Network ]
+        				      [ Framed-MTU ]
+        				      [ Framed-Protocol ]
+        				      [ Framed-Routing ]
+        				    * [ Login-IP-Host ]
+        				    * [ Login-IPv6-Host ]
+        				      [ Login-LAT-Group ]
+        				      [ Login-LAT-Node ]
+        				      [ Login-LAT-Port ]
+        				      [ Login-LAT-Service ]
+        				      [ Login-Service ]
+        				      [ Login-TCP-Port ]
+        				    * [ NAS-Filter-Rule ]
+        				    * [ QoS-Filter-Rule ]
+        				    * [ Tunneling ]
+        				    * [ Redirect-Host ]
+        				      [ Redirect-Host-Usage ]
+        				      [ Redirect-Max-Cache-Time ]
+        				    * [ Proxy-Info ]
+        				    * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					265, 					/* Code */
+					"AA-Answer", 				/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Configuration-Token",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Acct-Interim-Interval",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Multi-Round-Time-Out",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Session-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Filter-Id",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Password-Retry",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Prompt",				RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Challenge-Response",		RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Features",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security-Data",		RULE_OPTIONAL,   -1,-1 }
+							,{  "ARAP-Zone-Access",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Link",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Network",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-AppleTalk-Zone",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IPv6-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Route",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Route",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPX-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Routing",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-IP-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IPv6-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-LAT-Group",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Node",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Service",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-Service",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-TCP-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "QoS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , nasreq, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Re-Auth-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+			<RA-Request>  ::= < Diameter Header: 258, REQ, PXY >
+        			       < Session-Id >
+        			       { Origin-Host }
+        			       { Origin-Realm }
+        			       { Destination-Realm }
+        			       { Destination-Host }
+        			       { Auth-Application-Id }
+        			       { Re-Auth-Request-Type }
+        			       [ User-Name ]
+        			       [ Origin-AAA-Protocol ]
+        			       [ Origin-State-Id ]
+        			       [ NAS-Identifier ]
+        			       [ NAS-IP-Address ]
+        			       [ NAS-IPv6-Address ]
+        			       [ NAS-Port ]
+        			       [ NAS-Port-Id ]
+        			       [ NAS-Port-Type ]
+        			       [ Service-Type ]
+        			       [ Framed-IP-Address ]
+        			       [ Framed-IPv6-Prefix ]
+        			       [ Framed-Interface-Id ]
+        			       [ Called-Station-Id ]
+        			       [ Calling-Station-Id ]
+        			       [ Originating-Line-Info ]
+        			       [ Acct-Session-Id ]
+        			       [ Acct-Multi-Session-Id ]
+        			       [ State ]
+        			     * [ Class ]
+        			       [ Reply-Message ]
+        			     * [ Proxy-Info ]
+        			     * [ Route-Record ]
+        			     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Multi-Session-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Re-Auth-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+
+				<RA-Answer>  ::= < Diameter Header: 258, PXY >
+        				       < Session-Id >
+        				       { Result-Code }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       [ User-Name ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				       [ Error-Message ]
+        				       [ Error-Reporting-Host ]
+        				     * [ Failed-AVP ]
+        				     * [ Redirected-Host ]
+        				       [ Redirected-Host-Usage ]
+        				       [ Redirected-Host-Cache-Time ]
+        				       [ Service-Type ]
+        				     * [ Configuration-Token ]
+        				       [ Idle-Timeout ]
+        				       [ Authorization-Lifetime ]
+        				       [ Auth-Grace-Period ]
+        				       [ Re-Auth-Request-Type ]
+        				       [ State ]
+        				     * [ Class ]
+        				     * [ Reply-Message ]
+        				       [ Prompt ]
+        				     * [ Proxy-Info ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Configuration-Token",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Prompt",				RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Session-Termination-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+
+				<ST-Request> ::= < Diameter Header: 275, REQ, PXY >
+        				      < Session-Id >
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      { Destination-Realm }
+        				      { Auth-Application-Id }
+        				      { Termination-Cause }
+        				      [ User-Name ]
+        				      [ Destination-Host ]
+        				    * [ Class ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				    * [ Proxy-Info ]
+        				    * [ Route-Record ]
+        				    * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Session-Termination-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+				<ST-Answer>  ::= < Diameter Header: 275, PXY >
+        				       < Session-Id >
+        				       { Result-Code }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       [ User-Name ]
+        				     * [ Class ]
+        				       [ Error-Message ]
+        				       [ Error-Reporting-Host ]
+        				     * [ Failed-AVP ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				     * [ Redirect-Host ]
+        				       [ Redirect-Host-Usase ]
+        				       [ Redirect-Max-Cache-Time ]
+        				     * [ Proxy-Info ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Abort-Session-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+			<AS-Request>  ::= < Diameter Header: 274, REQ, PXY >
+        			       < Session-Id >
+        			       { Origin-Host }
+        			       { Origin-Realm }
+        			       { Destination-Realm }
+        			       { Destination-Host }
+        			       { Auth-Application-Id }
+        			       [ User-Name ]
+        			       [ Origin-AAA-Protocol ]
+        			       [ Origin-State-Id ]
+        			       [ NAS-Identifier ]
+        			       [ NAS-IP-Address ]
+        			       [ NAS-IPv6-Address ]
+        			       [ NAS-Port ]
+        			       [ NAS-Port-Id ]
+        			       [ NAS-Port-Type ]
+        			       [ Service-Type ]
+        			       [ Framed-IP-Address ]
+        			       [ Framed-IPv6-Prefix ]
+        			       [ Framed-Interface-Id ]
+        			       [ Called-Station-Id ]
+        			       [ Calling-Station-Id ]
+        			       [ Originating-Line-Info ]
+        			       [ Acct-Session-Id ]
+        			       [ Acct-Multi-Session-Id ]
+        			       [ State ]
+        			     * [ Class ]
+        			     * [ Reply-Message ]
+        			     * [ Proxy-Info ]
+        			     * [ Route-Record ]
+        			     * [ AVP ]
+				     
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Multi-Session-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Abort-Session-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				<AS-Answer>  ::= < Diameter Header: 274, PXY >
+        				       < Session-Id >
+        				       { Result-Code }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       [ User-Name ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				       [ State]
+        				       [ Error-Message ]
+        				       [ Error-Reporting-Host ]
+        				     * [ Failed-AVP ]
+        				     * [ Redirected-Host ]
+        				       [ Redirected-Host-Usage ]
+        				       [ Redirected-Max-Cache-Time ]
+        				     * [ Proxy-Info ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State", 				RULE_REQUIRED,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				<AC-Request> ::= < Diameter Header: 271, REQ, PXY >
+        				      < Session-Id >
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      { Destination-Realm }
+        				      { Accounting-Record-Type }
+        				      { Accounting-Record-Number }
+        				      [ Acct-Application-Id ]
+        				      [ Vendor-Specific-Application-Id ]
+        				      [ User-Name ]
+        				      [ Accounting-Sub-Session-Id ]
+        				      [ Acct-Session-Id ]
+        				      [ Acct-Multi-Session-Id ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				      [ Destination-Host ]
+        				      [ Event-Timestamp ]
+        				      [ Acct-Delay-Time ]
+        				      [ NAS-Identifier ]
+        				      [ NAS-IP-Address ]
+        				      [ NAS-IPv6-Address ]
+        				      [ NAS-Port ]
+        				      [ NAS-Port-Id ]
+        				      [ NAS-Port-Type ]
+        				    * [ Class ]
+        				      [ Service-Type ]
+        				      [ Termination-Cause ]
+        				      [ Accounting-Input-Octets ]
+        				      [ Accounting-Input-Packets ]
+        				      [ Accounting-Output-Octets ]
+        				      [ Accounting-Output-Packets ]
+        				      [ Acct-Authentic ]
+        				      [ Accounting-Auth-Method ]
+        				      [ Acct-Link-Count ]
+        				      [ Acct-Session-Time ]
+        				      [ Acct-Tunnel-Connection ]
+        				      [ Acct-Tunnel-Packets-Lost ]
+        				      [ Callback-Id ]
+        				      [ Callback-Number ]
+        				      [ Called-Station-Id ]
+        				      [ Calling-Station-Id ]
+        				    * [ Connection-Info ]
+        				      [ Originating-Line-Info ]
+        				      [ Authorization-Lifetime ]
+        				      [ Session-Timeout ]
+        				      [ Idle-Timeout ]
+        				      [ Port-Limit ]
+        				      [ Accounting-Realtime-Required ]
+        				      [ Acct-Interim-Interval ]
+        				    * [ Filter-Id ]
+        				    * [ NAS-Filter-Rule ]
+        				    * [ Qos-Filter-Rule ]
+        				      [ Framed-AppleTalk-Link ]
+        				      [ Framed-AppleTalk-Network ]
+        				      [ Framed-AppleTalk-Zone ]
+        				      [ Framed-Compression ]
+        				      [ Framed-Interface-Id ]
+        				      [ Framed-IP-Address ]
+        				      [ Framed-IP-Netmask ]
+        				    * [ Framed-IPv6-Prefix ]
+        				      [ Framed-IPv6-Pool ]
+        				    * [ Framed-IPv6-Route ]
+        				      [ Framed-IPX-Network ]
+        				      [ Framed-MTU ]
+        				      [ Framed-Pool ]
+        				      [ Framed-Protocol ]
+        				    * [ Framed-Route ]
+        				      [ Framed-Routing ]
+        				    * [ Login-IP-Host ]
+        				    * [ Login-IPv6-Host ]
+        				      [ Login-LAT-Group ]
+        				      [ Login-LAT-Node ]
+        				      [ Login-LAT-Port ]
+        				      [ Login-LAT-Service ]
+        				      [ Login-Service ]
+        				      [ Login-TCP-Port ]
+        				    * [ Tunneling ]
+        				    * [ Proxy-Info ]
+        				    * [ Route-Record ]
+        				    * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Delay-Time",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Termination-Cause",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Input-Octets",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Input-Packets",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Output-Octets",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Output-Packets",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Authentic",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Auth-Method",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Link-Count",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Tunnel-Connection",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Tunnel-Packets-Lost",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Connect-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Session-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Filter-Id",			RULE_OPTIONAL,   -1,-1 }
+							,{  "NAS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "QoS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-AppleTalk-Link",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Zone",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IPv6-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Route",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Route",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPX-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Routing",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-IP-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IPv6-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-LAT-Group",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Node",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Service",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-Service",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-TCP-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				<AC-Answer> ::= < Diameter Header: 271, PXY >
+        				      < Session-Id >
+        				      { Result-Code }
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      { Accounting-Record-Type }
+        				      { Accounting-Record-Number }
+        				      [ Acct-Application-Id ]
+        				      [ Vendor-Specific-Application-Id ]
+        				      [ User-Name ]
+        				      [ Accounting-Sub-Session-Id ]
+        				      [ Acct-Session-Id ]
+        				      [ Acct-Multi-Session-Id ]
+        				      [ Event-Timestamp ]
+        				      [ Error-Message ]
+        				      [ Error-Reporting-Host ]
+        				    * [ Failed-AVP ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				      [ NAS-Identifier ]
+        				      [ NAS-IP-Address ]
+        				      [ NAS-IPv6-Address ]
+        				      [ NAS-Port ]
+        				      [ NAS-Port-Id ]
+        				      [ NAS-Port-Type ]
+        				      [ Service-Type ]
+        				      [ Termination-Cause ]
+        				      [ Accounting-Realtime-Required ]
+        				      [ Acct-Interim-Interval ]
+        				    * [ Class ]
+        				    * [ Proxy-Info ]
+        				    * [ Route-Record ]
+        				    * [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier", 			RULE_REQUIRED,   -1, 1 }
+							,{  "NAS-IP-Address", 			RULE_REQUIRED,   -1, 1 }
+							,{  "NAS-IPv6-Address", 		RULE_REQUIRED,   -1, 1 }
+							,{  "NAS-Port", 			RULE_REQUIRED,   -1, 1 }
+							,{  "NAS-Port-Id", 			RULE_REQUIRED,   -1, 1 }
+							,{  "NAS-Port-Type", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Service-Type", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Termination-Cause", 		RULE_REQUIRED,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+	}
+	
+	TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for NASREQ' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_nasreq", dnr_entry);
--- a/freeDiameter/CMakeLists.txt	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -10,8 +10,11 @@
 SET(FD_COMMON_SRC
 	fD.h
 	config.c
+	dispatch.c
 	extensions.c
 	dict_base_proto.c
+	messages.c
+	queues.c
 	)
 
 SET(FD_COMMON_GEN_SRC
--- a/freeDiameter/config.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/config.c	Fri Sep 25 16:12:08 2009 +0900
@@ -42,25 +42,25 @@
 {
 	TRACE_ENTRY();
 	
-	fd_g_config->eyec = EYEC_CONFIG;
-	fd_g_config->conf_file = DEFAULT_CONF_FILE;
+	fd_g_config->cnf_eyec = EYEC_CONFIG;
+	fd_g_config->cnf_file = DEFAULT_CONF_FILE;
+	
+	fd_g_config->cnf_timer_tc = 30;
+	fd_g_config->cnf_timer_tw = 30;
 	
-	fd_g_config->loc_port     = 3868;
-	fd_g_config->loc_port_tls = 3869;
-	fd_g_config->loc_sctp_str = 30;
-	fd_list_init(&fd_g_config->loc_endpoints, NULL);
-	
+	fd_g_config->cnf_port     = 3868;
+	fd_g_config->cnf_port_tls = 3869;
+	fd_g_config->cnf_sctp_str = 30;
+	fd_list_init(&fd_g_config->cnf_endpoints, NULL);
+	fd_list_init(&fd_g_config->cnf_apps, NULL);
 	#ifdef DISABLE_SCTP
-	fd_g_config->flags.no_sctp = 1;
+	fd_g_config->cnf_flags.no_sctp = 1;
 	#endif /* DISABLE_SCTP */
 	
-	fd_g_config->timer_tc = 30;
-	fd_g_config->timer_tw = 30;
+	fd_g_config->cnf_orstateid = (uint32_t) time(NULL);
 	
-	fd_g_config->or_state_id = (uint32_t) time(NULL);
-	
-	CHECK_FCT( fd_dict_init(&fd_g_config->g_dict) );
-	CHECK_FCT( fd_fifo_new(&fd_g_config->g_fifo_main) );
+	CHECK_FCT( fd_dict_init(&fd_g_config->cnf_dict) );
+	CHECK_FCT( fd_fifo_new(&fd_g_config->cnf_main_ev) );
 	
 	return 0;
 }
@@ -72,39 +72,56 @@
 	
 	fd_log_debug("-- Configuration :\n");
 	fd_log_debug("  Debug trace level ...... : %+d\n", fd_g_debug_lvl);
-	fd_log_debug("  Configuration file ..... : %s\n", fd_g_config->conf_file);
-	fd_log_debug("  Diameter Identity ...... : %s (l:%Zi)\n", fd_g_config->diam_id, fd_g_config->diam_id_len);
-	fd_log_debug("  Diameter Realm ......... : %s (l:%Zi)\n", fd_g_config->diam_realm, fd_g_config->diam_realm_len);
-	fd_log_debug("  Local port ............. : %hu\n", fd_g_config->loc_port);
-	fd_log_debug("  Local secure port ...... : %hu\n", fd_g_config->loc_port_tls);
-	fd_log_debug("  Number of SCTP streams . : %hu\n", fd_g_config->loc_sctp_str);
-	if (FD_IS_LIST_EMPTY(&fd_g_config->loc_endpoints)) {
+	fd_log_debug("  Configuration file ..... : %s\n", fd_g_config->cnf_file);
+	fd_log_debug("  Diameter Identity ...... : %s (l:%Zi)\n", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len);
+	fd_log_debug("  Diameter Realm ......... : %s (l:%Zi)\n", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len);
+	fd_log_debug("  Tc Timer ............... : %u\n", fd_g_config->cnf_timer_tc);
+	fd_log_debug("  Tw Timer ............... : %u\n", fd_g_config->cnf_timer_tw);
+	fd_log_debug("  Local port ............. : %hu\n", fd_g_config->cnf_port);
+	fd_log_debug("  Local secure port ...... : %hu\n", fd_g_config->cnf_port_tls);
+	fd_log_debug("  Number of SCTP streams . : %hu\n", fd_g_config->cnf_sctp_str);
+	if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
 		fd_log_debug("  Local endpoints ........ : Default (use all available)\n");
 	} else {
-		struct fd_list * li = fd_g_config->loc_endpoints.next;
+		struct fd_list * li = fd_g_config->cnf_endpoints.next;
 		fd_log_debug("  Local endpoints ........ : ");
-		while (li != &fd_g_config->loc_endpoints) {
+		while (li != &fd_g_config->cnf_endpoints) {
 			struct fd_endpoint * ep = (struct fd_endpoint *)li;
-			if (li != fd_g_config->loc_endpoints.next) fd_log_debug("                             ");
+			if (li != fd_g_config->cnf_endpoints.next) fd_log_debug("                             ");
 			sSA_DUMP_NODE( &ep->ss, NI_NUMERICHOST );
 			fd_log_debug("\n");
 			li = li->next;
 		}
 	}
-	fd_log_debug("  Flags : - IP ........... : %s\n", fd_g_config->flags.no_ip4 ? "DISABLED" : "Enabled");
-	fd_log_debug("          - IPv6 ......... : %s\n", fd_g_config->flags.no_ip6 ? "DISABLED" : "Enabled");
-	fd_log_debug("          - Relay app .... : %s\n", fd_g_config->flags.no_fwd ? "DISABLED" : "Enabled");
-	fd_log_debug("          - TCP .......... : %s\n", fd_g_config->flags.no_tcp ? "DISABLED" : "Enabled");
+	if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) {
+		fd_log_debug("  Local applications ..... : (none)\n");
+	} else {
+		struct fd_list * li = fd_g_config->cnf_apps.next;
+		fd_log_debug("  Local applications ..... : ");
+		while (li != &fd_g_config->cnf_apps) {
+			struct fd_app * app = (struct fd_app *)li;
+			if (li != fd_g_config->cnf_apps.next) fd_log_debug("                             ");
+			fd_log_debug("App: %u\t%s%s%s\tVnd: %u\n", 
+					app->appid,
+					app->flags.auth ? "Au" : "--",
+					app->flags.acct ? "Ac" : "--",
+					app->flags.common ? "C" : "-",
+					app->vndid);
+			li = li->next;
+		}
+	}
+	fd_log_debug("  Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled");
+	fd_log_debug("          - IPv6 ......... : %s\n", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled");
+	fd_log_debug("          - Relay app .... : %s\n", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled");
+	fd_log_debug("          - TCP .......... : %s\n", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled");
 	#ifdef DISABLE_SCTP
 	fd_log_debug("          - SCTP ......... : DISABLED (at compilation)\n");
 	#else /* DISABLE_SCTP */
-	fd_log_debug("          - SCTP ......... : %s\n", fd_g_config->flags.no_sctp ? "DISABLED" : "Enabled");
+	fd_log_debug("          - SCTP ......... : %s\n", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled");
 	#endif /* DISABLE_SCTP */
-	fd_log_debug("          - Pref. proto .. : %s\n", fd_g_config->flags.pr_tcp ? "TCP" : "SCTP");
-	fd_log_debug("          - TLS method ... : %s\n", fd_g_config->flags.tls_alg ? "INBAND" : "Separate port");
-	fd_log_debug("  Tc Timer ............... : %u\n", fd_g_config->timer_tc);
-	fd_log_debug("  Tw Timer ............... : %u\n", fd_g_config->timer_tw);
-	fd_log_debug("  Origin-State-Id ........ : %u\n", fd_g_config->or_state_id);
+	fd_log_debug("          - Pref. proto .. : %s\n", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP");
+	fd_log_debug("          - TLS method ... : %s\n", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port");
+	fd_log_debug("  Origin-State-Id ........ : %u\n", fd_g_config->cnf_orstateid);
 }
 
 /* Parse the configuration file (using the yacc parser) */
@@ -112,12 +129,12 @@
 {
 	extern FILE * fddin;
 	
-	TRACE_DEBUG (FULL, "Parsing configuration file: %s", fd_g_config->conf_file);
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s", fd_g_config->cnf_file);
 	
-	fddin = fopen(fd_g_config->conf_file, "r");
+	fddin = fopen(fd_g_config->cnf_file, "r");
 	if (fddin == NULL) {
 		int ret = errno;
-		fprintf(stderr, "Unable to open configuration file %s for reading: %s\n", fd_g_config->conf_file, strerror(ret));
+		fprintf(stderr, "Unable to open configuration file %s for reading: %s\n", fd_g_config->cnf_file, strerror(ret));
 		return ret;
 	}
 	
@@ -128,7 +145,7 @@
 	fclose(fddin);
 	
 	/* Resolve hostname if not provided */
-	if (fd_g_config->diam_id == NULL) {
+	if (fd_g_config->cnf_diamid == NULL) {
 #ifndef HOST_NAME_MAX
 #define HOST_NAME_MAX 1024
 #endif /* HOST_NAME_MAX */
@@ -151,36 +168,36 @@
 					buf, gai_strerror(ret));
 			return EINVAL;
 		}
-		CHECK_MALLOC( fd_g_config->diam_id = strdup(info->ai_canonname) );
+		CHECK_MALLOC( fd_g_config->cnf_diamid = strdup(info->ai_canonname) );
 		freeaddrinfo(info);
 	}
 	
 	/* cache the length of the diameter id for the session module */
-	fd_g_config->diam_id_len = strlen(fd_g_config->diam_id);
+	fd_g_config->cnf_diamid_len = strlen(fd_g_config->cnf_diamid);
 	
 	/* Handle the realm part */
-	if (fd_g_config->diam_realm == NULL) {
+	if (fd_g_config->cnf_diamrlm == NULL) {
 		char * start = NULL;
 		
 		/* Check the diameter identity is a fqdn */
-		start = strchr(fd_g_config->diam_id, '.');
+		start = strchr(fd_g_config->cnf_diamid, '.');
 		if ((start == NULL) || (start[1] == '\0')) {
 			fprintf(stderr, "Unable to extract realm from the LocalIdentity '%s'.\n"
 					"Please fix your LocalIdentity setting or provide LocalRealm.\n",
-					fd_g_config->diam_id);
+					fd_g_config->cnf_diamid);
 			return EINVAL;
 		}		
 		
-		CHECK_MALLOC( fd_g_config->diam_realm = strdup( start + 1 )  ); 
+		CHECK_MALLOC( fd_g_config->cnf_diamrlm = strdup( start + 1 )  ); 
 	}
-	fd_g_config->diam_realm_len = strlen(fd_g_config->diam_realm);
+	fd_g_config->cnf_diamrlm_len = strlen(fd_g_config->cnf_diamrlm);
 	
 	/* Validate some flags */
-	if (fd_g_config->flags.no_ip4 && fd_g_config->flags.no_ip6) {
+	if (fd_g_config->cnf_flags.no_ip4 && fd_g_config->cnf_flags.no_ip6) {
 		fprintf(stderr, "IP and IPv6 cannot be disabled at the same time.\n");
 		return EINVAL;
 	}
-	if (fd_g_config->flags.no_tcp && fd_g_config->flags.no_sctp) {
+	if (fd_g_config->cnf_flags.no_tcp && fd_g_config->cnf_flags.no_sctp) {
 		fprintf(stderr, "TCP and SCTP cannot be disabled at the same time.\n");
 		return EINVAL;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/dispatch.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,100 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+#include "fD.h"
+
+int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct )
+{
+	vendor_id_t	 vid = 0;
+	application_id_t aid = 0;
+	struct fd_list * li;
+	int skip = 0;
+	
+	TRACE_ENTRY("%p %p %d %d", app, vendor, auth, acct);
+	CHECK_PARAMS( app && (auth || acct) );
+	
+	{
+		enum dict_object_type type = 0;
+		struct dict_application_data data;
+		CHECK_FCT( fd_dict_gettype(app, &type) );
+		CHECK_PARAMS( type == DICT_APPLICATION );
+		CHECK_FCT( fd_dict_getval(app, &data) );
+		aid = data.application_id;
+	}
+	
+	
+	/* Now insert in the list ordered by appid. Avoid duplicates */
+	for (li = &fd_g_config->cnf_apps; li->next != &fd_g_config->cnf_apps; li = li->next) {
+		struct fd_app * na = (struct fd_app *)(li->next);
+		if (na->appid < aid)
+			continue;
+		
+		if (na->appid > aid)
+			break;
+		
+		/* Otherwise, we merge with existing entry -- ignore vendor id in this case */
+		skip = 1;
+		
+		if (auth)
+			na->flags.auth = 1;
+		if (acct)
+			na->flags.acct = 1;
+		break;
+	}
+	
+	if (!skip) {			
+		struct fd_app  * new = NULL;
+
+		if (vendor) {
+			enum dict_object_type type = 0;
+			struct dict_vendor_data data;
+			CHECK_FCT( fd_dict_gettype(vendor, &type) );
+			CHECK_PARAMS( type == DICT_VENDOR );
+			CHECK_FCT( fd_dict_getval(vendor, &data) );
+			vid = data.vendor_id;
+		}
+	
+		CHECK_MALLOC( new = malloc(sizeof(struct fd_app)) );
+		memset(new, 0, sizeof(struct fd_app));
+		fd_list_init(&new->chain, NULL);
+		new->flags.auth = (auth ? 1 : 0);
+		new->flags.acct = (acct ? 1 : 0);
+		new->vndid = vid;
+		new->appid = aid;
+		fd_list_insert_after(li, &new->chain);
+	}
+	
+	return 0;
+}
--- a/freeDiameter/extensions.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/extensions.c	Fri Sep 25 16:12:08 2009 +0900
@@ -80,6 +80,20 @@
 	return 0;
 }
 
+/* Dump the list */
+void fd_ext_dump(void)
+{
+	struct fd_list * li;
+	
+	fd_log_debug("Dumping extensions list :\n");
+	
+	for (li = ext_list.next; li != &ext_list; li = li->next)
+	{
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+		fd_log_debug(" - '%s'[%s] is %sloaded\n", ext->filename, ext->conffile?:"no conf", ext->handler ? "" : "not ");
+	}
+}
+
 /* Load all extensions in the list */
 int fd_ext_load()
 {
--- a/freeDiameter/fD.h	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/fD.h	Fri Sep 25 16:12:08 2009 +0900
@@ -41,11 +41,6 @@
 #include <freeDiameter/freeDiameter-host.h>
 #include <freeDiameter/freeDiameter.h>
 
-/* Events codespace for fd_g_config->g_fifo_main */
-enum {
-	FM_TERMINATE = 1000	/* request to terminate */
-};
-
 /* Configuration */
 int fd_conf_init();
 void fd_conf_dump();
@@ -56,8 +51,20 @@
 int fd_ext_init();
 int fd_ext_add( char * filename, char * conffile );
 int fd_ext_load();
+void fd_ext_dump(void);
 int fd_ext_fini(void);
 
+/* Messages */
+int fd_msg_init(void);
+
+/* Global message queues */
+extern struct fifo * fd_g_incoming; /* all messages received from other peers, except local messages (CER, ...) */
+extern struct fifo * fd_g_outgoing; /* messages to be sent to other peers on the network following routing procedure */
+extern struct fifo * fd_g_local; /* messages to be handled to local extensions */
+/* Message queues */
+int fd_queues_init(void);
+int fd_queues_fini(void);
+
 /* Create all the dictionary objects defined in the Diameter base RFC. */
 int fd_dict_base_protocol(struct dictionary * dict);
 
--- a/freeDiameter/fdd.y	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/fdd.y	Fri Sep 25 16:12:08 2009 +0900
@@ -62,11 +62,11 @@
 void yyerror (YYLTYPE *ploc, struct fd_config * conf, char const *s)
 {
 	if (ploc->first_line != ploc->last_line)
-		fprintf(stderr, "%s:%d.%d-%d.%d : %s\n", conf->conf_file, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+		fprintf(stderr, "%s:%d.%d-%d.%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
 	else if (ploc->first_column != ploc->last_column)
-		fprintf(stderr, "%s:%d.%d-%d : %s\n", conf->conf_file, ploc->first_line, ploc->first_column, ploc->last_column, s);
+		fprintf(stderr, "%s:%d.%d-%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_column, s);
 	else
-		fprintf(stderr, "%s:%d.%d : %s\n", conf->conf_file, ploc->first_line, ploc->first_column, s);
+		fprintf(stderr, "%s:%d.%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, s);
 }
 
 %}
@@ -110,31 +110,47 @@
 conffile:		/* Empty is OK */
 			| conffile localidentity
 			| conffile localrealm
+			| conffile tctimer
+			| conffile twtimer
 			| conffile localport
 			| conffile localsecport
+			| conffile sctpstreams
+			| conffile listenon
+			| conffile norelay
 			| conffile noip
 			| conffile noip6
 			| conffile notcp
 			| conffile nosctp
 			| conffile prefertcp
 			| conffile oldtls
-			| conffile sctpstreams
-			| conffile listenon
-			| conffile tctimer
-			| conffile twtimer
-			| conffile norelay
 			| conffile loadext
 			;
 
 localidentity:		LOCALIDENTITY '=' QSTRING ';'
 			{
-				conf->diam_id = $3;
+				conf->cnf_diamid = $3;
 			}
 			;
 
 localrealm:		LOCALREALM '=' QSTRING ';'
 			{
-				conf->diam_realm = $3;
+				conf->cnf_diamrlm = $3;
+			}
+			;
+
+tctimer:		TCTIMER '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_timer_tc = (unsigned int)$3;
+			}
+			;
+
+twtimer:		TWTIMER '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 5),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_timer_tw = (unsigned int)$3;
 			}
 			;
 
@@ -142,7 +158,7 @@
 			{
 				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
 					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
-				conf->loc_port = (uint16_t)$3;
+				conf->cnf_port = (uint16_t)$3;
 			}
 			;
 
@@ -150,43 +166,7 @@
 			{
 				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
 					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
-				conf->loc_port_tls = (uint16_t)$3;
-			}
-			;
-
-noip:			NOIP ';'
-			{
-				conf->flags.no_ip4 = 1;
-			}
-			;
-
-noip6:			NOIP6 ';'
-			{
-				conf->flags.no_ip6 = 1;
-			}
-			;
-
-notcp:			NOTCP ';'
-			{
-				conf->flags.no_tcp = 1;
-			}
-			;
-
-nosctp:			NOSCTP ';'
-			{
-				conf->flags.no_sctp = 1;
-			}
-			;
-
-prefertcp:		PREFERTCP ';'
-			{
-				conf->flags.pr_tcp = 1;
-			}
-			;
-
-oldtls:			OLDTLS ';'
-			{
-				conf->flags.tls_alg = 1;
+				conf->cnf_port_tls = (uint16_t)$3;
 			}
 			;
 
@@ -194,7 +174,7 @@
 			{
 				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
 					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
-				conf->loc_sctp_str = (uint16_t)$3;
+				conf->cnf_sctp_str = (uint16_t)$3;
 			}
 			;
 
@@ -217,29 +197,49 @@
 				memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen);
 				free($3);
 				freeaddrinfo(ai);
-				fd_list_insert_before(&conf->loc_endpoints, &ep->chain);
-			}
-			;
-
-tctimer:		TCTIMER '=' INTEGER ';'
-			{
-				CHECK_PARAMS_DO( ($3 > 0),
-					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
-				conf->timer_tc = (unsigned int)$3;
-			}
-			;
-
-twtimer:		TWTIMER '=' INTEGER ';'
-			{
-				CHECK_PARAMS_DO( ($3 > 5),
-					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
-				conf->timer_tw = (unsigned int)$3;
+				fd_list_insert_before(&conf->cnf_endpoints, &ep->chain);
 			}
 			;
 
 norelay:		NORELAY ';'
 			{
-				conf->flags.no_fwd = 1;
+				conf->cnf_flags.no_fwd = 1;
+			}
+			;
+
+noip:			NOIP ';'
+			{
+				conf->cnf_flags.no_ip4 = 1;
+			}
+			;
+
+noip6:			NOIP6 ';'
+			{
+				conf->cnf_flags.no_ip6 = 1;
+			}
+			;
+
+notcp:			NOTCP ';'
+			{
+				conf->cnf_flags.no_tcp = 1;
+			}
+			;
+
+nosctp:			NOSCTP ';'
+			{
+				conf->cnf_flags.no_sctp = 1;
+			}
+			;
+
+prefertcp:		PREFERTCP ';'
+			{
+				conf->cnf_flags.pr_tcp = 1;
+			}
+			;
+
+oldtls:			OLDTLS ';'
+			{
+				conf->cnf_flags.tls_alg = 1;
 			}
 			;
 
--- a/freeDiameter/main.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/main.c	Fri Sep 25 16:12:08 2009 +0900
@@ -38,6 +38,101 @@
 #include <signal.h>
 #include <getopt.h>
 
+/* forward declarations */
+static void * sig_hdl(void * arg);
+static int main_cmdline(int argc, char *argv[]);
+
+/* The static configuration structure */
+static struct fd_config conf;
+struct fd_config * fd_g_config = &conf;
+
+/* freeDiameter starting point */
+int main(int argc, char * argv[])
+{
+	int ret;
+	pthread_t sig_th;
+	sigset_t sig_all;
+	
+	memset(fd_g_config, 0, sizeof(struct fd_config));
+	sigfillset(&sig_all);
+	CHECK_POSIX(  pthread_sigmask(SIG_BLOCK, &sig_all, NULL)  );
+	
+	/* Initialize the library */
+	CHECK_FCT( fd_lib_init() );
+	
+	/* Name this thread */
+	fd_log_threadname("Main");
+	
+	/* Initialize the config */
+	CHECK_FCT( fd_conf_init() );
+
+	/* Parse the command-line */
+	CHECK_FCT(  main_cmdline(argc, argv)  );
+	
+	/* Allow SIGINT and SIGTERM from this point */
+	CHECK_POSIX(  pthread_create(&sig_th, NULL, sig_hdl, NULL)  );
+	
+	/* Add definitions of the base protocol */
+	CHECK_FCT( fd_dict_base_protocol(fd_g_config->cnf_dict) );
+	
+	/* Initialize other modules */
+	CHECK_FCT(  fd_ext_init()  );
+	CHECK_FCT(  fd_queues_init()  );
+	CHECK_FCT(  fd_msg_init()  );
+	
+	/* Parse the configuration file */
+	CHECK_FCT( fd_conf_parse() );
+	
+	/* Load the dynamic extensions */
+	CHECK_FCT(  fd_ext_load()  );
+	
+	/* Start the peer state machines */
+	
+	
+	/* Now, just wait for events */
+	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
+	fd_conf_dump();
+	while (1) {
+		int code;
+		CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, NULL),  break  );
+		switch (code) {
+			case FDEV_DUMP_DICT:
+				fd_dict_dump(fd_g_config->cnf_dict);
+				break;
+			
+			case FDEV_DUMP_EXT:
+				fd_ext_dump();
+				break;
+			
+			case FDEV_DUMP_QUEUES:
+				fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk);
+				fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk);
+				fd_fifo_dump(0, "Local messages",    fd_g_local,    fd_msg_dump_walk);
+				break;
+			
+			case FDEV_DUMP_CONFIG:
+				fd_conf_dump();
+				break;
+			
+			
+			case FDEV_TERMINATE:
+				ret = 0;
+				goto end;
+			
+			default:
+				TRACE_DEBUG(INFO, "Unexpected event in the daemon (%d), ignored.\n", code);
+		}
+	}
+	
+end:
+	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon is stopping...");
+	
+	/* cleanups */
+	CHECK_FCT_DO( fd_ext_fini(), /* continue */ );
+	CHECK_FCT_DO( fd_thr_term(&sig_th), /* continue */ );
+	
+	return ret;
+}
 
 /* Display package version */
 static void main_version_core(void)
@@ -121,7 +216,7 @@
 
 			case 'c':	/* Read configuration from this file instead of the default location..  */
 				CHECK_PARAMS( optarg );
-				fd_g_config->conf_file = optarg;
+				fd_g_config->cnf_file = optarg;
 				break;
 
 			case 'd':	/* Increase verbosity of debug messages.  */
@@ -158,7 +253,6 @@
 # define SIGNALSTR(sig) ("")
 #endif /* HAVE_SIGNALENT_H */
 
-
 /* signal handler */
 static void * sig_hdl(void * arg)
 {
@@ -175,79 +269,7 @@
 	CHECK_SYS_DO(  sigwait(&sig_main, &sig), TRACE_DEBUG(INFO, "Error in sigwait function") );
 	
 	TRACE_DEBUG(INFO, "Received signal %s (%d), exiting", SIGNALSTR(sig), sig);
-	CHECK_FCT_DO( fd_event_send(fd_g_config->g_fifo_main, FM_TERMINATE, NULL), exit(2) );
+	CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), exit(2) );
 	return NULL;
 }
 	
-/* The static configuration structure */
-static struct fd_config conf;
-struct fd_config * fd_g_config = &conf;
-
-/* Entry point */
-int main(int argc, char * argv[])
-{
-	int ret;
-	pthread_t sig_th;
-	sigset_t sig_all;
-	
-	memset(fd_g_config, 0, sizeof(struct fd_config));
-	sigfillset(&sig_all);
-	CHECK_POSIX(  pthread_sigmask(SIG_BLOCK, &sig_all, NULL)  );
-	
-	/* Initialize the library */
-	CHECK_FCT( fd_lib_init() );
-	
-	/* Name this thread */
-	fd_log_threadname("Main");
-	
-	/* Initialize the config */
-	CHECK_FCT( fd_conf_init() );
-
-	/* Parse the command-line */
-	CHECK_FCT(  main_cmdline(argc, argv)  );
-	
-	/* Allow SIGINT and SIGTERM from this point */
-	CHECK_POSIX(  pthread_create(&sig_th, NULL, sig_hdl, NULL)  );
-	
-	/* Add definitions of the base protocol */
-	CHECK_FCT( fd_dict_base_protocol(fd_g_config->g_dict) );
-	
-	/* Initialize other modules */
-	CHECK_FCT(  fd_ext_init()  );
-	
-	/* Parse the configuration file */
-	CHECK_FCT( fd_conf_parse() );
-	
-	/* Load the dynamic extensions */
-	CHECK_FCT(  fd_ext_load()  );
-	
-	/* Start the peer state machines */
-	
-	
-	/* Now, just wait for events */
-	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
-	fd_conf_dump();
-	while (1) {
-		int code;
-		CHECK_FCT_DO(  fd_event_get(fd_g_config->g_fifo_main, &code, NULL),  break  );
-		switch (code) {
-			case FM_TERMINATE:
-				ret = 0;
-				goto end;
-			
-			default:
-				TRACE_DEBUG(INFO, "Unexpected event in the daemon (%d), terminating.\n", code);
-				ret = -1;
-				goto end;
-		}
-	}
-	
-end:
-	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon is stopping...");
-	
-	/* cleanups */
-	CHECK_FCT_DO( fd_ext_fini(), /* continue */ );
-	CHECK_FCT_DO( fd_thr_term(&sig_th), /* continue */ );
-	
-	return ret;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/messages.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,266 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+#include "fD.h"
+
+static struct dict_object * dict_avp_OH  = NULL; /* Origin-Host */
+static struct dict_object * dict_avp_OR  = NULL; /* Origin-Realm */
+static struct dict_object * dict_avp_OSI = NULL; /* Origin-State-Id */
+static struct dict_object * dict_avp_RC  = NULL; /* Result-Code */
+static struct dict_object * dict_avp_EM  = NULL; /* Error-Message */
+static struct dict_object * dict_avp_ERH = NULL; /* Error-Reporting-Host */
+static struct dict_object * dict_avp_FAVP= NULL; /* Failed-AVP */
+
+/* Resolve the dictionary objects */
+int fd_msg_init(void)
+{
+	TRACE_ENTRY("");
+	
+	/* Initialize the dictionary objects that we may use frequently */
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host",     	&dict_avp_OH  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm",    	&dict_avp_OR  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-State-Id", 	&dict_avp_OSI , ENOENT)  );
+	
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code",     	&dict_avp_RC  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message",   	&dict_avp_EM  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &dict_avp_ERH , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP",      	&dict_avp_FAVP, ENOENT)  );
+	
+	return 0;
+}
+
+/* Add Origin-Host, Origin-Realm, Origin-State-Id AVPS at the end of the message */
+int fd_msg_add_origin ( struct msg * msg, int osi )
+{
+	union avp_value val;
+	struct avp * avp_OH  = NULL;
+	struct avp * avp_OR  = NULL;
+	struct avp * avp_OSI = NULL;
+	
+	TRACE_ENTRY("%p", msg);
+	CHECK_PARAMS(  msg  );
+	
+	/* Create the Origin-Host AVP */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_OH, 0, &avp_OH ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.os.data = (unsigned char *)fd_g_config->cnf_diamid;
+	val.os.len  = fd_g_config->cnf_diamid_len;
+	CHECK_FCT( fd_msg_avp_setvalue( avp_OH, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OH ) );
+	
+	
+	/* Create the Origin-Realm AVP */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_OR, 0, &avp_OR ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.os.data = (unsigned char *)fd_g_config->cnf_diamrlm;
+	val.os.len  = fd_g_config->cnf_diamrlm_len;
+	CHECK_FCT( fd_msg_avp_setvalue( avp_OR, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OR ) );
+	
+	if (osi) {
+		/* Create the Origin-State-Id AVP */
+		CHECK_FCT( fd_msg_avp_new( dict_avp_OSI, 0, &avp_OSI ) );
+
+		/* Set its value */
+		memset(&val, 0, sizeof(val));
+		val.u32 = fd_g_config->cnf_orstateid;
+		CHECK_FCT( fd_msg_avp_setvalue( avp_OSI, &val ) );
+
+		/* Add it to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OSI ) );
+	}
+	
+	return 0;
+}
+
+/* Add Result-Code and eventually Failed-AVP, Error-Message and Error-Reporting-Host AVPs */
+int fd_msg_rescode_set( struct msg * msg, char * rescode, char * errormsg, struct avp * optavp, int type_id )
+{
+	union avp_value val;
+	struct avp * avp_RC  = NULL;
+	struct avp * avp_EM  = NULL;
+	struct avp * avp_ERH = NULL;
+	struct avp * avp_FAVP= NULL;
+	uint32_t rc_val = 0;
+	int set_e_bit=0;
+	int std_err_msg=0;
+	
+	TRACE_ENTRY("%p %s %p %p %d", msg, rescode, errormsg, optavp, type_id);
+		
+	CHECK_PARAMS(  msg && rescode  );
+	
+	/* Find the enum value corresponding to the rescode string, this will give the class of error */
+	{
+		struct dict_object * enum_obj = NULL;
+		struct dict_enumval_request req;
+		memset(&req, 0, sizeof(struct dict_enumval_request));
+		
+		/* First, get the enumerated type of the Result-Code AVP */
+		CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, dict_avp_RC, &(req.type_obj), ENOENT  )  );
+		
+		/* Now search for the value given as parameter */
+		req.search.enum_name = rescode;
+		CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enum_obj, ENOTSUP)  );
+		
+		/* finally retrieve its data */
+		CHECK_FCT_DO(  fd_dict_getval( enum_obj, &(req.search) ), return EINVAL );
+		
+		/* copy the found value, we're done */
+		rc_val = req.search.enum_value.u32;
+	}
+	
+	if (type_id == 1) {
+		/* Add the Origin-Host and Origin-Realm AVP */
+		CHECK_FCT( fd_msg_add_origin ( msg, 0 ) );
+	}
+	
+	/* Create the Result-Code AVP */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_RC, 0, &avp_RC ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.u32  = rc_val;
+	CHECK_FCT( fd_msg_avp_setvalue( avp_RC, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_RC ) );
+	
+	if (type_id == 2) {
+		/* Add the Error-Reporting-Host AVP */
+		
+		CHECK_FCT( fd_msg_avp_new( dict_avp_ERH, 0, &avp_ERH ) );
+
+		/* Set its value */
+		memset(&val, 0, sizeof(val));
+		val.os.data = (unsigned char *)fd_g_config->cnf_diamid;
+		val.os.len  = fd_g_config->cnf_diamid_len;
+		CHECK_FCT( fd_msg_avp_setvalue( avp_ERH, &val ) );
+
+		/* Add it to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_ERH ) );
+	
+	}
+	
+	/* Now add the optavp in a FailedAVP if provided */
+	if (optavp) {
+		/* Create the Failed-AVP AVP */
+		CHECK_FCT( fd_msg_avp_new( dict_avp_FAVP, 0, &avp_FAVP ) );
+
+		/* Add the passed AVP inside it */
+		CHECK_FCT( fd_msg_avp_add( avp_FAVP, MSG_BRW_LAST_CHILD, optavp ) );
+		
+		/* And add to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_FAVP ) );
+	}
+	
+	
+	/* Deal with the 'E' bit and the error message */
+	switch (rc_val / 1000) {
+		case 1:	/* Informational */
+		case 2: /* Success */
+			/* Nothing special here: no E bit, no error message unless one is specified */
+			break;
+			
+		case 3: /* Protocol Errors */
+			set_e_bit = 1;
+			std_err_msg = 1;
+			break;
+			
+		case 4: /* Transcient Failure */
+		case 5: /* Permanent Failure */
+		default:
+			std_err_msg = 1;
+			break;
+			
+	}
+	
+	{
+		struct msg_hdr * hdr = NULL;
+		
+		CHECK_FCT(  fd_msg_hdr( msg, &hdr )  );
+		
+		if (set_e_bit)
+			hdr->msg_flags |= CMD_FLAG_ERROR;
+		else
+			hdr->msg_flags &= ! CMD_FLAG_ERROR;
+	}
+	
+	if (std_err_msg || errormsg) {
+		/* Add the Error-Message AVP */
+		
+		CHECK_FCT( fd_msg_avp_new( dict_avp_EM, 0, &avp_EM ) );
+
+		/* Set its value */
+		memset(&val, 0, sizeof(val));
+		
+		if (errormsg) {
+			val.os.data = (unsigned char *)errormsg;
+			val.os.len  = strlen(errormsg);
+		} else {
+			val.os.data = (unsigned char *)rescode;
+			val.os.len  = strlen(rescode);
+		}
+		CHECK_FCT( fd_msg_avp_setvalue( avp_EM, &val ) );
+
+		/* Add it to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_EM ) );
+	}
+	
+	return 0;
+}
+
+/* Send a message and optionaly register a callback for an answer */
+int fd_msg_send ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data )
+{
+	TRACE_ENTRY("%p %p %p", pmsg, anscb, data);
+	CHECK_PARAMS( pmsg );
+	
+	/* Save the callback in the message */
+	CHECK_FCT(  fd_msg_anscb_associate( *pmsg, anscb, data )  );
+	
+	/* Post the message in the outgoing queue */
+	CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) );
+	
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/queues.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,65 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+#include "fD.h"
+
+/* The global message queues */
+struct fifo * fd_g_incoming = NULL;
+struct fifo * fd_g_outgoing = NULL;
+struct fifo * fd_g_local = NULL;
+
+/* Initialize the message queues. */
+int fd_queues_init(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT( fd_fifo_new ( &fd_g_incoming ) );
+	CHECK_FCT( fd_fifo_new ( &fd_g_outgoing ) );
+	CHECK_FCT( fd_fifo_new ( &fd_g_local ) );
+	return 0;
+}
+
+/* Destroy the message queues */
+int fd_queues_fini(void)
+{
+	TRACE_ENTRY();
+	
+	/* Stop the providing threads */
+	/* Empty all contents */
+	/* Now, delete the queues */
+	CHECK_FCT( fd_fifo_del ( &fd_g_incoming ) );
+	CHECK_FCT( fd_fifo_del ( &fd_g_outgoing ) );
+	CHECK_FCT( fd_fifo_del ( &fd_g_local ) );
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/routing.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,37 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+#include "fD.h"
+
--- a/freeDiameter/tests/CMakeLists.txt	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/tests/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -14,7 +14,7 @@
 	testlist
 	testdict
 	testmesg
-	testqueues
+	testfifo
 	testsess
 	testdisp
 )
--- a/freeDiameter/tests/testdict.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/tests/testdict.c	Fri Sep 25 16:12:08 2009 +0900
@@ -66,24 +66,24 @@
 		
 		
 		/* Create two vendors */
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_VENDOR, &vendor1_data , NULL, &obj1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_VENDOR, &vendor2_data , NULL, NULL ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor1_data , NULL, &obj1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor2_data , NULL, NULL ) );
 		
 		/* Check we always retrieve the correct vendor object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
 		CHECK( obj1, obj2);
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 1", &obj2, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 1", &obj2, ENOENT ) );
 		CHECK( obj1, obj2);
 		
 		/* Check the error conditions */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
 		
 		vendor_id = 735673; /* Not defined */
-		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
-		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", NULL, ENOENT ) );
-		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
-		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOENT ) );
-		CHECK( ENOTSUP, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOTSUP ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", NULL, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOENT ) );
+		CHECK( ENOTSUP, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOTSUP ) );
 		
 		/* Check the get_* functions */
 		CHECK( 0, fd_dict_getval ( obj1, &vendor1_data ) );
@@ -93,10 +93,10 @@
 		CHECK( EINVAL, fd_dict_getval ( (struct dict_object *)"not an object", &vendor1_data ) );
 		
 		/* Create the application with vendor1 as parent */
-		CHECK( EINVAL, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app1_data , (struct dict_object *)"bad object", &obj2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app1_data , obj1, &obj2 ) );
+		CHECK( EINVAL, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app1_data , (struct dict_object *)"bad object", &obj2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app1_data , obj1, &obj2 ) );
 		
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_OF_APPLICATION, obj2, &obj3, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_OF_APPLICATION, obj2, &obj3, ENOENT ) );
 		CHECK( obj1, obj3);
 		
 		/* Creating and searching the other objects is already done in dictionary initialization */
@@ -111,20 +111,20 @@
 		struct dict_rule_data rule_data = { NULL, RULE_REQUIRED, -1, -1 };
 		struct dict_avp_data example_avp_data = { 999999, 0, "Example-AVP", AVP_FLAG_VENDOR , 0, AVP_TYPE_GROUPED };
 
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT ) );
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT ) );
 		
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ) );
 		
 		rule_data.rule_avp = origin_host_avp;
 		rule_data.rule_min = 1;
 		rule_data.rule_max = 1;
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
 		
 		rule_data.rule_avp = session_id_avp;
 		rule_data.rule_min = 1;
 		rule_data.rule_max = -1;
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
 		
 		CHECK( 0, fd_dict_iterate_rules ( example_avp_avp, &nbr, iter_test) );
 		CHECK( 2, nbr );
--- a/freeDiameter/tests/testdisp.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/tests/testdisp.c	Fri Sep 25 16:12:08 2009 +0900
@@ -127,15 +127,15 @@
 		struct dict_enumval_data enu1_data = { "ENU test 1", { .u32 = 1 }};
 		struct dict_enumval_data enu2_data = { "ENU test 2", { .u32 = 2 }};
 		
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app1_data, NULL, &app1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app2_data, NULL, &app2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_COMMAND, &cmd1_data, NULL, &cmd1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_COMMAND, &cmd2_data, NULL, &cmd2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data, NULL, &enutype ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp1_data, NULL,    &avp1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp2_data, enutype, &avp2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &enu1_data, enutype, &enu1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &enu2_data, enutype, &enu2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app1_data, NULL, &app1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app2_data, NULL, &app2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd1_data, NULL, &cmd1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd2_data, NULL, &cmd2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data, NULL, &enutype ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp1_data, NULL,    &avp1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp2_data, enutype, &avp2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &enu1_data, enutype, &enu1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &enu2_data, enutype, &enu2 ) );
 	}
 	
 	/* Register first handler, very simple test */
@@ -668,6 +668,34 @@
 		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
 	}			
 	
+	/* Test application support advertisement */
+	{
+		struct dict_object * vnd;
+		struct dict_vendor_data vnd_data = { 1, "Vendor test" };
+		struct fd_app * app;
+		
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vnd_data, NULL, &vnd ) );
+		
+		CHECK( EINVAL, fd_disp_app_support ( vnd, NULL, 1, 0 ) );
+		CHECK( EINVAL, fd_disp_app_support ( app1, NULL, 0, 0 ) );
+		CHECK( 0, fd_disp_app_support ( app1, NULL, 1, 0 ) );
+		CHECK( 0, fd_disp_app_support ( app1, NULL, 0, 1 ) );
+		CHECK( 0, fd_disp_app_support ( app2, vnd, 1, 0 ) );
+		
+		app = (struct fd_app *)(fd_g_config->cnf_apps.next);
+		CHECK( 1, app->appid );
+		CHECK( 1, app->flags.auth );
+		CHECK( 1, app->flags.acct );
+		app = (struct fd_app *)(fd_g_config->cnf_apps.prev);
+		CHECK( 2, app->appid );
+		CHECK( 1, app->flags.auth );
+		CHECK( 0, app->flags.acct );
+		
+		#if 0
+		fd_conf_dump();
+		#endif
+	}
+	
 	/* That's all for the tests yet */
 	PASSTEST();
 } 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/tests/testfifo.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,423 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+/* Structure for testing threshold function */
+static struct thrh_test {
+	struct fifo *   queue; /* pointer to the queue */
+	int		h_calls; /* number of calls of h_cb */
+	int		l_calls; /* number of calls of l_cb */
+} thrh_td;
+
+/* Callbacks for threasholds test */
+void thrh_cb_h(struct fifo *queue, void **data)
+{
+	if (thrh_td.h_calls == thrh_td.l_calls) {
+		CHECK( NULL, *data );
+		*data = &thrh_td;
+	} else {
+		CHECK( *data, &thrh_td );
+	}
+	CHECK( queue, thrh_td.queue );
+	
+	/* Update the count */
+	thrh_td.h_calls ++;
+}
+void thrh_cb_l(struct fifo *queue, void **data)
+{
+	CHECK( 1, data ? 1 : 0 );
+	CHECK( *data, &thrh_td );
+
+	/* Check the queue parameter is correct */
+	CHECK( queue, thrh_td.queue );
+	
+	/* Update the count */
+	thrh_td.l_calls ++;
+	/* Cleanup the data ptr if needed */
+	if (thrh_td.l_calls == thrh_td.h_calls)
+		*data = NULL;
+	/* done */
+}
+
+
+/* Structure that is passed to the test function */
+struct test_data {
+	struct fifo     * queue; /* pointer to the queue */
+	pthread_barrier_t * bar;   /* if not NULL, barrier to synchronize before getting messages */
+	struct timespec   * ts;	   /* if not NULL, use a timedget instead of a get */
+	int		    nbr;   /* number of messages to retrieve from the queue */
+};
+
+/* The test function, to be threaded */
+static void * test_fct(void * data)
+{
+	int ret = 0, i;
+	struct msg * msg = NULL;
+	struct test_data * td = (struct test_data *) data;
+	
+	if (td->bar != NULL) {
+		ret = pthread_barrier_wait(td->bar);
+		if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+			CHECK( 0, ret);
+		} else {
+			CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* just for the traces */
+		}
+	}
+	
+	for (i=0; i< td->nbr; i++) {
+		if (td->ts != NULL) {
+			CHECK( 0, fd_fifo_timedget(td->queue, &msg, td->ts) );
+		} else {
+			CHECK( 0, fd_fifo_get(td->queue, &msg) );
+		}
+	}
+	
+	return NULL;
+}
+
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct timespec ts;
+	
+	struct msg * msg1 = NULL;
+	struct msg * msg2 = NULL;
+	struct msg * msg3 = NULL;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Prolog: create the messages */
+	{
+		struct dict_object * acr_model = NULL;
+		struct dict_object * cer_model = NULL;
+		struct dict_object * dwr_model = NULL;
+
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", 			&acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", 	&cer_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
+		CHECK( 0, fd_msg_new ( acr_model, 0, &msg1 ) );
+		CHECK( 0, fd_msg_new ( cer_model, 0, &msg2 ) );
+		CHECK( 0, fd_msg_new ( dwr_model, 0, &msg3 ) );
+	}
+	
+	/* Basic operation */
+	{
+		struct fifo * queue = NULL;
+		int count;
+		struct msg * msg  = NULL;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Check the count is 0 */
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* Now enqueue */
+		msg = msg1;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		msg = msg2;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		msg = msg3;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		
+		/* Check the count is 3 */
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 3, count);
+		
+		/* Retrieve the first message using fd_fifo_get */
+		CHECK( 0, fd_fifo_get(queue, &msg) );
+		CHECK( msg1, msg);
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 2, count);
+		
+		/* Retrieve the second message using fd_fifo_timedget */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 1; /* Set the timeout to 1 second */
+		CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) );
+		CHECK( msg2, msg);
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 1, count);
+		
+		/* Retrieve the third message using meq_tryget */
+		CHECK( 0, fd_fifo_tryget(queue, &msg) );
+		CHECK( msg3, msg);
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* Check that another meq_tryget does not block */
+		CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) );
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* We're done for basic tests */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test robustness, ensure no messages are lost */
+	{
+#define NBR_MSG		200
+#define NBR_THREADS	60
+		struct fifo  		*queue = NULL;
+		pthread_barrier_t	 bar;
+		struct test_data	 td_1;
+		struct test_data	 td_2;
+		struct msg   		*msgs[NBR_MSG * NBR_THREADS * 2], *msg;
+		pthread_t  		 thr [NBR_THREADS * 2];
+		struct dict_object	*dwr_model = NULL;
+		int 			 count;
+		int			 i;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Create the barrier */
+		CHECK( 0, pthread_barrier_init(&bar, NULL, NBR_THREADS * 2 + 1) );
+		
+		/* Initialize the ts */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 2; /* Set the timeout to 2 second */
+		
+		/* Create the messages */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
+		for (i = 0; i < NBR_MSG * NBR_THREADS * 2; i++) {
+			CHECK( 0, fd_msg_new ( dwr_model, 0, &msgs[i] ) );
+		}
+		
+		/* Initialize the test data structures */
+		td_1.queue = queue;
+		td_1.bar = &bar;
+		td_1.ts  = &ts;
+		td_1.nbr = NBR_MSG;
+		td_2.queue = queue;
+		td_2.bar = &bar;
+		td_2.ts  = NULL;
+		td_2.nbr = NBR_MSG;
+		
+		/* Create the threads */
+		for (i=0; i < NBR_THREADS * 2; i++) {
+			CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) );
+		}
+		
+		/* Synchronize everyone */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* for trace only */
+			}
+		}
+		
+		/* Now post all the messages */
+		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
+			msg = msgs[i];
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		}
+		
+		/* Join all threads. This blocks if messages are lost... */
+		for (i=0; i < NBR_THREADS * 2; i++) {
+			CHECK( 0, pthread_join( thr[i], NULL ) );
+		}
+		
+		/* Check the count of the queue is back to 0 */
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* Destroy this queue and the messages */
+		CHECK( 0, fd_fifo_del(&queue) );
+		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
+			CHECK( 0, fd_msg_free(  msgs[i] ) );
+		}
+	}
+	
+	/* Test thread cancelation */
+	{
+		struct fifo      	*queue = NULL;
+		pthread_barrier_t	 bar;
+		struct test_data	 td;
+		pthread_t		 th;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Create the barrier */
+		CHECK( 0, pthread_barrier_init(&bar, NULL, 2) );
+		
+		/* Initialize the ts */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 2; /* Set the timeout to 2 second */
+		
+		/* Initialize the test data structures */
+		td.queue = queue;
+		td.bar = &bar;
+		td.ts  = &ts;
+		td.nbr = 1;
+		
+		/* Create the thread */
+		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
+		
+		/* Wait for the thread to be running */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
+			}
+		}
+		
+		/* Now cancel the thread */
+		CHECK( 0, pthread_cancel( th ) );
+		
+		/* Join it */
+		CHECK( 0, pthread_join( th, NULL ) );
+		
+		/* Do the same with the other function */
+		td.ts  = NULL;
+		
+		/* Create the thread */
+		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
+		
+		/* Wait for the thread to be running */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
+			}
+		}
+		
+		/* Now cancel the thread */
+		CHECK( 0, pthread_cancel( th ) );
+		
+		/* Join it */
+		CHECK( 0, pthread_join( th, NULL ) );
+		
+		/* Destroy the queue */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test the threashold function */
+	{
+		struct fifo * queue = NULL;
+		int i;
+		struct msg * msg  = NULL;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Prepare the test data */
+		memset(&thrh_td, 0, sizeof(thrh_td));
+		thrh_td.queue = queue;
+		
+		/* Set the thresholds for the queue */
+		CHECK( 0, fd_fifo_setthrhd ( queue, NULL, 6, thrh_cb_h, 4, thrh_cb_l ) );
+		
+		/* Post 5 messages, no cb must be called. */
+		for (i=0; i<5; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 5 msg in queue */
+		CHECK( 0, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Get all these messages, and check again */
+		for (i=0; i<5; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 0 msg in queue */
+		CHECK( 0, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Now, post 6 messages, the high threashold */
+		for (i=0; i<6; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 6 msg in queue */
+		CHECK( 1, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Remove 2 messages, to reach the low threshold */
+		for (i=0; i<2; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 4 msg in queue */
+		CHECK( 1, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Come again at the high threshold */
+		for (i=0; i<2; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 6 msg in queue */
+		CHECK( 2, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Suppose the queue continues to grow */
+		for (i=0; i<6; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 12 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		for (i=0; i<5; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 17 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Now the queue goes back to 0 messages */
+		for (i=0; i<17; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 0 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 3, thrh_td.l_calls );
+		
+		/* We're done for this test */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Delete the messages */
+	CHECK( 0, fd_msg_free( msg1 ) );
+	CHECK( 0, fd_msg_free( msg2 ) );
+	CHECK( 0, fd_msg_free( msg3 ) );
+
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
--- a/freeDiameter/tests/testmesg.c	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/tests/testmesg.c	Fri Sep 25 16:12:08 2009 +0900
@@ -50,7 +50,7 @@
 		struct dict_object * acr_model = NULL;
 
 		/* Now find the ACR dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
 
 		/* Create the instance, using the templates */
 		CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) );
@@ -70,7 +70,7 @@
 		struct dict_object * pi_model = NULL;
 
 		/* Now find the ACR dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &pi_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &pi_model, ENOENT ) );
 
 		/* Create the instance, using the templates */
 		CHECK( 0, fd_msg_avp_new ( pi_model, 0, &pi ) );
@@ -132,7 +132,7 @@
 		struct dict_object * rr_model = NULL;
 
 		/* Now find the dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &rr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &rr_model, ENOENT ) );
 
 		/* Create the instance, using the templates */
 		CHECK( 0, fd_msg_avp_new ( rr_model, 0, &avp1 ) );
@@ -160,7 +160,7 @@
 		struct dict_object * acr_model = NULL;
 
 		/* Now find the ACR dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
 
 		/* Create the instance, using the templates */
 		CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) );
@@ -172,25 +172,25 @@
 		struct dict_object * vendor;
 		{
 			struct dict_vendor_data vendor_data = { 73565, "Vendor test" };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
 		}
 		
 		{
 			struct dict_application_data app_data = { 73566, "Application test" };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app_data , vendor, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app_data , vendor, NULL ) );
 		}
 		
 		{
 			struct dict_avp_data avp_data = { 73567, 0, "AVP Test - no vendor - f32", 0, 0, AVP_TYPE_FLOAT32 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		
 		{ 
 			struct dict_object  * type = NULL;
 			struct dict_type_data type_data = { AVP_TYPE_INTEGER64, "Int64 test" };
 			struct dict_avp_data  avp_data = { 73568, 73565, "AVP Test - i64", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER64 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
 		}
 		
 		{
@@ -201,19 +201,19 @@
 			struct dict_enumval_data val3 = { "i32 const test (val -5)",{ .i32 = -5 } };
 			struct dict_avp_data     avp_data = { 73569, 73565, "AVP Test - enumi32", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER32 };
 			
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
 		}
 			
 		{ 
 			struct dict_object  * type = NULL;
 			struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS test" };
 			struct dict_avp_data  avp_data = { 73570, 73565, "AVP Test - os", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
 		}
 		
 		{
@@ -224,31 +224,31 @@
 			struct dict_enumval_data val3 = { "os const test (waa)", { .os = { (unsigned char *)"waaad", 3 } } };
 			struct dict_avp_data     avp_data = { 73571, 73565, "AVP Test - enumos", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
 			
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
 		}
 		
 		{
 			struct dict_object * gavp = NULL;
 			struct dict_avp_data avp_data = { 73572, 73565, "AVP Test - grouped", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
 			
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
 			
 			/* Macro to search AVP and create a rule */		
 			#define ADD_RULE( _parent, _vendor, _avpname, _pos, _min, _max, _ord ) {		\
 				struct dict_object * _avp = NULL;						\
 				struct dict_avp_request _req = { (_vendor), 0, (_avpname) };			\
 				struct dict_rule_data _data;							\
-				CHECK( 0, fd_dict_search( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
 				_data.rule_avp = _avp;								\
 				_data.rule_position = (_pos);							\
 				_data.rule_order = (_ord);							\
 				_data.rule_min = (_min);							\
 				_data.rule_max = (_max);							\
-				CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
+				CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
 			}
 			
 			ADD_RULE(gavp, 73565, "AVP Test - os", RULE_OPTIONAL,   -1, -1,  0);
@@ -260,8 +260,8 @@
 			struct dict_object  * command = NULL;
 			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Request", CMD_FLAG_REQUEST, CMD_FLAG_REQUEST };
 			
-			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
 			ADD_RULE(command, 0,     "AVP Test - no vendor - f32", 	RULE_FIXED_HEAD, -1,  1,  1);
 			ADD_RULE(command, 73565, "AVP Test - i64",		RULE_REQUIRED,   -1, -1,  0);
 			ADD_RULE(command, 73565, "AVP Test - enumi32", 		RULE_OPTIONAL,   -1, -1,  0);
@@ -274,7 +274,7 @@
 			struct dict_object  * gavp = NULL;
 			struct dict_avp_data  avp_data = { 73574, 73565, "AVP Test - rules", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
 			
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
 			
 			ADD_RULE(gavp,     0, "AVP Test - no vendor - f32", RULE_FIXED_HEAD,   0, 1, 1);
 			ADD_RULE(gavp, 73565, "AVP Test - i64", 	    RULE_FIXED_HEAD,  -1, 1, 2);
@@ -302,11 +302,11 @@
 		struct avp         * avp = NULL;
 		union avp_value      value;
 		
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
 		
 		/* Check an error is trigged if the AVP has no value set */
 		{
-			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP,     AVP_BY_NAME,     "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP,     AVP_BY_NAME,     "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
 			
 			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
 			CHECK( 0, fd_msg_avp_new ( avp_model, 0, &avp ) );
@@ -328,7 +328,7 @@
 			#define ADD_AVP( _parent, _position, _avpi, _avpvendor, _avpname) {			\
 				struct dict_object * _avp = NULL;						\
 				struct dict_avp_request _req = { (_avpvendor), 0, (_avpname) };			\
-				CHECK( 0, fd_dict_search( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
 				CHECK( 0, fd_msg_avp_new ( _avp, 0, &_avpi ) );					\
 				CHECK( 0, fd_msg_avp_add ( (_parent), (_position), _avpi ) );			\
 			}
@@ -377,11 +377,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
 				memset(&request, 0, sizeof(request));
 				request.type_obj = type_model;
 				request.search.enum_name = "i32 const test (val 2)";
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
 				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
 				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
 				#if 0
@@ -398,11 +398,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
 				memset(&request, 0, sizeof(request));
 				request.type_obj = type_model;
 				request.search.enum_name = "i32 const test (val -5)";
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
 				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
 				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
 				#if 0
@@ -457,11 +457,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
 				memset(&request, 0, sizeof(request));
 				request.type_obj = type_model;
 				request.search.enum_name = "os const test (waaad)";
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
 				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
 				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
 				#if 0
@@ -482,11 +482,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
 				memset(&request, 0, sizeof(request));
 				request.type_obj = type_model;
 				request.search.enum_name = "os const test (waa)";
-				CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
 				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
 				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
 				#if 0
@@ -653,7 +653,7 @@
 			struct avp_hdr     * avpdata = NULL;
 			
 			/* Now find the ACR dictionary object */
-			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
 			
 			CPYBUF();
 			CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
@@ -679,7 +679,7 @@
 				/* Change the command-code */
 				buf_cpy[5] = 0x11;
 				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
-				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
+				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->cnf_dict ) );
 				
 				/* reset */
 				CHECK( 0, fd_msg_free ( msg ) );
@@ -694,7 +694,7 @@
 				
 				/* Check that we cannot support this message now */
 				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
-				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
+				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->cnf_dict ) );
 				
 				/* reset */
 				CHECK( 0, fd_msg_free ( msg ) );
@@ -708,7 +708,7 @@
 				
 				/* Check that we can support this message now */
 				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
-				CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
+				CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict ) );
 				
 				#if 0
 				fd_msg_dump_walk(0, msg);
@@ -719,7 +719,7 @@
 			}
 			
 			CHECK( 0, fd_msg_parse_buffer( &buf, 344, &msg) );
-			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
+			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict ) );
 			#if 0
 			fd_msg_dump_walk(0, msg);
 			#endif
@@ -729,7 +729,7 @@
 		{
 			struct dict_object * rule;
 			
-			CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
+			CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
 			
 			/* Use the "AVP Test - rules" AVP to test the rules */
 			{
@@ -748,26 +748,26 @@
 				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - grouped" );
 				
 				/* Check the message is still conform */
-				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
 				
 				/* The first avp is optional in fixed position, so remove it and check the message is still OK */
 				CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &childavp, NULL) );
 				CHECK( 0, fd_msg_free ( childavp ) );
-				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
 				ADD_AVP( tavp, MSG_BRW_FIRST_CHILD, childavp,     0, "AVP Test - no vendor - f32" );
 				
 				
 				/* Now break some rules and check it is detected */
 				#define CHECK_CONFLICT( _msg, _ruleavp, _avpvendor )		{				\
 					struct dict_object * _rule;								\
-					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_config->g_dict, &_rule ) );			\
+					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_config->cnf_dict, &_rule ) );			\
 					if ((_ruleavp) == NULL) {								\
 						CHECK( NULL, _rule);								\
 					} else {										\
 						struct dict_rule_data   _ruledata;						\
 						struct dict_object *    _avp;							\
 						struct dict_avp_request _req = { (_avpvendor), 0, (_ruleavp) };			\
-						CHECK( 0, fd_dict_search( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));	\
+						CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));	\
 						CHECK( 0, fd_dict_getval( _rule, &_ruledata ) );				\
 						CHECK( _avp, _ruledata.rule_avp );						\
 					}											\
@@ -823,7 +823,7 @@
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
 					
 					/* The message is still conform */
-					CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
+					CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
 					
 					/* Now break the rule */
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
@@ -864,10 +864,10 @@
 		struct sockaddr_in6 sin6, *psin6;
 		
 		/* Find the CER dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer_model, ENOENT ) );
 
 		/* Now find the Host-IP-Address dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &hia_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &hia_model, ENOENT ) );
 
 		/* Create the msg instance */
 		CHECK( 0, fd_msg_new ( cer_model, 0, &cer ) );
@@ -944,7 +944,7 @@
 		
 		/* Ok, now let's recreate the message */
 		CHECK( 0, fd_msg_parse_buffer( &buf, 64, &cer) );
-		CHECK( 0, fd_msg_parse_dict( cer, fd_g_config->g_dict ) );
+		CHECK( 0, fd_msg_parse_dict( cer, fd_g_config->cnf_dict ) );
 		
 		/* Get the pointers to the first and last AVP */
 		CHECK( 0, fd_msg_browse( cer, MSG_BRW_FIRST_CHILD, &avp4, NULL) );
@@ -971,31 +971,31 @@
 	{
 		{
 			struct dict_avp_data avp_data = { 91001, 0, "AVP Test 2 - os", 0, 0, AVP_TYPE_OCTETSTRING };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91002, 0, "AVP Test 2 - i32", 0, 0, AVP_TYPE_INTEGER32 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91003, 0, "AVP Test 2 - i64", 0, 0, AVP_TYPE_INTEGER64 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91004, 0, "AVP Test 2 - u32", 0, 0, AVP_TYPE_UNSIGNED32 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91005, 0, "AVP Test 2 - u64", 0, 0, AVP_TYPE_UNSIGNED64 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91006, 0, "AVP Test 2 - f32", 0, 0, AVP_TYPE_FLOAT32 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91007, 0, "AVP Test 2 - f64", 0, 0, AVP_TYPE_FLOAT64 };
-			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		
 		{
@@ -1009,7 +1009,7 @@
 			struct avp_hdr     * avpdata = NULL;
 			struct msg_hdr     * msgdata = NULL;
 
-			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
 
 			/* Create a message */
 			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
@@ -1174,7 +1174,7 @@
 			CHECK( 0, fd_msg_free( msg ) );
 			
 			CHECK( 0, fd_msg_parse_buffer( &buf, 148, &msg) );
-			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
+			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict ) );
 			#if 0
 			fd_msg_dump_walk(0, msg);
 			#endif
--- a/freeDiameter/tests/testqueues.c	Thu Sep 24 14:01:48 2009 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,423 +0,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, 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.								 *
-*********************************************************************************************************/
-
-#include "tests.h"
-
-/* Structure for testing threshold function */
-static struct thrh_test {
-	struct fifo *   queue; /* pointer to the queue */
-	int		h_calls; /* number of calls of h_cb */
-	int		l_calls; /* number of calls of l_cb */
-} thrh_td;
-
-/* Callbacks for threasholds test */
-void thrh_cb_h(struct fifo *queue, void **data)
-{
-	if (thrh_td.h_calls == thrh_td.l_calls) {
-		CHECK( NULL, *data );
-		*data = &thrh_td;
-	} else {
-		CHECK( *data, &thrh_td );
-	}
-	CHECK( queue, thrh_td.queue );
-	
-	/* Update the count */
-	thrh_td.h_calls ++;
-}
-void thrh_cb_l(struct fifo *queue, void **data)
-{
-	CHECK( 1, data ? 1 : 0 );
-	CHECK( *data, &thrh_td );
-
-	/* Check the queue parameter is correct */
-	CHECK( queue, thrh_td.queue );
-	
-	/* Update the count */
-	thrh_td.l_calls ++;
-	/* Cleanup the data ptr if needed */
-	if (thrh_td.l_calls == thrh_td.h_calls)
-		*data = NULL;
-	/* done */
-}
-
-
-/* Structure that is passed to the test function */
-struct test_data {
-	struct fifo     * queue; /* pointer to the queue */
-	pthread_barrier_t * bar;   /* if not NULL, barrier to synchronize before getting messages */
-	struct timespec   * ts;	   /* if not NULL, use a timedget instead of a get */
-	int		    nbr;   /* number of messages to retrieve from the queue */
-};
-
-/* The test function, to be threaded */
-static void * test_fct(void * data)
-{
-	int ret = 0, i;
-	struct msg * msg = NULL;
-	struct test_data * td = (struct test_data *) data;
-	
-	if (td->bar != NULL) {
-		ret = pthread_barrier_wait(td->bar);
-		if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-			CHECK( 0, ret);
-		} else {
-			CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* just for the traces */
-		}
-	}
-	
-	for (i=0; i< td->nbr; i++) {
-		if (td->ts != NULL) {
-			CHECK( 0, fd_fifo_timedget(td->queue, &msg, td->ts) );
-		} else {
-			CHECK( 0, fd_fifo_get(td->queue, &msg) );
-		}
-	}
-	
-	return NULL;
-}
-
-
-/* Main test routine */
-int main(int argc, char *argv[])
-{
-	struct timespec ts;
-	
-	struct msg * msg1 = NULL;
-	struct msg * msg2 = NULL;
-	struct msg * msg3 = NULL;
-	
-	/* First, initialize the daemon modules */
-	INIT_FD();
-	
-	/* Prolog: create the messages */
-	{
-		struct dict_object * acr_model = NULL;
-		struct dict_object * cer_model = NULL;
-		struct dict_object * dwr_model = NULL;
-
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", 			&acr_model, ENOENT ) );
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", 	&cer_model, ENOENT ) );
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
-		CHECK( 0, fd_msg_new ( acr_model, 0, &msg1 ) );
-		CHECK( 0, fd_msg_new ( cer_model, 0, &msg2 ) );
-		CHECK( 0, fd_msg_new ( dwr_model, 0, &msg3 ) );
-	}
-	
-	/* Basic operation */
-	{
-		struct fifo * queue = NULL;
-		int count;
-		struct msg * msg  = NULL;
-		
-		/* Create the queue */
-		CHECK( 0, fd_fifo_new(&queue) );
-		
-		/* Check the count is 0 */
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* Now enqueue */
-		msg = msg1;
-		CHECK( 0, fd_fifo_post(queue, &msg) );
-		msg = msg2;
-		CHECK( 0, fd_fifo_post(queue, &msg) );
-		msg = msg3;
-		CHECK( 0, fd_fifo_post(queue, &msg) );
-		
-		/* Check the count is 3 */
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 3, count);
-		
-		/* Retrieve the first message using fd_fifo_get */
-		CHECK( 0, fd_fifo_get(queue, &msg) );
-		CHECK( msg1, msg);
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 2, count);
-		
-		/* Retrieve the second message using fd_fifo_timedget */
-		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
-		ts.tv_sec += 1; /* Set the timeout to 1 second */
-		CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) );
-		CHECK( msg2, msg);
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 1, count);
-		
-		/* Retrieve the third message using meq_tryget */
-		CHECK( 0, fd_fifo_tryget(queue, &msg) );
-		CHECK( msg3, msg);
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* Check that another meq_tryget does not block */
-		CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) );
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* We're done for basic tests */
-		CHECK( 0, fd_fifo_del(&queue) );
-	}
-	
-	/* Test robustness, ensure no messages are lost */
-	{
-#define NBR_MSG		200
-#define NBR_THREADS	60
-		struct fifo  		*queue = NULL;
-		pthread_barrier_t	 bar;
-		struct test_data	 td_1;
-		struct test_data	 td_2;
-		struct msg   		*msgs[NBR_MSG * NBR_THREADS * 2], *msg;
-		pthread_t  		 thr [NBR_THREADS * 2];
-		struct dict_object	*dwr_model = NULL;
-		int 			 count;
-		int			 i;
-		
-		/* Create the queue */
-		CHECK( 0, fd_fifo_new(&queue) );
-		
-		/* Create the barrier */
-		CHECK( 0, pthread_barrier_init(&bar, NULL, NBR_THREADS * 2 + 1) );
-		
-		/* Initialize the ts */
-		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
-		ts.tv_sec += 2; /* Set the timeout to 2 second */
-		
-		/* Create the messages */
-		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
-		for (i = 0; i < NBR_MSG * NBR_THREADS * 2; i++) {
-			CHECK( 0, fd_msg_new ( dwr_model, 0, &msgs[i] ) );
-		}
-		
-		/* Initialize the test data structures */
-		td_1.queue = queue;
-		td_1.bar = &bar;
-		td_1.ts  = &ts;
-		td_1.nbr = NBR_MSG;
-		td_2.queue = queue;
-		td_2.bar = &bar;
-		td_2.ts  = NULL;
-		td_2.nbr = NBR_MSG;
-		
-		/* Create the threads */
-		for (i=0; i < NBR_THREADS * 2; i++) {
-			CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) );
-		}
-		
-		/* Synchronize everyone */
-		{
-			int ret = pthread_barrier_wait(&bar);
-			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-				CHECK( 0, ret);
-			} else {
-				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* for trace only */
-			}
-		}
-		
-		/* Now post all the messages */
-		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
-			msg = msgs[i];
-			CHECK( 0, fd_fifo_post(queue, &msg) );
-		}
-		
-		/* Join all threads. This blocks if messages are lost... */
-		for (i=0; i < NBR_THREADS * 2; i++) {
-			CHECK( 0, pthread_join( thr[i], NULL ) );
-		}
-		
-		/* Check the count of the queue is back to 0 */
-		CHECK( 0, fd_fifo_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* Destroy this queue and the messages */
-		CHECK( 0, fd_fifo_del(&queue) );
-		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
-			CHECK( 0, fd_msg_free(  msgs[i] ) );
-		}
-	}
-	
-	/* Test thread cancelation */
-	{
-		struct fifo      	*queue = NULL;
-		pthread_barrier_t	 bar;
-		struct test_data	 td;
-		pthread_t		 th;
-		
-		/* Create the queue */
-		CHECK( 0, fd_fifo_new(&queue) );
-		
-		/* Create the barrier */
-		CHECK( 0, pthread_barrier_init(&bar, NULL, 2) );
-		
-		/* Initialize the ts */
-		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
-		ts.tv_sec += 2; /* Set the timeout to 2 second */
-		
-		/* Initialize the test data structures */
-		td.queue = queue;
-		td.bar = &bar;
-		td.ts  = &ts;
-		td.nbr = 1;
-		
-		/* Create the thread */
-		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
-		
-		/* Wait for the thread to be running */
-		{
-			int ret = pthread_barrier_wait(&bar);
-			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-				CHECK( 0, ret);
-			} else {
-				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
-			}
-		}
-		
-		/* Now cancel the thread */
-		CHECK( 0, pthread_cancel( th ) );
-		
-		/* Join it */
-		CHECK( 0, pthread_join( th, NULL ) );
-		
-		/* Do the same with the other function */
-		td.ts  = NULL;
-		
-		/* Create the thread */
-		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
-		
-		/* Wait for the thread to be running */
-		{
-			int ret = pthread_barrier_wait(&bar);
-			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-				CHECK( 0, ret);
-			} else {
-				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
-			}
-		}
-		
-		/* Now cancel the thread */
-		CHECK( 0, pthread_cancel( th ) );
-		
-		/* Join it */
-		CHECK( 0, pthread_join( th, NULL ) );
-		
-		/* Destroy the queue */
-		CHECK( 0, fd_fifo_del(&queue) );
-	}
-	
-	/* Test the threashold function */
-	{
-		struct fifo * queue = NULL;
-		int i;
-		struct msg * msg  = NULL;
-		
-		/* Create the queue */
-		CHECK( 0, fd_fifo_new(&queue) );
-		
-		/* Prepare the test data */
-		memset(&thrh_td, 0, sizeof(thrh_td));
-		thrh_td.queue = queue;
-		
-		/* Set the thresholds for the queue */
-		CHECK( 0, fd_fifo_setthrhd ( queue, NULL, 6, thrh_cb_h, 4, thrh_cb_l ) );
-		
-		/* Post 5 messages, no cb must be called. */
-		for (i=0; i<5; i++) {
-			msg = msg1;
-			CHECK( 0, fd_fifo_post(queue, &msg) );
-		} /* 5 msg in queue */
-		CHECK( 0, thrh_td.h_calls );
-		CHECK( 0, thrh_td.l_calls );
-		
-		/* Get all these messages, and check again */
-		for (i=0; i<5; i++) {
-			CHECK( 0, fd_fifo_get(queue, &msg) );
-		} /* 0 msg in queue */
-		CHECK( 0, thrh_td.h_calls );
-		CHECK( 0, thrh_td.l_calls );
-		
-		/* Now, post 6 messages, the high threashold */
-		for (i=0; i<6; i++) {
-			msg = msg1;
-			CHECK( 0, fd_fifo_post(queue, &msg) );
-		} /* 6 msg in queue */
-		CHECK( 1, thrh_td.h_calls );
-		CHECK( 0, thrh_td.l_calls );
-		
-		/* Remove 2 messages, to reach the low threshold */
-		for (i=0; i<2; i++) {
-			CHECK( 0, fd_fifo_get(queue, &msg) );
-		} /* 4 msg in queue */
-		CHECK( 1, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		
-		/* Come again at the high threshold */
-		for (i=0; i<2; i++) {
-			msg = msg1;
-			CHECK( 0, fd_fifo_post(queue, &msg) );
-		} /* 6 msg in queue */
-		CHECK( 2, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		
-		/* Suppose the queue continues to grow */
-		for (i=0; i<6; i++) {
-			msg = msg1;
-			CHECK( 0, fd_fifo_post(queue, &msg) );
-		} /* 12 msg in queue */
-		CHECK( 3, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		for (i=0; i<5; i++) {
-			msg = msg1;
-			CHECK( 0, fd_fifo_post(queue, &msg) );
-		} /* 17 msg in queue */
-		CHECK( 3, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		
-		/* Now the queue goes back to 0 messages */
-		for (i=0; i<17; i++) {
-			CHECK( 0, fd_fifo_get(queue, &msg) );
-		} /* 0 msg in queue */
-		CHECK( 3, thrh_td.h_calls );
-		CHECK( 3, thrh_td.l_calls );
-		
-		/* We're done for this test */
-		CHECK( 0, fd_fifo_del(&queue) );
-	}
-	
-	/* Delete the messages */
-	CHECK( 0, fd_msg_free( msg1 ) );
-	CHECK( 0, fd_msg_free( msg2 ) );
-	CHECK( 0, fd_msg_free( msg3 ) );
-
-	/* That's all for the tests yet */
-	PASSTEST();
-} 
--- a/freeDiameter/tests/tests.h	Thu Sep 24 14:01:48 2009 +0900
+++ b/freeDiameter/tests/tests.h	Fri Sep 25 16:12:08 2009 +0900
@@ -103,7 +103,7 @@
 	CHECK( 0, fd_lib_init() );				\
 	fd_log_threadname(basename(__FILE__));			\
 	CHECK( 0, fd_conf_init() );				\
-	CHECK( 0, fd_dict_base_protocol(fd_g_config->g_dict) );	\
+	CHECK( 0, fd_dict_base_protocol(fd_g_config->cnf_dict) );	\
 	parse_cmdline(argc, argv);				\
 }
 
--- a/include/freeDiameter/freeDiameter.h	Thu Sep 24 14:01:48 2009 +0900
+++ b/include/freeDiameter/freeDiameter.h	Fri Sep 25 16:12:08 2009 +0900
@@ -42,54 +42,65 @@
 
 /* Structure to hold the configuration of the freeDiameter daemon */
 struct fd_config {
-	int		 eyec;		/* Eye catcher: EYEC_CONFIG */
-	char		*conf_file;	/* Configuration file to parse, default is DEFAULT_CONF_FILE */
+	int		 cnf_eyec;	/* Eye catcher: EYEC_CONFIG */
+			#define	EYEC_CONFIG	0xC011F16
+	
+	char		*cnf_file;	/* Configuration file to parse, default is DEFAULT_CONF_FILE */
+	
+	char   		*cnf_diamid;	/* Diameter Identity of the local peer (FQDN -- UTF-8) */
+	size_t		 cnf_diamid_len;	/* length of the previous string */
+	char		*cnf_diamrlm;	/* Diameter realm of the local peer, default to realm part of diam_id */
+	size_t		 cnf_diamrlm_len;/* length of the previous string */
 	
-	char   		*diam_id;	/* Diameter Identity of the local peer (FQDN -- UTF-8) */
-	size_t		 diam_id_len;	/* length of the previous string */
-	char		*diam_realm;	/* Diameter realm of the local peer, default to realm part of diam_id */
-	size_t		 diam_realm_len;/* length of the previous string */
+	unsigned int	 cnf_timer_tc;	/* The value in seconds of the default Tc timer */
+	unsigned int 	 cnf_timer_tw;	/* The value in seconds of the default Tw timer */
 	
-	uint16_t	 loc_port;	/* the local port for legacy Diameter (default: 3868) in host byte order */
-	uint16_t	 loc_port_tls;	/* the local port for Diameter/TLS (default: 3869) in host byte order */
-	uint16_t	 loc_sctp_str;	/* default max number of streams for SCTP associations (def: 30) */
-	struct fd_list	 loc_endpoints;	/* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all) */
+	uint16_t	 cnf_port;	/* the local port for legacy Diameter (default: 3868) in host byte order */
+	uint16_t	 cnf_port_tls;	/* the local port for Diameter/TLS (default: 3869) in host byte order */
+	uint16_t	 cnf_sctp_str;	/* default max number of streams for SCTP associations (def: 30) */
+	struct fd_list	 cnf_endpoints;	/* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all) */
+	struct fd_list	 cnf_apps;	/* Applications locally supported (except relay, see flags). Use fd_disp_app_support to add one. list of struct fd_app. */
 	struct {
+		unsigned no_fwd : 1;	/* the peer does not relay messages (0xffffff app id) */
 		unsigned no_ip4 : 1;	/* disable IP */
 		unsigned no_ip6 : 1;	/* disable IPv6 */
 		unsigned no_tcp : 1;	/* disable use of TCP */
 		unsigned no_sctp: 1;	/* disable the use of SCTP */
 		unsigned pr_tcp	: 1;	/* prefer TCP over SCTP */
 		unsigned tls_alg: 1;	/* TLS algorithm for initiated cnx. 0: separate port. 1: inband-security (old) */
-		unsigned no_fwd : 1;	/* the peer does not relay messages (0xffffff app id) */
-	} 		 flags;
-	
-	unsigned int	 timer_tc;	/* The value in seconds of the default Tc timer */
-	unsigned int 	 timer_tw;	/* The value in seconds of the default Tw timer */
+	} 		 cnf_flags;
 	
-	uint32_t	 or_state_id;	/* The value to use in Origin-State-Id, default to random value */
-	struct dictionary *g_dict;	/* pointer to the global dictionary */
-	struct fifo	  *g_fifo_main;	/* FIFO queue of events in the daemon main (struct fd_event items) */
+	uint32_t	 cnf_orstateid;	/* The value to use in Origin-State-Id, default to random value */
+	struct dictionary *cnf_dict;	/* pointer to the global dictionary */
+	struct fifo	  *cnf_main_ev;	/* events for the daemon's main (struct fd_event items) */
 };
-
-#define	EYEC_CONFIG	0xC011F16
-
-/* The pointer to access the global configuration, initalized in main */
-extern struct fd_config *fd_g_config;
+extern struct fd_config *fd_g_config; /* The pointer to access the global configuration, initalized in main */
 
 /* Endpoints */
 struct fd_endpoint {
-	struct fd_list  chain;	/* link in loc_endpoints list */
+	struct fd_list  chain;	/* link in cnf_endpoints list */
 	sSS		ss;	/* the socket information. */
 };
 
+/* Applications */
+struct fd_app {
+	struct fd_list	 chain;	/* link in cnf_apps list. List ordered by appid. */
+	struct {
+		unsigned auth   : 1;
+		unsigned acct   : 1;
+		unsigned common : 1;
+	}		 flags;
+	vendor_id_t	 vndid; /* if not 0, Vendor-Specific-App-Id AVP will be used */
+	application_id_t appid;	/* The identifier of the application */
+};
+	
+
 /* Events */
 struct fd_event {
 	int	 code; /* codespace depends on the queue */
 	void    *data;
 };
 
-/* send an event */
 static __inline__ int fd_event_send(struct fifo *queue, int code, void * data)
 {
 	struct fd_event * ev;
@@ -99,7 +110,6 @@
 	CHECK_FCT( fd_fifo_post(queue, &ev) );
 	return 0;
 }
-/* receive an event */
 static __inline__ int fd_event_get(struct fifo *queue, int *code, void ** data)
 {
 	struct fd_event * ev;
@@ -112,6 +122,98 @@
 	return 0;
 }
 
+/* Events codespace for fd_g_config->cnf_main_ev */
+enum {
+	FDEV_TERMINATE = 1000,	/* request to terminate */
+	FDEV_DUMP_DICT,		/* Dump the content of the dictionary */
+	FDEV_DUMP_EXT,		/* Dump state of extensions */
+	FDEV_DUMP_QUEUES,	/* Dump the message queues */
+	FDEV_DUMP_CONFIG,	/* Dump the configuration */
+	FDEV_DUMP_PEERS		/* Dump the list of peers */
+};
+
+
+
+/***************************************/
+/*   Peers information                 */
+/***************************************/
+
+/* States of a peer */
+enum peer_state {
+	/* Stable states */
+	STATE_DISABLED = 1,	/* No connexion must be attempted / only this state means that the peer PSM thread is not running */
+	STATE_OPEN,		/* Connexion established */
+	
+	/* Peer state machine */
+	STATE_CLOSED,		/* No connection established, will re-attempt after TcTimer. */
+	STATE_CLOSING,		/* the connection is being shutdown (DPR/DPA in progress) */
+	STATE_WAITCNXACK,	/* Attempting to establish transport-level connection */
+	STATE_WAITCNXACK_ELEC,	/* Received a CER from this same peer on an incoming connection (other peer object), while we were waiting for cnx ack */
+	STATE_WAITCEA,		/* Connection established, CER sent, waiting for CEA */
+	/* STATE_WAITRETURNS_ELEC, */	/* This state is not stable and therefore deprecated:
+				   We have sent a CER on our initiated connection, and received a CER from the remote peer on another connection. Election.
+				   If we win the election, we must disconnect the initiated connection and send a CEA on the other => we go to OPEN state.
+				   If we lose, we disconnect the other connection (receiver) and fallback to WAITCEA state. */
+	
+	/* Failover state machine */
+	STATE_SUSPECT,		/* A DWR was sent and not answered within TwTime. Failover in progress. */
+	STATE_REOPEN		/* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */
+};
+extern char *peer_state_str[];
+
+/* Information about a remote peer, used both for query and for creating a new entry */
+struct peer_info {
+	
+	/* This information is always there */
+	char * pi_diamid;	/* UTF-8, \0 terminated. The Diameter Identity of the remote peer */
+	char * pi_realm;	/* idem, its realm. */
+	
+	/* Flags */
+	struct {
+		#define PI_PROT_DEFAULT	0	/* Use the default algorithm configured for the host */
+		#define PI_PROT_TCP	1
+		#define PI_PROT_SCTP	2
+		unsigned	proto :2;
+		
+		#define PI_SEC_DEFAULT	0	/* The default behavior configured for the host */
+		#define PI_SEC_NONE	1	/* Transparent security with this peer (IPsec) */
+		#define PI_SEC_TLS_NEW	2	/* New TLS security (dedicated port protecting also CER/CEA) */
+		#define PI_SEC_TLS_OLD	3	/* Old TLS security (inband on default port) */
+		unsigned	sec :2;
+		
+		#define PI_EXP_DEFAULT	0
+		#define PI_EXP_NONE	1	/* the peer entry does not expire */
+		#define PI_EXP_INACTIVE	2	/* the peer entry expires after pi_lft seconds without activity */
+		#define PI_EXP_LIFETIME	3	/* the peer SA information is destroyed after lft seconds (example: DNS timeout) */
+		unsigned	exp :2;
+		
+		/* Following flags are read-only and received from remote peer */
+		#define PI_INB_NONE	1	/* Remote peer advertised inband-sec-id 0 (None) */
+		#define PI_INB_TLS	2	/* Remote peer advertised inband-sec-id 1 (TLS) */
+		unsigned	inband :2;	/* This is only meaningful with pi_flags.sec == 3 */
+		
+		unsigned	relay :1;	/* The remote peer advertized the relay application */		
+	} pi_flags;
+	
+	/* Additional parameters */
+	uint32_t 	pi_lft;		/* lifetime of entry without activity (except watchdogs) (see pi_flags.exp definition) */
+	uint16_t	pi_streams; 	/* number of streams for SCTP. 0 = default */
+	uint16_t	pi_port; 	/* port to connect to. 0: default. */
+	int		pi_tctimer; 	/* use this value for TcTimer instead of global, if != 0 */
+	int		pi_twtimer; 	/* use this value for TwTimer instead of global, if != 0 */
+	
+	struct fd_list	pi_endpoints;	/* Endpoint(s) of the remote peer (discovered or advertized). list of struct fd_endpoint. DNS resolved if empty. */
+	
+	/* The remaining information is read-only, not used for peer creation */
+	enum peer_state	pi_state;
+	uint32_t	pi_vendorid;	/* Content of the Vendor-Id AVP, or 0 by default */
+	uint32_t	pi_orstate;	/* Origin-State-Id value */
+	char *		pi_prodname;	/* copy of UTF-8 Product-Name AVP (\0 terminated) */
+	uint32_t	pi_firmrev;	/* Content of the Firmware-Revision AVP */
+	struct fd_list	pi_apps;	/* applications advertised by the remote peer, except relay (pi_flags.relay) */
+};
+
+
 /***************************************/
 /*   Sending a message on the network  */
 /***************************************/
@@ -157,7 +259,6 @@
  *
  * PARAMETERS:
  *  msg		: A msg object -- it must be an answer.
- *  dict	: dictionary to use for AVP definitions
  *  rescode	: The name of the returned error code (ex: "DIAMETER_INVALID_AVP")
  *  errormsg    : (optional) human-readable error message to put in Error-Message AVP
  *  optavp	: (optional) If provided, the content will be put inside a Failed-AVP
@@ -172,10 +273,10 @@
  *  0      	: Operation complete.
  *  !0      	: an error occurred.
  */
-int fd_msg_rescode_set( struct msg * msg, struct dictionary * dict, char * rescode, char * errormsg, struct avp * optavp, int type_id );
+int fd_msg_rescode_set( struct msg * msg, char * rescode, char * errormsg, struct avp * optavp, int type_id );
 
-/* The following functions are used to achieve frequent operations on the messages */
-int fd_msg_add_origin ( struct msg * msg, struct dictionary * dict, int osi ); /* Add Origin-Host, Origin-Realm, (if osi) Origin-State-Id AVPS at the end of the message */
+/* Add Origin-Host, Origin-Realm, (if osi) Origin-State-Id AVPS at the end of the message */
+int fd_msg_add_origin ( struct msg * msg, int osi ); 
 
 
 
@@ -183,17 +284,14 @@
 /*   Dispatch module, daemon's part    */
 /***************************************/
 
-enum {
-	DISP_APP_AUTH	= 1,
-	DISP_APP_ACCT	= 2
-};
 /*
  * FUNCTION:	fd_disp_app_support
  *
  * PARAMETERS:
  *  app		: The dictionary object corresponding to the Application.
  *  vendor	: (Optional) the dictionary object of a Vendor to claim support in Vendor-Specific-Application-Id
- *  flags	: Combination of DISP_APP_* flags.
+ *  auth	: Support auth app part.
+ *  acct	: Support acct app part.
  *
  * DESCRIPTION: 
  *   Registers an application to be advertized in CER/CEA exchanges.
@@ -204,7 +302,7 @@
  *  0      	: The application support is registered.
  *  EINVAL 	: A parameter is invalid.
  */
-int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int flags );
+int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct );
 
 /* Note: if we want to support capabilities updates, we'll have to add possibility to remove an app as well... */
 
--- a/include/freeDiameter/libfreeDiameter.h	Thu Sep 24 14:01:48 2009 +0900
+++ b/include/freeDiameter/libfreeDiameter.h	Fri Sep 25 16:12:08 2009 +0900
@@ -170,7 +170,7 @@
 	if ( TRACE_BOOL(level) ) {												\
 		char __buf[25];													\
 		char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-		fd_log_debug("\t | th:%-30s\t%s\tin %s@%s:%d\n"									\
+		fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"								\
 			  "\t%s|%*s" format "\n",  										\
 					__thn, fd_log_time(__buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,	\
 					(level < FULL)?"@":" ",level, "", ## args); 						\
@@ -2455,4 +2455,7 @@
 #define fd_fifo_timedget(queue, item, abstime) \
 	fd_fifo_timedget_int((queue), (void *)(item), (abstime))
 
+/* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */
+void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item));
+
 #endif /* _LIBFREEDIAMETER_H */
--- a/libfreeDiameter/CMakeLists.txt	Thu Sep 24 14:01:48 2009 +0900
+++ b/libfreeDiameter/CMakeLists.txt	Fri Sep 25 16:12:08 2009 +0900
@@ -6,11 +6,11 @@
 	libfD.h
 	dictionary.c
 	dispatch.c
+	fifo.c
 	init.c
 	lists.c
 	log.c
 	messages.c
-	queues.c
 	sessions.c
 	)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfreeDiameter/fifo.c	Fri Sep 25 16:12:08 2009 +0900
@@ -0,0 +1,430 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2008, 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.								 *
+*********************************************************************************************************/
+
+/* FIFO queues module.
+ *
+ * The threads that call these functions must be in the cancellation state PTHREAD_CANCEL_ENABLE and type PTHREAD_CANCEL_DEFERRED.
+ * This is the default state and type on thread creation.
+ *
+ * In order to destroy properly a queue, the application must:
+ *  -> shutdown any process that can add into the queue first.
+ *  -> pthread_cancel any thread that could be waiting on the queue.
+ *  -> consume any element that is in the queue, using fd_qu_tryget_int.
+ *  -> then destroy the queue using fd_mq_del.
+ */
+
+#include "libfD.h"
+
+/* Definition of a FIFO queue object */
+struct fifo {
+	int		eyec;	/* An eye catcher, also used to check a queue is valid. FIFO_EYEC */
+	
+	pthread_mutex_t	mtx;	/* Mutex protecting this queue */
+	pthread_cond_t	cond;	/* condition variable of the list */
+	
+	struct fd_list	list;	/* sentinel for the list of elements */
+	int		count;	/* number of objects in the list */
+	int		thrs;	/* number of threads waiting for a new element (when count is 0) */
+	
+	uint16_t	high;	/* High level threshold (see libfreeDiameter.h for details) */
+	uint16_t	low;	/* Low level threshhold */
+	void 		*data;	/* Opaque pointer for threshold callbacks */
+	void		(*h_cb)(struct fifo *, void **); /* The callbacks */
+	void		(*l_cb)(struct fifo *, void **);
+	int 		highest;/* The highest count value for which h_cb has been called */
+};
+
+/* The eye catcher value */
+#define FIFO_EYEC	0xe7ec1130
+
+/* Macro to check a pointer */
+#define CHECK_FIFO( _queue ) (( (_queue) != NULL) && ( (_queue)->eyec == FIFO_EYEC) )
+
+
+/* Create a new queue */
+int fd_fifo_new ( struct fifo ** queue )
+{
+	struct fifo * new;
+	
+	TRACE_ENTRY( "%p", queue );
+	
+	CHECK_PARAMS( queue );
+	
+	/* Create a new object */
+	CHECK_MALLOC( new = malloc (sizeof (struct fifo) )  );
+	
+	/* Initialize the content */
+	memset(new, 0, sizeof(struct fifo));
+	
+	new->eyec = FIFO_EYEC;
+	CHECK_POSIX( pthread_mutex_init(&new->mtx, NULL) );
+	CHECK_POSIX( pthread_cond_init(&new->cond, NULL) );
+	
+	fd_list_init(&new->list, NULL);
+	
+	/* We're done */
+	*queue = new;
+	return 0;
+}
+
+/* Dump the content of a queue */
+void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item))
+{
+	TRACE_ENTRY("%i %p %p %p", level, name, queue, dump_item);
+	
+	if (!TRACE_BOOL(level))
+		return;
+	
+	fd_log_debug("Dumping queue '%s' (%p):\n", name ?: "?", queue);
+	if (!CHECK_FIFO( queue )) {
+		fd_log_debug("  Queue invalid!\n");
+		if (queue)
+			fd_log_debug("  (%x != %x)\n", queue->eyec, FIFO_EYEC);
+		return;
+	}
+	
+	CHECK_POSIX_DO(  pthread_mutex_lock( &queue->mtx ), /* continue */  );
+	fd_log_debug("  %d elements in queue\n", queue->count);
+	fd_log_debug("  %d threads waiting\n", queue->thrs);
+	fd_log_debug("  thresholds: %d / %d, cb: %p / %p (%p), highest: %d\n",
+			queue->high, queue->low,
+			queue->h_cb, queue->l_cb, queue->data,
+			queue->highest);
+	
+	if (dump_item) {
+		struct fd_list * li;
+		int i = 0;
+		for (li = queue->list.next; li != &queue->list; li = li->next) {
+			fd_log_debug("  [%i] item %p in fifo %p:\n", i++, li->o, queue);
+			(*dump_item)(level, li->o);
+		}
+	}
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &queue->mtx ), /* continue */  );
+	
+}
+
+/* Delete a queue. It must be unused. */ 
+int fd_fifo_del ( struct fifo  ** queue )
+{
+	struct fifo * q;
+	
+	TRACE_ENTRY( "%p", queue );
+
+	CHECK_PARAMS( queue && CHECK_FIFO( *queue ) );
+	
+	q = *queue;
+	
+	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
+	
+	if ((q->count != 0) || (q->thrs != 0) || (q->data != NULL)) {
+		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %d, %p)", q->count, q->thrs, q->data);
+		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
+		return EINVAL;
+	}
+	
+	/* sanity check */
+	ASSERT(FD_IS_LIST_EMPTY(&q->list));
+	
+	/* Ok, now invalidate the queue */
+	q->eyec = 0xdead;
+	
+	/* And destroy it */
+	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
+	
+	CHECK_POSIX(  pthread_cond_destroy( &q->cond )  );
+	
+	CHECK_POSIX(  pthread_mutex_destroy( &q->mtx )  );
+	
+	free(q);
+	*queue = NULL;
+	
+	return 0;
+}
+
+/* Get the length of the queue */
+int fd_fifo_length ( struct fifo * queue, int * length )
+{
+	TRACE_ENTRY( "%p %p", queue, length );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && length );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Retrieve the count */
+	*length = queue->count;
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Done */
+	return 0;
+}
+
+/* alternate version with no error checking */
+int fd_fifo_length_noerr ( struct fifo * queue )
+{
+	if ( !CHECK_FIFO( queue ) )
+		return 0;
+	
+	return queue->count; /* Let's hope it's read atomically, since we are not locking... */
+}
+
+/* Set the thresholds of the queue */
+int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) )
+{
+	TRACE_ENTRY( "%p %p %hu %p %hu %p", queue, data, high, h_cb, low, l_cb );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && (high > low) && (queue->data == NULL) );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Save the values */
+	queue->high = high;
+	queue->low  = low;
+	queue->data = data;
+	queue->h_cb = h_cb;
+	queue->l_cb = l_cb;
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Done */
+	return 0;
+}
+
+/* Post a new item in the queue */
+int fd_fifo_post_int ( struct fifo * queue, void ** item )
+{
+	struct fd_list * new;
+	int call_cb = 0;
+	
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && *item );
+	
+	/* Create a new list item */
+	CHECK_MALLOC(  new = malloc (sizeof (struct fd_list))  );
+	
+	fd_list_init(new, *item);
+	*item = NULL;
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Add the new item at the end */
+	fd_list_insert_before( &queue->list, new);
+	queue->count++;
+	if (queue->high && ((queue->count % queue->high) == 0)) {
+		call_cb = 1;
+		queue->highest = queue->count;
+	}
+	
+	/* Signal if threads are asleep */
+	if (queue->thrs > 0) {
+		CHECK_POSIX(  pthread_cond_signal(&queue->cond)  );
+	}
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call high-watermark cb as needed */
+	if (call_cb && queue->h_cb)
+		(*queue->h_cb)(queue, &queue->data);
+	
+	/* Done */
+	return 0;
+}
+
+/* Pop the first item from the queue */
+static void * mq_pop(struct fifo * queue)
+{
+	void * ret = NULL;
+	struct fd_list * li;
+	
+	ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) );
+	
+	fd_list_unlink(li = queue->list.next);
+	queue->count--;
+	ret = li->o;
+	free(li);
+	
+	return ret;
+}
+
+/* Check if the low watermark callback must be called. */
+static __inline__ int test_l_cb(struct fifo * queue)
+{
+	if ((queue->high == 0) || (queue->low == 0) || (queue->l_cb == 0))
+		return 0;
+	
+	if (((queue->count % queue->high) == queue->low) && (queue->highest > queue->count)) {
+		queue->highest -= queue->high;
+		return 1;
+	}
+	
+	return 0;
+}
+
+/* Try poping an item */
+int fd_fifo_tryget_int ( struct fifo * queue, void ** item )
+{
+	int wouldblock = 0;
+	int call_cb = 0;
+	
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Check queue status */
+	if (queue->count > 0) {
+		/* There are elements in the queue, so pick the first one */
+		*item = mq_pop(queue);
+		call_cb = test_l_cb(queue);
+	} else {
+		wouldblock = 1;
+		*item = NULL;
+	}
+		
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call low watermark callback as needed */
+	if (call_cb)
+		(*queue->l_cb)(queue, &queue->data);
+	
+	/* Done */
+	return wouldblock ? EWOULDBLOCK : 0;
+}
+
+/* This handler is called when a thread is blocked on a queue, and cancelled */
+static void fifo_cleanup(void * queue)
+{
+	struct fifo * q = (struct fifo *)queue;
+	TRACE_ENTRY( "%p", queue );
+	
+	/* Check the parameter */
+	if ( ! CHECK_FIFO( q )) {
+		TRACE_DEBUG(INFO, "Invalid queue, skipping handler");
+		return;
+	}
+	
+	/* The thread has been cancelled, therefore it does not wait on the queue anymore */
+	q->thrs--;
+	
+	/* Now unlock the queue, and we're done */
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ),  /* nothing */  );
+	
+	/* End of cleanup handler */
+	return;
+}
+
+/* The internal function for fd_fifo_timedget and fd_fifo_get */
+static int fifo_tget ( struct fifo * queue, void ** item, int istimed, const struct timespec *abstime)
+{
+	int timedout = 0;
+	int call_cb = 0;
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && (abstime || !istimed) );
+	
+	/* Initialize the return value */
+	*item = NULL;
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+awaken:
+	/* Check queue status */
+	if (queue->count > 0) {
+		/* There are items in the queue, so pick the first one */
+		*item = mq_pop(queue);
+		call_cb = test_l_cb(queue);
+	} else {
+		int ret = 0;
+		/* We have to wait for a new item */
+		queue->thrs++ ;
+		pthread_cleanup_push( fifo_cleanup, queue);
+		if (istimed) {
+			ret = pthread_cond_timedwait( &queue->cond, &queue->mtx, abstime );
+		} else {
+			ret = pthread_cond_wait( &queue->cond, &queue->mtx );
+		}
+		pthread_cleanup_pop(0);
+		queue->thrs-- ;
+		if (ret == 0)
+			goto awaken;  /* test for spurious wake-ups */
+		
+		if (istimed && (ret == ETIMEDOUT)) {
+			timedout = 1;
+		} else {
+			/* Unexpected error condition (means we need to debug) */
+			ASSERT( ret == 0 /* never true */ );
+		}
+	}
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call low watermark callback as needed */
+	if (call_cb)
+		(*queue->l_cb)(queue, &queue->data);
+	
+	/* Done */
+	return timedout ? ETIMEDOUT : 0;
+}
+
+/* Get the next available item, block until there is one */
+int fd_fifo_get_int ( struct fifo * queue, void ** item )
+{
+	TRACE_ENTRY( "%p %p", queue, item );
+	return fifo_tget(queue, item, 0, NULL);
+}
+
+/* Get the next available item, block until there is one, or the timeout expires */
+int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime )
+{
+	TRACE_ENTRY( "%p %p %p", queue, item, abstime );
+	return fifo_tget(queue, item, 1, abstime);
+}
+
--- a/libfreeDiameter/queues.c	Thu Sep 24 14:01:48 2009 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,394 +0,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2008, 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.								 *
-*********************************************************************************************************/
-
-/* FIFO queues module.
- *
- * The threads that call these functions must be in the cancellation state PTHREAD_CANCEL_ENABLE and type PTHREAD_CANCEL_DEFERRED.
- * This is the default state and type on thread creation.
- *
- * In order to destroy properly a queue, the application must:
- *  -> shutdown any process that can add into the queue first.
- *  -> pthread_cancel any thread that could be waiting on the queue.
- *  -> consume any element that is in the queue, using fd_qu_tryget_int.
- *  -> then destroy the queue using fd_mq_del.
- */
-
-#include "libfD.h"
-
-/* Definition of a FIFO queue object */
-struct fifo {
-	int		eyec;	/* An eye catcher, also used to check a queue is valid. FIFO_EYEC */
-	
-	pthread_mutex_t	mtx;	/* Mutex protecting this queue */
-	pthread_cond_t	cond;	/* condition variable of the list */
-	
-	struct fd_list	list;	/* sentinel for the list of elements */
-	int		count;	/* number of objects in the list */
-	int		thrs;	/* number of threads waiting for a new element (when count is 0) */
-	
-	uint16_t	high;	/* High level threshold (see libfreeDiameter.h for details) */
-	uint16_t	low;	/* Low level threshhold */
-	void 		*data;	/* Opaque pointer for threshold callbacks */
-	void		(*h_cb)(struct fifo *, void **); /* The callbacks */
-	void		(*l_cb)(struct fifo *, void **);
-	int 		highest;/* The highest count value for which h_cb has been called */
-};
-
-/* The eye catcher value */
-#define FIFO_EYEC	0xe7ec1130
-
-/* Macro to check a pointer */
-#define CHECK_FIFO( _queue ) (( (_queue) != NULL) && ( (_queue)->eyec == FIFO_EYEC) )
-
-
-/* Create a new queue */
-int fd_fifo_new ( struct fifo ** queue )
-{
-	struct fifo * new;
-	
-	TRACE_ENTRY( "%p", queue );
-	
-	CHECK_PARAMS( queue );
-	
-	/* Create a new object */
-	CHECK_MALLOC( new = malloc (sizeof (struct fifo) )  );
-	
-	/* Initialize the content */
-	memset(new, 0, sizeof(struct fifo));
-	
-	new->eyec = FIFO_EYEC;
-	CHECK_POSIX( pthread_mutex_init(&new->mtx, NULL) );
-	CHECK_POSIX( pthread_cond_init(&new->cond, NULL) );
-	
-	fd_list_init(&new->list, NULL);
-	
-	/* We're done */
-	*queue = new;
-	return 0;
-}
-
-/* Delete a queue. It must be unused. */ 
-int fd_fifo_del ( struct fifo  ** queue )
-{
-	struct fifo * q;
-	
-	TRACE_ENTRY( "%p", queue );
-
-	CHECK_PARAMS( queue && CHECK_FIFO( *queue ) );
-	
-	q = *queue;
-	
-	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
-	
-	if ((q->count != 0) || (q->thrs != 0) || (q->data != NULL)) {
-		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %d, %p)", q->count, q->thrs, q->data);
-		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
-		return EINVAL;
-	}
-	
-	/* sanity check */
-	ASSERT(FD_IS_LIST_EMPTY(&q->list));
-	
-	/* Ok, now invalidate the queue */
-	q->eyec = 0xdead;
-	
-	/* And destroy it */
-	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
-	
-	CHECK_POSIX(  pthread_cond_destroy( &q->cond )  );
-	
-	CHECK_POSIX(  pthread_mutex_destroy( &q->mtx )  );
-	
-	free(q);
-	*queue = NULL;
-	
-	return 0;
-}
-
-/* Get the length of the queue */
-int fd_fifo_length ( struct fifo * queue, int * length )
-{
-	TRACE_ENTRY( "%p %p", queue, length );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_FIFO( queue ) && length );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Retrieve the count */
-	*length = queue->count;
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Done */
-	return 0;
-}
-
-/* alternate version with no error checking */
-int fd_fifo_length_noerr ( struct fifo * queue )
-{
-	if ( !CHECK_FIFO( queue ) )
-		return 0;
-	
-	return queue->count; /* Let's hope it's read atomically, since we are not locking... */
-}
-
-/* Set the thresholds of the queue */
-int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) )
-{
-	TRACE_ENTRY( "%p %p %hu %p %hu %p", queue, data, high, h_cb, low, l_cb );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_FIFO( queue ) && (high > low) && (queue->data == NULL) );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Save the values */
-	queue->high = high;
-	queue->low  = low;
-	queue->data = data;
-	queue->h_cb = h_cb;
-	queue->l_cb = l_cb;
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Done */
-	return 0;
-}
-
-/* Post a new item in the queue */
-int fd_fifo_post_int ( struct fifo * queue, void ** item )
-{
-	struct fd_list * new;
-	int call_cb = 0;
-	
-	TRACE_ENTRY( "%p %p", queue, item );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_FIFO( queue ) && item && *item );
-	
-	/* Create a new list item */
-	CHECK_MALLOC(  new = malloc (sizeof (struct fd_list))  );
-	
-	fd_list_init(new, *item);
-	*item = NULL;
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Add the new item at the end */
-	fd_list_insert_before( &queue->list, new);
-	queue->count++;
-	if (queue->high && ((queue->count % queue->high) == 0)) {
-		call_cb = 1;
-		queue->highest = queue->count;
-	}
-	
-	/* Signal if threads are asleep */
-	if (queue->thrs > 0) {
-		CHECK_POSIX(  pthread_cond_signal(&queue->cond)  );
-	}
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Call high-watermark cb as needed */
-	if (call_cb && queue->h_cb)
-		(*queue->h_cb)(queue, &queue->data);
-	
-	/* Done */
-	return 0;
-}
-
-/* Pop the first item from the queue */
-static void * mq_pop(struct fifo * queue)
-{
-	void * ret = NULL;
-	struct fd_list * li;
-	
-	ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) );
-	
-	fd_list_unlink(li = queue->list.next);
-	queue->count--;
-	ret = li->o;
-	free(li);
-	
-	return ret;
-}
-
-/* Check if the low watermark callback must be called. */
-static __inline__ int test_l_cb(struct fifo * queue)
-{
-	if ((queue->high == 0) || (queue->low == 0) || (queue->l_cb == 0))
-		return 0;
-	
-	if (((queue->count % queue->high) == queue->low) && (queue->highest > queue->count)) {
-		queue->highest -= queue->high;
-		return 1;
-	}
-	
-	return 0;
-}
-
-/* Try poping an item */
-int fd_fifo_tryget_int ( struct fifo * queue, void ** item )
-{
-	int wouldblock = 0;
-	int call_cb = 0;
-	
-	TRACE_ENTRY( "%p %p", queue, item );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_FIFO( queue ) && item );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Check queue status */
-	if (queue->count > 0) {
-		/* There are elements in the queue, so pick the first one */
-		*item = mq_pop(queue);
-		call_cb = test_l_cb(queue);
-	} else {
-		wouldblock = 1;
-		*item = NULL;
-	}
-		
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Call low watermark callback as needed */
-	if (call_cb)
-		(*queue->l_cb)(queue, &queue->data);
-	
-	/* Done */
-	return wouldblock ? EWOULDBLOCK : 0;
-}
-
-/* This handler is called when a thread is blocked on a queue, and cancelled */
-static void fifo_cleanup(void * queue)
-{
-	struct fifo * q = (struct fifo *)queue;
-	TRACE_ENTRY( "%p", queue );
-	
-	/* Check the parameter */
-	if ( ! CHECK_FIFO( q )) {
-		TRACE_DEBUG(INFO, "Invalid queue, skipping handler");
-		return;
-	}
-	
-	/* The thread has been cancelled, therefore it does not wait on the queue anymore */
-	q->thrs--;
-	
-	/* Now unlock the queue, and we're done */
-	CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ),  /* nothing */  );
-	
-	/* End of cleanup handler */
-	return;
-}
-
-/* The internal function for fd_fifo_timedget and fd_fifo_get */
-static int fifo_tget ( struct fifo * queue, void ** item, int istimed, const struct timespec *abstime)
-{
-	int timedout = 0;
-	int call_cb = 0;
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_FIFO( queue ) && item && (abstime || !istimed) );
-	
-	/* Initialize the return value */
-	*item = NULL;
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-awaken:
-	/* Check queue status */
-	if (queue->count > 0) {
-		/* There are items in the queue, so pick the first one */
-		*item = mq_pop(queue);
-		call_cb = test_l_cb(queue);
-	} else {
-		int ret = 0;
-		/* We have to wait for a new item */
-		queue->thrs++ ;
-		pthread_cleanup_push( fifo_cleanup, queue);
-		if (istimed) {
-			ret = pthread_cond_timedwait( &queue->cond, &queue->mtx, abstime );
-		} else {
-			ret = pthread_cond_wait( &queue->cond, &queue->mtx );
-		}
-		pthread_cleanup_pop(0);
-		queue->thrs-- ;
-		if (ret == 0)
-			goto awaken;  /* test for spurious wake-ups */
-		
-		if (istimed && (ret == ETIMEDOUT)) {
-			timedout = 1;
-		} else {
-			/* Unexpected error condition (means we need to debug) */
-			ASSERT( ret == 0 /* never true */ );
-		}
-	}
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Call low watermark callback as needed */
-	if (call_cb)
-		(*queue->l_cb)(queue, &queue->data);
-	
-	/* Done */
-	return timedout ? ETIMEDOUT : 0;
-}
-
-/* Get the next available item, block until there is one */
-int fd_fifo_get_int ( struct fifo * queue, void ** item )
-{
-	TRACE_ENTRY( "%p %p", queue, item );
-	return fifo_tget(queue, item, 0, NULL);
-}
-
-/* Get the next available item, block until there is one, or the timeout expires */
-int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime )
-{
-	TRACE_ENTRY( "%p %p %p", queue, item, abstime );
-	return fifo_tget(queue, item, 1, abstime);
-}
-
"Welcome to our mercurial repository"