Initial commit

Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_diameap/CMakeLists.txt b/extensions/app_diameap/CMakeLists.txt
new file mode 100644
index 0000000..f463022
--- /dev/null
+++ b/extensions/app_diameap/CMakeLists.txt
@@ -0,0 +1,56 @@
+# The Diameter EAP Application extension
+PROJECT("Diameter EAP Application extension" C)
+
+# Find MySQL 
+FIND_PACKAGE(MySQL REQUIRED)
+FIND_PACKAGE(Gcrypt REQUIRED)
+INCLUDE_DIRECTORIES(${MySQL_INCLUDE_DIR})
+
+# Parse plugins
+ADD_SUBDIRECTORY(plugins)
+
+# Parser 
+BISON_FILE(diameap.y)
+FLEX_FILE(diameap.l)
+SET_SOURCE_FILES_PROPERTIES(lex.diameap.c diameap.tab.c PROPERTIES COMPILE_FLAGS "-I \"${CMAKE_CURRENT_SOURCE_DIR}\"")
+
+
+set( diameapsrc
+    diameap_defs.h
+    diameap.h
+    diameap_server.h
+    diameap_plugins.h        
+    diameap_eap.h
+    plugins.h
+    diameap_eappacket.h
+    diameap_user.h
+    diameap.tab.h
+    diameap.tab.c
+    lex.diameap.c        
+    diameap.c
+    diameap_server.c
+    diameap_plugins.c
+    diameap_init.c
+    diameap_common.h
+    diameap_eappacket.c
+    libdiameap.h
+    diameap_eap.c
+    diameap_mysql.h
+    diameap_mysql.c
+    diameap_tls.h
+    diameap_tls.c
+    libcrypt.h
+    libcrypt.c
+    diameap_user.c
+)
+
+FD_ADD_EXTENSION(app_diameap ${diameapsrc})
+
+TARGET_LINK_LIBRARIES(app_diameap ${GCRYPT_LIBRARY} ${GNUTLS_LIBRARIES} ${MySQL_LIBRARY} )
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_diameap
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-eap-server)
diff --git a/extensions/app_diameap/LICENSE b/extensions/app_diameap/LICENSE
new file mode 100644
index 0000000..cfe48d2
--- /dev/null
+++ b/extensions/app_diameap/LICENSE
@@ -0,0 +1,35 @@
+ Software License Agreement (BSD License)
+ Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+
+ Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ All rights reserved.
+
+ Redistribution and use of this software in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. All advertising materials mentioning features or use of this software
+    must display the following acknowledgement:
+    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+
+ 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+ 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.
+
diff --git a/extensions/app_diameap/README b/extensions/app_diameap/README
new file mode 100644
index 0000000..fad85bd
--- /dev/null
+++ b/extensions/app_diameap/README
@@ -0,0 +1,119 @@
+DiamEAP (http://diameap.yagami.freediameter.net/)
+
+Copyright (c) 2009-2010 Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project.
+
+Author: Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+
+
+
+----- SUMMARY -----
+
+DiamEAP is an implementation of the Diameter Extensible Authentication Protocol (EAP) Application (RFC 4072).
+The Diameter protocol is a AAA protocol to securely carry Authentication, Authorization and Accounting informations between the AAA client and the AAA server.
+Diameter EAP Application is a Diameter application that supports authentication using Extensible Authentication Protocol (RFC 3748).  
+
+DiamEAP is designed to be extensible so that any new EAP method can be implemented separately as a shared library called 'EAP method plug-in'.
+Currently, DiamEAP comprises two EAP Methods plug-ins: 
+	- EAP MD5 plug-in : implementation of EAP-MD5 authentication method.
+	- EAP TLS plug-in : implementation of EAP-TLS authentication method .
+
+Other EAP methods are scheduled to be added in future releases. 	
+	
+DiamEAP is an extension for freeDiameter. Visit http://www.freediameter.net/ for more information on freeDiameter project.
+
+For more information on DiamEAP project, visit http://diameap.yagami.freediameter.net/
+
+
+
+----- REQUIREMENTS -----
+
+Some packages are required to compile DiamEAP from source.
+
+If you will install DiamEAP on Debian or Ubuntu system install the following packages: cmake flex bison libgnutls-dev libgcrypt-dev libmysqlclient-dev
+
+	$ sudo apt-get install cmake flex bison libgnutls-dev libgcrypt-dev libmysqlclient-dev
+
+
+
+----- INSTALLATION -----
+
+1- Add DiamEAP extension to freeDiameter. 
+	See freeDiameter documentation (http://www.freediameter.net/)
+
+2-Create a new MySQL database and add tables using the sql script 'diameap.sql'.
+
+3- Edit the extensions/CMakeList.txt file to add DiamEAP to freeDiameter.
+
+Add the following lines:
+   
+	  OPTION(BUILD_APP_DIAMEAP "Build DiamEAP? (Diameter EAP Application - RFC 4072)" OFF)
+	 	IF (BUILD_APP_DIAMEAP)
+	 	   ADD_SUBDIRECTORY(app_diameap)
+	 	ENDIF (BUILD_APP_DIAMEAP)
+
+Note: you can enable DiamEAP to be built with freeDiameter by setting the BUILD_APP_DIAMEAP to ON. If you enable it here you don't need to enable it when building freeDiameter.
+
+4- Enable DiamEAP by enabling BUILD_APP_DIAMEAP option with CMake:
+
+cmake -DBUILD_APP_DIAMEAP:BOOl=ON ../
+
+
+
+----- CONFIGURATION -----
+
+DiamEAP requires a configuration file to start the DiamEAP server. 
+It is advised to start by a copy of the sample file, and customize the configuration to fit your needs.
+A sample configuration file 'diameap.conf.sample' can be find in extensions/app_diameap/ or in doc/ folder of freeDiameter. 
+The file 'diameap.conf.sample' contains a description of all parameters that can be added to the DiamEAP configuration file.
+
+*Specify connection parameters to DiamEAP MySQL database:
+- username and password to connect to the MySQL Server
+- database server : address to MySQL server.
+- database name :  database for DiamEAP.
+
+Example:
+
+DiamEAP_MySQL = "UserName" , "MyPassword" , "localhost" , "drupal_ui";
+
+
+*Add EAP Method plug-ins to be loaded with DiamEAP server. Note that EAP Identity must be add.
+
+Example:
+
+Load_plugin = "EAP MD5":4:0:"extensions/eap_md5.emp":"";
+Load_plugin = "EAP TLS":13:0:"extensions/eap_tls.emp":"doc/eap_tls_plugin.app_diameap.conf";
+
+
+* Enable Authorization with DiamEAP.
+
+You can enable DiamEAP to check authorization of authenticated users. To enable authorization set authorization to 1. ( by default disabled).
+
+
+* Multiple round trips timeout
+
+This parameter indicates the maximum number of seconds provides the user to answer to a Diameter-EAP-Request. (by default set to 30 seconds)
+
+
+* Invalid EAP Packets
+
+This parameter defines the maximum number of invalid EAP packets that can be received before rejecting the connection. (by default set to 5 packets)
+
+
+For more documentation on configuring DiamEAP, visit the documentation page of the project : http://diameap.yagami.freediameter.net/documentation
+
+
+
+----- COPYRIGHT -----
+
+See LICENSE file for legal information on this software.
+
+
+
+----- CONTACT -----
+
+Author: Souheil Ben Ayed (souheil@tera.ics.keio.ac.jp)
+
+
+Current maintainers:
+-Souheil Ben Ayed (Teraoka Laboratory of Keio University) 	
+	souheil@tera.ics.keio.ac.jp
diff --git a/extensions/app_diameap/diameap.c b/extensions/app_diameap/diameap.c
new file mode 100644
index 0000000..ac399cb
--- /dev/null
+++ b/extensions/app_diameap/diameap.c
@@ -0,0 +1,87 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "diameap_common.h"
+
+
+
+/* DiamEAP Configuration */
+static struct diameap_conf conf;
+struct diameap_conf * diameap_config = &conf;
+
+/* The entry point */
+static int diameap_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+
+	memset(diameap_config, 0, sizeof(struct diameap_conf));
+
+	/* Initialize configuration */
+	CHECK_FCT(diameap_init(conffile));
+
+	/* Start Diameter EAP Application (Back-end Authenticator ) */
+	CHECK_FCT(diameap_start_server());
+
+	/* Announce the support of Diameter EAP Application to other peers */
+	CHECK_FCT(fd_disp_app_support(dataobj_diameap_app, dataobj_diameap_ven, 1, 0));
+
+	LOG_D("%sDiameter EAP Application Extension started successfully.",DIAMEAP_EXTENSION);
+
+	return 0;
+}
+
+void fd_ext_fini(void)
+{
+	TRACE_DEBUG(FULL,"%sStopping the server",DIAMEAP_EXTENSION);
+	CHECK_FCT_DO(diameap_stop_server(),
+			{	TRACE_DEBUG(INFO,"%sStopping the server: Error occurred.",DIAMEAP_EXTENSION);});
+
+	if (db_conn)
+	{
+		TRACE_DEBUG(FULL,"%sDisconnecting from MySQL Server",DIAMEAP_EXTENSION);
+		diameap_mysql_disconnect();
+	}
+
+	TRACE_DEBUG(FULL,"%sUnloading EAP Methods plug-ins: Error occurred.",DIAMEAP_EXTENSION);
+	CHECK_FCT_DO(diameap_plugin_unload(),
+			{	TRACE_DEBUG(INFO,"%sUnloading EAP Methods plug-ins: Error occurred.",DIAMEAP_EXTENSION);});
+	return;
+}
+
+/* Define the entry point */
+EXTENSION_ENTRY("DiamEAP", diameap_main, "dict_eap")
+;
diff --git a/extensions/app_diameap/diameap.h b/extensions/app_diameap/diameap.h
new file mode 100644
index 0000000..b55b280
--- /dev/null
+++ b/extensions/app_diameap/diameap.h
@@ -0,0 +1,80 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_H_
+#define DIAMEAP_H_
+
+/* Structure to hold configuration of DiamEAP*/
+struct diameap_conf
+{
+	char *conffile; /* configuration file of the extension*/
+
+	int authorize; /* Set to 1 if provides Authorization. Otherwise set to 0. (by default set to 0)*/
+
+	u32 vendor_id; /* Vendor ID*/
+	u32 application_id; /* Diameter EAP Application ID. Value set to 5. */
+	u32 command_code; /* Diameter EAP Application Command Code. Value set to 268. */
+
+	char * diam_realm; /* Diameter realm of the peer */
+
+	/*Diameter EAP Server*/
+	int max_invalid_eap_packet;
+
+	//MySQL Database parameters
+
+	struct {
+		char *server;
+		char *user;
+		char *password;
+		char *database;
+	}db;
+
+	u32 multi_round_time_out;
+};
+
+/* The pointer to access DiamEAP configuration*/
+extern struct diameap_conf *diameap_config;
+
+/* Initialize the configuration of DiamEAP*/
+int diameap_init(char * conffile);
+
+/* parser */
+int diameapparse(struct diameap_conf * config);
+
+
+#endif /* DIAMEAP_H_ */
diff --git a/extensions/app_diameap/diameap.l b/extensions/app_diameap/diameap.l
new file mode 100644
index 0000000..1dcb470
--- /dev/null
+++ b/extensions/app_diameap/diameap.l
@@ -0,0 +1,128 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+
+/*Declarations and option settings*/
+%{
+#include <stdio.h>
+#include "diameap_common.h"
+#include "diameap.tab.h"
+ 
+#define YY_USER_ACTION { 						\
+	yylloc->first_line = yylloc->last_line = yylineno; \
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column += yyleng +1;	\
+	}	
+ 
+#define YY_NO_INPUT
+%}
+
+
+
+%option noyywrap
+%option yylineno
+%option bison-bridge 
+%option bison-locations
+%option nounput
+
+%%
+	/* List of patterns and actions */
+
+<*>\n			{				
+				yylloc->last_column=0; 
+				}
+
+<*>#.*$			{ }
+
+[ \t\n]+		{ 	
+			yylloc->last_column=0; 
+				/* ignore whitespace */ 
+			}
+
+\"([^\n\"]*)\"		{
+				yylval->str = strdup(yytext+1); /* Quoted String */
+				yylval->str[yyleng-2]='\0';
+				return iSTRING;
+			}
+
+
+[[:digit:]]+		{ 	/* Digital number */
+				yylval->val = atoi(yytext);
+				return NUM; /* Numeric value */ 
+			}
+
+(?i:"Load_Plugin")	{
+				return EAPMETHOD;
+			}
+
+(?i:"Authorization")		{ 
+				return AUTHORIZE;
+			}
+
+(?i:"DiamEAP_MySQL")		{ 
+				return DIAMEAP_MYSQL;
+			}
+			
+(?i:"MAX_Invalid_EAP_Packets")		{
+				return MAX_INVALID_EAP_PACKET;
+			}
+
+(?i:"Multi_Round_Time_Out")		{
+				return MULTI_ROUND_TIMEOUT;
+			}
+
+(?i:"Check_user_identity")		{
+				return CHECK_USER_IDENTITY;
+			}
+
+"="|";"|":"|","		{	
+				return yytext[0]; 
+			}
+
+	/* Unrecognized token or text */
+	
+<*>[[:alnum:]]+	 |					 
+<*>.	{ 
+				fprintf(stderr,"Unrecognized input text '%s'( on line %i column %i )\n", yytext, yylloc->first_line, yylloc->first_column); 
+			 	return LEX_ERROR; 
+			}
+
+%%
+/* Routines */
+
+
diff --git a/extensions/app_diameap/diameap.sql b/extensions/app_diameap/diameap.sql
new file mode 100644
index 0000000..3d0a362
--- /dev/null
+++ b/extensions/app_diameap/diameap.sql
@@ -0,0 +1,82 @@
+#########################################################################
+#	diameap.sql							#
+#			DiamEAP extension				#
+#  		 Users Information Database schema           		#
+#  									#
+#  									#
+#									#
+# MySQL command to load the script:					#
+#    mysql> mysql -u username -p password diameap_ui <	diameap.sql	#
+#									#
+#########################################################################
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `authe`
+--
+
+CREATE TABLE IF NOT EXISTS `authe` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `grp` int(11) NOT NULL,
+  `attribute` set('Authorization-Lifetime','Auth-Grace-Period','Auth-Session-State','Re-Auth-Request-Type','Session-Timeout','Multi-Round-Time-Out','Acct-Interim-Interval') NOT NULL DEFAULT 'Authorization-Lifetime',
+  `value` char(255) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `authz`
+--
+
+CREATE TABLE IF NOT EXISTS `authz` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `grp` int(11) NOT NULL,
+  `attribute` set('NAS-IPv6-Address','NAS-Identifier','NAS-IP-Address','NAS-Port','NAS-Port-Id','NAS-Port-Type','Called-Station-Id','Calling-Station-Id','Connect-Info','Originating-Line-Info','Service-Type','Callback-Number','Callback-Id','Idle-Timeout','Port-Limit','NAS-Filter-Rule','Filter-Id','Configuration-Token','QoS-Filter-Rule','Framed-Protocol','Framed-Routing','Framed-MTU','Framed-Compression','Framed-IP-Address','Framed-IP-Netmask','Framed-Route','Framed-Pool','Framed-Interface-Id','Framed-IPv6-Prefix','Framed-IPv6-Pool','Framed-IPv6-Route','Framed-IPX-Network','Framed-Appletalk-Link','Framed-Appletalk-Network','Framed-Appletalk-Zone') NOT NULL DEFAULT 'Service-Type',
+  `op` set('==','>','>=','<','<=','!=','~=','=+','+==','+>','+>=','+<','+<=','+!=','+~=','==+','>+','>=+','<+','<=+','!=+') NOT NULL DEFAULT '==',
+  `value` char(255) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `grp`
+--
+
+CREATE TABLE IF NOT EXISTS `grp` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `grp_name` char(255) NOT NULL,
+  `active` set('Y','N') NOT NULL DEFAULT 'Y',
+  PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `users`
+--
+
+CREATE TABLE IF NOT EXISTS `users` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `username` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
+  `eapmethod` tinyint(3) unsigned NOT NULL DEFAULT '0',
+  `vendor` int(11) NOT NULL DEFAULT '0',
+  `password` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
+  `active` enum('Y','N') CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'Y',
+  PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `user_grp`
+--
+
+CREATE TABLE IF NOT EXISTS `user_grp` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `user` int(11) NOT NULL,
+  `grp` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+);
diff --git a/extensions/app_diameap/diameap.y b/extensions/app_diameap/diameap.y
new file mode 100644
index 0000000..543d404
--- /dev/null
+++ b/extensions/app_diameap/diameap.y
@@ -0,0 +1,194 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 <stdio.h>
+#include "diameap_common.h"
+#include "diameap.tab.h"
+
+void yyerror (YYLTYPE *llocp, struct diameap_conf * config, const char *s);
+
+extern int yywrap();
+extern int yylex();
+
+
+/* The Lex parser prototype */
+int diameaplex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+
+%}
+
+%locations
+%parse-param {struct diameap_conf * config} 
+%pure_parser
+/*%defines */
+%error-verbose
+%debug 
+
+%union {
+	char *str;
+	int val;
+	char byte;
+}
+
+
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+%token 	<val>	NUM
+
+%token 	<str>	iSTRING
+
+%token  <byte>	iBYTE
+
+%token 		EAPMETHOD
+%token 		AUTHORIZE
+%token 		MODE
+%token 		DIAMEAP_MYSQL
+%token		MAX_INVALID_EAP_PACKET
+%token		MULTI_ROUND_TIMEOUT
+%token		CHECK_USER_IDENTITY
+
+%%	
+
+confparams : 	/* empty */
+		| confparams EAPmethod
+		| confparams Authorize
+		| confparams DiamEAP_MySQL
+		| confparams MAX_Invalid_EAP_Packet
+		| confparams Multi_Round_Timeout
+		| confparams Check_User_Identity
+		| confparams errors
+		{
+			yyerror(&yylloc, config, "Unrecognized configuration parameter.");
+			return EINVAL;
+		}
+		;
+
+errors :	LEX_ERROR
+		| error
+		;
+
+
+EAPmethod :	EAPMETHOD '=' iSTRING ':' NUM ':' NUM ':' iSTRING ':' iSTRING ';'
+		{
+		char * infile, *cfile;
+		FILE * fl;
+
+		infile = $9;
+		fl = fopen(infile, "r");
+		if ((fl == NULL) && (*infile != '/')) {
+			char * tmpfile=infile;
+			CHECK_MALLOC_DO( infile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+				{ yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+			sprintf(infile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+			free(tmpfile);
+			fl = fopen(infile, "r");
+		}
+		if (fl == NULL) {
+			int ret = errno;
+			TRACE_DEBUG(INFO, "Unable to open %s plugin file %s for reading: %s", $3, infile, strerror(ret));
+			yyerror (&yylloc, config, "Error adding EAP Plugin"); 
+			YYERROR;
+		}
+		fclose(fl);
+		
+		cfile = $11;
+
+		if(strlen(cfile)>0){
+			fl = fopen(cfile, "r");
+			if ((fl == NULL) && (*cfile != '/')) {
+				char * tmp = cfile;
+				CHECK_MALLOC_DO( cfile = malloc( strlen(tmp) + strlen(DEFAULT_CONF_PATH) + 2 ),
+					{ yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+				sprintf(cfile, DEFAULT_CONF_PATH "/%s", tmp);
+				free(tmp);
+				fl = fopen(cfile, "r");
+			}
+			if (fl == NULL) {
+					
+			}
+			if(fl)
+				fclose(fl);
+		}		
+		
+		diameap_plugin_add($3,(char)$5,(char)$7,infile,cfile);
+		}
+		;
+
+Authorize :	AUTHORIZE '=' NUM ';'
+		{
+		if((int)$3)
+			config->authorize=1;
+		}
+		;
+			
+
+DiamEAP_MySQL :	DIAMEAP_MYSQL '=' iSTRING ',' iSTRING ',' iSTRING ',' iSTRING ';'
+		{
+		diameap_set_mysql_param($3,$5,$7,$9);
+		}
+		;
+
+MAX_Invalid_EAP_Packet : MAX_INVALID_EAP_PACKET '=' NUM ';'
+		{
+		config->max_invalid_eap_packet=(int)$3;
+		};
+
+Multi_Round_Timeout : MULTI_ROUND_TIMEOUT '=' NUM ';'
+		{
+		config->multi_round_time_out=(unsigned int)$3;
+		};
+
+Check_User_Identity: CHECK_USER_IDENTITY '=' NUM ';'
+		{
+			if((int)$3){
+				check_user_identity = TRUE;
+			}else{
+				check_user_identity = FALSE;
+			}
+		};
+		
+	
+%%
+
+void yyerror(YYLTYPE *llocp, struct diameap_conf * config,const char *str)
+{
+         fprintf(stderr,"Error in %s ( on line %i column %i -> line %i column %i) : %s\n",config->conffile, llocp->first_line, llocp->first_column, llocp->last_line, llocp->last_column, str);
+}
diff --git a/extensions/app_diameap/diameap_common.h b/extensions/app_diameap/diameap_common.h
new file mode 100644
index 0000000..82822c7
--- /dev/null
+++ b/extensions/app_diameap/diameap_common.h
@@ -0,0 +1,127 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_COMMON_H_
+#define DIAMEAP_COMMON_H_
+
+#include "libdiameap.h"
+#include "libcrypt.h"
+#include "diameap.h"
+#include "diameap_plugins.h"
+#include "diameap_eap.h"
+#include "diameap_server.h"
+#include <regex.h>
+
+
+
+/* Dictionary Object templates */
+extern struct dict_object * dataobj_diameap_cmd; /* Diameter-EAP-Request Command Code */
+extern struct dict_object * dataobj_diameap_app; /* Diameter EAP Application object */
+extern struct dict_object * dataobj_diameap_ven; /* Diameter EAP Application Vendor object */
+extern struct dict_object * dataobj_accounting_eap_auth_method;
+extern struct dict_object * dataobj_acct_interim_interval;
+extern struct dict_object * dataobj_auth_application_id;
+extern struct dict_object * dataobj_auth_grace_period;
+extern struct dict_object * dataobj_auth_request_type;
+extern struct dict_object * dataobj_auth_session_state;
+extern struct dict_object * dataobj_authorization_lifetime;
+extern struct dict_object * dataobj_callback_id;
+extern struct dict_object * dataobj_callback_number;
+extern struct dict_object * dataobj_called_station_id;
+extern struct dict_object * dataobj_calling_station_id;
+extern struct dict_object * dataobj_class;
+extern struct dict_object * dataobj_configuration_token;
+extern struct dict_object * dataobj_connect_info;
+extern struct dict_object * dataobj_destination_host;
+extern struct dict_object * dataobj_destination_realm;
+extern struct dict_object * dataobj_eap_master_session_key;
+extern struct dict_object * dataobj_eap_key_name;
+extern struct dict_object * dataobj_eap_payload;
+extern struct dict_object * dataobj_eap_reissued_payload;
+extern struct dict_object * dataobj_error_message;
+extern struct dict_object * dataobj_error_reporting_host;
+extern struct dict_object * dataobj_failed_avp;
+extern struct dict_object * dataobj_filter_id;
+extern struct dict_object * dataobj_framed_appletalk_link;
+extern struct dict_object * dataobj_framed_appletalk_network;
+extern struct dict_object * dataobj_framed_appletalk_zone;
+extern struct dict_object * dataobj_framed_compression;
+extern struct dict_object * dataobj_framed_interface_id;
+extern struct dict_object * dataobj_framed_ip_address;
+extern struct dict_object * dataobj_framed_ip_netmask;
+extern struct dict_object * dataobj_framed_ipv6_prefix;
+extern struct dict_object * dataobj_framed_ipv6_pool;
+extern struct dict_object * dataobj_framed_ipv6_route;
+extern struct dict_object * dataobj_framed_ipx_network;
+extern struct dict_object * dataobj_framed_mtu;
+extern struct dict_object * dataobj_framed_pool;
+extern struct dict_object * dataobj_framed_protocol;
+extern struct dict_object * dataobj_framed_route;
+extern struct dict_object * dataobj_framed_routing;
+extern struct dict_object * dataobj_idle_timeout;
+extern struct dict_object * dataobj_multi_round_time_out;
+extern struct dict_object * dataobj_nas_filter_rule;
+extern struct dict_object * dataobj_nas_identifier;
+extern struct dict_object * dataobj_nas_ip_address;
+extern struct dict_object * dataobj_nas_ipv6_address;
+extern struct dict_object * dataobj_nas_port;
+extern struct dict_object * dataobj_nas_port_id;
+extern struct dict_object * dataobj_nas_port_type;
+extern struct dict_object * dataobj_originating_line_info;
+extern struct dict_object * dataobj_origin_host;
+extern struct dict_object * dataobj_origin_realm;
+extern struct dict_object * dataobj_origin_state_id;
+extern struct dict_object * dataobj_port_limit;
+extern struct dict_object * dataobj_proxy_info;
+extern struct dict_object * dataobj_qos_filter_rule;
+extern struct dict_object * dataobj_re_auth_request_type;
+extern struct dict_object * dataobj_redirect_host;
+extern struct dict_object * dataobj_redirect_host_usage;
+extern struct dict_object * dataobj_redirect_max_cache_time;
+extern struct dict_object * dataobj_reply_message;
+extern struct dict_object * dataobj_result_code;
+extern struct dict_object * dataobj_route_record;
+extern struct dict_object * dataobj_service_type;
+extern struct dict_object * dataobj_session_id;
+extern struct dict_object * dataobj_session_timeout;
+extern struct dict_object * dataobj_state;
+extern struct dict_object * dataobj_tunneling;
+extern struct dict_object * dataobj_user_name;
+
+
+#endif /* DIAMEAP_COMMON_H_ */
diff --git a/extensions/app_diameap/diameap_defs.h b/extensions/app_diameap/diameap_defs.h
new file mode 100644
index 0000000..c095e86
--- /dev/null
+++ b/extensions/app_diameap/diameap_defs.h
@@ -0,0 +1,220 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_DEFS_H_
+#define DIAMEAP_DEFS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+
+/************************************************/
+/*		Data Type Definition 					*/
+/************************************************/
+
+/* boolean Type */
+typedef enum
+{
+	FALSE = 0, TRUE = 1
+} boolean;
+
+/* Exact-width integer types */
+typedef int8_t s8;		/* signed char */
+typedef uint8_t u8;		/* unsigned char */
+typedef int16_t s16;	/* signed int */
+typedef uint16_t u16;	/* unsigned int */
+typedef int32_t s32;	/* signed long int */
+typedef uint32_t u32;	/* unsigned long int */
+typedef int64_t s64;	/* signed long long int */
+typedef uint64_t u64;	/* unsigned long long int */
+
+/************************************************/
+/*		Macros									*/
+/************************************************/
+
+/* Macros for manipulating data*/
+
+/* Retrieve signed/unsigned exact-width integer types */
+#define G8(v) (u8) (* (v) )
+
+#define G16BIGE(v) ( 	( (u16) (* (v)   ) <<  8 ) ^ \
+		      	( (u16) (*((v)+1))       ) )
+#define G16LITE(v) (	( (u16) (*((v)+1)) <<  8 ) ^ \
+		      	( (u16) (* (v)   )       ) )
+
+#define G24BIGE(v) (	( (u32) (* (v)   ) << 16 ) ^ \
+			( (u32) (*((v)+1)) <<  8 ) ^ \
+			( (u32) (*((v)+2))       ) )
+#define G24LITE(v) ( 	( (u32) (*((v)+2)) << 16 ) ^ \
+			( (u32) (*((v)+1)) <<  8 ) ^ \
+			( (u32) (* (v)   )       ) )
+
+#define G32BIGE(v) ( 	( (u32) (* (v)   ) << 24 ) ^ \
+			( (u32) (*((v)+1)) << 16 ) ^ \
+			( (u32) (*((v)+2)) <<  8 ) ^ \
+			( (u32) (*((v)+3))       ) )
+#define G32LITE(v) (	( (u32) (*((v)+3)) << 24 ) ^ \
+			( (u32) (*((v)+2)) << 16 ) ^ \
+			( (u32) (*((v)+1)) <<  8 ) ^ \
+			( (u32) (* (v)   )       ) )
+
+#define G64BIGE(v) ( 	( (u64) (* (v)   ) << 56 ) ^ \
+			( (u64) (*((v)+1)) << 48 ) ^ \
+			( (u64) (*((v)+2)) << 40 ) ^ \
+			( (u64) (*((v)+3)) << 32 ) ^ \
+			( (u64) (*((v)+4)) << 24 ) ^ \
+			( (u64) (*((v)+5)) << 16 ) ^ \
+			( (u64) (*((v)+6)) <<  8 ) ^ \
+			( (u64) (*((v)+7))       ) )
+#define G64LITE(v) (	( (u64) (*((v)+7)) << 56 ) ^ \
+			( (u64) (*((v)+6)) << 48 ) ^ \
+			( (u64) (*((v)+5)) << 40 ) ^ \
+			( (u64) (*((v)+4)) << 32 ) ^ \
+			( (u64) (*((v)+3)) << 24 ) ^ \
+			( (u64) (*((v)+2)) << 16 ) ^ \
+			( (u64) (*((v)+1)) <<  8 ) ^ \
+			( (u64) (* (v)   )       ) )
+
+/* Insert signed/unsigned exact-width integer types */
+/* v : pointer where to insert the data
+ * b : pointer of data to be inserted
+ */
+/* Insertion format
+ * BIGE : BIG ENDIAN
+ * LITE : LITTLE ENDIAN
+ */
+
+#define P8(v,b) do { \
+		u8 x = (b); \
+		u8 *d = (v); \
+		d[0] = (x&0xffU); \
+	} while (0)
+
+#define P16BIGE(v,b) do { \
+		u16 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x >> 8)&0xffU); \
+		d[1] = (x&0xffU); \
+	} while (0)
+
+#define P16LITE(v,b) do { \
+		u16 x = (b); \
+		u8 *d = (v); \
+		d[0] = (x&0xffU); \
+		d[1] = ((x >> 8)&0xffU); \
+	} while (0)
+
+#define P24BIGE(v, b)  do { \
+		u32 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x >> 16)&0xffU); \
+		d[1] = ((x >> 8)&0xffU); \
+		d[2] = ((x)&0xffU); \
+	} while (0)
+
+#define P24LITE(v, b)  do { \
+		u32 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x)&0xffU); \
+		d[1] = ((x >> 8)&0xffU); \
+		d[2] = ((x >> 16)&0xffU); \
+	} while (0)
+
+#define P32BIGE(v, b)  do { \
+		u32 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x >> 24)&0xffU); \
+		d[1] = ((x >> 16)&0xffU); \
+		d[2] = ((x >> 8)&0xffU); \
+		d[3] = ((x)&0xffU); \
+	} while (0)
+
+#define P32LITE(v, b)  do { \
+		u32 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x)&0xffU); \
+		d[1] = ((x >> 8)&0xffU); \
+		d[2] = ((x >> 16)&0xffU); \
+		d[3] = ((x >> 24)&0xffU); \
+	} while (0)
+
+#define P64BIGE(v, b) do { \
+		u64 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x >> 56)&0xffU); \
+		d[1] = ((x >> 48)&0xffU); \
+		d[2] = ((x >> 40)&0xffU); \
+		d[3] = ((x >> 32)&0xffU); \
+		d[4] = ((x >> 24)&0xffU); \
+		d[5] = ((x >> 16)&0xffU); \
+		d[6] = ((x >> 8)&0xffU); \
+		d[7] = ((x)&0xffU); \
+	} while (0)
+
+#define P64LITE(v, b) do { \
+		u64 x = (b); \
+		u8 *d = (v); \
+		d[0] = ((x)&0xffU); \
+		d[1] = ((x >> 8)&0xffU); \
+		d[2] = ((x >> 16)&0xffU); \
+		d[3] = ((x >> 24)&0xffU); \
+		d[4] = ((x >> 32)&0xffU); \
+		d[5] = ((x >> 40)&0xffU); \
+		d[6] = ((x >> 48)&0xffU); \
+		d[7] = ((x >> 56)&0xffU); \
+	} while (0)
+
+/*
+ * Insert data in a specified position
+ * a : (u8*) pointer where to insert the data
+ * f : (int) insert from this position
+ * l : (int) length of the data in byte to insert
+ * b : (u8*) pointer of data to be inserted
+ */
+
+#define U8COPY(a,f,l,b) do{ \
+			u8 * x = (a); \
+			u8 * y = (b); \
+			int i; \
+			for(i=0;i<l;i++) \
+			x[i+f]= y[i]; \
+		} while (0)
+
+
+#endif /*DIAMEAP_DEFS_H_*/
diff --git a/extensions/app_diameap/diameap_eap.c b/extensions/app_diameap/diameap_eap.c
new file mode 100644
index 0000000..72885ea
--- /dev/null
+++ b/extensions/app_diameap/diameap_eap.c
@@ -0,0 +1,604 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "diameap_common.h"
+
+static void diameap_ba_nextid(struct eap_state_machine * sm, int * id)
+{
+	TRACE_ENTRY("%p %p",sm,id);
+
+	if (sm->currentId < 0)
+	{
+		*id = (u8) (255 * rand() / RAND_MAX) & 0xFFU;
+	}
+	else
+	{
+		*id = (sm->currentId++) & 0xFFU;
+	}
+	if (*id == sm->lastId)
+	{
+		*id=*id+1;
+	}
+}
+
+static void diameap_ba_policyupdate(struct eap_state_machine * eap_sm,
+		struct eap_packet *eapPacket)
+{
+	TRACE_ENTRY("%p %p",eap_sm, eapPacket);
+	if ((eap_sm->respMethod == TYPE_NAK))
+	{
+		int id;
+		eap_sm->user.pmethods = 0;
+		u32 vendor;
+		eap_type type;
+		u8 *data = (u8 *) eapPacket->data;
+		data += 5;
+		id = 5;
+		while (id < eapPacket->length)
+		{
+			vendor = VENDOR_IETF;
+			type = G8(data);
+			if (diameap_plugin_exist(vendor, type) == TRUE)
+			{
+				eap_sm->user.proposedmethods[id - 5].method = type;
+				eap_sm->user.proposedmethods[id - 5].vendor = vendor;
+				eap_sm->user.pmethods++;
+			}
+			data++;
+			id++;
+		}
+		eap_sm->user.methodId = -1;
+	}
+}
+
+static int diameap_ba_policygetnextmethod(struct eap_state_machine * eap_sm,
+		eap_type * eaptype, u32 * vendor)
+{
+	TRACE_ENTRY("%p %p %p",eap_sm,eaptype,vendor);
+	*vendor = 0;
+	*eaptype = TYPE_NONE;
+	if (eap_sm == NULL)
+	{
+		return EINVAL;
+	}
+
+	eap_sm->selectedMethod = NULL;
+
+	if (eap_sm->user.userid == NULL)
+	{
+		if ((eap_sm->currentMethod == TYPE_NONE))
+		{
+			*vendor = VENDOR_IETF;
+			*eaptype = TYPE_IDENTITY;
+			if (eap_sm->selectedMethod != NULL)
+			{
+				(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+				eap_sm->methodData = NULL;
+			}
+			CHECK_FCT(diameap_plugin_get(VENDOR_IETF,TYPE_IDENTITY,&eap_sm->selectedMethod));
+			return 0;
+		}
+
+		eap_sm->selectedMethod = NULL;
+		*vendor = 0;
+		*eaptype = TYPE_NONE;
+		return 0;
+	}
+
+	if (eap_sm->user.methodId == -1)
+	{
+		if (eap_sm->user.proposed_eap_method >= TYPE_EAP_MD5)
+		{
+			*vendor = eap_sm->user.proposed_eap_method_vendor;
+			if (*vendor == VENDOR_IETF)
+			{
+				*eaptype = eap_sm->user.proposed_eap_method;
+			}
+			else
+			{
+				*eaptype = TYPE_EXPANDED_TYPES;
+			}
+			if (eap_sm->selectedMethod != NULL)
+			{
+				(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+				eap_sm->methodData = NULL;
+			}
+			CHECK_FCT_DO(diameap_plugin_get(*vendor,*eaptype,&eap_sm->selectedMethod),
+					{	TRACE_DEBUG(INFO,"%s [EAP Protocol] Invalid EAP-TYPE %d (vendor %d)",DIAMEAP_EXTENSION,*eaptype,*vendor);return 1;});
+
+		}
+		eap_sm->user.proposed_eap_method = TYPE_NONE;
+	}
+	else
+	{
+		*vendor = eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor;
+		if (eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor
+				== VENDOR_IETF)
+		{
+			*eaptype
+					= eap_sm->user.proposedmethods[eap_sm->user.methodId].method;
+		}
+		else
+		{
+			*eaptype = TYPE_EXPANDED_TYPES;
+		}
+		if (eap_sm->selectedMethod != NULL)
+		{
+			(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+			eap_sm->methodData=NULL;
+		}
+		CHECK_FCT(diameap_plugin_get(eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor,eap_sm->user.proposedmethods[eap_sm->user.methodId].method,&eap_sm->selectedMethod));
+
+		eap_sm->user.methodId++;
+	}
+
+	return 0;
+}
+
+static int diameap_ba_policygetdecision(struct eap_state_machine * eap_sm,
+		struct diameap_eap_interface * eap_i, decision * gdecision)
+{
+	TRACE_ENTRY("%p %p %p",eap_sm,eap_i,gdecision);
+
+	if (eap_sm->user.userid != NULL)
+	{
+
+		if (eap_sm->methodState == EAP_M_END)
+		{
+
+			if (eap_sm->respMethod == TYPE_IDENTITY)
+			{
+
+				*gdecision = DECISION_CONTINUE;
+				return 0;
+			}
+
+			if ((eap_sm->respMethod == TYPE_NAK) || ((eap_sm->respMethod
+					== TYPE_EXPANDED_TYPES) && (eap_sm->respVendor
+					== VENDOR_IETF) && (eap_sm->respVendorMethod == TYPE_NAK)))
+			{
+				goto SelectNextMethod;
+			}
+
+			if (eap_sm->user.success == TRUE)
+			{
+
+				*gdecision = DECISION_SUCCESS;
+			}
+			else
+			{
+
+				*gdecision = DECISION_FAILURE;
+			}
+
+		}
+		else
+		{
+			goto SelectNextMethod;
+		}
+		return 0;
+
+		SelectNextMethod: if ((eap_sm->user.methodId
+				== (MAXPROPOSEDMETHODS - 1))
+				|| ((eap_sm->user.proposedmethods[eap_sm->user.methodId + 1].method
+						== TYPE_NONE)
+						&& (eap_sm->user.proposedmethods[eap_sm->user.methodId
+								+ 1].vendor == VENDOR_IETF)))
+		{
+			TRACE_DEBUG(FULL+1,
+					"%s [EAP protocol] None of proposed EAP Methods authenticated the user.(FAILURE)",DIAMEAP_EXTENSION);
+			*gdecision = DECISION_FAILURE;
+			return 0;
+		}
+
+		eap_sm->user.methodId = 0;
+		*gdecision = DECISION_CONTINUE;
+		return 0;
+	}
+
+	if (eap_sm->currentMethod == TYPE_IDENTITY)
+	{
+		*gdecision = DECISION_FAILURE;
+		return 0;
+	}
+
+	*gdecision = DECISION_CONTINUE;
+	return 0;
+}
+
+static boolean diameap_ba_policydopickup(eap_type type)
+{
+	TRACE_ENTRY("%d",type);
+	if (type == TYPE_IDENTITY)
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+int diameap_eap_statemachine(struct eap_state_machine * eap_sm,
+		struct diameap_eap_interface * eap_i, boolean * non_fatal_error)
+{
+	TRACE_ENTRY("%p %p %p", eap_sm, eap_i, non_fatal_error);
+	int ret;
+
+	if ((eap_sm->eap_state == EAP_IDLE) && (eap_i->aaaEapResp == TRUE))
+	{
+		eap_sm->eap_state = EAP_RECEIVED;
+	}
+	while (!((eap_sm->eap_state == EAP_IDLE) || (eap_sm->eap_state == EAP_END)))
+	{
+		switch (eap_sm->eap_state)
+		{
+		case EAP_INITIALIZE:
+			if (eap_sm->rxResp == TRUE)
+			{
+				eap_sm->lastId = eap_sm->currentId;
+				eap_sm->currentId = eap_sm->respId;
+			}
+			else
+			{
+				eap_sm->lastId = -1;
+				eap_sm->currentId = -1;
+			}
+			if (eap_sm->rxResp == FALSE)
+			{
+				eap_sm->eap_state = EAP_SELECT_ACTION;
+			}
+			else if ((eap_sm->respMethod == TYPE_NAK) || (eap_sm->respMethod
+					== TYPE_EXPANDED_TYPES && eap_sm->respVendor == VENDOR_IETF
+					&& eap_sm->respVendorMethod == TYPE_NAK))
+			{
+				eap_sm->eap_state = EAP_NAK;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_PICK_UP_METHOD;
+			}
+			break;
+		case EAP_PICK_UP_METHOD:
+			if (diameap_ba_policydopickup(eap_sm->respMethod) == TRUE)
+			{
+				eap_sm->currentMethod = eap_sm->respMethod;
+
+				if (diameap_plugin_get(eap_sm->currentVendor,
+						eap_sm->currentMethod, &eap_sm->selectedMethod))
+				{
+					TRACE_DEBUG(INFO,"%sNo EAP Method plugin available for EAP Method {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,eap_sm->currentMethod, eap_sm->currentVendor);
+				}
+				else
+				{
+					TRACE_DEBUG(FULL,"%sCurrent EAP Method {Type=%d, Vendor=%d} (EAP Method plugin selected).",DIAMEAP_EXTENSION,eap_sm->currentMethod, eap_sm->currentVendor);
+				}
+				eap_sm->currentVendor = VENDOR_IETF;
+				if (eap_sm->selectedMethod != NULL)
+				{
+					ret = (*eap_sm->selectedMethod->eap_method_initPickUp)(
+							eap_sm);
+					if (ret)
+					{
+						TRACE_DEBUG(INFO, "%sEAP Method InitPickUp returned error.",DIAMEAP_EXTENSION);
+						eap_sm->selectedMethod = NULL;
+						eap_sm->currentMethod = TYPE_NONE;
+					}
+				}
+			}
+			if (eap_sm->currentMethod == TYPE_NONE)
+			{
+				eap_sm->eap_state = EAP_SELECT_ACTION;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_METHOD_RESPONSE;
+			}
+			break;
+
+		case EAP_RECEIVED:
+			TRACE_DEBUG(FULL+1,"%s[EAP Protocol] New EAP Response received",DIAMEAP_EXTENSION)
+			;
+			diameap_eap_dump(FULL + 1, &eap_i->aaaEapRespData);
+			if ((eap_sm->rxResp == TRUE) && (eap_sm->respId
+					== eap_sm->currentId) && ((eap_sm->respMethod
+					== eap_sm->currentMethod) || ((eap_sm->respMethod
+					== TYPE_EXPANDED_TYPES) && (eap_sm->respVendor
+					== VENDOR_IETF) && (eap_sm->respVendorMethod
+					== eap_sm->currentMethod))))
+			{
+				eap_sm->eap_state = EAP_INTEGRITY_CHECK;
+			}
+			else if ((eap_sm->rxResp == TRUE) && (eap_sm->respId
+					== eap_sm->currentId) && ((eap_sm->respMethod == TYPE_NAK)
+					|| (eap_sm->respMethod == TYPE_EXPANDED_TYPES
+							&& eap_sm->respVendor == VENDOR_IETF
+							&& eap_sm->respVendorMethod == TYPE_NAK))
+					&& (eap_sm->methodState == EAP_M_PROPOSED))
+			{
+				eap_sm->eap_state = EAP_NAK;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_DISCARD;
+			}
+			break;
+		case EAP_DISCARD:
+			TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP Packet received (Non fatal error).",DIAMEAP_EXTENSION)
+			;
+			*non_fatal_error = TRUE;
+			eap_sm->eap_state = EAP_IDLE;
+			break;
+
+		case EAP_SEND_REQUEST:
+			TRACE_DEBUG(FULL+1,"%s[EAP Protocol] New EAP packet request created.",DIAMEAP_EXTENSION)
+			;
+			diameap_eap_dump(FULL, &eap_i->aaaEapReqData);
+			eap_i->aaaEapResp = FALSE;
+			eap_i->aaaEapReq = TRUE;
+			eap_sm->eap_state = EAP_IDLE;
+			break;
+
+		case EAP_INTEGRITY_CHECK:
+			if ((*eap_sm->selectedMethod->eap_method_check)(eap_sm,
+					&eap_i->aaaEapRespData) == FALSE)
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP packet received {Type=%d, Vendor=%d}. Integrity check failed (non fatal error).",DIAMEAP_EXTENSION,eap_sm->currentMethod,eap_sm->currentVendor);
+				//non_fata_error
+				*non_fatal_error = TRUE;
+				eap_sm->eap_state = EAP_IDLE;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_METHOD_RESPONSE;
+			}
+
+			break;
+		case EAP_METHOD_REQUEST:
+			eap_sm->lastId = eap_sm->currentId;
+			diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+			CHECK_FCT((*eap_sm->selectedMethod->eap_method_buildReq)(
+							eap_sm, eap_sm->currentId,&eap_i->aaaEapReqData))
+			;
+			if (eap_sm->selectedMethod->eap_method_getTimeout)
+			{
+				if ((*eap_sm->selectedMethod->eap_method_getTimeout)(eap_sm,
+						&eap_i->aaaMethodTimeout))
+				{
+					TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] getTimeout failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+					eap_i->aaaMethodTimeout = 0;
+				}
+			}
+			else
+			{
+				eap_i->aaaMethodTimeout = 0;
+			}
+			eap_sm->eap_state = EAP_SEND_REQUEST;
+			break;
+
+		case EAP_METHOD_RESPONSE:
+			if (eap_sm->respMethod >= TYPE_EAP_MD5)
+			{
+				if (eap_sm->user.methodId < 0)
+				{
+					eap_sm->user.methodId = 0;
+					eap_sm->user.methods[eap_sm->user.methodId].vendor
+							= eap_sm->respVendor;
+					eap_sm->user.methods[eap_sm->user.methodId].method
+							= eap_sm->respMethod;
+					eap_sm->user.methodId++;
+
+				}
+				else if (!((eap_sm->user.methods[eap_sm->user.methodId - 1].vendor
+						== eap_sm->respVendor)
+						&& (eap_sm->user.methods[eap_sm->user.methodId - 1].method
+								== eap_sm->respMethod)))
+				{
+					eap_sm->user.methods[eap_sm->user.methodId].vendor
+							= eap_sm->respVendor;
+					eap_sm->user.methods[eap_sm->user.methodId].method
+							= eap_sm->respMethod;
+					eap_sm->user.methodId++;
+				}
+			}
+			if ((*eap_sm->selectedMethod->eap_method_process)(eap_sm,
+					&eap_i->aaaEapRespData))
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Authentication process failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+				*non_fatal_error = TRUE;
+				eap_sm->eap_state = EAP_IDLE;
+
+			}else{
+			if ((*eap_sm->selectedMethod->eap_method_isDone)(eap_sm) == TRUE)
+			{
+				/*diameap_ba_PolicyUpdate();*/
+				eap_i->aaaEapMSKLength = 0;
+				eap_i->aaaEapEMSKLength = 0;
+				if (eap_sm->selectedMethod->eap_method_getKey)
+				{
+					if ((*eap_sm->selectedMethod->eap_method_getKey)(eap_sm,
+							&eap_i->aaaEapMSKData, &eap_i->aaaEapMSKLength,
+							&eap_i->aaaEapEMSKData, &eap_i->aaaEapEMSKLength))
+					{
+						TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Generating EAP Master Key failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname)
+						eap_i->aaaEapMSKLength = 0;
+						eap_i->aaaEapEMSKLength = 0;
+						eap_i->aaaEapKeyAvailable = FALSE;
+					}
+					else
+					{
+						eap_i->aaaEapKeyAvailable = TRUE;
+					}
+				}
+				eap_sm->methodState = EAP_M_END;
+				eap_sm->eap_state = EAP_SELECT_ACTION;
+			}
+			else
+			{
+				eap_sm->methodState = EAP_M_CONTINUE;
+				eap_sm->eap_state = EAP_METHOD_REQUEST;
+			}
+			}
+			break;
+		case EAP_PROPOSE_METHOD:
+			if (diameap_ba_policygetnextmethod(eap_sm, &eap_sm->currentMethod,
+					&eap_sm->currentVendor))
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Selecting EAP Method plugin failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+
+				*non_fatal_error = TRUE;
+				eap_sm->eap_state = EAP_END;
+
+			}
+			TRACE_DEBUG(FULL,"%s[EAP Protocol] Selecting EAP Method plugin: %s(%d). [user: %s]",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname,eap_sm->selectedMethod->methodtype,eap_sm->user.userid)
+			;
+			if ((*eap_sm->selectedMethod->eap_method_init)(eap_sm))
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Initializing EAP plugin failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+			}
+
+			if ((eap_sm->currentMethod == TYPE_IDENTITY)
+					|| (eap_sm->currentMethod == TYPE_NOTIFICATION))
+			{
+				eap_sm->methodState = EAP_M_CONTINUE;
+			}
+			else
+			{
+				eap_sm->methodState = EAP_M_PROPOSED;
+			}
+			eap_sm->eap_state = EAP_METHOD_REQUEST;
+			break;
+		case EAP_NAK:
+			TRACE_DEBUG(FULL+1,"%s[EAP Protocol] EAP NAK Packet received.",DIAMEAP_EXTENSION)
+			;
+			if (eap_sm->selectedMethod->eap_method_free)
+			{
+				(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+				eap_sm->methodData = NULL;
+			}
+			else
+			{
+				if (eap_sm->methodData)
+				{
+					free(eap_sm->methodData);
+					eap_sm->methodData = NULL;
+				}
+			}
+			diameap_ba_policyupdate(eap_sm, &eap_i->aaaEapRespData);
+			eap_sm->eap_state = EAP_SELECT_ACTION;
+			break;
+		case EAP_SELECT_ACTION:
+			CHECK_FCT(diameap_ba_policygetdecision(eap_sm, eap_i,&eap_sm->sm_decision))
+			;
+			switch (eap_sm->sm_decision)
+			{
+			case DECISION_CONTINUE:
+				eap_sm->eap_state = EAP_PROPOSE_METHOD;
+				break;
+			case DECISION_FAILURE:
+				TRACE_DEBUG(FULL,"%s[EAP Protocol] Authentication Failure [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid)
+				;
+				eap_sm->lastId = eap_sm->currentId;
+				diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+				CHECK_FCT(diameap_eap_new(EAP_FAILURE, (u8) eap_sm->currentId, TYPE_NONE, NULL, 0,&eap_i->aaaEapReqData))
+				;
+				eap_i->aaaFail = TRUE;
+				*non_fatal_error = FALSE;
+				eap_sm->eap_state = EAP_END;
+				if (eap_sm->methodData)
+				{
+					if (eap_sm->selectedMethod->eap_method_free)
+					{
+						(*eap_sm->selectedMethod->eap_method_free)(
+								eap_sm->methodData);
+						eap_sm->methodData = NULL;
+					}
+					else
+					{
+						free(eap_sm->methodData);
+						eap_sm->methodData = NULL;
+					}
+				}
+				break;
+			case DECISION_SUCCESS:
+				TRACE_DEBUG(FULL,"%s[EAP Protocol] Authentication Success [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid)
+				;
+				eap_sm->lastId = eap_sm->currentId;
+				diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+				CHECK_FCT(diameap_eap_new(EAP_SUCCESS, (u8) eap_sm->currentId, TYPE_NONE, NULL, 0,&eap_i->aaaEapReqData))
+				;
+				if (eap_i->aaaEapMSKData != NULL)
+				{
+					TRACE_DEBUG(FULL+1,"%s[EAP Protocol] EAP Key available [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid);
+					eap_i->aaaEapKeyAvailable = TRUE;
+				}
+				else
+				{
+					TRACE_DEBUG(FULL+1,"%s[EAP Protocol] No EAP Key available [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid);
+				}
+				eap_i->aaaSuccess = TRUE;
+				*non_fatal_error = FALSE;
+				eap_sm->eap_state = EAP_END;
+				if (eap_sm->selectedMethod->eap_method_free)
+				{
+					(*eap_sm->selectedMethod->eap_method_free)(
+							eap_sm->methodData);
+					eap_sm->methodData = NULL;
+				}
+				else
+				{
+					if (eap_sm->methodData)
+					{
+						free(eap_sm->methodData);
+						eap_sm->methodData = NULL;
+					}
+				}
+				break;
+			default:
+				TRACE_DEBUG(INFO,"%sIncorrect EAP Decision.(Please report this problem.)",DIAMEAP_EXTENSION)
+				;
+			}
+			break;
+
+		case EAP_END:
+			break;
+
+		case EAP_IDLE:
+			break;
+		}
+	}
+
+	return 0;
+}
+
diff --git a/extensions/app_diameap/diameap_eap.h b/extensions/app_diameap/diameap_eap.h
new file mode 100644
index 0000000..8fb6617
--- /dev/null
+++ b/extensions/app_diameap/diameap_eap.h
@@ -0,0 +1,73 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_EAP_H_
+#define DIAMEAP_EAP_H_
+
+
+/************************************************/
+/*		EAP AAA Interface						*/
+/************************************************/
+
+/* EAP Backend Authenticator State Machine */
+struct diameap_eap_interface
+{
+
+	/* Variables (AAA Interface to Backend Authenticator)*/
+	boolean aaaEapResp;
+	struct eap_packet aaaEapRespData;
+
+	/*Variables (Backend Authenticator to AAA Interface )*/
+	boolean aaaEapReq;
+	boolean aaaEapNoReq;
+	boolean aaaSuccess;
+	boolean aaaFail;
+	struct eap_packet aaaEapReqData;
+	u8 *aaaEapMSKData;
+	int aaaEapMSKLength;
+	u8 *aaaEapEMSKData;
+	int aaaEapEMSKLength;
+	boolean aaaEapKeyAvailable;
+	int aaaMethodTimeout;
+
+};
+
+int diameap_eap_statemachine(struct eap_state_machine * sm, struct diameap_eap_interface * eap_i, boolean * error);
+
+
+#endif /* EAP_H_ */
diff --git a/extensions/app_diameap/diameap_eappacket.c b/extensions/app_diameap/diameap_eappacket.c
new file mode 100644
index 0000000..a696161
--- /dev/null
+++ b/extensions/app_diameap/diameap_eappacket.c
@@ -0,0 +1,310 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "libdiameap.h"
+
+int diameap_eap_get_code(struct eap_packet *eappacket, eap_code * eapcode)
+{
+	TRACE_ENTRY("%p %p",eappacket,eapcode);
+
+	if (eappacket->data == NULL)
+	{
+		*eapcode = ERROR;
+		TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Code to return.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	if (eappacket->length < 1)
+	{
+		*eapcode = ERROR;
+		TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Code to return.",DIAMEAP_EXTENSION, eappacket->length);
+		return EINVAL;
+	}
+	*eapcode = G8(eappacket->data);
+	return 0;
+}
+
+int diameap_eap_get_identifier(struct eap_packet *eappacket, u8 * identifier)
+{
+	TRACE_ENTRY("%p %p",eappacket,identifier);
+	*identifier = 0;
+	if (eappacket->data == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Identifier field to return.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	if (eappacket->length < 2)
+	{
+		TRACE_DEBUG(INFO,"%sEAP packet length %d : no Identifier field to return.",DIAMEAP_EXTENSION, eappacket->length);
+		return EINVAL;
+	}
+	*identifier = G8(eappacket->data + 1);
+	return 0;
+}
+
+int diameap_eap_get_length(struct eap_packet *eappacket, u16 *length)
+{
+	TRACE_ENTRY("%p %p",eappacket,length);
+	*length = 0;
+
+	if (eappacket->data == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	if (eappacket->ulength < 4)
+	{
+		TRACE_DEBUG(INFO,"%sEAP packet length %d : no Length field to return.",DIAMEAP_EXTENSION, eappacket->length);
+		return EINVAL;
+	}
+	*length = (u16) G16BIGE((eappacket->data + 2));
+	return 0;
+}
+
+int diameap_eap_get_packetlength(struct eap_packet *eappacket, u16 *length)
+{
+	TRACE_ENTRY("%p %p",eappacket,length);
+	if (eappacket->data == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	*length = eappacket->ulength;
+	return 0;
+}
+
+int diameap_eap_get_type(struct eap_packet *eappacket, eap_type * eaptype)
+{
+	TRACE_ENTRY("%p %p",eappacket,eaptype);
+	*eaptype = 0;
+
+	if (eappacket->data == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Type field to return.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	if (eappacket->length < 5)
+	{
+		TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Type field to return.",DIAMEAP_EXTENSION, eappacket->length);
+		return EINVAL;
+	}
+	*eaptype = (u32) G8(eappacket->data + 4);
+	return 0;
+}
+
+boolean diameap_eap_check_code(eap_code code)
+{
+	TRACE_ENTRY("%d",code);
+	if (code != EAP_REQUEST && code != EAP_RESPONSE && code != EAP_SUCCESS
+			&& code != EAP_FAILURE)
+	{
+		TRACE_DEBUG(FULL,"%sIncorrect EAP Code (%d).",DIAMEAP_EXTENSION,code);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int diameap_eap_get_packetdata(struct eap_packet *eappacket, u8 ** data,
+		int *len)
+{
+	TRACE_ENTRY("%p %p",eappacket,data);
+	if (eappacket->length > 0)
+	{
+		*data = malloc(sizeof(u8) * eappacket->length);
+		U8COPY(*data,0,eappacket->length,eappacket->data);
+		*len = eappacket->length;
+		return 0;
+	}
+	TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
+	*data = NULL;
+	*len = 0;
+	return EINVAL;
+}
+
+int diameap_eap_get_data(struct eap_packet *eappacket, u8 ** data, int * len)
+{
+	TRACE_ENTRY("%p %p",eappacket,data);
+	if (eappacket->length > 5)
+	{
+		CHECK_MALLOC( *data = malloc(sizeof(u8) * (eappacket->length - 5)) );
+		U8COPY(*data,0,(eappacket->length-5),(eappacket->data+5));
+		*len = eappacket->length - 5;
+		return 0;
+	}
+	TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
+	*data = NULL;
+	*len = 0;
+
+	return EINVAL;
+}
+
+void diameap_eap_dump(int level, struct eap_packet *eappacket)
+{
+	TRACE_ENTRY("%d %p",level,eappacket);
+	if (!TRACE_BOOL(level))
+		return;
+
+	if (eappacket->data == NULL)
+		return;
+	if (eappacket->length < 5)
+		return;
+	if (eappacket->ulength < 5)
+		return;
+
+	fd_log_debug("------------- Dump EAP Packet-------------");
+	int i;
+	fd_log_debug("\t -Code       : ");
+	eap_code code;
+	CHECK_FCT_DO(diameap_eap_get_code(eappacket,&code),return);
+	switch (code)
+	{
+	case 1:
+		fd_log_debug("Request");
+		break;
+	case 2:
+		fd_log_debug("Response");
+		break;
+	case 3:
+		fd_log_debug("Success");
+		break;
+	case 4:
+		fd_log_debug("Failure");
+		break;
+	default:
+		fd_log_debug("Error (EAP Code value [%d] not allowed)",code);
+		break;
+	}
+	u8 id;
+	CHECK_FCT_DO(diameap_eap_get_identifier(eappacket,&id),return);
+	fd_log_debug("\t -Identifier : %x ", id);
+	u16 length;
+	CHECK_FCT_DO(diameap_eap_get_length(eappacket,&length),return);
+	fd_log_debug("\t -Length     : %d ", (unsigned int)length);
+	if (eappacket->length > 4)
+	{
+		eap_type type;
+		CHECK_FCT_DO(diameap_eap_get_type(eappacket,&type),return);
+		fd_log_debug("\t -Type       : %d ", type);
+	}
+	if (eappacket->length > 5)
+	{
+		char buf[1024];
+		snprintf(buf, sizeof(buf), "\t -Data       : ");
+		for (i = 5; i < eappacket->length && i < 30; i++)
+		{
+			snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02x ", G8(eappacket->data + i));
+		}
+		if(i+1<eappacket->length)
+			snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "[...] (len=%d)",(unsigned int) length);
+		fd_log_debug("%s", buf);
+	}
+	fd_log_debug("-------------End Dump EAP Packet-------------");
+}
+
+int diameap_eap_new(eap_code code, u8 id, eap_type type, u8 * data,
+		u16 dataLength, struct eap_packet *eappacket)
+{
+
+	TRACE_ENTRY("%d %hhu %d %p %hu %p", code, id, type, data, dataLength,eappacket);
+
+	int length = 0;
+
+	//Initialize EAP Packet
+	eappacket->length = 0;
+	eappacket->ulength = 0;
+	eappacket->data = NULL;
+
+	if (diameap_eap_check_code(code) == FALSE)
+	{
+		TRACE_DEBUG(
+				INFO,
+				"%sWrong EAP Code. Only Request, Response, Success or Failure are permitted.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+
+	length += EAP_HEADER;
+	if (code == EAP_REQUEST || code == EAP_RESPONSE)
+	{ // EAP Packet code is either Request or Response
+		if (type == TYPE_NONE)
+		{
+			TRACE_DEBUG(INFO,
+					"%sUnable to create a new EAP Packet (Request or Response) without EAP Type field.",DIAMEAP_EXTENSION);
+			return EINVAL;
+		}
+		length += EAP_TYPE; // EAP Packet code
+		if (data != NULL)
+		{
+			length += dataLength;
+
+			if (length > (int) MAX_EAP_PACKET)
+			{
+
+				TRACE_DEBUG(INFO,
+						"%sUnable to add Data to EAP Packet. Data field length exceed allowed data size.", DIAMEAP_EXTENSION);
+				return EINVAL;
+			}
+			else
+			{
+
+				CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+				memset(eappacket->data, 0, sizeof(u8) * length);
+				U8COPY(eappacket->data, 5, dataLength, data);
+			}
+		}
+		else
+		{
+			CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+			memset(eappacket->data, 0, sizeof(u8) * length);
+		}
+		P8(eappacket->data + 4, type);
+	}
+	else
+	{ //EAP Packet code is SUCCESS or FAILURE
+		CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+		memset(eappacket->data, 0, sizeof(u8) * length);
+		//No Data filed
+		//No Type field
+	}
+	//Add Code and Identifier fields
+	P8(eappacket->data, code);
+	P8(eappacket->data + 1, id);
+	//Add length field
+	P16BIGE(eappacket->data + 2, length);
+	eappacket->length = length;
+	eappacket->ulength = length;
+	return 0;
+}
diff --git a/extensions/app_diameap/diameap_eappacket.h b/extensions/app_diameap/diameap_eappacket.h
new file mode 100644
index 0000000..1f0c069
--- /dev/null
+++ b/extensions/app_diameap/diameap_eappacket.h
@@ -0,0 +1,258 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_EAPPACKET_H_
+#define DIAMEAP_EAPPACKET_H_
+
+#include "diameap_defs.h"
+
+/*EAP Packet definition : the Extensible Authentication Protocol (RFC3748) */
+
+/* Define Length/Size */
+#define EAP_HEADER 4 	/* EAP Packet header size : 4 Bytes */
+#define EAP_TYPE 1 		/* EAP Type field size : 1 Byte */
+#define MAX_EAP_PACKET (u16)0xffff /* Maximum value allowed for an EAP Packet */
+
+/*EAP Packet Codes Type*/
+typedef enum
+{
+	ERROR = 0, 			/* EAP Packet Code should not be set to ERROR. Indicates a wrong Code value received. */
+	EAP_REQUEST = 1, 	/* EAP Request (value=1). */
+	EAP_RESPONSE = 2, 	/* EAP Response (value=2). */
+	EAP_SUCCESS = 3, 	/* EAP Success (value=3). */
+	EAP_FAILURE = 4 	/* EAP Failure (value=4). */
+} eap_code;
+
+/* EAP Packet */
+struct eap_packet
+{
+	u16 length; 	/* Length of data (equivalent to the length field). */
+	u16 ulength; 	/* Length of received or inserted bytes in the data pointer. */
+	u8 *data; 		/* Data buffer (including Code, Identifier, Length,  (also Type and Data fields if exists)). */
+};
+
+/* EAP Methods Types */
+typedef enum
+{
+	TYPE_NONE = 0, 			/* Indicate no method specified */
+	TYPE_IDENTITY = 1, 		/* EAP Identity (RFC3748) */
+	TYPE_NOTIFICATION = 2, 	/* EAP Notification (RFC3748) */
+	TYPE_NAK = 3, 			/* EAP NAK (RFC3748) */
+	TYPE_EAP_MD5 = 4,		/* EAP MD5 (RFC3748) */
+	TYPE_OTP = 5, 			/* EAP OTP (RFC3748) */
+	TYPE_GTC = 6, 			/* EAP GTC (RFC3748) */
+	TYPE_EAP_TLS = 13,		/* EAP TLS (RFC5216) */
+	TYPE_EXPANDED_TYPES = 254, 	/* EAP Expanded NAK (RFC3748) */
+	TYPE_EXPERIMENTAL_USE = 255	/* for Experimental use (RFC3748) */
+} eap_type;
+
+
+/* Function		:	diameap_eap_get_code
+ *
+ * Parameters:
+ * 	eapPacket 	: 	an EAP Packet
+ *	eapcode		:	On successful return, the EAP Code is stored here.
+ *
+ * Description:
+ * 	Get the EAP Code of an EAP Packet. If NULL EAP Packet or empty packet ERROR is stored in eapcode.
+ *
+ * Return value:
+ * 	0 			: 	if successful
+* 	EINVAL		:	if EAP Packet is NULL or empty
+ */
+
+int diameap_eap_get_code(struct eap_packet *eapPacket, eap_code * eapcode);
+
+
+/* Function		:	diameap_eap_get_identifier
+ *
+ * Parameters:
+ * 	eapPacket 	: 	an EAP Packet
+ * 	identifier	:	on successful return, the identifier value is stored here.
+ *
+ * Description:
+ * 	Get the Identifier field of an EAP Packet.
+ *
+ * Return value:
+ * 	0 			: 	if successful
+ * 	EINVAL		: 	if the EAP Packet is NULL or the EAP identifier value is not valid or data length < 2
+ *
+ */
+
+int diameap_eap_get_identifier(struct eap_packet *eapPacket, u8 * identifier);
+
+
+/* Function		:	diameap_eap_get_length
+ *
+ * Parameters:
+ *	eapPacket	: 	an EAP Packet
+ *	length		:	on successful return, the EAP Packet length field is stored here.
+ *
+ * Description:
+ *	Get the Length field of an EAP Packet
+ *
+ * Return value:
+ *	0			:	if successful
+ *	EINVAL		: 	if the data length < 4, or the EAP Packet is NULL.
+ */
+
+int diameap_eap_get_length(struct eap_packet *eapPacket, u16 *length);
+
+
+/* Function		:	diameap_eap_get_packetlength
+ *
+ * Parameters:
+ *	eapPacket	: 	an EAP Packet
+ *	length		:	on successful return, the length of EAP Packet is stored here.
+ *
+ * Description:
+ *	Get the received or inserted length of Bytes in an EAP Packet.
+ *
+ * Return value:
+ *	0			: 	if successful
+ *	EINVAL		: 	if the EAP Packet is NULL
+ */
+
+int diameap_eap_get_packetlength(struct eap_packet *eapPacket, u16 *length);
+
+
+/* Function		:	diameap_eap_get_type
+ *
+ * Parameters:
+ *	eapPacket	: 	an EAP Packet
+ *	eaptype		:	on successful return, the EAP Type field is stored here.
+ *
+ * Description:
+ *	Get the Type field of an EAP Packet.
+ *
+ * Return value:
+ *	0			:	if successful
+ *	EINVAL		:	if the EAP Packet is NULL or data length < 5
+ */
+
+int diameap_eap_get_type(struct eap_packet *eapPacket,eap_type * eaptype);
+
+
+/* Function		:	diameap_eap_get_packetdata
+ *
+ * Parameters:
+ *	eapPacket	: 	an EAP Packet
+ *	eapdata		:	on successful return, the content of EAP Packet is stored here.
+ *	eapdatalen	:	on successful return, the length of EAP Packet is stored here.
+ *
+ * Description:
+ *	Get the data content of an EAP Packet.
+ *
+ * Return value:
+ *	0			: 	if successful
+ *	EINVAL		: 	if there is no data in the current EAP Packet (ulength<1)
+ */
+
+int diameap_eap_get_packetdata(struct eap_packet *eapPacket, u8 ** data, int *len);
+
+
+/* Function		:	diameap_eap_get_data
+ *
+ * Parameters:
+ *	eapPacket	: 	an EAP Packet
+ *	data		:	on successful return, the content of data field is stored here.
+ *	datalen		:	on successful return, the length of data field is stored here.
+ *
+ * Description:
+ *	Return the Data field of an EAP Packet
+ *
+ * Return value:
+ *	0			: 	if successful
+ *	EINVAL		: 	if there is no data in the current EAP Packet (ulength<6)
+ */
+
+int diameap_eap_get_data(struct eap_packet *eapPacket, u8 ** data, int * len);
+
+
+/* Function		:	diameap_eap_chech_code
+ *
+ * Parameters:
+ *	code		: 	an EAP Code value
+ *
+ * Description:
+ *	Check if the code value is valid or not
+ *
+ * Return value:
+ * 	TRUE		: 	if valid value
+ * 	FALSE		: 	if not valid value
+ *
+ */
+
+boolean diameap_eap_check_code(eap_code code);
+
+
+/* Function		:	diameap_eap_dump
+ *
+ * Parameters:
+ *	eapPacket	:	an EAP Packet
+ *	level		:	Debug level
+ *
+ * Description:
+ *	Dump the structure and the content of all the fields in this EAP Packet
+ *
+ */
+
+void diameap_eap_dump(int level, struct eap_packet *eapPacket);
+
+
+/* Function		:	diameap_eap_new
+ *
+ * Parameters:
+ *	code		:	EAP CODE field value
+ *	id			:	EAP Identifier field value
+ *	type		:	(optional) EAP type field value if exist, otherwise NULL
+ *	data		:	(optional) EAP data field value if exist, otherwise NULL
+ *	dataLength	:	(optional) Length of the data to be inserted in the Packet, otherwise 0
+ *	eappacket	:	on successful return, pointer to eap packet is stored here.
+ * Description:
+ *	Create a new EAP Packet with the specified parameters and data
+ *
+ * Return value:
+ *	0			: 	if successful
+ *	EINVAL		:	Invalid parameter
+ */
+
+int diameap_eap_new(eap_code code, u8 id, eap_type type,
+		u8 * data, u16 dataLength, struct eap_packet *eappacket);
+
+#endif /* DIAMEAP_EAPPACKET_H_ */
diff --git a/extensions/app_diameap/diameap_init.c b/extensions/app_diameap/diameap_init.c
new file mode 100644
index 0000000..e3b8cc9
--- /dev/null
+++ b/extensions/app_diameap/diameap_init.c
@@ -0,0 +1,424 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "diameap_common.h"
+
+/* Dictionary Object templates */
+struct dict_object * dataobj_diameap_cmd = NULL; /* Diameter-EAP-Request Command Code */
+struct dict_object * dataobj_diameap_app = NULL; /* Diameter EAP Application object */
+struct dict_object * dataobj_diameap_ven = NULL; /* Diameter EAP Application Vendor object */
+struct dict_object * dataobj_accounting_eap_auth_method = NULL;
+struct dict_object * dataobj_acct_interim_interval = NULL;
+struct dict_object * dataobj_auth_application_id = NULL;
+struct dict_object * dataobj_auth_grace_period = NULL;
+struct dict_object * dataobj_auth_request_type = NULL;
+struct dict_object * dataobj_auth_session_state = NULL;
+struct dict_object * dataobj_authorization_lifetime = NULL;
+struct dict_object * dataobj_callback_id = NULL;
+struct dict_object * dataobj_callback_number = NULL;
+struct dict_object * dataobj_called_station_id = NULL;
+struct dict_object * dataobj_calling_station_id = NULL;
+struct dict_object * dataobj_class = NULL;
+struct dict_object * dataobj_configuration_token = NULL;
+struct dict_object * dataobj_connect_info = NULL;
+struct dict_object * dataobj_destination_host = NULL;
+struct dict_object * dataobj_destination_realm = NULL;
+struct dict_object * dataobj_eap_master_session_key = NULL;
+struct dict_object * dataobj_eap_key_name = NULL;
+struct dict_object * dataobj_eap_payload = NULL;
+struct dict_object * dataobj_eap_reissued_payload = NULL;
+struct dict_object * dataobj_error_message = NULL;
+struct dict_object * dataobj_error_reporting_host = NULL;
+struct dict_object * dataobj_failed_avp = NULL;
+struct dict_object * dataobj_filter_id = NULL;
+struct dict_object * dataobj_framed_appletalk_link = NULL;
+struct dict_object * dataobj_framed_appletalk_network = NULL;
+struct dict_object * dataobj_framed_appletalk_zone = NULL;
+struct dict_object * dataobj_framed_compression = NULL;
+struct dict_object * dataobj_framed_interface_id = NULL;
+struct dict_object * dataobj_framed_ip_address = NULL;
+struct dict_object * dataobj_framed_ip_netmask = NULL;
+struct dict_object * dataobj_framed_ipv6_prefix = NULL;
+struct dict_object * dataobj_framed_ipv6_pool = NULL;
+struct dict_object * dataobj_framed_ipv6_route = NULL;
+struct dict_object * dataobj_framed_ipx_network = NULL;
+struct dict_object * dataobj_framed_mtu = NULL;
+struct dict_object * dataobj_framed_pool = NULL;
+struct dict_object * dataobj_framed_protocol = NULL;
+struct dict_object * dataobj_framed_route = NULL;
+struct dict_object * dataobj_framed_routing = NULL;
+struct dict_object * dataobj_idle_timeout = NULL;
+struct dict_object * dataobj_multi_round_time_out = NULL;
+struct dict_object * dataobj_nas_filter_rule = NULL;
+struct dict_object * dataobj_nas_identifier = NULL;
+struct dict_object * dataobj_nas_ip_address = NULL;
+struct dict_object * dataobj_nas_ipv6_address = NULL;
+struct dict_object * dataobj_nas_port = NULL;
+struct dict_object * dataobj_nas_port_id = NULL;
+struct dict_object * dataobj_nas_port_type = NULL;
+struct dict_object * dataobj_originating_line_info = NULL;
+struct dict_object * dataobj_origin_host = NULL;
+struct dict_object * dataobj_origin_realm = NULL;
+struct dict_object * dataobj_origin_state_id = NULL;
+struct dict_object * dataobj_port_limit = NULL;
+struct dict_object * dataobj_proxy_info = NULL;
+struct dict_object * dataobj_qos_filter_rule = NULL;
+struct dict_object * dataobj_re_auth_request_type = NULL;
+struct dict_object * dataobj_redirect_host = NULL;
+struct dict_object * dataobj_redirect_host_usage = NULL;
+struct dict_object * dataobj_redirect_max_cache_time = NULL;
+struct dict_object * dataobj_reply_message = NULL;
+struct dict_object * dataobj_result_code = NULL;
+struct dict_object * dataobj_route_record = NULL;
+struct dict_object * dataobj_service_type = NULL;
+struct dict_object * dataobj_session_id = NULL;
+struct dict_object * dataobj_session_timeout = NULL;
+struct dict_object * dataobj_state = NULL;
+struct dict_object * dataobj_tunneling = NULL;
+struct dict_object * dataobj_user_name = NULL;
+
+
+
+static int diameap_init_config(char * conffile)
+{
+	TRACE_ENTRY("%p",conffile);
+
+	if (conffile != NULL)
+	{
+		diameap_config->conffile = conffile;
+	}
+	else
+	{
+		TRACE_DEBUG(FULL,"%sNo configuration file provided with the DiamEAP extension: default parameters will be used.",DIAMEAP_EXTENSION);
+	}
+
+	diameap_config->application_id = 5;
+	diameap_config->vendor_id = 0;
+	diameap_config->command_code = 268;
+	diameap_config->diam_realm = strdup(fd_g_config->cnf_diamrlm);
+	diameap_config->max_invalid_eap_packet = 5;
+	diameap_config->multi_round_time_out = 30;
+	check_user_identity = TRUE;
+
+	return 0;
+}
+
+static int diameap_init_obj(void)
+{
+
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_ID, &(diameap_config->application_id),&dataobj_diameap_app, ENOENT));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND,CMD_BY_CODE_R, &(diameap_config->command_code), &dataobj_diameap_cmd, ENOENT));
+	//	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_VENDOR,VENDOR_OF_APPLICATION, &dataobj_diameap_app, &dataobj_diameap_ven,ENOENT) );
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Accounting-EAP-Auth-Method", &dataobj_accounting_eap_auth_method,
+					ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Acct-Interim-Interval", &dataobj_acct_interim_interval, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Auth-Application-Id", &dataobj_auth_application_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Auth-Grace-Period", &dataobj_auth_grace_period, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Auth-Request-Type", &dataobj_auth_request_type, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Auth-Session-State", &dataobj_auth_session_state, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Authorization-Lifetime", &dataobj_authorization_lifetime, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Callback-Id", &dataobj_callback_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Callback-Number", &dataobj_callback_number, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Called-Station-Id", &dataobj_called_station_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Calling-Station-Id", &dataobj_calling_station_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Class", &dataobj_class, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Configuration-Token", &dataobj_configuration_token, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Connect-Info", &dataobj_connect_info, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Destination-Host", &dataobj_destination_host, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Destination-Realm", &dataobj_destination_realm, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"EAP-Master-Session-Key", &dataobj_eap_master_session_key, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"EAP-Key-Name", &dataobj_eap_key_name, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"EAP-Payload", &dataobj_eap_payload, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"EAP-Reissued-Payload", &dataobj_eap_reissued_payload, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Error-Message", &dataobj_error_message, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Error-Reporting-Host", &dataobj_error_reporting_host, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Failed-AVP", &dataobj_failed_avp, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Filter-Id", &dataobj_filter_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-AppleTalk-Link", &dataobj_framed_appletalk_link, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-AppleTalk-Network", &dataobj_framed_appletalk_network,
+					ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-AppleTalk-Zone", &dataobj_framed_appletalk_zone, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-Compression", &dataobj_framed_compression, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-Interface-Id", &dataobj_framed_interface_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-IP-Address", &dataobj_framed_ip_address, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-IP-Netmask", &dataobj_framed_ip_netmask, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-IPv6-Prefix", &dataobj_framed_ipv6_prefix, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-IPv6-Pool", &dataobj_framed_ipv6_pool, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-IPv6-Route", &dataobj_framed_ipv6_route, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-IPX-Network", &dataobj_framed_ipx_network, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-MTU", &dataobj_framed_mtu, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-Pool", &dataobj_framed_pool, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-Protocol", &dataobj_framed_protocol, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-Route", &dataobj_framed_route, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Framed-Routing", &dataobj_framed_routing, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Idle-Timeout", &dataobj_idle_timeout, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Multi-Round-Time-Out", &dataobj_multi_round_time_out, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-Filter-Rule", &dataobj_nas_filter_rule, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-Identifier", &dataobj_nas_identifier, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-IP-Address", &dataobj_nas_ip_address, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-IPv6-Address", &dataobj_nas_ipv6_address, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-Port", &dataobj_nas_port, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-Port-Id", &dataobj_nas_port_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"NAS-Port-Type", &dataobj_nas_port_type, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Originating-Line-Info", &dataobj_originating_line_info, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Origin-Host", &dataobj_origin_host, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Origin-Realm", &dataobj_origin_realm, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Origin-State-Id", &dataobj_origin_state_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Port-Limit", &dataobj_port_limit, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Proxy-Info", &dataobj_proxy_info, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"QoS-Filter-Rule", &dataobj_qos_filter_rule, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Re-Auth-Request-Type", &dataobj_re_auth_request_type, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Redirect-Host", &dataobj_redirect_host, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Redirect-Host-Usage", &dataobj_redirect_host_usage, ENOENT));
+	CHECK_FCT(
+			fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Redirect-Max-Cache-Time",
+					&dataobj_redirect_max_cache_time, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Reply-Message", &dataobj_reply_message, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Result-Code", &dataobj_result_code, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Route-Record", &dataobj_route_record, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Service-Type", &dataobj_service_type, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Session-Id", &dataobj_session_id, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Session-Timeout", &dataobj_session_timeout, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"State", &dataobj_state, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"Tunneling", &dataobj_tunneling, ENOENT));
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+					"User-Name", &dataobj_user_name, ENOENT));
+
+	return 0;
+}
+
+/* Parse the configuration file (using the yacc parser) */
+static int diameap_parse_conffile(void)
+{
+	if (!diameap_config->conffile)
+	{
+		TRACE_DEBUG (INFO,"%sNo configuration file to parse for DiamEAP Extension.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	extern FILE * diameapin;
+
+	TRACE_DEBUG (FULL, "%sParsing configuration file: %s",DIAMEAP_EXTENSION, diameap_config->conffile);
+	diameapin = fopen(diameap_config->conffile, "r");
+	if (!diameapin)
+	{
+		TRACE_DEBUG(INFO,"%sUnable to open configuration file %s for reading: %s",DIAMEAP_EXTENSION, diameap_config->conffile, strerror(errno));
+		return errno;
+	}
+
+	/* call yacc parser */
+	CHECK_FCT(diameapparse(diameap_config));
+
+	/* close the file */
+	CHECK_FCT(fclose(diameapin));
+	return 0;
+}
+
+int diameap_set_mysql_param(char * user, char * passwd, char * server,
+		char * database)
+{
+	TRACE_ENTRY("%p %p %p %p",user,passwd,server,database);
+	if (user == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sUnable to connect to MySQL Database Server: Empty user name or missing in the configuration file.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+
+	if (server == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sUnable to connect to MySQL Database Server: MySQL Database Server address missing in the configuration file.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	if (database == NULL)
+	{
+		TRACE_DEBUG(INFO,"%sUnable to connect to MySQL Database Server: MySQL Database name missing in configuration file.",DIAMEAP_EXTENSION);
+		return EINVAL;
+	}
+	diameap_config->db.user = user;
+	diameap_config->db.password = passwd;
+	diameap_config->db.server = server;
+	diameap_config->db.database = database;
+	return 0;
+}
+
+/* Connecting to MySQL Database */
+int diameap_mysql_connect(void)
+{
+	TRACE_ENTRY();
+	db_conn = mysql_init(NULL);
+	const my_bool mysql_reconnect_val=1;
+	mysql_options(db_conn,MYSQL_OPT_RECONNECT,&mysql_reconnect_val);
+	/* Connect to database */
+	if (!mysql_real_connect(db_conn, diameap_config->db.server,
+			diameap_config->db.user, diameap_config->db.password,
+			diameap_config->db.database, 0, NULL, 0))
+	{
+		TRACE_DEBUG(INFO,"%sConnection to MySQL Database Server failed: %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+		return errno;
+	}
+	return 0;
+}
+
+static void diameap_conf_dump(void)
+{
+
+	if (!TRACE_BOOL(INFO))
+		return;
+
+	fd_log_debug("-------- DiamEAP extension : Configuration parameters (Dump) -------------");
+	fd_log_debug("\t-Configuration file.....: %s", diameap_config->conffile);
+	fd_log_debug("\t-EAP Application Id.....: %u",
+			diameap_config->application_id);
+	fd_log_debug("\t-EAP Application Command: %u",
+			diameap_config->command_code);
+	fd_log_debug("\t-EAP Application Vendor.: %u", diameap_config->vendor_id);
+	fd_log_debug("\t-Max invalid EAP packets: %u", diameap_config->max_invalid_eap_packet);
+	fd_log_debug("\t-Multi-Round Timeout....: %u", diameap_config->multi_round_time_out);
+	if (diameap_config->db.user)
+	{
+		fd_log_debug("\t-MySQL Database Params..:");
+		fd_log_debug("\t\tUser .......:%s", diameap_config->db.user);
+		fd_log_debug("\t\tServer .....:%s", diameap_config->db.server);
+		fd_log_debug("\t\tDatabase....:%s", diameap_config->db.database);
+	}
+
+	fd_log_debug("\t-EAP Method Plugins.....: ");
+	diameap_plugin_dump();
+
+	fd_log_debug("-------- DiamEAP extension : Configuration parameters (End) ---------------");
+}
+
+int diameap_init(char * conffile)
+{
+	TRACE_ENTRY("%p",conffile);
+
+	/* Initialize the diameap_config structure*/
+	CHECK_FCT(diameap_init_config(conffile));
+
+	if (diameap_config->conffile)
+	{
+		/* parse the configuration file*/
+		CHECK_FCT(diameap_parse_conffile());
+
+		/* Load EAP methods plug-ins */
+		CHECK_FCT(diameap_plugin_load());
+
+	}
+	else
+	{
+		TRACE_DEBUG(FULL,"%sNo EAP method plug-in available with a default configuration.",DIAMEAP_EXTENSION);
+	}
+
+	/* Initialize Dictionary templates */
+	CHECK_FCT(diameap_init_obj());
+
+	/* Initialize access to user's information Database */
+	CHECK_FCT(diameap_mysql_connect());
+
+	/* Dump DiamEAP extension configuration */
+	diameap_conf_dump();
+
+	return 0;
+}
diff --git a/extensions/app_diameap/diameap_mysql.c b/extensions/app_diameap/diameap_mysql.c
new file mode 100644
index 0000000..b7a09c5
--- /dev/null
+++ b/extensions/app_diameap/diameap_mysql.c
@@ -0,0 +1,234 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "diameap_mysql.h"
+
+static pthread_mutex_t db_cs_mutex =
+PTHREAD_MUTEX_INITIALIZER;
+
+int diameap_get_eap_user(struct eap_user * user, char * username)
+{
+	TRACE_ENTRY("%p %p",user,username);
+	if (db_conn == NULL)
+	{
+		TRACE_DEBUG(INFO, "%sNot connected to the MySQL Database server.",DIAMEAP_EXTENSION);
+
+		return EINVAL;
+
+	}
+	mysql_thread_init();
+
+	MYSQL_RES *res;
+	MYSQL_ROW row;
+	char * query;
+	CHECK_MALLOC(query=(char *)malloc(sizeof(char)*255));
+
+	sprintf(
+			query,
+			"SELECT id,username,password,eapmethod, vendor FROM users WHERE  users.username='%s' and users.active='Y' ",
+			username);
+
+	CHECK_POSIX(pthread_mutex_lock( &db_cs_mutex ));
+
+	if (mysql_query(db_conn, query))
+	{
+		CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+		TRACE_DEBUG(INFO, "%sQuery execution fail. %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+		mysql_thread_end();
+		free(query);
+		query = NULL;
+		return EINVAL;
+	}
+
+	res = mysql_store_result(db_conn);
+
+	CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+
+	if ((row = mysql_fetch_row(res)) != NULL)
+	{
+
+		user->id = atoi(row[0]);
+		CHECK_MALLOC(user->userid=malloc(strlen(row[1])+1));
+		memcpy(user->userid,row[1],strlen(row[1])+1);
+		user->useridLength = strlen(row[1]);
+		CHECK_MALLOC(user->password=malloc(strlen(row[2])+1));
+		memcpy(user->password, row[2],strlen(row[2])+1);
+		user->passwordLength = strlen(row[2]);
+		user->proposed_eap_method = atoi(row[3]);
+		user->proposed_eap_method_vendor = atoi(row[4]);
+
+		mysql_free_result(res);
+		mysql_thread_end();
+		free(query);
+		query = NULL;
+		return 0;
+	}
+
+	TRACE_DEBUG(INFO, "%sUser unavailable.",DIAMEAP_EXTENSION);
+	mysql_free_result(res);
+	mysql_thread_end();
+	free(query);
+	query = NULL;
+	return EINVAL;
+
+}
+
+int diameap_authentication_get_attribs(struct eap_user *user,
+		struct fd_list * attribute_list)
+{
+
+	TRACE_ENTRY("%p %p",user,attribute_list);
+
+	if (db_conn == NULL)
+	{
+		TRACE_DEBUG(INFO, "%sNot connected to the MySQL Database server.",DIAMEAP_EXTENSION);
+
+		return EINVAL;
+
+	}
+
+	mysql_thread_init();
+	MYSQL_RES *res;
+	MYSQL_ROW row;
+	char * query;
+	CHECK_MALLOC(query=malloc(sizeof(char)*255));
+
+	sprintf(
+			query,
+			"SELECT `authe`.`attribute` ,`authe`.`value` FROM `authe` WHERE `authe`.`grp` IN ( SELECT `user_grp`.`grp` FROM `user_grp` WHERE `user_grp`.`user` = %d ) ",
+			user->id);
+
+	CHECK_POSIX(pthread_mutex_lock( &db_cs_mutex ));
+
+	if (mysql_query(db_conn, query))
+	{
+		CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+		TRACE_DEBUG(INFO, "%sQuery execution fail. %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+		mysql_thread_end();
+		free(query);
+		query = NULL;
+		return EINVAL;
+	}
+
+	res = mysql_store_result(db_conn);
+
+	CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+
+	while ((row = mysql_fetch_row(res)))
+	{
+		struct auth_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct auth_attribute)));
+		memset(attribute, 0, sizeof(struct auth_attribute));
+		fd_list_init(&attribute->chain, NULL);
+		attribute->attrib = strdup(row[0]);
+		attribute->op = NULL;
+		attribute->value = strdup(row[1]);
+		fd_list_insert_before(attribute_list, &attribute->chain);
+
+	}
+
+	mysql_free_result(res);
+	mysql_thread_end();
+	free(query);
+	query = NULL;
+	return 0;
+}
+
+int diameap_authorization_get_attribs(struct eap_user *user,
+		struct fd_list * attribute_list)
+{
+	TRACE_ENTRY("%p %p",user,attribute_list);
+
+	if (db_conn == NULL)
+	{
+		TRACE_DEBUG(INFO, "%sNot connected to the MySQL Database server.",DIAMEAP_EXTENSION);
+
+		return EINVAL;
+
+	}
+
+	mysql_thread_init();
+
+	MYSQL_RES *res;
+	MYSQL_ROW row;
+	char * query;
+	CHECK_MALLOC(query=malloc(sizeof(char)*255));
+
+	sprintf(
+			query,
+			"SELECT `authz`.`attribute` , `authz`.`op` , `authz`.`value` FROM `authz` WHERE `authz`.`grp` IN ( SELECT `user_grp`.`grp` FROM `user_grp` WHERE `user_grp`.`user` = %d ) ",
+			user->id);
+
+	CHECK_POSIX(pthread_mutex_lock( &db_cs_mutex ));
+
+	if (mysql_query(db_conn, query))
+	{
+		CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+		TRACE_DEBUG(INFO, "%sQuery execution fail. %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+		mysql_thread_end();
+		free(query);
+		query = NULL;
+		return EINVAL;
+	}
+
+	res = mysql_store_result(db_conn);
+
+	CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+
+	while ((row = mysql_fetch_row(res)))
+	{
+		struct auth_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct auth_attribute)));
+		memset(attribute, 0, sizeof(struct auth_attribute));
+		fd_list_init(&attribute->chain, NULL);
+		attribute->attrib = strdup(row[0]);
+		attribute->op = strdup(row[1]);
+		attribute->value = strdup(row[2]);
+		fd_list_insert_before(attribute_list, &attribute->chain);
+	}
+
+	mysql_free_result(res);
+	mysql_thread_end();
+	free(query);
+	query = NULL;
+	return 0;
+}
+
+void diameap_mysql_disconnect()
+{
+	mysql_close(db_conn);
+}
diff --git a/extensions/app_diameap/diameap_mysql.h b/extensions/app_diameap/diameap_mysql.h
new file mode 100644
index 0000000..c217dc6
--- /dev/null
+++ b/extensions/app_diameap/diameap_mysql.h
@@ -0,0 +1,67 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_MYSQL_H_
+#define DIAMEAP_MYSQL_H_
+
+#include "libdiameap.h"
+#include <mysql.h>
+
+/* MySQL Database connection */
+MYSQL *db_conn;
+
+int diameap_get_eap_user(struct eap_user * user, char * username);
+
+int diameap_mysql_connect();
+
+int diameap_mysql_reconnect();
+
+int diameap_set_mysql_param(char * user, char * passwd, char * server, char * database);
+
+void diameap_mysql_disconnect();
+
+/* */
+int diameap_authentication_get_attribs(struct eap_user *user,
+			struct fd_list * attribute_list);
+
+/* */
+int diameap_authorization_get_attribs(struct eap_user *user,
+			struct fd_list * attribute_list);
+
+
+#endif /* DIAMEAP_MYSQL_H_ */
diff --git a/extensions/app_diameap/diameap_plugins.c b/extensions/app_diameap/diameap_plugins.c
new file mode 100644
index 0000000..836c686
--- /dev/null
+++ b/extensions/app_diameap/diameap_plugins.c
@@ -0,0 +1,455 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 CONTRIBUTfORS 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 "diameap_common.h"
+
+/********************************************/
+/*	Loading and initializing plug-ins		*/
+/********************************************/
+
+/* Add new plugin */
+int diameap_plugin_add(char * name, eap_type methodtype, u32 vendor,
+		char * filename, char * conffile)
+{
+	TRACE_ENTRY("%p %d %d %p %p", name, methodtype, vendor, filename, conffile);
+
+	/* Check the filename is valid */
+	CHECK_PARAMS(filename);
+
+	/* add new EAP method  in the list of plugins*/
+	{
+		struct plugin * plugin;
+		CHECK_MALLOC(plugin = malloc(sizeof(struct plugin)));
+		memset(plugin, 0, sizeof(struct plugin));
+		fd_list_init(&plugin->chain, plugin);
+		plugin->methodname = name;
+		plugin->methodtype = methodtype;
+		plugin->vendor = vendor;
+		plugin->pluginfile = filename;
+		plugin->conffile = conffile;
+		fd_list_insert_before(&plugins_list, &plugin->chain);
+	}
+
+	return 0;
+}
+
+/* Dump plugins list */
+void diameap_plugin_dump(void)
+{
+	struct fd_list * pl;
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		fd_log_debug("\t\t - %s plugin \t [Type: %i, Vendor: %i]  %sloaded", plugin->methodname,
+				plugin->methodtype,plugin->vendor, plugin->handler ? "" : "not ");
+	}
+}
+
+int diameap_plugin_get(u32 vendor, eap_type type, struct plugin ** getplugin)
+{
+	TRACE_ENTRY("%d %d %p",vendor,type,getplugin);
+	struct fd_list * pl;
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		if (plugin->methodtype == type && plugin->vendor == vendor)
+		{
+			*getplugin = plugin;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/* Load all method in the plugins list */
+int diameap_plugin_load(void)
+{
+
+	int ret;
+	struct fd_list * pl;
+
+	/* Loop on all plugins */
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		struct register_plugin * registerplugin;
+		int (*diameap_plugin_register)();
+
+		TRACE_DEBUG(FULL, "%sLoading EAP method plugin: %s",DIAMEAP_EXTENSION, plugin->methodname);
+
+		/* Load the method */
+		plugin->handler = dlopen(plugin->pluginfile, RTLD_LAZY | RTLD_GLOBAL);
+		if (plugin->handler == NULL)
+		{
+			TRACE_DEBUG(INFO, "%sLoading of plugin %s failed: %s",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		/* Defined register methods for this EAP method*/
+		diameap_plugin_register = (int(*)()) dlsym(plugin->handler,
+				"diameap_plugin_register");
+		if (!diameap_plugin_register)
+		{
+			TRACE_DEBUG(INFO,
+					"%s[%s plugin] Unable to register EAP method: %s.",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		if ((*diameap_plugin_register)() != 0)
+		{
+			TRACE_DEBUG(INFO,
+					"%s[%s plugin] Unable to register EAP method plugin",DIAMEAP_EXTENSION,plugin->methodname);
+		}
+
+		int (*diameap_plugin_objects)(struct register_plugin **);
+
+		diameap_plugin_objects = (int(*)(struct register_plugin **)) dlsym(
+				plugin->handler, "diameap_plugin_objects");
+		if (!diameap_plugin_objects)
+		{
+			TRACE_DEBUG(INFO,
+					"%s[%s plugin] Unable to resolve symbol of the plugin: %s",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		if ((*diameap_plugin_objects)(&registerplugin) != 0)
+		{
+
+			TRACE_DEBUG(
+					INFO,
+					"%s[%s plugin] Unable to get objects description from the plug-in: %s",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		/* eap_method_configure method */
+		if (registerplugin->configure)
+		{
+			plugin->eap_method_configure = (int(*)(char *)) dlsym(
+					plugin->handler, registerplugin->configure);
+			if (plugin->eap_method_configure == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_configure': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+			}
+		}
+		else
+		{
+			plugin->eap_method_configure = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_configure'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_init method */
+		if (registerplugin->init)
+		{
+			plugin->eap_method_init
+					= (int(*)(struct eap_state_machine *)) dlsym(
+							plugin->handler, registerplugin->init);
+			if (plugin->eap_method_init == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_init': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_init = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_init'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_initPickUp method */
+		if (registerplugin->initPickUp)
+		{
+			plugin->eap_method_initPickUp
+					= (int(*)(struct eap_state_machine *)) dlsym(
+							plugin->handler, registerplugin->initPickUp);
+		}
+		else
+		{
+			plugin->eap_method_initPickUp = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_initPickUp'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_buildReq method */
+		if (registerplugin->buildReq)
+		{
+			plugin->eap_method_buildReq = (int(*)(struct eap_state_machine *,
+					u8, struct eap_packet *)) dlsym(plugin->handler,
+					registerplugin->buildReq);
+			if (plugin->eap_method_buildReq == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_buildReq': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_buildReq = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_buildReq'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_getTimeout method */
+		if (registerplugin->getTimeout)
+		{
+			plugin->eap_method_getTimeout = (int(*)(struct eap_state_machine *,
+					int *)) dlsym(plugin->handler, registerplugin->getTimeout);
+			if (plugin->eap_method_getTimeout == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_getTimeout': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_getTimeout = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function  'eap_method_getTimeout'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_check method */
+		if (registerplugin->check)
+		{
+			plugin->eap_method_check = (boolean(*)(struct eap_state_machine *,
+					struct eap_packet*)) dlsym(plugin->handler,
+					registerplugin->check);
+			if (plugin->eap_method_check == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_check': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_check = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_check'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_process method */
+		if (registerplugin->process)
+		{
+			plugin->eap_method_process = (int(*)(struct eap_state_machine *,
+					struct eap_packet*)) dlsym(plugin->handler,
+					registerplugin->process);
+			if (plugin->eap_method_process == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_process': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_process = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_process'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_isDone method */
+		if (registerplugin->isDone)
+		{
+			plugin->eap_method_isDone
+					= (boolean(*)(struct eap_state_machine *)) dlsym(
+							plugin->handler, registerplugin->isDone);
+			if (plugin->eap_method_isDone == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_isDone': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_isDone = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_isDone'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_getKey method */
+		if (registerplugin->getKey)
+		{
+			plugin->eap_method_getKey = (int(*)(struct eap_state_machine *,
+					u8**, int*,u8**, int*)) dlsym(plugin->handler, registerplugin->getKey);
+			if (plugin->eap_method_getKey == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_getKey': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_getKey = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_getKey'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_unregister method */
+		if (registerplugin->unregister)
+		{
+			plugin->eap_method_unregister = (void(*)(void)) dlsym(
+					plugin->handler, registerplugin->unregister);
+			if (plugin->eap_method_unregister == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_unregister': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_unregister = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_unregister'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_datafree method */
+		if (registerplugin->datafree)
+		{
+			plugin->eap_method_free = (void(*)(void *)) dlsym(plugin->handler,
+					registerplugin->datafree);
+			if (plugin->eap_method_free == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_datafree': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_free = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_datafree'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		if (plugin->eap_method_configure != NULL)
+		{
+			/* call the configuration method */
+			ret = (*plugin->eap_method_configure)(plugin->conffile);
+			if (ret != 0)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to configure the plugin",DIAMEAP_EXTENSION,
+						plugin->methodname);
+				return ret;
+			}
+		}
+
+		TRACE_DEBUG(FULL, "%s[%s plugin] Loaded successfully.",DIAMEAP_EXTENSION,
+				plugin->methodname);
+
+		/* load next method */
+	}
+
+	return 0;
+}
+
+boolean diameap_plugin_exist(u32 vendor, eap_type type)
+{
+
+	TRACE_ENTRY("%d %d",vendor,type);
+	struct fd_list * pl;
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		if (plugin->methodtype == type && plugin->vendor == vendor)
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+int diameap_plugin_unload(void)
+{
+
+	while (!FD_IS_LIST_EMPTY(&plugins_list))
+	{
+		struct fd_list * plugin = plugins_list.next;
+		struct plugin * item = (struct plugin *) plugin;
+
+		fd_list_unlink(plugin);
+
+		if (item->eap_method_unregister != NULL)
+		{
+			(*item->eap_method_unregister)();
+		}
+
+		if (item->handler)
+		{
+			if (dlclose(item->handler) != 0)
+			{
+				TRACE_DEBUG (INFO, "%sFail to unload plugin %s : %s",DIAMEAP_EXTENSION, item->methodname, dlerror());
+			}
+		}
+
+		free(item->conffile);
+		free(item->pluginfile);
+		free(item);
+	}
+	return 0;
+}
diff --git a/extensions/app_diameap/diameap_plugins.h b/extensions/app_diameap/diameap_plugins.h
new file mode 100644
index 0000000..9a12c39
--- /dev/null
+++ b/extensions/app_diameap/diameap_plugins.h
@@ -0,0 +1,67 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_PLUGINS_H_
+#define DIAMEAP_PLUGINS_H_
+
+#include <dlfcn.h>
+
+
+
+static struct fd_list plugins_list = FD_LIST_INITIALIZER(plugins_list);
+
+/* Add a plug-in to the list of plugins*/
+int diameap_plugin_add(char * name, eap_type methodtype, u32 vendor, char * filename,
+		char * conffile);
+
+/* Dump all plug-ins (plugins_list)*/
+void diameap_plugin_dump();
+
+/* Return pointer to a plug-in */
+int diameap_plugin_get(u32 vendor,eap_type type, struct plugin ** getplugin);
+
+/* Load plug-ins */
+int diameap_plugin_load(void);
+
+/* Check if a plug-in exists for a given EAP method type */
+boolean diameap_plugin_exist(u32 vendor, eap_type type);
+
+/* Unload all plug-ins*/
+int diameap_plugin_unload(void);
+
+#endif /* DIAMEAP_PLUGINS_H_ */
diff --git a/extensions/app_diameap/diameap_server.c b/extensions/app_diameap/diameap_server.c
new file mode 100644
index 0000000..b93f6bb
--- /dev/null
+++ b/extensions/app_diameap/diameap_server.c
@@ -0,0 +1,3419 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "diameap_common.h"
+
+/* handler for DiamEAP server callback */
+static struct disp_hdl * handle;
+
+/* session handler for DiamEAP sessions state machine */
+static struct session_handler * diameap_server_reg = NULL;
+
+
+struct avp_max_occurences auth_avps[] =
+{
+{ "Service-Type", 1 },
+{ "Callback-Number", 1 },
+{ "Callback-Id", 1 },
+{ "Idle-Timeout", 1 },
+{ "Port-Limit", 1 },
+{ "NAS-Filter-Rule" - 1 },
+{ "Filter-Id", -1 },
+{ "Configuration-Token", -1 },
+{ "QoS-Filter-Rule", -1 },
+{ "Framed-Protocol", 1 },
+{ "Framed-Routing", 1 },
+{ "Framed-MTU", 1 },
+{ "Framed-Compression", -1 },
+{ "Framed-IP-Address", 1 },
+{ "Framed-IP-Netmask", 1 },
+{ "Framed-Route", -1 },
+{ "Framed-Pool", 1 },
+{ "Framed-Interface-Id", 1 },
+{ "Framed-IPv6-Prefix", -1 },
+{ "Framed-IPv6-Pool", 1 },
+{ "Framed-IPv6-Route", -1 },
+{ "Framed-IPX-Network", 1 },
+{ "Framed-Appletalk-Link", 1 },
+{ "Framed-Appletalk-Network", -1 },
+{ "Framed-Appletalk-Zone", 1 },
+{ "NAS-IPv6-Address", 0 },
+{ "NAS-Identifier", 0 },
+{ "NAS-IP-Address", 0 },
+{ "NAS-Port", 0 },
+{ "NAS-Port-Id", 0 },
+{ "NAS-Port-Type", 0 },
+{ "Called-Station-Id", 0 },
+{ "Calling-Station-Id", 0 },
+{ "Connect-Info", 0 },
+{ "Originating-Line-Info", 0 } };
+
+
+
+void diameap_cli_sess_cleanup(struct sess_state * diameap_sess_data, os0_t sid, void * opaque)
+{
+
+	CHECK_PARAMS_DO( diameap_sess_data, return );
+
+	if (diameap_sess_data != NULL)
+	{
+		if (diameap_sess_data->methodData != NULL)
+		{
+			struct plugin * cplugin;
+			if (diameap_plugin_get(diameap_sess_data->currentVendor,
+					diameap_sess_data->currentMethod, &cplugin))
+			{
+				TRACE_DEBUG(INFO,"%sUnable to access EAP Method plugin {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,diameap_sess_data->currentMethod,diameap_sess_data->currentVendor);
+			}
+
+			if (cplugin->eap_method_free)
+			{
+				(*cplugin->eap_method_free)(diameap_sess_data->methodData);
+				diameap_sess_data->methodData = NULL;
+			}
+			else
+			{
+				TRACE_DEBUG(FULL+1,"%s[%s plugin] datafree function not available.",DIAMEAP_EXTENSION,cplugin->methodname);
+				if (diameap_sess_data->methodData != NULL)
+				{
+					free(diameap_sess_data->methodData);
+					diameap_sess_data->methodData = NULL;
+				}
+			}
+			if (diameap_sess_data->methodData)
+			{
+				TRACE_DEBUG(INFO,"%sSession state was not been freed correctly!!!",DIAMEAP_EXTENSION);
+			}
+		}
+
+		if (diameap_sess_data->user.password != NULL)
+		{
+			free(diameap_sess_data->user.password);
+			diameap_sess_data->user.password = NULL;
+		}
+
+		if (diameap_sess_data->user.userid != NULL)
+		{
+			free(diameap_sess_data->user.userid);
+			diameap_sess_data->user.userid = NULL;
+		}
+		free(diameap_sess_data);
+		diameap_sess_data = NULL;
+	}
+}
+
+static int diameap_initialize_diameap_sm(
+		struct diameap_state_machine * diameap_sm,
+		struct sess_state * diameap_sess_data)
+{
+	TRACE_ENTRY("%p %p", diameap_sm, diameap_sess_data);
+
+	int i;
+
+	/* Initialize Long Term Variables */
+	if (diameap_sess_data != NULL)
+	{
+		diameap_sm->invalid_eappackets = diameap_sess_data->invalid_eappackets;
+
+		/* Initialize eap state machine variables */
+		/*User*/
+		diameap_sm->eap_sm.user.id = diameap_sess_data->user.id;
+
+		if ((diameap_sess_data->user.userid != NULL)
+				&& (diameap_sess_data->user.useridLength > 0))
+		{
+			diameap_sm->eap_sm.user.useridLength
+					= diameap_sess_data->user.useridLength;
+			CHECK_MALLOC(diameap_sm->eap_sm.user.userid= malloc(diameap_sm->eap_sm.user.useridLength+1));
+			U8COPY(diameap_sm->eap_sm.user.userid,0,diameap_sm->eap_sm.user.useridLength+1,diameap_sess_data->user.userid);
+			free(diameap_sess_data->user.userid);
+			diameap_sess_data->user.userid = NULL;
+
+		}
+		else
+		{
+			TRACE_DEBUG(INFO,"%s user not identified yet.",DIAMEAP_EXTENSION);
+			diameap_sm->eap_sm.user.useridLength = 0;
+			diameap_sm->eap_sm.user.userid = NULL;
+		}
+
+		if ((diameap_sess_data->user.password != NULL)
+				&& (diameap_sess_data->user.passwordLength > 0))
+		{
+			diameap_sm->eap_sm.user.passwordLength
+					= diameap_sess_data->user.passwordLength;
+			CHECK_MALLOC(diameap_sm->eap_sm.user.password = malloc(diameap_sm->eap_sm.user.passwordLength+1));
+			U8COPY(diameap_sm->eap_sm.user.password,0,diameap_sm->eap_sm.user.passwordLength+1, diameap_sess_data->user.password);
+			free(diameap_sess_data->user.password);
+			diameap_sess_data->user.password = NULL;
+		}
+		else
+		{
+			diameap_sm->eap_sm.user.passwordLength = 0;
+			diameap_sm->eap_sm.user.password = NULL;
+		}
+
+		diameap_sm->eap_sm.user.methodId = diameap_sess_data->user.methodId;
+		for (i = 0; i < MAXMETHODS; i++)
+		{
+			diameap_sm->eap_sm.user.methods[i].method
+					= diameap_sess_data->user.methods[i].method;
+			diameap_sm->eap_sm.user.methods[i].vendor
+					= diameap_sess_data->user.methods[i].vendor;
+		}
+		for (i = 0; i < MAXPROPOSEDMETHODS; i++)
+		{
+			diameap_sm->eap_sm.user.proposedmethods[i].method
+					= diameap_sess_data->user.proposedmethods[i].method;
+			diameap_sm->eap_sm.user.proposedmethods[i].vendor
+					= diameap_sess_data->user.proposedmethods[i].vendor;
+		}
+
+		diameap_sm->eap_sm.user.pmethods = diameap_sess_data->user.pmethods;
+		diameap_sm->eap_sm.user.proposed_eap_method
+				= diameap_sess_data->user.proposed_eap_method;
+		diameap_sm->eap_sm.user.proposed_eap_method_vendor
+				= diameap_sess_data->user.proposed_eap_method_vendor;
+		diameap_sm->eap_sm.user.success = diameap_sess_data->user.success;
+
+		diameap_sm->eap_sm.currentId = diameap_sess_data->currentId;
+		diameap_sm->eap_sm.currentVendor = diameap_sess_data->currentVendor;
+		diameap_sm->eap_sm.lastId = diameap_sess_data->lastId;
+		diameap_sm->eap_sm.methodState = diameap_sess_data->methodState;
+		diameap_sm->eap_sm.currentMethod = diameap_sess_data->currentMethod;
+
+		diameap_sm->eap_sm.methodData = diameap_sess_data->methodData;
+		diameap_sess_data->methodData = NULL;
+
+		if (diameap_sm->eap_sm.currentMethod != TYPE_NONE)
+		{
+			diameap_plugin_get(diameap_sm->eap_sm.currentVendor,
+					diameap_sm->eap_sm.currentMethod,
+					&diameap_sm->eap_sm.selectedMethod);
+		}
+
+		/* free session data*/
+		free(diameap_sess_data);
+		diameap_sess_data = NULL;
+
+	}
+	else
+	{
+		diameap_sm->invalid_eappackets = 0;
+
+		/* Initialize eap state machine variables */
+		/*User*/
+		diameap_sm->eap_sm.user.id = 0;
+		diameap_sm->eap_sm.user.userid = NULL;
+		diameap_sm->eap_sm.user.useridLength = 0;
+		diameap_sm->eap_sm.user.password = NULL;
+		diameap_sm->eap_sm.user.passwordLength = 0;
+		diameap_sm->eap_sm.user.methodId = -1;
+		for (i = 0; i < MAXMETHODS; i++)
+		{
+			diameap_sm->eap_sm.user.methods[i].method = TYPE_NONE;
+			diameap_sm->eap_sm.user.methods[i].vendor = VENDOR_IETF;
+		}
+		for (i = 0; i < MAXPROPOSEDMETHODS; i++)
+		{
+			diameap_sm->eap_sm.user.proposedmethods[i].method = TYPE_NONE;
+			diameap_sm->eap_sm.user.proposedmethods[i].vendor = VENDOR_IETF;
+		}
+
+		diameap_sm->eap_sm.user.pmethods = -1;
+		diameap_sm->eap_sm.user.proposed_eap_method = TYPE_NONE;
+		diameap_sm->eap_sm.user.proposed_eap_method_vendor = VENDOR_IETF;
+		diameap_sm->eap_sm.user.success = FALSE;
+
+		diameap_sm->eap_sm.currentId = -1;
+		diameap_sm->eap_sm.currentVendor = VENDOR_IETF;
+		diameap_sm->eap_sm.lastId = -1;
+		diameap_sm->eap_sm.methodState = EAP_M_PROPOSED;
+
+		diameap_sm->eap_sm.currentMethod = TYPE_NONE;
+
+		diameap_sm->eap_sm.methodData = NULL;
+
+	}
+
+	diameap_sm->result_code = 0;
+	fd_list_init(&diameap_sm->attributes, NULL);
+	fd_list_init(&diameap_sm->req_attributes, NULL);
+	fd_list_init(&diameap_sm->ans_attributes, NULL);
+	diameap_sm->failedavp = NULL;
+	diameap_sm->auth_request_val = AUTHENTICATE_ONLY;
+	diameap_sm->verify_authorization = FALSE;
+	diameap_sm->authSuccess = FALSE;
+	diameap_sm->authFailure = FALSE;
+	diameap_sm->lastReqEAPavp = NULL;
+	diameap_sm->privateUser = FALSE;
+	diameap_sm->authorized = FALSE;
+
+	diameap_sm->eap_sm.rxResp = FALSE;
+	diameap_sm->eap_sm.respId = -1;
+	diameap_sm->eap_sm.respMethod = TYPE_NONE;
+	diameap_sm->eap_sm.respVendor = VENDOR_IETF;
+	diameap_sm->eap_sm.respVendorMethod = TYPE_NONE;
+
+	return 0;
+}
+
+static int diameap_initialize_diameap_eap_interface(
+		struct diameap_eap_interface * eap_i)
+{
+	TRACE_ENTRY("%p", eap_i);
+
+	//Initialize AAA-EAP Interface
+	eap_i->aaaEapResp = FALSE;
+	eap_i->aaaEapRespData.data = NULL;
+	//Initialize EAP-AAA Interface
+	eap_i->aaaEapReq = FALSE;
+	eap_i->aaaEapNoReq = FALSE;
+	eap_i->aaaSuccess = FALSE;
+	eap_i->aaaFail = FALSE;
+	eap_i->aaaEapReqData.data = NULL;
+	eap_i->aaaEapMSKData = NULL;
+	eap_i->aaaEapEMSKData = NULL;
+	eap_i->aaaEapKeyAvailable = FALSE;
+	eap_i->aaaMethodTimeout = 0;
+
+	return 0;
+}
+
+static int diameap_failed_avp(struct diameap_state_machine * diameap_sm,
+		struct avp * invalidavp)
+{
+	TRACE_ENTRY("%p %p",diameap_sm,invalidavp);
+	if (!invalidavp)
+		return EINVAL;
+
+	if (!diameap_sm)
+		return EINVAL;
+
+	if (diameap_sm->failedavp == NULL)
+	{
+		CHECK_FCT( fd_msg_avp_new( dataobj_failed_avp, 0, &diameap_sm->failedavp) );
+
+		CHECK_FCT( fd_msg_avp_add( diameap_sm->failedavp, MSG_BRW_LAST_CHILD, invalidavp ) );
+
+	}
+	else
+	{
+		//add multiple AVPs in Failed-AVP
+	}
+	return 0;
+}
+
+static int diameap_parse_eap_resp(struct eap_state_machine * eap_sm,
+		struct eap_packet *eappacket)
+{
+	TRACE_ENTRY("%p %p",eap_sm, eappacket)
+
+	eap_sm->rxResp = FALSE;
+	eap_sm->respId = -1;
+	eap_sm->respMethod = TYPE_NONE;
+	eap_sm->respVendor = VENDOR_IETF;
+	eap_sm->respVendorMethod = TYPE_NONE;
+
+	if (eappacket->data == NULL)
+	{
+		TRACE_DEBUG(INFO,"%s Empty EAP packet",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	u16 plength;
+	CHECK_FCT(diameap_eap_get_packetlength(eappacket,&plength));
+	if ((int) plength < EAP_HEADER)
+	{
+		TRACE_DEBUG(INFO,"%s EAP packet length less than EAP header.",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	u16 length;
+	CHECK_FCT(diameap_eap_get_length(eappacket,&length));
+	if ((int) length < EAP_HEADER)
+	{
+		TRACE_DEBUG(INFO,"%sEAP packet length field less than EAP header.",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	if (plength < length)
+	{
+		TRACE_DEBUG(INFO,"%sLength of received EAP packet is less than the value of the length field.",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	eap_code code;
+	CHECK_FCT(diameap_eap_get_code(eappacket,&code));
+	if (code == EAP_REQUEST || code == EAP_SUCCESS || code == EAP_FAILURE)
+	{
+		TRACE_DEBUG(INFO,"%sOnly EAP Responses are accepted at EAP server side.",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	u8 id;
+	CHECK_FCT(diameap_eap_get_identifier(eappacket,&id));
+	eap_sm->respId = id;
+
+	CHECK_FCT(diameap_eap_get_type(eappacket,&eap_sm->respMethod));
+	if ((eap_sm->methodState != EAP_M_PROPOSED) && (eap_sm->respMethod
+			== TYPE_NAK || eap_sm->respMethod == TYPE_EXPANDED_TYPES))
+	{
+		TRACE_DEBUG(INFO,"%sNAK or EXPANDED_NAK received after an EAP TYPE been selected",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	if ((eap_sm->respMethod == TYPE_EXPANDED_TYPES) && (length < 20))
+	{
+		TRACE_DEBUG(INFO,"%s Truncated EAP Packet received.",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	if ((eap_sm->respMethod == TYPE_NAK) && (eap_sm->currentMethod < 4))
+	{
+		TRACE_DEBUG(INFO,"%sNAK response not expected at this step (Only EAP type = 4 and above are accepted).",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	if (eap_sm->respMethod == TYPE_EXPANDED_TYPES)
+	{
+		u8 *data = (u8 *) eappacket->data;
+		//int len = 0;
+		//u32 respVendor, respVendorMethod;
+		data += 5;
+		eap_sm->respVendor = G24BIGE(data);
+		data += 3;
+		eap_sm->respVendorMethod = G32BIGE(data);
+		data += 4;
+		/*		while ((length - 12) > (len * 8))
+		 {
+		 if (((eap_type) G8(data)) != TYPE_EXPANDED_TYPES)
+		 {
+		 return FALSE;
+		 }
+		 data += 1;
+		 respVendor = G24BIGE(data);
+		 data += 3;
+		 respVendorMethod = G32BIGE(data);
+		 eap_sm->user.proposedmethods[len].method = respVendor;
+		 eap_sm->user.proposedmethods[len].vendor = respVendorMethod;
+		 len++;
+		 data += 4;
+		 }
+		 eap_sm->user.methodId = 0;*/
+	}
+
+	if((eap_sm->respMethod == TYPE_IDENTITY) && (length < 6)){
+		TRACE_DEBUG(INFO,"%sUser Identity missing",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	eap_sm->rxResp = TRUE;
+	return 0;
+}
+
+static int diameap_eappacket_new(struct eap_packet * eappacket,
+		struct avp_hdr * avpdata)
+{
+	TRACE_ENTRY("%p %p",eappacket,avpdata);
+	eappacket->ulength = (u16) avpdata->avp_value->os.len;
+	eappacket->data = (u8 *) avpdata->avp_value->os.data;
+	diameap_eap_get_packetlength(eappacket, &eappacket->length);
+	return 0;
+}
+
+static int diameap_parse_avps(struct diameap_state_machine * diameap_sm,
+		struct msg * req, struct diameap_eap_interface * eap_i)
+{
+	TRACE_ENTRY("%p %p %p",diameap_sm,req,eap_i);
+	struct avp * avp, *avp2;
+	struct avp_hdr * avpdata;
+	int ret;
+	int depth;
+
+	/* EAP-Payload data*/
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_payload, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		CHECK_FCT(diameap_eappacket_new(&eap_i->aaaEapRespData, avpdata));
+		eap_i->aaaEapResp = TRUE;
+		u16 length;
+		diameap_eap_get_length(&eap_i->aaaEapRespData, &length);
+		if (length >= 4)
+		{
+			eap_code code;
+			CHECK_FCT(diameap_eap_get_code(&eap_i->aaaEapRespData,&code));
+
+			if (code != EAP_RESPONSE)
+			{
+				diameap_sm->result_code = 5004; /* DIAMETER_INVALID_AVP_VALUE 5004 */
+				struct avp * invalidavp;
+				union avp_value val;
+				CHECK_FCT( fd_msg_avp_new ( dataobj_eap_payload, 0, &invalidavp));
+				val.os.data = eap_i->aaaEapRespData.data;
+				val.os.len = eap_i->aaaEapRespData.length;
+				CHECK_FCT( fd_msg_avp_setvalue( invalidavp, &val ))
+				CHECK_FCT( diameap_failed_avp(diameap_sm, invalidavp));
+				TRACE_DEBUG(INFO,"%sIncorrect EAP Packet. EAP Code != Response.",DIAMEAP_EXTENSION);
+				return 0;
+			}
+			else
+			{
+				CHECK_FCT(diameap_parse_eap_resp(&diameap_sm->eap_sm, &eap_i->aaaEapRespData));
+				if (diameap_sm->eap_sm.rxResp == FALSE)
+				{
+					diameap_sm->result_code = 1001; /*DIAMETER_MULTI_ROUND_AUTH*/
+					eap_i->aaaEapNoReq = TRUE;
+					eap_i->aaaEapResp = FALSE;
+				}
+			}
+		}
+		else
+		{
+			if (diameap_sm->eap_sm.currentMethod != TYPE_NONE)
+			{
+				diameap_sm->result_code = 5004; /* DIAMETER_INVALID_AVP_VALUE 5004 */
+				CHECK_FCT(diameap_failed_avp(diameap_sm, avp));
+				TRACE_DEBUG(INFO,"%sEAP packet length < Minimum EAP packet length.",DIAMEAP_EXTENSION);
+				return 1;
+			}
+			//EAP start received
+
+		}
+	}
+
+	/* User-Name AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_user_name, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "User-Name";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* EAP-Key-Name AVP */
+
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_key_name, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "EAP-Key-Name";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Auth-Request-Type AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_request_type, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		diameap_sm->auth_request_val = avpdata->avp_value->i32;
+	}
+
+	/* Authorization-Lifetime AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_authorization_lifetime, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Authorization-Lifetime";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Auth-Grace-Period AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_grace_period, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Auth-Grace-Period";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Auth-Session-State AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_session_state, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Auth-Session-State";
+		attribute->value.i32 = avpdata->avp_value->i32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Origin-state-Id AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_origin_state_id, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Origin-state-Id AVP";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* NAS-Port AVP*/
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "NAS-Port";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* NAS-Port-Id AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port_id, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "NAS-Port-Id";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* NAS-Port-Type AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port_type, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "NAS-Port-Type";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Called-Station-Id AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_called_station_id, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Called-Station-Id";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Calling-Station-Id AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_calling_station_id, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Calling-Station-Id";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Connect-Info AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_connect_info, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Connect-Info";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Originating-Line-Info AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_originating_line_info, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Originating-Line-Info";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Service-Type AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_service_type, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Service-Type";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Callback-Number AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_callback_number, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Callback-Number";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Port-Limit AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_port_limit, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Port-Limit";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Framed-Protocol AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_protocol, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Framed-Protocol";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Framed-MTU AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_mtu, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Framed-MTU";
+		attribute->value.u32 = avpdata->avp_value->u32;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Framed-Compression AVP */
+	avp = NULL;
+	avp2 = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_compression, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		u32 Pi_Code = avpdata->avp_code;
+		int depth;
+		do
+		{
+			struct avp_attribute * attribute;
+			CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+			memset(attribute, 0, sizeof(struct avp_attribute));
+			fd_list_init(&attribute->chain, attribute);
+			attribute->attrib = "Framed-Compression";
+			attribute->value.u32 = avpdata->avp_value->u32;
+			fd_list_insert_before(&diameap_sm->req_attributes,
+					&attribute->chain);
+			ret = 0;
+			depth = 0;
+			ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+			if (avp2 != NULL)
+			{
+				CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata));
+			}
+			avp = avp2;
+		} while ((avp2 != NULL) && (ret == 0) && (ret == 0)
+				&& (avpdata->avp_code == Pi_Code));
+	}
+
+	/* Framed-IP-Address AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ip_address, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Framed-IP-Address";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Framed-IP-Netmask AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ip_netmask, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Framed-IP-Netmask";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Framed-Interface-Id AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_interface_id, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "Framed-Interface-Id";
+		attribute->value.u64 = avpdata->avp_value->u64;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* Framed-IPv6-Prefix AVP */
+	avp = NULL;
+	avp2 = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ipv6_prefix, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		u32 Pi_Code = avpdata->avp_code;
+		do
+		{
+			struct avp_attribute * attribute;
+			CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+			memset(attribute, 0, sizeof(struct avp_attribute));
+			fd_list_init(&attribute->chain, attribute);
+			attribute->attrib = "Framed-IPv6-Prefix";
+			attribute->value.u32 = avpdata->avp_value->u32;
+			fd_list_insert_before(&diameap_sm->req_attributes,
+					&attribute->chain);
+			ret = 0;
+			depth = 0;
+			ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+			if (avp2 != NULL)
+			{
+				CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata));
+			}
+			avp = avp2;
+		} while ((avp2 != NULL) && (ret == 0) && (ret == 0)
+				&& (avpdata->avp_code == Pi_Code));
+	}
+
+	/* Tunneling AVP */
+	avp = NULL;
+	avp2 = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_tunneling, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		u32 Pi_Code = avpdata->avp_code;
+		int depth;
+		do
+		{
+			struct avp_attribute * attribute;
+			CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+			memset(attribute, 0, sizeof(struct avp_attribute));
+			fd_list_init(&attribute->chain, attribute);
+			attribute->attrib = "Tunneling";
+			//grouped AVP
+			fd_list_insert_before(&diameap_sm->req_attributes,
+					&attribute->chain);
+			ret = 0;
+			depth = 0;
+			ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+			if (avp2 != NULL)
+			{
+				CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata));
+			}
+			avp = avp2;
+		} while ((avp2 != NULL) && (ret == 0) && (ret == 0)
+				&& (avpdata->avp_code == Pi_Code));
+	}
+
+	/* NAS-Identifier AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_identifier, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "NAS-Identifier";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* NAS-IP-Address AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_ip_address, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "NAS-IP-Address";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* NAS-IPv6-Address AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_ipv6_address, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "NAS-IPv6-Address";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	/* State AVP */
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_state, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+		struct avp_attribute * attribute;
+		CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+		memset(attribute, 0, sizeof(struct avp_attribute));
+		fd_list_init(&attribute->chain, attribute);
+		attribute->attrib = "State";
+		attribute->value.os.data = avpdata->avp_value->os.data;
+		attribute->value.os.len = avpdata->avp_value->os.len;
+		fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+	}
+
+	return 0;
+}
+
+
+static int diameap_sess_data_new(
+		struct sess_state *diameap_sess_data,
+		struct diameap_state_machine *diameap_sm)
+{
+	if (!diameap_sm)
+		return EINVAL;
+
+	int i;
+
+	diameap_sess_data->invalid_eappackets = diameap_sm->invalid_eappackets;
+
+	diameap_sess_data->user.id = diameap_sm->eap_sm.user.id;
+
+	if ((diameap_sm->eap_sm.user.userid != NULL)
+			&& (diameap_sm->eap_sm.user.useridLength > 0))
+	{
+		diameap_sess_data->user.useridLength
+				= diameap_sm->eap_sm.user.useridLength;
+		CHECK_MALLOC(diameap_sess_data->user.userid= malloc(diameap_sess_data->user.useridLength+1));
+		U8COPY(diameap_sess_data->user.userid,0,diameap_sess_data->user.useridLength+1,diameap_sm->eap_sm.user.userid);
+		free(diameap_sm->eap_sm.user.userid);
+		diameap_sm->eap_sm.user.userid = NULL;
+
+	}
+	else
+	{
+		diameap_sess_data->user.useridLength = 0;
+		diameap_sess_data->user.userid = NULL;
+	}
+
+	if ((diameap_sm->eap_sm.user.password != NULL)
+			&& (diameap_sm->eap_sm.user.passwordLength > 0))
+	{
+		diameap_sess_data->user.passwordLength
+				= diameap_sm->eap_sm.user.passwordLength;
+		CHECK_MALLOC(diameap_sess_data->user.password = malloc(diameap_sess_data->user.passwordLength+1));
+		U8COPY(diameap_sess_data->user.password,0,diameap_sess_data->user.passwordLength+1,diameap_sm->eap_sm.user.password);
+		free(diameap_sm->eap_sm.user.password);
+		diameap_sm->eap_sm.user.password = NULL;
+	}
+	else
+	{
+		diameap_sess_data->user.passwordLength = 0;
+		diameap_sess_data->user.password = NULL;
+	}
+
+	diameap_sess_data->user.methodId = diameap_sm->eap_sm.user.methodId;
+	for (i = 0; i < MAXMETHODS; i++)
+	{
+		diameap_sess_data->user.methods[i].method
+				= diameap_sm->eap_sm.user.methods[i].method;
+		diameap_sess_data->user.methods[i].vendor
+				= diameap_sm->eap_sm.user.methods[i].vendor;
+	}
+
+	for (i = 0; i < MAXPROPOSEDMETHODS; i++)
+	{
+		diameap_sess_data->user.proposedmethods[i].method
+				= diameap_sm->eap_sm.user.proposedmethods[i].method;
+		diameap_sess_data->user.proposedmethods[i].vendor
+				= diameap_sm->eap_sm.user.proposedmethods[i].vendor;
+	}
+
+	diameap_sess_data->user.pmethods = diameap_sm->eap_sm.user.pmethods;
+	diameap_sess_data->user.proposed_eap_method
+			= diameap_sm->eap_sm.user.proposed_eap_method;
+	diameap_sess_data->user.proposed_eap_method_vendor
+			= diameap_sm->eap_sm.user.proposed_eap_method_vendor;
+	diameap_sess_data->user.success = diameap_sm->eap_sm.user.success;
+
+	diameap_sess_data->currentId = diameap_sm->eap_sm.currentId;
+	diameap_sess_data->currentMethod = diameap_sm->eap_sm.currentMethod;
+	diameap_sess_data->currentVendor = diameap_sm->eap_sm.currentVendor;
+	diameap_sess_data->lastId = diameap_sm->eap_sm.lastId;
+	diameap_sess_data->methodState = diameap_sm->eap_sm.methodState;
+
+	diameap_sess_data->methodData = diameap_sm->eap_sm.methodData;
+	diameap_sm->eap_sm.methodData = NULL;
+
+	return 0;
+}
+
+static void free_attrib(struct auth_attribute * auth_attrib)
+{
+	if (auth_attrib == NULL)
+	{
+		return;
+	}
+	if (auth_attrib->attrib != NULL)
+	{
+		free(auth_attrib->attrib);
+		auth_attrib->attrib = NULL;
+	}
+	if (auth_attrib->op != NULL)
+	{
+		free(auth_attrib->op);
+		auth_attrib->op = NULL;
+	}
+	if (auth_attrib->value != NULL)
+	{
+		free(auth_attrib->value);
+		auth_attrib->value = NULL;
+	}
+	free(auth_attrib);
+	auth_attrib = NULL;
+}
+
+static void free_avp_attrib(struct avp_attribute * avp_attrib)
+{
+	if(avp_attrib){
+	free(avp_attrib);
+	avp_attrib = NULL;
+	}
+}
+
+static void free_ans_attrib(struct avp_attribute * ans_attrib)
+{
+	if(ans_attrib){
+		if (ans_attrib->tofree == 1)
+		{
+			if(ans_attrib->value.os.data){
+			free(ans_attrib->value.os.data);
+			ans_attrib->value.os.data = NULL;
+			}
+		}
+		free(ans_attrib);
+		ans_attrib = NULL;
+	}
+}
+
+static int diameap_unlink_attributes_lists(
+		struct diameap_state_machine * diameap_sm)
+{
+	TRACE_ENTRY("%p ", diameap_sm);
+	if (diameap_sm == NULL)
+	{
+		return EINVAL;
+	}
+
+	while (!FD_IS_LIST_EMPTY(&diameap_sm->attributes))
+	{
+		struct fd_list * item = (struct fd_list *) diameap_sm->attributes.next;
+		struct auth_attribute * auth = (struct auth_attribute *) item;
+		fd_list_unlink(item);
+		free_attrib(auth);
+	}
+
+	while (!FD_IS_LIST_EMPTY(&diameap_sm->req_attributes))
+	{
+		struct fd_list * item =
+				(struct fd_list *) diameap_sm->req_attributes.next;
+		struct avp_attribute * avp = (struct avp_attribute *) item;
+		fd_list_unlink(item);
+		free_avp_attrib(avp);
+	}
+
+	while (!FD_IS_LIST_EMPTY(&diameap_sm->ans_attributes))
+	{
+		struct fd_list * item =
+				(struct fd_list *) diameap_sm->ans_attributes.next;
+		struct avp_attribute * avp_ans = (struct avp_attribute *) item;
+		fd_list_unlink(item);
+		free_ans_attrib(avp_ans);
+	}
+
+	return 0;
+}
+
+static void diameap_free(struct diameap_state_machine * diameap_sm)
+{
+
+	if (diameap_sm != NULL)
+	{
+		if (diameap_sm->eap_sm.user.userid != NULL)
+		{
+			free(diameap_sm->eap_sm.user.userid);
+			diameap_sm->eap_sm.user.userid = NULL;
+		}
+
+		if (diameap_sm->eap_sm.user.password != NULL)
+		{
+			free(diameap_sm->eap_sm.user.password);
+			diameap_sm->eap_sm.user.password = NULL;
+		}
+
+		diameap_sm->eap_sm.selectedMethod = NULL;
+
+		if (diameap_sm->eap_sm.methodData != NULL)
+		{
+
+			struct plugin * cplugin;
+			if (diameap_plugin_get(diameap_sm->eap_sm.currentVendor,
+					diameap_sm->eap_sm.currentMethod, &cplugin))
+			{
+				TRACE_DEBUG(INFO,"%sUnable to access EAP Method plugin {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,diameap_sm->eap_sm.currentMethod,diameap_sm->eap_sm.currentVendor);
+			}
+
+			if (cplugin->eap_method_free)
+			{
+				(*cplugin->eap_method_free)(diameap_sm->eap_sm.methodData);
+				diameap_sm->eap_sm.methodData = NULL;
+			}
+			else
+			{
+				TRACE_DEBUG(INFO,"%s[%s plugin] datafree function not available.",DIAMEAP_EXTENSION,cplugin->methodname);
+				if (diameap_sm->eap_sm.methodData != NULL)
+				{
+					free(diameap_sm->eap_sm.methodData);
+					diameap_sm->eap_sm.methodData = NULL;
+				}
+			}
+			if (diameap_sm->eap_sm.methodData)
+			{
+				TRACE_DEBUG(INFO,"%sSession state was not been freed correctly!!!",DIAMEAP_EXTENSION);
+			}
+		}
+
+		if (diameap_sm->failedavp != NULL)
+		{
+			CHECK_FCT_DO(fd_msg_free(diameap_sm->failedavp), );
+		}
+
+		if (diameap_sm->lastReqEAPavp != NULL)
+		{
+			CHECK_FCT_DO(fd_msg_free(diameap_sm->lastReqEAPavp), );
+		}
+
+		CHECK_FCT_DO(diameap_unlink_attributes_lists(diameap_sm), );
+
+		free(diameap_sm);
+		diameap_sm = NULL;
+	}
+
+}
+
+static int diameap_get_avp_attribute(struct fd_list * avp_attributes,
+		char * attribute, struct avp_attribute ** avp_attrib, int unlink,
+		int *ret)
+{
+	TRACE_ENTRY("%p %p %p %d %p", avp_attributes, attribute, avp_attrib, unlink, ret);
+	if (avp_attributes == NULL)
+	{
+		return EINVAL;
+	}
+	if (attribute == NULL)
+	{
+		return EINVAL;
+	}
+	struct fd_list * attrib;
+	for (attrib = avp_attributes->next; attrib != avp_attributes; attrib
+			= attrib->next)
+	{
+		*avp_attrib = (struct avp_attribute *) attrib;
+		if (strcmp((*avp_attrib)->attrib, attribute) == 0)
+		{
+			*ret = 0;
+			if (unlink == 1)
+			{
+				fd_list_unlink(&(*avp_attrib)->chain);
+			}
+			return 0;
+		}
+	}
+	*avp_attrib = NULL;
+	*ret = 1;
+	return 0;
+}
+
+static int diameap_get_auth_attribute(struct fd_list * auth_attributes,
+		char * attribute, struct auth_attribute ** auth_attrib, int unlink,
+		int *ret)
+{
+
+	TRACE_ENTRY("%p %p %p %d %p", auth_attributes, attribute, auth_attrib, unlink, ret);
+
+	if (auth_attributes == NULL)
+	{
+		return EINVAL;
+	}
+	if (attribute == NULL)
+	{
+		return EINVAL;
+	}
+
+	struct fd_list * attrib;
+
+	for (attrib = auth_attributes->next; attrib != auth_attributes; attrib
+			= attrib->next)
+	{
+		*auth_attrib = (struct auth_attribute *) attrib;
+		if (strcmp((*auth_attrib)->attrib, attribute) == 0)
+		{
+			*ret = 0;
+			if (unlink == 1)
+			{
+				fd_list_unlink(&(*auth_attrib)->chain);
+			}
+			return 0;
+		}
+	}
+	*auth_attrib = NULL;
+	*ret = 1;
+	return 0;
+}
+
+static int diameap_get_ans_attribute(struct fd_list * ans_attributes,
+		char * attribute, struct avp_attribute ** ans_attrib, int unlink,
+		int *ret)
+{
+	TRACE_ENTRY("%p %p %p %d %p", ans_attributes, attribute, ans_attrib, unlink, ret);
+	if (ans_attributes == NULL)
+	{
+		return EINVAL;
+	}
+	if (attribute == NULL)
+	{
+		return EINVAL;
+	}
+	struct fd_list * attrib;
+	for (attrib = ans_attributes->next; attrib != ans_attributes; attrib
+			= attrib->next)
+	{
+		*ans_attrib = (struct avp_attribute *) attrib;
+		if (strcmp((*ans_attrib)->attrib, attribute) == 0)
+		{
+			*ret = 0;
+			if (unlink == 1)
+			{
+				fd_list_unlink(&(*ans_attrib)->chain);
+			}
+			return 0;
+		}
+	}
+	*ans_attrib = NULL;
+	*ret = 1;
+	return 0;
+}
+
+static int diameap_answer_avp_attributes(
+		struct diameap_state_machine * diameap_sm)
+{
+	TRACE_ENTRY("%p",diameap_sm);
+
+	if (diameap_sm == NULL)
+	{
+		return EINVAL;
+	}
+	int ret1, ret2;
+	struct avp_attribute * avp_attrib;
+	struct avp_attribute * ans_attrib;
+	struct auth_attribute * auth_attrib;
+
+	/* Authorization-Lifetime */
+	{
+		CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes, "Authorization-Lifetime", &avp_attrib,1, &ret1));
+
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Authorization-Lifetime", &auth_attrib,1, &ret2));
+
+		if ((ret1 == 1) && (ret2 == 0) && (auth_attrib != NULL))
+		{
+
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+
+			fd_list_init(&ans_attrib->chain, NULL);
+
+			ans_attrib->attrib = "Authorization-Lifetime";
+
+			ans_attrib->value.u32 = atoi(auth_attrib->value);
+
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+
+			free_attrib(auth_attrib);
+
+		}
+		if ((ret1 == 0) && (ret2 == 1) && (avp_attrib != NULL))
+		{
+
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+
+			fd_list_init(&ans_attrib->chain, NULL);
+
+			ans_attrib->attrib = "Authorization-Lifetime";
+
+			ans_attrib->value.u32 = avp_attrib->value.u32;
+
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+
+			free_avp_attrib(avp_attrib);
+
+		}
+		if ((ret1 == 0) && (ret2 == 0) && (auth_attrib != NULL) && (avp_attrib
+				!= NULL))
+		{
+
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Authorization-Lifetime";
+			if (avp_attrib->value.u32 < atoi(auth_attrib->value))
+			{
+				ans_attrib->value.u32 = avp_attrib->value.u32;
+			}
+			else
+			{
+				ans_attrib->value.u32 = atoi(auth_attrib->value);
+			}
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_avp_attrib(avp_attrib);
+			free_attrib(auth_attrib);
+		}
+	}
+
+	/* Auth-Grace-Period */
+	{
+		CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes, "Auth-Grace-Period", &avp_attrib,1, &ret1));
+
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Auth-Grace-Period", &auth_attrib,1, &ret2));
+
+		if ((ret1 == 1) && (ret2 == 0) && (auth_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Auth-Grace-Period";
+			ans_attrib->value.u32 = atoi(auth_attrib->value);
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+		}
+		if ((ret1 == 0) && (ret2 == 1) && (avp_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Auth-Grace-Period";
+			ans_attrib->value.u32 = avp_attrib->value.u32;
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_avp_attrib(avp_attrib);
+		}
+		if ((ret1 == 0) && (ret2 == 0) && (auth_attrib != NULL) && (avp_attrib
+				!= NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Auth-Grace-Period";
+			if (avp_attrib->value.u32 < atoi(auth_attrib->value))
+			{
+				ans_attrib->value.u32 = avp_attrib->value.u32;
+			}
+			else
+			{
+				ans_attrib->value.u32 = atoi(auth_attrib->value);
+			}
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+			free_avp_attrib(avp_attrib);
+		}
+	}
+
+	/* Auth-Session-State */
+	{
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Auth-Session-State", &auth_attrib,1, &ret2));
+		if ((ret2 == 0) && (auth_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Auth-Session-State";
+			ans_attrib->value.i32 = atoi(auth_attrib->value);
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+		}
+	}
+
+	/* Re-Auth-Request-Type */
+	{
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Re-Auth-Request-Type", &auth_attrib,1, &ret2));
+		if ((ret2 == 0) && (auth_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Re-Auth-Request-Type";
+			ans_attrib->value.i32 = atoi(auth_attrib->value);
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+		}
+		else
+		{
+			ans_attrib = NULL;
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes, "Authorization-Lifetime", &ans_attrib,0, &ret1));
+			if ((ret1 == 0) && (ans_attrib != NULL))
+			{
+				CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+				memset(ans_attrib, 0, sizeof(struct avp_attribute));
+				fd_list_init(&ans_attrib->chain, NULL);
+				ans_attrib->attrib = "Re-Auth-Request-Type";
+				ans_attrib->value.i32 = 0;
+				fd_list_insert_before(&diameap_sm->ans_attributes,
+						&ans_attrib->chain);
+			}
+		}
+	}
+
+	/* Session-Timeout */
+	{
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Session-Timeout", &auth_attrib,1, &ret2));
+		if ((ret2 == 0) && (auth_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Session-Timeout";
+			ans_attrib->value.u32 = atoi(auth_attrib->value);
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+		}
+	}
+
+	/* Multi-Round-Time-Out */
+	{
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Multi-Round-Time-Out", &auth_attrib,1, &ret2));
+		if ((ret2 == 0) && (auth_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Multi-Round-Time-Out";
+			ans_attrib->value.u32 = atoi(auth_attrib->value);
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+		}
+	}
+
+	/* Acct-Interim-Interval */
+	{
+		CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Acct-Interim-Interval", &auth_attrib,1, &ret2));
+		if ((ret2 == 0) && (auth_attrib != NULL))
+		{
+			CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+			memset(ans_attrib, 0, sizeof(struct avp_attribute));
+			fd_list_init(&ans_attrib->chain, NULL);
+			ans_attrib->attrib = "Acct-Interim-Interval";
+			ans_attrib->value.u32 = atoi(auth_attrib->value);
+			fd_list_insert_before(&diameap_sm->ans_attributes,
+					&ans_attrib->chain);
+			free_attrib(auth_attrib);
+		}
+	}
+
+	return 0;
+}
+
+#define	DIAMEAP_STR	1
+#define	DIAMEAP_NUM	2
+
+#define DIAMEAP_OP_NO	0	//Not supported operator
+#define	DIAMEAP_OP_EQ	1	//==
+#define	DIAMEAP_OP_GT	2	//>
+#define	DIAMEAP_OP_LT	3	//<
+#define	DIAMEAP_OP_GE	4	//>=
+#define	DIAMEAP_OP_LE	5	//<=
+#define	DIAMEAP_OP_NE	6	//!=
+#define	DIAMEAP_OP_EX	7	//~=
+#define EQ(A,B) A==B ? TRUE : FALSE
+#define GT(A,B) A>B ? TRUE : FALSE
+#define GE(A,B) A>=B ? TRUE : FALSE
+#define LT(A,B) A<B ? TRUE : FALSE
+#define LE(A,B) A<=B ? TRUE : FALSE
+#define NE(A,B) A!=B ? TRUE : FALSE
+
+int diameap_get_operator(char *operator)
+{
+	TRACE_ENTRY("%p",operator);
+	if (strcmp(operator, "==") == 0)
+	{
+		return DIAMEAP_OP_EQ;
+	}
+	if (strcmp(operator, ">") == 0)
+	{
+		return DIAMEAP_OP_GT;
+	}
+	if (strcmp(operator, "<") == 0)
+	{
+		return DIAMEAP_OP_LT;
+	}
+	if (strcmp(operator, ">=") == 0)
+	{
+		return DIAMEAP_OP_GE;
+	}
+	if (strcmp(operator, "<=") == 0)
+	{
+		return DIAMEAP_OP_LE;
+	}
+	if (strcmp(operator, "!=") == 0)
+	{
+		return DIAMEAP_OP_NE;
+	}
+	if (strcmp(operator, "~=") == 0)
+	{
+		return DIAMEAP_OP_EX;
+	}
+	return DIAMEAP_OP_NO;
+}
+
+boolean is_operator(int format_type, char * operator)
+{
+	TRACE_ENTRY("%d %p",format_type,operator);
+	if ((format_type == DIAMEAP_STR) && (strcmp(operator, "==") == 0 || strcmp(
+			operator, "~=") == 0 || strcmp(operator, "!=") == 0))
+	{
+		return TRUE;
+	}
+	if ((format_type == DIAMEAP_NUM) && (strcmp(operator, "~=") != 0))
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+union avp_value diameap_get_num(char * num, enum dict_avp_basetype datatype)
+{
+	TRACE_ENTRY("%p %d",num,datatype);
+	union avp_value val;
+	switch (datatype)
+	{
+	case AVP_TYPE_INTEGER32://i32
+		val.i32 = atoi(num);
+		break;
+	case AVP_TYPE_INTEGER64://i64
+		val.i64 = atoll(num);
+		break;
+	case AVP_TYPE_UNSIGNED32://u32
+		val.u32 = strtoul(num, NULL, 10);
+		break;
+	case AVP_TYPE_UNSIGNED64://u64
+		val.u64 = strtoull(num, NULL, 10);
+		break;
+	case AVP_TYPE_FLOAT32://f32
+		val.f32 = atof(num);
+		break;
+	case AVP_TYPE_FLOAT64://f64
+		val.f64 = strtod(num, NULL);
+		break;
+	default:
+		TRACE_DEBUG(INFO, "%sUnknown AVP Base Type.",DIAMEAP_EXTENSION)
+		;
+	}
+	return val;
+}
+
+boolean diameap_check(union avp_value *A, char * B, char * operator,
+		enum dict_avp_basetype datatype)
+{
+	TRACE_ENTRY("%p %p %p %d",A,B,operator,datatype);
+	if (((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+			operator) == TRUE)) || ((datatype != AVP_TYPE_OCTETSTRING)
+			&& (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM,
+			operator) == TRUE)))
+	{
+		switch (diameap_get_operator(operator))
+		{
+		case DIAMEAP_OP_EQ:
+			if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+					operator) == TRUE))
+			{
+				if (strcmp((char *)A->os.data, B) == 0)
+					return TRUE;
+				else
+					return FALSE;
+			}
+			else if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+					!= AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+					== TRUE))
+			{
+
+				switch (datatype)
+				{
+				case AVP_TYPE_INTEGER32://i32
+					return EQ(A->i32,diameap_get_num(B, datatype).i32);
+					break;
+				case AVP_TYPE_INTEGER64://i64
+					return EQ(A->i64,diameap_get_num(B, datatype).i64);
+					break;
+				case AVP_TYPE_UNSIGNED32://u32
+					return EQ(A->u32,diameap_get_num(B, datatype).u32);
+					break;
+				case AVP_TYPE_UNSIGNED64://u64
+					return EQ(A->u64,diameap_get_num(B, datatype).u64);
+					break;
+				case AVP_TYPE_FLOAT32://f32
+					return EQ(A->f32,diameap_get_num(B, datatype).f32);
+					break;
+				case AVP_TYPE_FLOAT64://f64
+					return EQ(A->f64,diameap_get_num(B, datatype).f64);
+					break;
+				default:
+					return FALSE;
+				}
+			}
+			else
+			{
+				return FALSE;
+			}
+			break;
+		case DIAMEAP_OP_EX:
+		{
+			//string only
+			boolean authorized = FALSE;
+			if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+					operator) == TRUE))
+			{
+				regex_t rule_regexp;
+				regcomp(&rule_regexp, B, REG_EXTENDED | REG_NOSUB | REG_ICASE);
+				if (regexec(&rule_regexp, (char *)A->os.data, 0, NULL, 0) != 0)
+				{
+					authorized = FALSE;
+				}
+				else
+				{
+					authorized = TRUE;
+				}
+				regfree(&rule_regexp);
+			}
+			return authorized;
+		}
+		case DIAMEAP_OP_GT:
+
+			if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+					!= AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+					== TRUE))
+			{
+				switch (datatype)
+				{
+				case AVP_TYPE_INTEGER32://i32
+					return GT(A->i32, diameap_get_num(B, datatype).i32);
+					break;
+				case AVP_TYPE_INTEGER64://i64
+					return GT(A->i64, diameap_get_num(B, datatype).i64);
+					break;
+				case AVP_TYPE_UNSIGNED32://u32
+					return GT(A->u32, diameap_get_num(B, datatype).u32);
+					break;
+				case AVP_TYPE_UNSIGNED64://u64
+					return GT(A->u64, diameap_get_num(B, datatype).u64);
+					break;
+				case AVP_TYPE_FLOAT32://f32
+					return GT(A->f32, diameap_get_num(B, datatype).f32);
+					break;
+				case AVP_TYPE_FLOAT64://f64
+					return GT(A->f64, diameap_get_num(B, datatype).f64);
+					break;
+				default:
+					return FALSE;
+				}
+			}
+			else
+			{
+				return FALSE;
+			}
+			break;
+		case DIAMEAP_OP_GE:
+			if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+					!= AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+					== TRUE))
+			{
+				switch (datatype)
+				{
+				case AVP_TYPE_INTEGER32://i32
+					return GE(A->i32,diameap_get_num(B, datatype).i32);
+					break;
+				case AVP_TYPE_INTEGER64://i64
+					return GE(A->i64,diameap_get_num(B, datatype).i64);
+					break;
+				case AVP_TYPE_UNSIGNED32://u32
+					return GE(A->u32,diameap_get_num(B, datatype).u32);
+					break;
+				case AVP_TYPE_UNSIGNED64://u64
+					return GE(A->u64,diameap_get_num(B, datatype).u64);
+					break;
+				case AVP_TYPE_FLOAT32://f32
+					return GE(A->f32,diameap_get_num(B, datatype).f32);
+					break;
+				case AVP_TYPE_FLOAT64://f64
+					return GE(A->f64,diameap_get_num(B, datatype).f64);
+					break;
+				default:
+					return FALSE;
+				}
+			}
+			else
+			{
+				return FALSE;
+			}
+			break;
+		case DIAMEAP_OP_LT:
+			if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+					!= AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+					== TRUE))
+			{
+				switch (datatype)
+				{
+				case AVP_TYPE_INTEGER32://i32
+					return LT(A->i32, diameap_get_num(B, datatype).i32);
+					break;
+				case AVP_TYPE_INTEGER64://i64
+					return LT(A->i64, diameap_get_num(B, datatype).i64);
+					break;
+				case AVP_TYPE_UNSIGNED32://u32
+					return LT(A->u32, diameap_get_num(B, datatype).u32);
+					break;
+				case AVP_TYPE_UNSIGNED64://u64
+					return LT(A->u64, diameap_get_num(B, datatype).u64);
+					break;
+				case AVP_TYPE_FLOAT32://f32
+					return LT(A->f32, diameap_get_num(B, datatype).f32);
+					break;
+				case AVP_TYPE_FLOAT64://f64
+					return LT(A->f64, diameap_get_num(B, datatype).f64);
+					break;
+				default:
+					return FALSE;
+				}
+			}
+			else
+			{
+				return FALSE;
+			}
+			break;
+		case DIAMEAP_OP_LE:
+			if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+					!= AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+					== TRUE))
+			{
+				switch (datatype)
+				{
+				case AVP_TYPE_INTEGER32://i32
+					return LE(A->i32, diameap_get_num(B, datatype).i32);
+					break;
+				case AVP_TYPE_INTEGER64://i64
+					return LE(A->i64, diameap_get_num(B, datatype).i64);
+					break;
+				case AVP_TYPE_UNSIGNED32://u32
+					return LE(A->u32, diameap_get_num(B, datatype).u32);
+					break;
+				case AVP_TYPE_UNSIGNED64://u64
+					return LE(A->u64, diameap_get_num(B, datatype).u64);
+					break;
+				case AVP_TYPE_FLOAT32://f32
+					return LE(A->f32, diameap_get_num(B, datatype).f32);
+					break;
+				case AVP_TYPE_FLOAT64://f64
+					return LE(A->f64, diameap_get_num(B, datatype).f64);
+					break;
+				default:
+					return FALSE;
+				}
+			}
+			else
+			{
+				return FALSE;
+			}
+			break;
+		case DIAMEAP_OP_NE:
+			if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+					operator) == TRUE))
+			{
+				if (strcmp((char *)A->os.data, B) != 0)
+					return TRUE;
+				else
+					return FALSE;
+			}
+			else if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+					!= AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+					== TRUE))
+			{
+				switch (datatype)
+				{
+				case AVP_TYPE_INTEGER32://i32
+					return NE(A->i32, diameap_get_num(B, datatype).i32);
+					break;
+				case AVP_TYPE_INTEGER64://i64
+					return NE(A->i64, diameap_get_num(B, datatype).i64);
+					break;
+				case AVP_TYPE_UNSIGNED32://u32
+					return NE(A->u32, diameap_get_num(B, datatype).u32);
+					break;
+				case AVP_TYPE_UNSIGNED64://u64
+					return NE(A->u64, diameap_get_num(B, datatype).u64);
+					break;
+				case AVP_TYPE_FLOAT32://f32
+					return NE(A->f32, diameap_get_num(B, datatype).f32);
+					break;
+				case AVP_TYPE_FLOAT64://f64
+					return NE(A->f64, diameap_get_num(B, datatype).f64);
+					break;
+				default:
+					return FALSE;
+				}
+			}
+			else
+			{
+				return FALSE;
+			}
+			break;
+		}
+	}
+	return FALSE;
+}
+
+char * diameap_attribute_operator(char * op, int * toadd, boolean *isrule)
+{
+	TRACE_ENTRY("%p %p %p",op,toadd,isrule);
+	char * attribute_op;
+
+	if (op[0] == '+')
+	{
+		*toadd = 1;
+	}
+	else if (op[strlen(op) - 1] == '+')
+	{
+		*toadd = 2;
+	}
+	else
+	{
+		*toadd = 0;
+	}
+
+	switch (*toadd)
+	{
+	case 1:
+		attribute_op = malloc(strlen(op));
+		memset(attribute_op, 0, strlen(op));
+		strncpy(attribute_op, op + 1, strlen(op) - 1);
+		attribute_op[strlen(op)] = '\0';
+		break;
+	case 2:
+		attribute_op = malloc(strlen(op));
+		memset(attribute_op, 0, strlen(op));
+		strncpy(attribute_op, op, strlen(op) - 1);
+		attribute_op[strlen(op)] = '\0';
+		break;
+	default:
+		attribute_op = malloc(strlen(op) + 1);
+		memset(attribute_op, 0, strlen(op) + 1);
+		strcpy(attribute_op, op);
+		attribute_op[strlen(op) + 1] = '\0';
+	}
+	if (strcmp(attribute_op, "=") == 0)
+	{
+		*isrule = FALSE;
+		*toadd = 2;
+	}
+	else
+	{
+		*isrule = TRUE;
+	}
+
+	return attribute_op;
+}
+
+int diameap_answer_set_attribute_valueA(union avp_value *A, int *tofree,
+		enum dict_avp_basetype datatype, union avp_value * rval)
+{
+	TRACE_ENTRY("%p %p %d %p",A,tofree,datatype,rval);
+	if (datatype == AVP_TYPE_OCTETSTRING)
+	{
+		CHECK_MALLOC(rval->os.data=malloc(A->os.len));
+		memcpy(rval->os.data,A->os.data,A->os.len);
+		rval->os.len = A->os.len;
+		*tofree = 1;
+	}
+	else
+	{
+		*rval = *A;
+	}
+	return 0;
+}
+int diameap_answer_set_attribute_valueB(char * B, int *tofree,
+		enum dict_avp_basetype datatype, union avp_value * rval)
+{
+	TRACE_ENTRY("%p %p %d %p",B,tofree,datatype,rval);
+	if (datatype == AVP_TYPE_OCTETSTRING)
+	{
+		CHECK_MALLOC(rval->os.data=malloc(strlen(B)));
+		memcpy(rval->os.data,B,strlen(B));
+		rval->os.len = strlen(B);
+
+		*tofree = 1;
+	}
+	else
+	{
+
+		*rval = diameap_get_num(B, datatype);
+	}
+
+	return 0;
+}
+
+static int diameap_attribute_limits(char * attrib, int * max, int *ret)
+{
+	TRACE_ENTRY("%p %p %p",attrib,max,ret);
+	if (attrib == NULL)
+	{
+		return EINVAL;
+	}
+	int i;
+	for (i = 0; i < sizeof(auth_avps); i++)
+	{
+		if (strcmp(auth_avps[i].avp_attribute, attrib) == 0)
+		{
+			*max = auth_avps[i].max;
+			*ret = 0;
+			return 0;
+		}
+	}
+	*max = 0;
+	*ret = 1;
+	return 0;
+}
+
+static int diameap_answer_authorization_attributes(
+		struct diameap_state_machine * diameap_sm)
+{
+	TRACE_ENTRY("%p",diameap_sm);
+
+	if (diameap_sm == NULL)
+	{
+		return EINVAL;
+	}
+	boolean checked = TRUE;
+
+	struct fd_list * attrib;
+	struct auth_attribute * auth_attrib;
+	struct avp_attribute * avp_attrib;
+	int ret;
+
+	for (attrib = (&diameap_sm->attributes)->next; attrib
+			!= (&diameap_sm->attributes); attrib = attrib->next)
+	{
+		avp_attrib = NULL;
+		auth_attrib = (struct auth_attribute *) attrib;
+
+		int toadd = 0;
+		boolean isrule = FALSE;
+		char * op;
+
+		op = diameap_attribute_operator(auth_attrib->op, &toadd, &isrule);
+
+		struct dict_object * dobj;
+		struct dict_avp_data avpdata;
+		fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+				auth_attrib->attrib, &dobj, ENOENT);
+		fd_dict_getval(dobj, &avpdata);
+
+		checked = TRUE;
+		if (isrule == TRUE)
+		{
+			CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes,auth_attrib->attrib,&avp_attrib,0,&ret));
+			if (ret == 0)
+			{
+				checked = diameap_check(&avp_attrib->value, auth_attrib->value,
+						op, avpdata.avp_basetype);
+			}
+		}
+		if (checked == TRUE && toadd != 0)
+		{
+
+			struct avp_attribute * ans_attrib;
+			int max = 0;
+			diameap_attribute_limits(auth_attrib->attrib, &max, &ret);
+			if ((ret == 0) && (max != 0))
+			{
+				if (max == 1)//only one
+				{
+					int ret = 0;
+					diameap_get_ans_attribute(&diameap_sm->ans_attributes,
+							auth_attrib->attrib, &ans_attrib, 0, &ret);
+					if (ret == 1)
+					{
+						ans_attrib = NULL;
+						CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+						memset(ans_attrib, 0, sizeof(struct avp_attribute));
+						fd_list_init(&ans_attrib->chain, NULL);
+						ans_attrib->attrib = strdup(auth_attrib->attrib);
+						if (toadd == 1)
+						{
+							diameap_answer_set_attribute_valueA(
+									&avp_attrib->value, &ans_attrib->tofree,
+									avpdata.avp_basetype, &ans_attrib->value);
+						}
+						else
+						{
+							diameap_answer_set_attribute_valueB(
+									auth_attrib->value, &ans_attrib->tofree,
+									avpdata.avp_basetype, &ans_attrib->value);
+						}
+						fd_list_insert_before(&diameap_sm->ans_attributes,
+								&ans_attrib->chain);
+
+					}
+					else
+					{
+						//an answer avp is already added
+					}
+				}
+				else
+				{
+					ans_attrib = NULL;
+					CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+					memset(ans_attrib, 0, sizeof(struct avp_attribute));
+					fd_list_init(&ans_attrib->chain, NULL);
+					ans_attrib->attrib = auth_attrib->attrib;
+					if (toadd == 1)
+					{
+						diameap_answer_set_attribute_valueA(&avp_attrib->value,
+								&ans_attrib->tofree, avpdata.avp_basetype,
+								&ans_attrib->value);
+					}
+					else
+					{
+						diameap_answer_set_attribute_valueB(auth_attrib->value,
+								&ans_attrib->tofree, avpdata.avp_basetype,
+								&ans_attrib->value);
+					}
+					fd_list_insert_before(&diameap_sm->ans_attributes,
+							&ans_attrib->chain);
+				}
+			}
+		}
+		if (checked == FALSE)
+		{
+
+			diameap_sm->authorized = FALSE;
+			return 0;
+		}
+	}
+	diameap_sm->authorized = checked;
+	return 0;
+
+	return 0;
+}
+
+
+
+static int diameap_policy_decision(struct diameap_state_machine * diameap_sm,
+		struct diameap_eap_interface *eap_i)
+{
+	TRACE_ENTRY("%p %p",diameap_sm,eap_i);
+
+	if ((eap_i->aaaFail == TRUE) && (eap_i->aaaSuccess == TRUE))
+	{
+		TRACE_DEBUG(INFO,"%s Incorrect EAP decision. EAP process should not return both success and failure for the same session.(please report this problem.)",DIAMEAP_EXTENSION);
+		return -1;
+	}
+
+	if (eap_i->aaaFail == TRUE)
+	{
+		diameap_sm->result_code = 4001; /* DIAMETER_AUTHENTICATION_REJECTED 4001 */
+		diameap_sm->authFailure = TRUE;
+		TRACE_DEBUG(FULL+1,"%s Auth failure: Authentication Rejected ",DIAMEAP_EXTENSION);
+		return 0;
+	}
+
+	if (eap_i->aaaSuccess == FALSE)
+	{
+		diameap_sm->result_code = 1001; /* DIAMETER_MULTI_ROUND_AUTH 1001 */
+		return 0;
+	}
+
+	if (eap_i->aaaSuccess == TRUE)
+	{
+		if (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE)
+		{
+			if ((diameap_sm->verify_authorization == TRUE)
+					&& (diameap_sm->result_code == 0))
+			{
+				diameap_sm->result_code = 2001; /* DIAMETER_SUCCESS 2001 */
+				diameap_sm->authSuccess = TRUE;
+				TRACE_DEBUG(FULL+1,"%s Auth success: Authorization and Authentication ",DIAMEAP_EXTENSION);
+				return 0;
+			}
+			else
+			{
+				//
+			}
+		}
+		if (diameap_sm->auth_request_val == AUTHENTICATE_ONLY)
+		{
+			diameap_sm->result_code = 2001; /* DIAMETER_SUCCESS 2001 */
+			diameap_sm->authSuccess = TRUE;
+			TRACE_DEBUG(FULL+1,"%s Auth success: Authentication Only ",DIAMEAP_EXTENSION);
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int diameap_add_avps(struct diameap_state_machine * diameap_sm,
+		struct msg * ans, struct msg * req)
+{
+	TRACE_ENTRY("%p %p %p",diameap_sm,ans,req);
+
+	struct avp * avp, *avp2;
+	struct avp_hdr * avpdata;
+	union avp_value avp_val;
+	int ret = 0;
+
+	/* Origin-Host AVP and Origin-Realm AVP */
+	{
+		CHECK_FCT( fd_msg_add_origin ( ans, 0 ) );
+	}
+
+	/* Auth-Application-Id AVP */
+	{
+		CHECK_FCT(fd_msg_avp_new(dataobj_auth_application_id, 0, &avp));
+		avp_val.u32 = diameap_config->application_id;
+		CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+		CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp));
+	}
+
+	/* Auth-Request-Type AVP
+	 * Enumerated values:
+	 * 	AUTHENTICATE_ONLY 1
+	 * 	AUTHORIZE_ONLY 2
+	 * 	AUTHORIZE_AUTHENTICATE 3 */
+	{
+		CHECK_FCT(fd_msg_avp_new(dataobj_auth_request_type, 0, &avp));
+		if (!diameap_config->authorize)
+		{
+			//AUTHENTICATE ONLY
+			avp_val.i32 = AUTHENTICATE_ONLY;
+		}
+		else
+		{
+			if (diameap_sm->auth_request_val == 3)
+			{
+				//AUTHORIZE_AUTHENTICATE
+				avp_val.i32 = AUTHORIZE_AUTHENTICATE;
+			}
+			else
+			{
+				//AUTHENTICATE_ONLY
+				avp_val.i32 = AUTHENTICATE_ONLY;
+			}
+		}
+		CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+		CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp));
+	}
+
+	/* Proxy-Info AVP */
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_proxy_info, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT(fd_msg_avp_hdr ( avp, &avpdata ) );
+		u32 proxy_info_code = avpdata->avp_code;
+		int depth;
+		do
+		{
+			ret = 0;
+			depth = 0;
+			CHECK_FCT(fd_msg_avp_hdr ( avp, &avpdata ) );
+			if (avpdata->avp_code == proxy_info_code)
+			{
+				CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp));
+			}
+			ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+			avp = avp2;
+		} while ((avp != NULL) && (ret == 0) && (ret == 0));
+	}
+
+	if (diameap_sm->eap_sm.user.userid)
+	{
+		/* User-Name AVP */
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_user_name, 0, &avp));
+
+			if (diameap_sm->privateUser == FALSE)
+			{
+
+				avp_val.os.data = diameap_sm->eap_sm.user.userid;
+				avp_val.os.len = diameap_sm->eap_sm.user.useridLength;
+				CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+				CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			}
+			else
+			{
+
+			}
+
+		}
+	}
+	return 0;
+}
+
+static int diameap_add_user_sessions_avps(
+		struct diameap_state_machine * diameap_sm, struct msg * ans)
+{
+	TRACE_ENTRY("%p %p",diameap_sm,ans);
+
+	struct avp * avp;
+	union avp_value avp_val;
+	int ret;
+
+	/* Authorization-Lifetime AVP */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Authorization-Lifetime",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_authorization_lifetime, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Auth-Grace-Period AVP */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Auth-Grace-Period",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_auth_grace_period, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Auth-Session-State AVP */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Auth-Session-State",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_auth_session_state, 0, &avp));
+			avp_val.i32 = ans_attrib->value.i32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Re-Auth-Request-Type AVP */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Re-Auth-Request-Type",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_re_auth_request_type, 0, &avp));
+			avp_val.i32 = ans_attrib->value.i32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Session-Timeout AVP */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Session-Timeout",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_session_timeout, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Acct-Interim-Interval AVP */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Acct-Interim-Interval",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_acct_interim_interval, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+	return 0;
+}
+
+static int diameap_add_authorization_avps(
+		struct diameap_state_machine * diameap_sm, struct msg * ans)
+{
+
+	TRACE_ENTRY("%p %p",diameap_sm, ans);
+
+	struct avp * avp;
+	union avp_value avp_val;
+	int ret;
+
+	if (diameap_sm == NULL)
+	{
+		return EINVAL;
+	}
+	if (ans == NULL)
+	{
+		return EINVAL;
+	}
+
+	/* Reply-Message */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Reply-Message",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_reply_message, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Reply-Message",&ans_attrib,1,&ret));
+		}
+
+	}
+
+	/* Service-Type */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Service-Type",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_service_type, 0, &avp));
+			avp_val.i32 = ans_attrib->value.i32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Callback-Number */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Callback-Number",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_callback_number, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Callback-Id */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Callback-Id",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_callback_id, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Idle-Timeout */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Idle-Timeout",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_idle_timeout, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* NAS-Filter-Rule */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"NAS-Filter-Rule",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_nas_filter_rule, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Filter-Id */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Filter-Id",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_filter_id, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Filter-Id",&ans_attrib,1,&ret));
+		}
+
+	}
+
+	/* Configuration-Token */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Configuration-Token",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_configuration_token, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Configuration-Token",&ans_attrib,1,&ret));
+		}
+	}
+
+	/* QoS-Filter-Rule */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"QoS-Filter-Rule",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_qos_filter_rule, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"QoS-Filter-Rule",&ans_attrib,1,&ret));
+		}
+
+	}
+
+	/* Framed-Protocol */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Protocol",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_protocol, 0, &avp));
+			avp_val.i32 = ans_attrib->value.i32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-Routing */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Routing",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_routing, 0, &avp));
+			avp_val.i32 = ans_attrib->value.i32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+
+	}
+
+	/* Framed-MTU */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-MTU",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_mtu, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-Compression */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Compression",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_compression, 0, &avp));
+			avp_val.i32 = ans_attrib->value.i32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Compression",&ans_attrib,1,&ret));
+		}
+
+	}
+	/* Framed-IP-Address */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IP-Address",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_ip_address, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-IP-Netmask */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IP-Netmask",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_ip_netmask, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-Route */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Route",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_route, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Route",&ans_attrib,1,&ret));
+		}
+	}
+
+	/* Framed-Pool */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Pool",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_pool, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-Interface-Id */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Interface-Id",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_interface_id, 0, &avp));
+			avp_val.u64 = ans_attrib->value.u64;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-IPv6-Prefix */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Prefix",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_prefix, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Prefix",&ans_attrib,1,&ret));
+		}
+	}
+
+	/* Framed-IPv6-Route */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Route",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_route, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Route",&ans_attrib,1,&ret));
+		}
+	}
+
+	/* Framed-IPv6-Pool */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Pool",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_pool, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Framed-IPX-Network */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPX-Network",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipx_network, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+
+	}
+	/* Framed-AppleTalk-Link */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Link",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_link, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+
+	}
+
+	/* Framed-AppleTalk-Network */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Network",&ans_attrib,1,&ret));
+		while ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_network, 0, &avp));
+			avp_val.u32 = ans_attrib->value.u32;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+			CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Network",&ans_attrib,1,&ret));
+		}
+
+	}
+
+	/* Framed-AppleTalk-Zone */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Zone",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_zone, 0, &avp));
+			avp_val.os.data = ans_attrib->value.os.data;
+			avp_val.os.len = ans_attrib->value.os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_ans_attrib(ans_attrib);
+		}
+	}
+
+	/* Tunneling */
+	//
+
+	/* State */
+	//
+	return 0;
+}
+
+static int diameap_add_result_code(struct diameap_state_machine * diameap_sm,
+		struct msg * ans, struct session * sess)
+{
+	TRACE_ENTRY("%p %p",diameap_sm,ans);
+	struct avp * avp;
+	union avp_value avp_val;
+	int ret;
+
+	/* Result-Code AVP */
+	CHECK_FCT(fd_msg_avp_new(dataobj_result_code, 0, &avp));
+	avp_val.u32 = diameap_sm->result_code;
+	CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+	/* Add Result-Code AVP to the message */
+	CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+
+	/* Multi_Round_Time_Out AVP */
+	if (diameap_sm->result_code == 1001)
+	{
+		struct timespec sess_timeout;
+		CHECK_FCT(fd_msg_avp_new(dataobj_multi_round_time_out, 0, &avp));
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Multi-Round-Time-Out",&ans_attrib,1,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			avp_val.u32 = ans_attrib->value.u32;
+			/* Update the session timeout with multi-round-time-out value */
+			CHECK_SYS(clock_gettime(CLOCK_REALTIME,&sess_timeout));
+			sess_timeout.tv_sec += diameap_config->multi_round_time_out;
+			CHECK_FCT(fd_sess_settimeout(sess, &sess_timeout));
+			free_ans_attrib(ans_attrib);
+		}
+		else
+		{
+			avp_val.u32 = diameap_config->multi_round_time_out;
+			/* Update the session timeout with multi-round-time-out value */
+			CHECK_SYS(clock_gettime(CLOCK_REALTIME,&sess_timeout));
+			sess_timeout.tv_sec += diameap_config->multi_round_time_out;
+			CHECK_FCT(fd_sess_settimeout(sess, &sess_timeout));
+		}
+		CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	return 0;
+}
+
+static int diameap_add_eap_payload(struct diameap_state_machine * diameap_sm,
+		struct msg * ans, struct diameap_eap_interface *eap_i)
+{
+	TRACE_ENTRY("%p %p",diameap_sm,ans);
+	struct avp * avp;
+	union avp_value avp_val;
+	int ret;
+	u32 Framed_MTU = 1500; //1500 default value
+	u32 NAS_Port_Type_HeaderLength = 4;
+	int EAP_Max_Length = 0;
+
+	/* get Framed-MTU AVP value */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-MTU",&ans_attrib,0,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			Framed_MTU = ans_attrib->value.u32;
+		}
+	}
+
+	/* get NAS-Port-Type AVP value */
+	{
+		struct avp_attribute * ans_attrib;
+		CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"NAS-Port-Type",&ans_attrib,0,&ret));
+		if ((ret == 0) && (ans_attrib != NULL))
+		{
+			// = ans_attrib->value.i32;
+		}
+	}
+
+	//TD take the link type into consideration when calculating EAP_MAX_Length
+	EAP_Max_Length = Framed_MTU - NAS_Port_Type_HeaderLength;
+
+	if (eap_i->aaaEapReqData.length <= EAP_Max_Length)
+	{
+
+		/* EAP-Payload AVP */
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_eap_payload, 0, &avp));
+			avp_val.os.data = eap_i->aaaEapReqData.data;
+			avp_val.os.len = eap_i->aaaEapReqData.length;
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+
+			if (diameap_sm->lastReqEAPavp != NULL)
+			{
+				fd_msg_free(diameap_sm->lastReqEAPavp);
+				diameap_sm->lastReqEAPavp = NULL;
+			}
+
+			CHECK_FCT(fd_msg_avp_new(dataobj_eap_payload, 0, &diameap_sm->lastReqEAPavp));
+			avp_val.os.data = eap_i->aaaEapReqData.data;
+			avp_val.os.len = eap_i->aaaEapReqData.length;
+			CHECK_FCT(fd_msg_avp_setvalue(diameap_sm->lastReqEAPavp, &avp_val));
+
+		}
+	}
+	else
+	{
+		//if EAP Packet length > EAP_Max_Length
+	}
+	return 0;
+}
+
+static int diameap_send(struct msg ** rmsg)
+{
+	TRACE_ENTRY("%p",rmsg);
+	CHECK_FCT( fd_msg_send( rmsg, NULL, NULL));
+	return 0;
+}
+
+static int diameap_add_eap_success_avps(
+		struct diameap_state_machine * diameap_sm, struct msg * ans,
+		struct diameap_eap_interface *eap_i)
+{
+	TRACE_ENTRY("%p %p %p",diameap_sm,ans,eap_i);
+	struct avp * avp;
+	union avp_value avp_val;
+	int ret;
+
+	/* EAP-Master-Session-Key AVP */
+	if (eap_i->aaaEapKeyAvailable == TRUE)
+	{
+		CHECK_FCT(fd_msg_avp_new(dataobj_eap_master_session_key, 0, &avp));
+		avp_val.os.data = eap_i->aaaEapMSKData;
+		avp_val.os.len = eap_i->aaaEapMSKLength;
+		CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+
+	}
+
+	/* EAP-Key-Name AVP */
+	struct avp_attribute * avp_attrib = NULL;
+
+	CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes,"EAP-Key-Name",&avp_attrib,1,&ret))
+	if ((avp_attrib != NULL) && (ret != 1))
+	{
+		if (avp_attrib->value.os.len == 0)
+		{
+			CHECK_FCT(fd_msg_avp_new(dataobj_eap_key_name, 0, &avp));
+			avp_val.os.data = NULL;//
+			avp_val.os.len = 0;//
+			CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			free_avp_attrib(avp_attrib);
+		}
+	}
+
+	return 0;
+}
+
+int diameap_authorize(struct diameap_state_machine * diameap_sm)
+{
+	TRACE_ENTRY("%p",diameap_sm);
+
+	CHECK_FCT(diameap_authorization_get_attribs(&diameap_sm->eap_sm.user, &diameap_sm->attributes));
+
+	diameap_sm->authorized = TRUE;
+
+	CHECK_FCT_DO(diameap_answer_authorization_attributes(diameap_sm),
+	);
+	if (diameap_sm->authorized == FALSE)
+	{
+		diameap_sm->result_code = 4001; /* DIAMETER_AUTHENTICATION_REJECTED 4001 */
+	}
+	return 0;
+}
+
+static int diameap_add_accounting_eap_auth_method(
+		struct diameap_state_machine * diameap_sm, struct msg * ans)
+{
+	TRACE_ENTRY("%p %p",diameap_sm,ans);
+	int i = 0;
+	struct avp * avp;
+	union avp_value avp_val;
+	/* Accounting-EAP-Auth-Method AVP */
+	while (i < diameap_sm->eap_sm.user.methodId)
+	{
+		CHECK_FCT(fd_msg_avp_new(dataobj_accounting_eap_auth_method, 0, &avp));
+
+		avp_val.u64 = (u64) (((diameap_sm->eap_sm.user.methods[i].vendor)
+				* pow((double) 2, (double) 32))
+				+ diameap_sm->eap_sm.user.methods[i].method);
+		CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+		i++;
+	}
+	return 0;
+}
+
+static int diameap_add_eap_reissued_payload(struct msg * ans, struct msg * req)
+{
+	TRACE_ENTRY("%p %p", ans, req);
+	struct avp * avp, *re_avp;
+	union avp_value avp_val;
+	struct avp_hdr * avphdr;
+
+	if ((ans == NULL) || (req == NULL))
+	{
+		return EINVAL;
+	}
+	avp = NULL;
+	CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_payload, &avp));
+	if (avp != NULL)
+	{
+		CHECK_FCT( fd_msg_avp_hdr(avp, &avphdr));
+		CHECK_FCT( fd_msg_avp_new(dataobj_eap_reissued_payload, 0, &re_avp));
+		CHECK_MALLOC(avp_val.os.data=malloc(avphdr->avp_value->os.len));
+		memcpy(avp_val.os.data,avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+		avp_val.os.len = avphdr->avp_value->os.len;
+		CHECK_FCT(fd_msg_avp_setvalue(re_avp, &avp_val));
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, re_avp ) );
+	}
+	else
+	{
+		TRACE_DEBUG(INFO,"%sUnable to find EAP-Payload AVP in received Diameter-EAP-Request.",DIAMEAP_EXTENSION);
+		return 1;
+	}
+
+	return 0;
+}
+
+
+
+
+static int diameap_server_callback(struct msg ** rmsg, struct avp * ravp,
+		struct session * sess, void * opaque, enum disp_action * action)
+{
+	TRACE_ENTRY("%p %p %p %p", rmsg, ravp, sess, action);
+
+	struct sess_state * diameap_sess_data = NULL;
+	struct diameap_state_machine * diameap_sm = NULL;
+	struct diameap_eap_interface eap_i;
+	struct msg *req, *ans;
+	boolean non_fatal_error = FALSE;
+
+	if (rmsg == NULL)
+		return EINVAL;
+
+	req = *rmsg;
+
+	CHECK_FCT_DO(fd_sess_state_retrieve(diameap_server_reg, sess, &diameap_sess_data),
+			{	TRACE_DEBUG(INFO,"%s retrieving session state failed.",DIAMEAP_EXTENSION); goto s_end;});
+
+	CHECK_MALLOC_DO(diameap_sm = malloc(sizeof(struct diameap_state_machine)),
+			goto s_end);
+	memset(diameap_sm, 0, sizeof(struct diameap_state_machine));
+
+	if (diameap_sess_data)
+	{
+		diameap_sm->state = DIAMEAP_RECEIVED;
+		diameap_sm->eap_sm.eap_state = EAP_IDLE;
+	}
+	else
+	{
+		diameap_sm->state = DIAMEAP_DISABLED;
+		diameap_sm->eap_sm.eap_state = EAP_INITIALIZE;
+	}
+
+	while (diameap_sm->state != DIAMEAP_IDLE && diameap_sm->state
+			!= DIAMEAP_END)
+	{
+		switch (diameap_sm->state)
+		{
+		case DIAMEAP_DISABLED:
+			if (rmsg)
+			{
+				diameap_sm->state = DIAMEAP_INITIALIZE;
+			}
+			else
+			{
+				TRACE_DEBUG(INFO,"%sReceived empty Diameter EAP Request message.",DIAMEAP_EXTENSION);
+				goto s_end;
+			}
+			break;
+
+		case DIAMEAP_INITIALIZE:
+
+			CHECK_FCT_DO(diameap_initialize_diameap_sm(diameap_sm,diameap_sess_data),
+					{	TRACE_DEBUG(INFO,"%s Initializing DiamEAP state machine failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			CHECK_FCT_DO(diameap_initialize_diameap_eap_interface(&eap_i),
+					{	TRACE_DEBUG(INFO,"%s Initializing DiamEAP-EAP Interface failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sParsing AVPs",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO(diameap_parse_avps(diameap_sm, req, &eap_i), TRACE_DEBUG(INFO,"%s Unable to parse Diameter-EAP-Request AVPs.",DIAMEAP_EXTENSION))
+			;
+
+			if ((diameap_sm->result_code != 0))
+			{
+				diameap_sm->state = DIAMEAP_SEND_ERROR_MSG;
+			}
+			else
+			{
+				diameap_sm->state = DIAMEAP_AUTHENTICATION_VERIFY;
+			}
+			break;
+
+		case DIAMEAP_RECEIVED:
+
+			CHECK_FCT_DO(diameap_initialize_diameap_sm(diameap_sm,diameap_sess_data),
+					{	TRACE_DEBUG(INFO,"%s Initializing DiamEAP state machine failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			CHECK_FCT_DO(diameap_initialize_diameap_eap_interface(&eap_i),
+					{	TRACE_DEBUG(INFO,"%s Initializing DiamEAP-EAP Interface failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sParsing AVPs",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO(diameap_parse_avps(diameap_sm, req, &eap_i), TRACE_DEBUG(INFO,"%s Unable to parse Diameter-EAP-Request AVPs.",DIAMEAP_EXTENSION))
+			;
+
+			if (diameap_sm->result_code != 0)
+			{
+				diameap_sm->state = DIAMEAP_SEND_ERROR_MSG;
+			}
+			else
+			{
+				diameap_sm->state = DIAMEAP_AUTHENTICATION_VERIFY;
+			}
+			break;
+
+		case DIAMEAP_AUTHENTICATION_VERIFY:
+		{
+
+			TRACE_DEBUG(FULL+1,"%sVerify authentication",DIAMEAP_EXTENSION);
+			CHECK_FCT_DO(diameap_eap_statemachine(&diameap_sm->eap_sm, &eap_i,&non_fatal_error),
+					{	TRACE_DEBUG(INFO,"%s EAP process failed.",DIAMEAP_EXTENSION); goto s_end;});
+
+			if (non_fatal_error == TRUE)
+			{
+				TRACE_DEBUG(FULL+1,"%sAuthentication verify finished with a non-fatal-error.",DIAMEAP_EXTENSION);
+				diameap_sm->state = DIAMEAP_SEND_ERROR_MSG;
+			}
+			else
+			{
+				diameap_sm->state = DIAMEAP_SELECT_DECISION;
+
+			}
+		}
+			break;
+
+		case DIAMEAP_SELECT_DECISION:
+
+			CHECK_FCT_DO( diameap_policy_decision(diameap_sm,&eap_i),
+					goto s_end)
+			;
+
+			if ((eap_i.aaaSuccess == TRUE) && (diameap_sm->auth_request_val
+					== AUTHORIZE_AUTHENTICATE)
+					&& (diameap_sm->verify_authorization == FALSE))
+			{
+				diameap_sm->state = DIAMEAP_AUTHORIZATION_VERIFY;
+			}
+			else
+			{
+				diameap_sm->state = DIAMEAP_DIAMETER_EAP_ANSWER;
+			}
+			break;
+
+		case DIAMEAP_AUTHORIZATION_VERIFY:
+			diameap_sm->verify_authorization = TRUE;
+			TRACE_DEBUG(FULL+1,"%sVerify authorization",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO(diameap_authorize(diameap_sm),
+					{	TRACE_DEBUG(INFO,"%s Authorization check process failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			diameap_sm->state = DIAMEAP_SELECT_DECISION;
+
+			break;
+
+		case DIAMEAP_DIAMETER_EAP_ANSWER:
+			TRACE_DEBUG(FULL+1,"%screate Diameter EAP Answer",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, rmsg, 0),
+					goto s_end)
+			;
+			ans = *rmsg;
+			TRACE_DEBUG(FULL+1,"%sAdding AVPs to Diameter EAP Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_avps(diameap_sm, ans,req),
+					{	TRACE_DEBUG(INFO,"%s Unable to add AVPs to Diameter-EAP-Answer message.",DIAMEAP_EXTENSION);goto s_end;})
+			;
+			if (diameap_sm->authFailure == FALSE)
+			{
+				if (diameap_sm->eap_sm.user.id != 0)
+				{
+					TRACE_DEBUG(FULL+1,"%sSelect authentication attributes.",DIAMEAP_EXTENSION);
+					CHECK_FCT_DO(diameap_authentication_get_attribs(&diameap_sm->eap_sm.user, &diameap_sm->attributes),
+							{	TRACE_DEBUG(INFO,"%s Unable to get user's session attributes.",DIAMEAP_EXTENSION); goto s_end;});
+					TRACE_DEBUG(FULL+1,"%sCreate answer authentication attributes.",DIAMEAP_EXTENSION);
+					CHECK_FCT_DO(diameap_answer_avp_attributes(diameap_sm),
+							{	TRACE_DEBUG(INFO,"%s Unable to generate answer attributes.",DIAMEAP_EXTENSION); goto s_end;});
+				}
+
+				if (diameap_sm->authSuccess == FALSE)
+				{
+					diameap_sm->state = DIAMEAP_SEND_REQUEST;
+				}
+				else
+				{
+
+					diameap_sm->state = DIAMEAP_SEND_SUCCESS;
+				}
+			}
+			else
+			{
+				diameap_sm->state = DIAMEAP_SEND_FAILURE;
+			}
+			break;
+
+		case DIAMEAP_SEND_REQUEST:
+			TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess),
+					{	TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i),
+					{	TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sStoring DiamEAP session data.",DIAMEAP_EXTENSION)
+			;
+			CHECK_MALLOC(diameap_sess_data = malloc(sizeof(struct sess_state)))
+			;
+			memset(diameap_sess_data, 0, sizeof(struct sess_state));
+			diameap_sess_data_new(diameap_sess_data, diameap_sm);
+
+			CHECK_FCT_DO(fd_sess_state_store(diameap_server_reg, sess, &diameap_sess_data),
+					{	TRACE_DEBUG(INFO,"%s Storing session state failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+
+			CHECK_FCT_DO( diameap_send(rmsg),
+					goto s_end)
+			;
+
+			diameap_sm->state = DIAMEAP_IDLE;
+			break;
+
+		case DIAMEAP_SEND_FAILURE:
+			TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess),
+					{	TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i),
+					{	TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+
+			LOG_N("%s Auth FAIL: %.*s",DIAMEAP_EXTENSION, diameap_sm->eap_sm.user.useridLength, diameap_sm->eap_sm.user.userid);
+			
+			CHECK_FCT_DO( diameap_send(rmsg),
+					goto s_end)
+			;
+			diameap_sm->state = DIAMEAP_END;
+			break;
+
+		case DIAMEAP_SEND_SUCCESS:
+			TRACE_DEBUG(FULL+1,"%sAdding User session AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO(diameap_add_user_sessions_avps(diameap_sm,ans),
+					{	TRACE_DEBUG(INFO,"%s Adding user's session AVPs failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+
+			if (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE)
+			{
+				TRACE_DEBUG(FULL+1,"%sAdding Authorization AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION);
+				CHECK_FCT_DO(diameap_add_authorization_avps(diameap_sm,ans),
+						{	TRACE_DEBUG(INFO,"%s Adding Authorization AVPs failed.",DIAMEAP_EXTENSION); goto s_end;});
+			}
+			TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess),
+					{	TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i),
+					{	TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			TRACE_DEBUG(FULL+1,"%sAdding EAP success AVPs AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO( diameap_add_eap_success_avps(diameap_sm, ans, &eap_i),
+					goto s_end)
+			;
+			TRACE_DEBUG(FULL+1,"%sAdding Accounting-EAP-Auth-Method AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+			;
+			CHECK_FCT_DO(diameap_add_accounting_eap_auth_method(diameap_sm, ans),
+					{	TRACE_DEBUG(INFO,"%s Adding accounting AVP failed",DIAMEAP_EXTENSION); goto s_end;})
+			;
+			
+			LOG_N("%s Auth Success: %.*s",DIAMEAP_EXTENSION, diameap_sm->eap_sm.user.useridLength, diameap_sm->eap_sm.user.userid);
+			
+			CHECK_FCT_DO( diameap_send(rmsg),
+					goto s_end)
+			;
+			diameap_sm->state = DIAMEAP_END;
+			break;
+
+		case DIAMEAP_SEND_ERROR_MSG:
+			diameap_sm->invalid_eappackets++;
+			if (diameap_sm->invalid_eappackets
+					== diameap_config->max_invalid_eap_packet)
+			{
+				diameap_sm->result_code = 4001;//DIAMETER_AUTHENTICATION_REJECTED
+				TRACE_DEBUG(FULL,"%s Maximum permitted invalid EAP Packet reached. Diameter Authentication Rejected.",DIAMEAP_EXTENSION);
+			}
+
+			CHECK_FCT_DO(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, rmsg, 0),
+					goto s_end)
+			;
+
+			ans = *rmsg;
+			CHECK_FCT_DO( diameap_add_avps(diameap_sm, ans,req),
+					{	TRACE_DEBUG(INFO,"%s Adding AVPs to Diameter-EAP-Answer message failed.",DIAMEAP_EXTENSION);goto s_end;})
+			;
+			if ((non_fatal_error == TRUE) && (diameap_sm->result_code == 0))
+			{
+				diameap_sm->result_code = 1001;
+			}
+
+			if (diameap_sm->result_code == 1001)
+			{
+				CHECK_FCT_DO( diameap_add_eap_reissued_payload(ans,req), goto s_end);
+			}
+
+			if (diameap_sm->result_code == 5004)
+			{
+				CHECK_FCT_DO( fd_msg_avp_add( ans , MSG_BRW_LAST_CHILD, diameap_sm->failedavp ),goto s_end );
+			}
+
+			CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess), goto s_end)
+			;
+
+			CHECK_FCT_DO( diameap_send(rmsg), goto s_end)
+			;
+			diameap_sm->state = DIAMEAP_IDLE;
+			break;
+
+		case DIAMEAP_END:
+			break;
+
+		case DIAMEAP_IDLE:
+			break;
+		}
+	}
+
+	diameap_free(diameap_sm);
+
+	s_end: return 0;
+}
+
+int diameap_start_server(void)
+{
+	struct disp_when when;
+
+	/*create handler for sessions */
+	CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup, NULL, NULL));
+
+	/* Register the callback */
+	memset(&when, 0, sizeof(when));
+	when.command = dataobj_diameap_cmd;
+	when.app = dataobj_diameap_app;
+
+	/* Register the callback for EAP Application */
+	CHECK_FCT(fd_disp_register(diameap_server_callback, DISP_HOW_CC, &when, NULL,
+					&handle));
+
+	if (handle == NULL)
+	{
+		TRACE_DEBUG(INFO, "%sCannot register the callback !!!",DIAMEAP_EXTENSION);
+		return 1;
+	}
+	return 0;
+}
+
+int diameap_stop_server(void)
+{
+	CHECK_FCT(fd_sess_handler_destroy(&diameap_server_reg, NULL));
+	CHECK_FCT(fd_disp_unregister(&handle, NULL));
+
+	return 0;
+}
diff --git a/extensions/app_diameap/diameap_server.h b/extensions/app_diameap/diameap_server.h
new file mode 100644
index 0000000..cef11c7
--- /dev/null
+++ b/extensions/app_diameap/diameap_server.h
@@ -0,0 +1,117 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_SERVER_H_
+#define DIAMEAP_SERVER_H_
+
+ 
+/* session data structure to store */
+struct sess_state
+{
+	int invalid_eappackets; /* Number of invalid EAP Packet received*/
+
+	eap_type currentMethod;
+	u32 currentVendor;
+	int currentId;
+	int lastId;
+	void * methodData;
+
+	u8 NAKproposedMethods[251];
+
+	eap_method_state methodState;
+
+	struct eap_user user;
+};
+
+typedef enum
+{
+	AUTHENTICATE_ONLY = 1, AUTHORIZE_ONLY = 2, AUTHORIZE_AUTHENTICATE = 3
+} auth_request;
+
+struct diameap_state_machine
+{
+	int invalid_eappackets; /* Number of invalid EAP Packet received*/
+	struct avp * lastReqEAPavp; //last EAP-Payload AVP
+
+	int result_code; /*Error number for Result_code*/
+	struct fd_list attributes; //database attributes
+	struct fd_list req_attributes; //attributes from DER
+	struct fd_list ans_attributes; //attributes to be set for DEA
+	struct avp * failedavp; /* The Failed-AVP AVP. should be update whenever a Failed AVP is encountered during authentication. */
+	struct eap_state_machine eap_sm; /* EAP State Machine */
+	auth_request auth_request_val; /*the Request Type of Auth-Request-Type AVP*/
+	boolean verify_authorization; /* Set to TRUE at the authorization state. Parameter used to indicate that authorization is performed.*/
+	boolean authSuccess; // Set to TRUE if client authenticated and authorized
+	boolean authFailure; //set to TRUE if client is not authenticated
+	boolean authorized; //set to TRUE if client is authorized
+	enum
+	{
+		DIAMEAP_DISABLED,
+		DIAMEAP_INITIALIZE,
+		DIAMEAP_RECEIVED,
+		DIAMEAP_IDLE,
+		DIAMEAP_AUTHENTICATION_VERIFY,
+		DIAMEAP_SEND_ERROR_MSG,
+		DIAMEAP_SELECT_DECISION,
+		DIAMEAP_DIAMETER_EAP_ANSWER,
+		DIAMEAP_END,
+		DIAMEAP_AUTHORIZATION_VERIFY,
+		DIAMEAP_SEND_REQUEST,
+		DIAMEAP_SEND_SUCCESS,
+		DIAMEAP_SEND_FAILURE
+
+	} state; // state of DiamEAP
+
+	boolean privateUser;//TD
+};
+
+struct avp_max_occurences
+{
+	char * avp_attribute;
+	int max; //-1 means no limits
+};
+
+
+
+/* start server */
+int diameap_start_server(void);
+
+/* stop server*/
+int diameap_stop_server(void);
+
+#endif /* DIAMEAP_SERVER_H_ */
diff --git a/extensions/app_diameap/diameap_tls.c b/extensions/app_diameap/diameap_tls.c
new file mode 100644
index 0000000..e77a65c
--- /dev/null
+++ b/extensions/app_diameap/diameap_tls.c
@@ -0,0 +1,492 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "diameap_tls.h"
+
+//GCRY_THREAD_OPTION_PTHREAD_IMPL;
+
+int diameap_tls_init(struct tls_config * tls_conf)
+{
+	int ret;
+	ret = gnutls_global_init();
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+	}
+
+	gnutls_global_set_log_function(diameap_tls_log);
+	//gnutls_global_set_log_level(9);
+
+
+	if(tls_conf->cafile ==NULL){
+		fprintf(stderr,"[DiamEAP extension] [EAP TLS] Missing certification authority (CA) certificates. Please provide CA configuration directive.\n"); 
+		return EINVAL;
+	}
+	if( !tls_conf->certfile || !tls_conf->keyfile){
+		fprintf(stderr,"[DiamEAP extension] [EAP TLS] Missing private Key. Please provide Cred configuration directive.\n"); 
+		return EINVAL;
+	}
+
+	ret = gnutls_certificate_allocate_credentials(&tls_conf->cert_cred);
+
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+		return ret;
+	}
+
+	ret = gnutls_certificate_set_x509_trust_file(tls_conf->cert_cred,
+			tls_conf->cafile, GNUTLS_X509_FMT_PEM);
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+		return ret;
+	}
+	if (tls_conf->crlfile)
+	{
+		ret = gnutls_certificate_set_x509_crl_file(tls_conf->cert_cred,
+				tls_conf->crlfile, GNUTLS_X509_FMT_PEM);
+		if (ret < 0)
+		{
+			gnutls_perror(ret);
+			return ret;
+		}
+	}
+
+	ret = gnutls_certificate_set_x509_key_file(tls_conf->cert_cred,
+			tls_conf->certfile, tls_conf->keyfile, GNUTLS_X509_FMT_PEM);
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+		return ret;
+	}
+	return 0;
+}
+
+void diameap_tls_log(int lev, const char * text)
+{
+	u8 * msg;
+	if (text == NULL)
+		return;
+	msg = (u8 *) strdup(text);
+	int i;
+	for (i = 0; (G8(text+i) != '\n') && (G8(text+i) != '\0'); i++)
+	{
+	}
+	P8((msg+i),'\0');
+	fprintf(stderr, "[DiamEAP extension] [EAP TLS] GNUTLS log[%d] : %s\n", lev, msg);
+	free(msg);
+}
+
+int diameap_tls_init_session(struct tls_config * tls_conf,
+		struct tls_data * data)
+{
+	int ret;
+	ret = gnutls_init(&data->session, GNUTLS_SERVER);
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+	}
+	ret = gnutls_set_default_priority(data->session);
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+	}
+
+	ret = gnutls_credentials_set(data->session, GNUTLS_CRD_CERTIFICATE,
+			tls_conf->cert_cred);
+	if (ret < 0)
+	{
+		gnutls_perror(ret);
+	}
+
+	/* request client certificate if any.
+	 */
+	gnutls_certificate_server_set_request(data->session, GNUTLS_CERT_REQUIRE); //GNUTLS_CERT_REQUEST);
+
+	gnutls_transport_set_pull_function(data->session, diameap_tls_receive);
+	gnutls_transport_set_push_function(data->session, diameap_tls_send);
+	gnutls_transport_set_ptr(data->session, (gnutls_transport_ptr_t) data);
+
+	/* starting version 2.12, this call is not needed */
+	//gnutls_transport_set_lowat(data->session, 0);
+	
+	return ret;
+}
+
+ssize_t diameap_tls_receive(gnutls_transport_ptr_t ptr, void *buffer,
+		size_t length)
+{
+	struct tls_data * data = (struct tls_data *) ptr;
+	if (data->p_length == 0)
+	{
+		errno = EWOULDBLOCK;
+		return -1;
+	}
+	if (length > data->p_length)
+	{
+		length = data->p_length;
+	}
+	memcpy(buffer, data->tlsResp.data + (data->tlsResp.datalength
+			- data->p_length), length);
+	data->p_length -= length;
+
+	return length;
+}
+
+ssize_t diameap_tls_send(gnutls_transport_ptr_t ptr, const void *buffer,
+		size_t length)
+{
+	struct tls_data * data = (struct tls_data *) ptr;
+	data->tlsReq.data = realloc(data->tlsReq.data, data->tlsReq.datalength
+			+ length);
+	U8COPY(data->tlsReq.data,data->tlsReq.datalength,length,(u8*)buffer);
+	data->tlsReq.datalength += length;
+
+	return length;
+}
+
+int diameap_tls_new(struct tls_msg * tlsmsg)
+{
+	if (!tlsmsg)
+	{
+		return EINVAL;
+	}
+	tlsmsg->flags = 0x00;
+	tlsmsg->length = 0;
+	tlsmsg->data = NULL;
+	tlsmsg->datalength = 0;
+	return 0;
+}
+
+int diameap_tls_get_flags(struct tls_msg tlsmsg, u8 * flags)
+{
+	*flags = tlsmsg.flags;
+	return 0;
+}
+
+int diameap_tls_set_flags(struct tls_msg * tlsmsg, u8 flags)
+{
+	if (!tlsmsg)
+	{
+		return EINVAL;
+	}
+	if ((flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+	{
+		flags = flags ^ TLS_FLAG_LENGTH;
+	}
+	tlsmsg->flags = tlsmsg->flags | flags;
+	return 0;
+}
+
+int diameap_tls_get_message_length(struct tls_msg tlsmsg, u32 * length)
+{
+	if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+	{
+		*length = tlsmsg.length;
+	}
+	else
+	{
+		*length = 0;
+	}
+	return 0;
+}
+
+int diameap_tls_set_message_length(struct tls_msg * tlsmsg, u32 length)
+{
+	if (!tlsmsg)
+	{
+		return EINVAL;
+	}
+	if (length > 0)
+	{
+		tlsmsg->length = length;
+		tlsmsg->flags = tlsmsg->flags | TLS_FLAG_LENGTH;
+	}
+	else
+	{
+		tlsmsg->length = 0;
+		if ((tlsmsg->flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+		{
+			tlsmsg->flags = tlsmsg->flags ^ TLS_FLAG_LENGTH;
+		}
+	}
+	return 0;
+}
+
+int diameap_tls_get_data(struct tls_msg tlsmsg, u8** tls_data,
+		u32 * data_length)
+{
+	if (tlsmsg.datalength > 0)
+	{
+		*tls_data = malloc(sizeof(u8) * tlsmsg.datalength);
+		U8COPY(*tls_data,0,tlsmsg.datalength,tlsmsg.data);
+		*data_length = tlsmsg.datalength;
+	}
+	else
+	{
+		*tls_data = NULL;
+		*data_length = 0;
+	}
+	return 0;
+}
+
+int diameap_tls_set_data(struct tls_msg * tlsmsg, u8* tls_data, int data_length)
+{
+	if (!tlsmsg)
+	{
+		return EINVAL;
+	}
+	tlsmsg->data = malloc(sizeof(u8) * data_length);
+	U8COPY(tlsmsg->data,0,data_length,tls_data);
+	tlsmsg->datalength = data_length;
+	return 0;
+}
+
+/*
+ * data : returned data
+ * eaptls_data : the TLS_Data field
+ * length : the length of eaptls_data
+ * flags : combination of flags et set
+ */
+int diameap_tls_new_tls_packet(u8** data, int * len, struct tls_msg tlsmsg)
+{
+	int buflen, pos = 0;
+
+	buflen = 1;
+
+	if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+	{
+		buflen += 4;
+	}
+
+	if (tlsmsg.datalength > 0)
+	{
+		buflen += tlsmsg.datalength;
+	}
+	*data = malloc(sizeof(u8) * buflen);
+	memset(*data, 0, sizeof(u8) * buflen);
+	P8(*data,tlsmsg.flags);
+	pos++;
+
+	if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+	{
+		P32BIGE(*data+pos,tlsmsg.length);
+		pos += 4;
+	}
+	if (tlsmsg.data)
+	{
+		U8COPY(*data,pos,tlsmsg.datalength,tlsmsg.data);
+	}
+	*len = buflen;
+	return 0;
+}
+
+int diameap_set_tls(struct tls_msg * tlsmsg, u8 flags, u32 length,
+		u8 *tls_data, int data_length)
+{
+	diameap_tls_new(tlsmsg);
+	diameap_tls_set_flags(tlsmsg, flags);
+	diameap_tls_set_message_length(tlsmsg, length);
+	diameap_tls_set_data(tlsmsg, tls_data, data_length);
+	return 0;
+}
+
+int diameap_tls_parse(u8* data, int len, struct tls_msg * tlsmsg)
+{
+
+	if (data == NULL)
+		return EINVAL;
+	int pos = 0;
+	diameap_tls_new(tlsmsg);
+	tlsmsg->flags = G8(data);
+	pos++;
+	if ((tlsmsg->flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+	{
+		tlsmsg->length = G32BIGE(data+1);
+		pos = pos + 4;
+	}
+
+	if (len > pos)
+	{
+		tlsmsg->data = malloc(sizeof(u8) * (len - pos));
+		U8COPY(tlsmsg->data,0,(len-pos),data+pos);
+		tlsmsg->datalength = len - pos;
+	}
+	else
+	{
+		tlsmsg->data = NULL;
+		tlsmsg->datalength = 0;
+	}
+	return 0;
+}
+
+void diameap_tls_dump(struct tls_msg tlsmsg)
+{
+	u8 * data = NULL;
+	u32 len;
+	diameap_tls_get_data(tlsmsg, &data, &len);
+
+	fprintf(stderr, "-------------Dump EAP-TLS msg-------------\n");
+	u8 flags;
+	diameap_tls_get_flags(tlsmsg, &flags);
+	fprintf(stderr, "\t -flags       		: %02x ", flags);
+	if (flags & TLS_FLAG_LENGTH)
+		fprintf(stderr, " TLS_FLAG_LENGTH ");
+	if (flags & TLS_FLAG_MORE)
+		fprintf(stderr, " TLS_FLAG_MORE ");
+	if (flags & TLS_FLAG_START)
+		fprintf(stderr, " TLS_FLAG_START ");
+	fprintf(stderr, "\n");
+	if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+	{
+		u32 length;
+		diameap_tls_get_message_length(tlsmsg, &length);
+		fprintf(stderr, "\t -TLS msg length	: %u (0x%02x%02x%02x%02x)\n",
+				length, (length >> 24) & 0xffU, (length >> 16) & 0xffU, (length
+						>> 8) & 0xffU, length & 0xffU);
+	}
+	fprintf(stderr, "\t -data length		: %d \n", len);
+	/*
+	if (len > 0)
+	{
+		int i;
+		fprintf(stderr, "\t -Data			: ");
+		for (i = 0; i < len; i++)
+		{
+			fprintf(stderr, "%02x ", G8(data + i));
+		}
+		fprintf(stderr, "\n");
+	}
+	*/
+	fprintf(stderr, "-------------End Dump EAP-TLS msg-------------\n");
+	
+	free(data);
+}
+
+int diameap_tls_initialize(struct tls_data * data)
+{
+	if (!data)
+	{
+		return EINVAL;
+	}
+	data->state = START;
+	data->more_tosend_length = 0;
+	data->more_toreceive = FALSE;
+	data->handshake = FALSE;
+	return 0;
+}
+
+int diameap_tls_reassemble(struct tls_msg * to, struct tls_msg from)
+{
+	u8 from_flag;
+	diameap_tls_get_flags(from, &from_flag);
+
+	if (from_flag & TLS_FLAG_LENGTH)
+	{
+		diameap_tls_new(to);
+		u32 length;
+		diameap_tls_get_message_length(from, &length);
+		diameap_tls_set_message_length(to, length);
+	}
+	diameap_tls_set_flags(to, from_flag);
+
+	u8 * tlsRespData;
+	u32 tlsRespDataLength;
+	diameap_tls_get_data(from, &tlsRespData, &tlsRespDataLength);
+	to->data = realloc(to->data, to->datalength + tlsRespDataLength);
+	U8COPY(to->data,to->datalength,tlsRespDataLength,tlsRespData);
+	to->datalength += tlsRespDataLength;
+	free(tlsRespData);
+	return 0;
+}
+
+int diameap_tls_copy(struct tls_msg * to, struct tls_msg from)
+{
+	u8 flag;
+	u32 length;
+	u8 * data;
+	diameap_tls_new(to);
+	diameap_tls_get_flags(from, &flag);
+	diameap_tls_set_flags(to, flag);
+	diameap_tls_get_message_length(from, &length);
+	diameap_tls_set_message_length(to, length);
+	length = 0;
+	diameap_tls_get_data(from, &data, &length);
+	diameap_tls_set_data(to, data, length);
+	return 0;
+}
+
+int diameap_tls_process_receive(struct tls_data * data)
+{
+	int ret;
+
+	data->p_length = data->tlsResp.datalength;
+
+	ret = gnutls_handshake(data->session);
+
+	if (ret < 0)
+	{
+		switch (ret)
+		{
+		case GNUTLS_E_AGAIN:
+			break;
+		case GNUTLS_E_INTERRUPTED:
+			fprintf(stderr, "[DiamEAP extension] [EAP TLS] gnutls handshake : GNUTLS_E_INTERRUPTED");
+			break;
+		case GNUTLS_E_GOT_APPLICATION_DATA:
+			fprintf(stderr,
+					"[DiamEAP extension] [EAP TLS] gnutls handshake : GNUTLS_E_GOT_APPLICATION_DATA");
+			break;
+		case GNUTLS_E_WARNING_ALERT_RECEIVED:
+			fprintf(stderr,
+					"[DiamEAP extension] [EAP TLS] gnutls handshake : GNUTLS_E_WARNING_ALERT_RECEIVED");
+			break;
+		}
+		if (ret != GNUTLS_E_AGAIN)
+		{
+			gnutls_perror(ret);
+		}
+	}
+	if (ret == GNUTLS_E_SUCCESS)
+	{
+		data->handshake = TRUE;
+	}
+	return 0;
+}
+
diff --git a/extensions/app_diameap/diameap_tls.h b/extensions/app_diameap/diameap_tls.h
new file mode 100644
index 0000000..c5774e7
--- /dev/null
+++ b/extensions/app_diameap/diameap_tls.h
@@ -0,0 +1,141 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_TLS_H_
+#define DIAMEAP_TLS_H_
+
+#if defined(__GNUC__)
+# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
+# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406		/* 4.6.x */
+#  define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \
+     GCC_DIAG_PRAGMA(ignored x)
+#  define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop)
+# else							/* older */
+#  define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored x)
+#  define GCC_DIAG_ON(x)  GCC_DIAG_PRAGMA(warning x)
+# endif
+#else
+# define GCC_DIAG_OFF(x)
+# define GCC_DIAG_ON(x)
+#endif
+
+
+#include "diameap_defs.h"
+#include <gnutls/gnutls.h>
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <errno.h>
+#include <pthread.h>
+
+
+
+#define TLS_FLAG_LENGTH	0x80
+#define TLS_FLAG_MORE	0x40
+#define TLS_FLAG_START	0x20
+
+struct tls_config{
+	char * conffile;
+	//certificates
+	char * keyfile;
+	char * certfile;
+	char * cafile;
+	char * crlfile;
+
+	//configuration parameters
+	boolean check_cert_cn_username;
+
+	int max_size;
+
+	gnutls_certificate_credentials_t cert_cred;
+};
+
+struct tls_msg{
+	u8	flags;
+	u32 length;
+	u8 *data;
+	u32 datalength;
+};
+
+struct tls_data
+{
+	gnutls_session_t session;
+	enum { START, CONTINUE, SUCCESS, FAILURE } state;
+	struct tls_msg tlsReq;
+	int p_length; 			/* length of buffer still not returned to handshake */
+	struct tls_msg tlsResp;
+	int more_tosend_length;	/* 0 if no more fragment to send. Otherwise the length of the buff not yet sent */
+	boolean more_toreceive; /* TRUE if wait for more fragments. */
+	boolean handshake; 		/* TRUE if handshake terminated successful. */
+};
+
+int diameap_tls_init(struct tls_config * tls_conf );
+void diameap_tls_log(int lev, const char * text);
+int diameap_tls_init_session(struct tls_config * tls_conf, struct tls_data * data);
+int diameap_tls_new(struct tls_msg * tlsmsg);
+
+int diameap_tls_get_message_length(struct tls_msg tlsmsg, u32 * length);
+int diameap_tls_set_message_length(struct tls_msg * tlsmsg, u32 length);
+
+int diameap_tls_get_flags(struct tls_msg tlsmsg, u8 * flags);
+int diameap_tls_set_flags(struct tls_msg * tlsmsg, u8 flags);
+
+int diameap_tls_get_data(struct tls_msg tlsmsg, u8** tls_data, u32 * data_length);
+int diameap_tls_set_data(struct tls_msg * tlsmsg, u8* tls_data, int data_length);
+
+int diameap_tls_parse(u8* data, int length, struct tls_msg * tlsmsg);
+
+int diameap_tls_new_tls_packet(u8** data, int * len, struct tls_msg tlsmsg);
+
+int diameap_set_tls(struct tls_msg * tlsmsg, u8 flags, u32 length,u8 *tls_data, int data_length);
+
+void diameap_tls_dump(struct tls_msg tlsmsg);
+
+int diameap_tls_initialize(struct tls_data * data);
+
+int diameap_tls_reassemble(struct tls_msg * to,struct tls_msg from);
+
+int diameap_tls_copy(struct tls_msg * to,struct tls_msg from);
+
+int diameap_tls_process_receive(struct tls_data * data);
+
+ssize_t diameap_tls_receive(gnutls_transport_ptr_t data , void *buffer, size_t length);
+ssize_t diameap_tls_send(gnutls_transport_ptr_t data , const void *buffer, size_t length);
+
+#endif /* DIAMEAP_TLS_H_ */
diff --git a/extensions/app_diameap/diameap_user.c b/extensions/app_diameap/diameap_user.c
new file mode 100644
index 0000000..8e8de1b
--- /dev/null
+++ b/extensions/app_diameap/diameap_user.c
@@ -0,0 +1,152 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "libdiameap.h"
+
+int diameap_user_get_userid(struct eap_user *user, u8* userid)
+{
+	TRACE_ENTRY("%p %p",user,userid);
+	if (user->userid == NULL)
+		return EINVAL;
+	userid = user->userid;
+	return 0;
+}
+
+int diameap_user_get_password(struct eap_user *user, u8* password,u16 * passwordlength)
+{
+	TRACE_ENTRY("%p %p",user,password);
+	if (user->password == NULL)
+		return EINVAL;
+	password = user->password;
+	*passwordlength = user->passwordLength;
+	return 0;
+}
+
+int diameap_user_get_passwordlength(struct eap_user *user, u16 * passwordlength)
+{
+	TRACE_ENTRY("%p %p",user,passwordlength);
+	if (user->password == NULL)
+		return EINVAL;
+	*passwordlength = user->passwordLength;
+	return 0;
+}
+
+int diameap_user_set_password(struct eap_user * user, u8 * password,
+		u16 passwordLength)
+{
+	TRACE_ENTRY("%p %p %hu",user,password,passwordLength);
+	if (password == NULL)
+		return EINVAL;
+	if (passwordLength < 1)
+		return EINVAL;
+	user->password = password;
+	user->passwordLength = passwordLength;
+	return 0;
+}
+
+int diameap_user_set_userid(struct eap_user * user, u8 * userid,
+		u16 useridLength)
+{
+	TRACE_ENTRY("%p %p %hu",user,userid,useridLength);
+	if (userid == NULL)
+		return EINVAL;
+	if (useridLength < 1)
+		return EINVAL;
+	user->userid = userid;
+	user->useridLength = useridLength;
+	return 0;
+}
+
+int diameap_user_get_methodid(struct eap_user *user, int * methodid)
+{
+	TRACE_ENTRY("%p %p",user,methodid);
+	if (user->password == NULL)
+		return EINVAL;
+	*methodid = user->methodId;
+	return 0;
+}
+
+int diameap_user_set_methodid(struct eap_user * user, int methodId)
+{
+	TRACE_ENTRY("%p %d",user,methodId);
+	if (user->password == NULL)
+		return EINVAL;
+	if (methodId < 0)
+		return EINVAL;
+	user->methodId = methodId;
+	return 0;
+}
+
+boolean diameap_user_issuccess(struct eap_user *user)
+{
+	TRACE_ENTRY("%p",user);
+	if (user->password == NULL)
+		return FALSE;
+	return user->success;
+}
+
+int diameap_user_set_success(struct eap_user * user)
+{
+	TRACE_ENTRY("%p",user);
+	if (user->password == NULL)
+		return EINVAL;
+	user->success = TRUE;
+	return 0;
+}
+
+int diameap_user_get_eap_method(struct eap_user *user, int id,
+		struct eap_method *method)
+{
+	TRACE_ENTRY("%p %d %p",user,id,method);
+	if (sizeof(user->methods) >= (id - 1))
+		*method = user->methods[id];
+	return 0;
+}
+
+int diameap_user_set_eap_method(struct eap_user * user, int id,
+		struct eap_method * method)
+{
+	TRACE_ENTRY("%p %d %p",user,id,method);
+	if (user->password == NULL)
+		return EINVAL;
+	if (sizeof(user->methods) < (id - 1))
+		return EINVAL;
+	user->methods[id].vendor = method->vendor;
+	user->methods[id].method = method->method;
+	return 0;
+}
diff --git a/extensions/app_diameap/diameap_user.h b/extensions/app_diameap/diameap_user.h
new file mode 100644
index 0000000..f798a88
--- /dev/null
+++ b/extensions/app_diameap/diameap_user.h
@@ -0,0 +1,98 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_USER_H_
+#define DIAMEAP_USER_H_
+
+#define MAXMETHODS 8 	/*Maximum number of allowed methods */
+
+#define MAXPROPOSEDMETHODS 8 	/*Maximum number of allowed proposed methods */
+
+#define	VENDOR_IETF 0
+
+/*EAP User structure */
+struct eap_user
+{
+	int id;	/*user's identifier*/
+	u8 	*userid;	/*user's identity*/
+	u16	useridLength;	/*User's identity length*/
+	u8 	*password; /*user's password*/
+	u16 passwordLength;	/*Length of password*/
+
+	int methodId;	/*Current method Id*/
+	struct eap_method
+	{
+		u32 vendor;
+		eap_type method;
+	} methods[MAXMETHODS]; /*used method for authentication*/
+
+	struct proposed_eap_method
+	{
+		u32 vendor;
+		eap_type method;
+	} proposedmethods[MAXPROPOSEDMETHODS]; /* methods proposed throw NAK response or EXPANDED NAK*/
+	int pmethods; /*Number of accepted methods from peer's proposed methods*/
+
+	eap_type proposed_eap_method; /* Proposed EAP Method*/
+	u32 proposed_eap_method_vendor;
+	boolean success; /* Set to TRUE if User is authenticated successfully */
+};
+
+boolean check_user_identity;
+
+int diameap_user_get_password(struct eap_user *user, u8 * password,u16 *length);
+
+int diameap_user_get_userid(struct eap_user *user, u8 * userid);
+
+int diameap_user_set_password(struct eap_user * user, u8 * password, u16 Length);
+
+int diameap_user_set_userid(struct eap_user * user, u8 * userid, u16 Length);
+
+int diameap_user_get_methodid(struct eap_user *user,int *methodId);
+
+int diameap_user_set_methodid(struct eap_user * user, int methodId);
+
+boolean diameap_user_issuccess(struct eap_user *user);
+
+int diameap_user_set_success(struct eap_user * user);
+
+int diameap_user_get_eap_method(struct eap_user *user, int id, struct eap_method * eapmethod);
+
+int diameap_user_set_eap_method(struct eap_user * user, int id, struct eap_method * method);
+
+#endif /* DIAMEAP_USER_H_ */
diff --git a/extensions/app_diameap/libcrypt.c b/extensions/app_diameap/libcrypt.c
new file mode 100644
index 0000000..846d6c8
--- /dev/null
+++ b/extensions/app_diameap/libcrypt.c
@@ -0,0 +1,56 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "libcrypt.h"
+
+int md5hash(void * buffer, int length, void * digest){
+
+	gcry_md_hd_t md5_ctx;
+
+	gcry_md_open ( &md5_ctx, GCRY_MD_MD5, 0);
+
+	if(!gcry_md_is_enabled(md5_ctx, GCRY_MD_MD5)){
+		fprintf(stderr,"[libcrypt] unable to initiate MD5 hash algorithm.\n");
+	}
+
+	gcry_md_write(md5_ctx,buffer,length);
+
+	memcpy (digest, gcry_md_read (md5_ctx, 0), 16);
+	gcry_md_close (md5_ctx);
+	return 0;
+}
diff --git a/extensions/app_diameap/libcrypt.h b/extensions/app_diameap/libcrypt.h
new file mode 100644
index 0000000..375234b
--- /dev/null
+++ b/extensions/app_diameap/libcrypt.h
@@ -0,0 +1,54 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef LIBCRYPT_H_
+#define LIBCRYPT_H_
+
+/* EAP-TLS*/
+#include "diameap_tls.h"
+
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <stdio.h>
+
+
+
+int md5hash(void * buffer, int length, void * digest);
+
+#endif /* LIBCRYPT_H_ */
diff --git a/extensions/app_diameap/libdiameap.h b/extensions/app_diameap/libdiameap.h
new file mode 100644
index 0000000..b459e29
--- /dev/null
+++ b/extensions/app_diameap/libdiameap.h
@@ -0,0 +1,187 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef LIBDIAMEAP_H_
+#define LIBDIAMEAP_H_
+
+#include <freeDiameter/extension.h>
+
+#define DIAMEAP_EXTENSION "[DiamEAP extension] "
+
+#include "diameap_defs.h"
+#include "diameap_eappacket.h"
+#include "diameap_user.h"
+#include "diameap_mysql.h"
+
+#include <math.h>
+#include <dlfcn.h>
+
+
+/* authentication and authorization attributes  */
+
+struct auth_attribute
+{
+	struct fd_list chain;
+	char * attrib;
+	char * op;
+	char * value;
+};
+
+struct avp_attribute
+{
+	struct fd_list chain;
+	char * attrib;
+	union avp_value value;
+	int tofree;
+};
+
+
+/************************************************/
+/*		EAP Methods	plugins							*/
+/************************************************/
+
+/* The register functions of an EAP method */
+struct register_plugin
+{
+	char * configure;
+	char * init;
+	char * initPickUp;
+	char * buildReq;
+	char * isDone;
+	char * process;
+	char * check;
+	char * getTimeout;
+	char * getKey;
+	char * unregister;
+	char * datafree;
+};
+
+struct eap_state_machine;
+/* List of plugins to load ( only EAP methods declared in the configuration file will be loaded) */
+struct plugin
+{
+	struct fd_list chain; /* link in the list */
+	u32 vendor;	/* vendor*/
+	const char *methodname; /* name of the EAP method*/
+	eap_type methodtype; /* type number of the EAP method */
+	char *pluginfile; /* plugin filename */
+	char *conffile; /* optional configuration file name for the method */
+	void *handler; /* object returned by dlopen() */
+	int (*eap_method_configure)(char * configfile); /* (Optional) address of the eap_method_configure method */
+	int (*eap_method_init)(struct eap_state_machine *smd); /* address of the eap_method_init method */
+	int (*eap_method_initPickUp)(struct eap_state_machine *smd); /* address of the eap_method_initPickUp method */
+	int (*eap_method_buildReq)(struct eap_state_machine *smd,
+			u8 identifier,struct eap_packet * eapPacket); /* address of the eap_method_buildReq method */
+	int (*eap_method_getTimeout)(struct eap_state_machine *smd, int * timeout); /* address of the eap_method_getTimeout method */
+	boolean (*eap_method_check)(struct eap_state_machine *smd,
+			struct eap_packet * eapRespData); /* address of the eap_method_check method */
+	int (*eap_method_process)(struct eap_state_machine *smd,
+			struct eap_packet * eapRespData); /* address of the eap_method_process method */
+	boolean (*eap_method_isDone)(struct eap_state_machine *smd); /* address of the eap_method_isDone method */
+	int (*eap_method_getKey)(struct eap_state_machine *smd, u8 ** msk,int *msklength, 
+			u8 ** emsk,int *emsklength); /* address of the eap_method_getKey method */
+	void (*eap_method_unregister)(void); /* (Optional) address of the eap_method_unregister method */
+	void (*eap_method_free)(void *); /* (Optional) address of the eap_method_datafree method */
+
+};
+
+
+/************************************************/
+/*		EAP State Machine						*/
+/************************************************/
+
+/* EAP Policy Decision */
+typedef enum
+{
+	DECISION_FAILURE = 0, DECISION_SUCCESS = 1, DECISION_CONTINUE = 2
+} decision;
+
+typedef enum
+{
+	EAP_M_END, EAP_M_CONTINUE, EAP_M_PROPOSED
+} eap_method_state;
+
+/* EAP Backend Authenticator State Machine (RFC4137) */
+/* Most of variables are described in the part 6 of the RFC 4137 */
+/* */
+struct eap_state_machine
+{
+	/*Local state Machine Variables*/
+
+	/* Long-Term (Maintained between Packets) */
+	eap_type currentMethod;
+	u32 currentVendor;
+	int currentId;
+	int lastId;
+	void * methodData;
+	struct plugin *selectedMethod;
+	u8 NAKproposedMethods[251];
+
+	eap_method_state methodState;
+
+	struct eap_user user;
+
+	/* Short-Term (Not Maintained between exchanged Diameter EAP messages)*/
+	boolean rxResp;
+	int respId;
+	eap_type respMethod;
+	int respVendorMethod;
+	u32 respVendor;
+	decision sm_decision;
+	enum
+	{
+		EAP_INITIALIZE,
+		EAP_PICK_UP_METHOD,
+		EAP_IDLE,
+		EAP_RECEIVED,
+		EAP_SEND_REQUEST,
+		EAP_INTEGRITY_CHECK,
+		EAP_METHOD_REQUEST,
+		EAP_METHOD_RESPONSE,
+		EAP_PROPOSE_METHOD,
+		EAP_NAK,
+		EAP_SELECT_ACTION,
+		EAP_END,
+		EAP_DISCARD
+	} eap_state;
+
+};
+
+
+
+#endif /* LIBDIAMEAP_H_ */
diff --git a/extensions/app_diameap/plugins.h b/extensions/app_diameap/plugins.h
new file mode 100644
index 0000000..edf92e5
--- /dev/null
+++ b/extensions/app_diameap/plugins.h
@@ -0,0 +1,82 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef _PLUGINS_H
+#define _PLUGINS_H
+
+#include "libdiameap.h"
+#include "libcrypt.h"
+
+
+
+
+/* Macro that define the register functions of an EAP method */
+#define REGISTER_METHOD(_methodName, _configFunction, _initFunction, _initPickUpFunction, _buildReqFunction, _getTimeoutFunction, _checkFunction, _processFunction, _isDoneFunction, _getKeyFunction, _unregisterFunction, _datafreeFunction  ) \
+static struct register_plugin *registerplugin = NULL;	\
+static int isregistered = 0;	\
+int diameap_plugin_register() {	\
+		if (!isregistered){	\
+			registerplugin = malloc (sizeof(struct register_plugin)); \
+			if(registerplugin==NULL) \
+				fprintf(stderr,"[DiamEAP extension] Error in registering plug-in\t%s\n",strerror(errno)); \
+			memset(registerplugin, 0, sizeof(struct register_plugin)); \
+			if(_configFunction) registerplugin->configure=_configFunction;	\
+			if(_initFunction) registerplugin->init=_initFunction;	\
+			if(_initPickUpFunction) registerplugin->initPickUp=_initPickUpFunction;	\
+			if(_buildReqFunction) registerplugin->buildReq=_buildReqFunction;	\
+			if(_getTimeoutFunction) registerplugin->getTimeout=_getTimeoutFunction;	\
+			if(_checkFunction) registerplugin->check=_checkFunction;	\
+			if(_processFunction) registerplugin->process=_processFunction;	\
+			if(_isDoneFunction) registerplugin->isDone=_isDoneFunction;	\
+			if(_getKeyFunction) registerplugin->getKey=_getKeyFunction;	\
+			if(_unregisterFunction) registerplugin->unregister=_unregisterFunction;	\
+			if(_datafreeFunction) registerplugin->datafree=_datafreeFunction;	\
+			isregistered++; \
+		}else{ \
+			 fprintf(stderr, "Cannot register the " _methodName " plugin twice\n");	\
+			return EINVAL; \
+		} \
+		return 0; \
+	}	\
+int diameap_plugin_objects(struct register_plugin ** rplugin){ \
+*rplugin=registerplugin; \
+return 0; \
+} \
+
+
+#endif /*_PLUGINS_H*/
diff --git a/extensions/app_diameap/plugins/CMakeLists.txt b/extensions/app_diameap/plugins/CMakeLists.txt
new file mode 100644
index 0000000..5b36611
--- /dev/null
+++ b/extensions/app_diameap/plugins/CMakeLists.txt
@@ -0,0 +1,34 @@
+PROJECT("EAP Methods Plugins" C)
+
+MACRO(EAP_ADD_METHOD METHNAME)
+  ADD_LIBRARY(${METHNAME} MODULE ${ARGN})
+  SET_TARGET_PROPERTIES(${METHNAME} PROPERTIES PREFIX "" )
+  SET_TARGET_PROPERTIES(${METHNAME} PROPERTIES SUFFIX ".emp" )
+  INSTALL(TARGETS ${METHNAME}
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-eap-server)
+ENDMACRO(EAP_ADD_METHOD)
+
+# Use the macro FD_EAP_PLUGIN(extmacroname subdir descr default) to 
+# add a new extension subdirectory.
+MACRO(FD_EAP_PLUGIN EXTSUBDIR EXTDESCR EXTDEFAULT)
+   STRING(TOUPPER ${EXTSUBDIR} EXTMACRONAME)
+   IF (NOT ALL_EXTENSIONS)
+     OPTION(BUILD_${EXTMACRONAME} ${EXTDESCR} ${EXTDEFAULT})
+   ENDIF (NOT ALL_EXTENSIONS)
+   IF (BUILD_${EXTMACRONAME} OR ALL_EXTENSIONS)
+      ADD_SUBDIRECTORY(${EXTSUBDIR})
+   ENDIF (BUILD_${EXTMACRONAME} OR ALL_EXTENSIONS)
+ENDMACRO(FD_EAP_PLUGIN)
+
+###########################
+# EAP Methods Plugins Section
+
+# EAP Identity plugin
+FD_EAP_PLUGIN(eap_identity "Build EAP Identity Plugin " ON)
+
+# EAP MD5 plugin
+FD_EAP_PLUGIN(eap_md5 "Build EAP-MD5 Plugin " OFF)
+
+# EAP TLS plugin
+FD_EAP_PLUGIN(eap_tls "Build EAP-TLS Plugin " OFF)
diff --git a/extensions/app_diameap/plugins/eap_identity/CMakeLists.txt b/extensions/app_diameap/plugins/eap_identity/CMakeLists.txt
new file mode 100644
index 0000000..45f469f
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_identity/CMakeLists.txt
@@ -0,0 +1,4 @@
+# EAP Identity plugin
+PROJECT("EAP Identity Plugin" C)
+
+EAP_ADD_METHOD(eap_identity eap_identity.c)
diff --git a/extensions/app_diameap/plugins/eap_identity/eap_identity.c b/extensions/app_diameap/plugins/eap_identity/eap_identity.c
new file mode 100644
index 0000000..e736f9d
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_identity/eap_identity.c
@@ -0,0 +1,177 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "../../plugins.h"
+
+struct identity_data
+{
+	enum
+	{
+		IDENTITY_CONTINUE, IDENTITY_SUCCESS, IDENTITY_FAILURE
+	} state;
+};
+
+int identity_init(struct eap_state_machine *smd);
+int identity_initPickUp(struct eap_state_machine *smd);
+int identity_buildReq(struct eap_state_machine *smd, u8 identity, struct eap_packet * eapPacket);
+boolean identity_check(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+int identity_process(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+boolean identity_isDone(struct eap_state_machine *smd);
+void identity_free(void * data);
+
+REGISTER_METHOD("identity", NULL, "identity_init", "identity_initPickUp", "identity_buildReq", NULL, "identity_check", "identity_process", "identity_isDone", NULL, NULL, "identity_free");
+
+
+int identity_init(struct eap_state_machine *smd)
+{
+	struct identity_data *data = NULL;
+	CHECK_MALLOC(data = malloc(sizeof(struct identity_data)));
+	memset(data, 0, sizeof(struct identity_data));
+	data->state = IDENTITY_CONTINUE;
+	smd->methodData = (struct identity_data*) data;
+
+	return 0;
+}
+
+int identity_initPickUp(struct eap_state_machine *smd)
+{
+	struct identity_data *data = NULL;
+	CHECK_MALLOC(data = malloc(sizeof(struct identity_data)));
+	memset(data, 0, sizeof(struct identity_data));
+	data->state = IDENTITY_CONTINUE;
+	smd->methodData = (struct identity_data*) data;
+	return 0;
+}
+
+int identity_buildReq(struct eap_state_machine *smd, u8 identity, struct eap_packet * eapPacket)
+{
+
+	CHECK_FCT(diameap_eap_new(EAP_REQUEST, identity, TYPE_IDENTITY, NULL, 0,eapPacket));
+	return 0;
+
+}
+
+
+boolean identity_check(struct eap_state_machine *smd, struct eap_packet *eapPacket)
+{
+
+	if (eapPacket->data == NULL)
+	{
+		TRACE_DEBUG(INFO,"%s[EAP Identity plugin] Empty EAP packet received.",DIAMEAP_EXTENSION);
+		return FALSE;
+	}
+	eap_type type;
+	if(diameap_eap_get_type(eapPacket,&type)!=0){
+		return FALSE;
+	}
+	if (type == TYPE_IDENTITY)
+	{
+		u16 length;
+		CHECK_FCT(diameap_eap_get_length(eapPacket,&length));
+		if ((int)length < 6)
+		{
+			TRACE_DEBUG(INFO,"%s[EAP Identity plugin] Incorrect EAP packet received (length = %d ).",DIAMEAP_EXTENSION,length);
+			return FALSE;
+		}
+		if ((int)length > 1020)
+		{
+			TRACE_DEBUG(INFO,"%s[EAP Identity plugin] Incorrect EAP packet received (length = %d ).",DIAMEAP_EXTENSION,length);
+			return FALSE;
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+int identity_process(struct eap_state_machine *smd, struct eap_packet *eapRespData)
+{
+	struct identity_data * data;
+	u16 length;
+	char * user;
+	u8 * Respdata;
+	int len,ret;
+
+	CHECK_FCT(diameap_eap_get_length(eapRespData,&length));
+	data = (struct identity_data*) smd->methodData;
+
+	CHECK_MALLOC(user=malloc(sizeof(char)*((int)length-4)));
+
+	diameap_eap_get_data(eapRespData,&Respdata,&len);
+	if(Respdata==NULL){
+		data->state = IDENTITY_FAILURE;
+		goto end;
+	}
+	U8COPY((u8 *)user,0,len,Respdata);
+	user[length-5]='\0';
+	if(check_user_identity == FALSE){
+		ret=diameap_get_eap_user(&(smd->user),"Default User");
+		CHECK_MALLOC_DO(smd->user.userid=realloc(smd->user.userid,strlen(user)+1),{ret = 1; goto next;});
+		memcpy(smd->user.userid,user,strlen(user)+1);
+		smd->user.useridLength = strlen(user);
+	} else {
+		ret=diameap_get_eap_user(&(smd->user),user);
+	}
+next:
+	if(ret==0)
+	{
+		smd->user.methodId = -1;
+		data->state = IDENTITY_SUCCESS;
+	}else{
+		data->state = IDENTITY_FAILURE;
+	}
+end:
+	smd->methodData = data;
+	free(user);
+	user=NULL;
+	return 0;
+}
+
+boolean identity_isDone(struct eap_state_machine *smd)
+{
+	struct identity_data *data;
+	data = (struct identity_data*) smd->methodData;
+	if (data->state != IDENTITY_CONTINUE)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+void identity_free(void * data)
+{
+	free(data);
+	data=NULL;
+}
diff --git a/extensions/app_diameap/plugins/eap_md5/CMakeLists.txt b/extensions/app_diameap/plugins/eap_md5/CMakeLists.txt
new file mode 100644
index 0000000..1c0253b
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_md5/CMakeLists.txt
@@ -0,0 +1,4 @@
+# EAP MD5 Plugin
+PROJECT("EAP MD5 Plugin" C)
+
+EAP_ADD_METHOD(eap_md5 eap_md5.c)
diff --git a/extensions/app_diameap/plugins/eap_md5/eap_md5.c b/extensions/app_diameap/plugins/eap_md5/eap_md5.c
new file mode 100644
index 0000000..d21c9ce
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_md5/eap_md5.c
@@ -0,0 +1,200 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "../../plugins.h"
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+
+#define CHALLENGE_LEN	16
+
+struct eap_md5_data
+{
+	enum
+	{
+		EAP_MD5_CONTINUE, EAP_MD5_SUCCESS, EAP_MD5_FAILURE
+	} state;
+	u8 * challenge;
+};
+
+int eap_md5_configure(char * configfile);
+int eap_md5_init(struct eap_state_machine *smd);
+int eap_md5_initPickUp(struct eap_state_machine *smd);
+int eap_md5_buildReq(struct eap_state_machine *smd, u8 eap_md5,
+		struct eap_packet * eapPacket);
+boolean eap_md5_check(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+int eap_md5_process(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+boolean eap_md5_isDone(struct eap_state_machine *smd);
+void eap_md5_free(void * data);
+
+REGISTER_METHOD("eap_md5", "eap_md5_configure", "eap_md5_init", "eap_md5_initPickUp", "eap_md5_buildReq", NULL, "eap_md5_check", "eap_md5_process", "eap_md5_isDone", NULL, NULL, "eap_md5_free")
+;
+
+int eap_md5_configure(char * configfile)
+{
+	gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+
+	return 0;
+}
+
+int eap_md5_init(struct eap_state_machine *smd)
+{
+	struct eap_md5_data *data = NULL;
+	CHECK_MALLOC(data = malloc(sizeof(struct eap_md5_data)));
+	memset(data, 0, sizeof(struct eap_md5_data));
+	data->state = EAP_MD5_CONTINUE;
+	data->challenge = NULL;
+	smd->methodData = (struct eap_md5_data*) data;
+	return 0;
+}
+
+
+int eap_md5_buildReq(struct eap_state_machine *smd, u8 id,
+		struct eap_packet * eapPacket)
+{
+	struct eap_md5_data * data;
+	u8 *payload, *challenge;
+
+	data = (struct eap_md5_data *) smd->methodData;
+	CHECK_MALLOC( challenge=malloc(sizeof(u8)*CHALLENGE_LEN));
+	CHECK_MALLOC( payload=malloc(sizeof(u8)*(CHALLENGE_LEN+1)));
+	memset(payload, 0, sizeof(u8) * (CHALLENGE_LEN + 1));
+
+	gcry_create_nonce(challenge,CHALLENGE_LEN);
+	U8COPY(payload, 1, CHALLENGE_LEN, challenge);
+	payload[0] = (u8) CHALLENGE_LEN;
+	CHECK_FCT(diameap_eap_new(EAP_REQUEST, id, TYPE_EAP_MD5, payload, CHALLENGE_LEN
+					+ 1,eapPacket));
+	CHECK_MALLOC(data->challenge=realloc(data->challenge,sizeof(u8)*CHALLENGE_LEN));
+	U8COPY(data->challenge,0,CHALLENGE_LEN,challenge);
+
+	smd->methodData = data;
+
+	free(challenge);
+	challenge=NULL;
+	free(payload);
+	payload=NULL;
+
+	return 0;
+}
+
+
+boolean eap_md5_check(struct eap_state_machine *smd, struct eap_packet *eapRespData)
+{
+	eap_type type;
+	if(diameap_eap_get_type(eapRespData,&type)!=0){
+		return FALSE;
+	}
+	if (type == TYPE_EAP_MD5)
+	{
+		u16 length;
+		CHECK_FCT(diameap_eap_get_length(eapRespData,&length));
+		if ((int) length < 6)
+		{
+			TRACE_DEBUG(INFO,"%s[EAP MD5 plugin] Incorrect EAP packet received (length = %d ).",DIAMEAP_EXTENSION,length);
+			return FALSE;
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+
+int eap_md5_process(struct eap_state_machine *smd, struct eap_packet *eapRespData)
+{
+
+	struct eap_md5_data * data;
+	int wordlen = 0, i = 0;
+	u8 * word, *hash, id;
+	data = (struct eap_md5_data*) smd->methodData;
+	wordlen = 1 + smd->user.passwordLength + CHALLENGE_LEN;
+	CHECK_MALLOC(word = malloc(sizeof(u8)*wordlen));
+	memset(word, 0, sizeof(u8) * wordlen);
+	CHECK_FCT(diameap_eap_get_identifier(eapRespData,&id));
+	*word = id;
+	U8COPY(word,1,smd->user.passwordLength,smd->user.password);
+	U8COPY(word,1+smd->user.passwordLength,CHALLENGE_LEN,data->challenge);
+	CHECK_MALLOC(hash = malloc(sizeof(u8)*16));
+
+	md5hash(word, wordlen, hash);
+
+
+	for (i = 0; i < CHALLENGE_LEN; i++)
+	{
+		if (G8(hash + i) != G8(eapRespData->data + 6 + i))
+		{
+			data->state = EAP_MD5_FAILURE;
+		}
+	}
+
+	if (data->state != EAP_MD5_FAILURE)
+	{
+		data->state = EAP_MD5_SUCCESS;
+		smd->user.success = TRUE;
+	}
+
+	smd->methodData = data;
+	free(hash);
+	hash=NULL;
+	free(word);
+	word=NULL;
+	return 0;
+}
+
+boolean eap_md5_isDone(struct eap_state_machine *smd)
+{
+	struct eap_md5_data *data;
+	data = (struct eap_md5_data*) smd->methodData;
+	if (data->state != EAP_MD5_CONTINUE)
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+void eap_md5_free(void * mdata)
+{
+	struct eap_md5_data *data;
+	data = (struct eap_md5_data*) mdata;
+	free(data->challenge);
+	data->challenge=NULL;
+	free(data);
+	data=NULL;
+}
diff --git a/extensions/app_diameap/plugins/eap_tls/CMakeLists.txt b/extensions/app_diameap/plugins/eap_tls/CMakeLists.txt
new file mode 100644
index 0000000..023d134
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/CMakeLists.txt
@@ -0,0 +1,18 @@
+# The EAP-TLS Plugin
+PROJECT("EAP-TLS Plugin" C)
+
+# Parser for the configuration file 
+BISON_FILE(eaptls.y)
+FLEX_FILE(eaptls.l)
+
+SET_SOURCE_FILES_PROPERTIES(lex.eaptls.c eaptls.tab.c PROPERTIES COMPILE_FLAGS "-I \"${CMAKE_CURRENT_SOURCE_DIR}\"")
+
+EAP_ADD_METHOD(eap_tls
+    eap_tls.c
+    eap_tls.h    
+    lex.eaptls.c
+    eaptls.tab.c
+    eaptls.tab.h
+    )
+
+TARGET_LINK_LIBRARIES(eap_tls ${GNUTLS_LIBRARIES})
diff --git a/extensions/app_diameap/plugins/eap_tls/eap_tls.c b/extensions/app_diameap/plugins/eap_tls/eap_tls.c
new file mode 100644
index 0000000..6b812dd
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eap_tls.c
@@ -0,0 +1,426 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "eap_tls.h"
+
+int eap_tls_configure(char * configfile);
+int eap_tls_init(struct eap_state_machine *smd);
+int eap_tls_initPickUp(struct eap_state_machine *smd);
+int eap_tls_buildReq(struct eap_state_machine *smd, u8 eap_md5,
+		struct eap_packet * eapPacket);
+int eap_tls_getTimeout(struct eap_state_machine *smd, int * timeout);
+boolean eap_tls_check(struct eap_state_machine *smd,
+		struct eap_packet *eapRespData);
+int eap_tls_process(struct eap_state_machine *smd,
+		struct eap_packet *eapRespData);
+boolean eap_tls_isDone(struct eap_state_machine *smd);
+int eap_tls_getKey(struct eap_state_machine *smd, u8** msk, int * msklen, u8** emsk, int * emsklen);
+void eap_tls_unregister(void);
+void eap_tls_free(void * data);
+
+REGISTER_METHOD("eap_tls", "eap_tls_configure", "eap_tls_init", "eap_tls_initPickUp", "eap_tls_buildReq", "eap_tls_getTimeout", "eap_tls_check", "eap_tls_process", "eap_tls_isDone", "eap_tls_getKey", "eap_tls_unregister", "eap_tls_free")
+;
+
+int eap_tls_configure(char * configfile)
+{
+	int ret;
+	extern FILE * eaptlsin;
+
+	if (configfile)
+	{
+		tls_global_conf.conffile = configfile;
+	}
+	tls_global_conf.certfile = NULL;
+	tls_global_conf.keyfile = NULL;
+	tls_global_conf.cafile = NULL;
+	tls_global_conf.crlfile = NULL;
+	tls_global_conf.check_cert_cn_username = FALSE;
+
+	/*Parse EAP TLS configuration file */
+	eaptlsin = fopen(tls_global_conf.conffile, "r");
+	if (!eaptlsin)
+	{
+		TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open configuration file %s for reading: %s",DIAMEAP_EXTENSION, tls_global_conf.conffile, strerror(errno));
+		return errno;
+	}
+
+	/* call yacc parser */
+	CHECK_FCT(eaptlsparse(&tls_global_conf));
+
+
+	tls_global_conf.max_size = 64*1024 /* As per RFC 5216 recommendation */;
+
+	/* Initializing GnuTLS library */
+	ret = diameap_tls_init(&tls_global_conf);
+
+	return ret;
+}
+
+int eap_tls_init(struct eap_state_machine *smd)
+{
+	int ret;
+	struct tls_data *data = NULL;
+	CHECK_MALLOC(data = malloc(sizeof(struct tls_data)));
+	memset(data, 0, sizeof(struct tls_data));
+	CHECK_FCT(diameap_tls_initialize(data));
+	ret = diameap_tls_init_session(&tls_global_conf, data);
+
+	smd->methodData = (struct tls_data*) data;
+	if (ret < 0)
+	{
+		return ret;
+	}
+	return 0;
+}
+
+int eap_tls_initPickUp(struct eap_state_machine *smd)
+{
+	return 0;
+}
+
+int eap_tls_buildReq(struct eap_state_machine *smd, u8 id,
+		struct eap_packet * eapPacket)
+{
+	struct tls_data * data;
+	data = (struct tls_data *) smd->methodData;
+
+	if (data->more_toreceive == TRUE)
+	{
+		CHECK_FCT(diameap_eap_tls_buildReq_ack(id,eapPacket));
+		return 0;
+	}
+
+	if (data->state == START)
+	{
+		CHECK_FCT(diameap_eap_tls_buildReq_start(id,eapPacket));
+		return 0;
+	}
+
+	if (data->state == CONTINUE)
+	{
+		diameap_eap_tls_buildReq_data(data, id, eapPacket);
+
+		smd->methodData = (struct tls_data*) data;
+		return 0;
+	}
+
+	return 0;
+}
+
+int eap_tls_getTimeout(struct eap_state_machine *smd, int * timeout)
+{
+	return 0;
+}
+
+boolean eap_tls_check(struct eap_state_machine *smd,
+		struct eap_packet *eapRespData)
+{
+	eap_type type;
+	if(diameap_eap_get_type(eapRespData,&type)!=0){
+		goto cf;
+	}
+	if (type == TYPE_EAP_TLS)
+	{
+		return TRUE;
+	}
+cf:
+	TRACE_DEBUG(INFO,"%s[EAP TLS plugin] EAP-TLS check failed: Received EAP packet with different EAP-Type (Type = %d)",DIAMEAP_EXTENSION, type);
+	return FALSE;
+}
+
+int eap_tls_process(struct eap_state_machine *smd,
+		struct eap_packet *eapRespData)
+{
+	struct tls_data * data;
+	data = (struct tls_data *) smd->methodData;
+	struct tls_msg tlsmsg;
+	CHECK_FCT(diameap_eap_tls_parse(&tlsmsg,eapRespData));
+
+	if ((tlsmsg.datalength == 0))
+	{
+		if (data->more_tosend_length > 0)
+		{
+			//ACK and more to send
+			return 0;
+		}
+		else
+		{
+			//Success
+			if (data->handshake == TRUE)
+			{
+				data->state = SUCCESS;
+				smd->user.success = TRUE;
+
+				if(tls_global_conf.check_cert_cn_username == TRUE){
+					unsigned int list_size;
+					const gnutls_datum_t * list = gnutls_certificate_get_peers (data->session, &list_size);
+					if(list_size<1){
+						goto failure;
+					}
+
+					gnutls_x509_crt_t cert;
+		
+					CHECK_GNUTLS_DO(gnutls_x509_crt_init(&cert),{
+						TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error in initialization crt init",DIAMEAP_EXTENSION);
+						goto failure;});
+					
+					CHECK_GNUTLS_DO(gnutls_x509_crt_import(cert, &list[0], GNUTLS_X509_FMT_DER), {
+						TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error parsing certificate",DIAMEAP_EXTENSION);
+						goto failure;});
+
+					void * buff;
+					size_t size_buffer;
+					int ret;
+					ret = gnutls_x509_crt_get_dn_by_oid(cert,GNUTLS_OID_X520_COMMON_NAME,0,0,NULL,&size_buffer);
+					if( ret != GNUTLS_E_SHORT_MEMORY_BUFFER){
+						CHECK_GNUTLS_DO(ret,{
+							TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error get dn by oid",DIAMEAP_EXTENSION);
+							goto failure;});
+					}
+
+					CHECK_MALLOC_DO(buff=malloc(size_buffer), goto failure);
+
+					CHECK_GNUTLS_DO(gnutls_x509_crt_get_dn_by_oid(cert,GNUTLS_OID_X520_COMMON_NAME,0,0,buff,&size_buffer),{
+						TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error get dn by oid",DIAMEAP_EXTENSION);
+						goto failure;});
+
+					if(strncmp((char *)smd->user.userid,buff,smd->user.useridLength)!=0){
+						goto failure;
+					}
+
+					gnutls_x509_crt_deinit(cert);				
+					goto next;
+
+					failure:
+					TRACE_DEBUG(NONE,"%s[EAP TLS plugin] Checking failed. certificate's CN does not match User_Name AVP value.",DIAMEAP_EXTENSION);
+					data->state = FAILURE;
+					smd->user.success = FALSE;
+					gnutls_x509_crt_deinit(cert);
+				}
+
+				next:
+				smd->methodData = (struct tls_data*) data;
+				return 0;
+
+			}
+
+			return 0;
+		}
+
+	}
+
+	if (data->more_toreceive == TRUE)
+	{
+		//reassemble received fragment to TLS Response
+		CHECK_FCT(diameap_tls_reassemble(&data->tlsResp,tlsmsg));
+	}
+	else
+	{
+		//receive the first fragment or a complete TLS message
+		CHECK_FCT(diameap_tls_copy(&data->tlsResp,tlsmsg));
+	}
+
+	if (tlsmsg.flags & TLS_FLAG_MORE)
+	{
+		data->more_toreceive = TRUE;
+		smd->methodData = (struct tls_data*) data;
+		return 0;
+	}
+	else
+	{
+		//last fragment received
+		data->more_toreceive = FALSE;
+	}
+	data->state = CONTINUE;
+	diameap_tls_process_receive(data);
+
+	if (data->state == SUCCESS)
+	{
+		smd->user.success = TRUE;
+	}
+	smd->methodData = (struct tls_data*) data;
+	return 0;
+}
+
+boolean eap_tls_isDone(struct eap_state_machine *smd)
+{
+	struct tls_data * data;
+	data = (struct tls_data *) smd->methodData;
+	if (data->state == CONTINUE || data->state == START)
+	{
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int eap_tls_getKey(struct eap_state_machine *smd, u8 ** msk, int *msklen, u8 ** emsk, int *emsklen)
+{
+	struct tls_data * data;
+	int len = emsk ? 128 : 64;
+	data = (struct tls_data *) smd->methodData;
+	*msk = malloc(len);
+	if (gnutls_prf(data->session, strlen("client EAP encryption"),
+			"client EAP encryption", 0, 0, NULL, len, (char *) *msk)
+			!= GNUTLS_E_SUCCESS)
+	{
+		free(*msk);
+		*msk = NULL;
+		*msklen = 0;
+		return 1;
+	}
+	else
+	{
+		*msklen = 64;
+	}
+	if (emsk) {
+		*emsk = malloc(64);
+		memcpy(*emsk, (*msk)+64, 64);
+		memset((*msk)+64, 0, 64);
+		*emsklen = 64;
+	}
+
+	return 0;
+}
+
+void eap_tls_unregister(void)
+{
+	//
+}
+
+void eap_tls_free(void * mdata)
+{
+	struct tls_data *data;
+	data = (struct tls_data*) mdata;
+	gnutls_deinit(data->session);
+	if(data->tlsReq.data){
+		free(data->tlsReq.data);
+		data->tlsReq.data=NULL;
+	}
+	if(data->tlsResp.data){
+		free(data->tlsResp.data);
+		data->tlsResp.data=NULL;
+	}
+	free(data);
+	data=NULL;
+}
+
+//send TLS ACK Request (empty TLS msg)
+int diameap_eap_tls_buildReq_ack(u8 id, struct eap_packet * eapPacket)
+{
+	u8* payload;
+	struct tls_msg tlsmsg;
+	int len;
+	CHECK_FCT(diameap_tls_new(&tlsmsg));
+	CHECK_FCT(diameap_tls_new_tls_packet(&payload,&len,tlsmsg));
+	CHECK_FCT(diameap_eap_new(EAP_REQUEST,id,TYPE_EAP_TLS,payload,len,eapPacket));
+	return 0;
+}
+
+// parse EAP TLS msg
+int diameap_eap_tls_parse(struct tls_msg * tlsmsg, struct eap_packet *eapPacket)
+{
+	u8 *datatls;
+	int len;
+
+	//initialize a new empty EAP TLS msg
+	diameap_tls_new(tlsmsg);
+	//retrieve the data field from EAP Packet
+	diameap_eap_get_data(eapPacket, &datatls, &len);
+	//parse EAP TLS msg
+	diameap_tls_parse(datatls, len, tlsmsg);
+	return 0;
+}
+
+int diameap_eap_tls_buildReq_start(u8 id, struct eap_packet * eapPacket)
+{
+	u8* payload;
+	struct tls_msg tlsmsg;
+	int len;
+	CHECK_FCT(diameap_tls_new(&tlsmsg));
+	CHECK_FCT(diameap_tls_set_flags(&tlsmsg,TLS_FLAG_START));
+	CHECK_FCT(diameap_tls_new_tls_packet(&payload,&len,tlsmsg));
+	CHECK_FCT(diameap_eap_new(EAP_REQUEST,id,TYPE_EAP_TLS,payload,len,eapPacket));
+	return 0;
+}
+
+int diameap_eap_tls_buildReq_data(struct tls_data * data, int id,
+		struct eap_packet * eapPacket)
+{
+	struct tls_msg tlsmsg;
+	u8* datatosend;
+	u8 * eaptls_data;
+	int length = 0;
+
+	diameap_tls_new(&tlsmsg);
+
+	if (data->more_tosend_length == 0)
+	{
+		//First fragment of message or the only fragment of message
+		data->more_tosend_length = data->tlsReq.datalength;
+	}
+	if (data->more_tosend_length > tls_global_conf.max_size)
+	{
+		//New fragment of message. Is not the last fragment.
+		length = tls_global_conf.max_size;
+		CHECK_FCT(diameap_tls_set_flags(&tlsmsg,TLS_FLAG_MORE));
+		if (data->more_tosend_length == data->tlsReq.datalength)
+		{
+			//The first fragment of message
+			CHECK_FCT(diameap_tls_set_message_length(&tlsmsg,data->tlsReq.datalength));//set L flag and length value
+		}
+	}
+	else
+	{
+		//The last fragment or the only fragment.
+		length = data->more_tosend_length;
+	}
+
+	datatosend = malloc(sizeof(u8) * length);
+	U8COPY(datatosend,0,length,data->tlsReq.data+(data->tlsReq.datalength-data->more_tosend_length));
+	data->more_tosend_length -= length;
+	CHECK_FCT(diameap_tls_set_data(&tlsmsg,datatosend,length));
+
+	CHECK_FCT(diameap_tls_new_tls_packet(&eaptls_data,&length,tlsmsg));
+	CHECK_FCT(diameap_eap_new(EAP_REQUEST,id,TYPE_EAP_TLS,eaptls_data,length,eapPacket));
+
+	if (data->more_tosend_length == 0)
+	{
+		diameap_tls_new(&data->tlsReq);
+	}
+	return 0;
+}
diff --git a/extensions/app_diameap/plugins/eap_tls/eap_tls.h b/extensions/app_diameap/plugins/eap_tls/eap_tls.h
new file mode 100644
index 0000000..400f3d9
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eap_tls.h
@@ -0,0 +1,51 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+#ifndef EAP_TLS_H_
+#define EAP_TLS_H_
+
+#include "../../plugins.h"
+
+struct tls_config	tls_global_conf;
+
+int diameap_eap_tls_buildReq_ack(u8 id, struct eap_packet * eapPacket);
+int diameap_eap_tls_buildReq_start(u8 id, struct eap_packet * eapPacket);
+int diameap_eap_tls_buildReq_data(struct tls_data * data,int id,struct eap_packet * eapPacket);
+int diameap_eap_tls_parse(struct tls_msg * eaptls,struct eap_packet *eapPacket);
+int eaptlsparse(struct tls_config * conf);
+
+#endif /* EAP_TLS_H_ */
diff --git a/extensions/app_diameap/plugins/eap_tls/eaptls.l b/extensions/app_diameap/plugins/eap_tls/eaptls.l
new file mode 100644
index 0000000..7689333
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eaptls.l
@@ -0,0 +1,119 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ *****************************************************************************************************/
+
+
+/*Declarations and option settings*/
+%{
+#include <stdio.h>
+#include "eap_tls.h"
+#include "eaptls.tab.h"
+
+#define YY_USER_ACTION { 						\
+	yylloc->first_line = yylloc->last_line = yylineno; \
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column += yyleng +1;	\
+	}	 
+	
+#define YY_NO_INPUT
+%}
+
+%option noyywrap
+%option yylineno
+%option bison-bridge 
+%option bison-locations
+%option nounput
+%%
+	/* List of patterns and actions */
+
+<*>\n			{				
+				yylloc->last_column=0; 
+			}
+
+
+<*>#.*$			{}
+
+
+[ \t\n]+		{
+				yylloc->last_column=0; 
+			}
+
+\"([^\n\"]*)\"	{ 	/* Quoted String */
+					yylval->str = strdup(yytext+1); 
+					yylval->str[yyleng-2]='\0';
+					return iSTRING;
+				}
+
+
+[[:digit:]]+	{ 	/* Digital number */
+					yylval->val = atoi(yytext);
+					return NUM; /* Numeric value */ 
+				}
+
+(?i:"Cred")	{
+				return CERTS;
+			}
+
+(?i:"CA")		{ 
+				return CAPATH;
+			}
+
+(?i:"CRL")		{ 
+				return CRLPATH;
+			}
+
+(?i:"check_cert_cn_username")		{
+				return CHECK_CN_USERNAME;
+			}
+
+
+
+"="|";"|":"|","		{	/* Single characters for yyparse */ 
+				return yytext[0]; 
+			}
+
+	/* Unrecognized token or text */
+	
+<*>[[:alnum:]]+	 |					 
+<*>.	{ 
+				fprintf(stderr,"Unrecognized input text '%s'( on line %i column %i )\n", yytext, yylloc->first_line, yylloc->first_column); 
+			 	return LEX_ERROR; 
+			}
+
+%%
+/* Routines */
+
+
diff --git a/extensions/app_diameap/plugins/eap_tls/eaptls.y b/extensions/app_diameap/plugins/eap_tls/eaptls.y
new file mode 100644
index 0000000..31559eb
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eaptls.y
@@ -0,0 +1,243 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 <stdio.h>
+#include "eap_tls.h"
+#include "eaptls.tab.h"
+
+void yyerror (YYLTYPE *llocp, struct tls_config * config, const char *s);
+
+extern int yywrap();
+extern int yylex();
+
+
+/* The Lex parser prototype */
+int eaptlslex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+
+%}
+
+%locations
+%parse-param {struct tls_config * config} 
+%pure_parser
+/*%defines */
+%error-verbose
+%debug 
+
+%union {
+	char *str;
+	int val;
+	char byte;
+}
+
+
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+%token 	<val>	NUM
+
+%token 	<str>	iSTRING
+
+%token  <byte>	iBYTE
+
+%token 		CERTS
+%token 		CAPATH
+%token 		CRLPATH
+%token		CHECK_CN_USERNAME
+
+%%	
+
+confparams : 	/* empty */
+		| confparams CERTS_files
+		| confparams CA_file
+		| confparams CRL_file
+		| confparams CHECK_CN_USERNAME_param
+		| confparams errors
+		{
+			return EINVAL;
+		}
+		;
+
+errors :	LEX_ERROR
+		| error
+		;
+
+
+CERTS_files :	CERTS '=' iSTRING ':' iSTRING ';'
+		{
+		char * certfile, *keyfile;
+		FILE * fl;
+
+		certfile = $3;
+		keyfile = $5;
+		if(certfile == NULL){
+			TRACE_DEBUG(INFO,"%s[EAP TLS plugin] certificate file missing in configuration file",DIAMEAP_EXTENSION);
+			yyerror (&yylloc, config, "cert file missing"); 
+			YYERROR;
+		}
+		if(keyfile == NULL){
+			TRACE_DEBUG(INFO,"%s[EAP TLS plugin] privateKey file missing in configuration file",DIAMEAP_EXTENSION);
+			yyerror (&yylloc, config, "privateKey file missing"); 
+			YYERROR;
+		}
+		
+		fl = fopen(certfile, "r");
+		if ((fl == NULL) && (*certfile != '/')) {
+			char * tmpfile=certfile;
+			CHECK_MALLOC_DO( certfile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+				{ yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+			sprintf(certfile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+			free(tmpfile);
+			fl = fopen(certfile, "r");
+		}
+		if (fl == NULL) {
+			int ret = errno;
+			TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open certificate file %s for reading: %s",DIAMEAP_EXTENSION,certfile,strerror(ret));
+			yyerror (&yylloc, config, "Error configuring certificate for EAP-TLS"); 
+			YYERROR;
+		}
+		fclose(fl);
+		
+		fl = fopen(keyfile, "r");
+		if ((fl == NULL) && (*keyfile != '/')) {
+			char * tmpfile=keyfile;
+			CHECK_MALLOC_DO( keyfile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+				{ yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+			sprintf(keyfile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+			free(tmpfile);
+			fl = fopen(keyfile, "r");
+		}
+		if (fl == NULL) {
+			int ret = errno;
+			TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open privateKey file %s for reading: %s",DIAMEAP_EXTENSION,keyfile,strerror(ret));
+			yyerror (&yylloc, config, "Error configuring privateKey for EAP-TLS"); 
+			YYERROR;
+		}
+		fclose(fl);
+		
+		config->certfile = certfile;
+		config->keyfile = keyfile;
+		}
+		;
+		
+CA_file :	CAPATH '=' iSTRING ';'
+		{
+		char * cafile;
+		FILE * fl;
+
+		cafile = $3;
+
+		if(cafile == NULL){
+			TRACE_DEBUG(INFO,"%s[EAP TLS plugin] CA file missing in configuration file",DIAMEAP_EXTENSION);
+			yyerror (&yylloc, config, "cert file missing"); 
+			YYERROR;
+		}
+		
+		fl = fopen(cafile, "r");
+		if ((fl == NULL) && (*cafile != '/')) {
+			char * tmpfile=cafile;
+			CHECK_MALLOC_DO( cafile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+				{ yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+			sprintf(cafile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+			free(tmpfile);
+			fl = fopen(cafile, "r");
+		}
+		if (fl == NULL) {
+			int ret = errno;
+			TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open CA file %s for reading: %s",DIAMEAP_EXTENSION,cafile,strerror(ret));
+			yyerror (&yylloc, config, "Error configuring CA file for EAP-TLS"); 
+			YYERROR;
+		}
+		fclose(fl);
+			config->cafile=$3;
+		}
+		;
+
+CRL_file :	CRLPATH '=' iSTRING ';'
+		{
+		char * crlfile;
+		FILE * fl;
+
+		crlfile = $3;
+
+		if(crlfile == NULL){
+			TRACE_DEBUG(FULL+1,"%s[EAP TLS plugin] CRL file missing in configuration file",DIAMEAP_EXTENSION);
+
+		}else{
+		
+			fl = fopen(crlfile, "r");
+			if ((fl == NULL) && (*crlfile != '/')) {
+				char * tmpfile=crlfile;
+				CHECK_MALLOC_DO( crlfile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+					{ yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+				sprintf(crlfile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+				free(tmpfile);
+				fl = fopen(crlfile, "r");
+			}
+			if (fl == NULL) {
+				int ret = errno;
+				TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open CRL file %s for reading: %s",DIAMEAP_EXTENSION,crlfile,strerror(ret));
+				yyerror (&yylloc, config, "Error configuring CRL file for EAP-TLS"); 
+				YYERROR;
+			}
+			fclose(fl);	
+		}
+			config->crlfile=$3;
+		}
+		;
+
+CHECK_CN_USERNAME_param :	
+		CHECK_CN_USERNAME '=' NUM ';'
+		{
+			if((int)$3 == 0){
+				config->check_cert_cn_username = FALSE;
+			}
+			else
+			{
+				config->check_cert_cn_username = TRUE;			
+			}
+		}
+		;
+		
+%%
+
+void yyerror(YYLTYPE *llocp, struct tls_config * config,const char *str)
+{
+         fprintf(stderr,"Error in %s ( on line %i column %i -> line %i column %i) : %s\n",config->conffile, llocp->first_line, llocp->first_column, llocp->last_line, llocp->last_column, str);
+}